Author: joehni
Date: Wed Mar 8 13:13:49 2006
New Revision: 384329
URL: http://svn.apache.org/viewcvs?rev=384329&view=rev
Log:
Remove possible NPEs (Issue 36685).
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/CPDSConnectionFactory.java
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/InstanceKeyObjectFactory.java
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/KeyedCPDSConnectionFactory.java
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java
URL:
http://svn.apache.org/viewcvs/jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java?rev=384329&r1=384328&r2=384329&view=diff
==============================================================================
---
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java
(original)
+++
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/PoolableConnectionFactory.java
Wed Mar 8 13:13:49 2006
@@ -1,12 +1,12 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -92,7 +92,7 @@
boolean defaultReadOnly,
boolean defaultAutoCommit,
AbandonedConfig config) {
-
+
_connFactory = connFactory;
_pool = pool;
_config = config;
@@ -124,7 +124,7 @@
boolean defaultAutoCommit,
int defaultTransactionIsolation,
AbandonedConfig config) {
-
+
_connFactory = connFactory;
_pool = pool;
_config = config;
@@ -159,7 +159,7 @@
int defaultTransactionIsolation,
String defaultCatalog,
AbandonedConfig config) {
-
+
_connFactory = connFactory;
_pool = pool;
_config = config;
@@ -194,7 +194,7 @@
int defaultTransactionIsolation,
String defaultCatalog,
AbandonedConfig config) {
-
+
_connFactory = connFactory;
_pool = pool;
_config = config;
@@ -285,7 +285,7 @@
public void setDefaultCatalog(String defaultCatalog) {
_defaultCatalog = defaultCatalog;
}
-
+
synchronized public Object makeObject() throws Exception {
Connection conn = _connFactory.createConnection();
if(null != _stmtPoolFactory) {
@@ -309,7 +309,7 @@
return true;
} catch(Exception e) {
return false;
- }
+ }
} else {
return false;
}
@@ -330,17 +330,20 @@
throw new SQLException("validationQuery didn't return a
row");
}
} finally {
- try {
- rset.close();
- } catch(Exception t) {
- // ignored
+ if (rset != null) {
+ try {
+ rset.close();
+ } catch(Exception t) {
+ // ignored
+ }
}
- try {
- stmt.close();
- } catch(Exception t) {
- // ignored
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch(Exception t) {
+ // ignored
+ }
}
-
}
}
}
@@ -386,14 +389,14 @@
protected boolean _defaultAutoCommit = true;
protected int _defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;
protected String _defaultCatalog;
-
+
/**
* @deprecated AbandonedConfig is now deprecated.
*/
protected AbandonedConfig _config = null;
/**
- * Internal constant to indicate the level is not set.
+ * Internal constant to indicate the level is not set.
*/
static final int UNKNOWN_TRANSACTIONISOLATION = -1;
}
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/CPDSConnectionFactory.java
URL:
http://svn.apache.org/viewcvs/jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/CPDSConnectionFactory.java?rev=384329&r1=384328&r2=384329&view=diff
==============================================================================
---
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/CPDSConnectionFactory.java
(original)
+++
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/CPDSConnectionFactory.java
Wed Mar 8 13:13:49 2006
@@ -1,12 +1,12 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -40,11 +40,11 @@
* @author John D. McNally
* @version $Revision$ $Date$
*/
-class CPDSConnectionFactory
+class CPDSConnectionFactory
implements PoolableObjectFactory, ConnectionEventListener {
- private static final String NO_KEY_MESSAGE
- = "close() was called on a Connection, but "
+ private static final String NO_KEY_MESSAGE
+ = "close() was called on a Connection, but "
+ "I have no record of the underlying PooledConnection.";
protected ConnectionPoolDataSource _cpds = null;
@@ -57,18 +57,18 @@
/**
* Create a new <tt>PoolableConnectionFactory</tt>.
- * @param cpds the ConnectionPoolDataSource from which to obtain
+ * @param cpds the ConnectionPoolDataSource from which to obtain
* PooledConnection's
- * @param pool the {*link ObjectPool} in which to pool those
+ * @param pool the {*link ObjectPool} in which to pool those
* {*link Connection}s
* @param validationQuery a query to use to {*link #validateObject
validate}
- * {*link Connection}s. Should return at least one row.
+ * {*link Connection}s. Should return at least one row.
* May be <tt>null</tt>
- * @param username
+ * @param username
* @param password
*/
- public CPDSConnectionFactory(ConnectionPoolDataSource cpds,
- ObjectPool pool,
+ public CPDSConnectionFactory(ConnectionPoolDataSource cpds,
+ ObjectPool pool,
String validationQuery,
String username,
String password) {
@@ -81,9 +81,9 @@
}
/**
- * Sets the {*link ConnectionFactory} from which to obtain base
+ * Sets the {*link ConnectionFactory} from which to obtain base
* {*link Connection}s.
- * @param connFactory the {*link ConnectionFactory} from which to obtain
+ * @param connFactory the {*link ConnectionFactory} from which to obtain
* base {*link Connection}s
*/
public synchronized void setCPDS(ConnectionPoolDataSource cpds) {
@@ -91,11 +91,11 @@
}
/**
- * Sets the query I use to {*link #validateObject validate}
+ * Sets the query I use to {*link #validateObject validate}
* {*link Connection}s.
* Should return at least one row.
* May be <tt>null</tt>
- * @param validationQuery a query to use to {*link #validateObject
validate}
+ * @param validationQuery a query to use to {*link #validateObject
validate}
* {*link Connection}s.
*/
public synchronized void setValidationQuery(String validationQuery) {
@@ -104,7 +104,7 @@
/**
* Sets the {*link ObjectPool} in which to pool {*link Connection}s.
- * @param pool the {*link ObjectPool} in which to pool those
+ * @param pool the {*link ObjectPool} in which to pool those
* {*link Connection}s
*/
public synchronized void setPool(ObjectPool pool) throws SQLException {
@@ -153,7 +153,7 @@
public boolean validateObject(Object obj) {
boolean valid = false;
if (obj instanceof PooledConnectionAndInfo) {
- PooledConnection pconn =
+ PooledConnection pconn =
((PooledConnectionAndInfo) obj).getPooledConnection();
String query = _validationQuery;
if (null != query) {
@@ -161,9 +161,9 @@
Statement stmt = null;
ResultSet rset = null;
// logical Connection from the PooledConnection must be closed
- // before another one can be requested and closing it will
+ // before another one can be requested and closing it will
// generate an event. Keep track so we know not to return
- // the PooledConnection
+ // the PooledConnection
validatingMap.put(pconn, null);
try {
conn = pconn.getConnection();
@@ -177,20 +177,26 @@
} catch (Exception e) {
valid = false;
} finally {
- try {
- rset.close();
- } catch (Throwable t) {
- // ignore
+ if (rset != null) {
+ try {
+ rset.close();
+ } catch (Throwable t) {
+ // ignore
+ }
}
- try {
- stmt.close();
- } catch (Throwable t) {
- // ignore
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (Throwable t) {
+ // ignore
+ }
}
- try {
- conn.close();
- } catch (Throwable t) {
- // ignore
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (Throwable t) {
+ // ignore
+ }
}
validatingMap.remove(pconn);
}
@@ -227,17 +233,17 @@
Object info = pcMap.get(pc);
if (info == null) {
throw new IllegalStateException(NO_KEY_MESSAGE);
- }
+ }
try {
_pool.returnObject(info);
} catch (Exception e) {
- System.err.println("CLOSING DOWN CONNECTION AS IT COULD "
+ System.err.println("CLOSING DOWN CONNECTION AS IT COULD "
+ "NOT BE RETURNED TO THE POOL");
try {
destroyObject(info);
} catch (Exception e2) {
- System.err.println("EXCEPTION WHILE DESTROYING OBJECT "
+ System.err.println("EXCEPTION WHILE DESTROYING OBJECT "
+ info);
e2.printStackTrace();
}
@@ -254,10 +260,10 @@
try {
if (null != event.getSQLException()) {
System.err.println(
- "CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR ("
+ "CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR ("
+ event.getSQLException() + ")");
}
- //remove this from the listener list because we are no more
+ //remove this from the listener list because we are no more
//interested in errors since we are about to close this connection
pc.removeConnectionEventListener(this);
} catch (Exception ignore) {
@@ -267,7 +273,7 @@
Object info = pcMap.get(pc);
if (info == null) {
throw new IllegalStateException(NO_KEY_MESSAGE);
- }
+ }
try {
destroyObject(info);
} catch (Exception e) {
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/InstanceKeyObjectFactory.java
URL:
http://svn.apache.org/viewcvs/jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/InstanceKeyObjectFactory.java?rev=384329&r1=384328&r2=384329&view=diff
==============================================================================
---
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/InstanceKeyObjectFactory.java
(original)
+++
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/InstanceKeyObjectFactory.java
Wed Mar 8 13:13:49 2006
@@ -1,12 +1,12 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -35,7 +35,7 @@
/**
* A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s
* or <code>PerUserPoolDataSource</code>s
- *
+ *
* @version $Revision$ $Date$
*/
abstract class InstanceKeyObjectFactory
@@ -48,7 +48,7 @@
Iterator i = instanceMap.keySet().iterator();
while (i.hasNext()) {
Object obj = i.next();
- if (obj instanceof String)
+ if (obj instanceof String)
{
try {
max = Math.max(max,
Integer.valueOf((String)obj).intValue());
@@ -64,7 +64,7 @@
instanceMap.put(instanceKey, ds);
return instanceKey;
}
-
+
static void removeInstance(String key)
{
instanceMap.remove(key);
@@ -77,7 +77,7 @@
//Get iterator to loop over all instances of this datasource.
Iterator instanceIterator = instanceMap.entrySet().iterator();
while (instanceIterator.hasNext()) {
- ((InstanceKeyDataSource)
+ ((InstanceKeyDataSource)
((Map.Entry) instanceIterator.next()).getValue()).close();
}
instanceMap.clear();
@@ -87,41 +87,41 @@
/**
* implements ObjectFactory to create an instance of SharedPoolDataSource
* or PerUserPoolDataSource
- */
- public Object getObjectInstance(Object refObj, Name name,
+ */
+ public Object getObjectInstance(Object refObj, Name name,
Context context, Hashtable env)
throws IOException, ClassNotFoundException {
- // The spec says to return null if we can't create an instance
+ // The spec says to return null if we can't create an instance
// of the reference
Object obj = null;
if (refObj instanceof Reference) {
Reference ref = (Reference) refObj;
- if (isCorrectClass(ref.getClassName())) {
+ if (isCorrectClass(ref.getClassName())) {
RefAddr ra = ref.get("instanceKey");
if (ra != null && ra.getContent() != null) {
// object was bound to jndi via Referenceable api.
obj = instanceMap.get(ra.getContent());
}
- else
+ else
{
- // tomcat jndi creates a Reference out of server.xml
+ // tomcat jndi creates a Reference out of server.xml
// <ResourceParam> configuration and passes it to an
// instance of the factory given in server.xml.
String key = null;
- if (name != null)
+ if (name != null)
{
key = name.toString();
- obj = instanceMap.get(key);
- }
+ obj = instanceMap.get(key);
+ }
if (obj == null)
{
InstanceKeyDataSource ds = getNewInstance(ref);
setCommonProperties(ref, ds);
obj = ds;
- if (key != null)
+ if (key != null)
{
instanceMap.put(key, ds);
- }
+ }
}
}
}
@@ -129,81 +129,81 @@
return obj;
}
- private void setCommonProperties(Reference ref,
- InstanceKeyDataSource ikds)
+ private void setCommonProperties(Reference ref,
+ InstanceKeyDataSource ikds)
throws IOException, ClassNotFoundException {
-
+
RefAddr ra = ref.get("dataSourceName");
if (ra != null && ra.getContent() != null) {
ikds.setDataSourceName(ra.getContent().toString());
}
-
+
ra = ref.get("defaultAutoCommit");
if (ra != null && ra.getContent() != null) {
ikds.setDefaultAutoCommit(Boolean.valueOf(
ra.getContent().toString()).booleanValue());
}
-
+
ra = ref.get("defaultReadOnly");
if (ra != null && ra.getContent() != null) {
ikds.setDefaultReadOnly(Boolean.valueOf(
ra.getContent().toString()).booleanValue());
}
-
+
ra = ref.get("description");
if (ra != null && ra.getContent() != null) {
ikds.setDescription(ra.getContent().toString());
}
-
+
ra = ref.get("jndiEnvironment");
if (ra != null && ra.getContent() != null) {
byte[] serialized = (byte[]) ra.getContent();
- ikds.jndiEnvironment =
+ ikds.jndiEnvironment =
(Properties) deserialize(serialized);
}
-
+
ra = ref.get("loginTimeout");
if (ra != null && ra.getContent() != null) {
ikds.setLoginTimeout(
Integer.parseInt(ra.getContent().toString()));
}
-
+
ra = ref.get("testOnBorrow");
if (ra != null && ra.getContent() != null) {
ikds.setTestOnBorrow(
Boolean.getBoolean(ra.getContent().toString()));
}
-
+
ra = ref.get("testOnReturn");
if (ra != null && ra.getContent() != null) {
ikds.setTestOnReturn(Boolean.valueOf(
ra.getContent().toString()).booleanValue());
}
-
+
ra = ref.get("timeBetweenEvictionRunsMillis");
if (ra != null && ra.getContent() != null) {
ikds.setTimeBetweenEvictionRunsMillis(
Integer.parseInt(ra.getContent().toString()));
}
-
+
ra = ref.get("numTestsPerEvictionRun");
if (ra != null && ra.getContent() != null) {
ikds.setNumTestsPerEvictionRun(
Integer.parseInt(ra.getContent().toString()));
}
-
+
ra = ref.get("minEvictableIdleTimeMillis");
if (ra != null && ra.getContent() != null) {
ikds.setMinEvictableIdleTimeMillis(
Integer.parseInt(ra.getContent().toString()));
}
-
+
ra = ref.get("testWhileIdle");
if (ra != null && ra.getContent() != null) {
ikds.setTestWhileIdle(Boolean.valueOf(
ra.getContent().toString()).booleanValue());
}
-
+
ra = ref.get("validationQuery");
if (ra != null && ra.getContent() != null) {
ikds.setValidationQuery(ra.getContent().toString());
@@ -227,16 +227,18 @@
/**
* used to set some properties saved within a Reference
*/
- protected static final Object deserialize(byte[] data)
+ protected static final Object deserialize(byte[] data)
throws IOException, ClassNotFoundException {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new ByteArrayInputStream(data));
return in.readObject();
} finally {
- try {
- in.close();
- } catch (IOException ex) {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ex) {
+ }
}
}
}
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/KeyedCPDSConnectionFactory.java
URL:
http://svn.apache.org/viewcvs/jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/KeyedCPDSConnectionFactory.java?rev=384329&r1=384328&r2=384329&view=diff
==============================================================================
---
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/KeyedCPDSConnectionFactory.java
(original)
+++
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/datasources/KeyedCPDSConnectionFactory.java
Wed Mar 8 13:13:49 2006
@@ -1,12 +1,12 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -40,11 +40,11 @@
* @author John D. McNally
* @version $Revision$ $Date$
*/
-class KeyedCPDSConnectionFactory
+class KeyedCPDSConnectionFactory
implements KeyedPoolableObjectFactory, ConnectionEventListener {
- private static final String NO_KEY_MESSAGE
- = "close() was called on a Connection, but "
+ private static final String NO_KEY_MESSAGE
+ = "close() was called on a Connection, but "
+ "I have no record of the underlying PooledConnection.";
protected ConnectionPoolDataSource _cpds = null;
@@ -59,8 +59,8 @@
* @param pool the {*link ObjectPool} in which to pool those {*link
Connection}s
* @param validationQuery a query to use to {*link #validateObject
validate} {*link Connection}s. Should return at least one row. May be
<tt>null</tt>
*/
- public KeyedCPDSConnectionFactory(ConnectionPoolDataSource cpds,
- KeyedObjectPool pool,
+ public KeyedCPDSConnectionFactory(ConnectionPoolDataSource cpds,
+ KeyedObjectPool pool,
String validationQuery) {
_cpds = cpds;
_pool = pool;
@@ -90,7 +90,7 @@
* Sets the {*link ObjectPool} in which to pool {*link Connection}s.
* @param pool the {*link ObjectPool} in which to pool those {*link
Connection}s
*/
- synchronized public void setPool(KeyedObjectPool pool)
+ synchronized public void setPool(KeyedObjectPool pool)
throws SQLException {
if (null != _pool && pool != _pool) {
try {
@@ -130,7 +130,7 @@
pc.addConnectionEventListener(this);
obj = new PooledConnectionAndInfo(pc, username, password);
pcMap.put(pc, obj);
-
+
return obj;
}
@@ -145,7 +145,7 @@
public boolean validateObject(Object key, Object obj) {
boolean valid = false;
if (obj instanceof PooledConnectionAndInfo) {
- PooledConnection pconn =
+ PooledConnection pconn =
((PooledConnectionAndInfo)obj).getPooledConnection();
String query = _validationQuery;
if (null != query) {
@@ -153,9 +153,9 @@
Statement stmt = null;
ResultSet rset = null;
// logical Connection from the PooledConnection must be closed
- // before another one can be requested and closing it will
+ // before another one can be requested and closing it will
// generate an event. Keep track so we know not to return
- // the PooledConnection
+ // the PooledConnection
validatingMap.put(pconn, null);
try {
conn = pconn.getConnection();
@@ -169,20 +169,26 @@
} catch(Exception e) {
valid = false;
} finally {
- try {
- rset.close();
- } catch (Throwable t) {
- // ignore
+ if (rset != null) {
+ try {
+ rset.close();
+ } catch (Throwable t) {
+ // ignore
+ }
}
- try {
- stmt.close();
- } catch (Throwable t) {
- // ignore
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (Throwable t) {
+ // ignore
+ }
}
- try {
- conn.close();
- } catch (Throwable t) {
- // ignore
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (Throwable t) {
+ // ignore
+ }
}
validatingMap.remove(pconn);
}
@@ -216,20 +222,20 @@
// if this event occured becase we were validating, ignore it
// otherwise return the connection to the pool.
if (!validatingMap.containsKey(pc)) {
- PooledConnectionAndInfo info =
+ PooledConnectionAndInfo info =
(PooledConnectionAndInfo) pcMap.get(pc);
if (info == null) {
throw new IllegalStateException(NO_KEY_MESSAGE);
- }
+ }
try {
_pool.returnObject(info.getUserPassKey(), info);
} catch (Exception e) {
- System.err.println("CLOSING DOWN CONNECTION AS IT COULD " +
+ System.err.println("CLOSING DOWN CONNECTION AS IT COULD " +
"NOT BE RETURNED TO THE POOL");
try {
destroyObject(info.getUserPassKey(), info);
} catch (Exception e2) {
- System.err.println("EXCEPTION WHILE DESTROYING OBJECT " +
+ System.err.println("EXCEPTION WHILE DESTROYING OBJECT " +
info);
e2.printStackTrace();
}
@@ -249,7 +255,7 @@
.println("CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR ("
+
event.getSQLException() + ")");
}
- //remove this from the listener list because we are no more
+ //remove this from the listener list because we are no more
//interested in errors since we are about to close this connection
pc.removeConnectionEventListener(this);
} catch (Exception ignore) {
@@ -259,7 +265,7 @@
PooledConnectionAndInfo info = (PooledConnectionAndInfo) pcMap.get(pc);
if (info == null) {
throw new IllegalStateException(NO_KEY_MESSAGE);
- }
+ }
try {
destroyObject(info.getUserPassKey(), info);
} catch (Exception e) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]