You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2011/12/23 21:19:13 UTC

svn commit: r1222829 - in /james/protocols/trunk: api/src/main/java/org/apache/james/protocols/api/handler/ netty/src/main/java/org/apache/james/protocols/netty/ smtp/src/main/java/org/apache/james/protocols/smtp/core/ smtp/src/main/java/org/apache/jam...

Author: norman
Date: Fri Dec 23 20:19:13 2011
New Revision: 1222829

URL: http://svn.apache.org/viewvc?rev=1222829&view=rev
Log:
Use ByteBuffer as parameter in LineHandler and DataLineFilter. See PROTOCOLS-71

Modified:
    james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/CommandDispatcher.java
    james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/LineHandler.java
    james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/BasicChannelUpstreamHandler.java
    james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/LineHandlerUpstreamHandler.java
    james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
    james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineFilter.java
    james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java
    james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java
    james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/AuthCmdHandler.java
    james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java

Modified: james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/CommandDispatcher.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/CommandDispatcher.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/CommandDispatcher.java (original)
+++ james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/CommandDispatcher.java Fri Dec 23 20:19:13 2011
@@ -19,6 +19,7 @@
 
 package org.apache.james.protocols.api.handler;
 
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -129,10 +130,11 @@ public class CommandDispatcher<Session e
 
     }
     
-    /**
-     * @see org.apache.james.protocols.api.handler.LineHandler#onLine(ProtocolSession, byte[])
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.protocols.api.handler.LineHandler#onLine(org.apache.james.protocols.api.ProtocolSession, java.nio.ByteBuffer)
      */
