Author: rdonkin
Date: Tue Sep 15 20:22:59 2009
New Revision: 815465
URL: http://svn.apache.org/viewvc?rev=815465&view=rev
Log:
JAMES-917 Inject commons logger with prefixing. This adds the name of the
handler but does not include session specific information. Maybe this needs to
be added. http://issues.apache.org/jira/browse/JAMES-917
Added:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/HandlerLog.java
(with props)
Modified:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/ProtocolHandlerHelper.java
james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/ImapHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SMTPCommandDispatcherLineHandler.java
Modified:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java?rev=815465&r1=815464&r2=815465&view=diff
==============================================================================
---
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java
(original)
+++
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java
Tue Sep 15 20:22:59 2009
@@ -693,7 +693,7 @@
return enabled;
}
/**
- * Overide this method to create actual instance of connection handler.
+ * Override this method to create actual instance of connection handler.
*
* @return the new ConnectionHandler
* @exception Exception if an error occurs
@@ -793,7 +793,7 @@
/**
* Returns the server socket type, plain or SSL
*
- * @return String The scoekt type, plain or SSL
+ * @return String The socket type, plain or SSL
*/
public String getSocketType() {
return serverSocketType;
@@ -819,8 +819,9 @@
* @see org.apache.avalon.excalibur.pool.ObjectFactory#newInstance()
*/
public Object newInstance() throws Exception {
- final DelegatingJamesHandler delegatingJamesHandler = new
DelegatingJamesHandler(newProtocolHandlerInstance(), dnsServer);
- delegatingJamesHandler.setName("Handler-" + handlerCount.getAndAdd(1));
+ final String name = "Handler-" + handlerCount.getAndAdd(1);
+ final DelegatingJamesHandler delegatingJamesHandler =
+ new DelegatingJamesHandler(newProtocolHandlerInstance(),
dnsServer, name, getLogger());
return delegatingJamesHandler;
}
Modified:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java?rev=815465&r1=815464&r2=815465&view=diff
==============================================================================
---
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java
(original)
+++
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java
Tue Sep 15 20:22:59 2009
@@ -34,15 +34,15 @@
import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
import org.apache.avalon.excalibur.pool.Poolable;
import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
+import org.apache.commons.logging.Log;
import org.apache.james.api.dnsservice.DNSService;
import org.apache.james.util.InternetPrintWriter;
/**
* Common Handler code
*/
-public class DelegatingJamesHandler extends AbstractLogEnabled implements
ProtocolHandlerHelper, ConnectionHandler, Poolable {
+public class DelegatingJamesHandler implements ProtocolHandlerHelper,
ConnectionHandler, Poolable {
private static final int DEFAULT_OUTPUT_BUFFER_SIZE = 1024;
@@ -111,7 +111,7 @@
* Names the handler.
* This name is used for contextual logging.
*/
- private String name = DEFAULT_NAME;
+ private final String name;
/**
@@ -121,10 +121,21 @@
private final ProtocolHandler protocolHandler;
- public DelegatingJamesHandler(final ProtocolHandler delegated, final
DNSService dnsServer) {
+ private final Log log;
+ private final Logger logger;
+
+ public DelegatingJamesHandler(final ProtocolHandler delegated, final
DNSService dnsServer, final String name,
+ final Logger logger) {
this.protocolHandler = delegated;
this.dnsServer = dnsServer;
this.protocolHandler.setProtocolHandlerHelper(this);
+ if (name == null) {
+ this.name = DEFAULT_NAME;
+ } else {
+ this.name = name;
+ }
+ this.log = new HandlerLog(logger, "[" + name + "] ");
+ this.logger = logger;
}
/**
@@ -160,38 +171,38 @@
} catch (RuntimeException e) {
StringBuilder exceptionBuffer =
new StringBuilder(256)
- .append("[" + toString() + "] Unexpected exception opening
from ")
+ .append("Unexpected exception opening from ")
.append(remoteHost)
.append(" (")
.append(remoteIP)
.append("): ")
.append(e.getMessage());
String exceptionString = exceptionBuffer.toString();
- getLogger().error(exceptionString, e);
+ log.error(exceptionString, e);
throw e;
} catch (IOException e) {
StringBuilder exceptionBuffer =
new StringBuilder(256)
- .append("[" + toString() + "] Cannot open connection from
")
+ .append("Cannot open connection from ")
.append(remoteHost)
.append(" (")
.append(remoteIP)
.append("): ")
.append(e.getMessage());
String exceptionString = exceptionBuffer.toString();
- getLogger().error(exceptionString, e);
+ log.error(exceptionString, e);
throw e;
}
- if (getLogger().isInfoEnabled()) {
+ if (log.isInfoEnabled()) {
StringBuilder infoBuffer =
new StringBuilder(128)
- .append("[" + toString() + "]Connection from ")
+ .append("Connection from ")
.append(remoteHost)
.append(" (")
.append(remoteIP)
.append(")");
- getLogger().info(infoBuffer.toString());
+ log.info(infoBuffer.toString());
}
}
@@ -211,7 +222,7 @@
inReader.close();
}
} catch (IOException ioe) {
- getLogger().warn("[" + toString() + "] Unexpected exception
occurred while closing reader: " + ioe);
+ log.warn("Unexpected exception occurred while closing reader: " +
ioe);
} finally {
inReader = null;
}
@@ -229,7 +240,7 @@
socket.close();
}
} catch (IOException ioe) {
- getLogger().warn("[" + toString() + "] Unexpected exception
occurred while closing socket: " + ioe);
+ log.warn("[Unexpected exception occurred while closing socket: " +
ioe);
} finally {
socket = null;
}
@@ -248,50 +259,49 @@
public void handleConnection(Socket connection) throws IOException {
initHandler(connection);
- final Logger logger = getLogger();
try {
// Do something:
handleProtocol();
- logger.debug("[" + toString() + "] Closing socket");
+ log.debug("Closing socket");
} catch (SocketException se) {
// Indicates a problem at the underlying protocol level
- if (logger.isWarnEnabled()) {
+ if (log.isWarnEnabled()) {
String message =
new StringBuilder(64)
- .append("[" + toString() + "]Socket to ")
+ .append("Socket to ")
.append(remoteHost)
.append(" (")
.append(remoteIP)
.append("): ")
.append(se.getMessage()).toString();
- logger.warn(message);
- logger.debug(se.getMessage(), se);
+ log.warn(message);
+ log.debug(se.getMessage(), se);
}
} catch ( InterruptedIOException iioe ) {
- if (logger.isErrorEnabled()) {
+ if (log.isErrorEnabled()) {
StringBuilder errorBuffer =
new StringBuilder(64)
- .append("[" + toString() + "] Socket to ")
+ .append("Socket to ")
.append(remoteHost)
.append(" (")
.append(remoteIP)
.append(") timeout.");
- logger.error( errorBuffer.toString(), iioe );
+ log.error( errorBuffer.toString(), iioe );
}
} catch ( IOException ioe ) {
- if (logger.isWarnEnabled()) {
+ if (log.isWarnEnabled()) {
String message =
new StringBuilder(256)
- .append("[" + toString() + "] Exception handling
socket to ")
+ .append("Exception handling socket to ")
.append(remoteHost)
.append(" (")
.append(remoteIP)
.append(") : ")
.append(ioe.getMessage()).toString();
- logger.warn(message);
- logger.debug( ioe.getMessage(), ioe );
+ log.warn(message);
+ log.debug( ioe.getMessage(), ioe );
}
} catch (RuntimeException e) {
errorHandler(e);
@@ -325,8 +335,8 @@
* Idle out this connection
*/
void idleClose() {
- if (getLogger() != null) {
- getLogger().error("[" + toString() + "] Service Connection has
idled out.");
+ if (log != null) {
+ log.error("Service Connection has idled out.");
}
try {
if (socket != null) {
@@ -357,8 +367,8 @@
* @param responseString the response string sent to the client
*/
private final void logResponseString(String responseString) {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("[" + toString() + "] Sent: " + responseString);
+ if (log.isDebugEnabled()) {
+ log.debug("Sent: " + responseString);
}
}
@@ -438,20 +448,6 @@
}
/**
- * The name of this handler.
- * Note that this name should be file-system safe.
- * Used for context sensitive logging.
- * @param name the name to set
- */
- public final void setName(final String name) {
- if (name == null) {
- this.name = DEFAULT_NAME;
- } else {
- this.name = name;
- }
- }
-
- /**
* Use for context sensitive logging.
* @return the name of the handler
*/
@@ -496,8 +492,8 @@
* @see
org.apache.james.socket.ProtocolHandlerHelper#defaultErrorHandler(java.lang.RuntimeException)
*/
public void defaultErrorHandler(RuntimeException e) {
- if (getLogger().isErrorEnabled()) {
- getLogger().error( "[" + toString() + "] Unexpected runtime
exception: "
+ if (log.isErrorEnabled()) {
+ log.error( "Unexpected runtime exception: "
+ e.getMessage(), e );
}
}
@@ -548,7 +544,7 @@
* @see org.apache.james.socket.ProtocolHandlerHelper#getAvalonLogger()
*/
public Logger getAvalonLogger() {
- return getLogger();
+ return logger;
}
/**
@@ -564,4 +560,11 @@
public Socket getSocket() {
return socket;
}
+
+ /**
+ * @see org.apache.james.socket.ProtocolHandlerHelper#getLogger()
+ */
+ public Log getLogger() {
+ return log;
+ }
}
Added:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/HandlerLog.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/HandlerLog.java?rev=815465&view=auto
==============================================================================
---
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/HandlerLog.java
(added)
+++
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/HandlerLog.java
Tue Sep 15 20:22:59 2009
@@ -0,0 +1,133 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.socket;
+
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.commons.logging.Log;
+
+/**
+ * Context sensitive logger for handlers.
+ */
+public final class HandlerLog implements Log {
+
+ private final Logger logger;
+ private final String prefix;
+
+ public HandlerLog(final Logger logger, final String prefix) {
+ this.logger = logger;
+ this.prefix = prefix;
+ }
+
+ public final void debug(Object message) {
+ if (isDebugEnabled()) {
+ logger.debug(toString(message));
+ }
+ }
+
+ public final void debug(Object message, Throwable t) {
+ if (isDebugEnabled()) {
+ logger.debug(toString(message), t);
+ }
+ }
+
+ public final void error(Object message) {
+ if (isErrorEnabled()) {
+ logger.error(toString(message));
+ }
+ }
+
+ public final void error(Object message, Throwable t) {
+ if (isErrorEnabled()) {
+ logger.error(toString(message), t);
+ }
+ }
+
+ public final void fatal(Object message) {
+ if (isFatalEnabled()) {
+ logger.fatalError(toString(message));
+ }
+ }
+
+ public final void fatal(Object message, Throwable t) {
+ if (isFatalEnabled()) {
+ logger.fatalError(toString(message), t);
+ }
+ }
+
+ public final void info(Object message) {
+ if (isInfoEnabled()) {
+ logger.info(toString(message));
+ }
+ }
+
+ public final void info(Object message, Throwable t) {
+ if (isInfoEnabled()) {
+ logger.info(toString(message), t);
+ }
+ }
+
+ public final boolean isDebugEnabled() {
+ return logger.isDebugEnabled();
+ }
+
+ public final boolean isErrorEnabled() {
+ return logger.isErrorEnabled();
+ }
+
+ public final boolean isFatalEnabled() {
+ return logger.isFatalErrorEnabled();
+ }
+
+ public final boolean isInfoEnabled() {
+ return logger.isInfoEnabled();
+ }
+
+ public final boolean isTraceEnabled() {
+ return isDebugEnabled();
+ }
+
+ public final boolean isWarnEnabled() {
+ return logger.isWarnEnabled();
+ }
+
+ public final void trace(Object message) {
+ debug(message);
+ }
+
+ public final void trace(Object message, Throwable t) {
+ debug(message, t);
+ }
+
+ public final void warn(Object message) {
+ if (isWarnEnabled()) {
+ logger.warn(toString(message));
+ }
+ }
+
+ public final void warn(Object message, Throwable t) {
+ if (isWarnEnabled()) {
+ logger.warn(toString(message), t);
+ }
+ }
+
+ private String toString(final Object message) {
+ return prefix + message;
+ }
+}
Propchange:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/HandlerLog.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/ProtocolHandlerHelper.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/ProtocolHandlerHelper.java?rev=815465&r1=815464&r2=815465&view=diff
==============================================================================
---
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/ProtocolHandlerHelper.java
(original)
+++
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/ProtocolHandlerHelper.java
Tue Sep 15 20:22:59 2009
@@ -21,6 +21,7 @@
package org.apache.james.socket;
import org.apache.avalon.framework.logger.Logger;
+import org.apache.commons.logging.Log;
import java.io.InputStream;
import java.io.OutputStream;
@@ -104,11 +105,10 @@
* @return socket
*/
public Socket getSocket();
-
+
/**
- * The name of this handler.
- * Used for context sensitive logging.
- * @return the name, not null
+ * Gets a context sensitive logger.
+ * @return not null
*/
- public String getName();
+ public Log getLogger();
}
\ No newline at end of file
Modified:
james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/ImapHandler.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/ImapHandler.java?rev=815465&r1=815464&r2=815465&view=diff
==============================================================================
---
james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/ImapHandler.java
(original)
+++
james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/ImapHandler.java
Tue Sep 15 20:22:59 2009
@@ -23,18 +23,15 @@
import java.net.Socket;
import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
-import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.avalon.framework.logger.Logger;
+import org.apache.commons.logging.Log;
import org.apache.james.imap.api.process.ImapSession;
-import org.apache.james.imap.main.ContextualLog;
+import org.apache.james.imap.encode.ImapResponseComposer;
+import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
import org.apache.james.imap.main.ImapRequestHandler;
import org.apache.james.imap.main.ImapSessionImpl;
import org.apache.james.imap.main.OutputStreamImapResponseWriter;
-import org.apache.james.imap.encode.ImapResponseComposer;
-import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
import org.apache.james.socket.ProtocolHandler;
import org.apache.james.socket.ProtocolHandlerHelper;
-import org.apache.commons.logging.impl.AvalonLogger;
/**
* Handles IMAP connections.
@@ -114,7 +111,7 @@
*/
private void setUpSession() {
final ImapSessionImpl session = new ImapSessionImpl();
- session.setLog(new ContextualLog("[" + helper.getName() + "]", new
AvalonLogger(getLogger())));
+ session.setLog(helper.getLogger());
this.session = session;
}
@@ -137,8 +134,8 @@
helper.defaultErrorHandler(e);
}
- public Logger getLogger() {
- return helper.getAvalonLogger();
+ public Log getLogger() {
+ return helper.getLogger();
}
public void setProtocolHandlerHelper(ProtocolHandlerHelper phh) {
Modified:
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java?rev=815465&r1=815464&r2=815465&view=diff
==============================================================================
---
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java
(original)
+++
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java
Tue Sep 15 20:22:59 2009
@@ -29,8 +29,6 @@
import java.util.Random;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.logging.impl.AvalonLogger;
import org.apache.james.socket.CRLFDelimitedByteBuffer;
import org.apache.james.socket.ProtocolHandler;
import org.apache.james.socket.ProtocolHandlerHelper;
@@ -49,8 +47,6 @@
* Static Random instance used to generate SMTP ids
*/
private final static Random random = new Random();
-
- private Log log = LogFactory.getLog(this.getClass());
/**
* The name of the currently parsed command
@@ -113,7 +109,6 @@
* @see org.apache.james.socket.ProtocolHandler#handleProtocol()
*/
public void handleProtocol() throws IOException {
- this.log = new AvalonLogger(helper.getAvalonLogger());
smtpID = Integer.toString(random.nextInt(1024));
relayingAllowed =
theConfigData.isRelayingAllowed(helper.getRemoteIP());
authSupported = theConfigData.isAuthRequired(helper.getRemoteIP());
@@ -417,6 +412,6 @@
}
public Log getLogger() {
- return log;
+ return helper.getLogger();
}
}
Modified:
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SMTPCommandDispatcherLineHandler.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SMTPCommandDispatcherLineHandler.java?rev=815465&r1=815464&r2=815465&view=diff
==============================================================================
---
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SMTPCommandDispatcherLineHandler.java
(original)
+++
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SMTPCommandDispatcherLineHandler.java
Tue Sep 15 20:22:59 2009
@@ -42,7 +42,7 @@
/**
* The list of available command handlers
*/
- private HashMap commandHandlerMap = new HashMap();
+ private HashMap<String, List<CommandHandler>> commandHandlerMap = new
HashMap<String, List<CommandHandler>>();
private final CommandHandler unknownHandler = new UnknownCmdHandler();
@@ -71,7 +71,7 @@
}
curCommandName = curCommandName.toUpperCase(Locale.US);
- List commandHandlers = getCommandHandlers(curCommandName);
+ List<CommandHandler> commandHandlers =
getCommandHandlers(curCommandName, session);
//fetch the command handlers registered to the command
if(commandHandlers == null) {
//end the session
@@ -81,7 +81,7 @@
} else {
int count = commandHandlers.size();
for(int i = 0; i < count; i++) {
- SMTPResponse response =
((CommandHandler)commandHandlers.get(i)).onCommand(session, curCommandName,
curCommandArgument);
+ SMTPResponse response =
commandHandlers.get(i).onCommand(session, curCommandName, curCommandArgument);
session.writeSMTPResponse(response);
@@ -116,7 +116,7 @@
* @see
org.apache.james.smtpserver.ExtensibleHandler#wireExtensions(java.lang.Class,
java.util.List)
*/
public void wireExtensions(Class interfaceName, List extension) throws
WiringException {
- this.commandHandlerMap = new HashMap();
+ this.commandHandlerMap = new HashMap<String, List<CommandHandler>>();
for (Iterator it = extension.iterator(); it.hasNext(); ) {
CommandHandler handler = (CommandHandler) it.next();
@@ -165,15 +165,15 @@
/**
- * Add it to map (key as command name, value is an array list of
commandhandlers)
+ * Add it to map (key as command name, value is an array list of
CommandHandlers)
*
* @param commandName the command name which will be key
- * @param cmdHandler The commandhandler object
+ * @param cmdHandler The CommandHandler object
*/
private void addToMap(String commandName, CommandHandler cmdHandler) {
- ArrayList handlers = (ArrayList)commandHandlerMap.get(commandName);
+ List<CommandHandler> handlers = commandHandlerMap.get(commandName);
if(handlers == null) {
- handlers = new ArrayList();
+ handlers = new ArrayList<CommandHandler>();
commandHandlerMap.put(commandName, handlers);
}
handlers.add(cmdHandler);
@@ -181,21 +181,22 @@
/**
- * Returns all the configured commandhandlers for the specified command
+ * Returns all the configured CommandHandlers for the specified command
*
* @param command the command name which will be key
- * @return List of commandhandlers
+ * @param session not null
+ * @return List of CommandHandlers
*/
- List getCommandHandlers(String command) {
+ private List<CommandHandler> getCommandHandlers(String command,
SMTPSession session) {
if (command == null) {
return null;
}
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("Lookup command handler for command: " +
command);
+ if (session.getLogger().isDebugEnabled()) {
+ session.getLogger().debug("Lookup command handler for command: " +
command);
}
- List handlers = (List)commandHandlerMap.get(command);
+ List<CommandHandler> handlers = commandHandlerMap.get(command);
if(handlers == null) {
- handlers =
(List)commandHandlerMap.get(UnknownCmdHandler.UNKNOWN_COMMAND);
+ handlers =
commandHandlerMap.get(UnknownCmdHandler.UNKNOWN_COMMAND);
}
return handlers;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]