-    public Response onLine(final Session session, byte[] line) {
+    public Response onLine(final Session session, ByteBuffer line) {
         
         try {
             
@@ -184,9 +186,16 @@ public class CommandDispatcher<Session e
      * @return request
      * @throws Exception
      */
-    protected Request parseRequest(Session session, byte[] line) throws Exception {
+    protected Request parseRequest(Session session, ByteBuffer buffer) throws Exception {
         String curCommandName = null;
         String curCommandArgument = null;
+        byte[] line;
+        if (buffer.hasArray()) {
+            line = buffer.array();
+        } else {
+            line = new byte[buffer.remaining()];
+            buffer.get(line);
+        }
         String cmdString = new String(line, getLineDecodingCharset()).trim();
         int spaceIndex = cmdString.indexOf(" ");
         if (spaceIndex > 0) {

Modified: james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/LineHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/LineHandler.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/LineHandler.java (original)
+++ james/protocols/trunk/api/src/main/java/org/apache/james/protocols/api/handler/LineHandler.java Fri Dec 23 20:19:13 2011
@@ -19,6 +19,8 @@
 
 package org.apache.james.protocols.api.handler;
 
+import java.nio.ByteBuffer;
+
 import org.apache.james.protocols.api.ProtocolSession;
 import org.apache.james.protocols.api.Response;
 
@@ -29,14 +31,15 @@ import org.apache.james.protocols.api.Re
  */
 public interface LineHandler<Session extends ProtocolSession> extends ProtocolHandler{
      
+    public static final String CRLF = "\r\n";
     /**
-     * Processing the give line. The line includes the CRLF delimiter.
+     * Processing the give line. The line includes the {@link #CRLF} delimiter.
      * If true is returned the connection is closed
      * 
      * @param session not null
      * @param line not null 
      * @return response or null
      */
-    Response onLine(Session session, byte[] line);
+    Response onLine(Session session, ByteBuffer buffer);
     
 }

Modified: james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/BasicChannelUpstreamHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/BasicChannelUpstreamHandler.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/BasicChannelUpstreamHandler.java (original)
+++ james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/BasicChannelUpstreamHandler.java Fri Dec 23 20:19:13 2011
@@ -144,19 +144,10 @@ public class BasicChannelUpstreamHandler
         if (lineHandlers.size() > 0) {
         
             ChannelBuffer buf = (ChannelBuffer) e.getMessage();      
-            byte[] line;
-            
-            if (buf.hasArray()) {
-                line = buf.array();
-            } else {
-                // copy the ChannelBuffer to a byte array to process the LineHandler
-                line = new byte[buf.capacity()];
-                buf.getBytes(0, line);
-            }
             
             LineHandler lHandler=  (LineHandler) lineHandlers.getLast();
             long start = System.currentTimeMillis();            
-            Response response = lHandler.onLine(pSession,line);
+            Response response = lHandler.onLine(pSession,buf.toByteBuffer());
             long executionTime = System.currentTimeMillis() - start;
 
             for (int i = 0; i < resultHandlers.size(); i++) {

Modified: james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/LineHandlerUpstreamHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/LineHandlerUpstreamHandler.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/LineHandlerUpstreamHandler.java (original)
+++ james/protocols/trunk/netty/src/main/java/org/apache/james/protocols/netty/LineHandlerUpstreamHandler.java Fri Dec 23 20:19:13 2011
@@ -46,23 +46,8 @@ public class LineHandlerUpstreamHandler<
     @Override
     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {        
         ChannelBuffer buf = (ChannelBuffer) e.getMessage();      
-        byte[] line;
-        if (buf.hasArray()) {
-            if (buf.arrayOffset() == 0 && buf.readableBytes() == buf.capacity()) {
-                // we have no offset and the length is the same as the capacity. Its safe to reuse the array without copy it first
-                line = buf.array();
-            } else {
-                // copy the ChannelBuffer to a byte array to process the LineHandler
-                line = new byte[buf.readableBytes()];
-                buf.getBytes(0, line);
-            }
-        } else {
-            // copy the ChannelBuffer to a byte array to process the LineHandler
-            line = new byte[buf.readableBytes()];
-            buf.getBytes(0, line);
-        }
 
-        Response response = handler.onLine(session, line); 
+        Response response = handler.onLine(session, buf.toByteBuffer()); 
         if (response != null) {
             // TODO: This kind of sucks but I was able to come up with something more elegant here
             ((ProtocolSessionImpl)session).getProtocolTransport().writeResponse(response, session);

Modified: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java (original)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataCmdHandler.java Fri Dec 23 20:19:13 2011
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.protocols.smtp.core;
 
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -50,14 +51,9 @@ public class DataCmdHandler implements C
 	
     public static final class DataConsumerLineHandler implements LineHandler<SMTPSession> {
 
-        /**
-         * @see org.apache.james.protocols.api.handler.LineHandler
-         * #onLine(org.apache.james.protocols.api.ProtocolSession, byte[])
-         */
-        public SMTPResponse onLine(SMTPSession session, byte[] line) {
-            
+        public SMTPResponse onLine(SMTPSession session, ByteBuffer line) {
             // Discard everything until the end of DATA session
-            if (line.length == 3 && line[0] == 46) {
+            if (line.remaining() == 3 && line.get() == 46) {
                 session.popLineHandler();
             }
             return null;
@@ -74,12 +70,15 @@ public class DataCmdHandler implements C
             this.next = next;
         }
         
-        /**
-         * @see org.apache.james.protocols.api.handler.LineHandler
-         * #onLine(org.apache.james.protocols.api.ProtocolSession, byte[])
+
+        /*
+         * (non-Javadoc)
+         * @see org.apache.james.protocols.api.handler.LineHandler#onLine(org.apache.james.protocols.api.ProtocolSession, java.nio.ByteBuffer)
          */
-        public Response onLine(SMTPSession session, byte[] line) {
-            return filter.onLine(session, line, next);
+        public Response onLine(SMTPSession session, ByteBuffer line) {
+            line.rewind();
+            Response r = filter.onLine(session, line, next);
+            return r;
         }
                 
     }

Modified: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineFilter.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineFilter.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineFilter.java (original)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineFilter.java Fri Dec 23 20:19:13 2011
@@ -21,6 +21,8 @@
 
 package org.apache.james.protocols.smtp.core;
 
+import java.nio.ByteBuffer;
+
 import org.apache.james.protocols.api.Response;
 import org.apache.james.protocols.api.handler.LineHandler;
 import org.apache.james.protocols.api.handler.ProtocolHandler;
@@ -39,5 +41,5 @@ public interface DataLineFilter extends 
      * @param line
      * @param next
      */
-    Response onLine(SMTPSession session, byte[] line, LineHandler<SMTPSession> next);
+    Response onLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next);
 }
\ No newline at end of file

Modified: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java (original)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/DataLineMessageHookHandler.java Fri Dec 23 20:19:13 2011
@@ -23,6 +23,7 @@ package org.apache.james.protocols.smtp.
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.ByteBuffer;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -54,16 +55,19 @@ public class DataLineMessageHookHandler 
     private List<?> rHooks;
     
 
-    /**
-     * @see org.apache.james.protocols.smtp.core.DataLineFilter#onLine(SMTPSession, byte[], LineHandler)
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.protocols.smtp.core.DataLineFilter#onLine(org.apache.james.protocols.smtp.SMTPSession, java.nio.ByteBuffer, org.apache.james.protocols.api.handler.LineHandler)
      */
-    public Response onLine(final SMTPSession session, byte[] line, LineHandler<SMTPSession> next) {
+    public Response onLine(final SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
         MailEnvelopeImpl env = (MailEnvelopeImpl) session.getAttachment(DataCmdHandler.MAILENV, ProtocolSession.State.Transaction);
         OutputStream out = env.getMessageOutputStream();
         try {
             // 46 is "."
-            // Stream terminated
-            if (line.length == 3 && line[0] == 46) {
+            // Stream terminated            
+            int c = line.get();
+            if (line.remaining() == 2 && c== 46) {
                 out.flush();
                 out.close();
                 
@@ -73,14 +77,15 @@ public class DataLineMessageHookHandler 
                 return response;
                 
             // DotStuffing.
-            } else if (line[0] == 46 && line[1] == 46) {
-                out.write(line,1,line.length-1);
+            } else if (c == 46 && line.get() == 46) {
+                byte[] bline = readBytes(line);
+                out.write(bline,1,bline.length-1);
             // Standard write
             } else {
                 // TODO: maybe we should handle the Header/Body recognition here
                 // and if needed let a filter to cache the headers to apply some
                 // transformation before writing them to output.
-                out.write(line);
+                out.write(readBytes(line));
             }
             out.flush();
         } catch (IOException e) {
@@ -92,10 +97,21 @@ public class DataLineMessageHookHandler 
             
             session.resetState();
             return response;
-        } 
+        }
         return null;
     }
 
+    private byte[] readBytes(ByteBuffer line) {
+        line.rewind();
+        byte[] bline;
+        if (line.hasArray()) {
+            bline = line.array();
+        } else {
+            bline = new byte[line.remaining()];
+            line.get(bline);
+        }
+        return bline;
+    }
 
     /**
      * @param session

Modified: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java (original)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/ReceivedDataLineFilter.java Fri Dec 23 20:19:13 2011
@@ -19,6 +19,7 @@
 package org.apache.james.protocols.smtp.core;
 
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
@@ -49,10 +50,12 @@ public class ReceivedDataLineFilter impl
     private final static String HEADERS_WRITTEN = "HEADERS_WRITTEN";
 
 
-    /**
-     * @see org.apache.james.protocols.smtp.core.DataLineFilter#onLine(SMTPSession, byte[], LineHandler)
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.protocols.smtp.core.DataLineFilter#onLine(org.apache.james.protocols.smtp.SMTPSession, java.nio.ByteBuffer, org.apache.james.protocols.api.handler.LineHandler)
      */
-    public Response onLine(SMTPSession session,  byte[] line, LineHandler<SMTPSession> next) {
+    public Response onLine(SMTPSession session,  ByteBuffer line, LineHandler<SMTPSession> next) {
         if (session.getAttachment(HEADERS_WRITTEN, State.Transaction) == null) {
             Response response = addNewReceivedMailHeaders(session, next);
 
@@ -83,7 +86,7 @@ public class ReceivedDataLineFilter impl
 
             headerLineBuffer.append(" ([").append(session.getRemoteAddress().getAddress().getHostAddress()).append("])").append("\r\n");
 
-            Response response = next.onLine(session, headerLineBuffer.toString().getBytes(CHARSET));
+            Response response = next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
             if (response != null) {
                 return response;
             }
@@ -99,12 +102,12 @@ public class ReceivedDataLineFilter impl
                 // (prevents email address harvesting and large headers in
                 // bulk email)
                 headerLineBuffer.append("\r\n");
-                next.onLine(session, headerLineBuffer.toString().getBytes(CHARSET));
+                next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
                 headerLineBuffer.delete(0, headerLineBuffer.length());
 
                 headerLineBuffer.delete(0, headerLineBuffer.length());
                 headerLineBuffer.append("          for <").append(((List<MailAddress>) session.getAttachment(SMTPSession.RCPT_LIST, State.Transaction)).get(0).toString()).append(">;").append("\r\n");
-                response = next.onLine(session, headerLineBuffer.toString().getBytes(CHARSET));
+                response = next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
 
                 if (response != null) {
                     return response;
@@ -117,14 +120,14 @@ public class ReceivedDataLineFilter impl
                 headerLineBuffer.append(";");
                 headerLineBuffer.append("\r\n");
 
-                response = next.onLine(session, headerLineBuffer.toString().getBytes(CHARSET));
+                response = next.onLine(session, ByteBuffer.wrap(headerLineBuffer.toString().getBytes(CHARSET)));
                 if (response != null) {
                     return response;
                 }
                 headerLineBuffer.delete(0, headerLineBuffer.length());
             }
             headerLineBuffer = null;
-            return next.onLine(session, ("          " + DATEFORMAT.get().format(new Date()) + "\r\n").getBytes(CHARSET));
+            return next.onLine(session, ByteBuffer.wrap(("          " + DATEFORMAT.get().format(new Date()) + "\r\n").getBytes(CHARSET)));
         } catch (UnsupportedEncodingException e) {
             throw new RuntimeException("No US-ASCII support ?");
         }

Modified: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/AuthCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/AuthCmdHandler.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/AuthCmdHandler.java (original)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/AuthCmdHandler.java Fri Dec 23 20:19:13 2011
@@ -22,6 +22,7 @@
 package org.apache.james.protocols.smtp.core.esmtp;
 
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -65,8 +66,15 @@ public class AuthCmdHandler
     private final static String CHARSET = "US-ASCII";
     private abstract class AbstractSMTPLineHandler implements LineHandler<SMTPSession> {
 
-        public Response onLine(SMTPSession session, byte[] l) {
+        public Response onLine(SMTPSession session, ByteBuffer line) {
             try {
+                byte[] l;
+                if (line.hasArray()) {
+                    l = line.array();
+                } else {
+                    l = new byte[line.remaining()];
+                    line.get(l);
+                }
                 return handleCommand(session, new String(l, CHARSET));
             } catch (UnsupportedEncodingException e) {
                 throw new RuntimeException("No " + CHARSET + " support!");

Modified: james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java?rev=1222829&r1=1222828&r2=1222829&view=diff
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java (original)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/MailSizeEsmtpExtension.java Fri Dec 23 20:19:13 2011
@@ -19,6 +19,7 @@
 
 package org.apache.james.protocols.smtp.core.esmtp;
 
+import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -141,7 +142,7 @@ public class MailSizeEsmtpExtension impl
     /**
      * @see org.apache.james.protocols.smtp.core.DataLineFilter#onLine(SMTPSession, byte[], LineHandler)
      */
-    public Response onLine(SMTPSession session, byte[] line, LineHandler<SMTPSession> next) {
+    public Response onLine(SMTPSession session, ByteBuffer line, LineHandler<SMTPSession> next) {
         Response response = null;
     	Boolean failed = (Boolean) session.getAttachment(MESG_FAILED, State.Transaction);
         // If we already defined we failed and sent a reply we should simply
@@ -149,15 +150,17 @@ public class MailSizeEsmtpExtension impl
         if (failed != null && failed.booleanValue()) {
             // TODO
         } else {
-            if (line.length == 3 && line[0] == 46) {
+            if (line.remaining() == 3 && line.get() == 46) {
+                line.rewind();
                 response = next.onLine(session, line);
             } else {
+                line.rewind();
                 Long currentSize = (Long) session.getAttachment("CURRENT_SIZE", State.Transaction);
                 Long newSize;
                 if (currentSize == null) {
-                    newSize = Long.valueOf(line.length);
+                    newSize = Long.valueOf(line.remaining());
                 } else {
-                    newSize = Long.valueOf(currentSize.intValue()+line.length);
+                    newSize = Long.valueOf(currentSize.intValue()+line.remaining());
                 }
                 
                 if (session.getConfiguration().getMaxMessageSize() > 0 && newSize.intValue() > session.getConfiguration().getMaxMessageSize()) {
@@ -168,8 +171,9 @@ public class MailSizeEsmtpExtension impl
                     session.setAttachment(MESG_FAILED, Boolean.TRUE, State.Transaction);
                     // then let the client know that the size
                     // limit has been hit.
-                    response = next.onLine(session, ".\r\n".getBytes());
+                    response = next.onLine(session, ByteBuffer.wrap(".\r\n".getBytes()));
                 } else {
+                    line.rewind();
                     response = next.onLine(session, line);
                 }
                 



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org