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 ba...@apache.org on 2006/05/06 19:09:58 UTC

svn commit: r400340 - in /james/server/trunk/src/java/org/apache/james: core/ nntpserver/ pop3server/ remotemanager/ smtpserver/

Author: bago
Date: Sat May  6 10:09:57 2006
New Revision: 400340

URL: http://svn.apache.org/viewcvs?rev=400340&view=rev
Log:
Created an AbstractJamesHandler to remove duplicated code/behaviours from our 4 service handlers.
Just another step to remove avalon stuff from the core handler, and group avalon specific code in fewer classes as possible.

Added:
    james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java   (with props)
Modified:
    james/server/trunk/src/java/org/apache/james/core/AbstractJamesService.java
    james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java
    james/server/trunk/src/java/org/apache/james/nntpserver/NNTPServer.java
    james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java
    james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java
    james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManager.java
    james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java
    james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java
    james/server/trunk/src/java/org/apache/james/smtpserver/SMTPServer.java

Added: james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java?rev=400340&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java (added)
+++ james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java Sat May  6 10:09:57 2006
@@ -0,0 +1,168 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * 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.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.james.core;
+
+import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
+import org.apache.avalon.excalibur.pool.Poolable;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.james.util.watchdog.Watchdog;
+import org.apache.james.util.watchdog.WatchdogTarget;
+
+import java.io.PrintWriter;
+import java.net.Socket;
+
+/**
+ * Common Handler code
+ */
+public abstract class AbstractJamesHandler extends AbstractLogEnabled implements ConnectionHandler, Poolable {
+
+
+    /**
+     * The thread executing this handler
+     */
+    protected Thread handlerThread;
+
+    /**
+     * The TCP/IP socket over which the POP3 interaction
+     * is occurring
+     */
+    protected Socket socket;
+
+    /**
+     * The writer to which outgoing messages are written.
+     */
+    protected PrintWriter out;
+    
+    /**
+     * The watchdog being used by this handler to deal with idle timeouts.
+     */
+    protected Watchdog theWatchdog;
+
+    /**
+     * The watchdog target that idles out this handler.
+     */
+    private WatchdogTarget theWatchdogTarget = new JamesWatchdogTarget();
+
+
+    public abstract void setConfigurationData(Object theData);
+
+
+    /**
+     * Set the Watchdog for use by this handler.
+     *
+     * @param theWatchdog the watchdog
+     */
+    void setWatchdog(Watchdog theWatchdog) {
+        this.theWatchdog = theWatchdog;
+    }
+
+    /**
+     * Gets the Watchdog Target that should be used by Watchdogs managing
+     * this connection.
+     *
+     * @return the WatchdogTarget
+     */
+    WatchdogTarget getWatchdogTarget() {
+        return theWatchdogTarget;
+    }
+
+    /**
+     * Idle out this connection
+     */
+    void idleClose() {
+        if (getLogger() != null) {
+            getLogger().error("POP3 Connection has idled out.");
+        }
+        try {
+            if (socket != null) {
+                socket.close();
+            }
+        } catch (Exception e) {
+            // ignored
+        } finally {
+            socket = null;
+        }
+
+        synchronized (this) {
+            // Interrupt the thread to recover from internal hangs
+            if (handlerThread != null) {
+                handlerThread.interrupt();
+                handlerThread = null;
+            }
+        }
+
+    }
+
+    /**
+     * This method logs at a "DEBUG" level the response string that
+     * was sent to the POP3 client.  The method is provided largely
+     * as syntactic sugar to neaten up the code base.  It is declared
+     * private and final to encourage compiler inlining.
+     *
+     * @param responseString the response string sent to the client
+     */
+    private final void logResponseString(String responseString) {
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Sent: " + responseString);
+        }
+    }
+
+    /**
+     * Write and flush a response string.  The response is also logged.
+     * Should be used for the last line of a multi-line response or
+     * for a single line response.
+     *
+     * @param responseString the response string sent to the client
+     */
+    protected final void writeLoggedFlushedResponse(String responseString) {
+        out.println(responseString);
+        out.flush();
+        logResponseString(responseString);
+    }
+
+    /**
+     * Write a response string.  The response is also logged.
+     * Used for multi-line responses.
+     *
+     * @param responseString the response string sent to the client
+     */
+    protected final void writeLoggedResponse(String responseString) {
+        out.println(responseString);
+        logResponseString(responseString);
+    }
+
+
+    /**
+     * A private inner class which serves as an adaptor
+     * between the WatchdogTarget interface and this
+     * handler class.
+     */
+    private class JamesWatchdogTarget
+        implements WatchdogTarget {
+
+        /**
+         * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
+         */
+        public void execute() {
+            AbstractJamesHandler.this.idleClose();
+        }
+
+    }
+
+
+}

Propchange: james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: james/server/trunk/src/java/org/apache/james/core/AbstractJamesService.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/core/AbstractJamesService.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/core/AbstractJamesService.java (original)
+++ james/server/trunk/src/java/org/apache/james/core/AbstractJamesService.java Sat May  6 10:09:57 2006
@@ -17,10 +17,17 @@
 
 package org.apache.james.core;
 
+import org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory;
+import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
+import org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory;
+import org.apache.avalon.cornerstone.services.sockets.ServerSocketFactory;
+import org.apache.avalon.cornerstone.services.sockets.SocketManager;
+import org.apache.avalon.cornerstone.services.threads.ThreadManager;
 import org.apache.avalon.excalibur.pool.DefaultPool;
 import org.apache.avalon.excalibur.pool.HardResourceLimitingPool;
 import org.apache.avalon.excalibur.pool.ObjectFactory;
 import org.apache.avalon.excalibur.pool.Pool;
+import org.apache.avalon.excalibur.pool.Poolable;
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configurable;
@@ -30,18 +37,10 @@
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.Serviceable;
-
 import org.apache.excalibur.thread.ThreadPool;
-import org.apache.avalon.cornerstone.services.threads.ThreadManager;
-
-import org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory;
-import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
-import org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory;
-import org.apache.avalon.cornerstone.services.sockets.ServerSocketFactory;
-import org.apache.avalon.cornerstone.services.sockets.SocketManager;
-
 import org.apache.james.services.JamesConnectionManager;
 import org.apache.james.util.watchdog.ThreadPerWatchdogFactory;
+import org.apache.james.util.watchdog.Watchdog;
 import org.apache.james.util.watchdog.WatchdogFactory;
 
 import java.net.InetAddress;
@@ -497,8 +496,33 @@
      * @return the new ConnectionHandler
      * @exception Exception if an error occurs
      */
-    protected abstract ConnectionHandler newHandler()
-        throws Exception;
+    protected ConnectionHandler newHandler()
+            throws Exception {
+        AbstractJamesHandler theHandler = (AbstractJamesHandler)theHandlerPool.get();
+        
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Getting Handler from pool.");
+        }
+
+        Watchdog theWatchdog = theWatchdogFactory.getWatchdog(theHandler.getWatchdogTarget());
+
+        theHandler.setConfigurationData(getConfigurationData());
+        theHandler.setWatchdog(theWatchdog);
+        return theHandler;
+    }
+
+    protected abstract Object getConfigurationData();
+
+    /**
+     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory#releaseConnectionHandler(ConnectionHandler)
+     */
+    public void releaseConnectionHandler( ConnectionHandler connectionHandler ) {
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Returning Handler to pool.");
+        }
+        theHandlerPool.put((Poolable)connectionHandler);
+    }
+
 
     /**
      * Get the default port for this server type.

Modified: james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java (original)
+++ james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java Sat May  6 10:09:57 2006
@@ -17,10 +17,8 @@
 
 package org.apache.james.nntpserver;
 
-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.james.core.AbstractJamesHandler;
 import org.apache.james.core.MailHeaders;
 import org.apache.james.nntpserver.repository.NNTPArticle;
 import org.apache.james.nntpserver.repository.NNTPGroup;
@@ -28,11 +26,11 @@
 import org.apache.james.util.DotStuffingInputStream;
 import org.apache.james.util.ExtraDotOutputStream;
 import org.apache.james.util.InternetPrintWriter;
-import org.apache.mailet.dates.RFC977DateFormat;
 import org.apache.mailet.dates.RFC2980DateFormat;
+import org.apache.mailet.dates.RFC977DateFormat;
 import org.apache.mailet.dates.SimplifiedDateFormat;
-import org.apache.james.util.watchdog.Watchdog;
-import org.apache.james.util.watchdog.WatchdogTarget;
+
+import javax.mail.MessagingException;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -42,7 +40,6 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.io.PrintWriter;
 import java.io.SequenceInputStream;
 import java.net.Socket;
 import java.text.ParseException;
@@ -53,7 +50,6 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.StringTokenizer;
-import javax.mail.MessagingException;
 
 /**
  * The NNTP protocol is defined by RFC 977.
@@ -63,8 +59,7 @@
  * Common NNTP extensions are in RFC 2980.
  */
 public class NNTPHandler
-    extends AbstractLogEnabled
-    implements ConnectionHandler, Poolable {
+    extends AbstractJamesHandler {
 
     /**
      * used to calculate DATE from - see 11.3
@@ -227,11 +222,6 @@
     private final static char[] NNTPTerminator = { '\r', '\n', '.', '\r', '\n' };
 
     /**
-     * The thread executing this handler 
-     */
-    private Thread handlerThread;
-
-    /**
      * The remote host name obtained by lookup on the socket.
      */
     private String remoteHost;
@@ -242,12 +232,6 @@
     private String remoteIP;
 
     /**
-     * The TCP/IP socket over which the POP3 interaction
-     * is occurring
-     */
-    private Socket socket;
-
-    /**
      * The incoming stream of bytes coming from the socket.
      */
     private InputStream in;
@@ -263,11 +247,6 @@
     private OutputStream outs;
 
     /**
-     * The writer to which outgoing messages are written.
-     */
-    private PrintWriter writer;
-
-    /**
      * The current newsgroup.
      */
     private NNTPGroup group;
@@ -300,66 +279,15 @@
     boolean isAlreadyAuthenticated = false;
 
     /**
-     * The watchdog being used by this handler to deal with idle timeouts.
-     */
-    private Watchdog theWatchdog;
-
-    /**
-     * The watchdog target that idles out this handler.
-     */
-    private WatchdogTarget theWatchdogTarget = new NNTPWatchdogTarget();
-
-    /**
      * Set the configuration data for the handler
      *
      * @param theData configuration data for the handler
      */
-    void setConfigurationData(NNTPHandlerConfigurationData theData) {
-        theConfigData = theData;
-    }
-
-    /**
-     * Set the Watchdog for use by this handler.
-     *
-     * @param theWatchdog the watchdog
-     */
-    void setWatchdog(Watchdog theWatchdog) {
-        this.theWatchdog = theWatchdog;
-    }
-
-    /**
-     * Gets the Watchdog Target that should be used by Watchdogs managing
-     * this connection.
-     *
-     * @return the WatchdogTarget
-     */
-    WatchdogTarget getWatchdogTarget() {
-        return theWatchdogTarget;
-    }
-
-    /**
-     * Idle out this connection
-     */
-    void idleClose() {
-        if (getLogger() != null) {
-            getLogger().error("NNTP Connection has idled out.");
-        }
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (Exception e) {
-            // ignored
-        } finally {
-            socket = null;
-        }
-
-        synchronized (this) {
-            // Interrupt the thread to recover from internal hangs
-            if (handlerThread != null) {
-                handlerThread.interrupt();
-                handlerThread = null;
-            }
+    public void setConfigurationData(Object theData) {
+        if (theData instanceof NNTPHandlerConfigurationData) {
+            theConfigData = (NNTPHandlerConfigurationData) theData;
+        } else {
+            throw new IllegalArgumentException("Configuration object does not implement NNTPHandlerConfigurationData");
         }
     }
 
@@ -380,7 +308,7 @@
             // to be ASCII
             reader = new BufferedReader(new InputStreamReader(in, "ASCII"), 512);
             outs = new BufferedOutputStream(socket.getOutputStream(), 1024);
-            writer = new InternetPrintWriter(outs, true);
+            out = new InternetPrintWriter(outs, true);
         } catch (Exception e) {
             StringBuffer exceptionBuffer = 
                 new StringBuffer(256)
@@ -459,9 +387,9 @@
 
         in = null;
 
-        if (writer != null) {
-            writer.close();
-            writer = null;
+        if (out != null) {
+            out.close();
+            out = null;
         }
         outs = null;
 
@@ -1039,7 +967,7 @@
             }
         }
         if (article != null) {
-            writer.flush();
+            out.flush();
             article.writeBody(new ExtraDotOutputStream(outs));
             writeLoggedFlushedResponse("\r\n.");
         }
@@ -1107,7 +1035,7 @@
             }
         }
         if (article != null) {
-            writer.flush();
+            out.flush();
             article.writeHead(new ExtraDotOutputStream(outs));
             writeLoggedFlushedResponse(".");
         }
@@ -1175,7 +1103,7 @@
             }
         }
         if (article != null) {
-            writer.flush();
+            out.flush();
             article.writeArticle(new ExtraDotOutputStream(outs));
             // see jira JAMES-311 for an explanation of the "\r\n"
             writeLoggedFlushedResponse("\r\n.");
@@ -1564,7 +1492,6 @@
         String date = tok.nextToken();
         String time = tok.nextToken();
         boolean utc = ( tok.hasMoreTokens() );
-        Date d = new Date();
         try {
             StringBuffer dateStringBuffer =
                 new StringBuffer(64)
@@ -1689,58 +1616,4 @@
         }
    }
 
-    /**
-     * This method logs at a "DEBUG" level the response string that 
-     * was sent to the SMTP client.  The method is provided largely
-     * as syntactic sugar to neaten up the code base.  It is declared
-     * private and final to encourage compiler inlining.
-     *
-     * @param responseString the response string sent to the client
-     */
-    private final void logResponseString(String responseString) {
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Sent: " + responseString);
-        }
-    }
-
-    /**
-     * Write and flush a response string.  The response is also logged.
-     * Should be used for the last line of a multi-line response or
-     * for a single line response.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedFlushedResponse(String responseString) {
-        writer.println(responseString);
-        writer.flush();
-        logResponseString(responseString);
-    }
-
-    /**
-     * Write a response string.  The response is also logged. 
-     * Used for multi-line responses.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedResponse(String responseString) {
-        writer.println(responseString);
-        logResponseString(responseString);
-    }
-
-    /**
-     * A private inner class which serves as an adaptor
-     * between the WatchdogTarget interface and this
-     * handler class.
-     */
-    private class NNTPWatchdogTarget
-        implements WatchdogTarget {
-
-        /**
-         * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
-         */
-        public void execute() {
-            NNTPHandler.this.idleClose();
-        }
-
-    }
 }

Modified: james/server/trunk/src/java/org/apache/james/nntpserver/NNTPServer.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/nntpserver/NNTPServer.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/nntpserver/NNTPServer.java (original)
+++ james/server/trunk/src/java/org/apache/james/nntpserver/NNTPServer.java Sat May  6 10:09:57 2006
@@ -17,9 +17,7 @@
 
 package org.apache.james.nntpserver;
 
-import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
 import org.apache.avalon.excalibur.pool.ObjectFactory;
-import org.apache.avalon.excalibur.pool.Poolable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.service.ServiceException;
@@ -27,7 +25,6 @@
 import org.apache.james.core.AbstractJamesService;
 import org.apache.james.nntpserver.repository.NNTPRepository;
 import org.apache.james.services.UsersRepository;
-import org.apache.james.util.watchdog.Watchdog;
 
 /**
  * NNTP Server
@@ -104,30 +101,6 @@
     }
 
     /**
-     * @see org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory#newHandler()
-     */
-    protected ConnectionHandler newHandler()
-            throws Exception {
-        NNTPHandler theHandler = (NNTPHandler)theHandlerPool.get();
-
-        Watchdog theWatchdog = theWatchdogFactory.getWatchdog(theHandler.getWatchdogTarget());
-
-        theHandler.setConfigurationData(theConfigData);
-        theHandler.setWatchdog(theWatchdog);
-        return theHandler;
-    }
-
-    /**
-     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory#releaseConnectionHandler(ConnectionHandler)
-     */
-    public void releaseConnectionHandler( ConnectionHandler connectionHandler ) {
-        if (!(connectionHandler instanceof NNTPHandler)) {
-            throw new IllegalArgumentException("Attempted to return non-NNTPHandler to pool.");
-        }
-        theHandlerPool.put((Poolable)connectionHandler);
-    }
-
-    /**
      * The factory for producing handlers.
      */
     private static class NNTPHandlerFactory
@@ -189,5 +162,12 @@
             return NNTPServer.this.repo;
         }
 
+    }
+
+    /**
+     * @see org.apache.james.core.AbstractJamesService#getConfigurationData()
+     */
+    protected Object getConfigurationData() {
+        return theConfigData;
     }
 }

Modified: james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java (original)
+++ james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java Sat May  6 10:09:57 2006
@@ -17,20 +17,16 @@
 
 package org.apache.james.pop3server;
 
-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.commons.collections.ListUtils;
 import org.apache.james.Constants;
+import org.apache.james.core.AbstractJamesHandler;
 import org.apache.james.core.MailImpl;
 import org.apache.james.services.MailRepository;
 import org.apache.james.util.CRLFTerminatedReader;
 import org.apache.james.util.ExtraDotOutputStream;
 import org.apache.james.util.InternetPrintWriter;
 import org.apache.james.util.watchdog.BytesWrittenResetOutputStream;
-import org.apache.james.util.watchdog.Watchdog;
-import org.apache.james.util.watchdog.WatchdogTarget;
 import org.apache.mailet.Mail;
 
 import javax.mail.MessagingException;
@@ -42,7 +38,6 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.io.PrintWriter;
 import java.net.Socket;
 import java.util.ArrayList;
 import java.util.Enumeration;
@@ -56,8 +51,7 @@
  *
  */
 public class POP3Handler
-    extends AbstractLogEnabled
-    implements ConnectionHandler, Poolable {
+    extends AbstractJamesHandler {
 
     // POP3 Server identification string used in POP3 headers
     private static final String softwaretype        = "JAMES POP3 Server "
@@ -102,27 +96,11 @@
     private MailRepository userInbox;
 
     /**
-     * The thread executing this handler
-     */
-    private Thread handlerThread;
-
-    /**
-     * The TCP/IP socket over which the POP3 interaction
-     * is occurring
-     */
-    private Socket socket;
-
-    /**
      * The reader associated with incoming characters.
      */
     private CRLFTerminatedReader in;
 
     /**
-     * The writer to which outgoing messages are written.
-     */
-    private PrintWriter out;
-
-    /**
      * The socket's output stream
      */
     private OutputStream outs;
@@ -149,70 +127,18 @@
                                                  // of the transaction
 
     /**
-     * The watchdog being used by this handler to deal with idle timeouts.
-     */
-    private Watchdog theWatchdog;
-
-    /**
-     * The watchdog target that idles out this handler.
-     */
-    private WatchdogTarget theWatchdogTarget = new POP3WatchdogTarget();
-
-    /**
      * Set the configuration data for the handler.
      *
      * @param theData the configuration data
      */
-    void setConfigurationData(POP3HandlerConfigurationData theData) {
-        theConfigData = theData;
-    }
-
-    /**
-     * Set the Watchdog for use by this handler.
-     *
-     * @param theWatchdog the watchdog
-     */
-    void setWatchdog(Watchdog theWatchdog) {
-        this.theWatchdog = theWatchdog;
-    }
-
-    /**
-     * Gets the Watchdog Target that should be used by Watchdogs managing
-     * this connection.
-     *
-     * @return the WatchdogTarget
-     */
-    WatchdogTarget getWatchdogTarget() {
-        return theWatchdogTarget;
-    }
-
-    /**
-     * Idle out this connection
-     */
-    void idleClose() {
-        if (getLogger() != null) {
-            getLogger().error("POP3 Connection has idled out.");
-        }
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (Exception e) {
-            // ignored
-        } finally {
-            socket = null;
-        }
-
-        synchronized (this) {
-            // Interrupt the thread to recover from internal hangs
-            if (handlerThread != null) {
-                handlerThread.interrupt();
-                handlerThread = null;
-            }
+    public void setConfigurationData(Object theData) {
+        if (theData instanceof POP3HandlerConfigurationData) {
+            theConfigData = (POP3HandlerConfigurationData) theData;
+        } else {
+            throw new IllegalArgumentException("Configuration object does not implement POP3HandlerConfigurationData");
         }
-
     }
-
+    
     /**
      * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
      */
@@ -270,6 +196,7 @@
                         .append(POP3Handler.softwaretype)
                         .append(") ready ");
             out.println(responseBuffer.toString());
+            out.flush();
 
             theWatchdog.start();
             while (parseCommand(readCommandLine())) {
@@ -1093,61 +1020,5 @@
     private void doUnknownCmd(String command,String argument,String argument1) {
         writeLoggedFlushedResponse(ERR_RESPONSE);
     }
-
-    /**
-     * This method logs at a "DEBUG" level the response string that
-     * was sent to the POP3 client.  The method is provided largely
-     * as syntactic sugar to neaten up the code base.  It is declared
-     * private and final to encourage compiler inlining.
-     *
-     * @param responseString the response string sent to the client
-     */
-    private final void logResponseString(String responseString) {
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Sent: " + responseString);
-        }
-    }
-
-    /**
-     * Write and flush a response string.  The response is also logged.
-     * Should be used for the last line of a multi-line response or
-     * for a single line response.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedFlushedResponse(String responseString) {
-        out.println(responseString);
-        out.flush();
-        logResponseString(responseString);
-    }
-
-    /**
-     * Write a response string.  The response is also logged.
-     * Used for multi-line responses.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedResponse(String responseString) {
-        out.println(responseString);
-        logResponseString(responseString);
-    }
-
-    /**
-     * A private inner class which serves as an adaptor
-     * between the WatchdogTarget interface and this
-     * handler class.
-     */
-    private class POP3WatchdogTarget
-        implements WatchdogTarget {
-
-        /**
-         * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
-         */
-        public void execute() {
-            POP3Handler.this.idleClose();
-        }
-
-    }
-
 }
 

Modified: james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java (original)
+++ james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java Sat May  6 10:09:57 2006
@@ -17,9 +17,7 @@
 
 package org.apache.james.pop3server;
 
-import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
 import org.apache.avalon.excalibur.pool.ObjectFactory;
-import org.apache.avalon.excalibur.pool.Poolable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.service.ServiceException;
@@ -27,7 +25,6 @@
 import org.apache.james.core.AbstractJamesService;
 import org.apache.james.services.MailServer;
 import org.apache.james.services.UsersRepository;
-import org.apache.james.util.watchdog.Watchdog;
 
 /**
  * <p>Accepts POP3 connections on a server socket and dispatches them to POP3Handlers.</p>
@@ -101,32 +98,6 @@
     }
 
     /**
-     * @see org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory#newHandler()
-     */
-    protected ConnectionHandler newHandler()
-            throws Exception {
-        POP3Handler theHandler = (POP3Handler)theHandlerPool.get();
-
-        Watchdog theWatchdog = theWatchdogFactory.getWatchdog(theHandler.getWatchdogTarget());
-
-        theHandler.setConfigurationData(theConfigData);
-
-        theHandler.setWatchdog(theWatchdog);
-
-        return theHandler;
-    }
-
-    /**
-     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory#releaseConnectionHandler(ConnectionHandler)
-     */
-    public void releaseConnectionHandler( ConnectionHandler connectionHandler ) {
-        if (!(connectionHandler instanceof POP3Handler)) {
-            throw new IllegalArgumentException("Attempted to return non-POP3Handler to pool.");
-        }
-        theHandlerPool.put((Poolable)connectionHandler);
-    }
-
-    /**
      * The factory for producing handlers.
      */
     private static class POP3HandlerFactory
@@ -187,5 +158,12 @@
         public UsersRepository getUsersRepository() {
             return POP3Server.this.users;
         }
+    }
+
+    /**
+     * @see org.apache.james.core.AbstractJamesService#getConfigurationData()
+     */
+    protected Object getConfigurationData() {
+        return theConfigData;
     }
 }

Modified: james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManager.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManager.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManager.java (original)
+++ james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManager.java Sat May  6 10:09:57 2006
@@ -17,19 +17,15 @@
 
 package org.apache.james.remotemanager;
 
-import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
 import org.apache.avalon.excalibur.pool.ObjectFactory;
-import org.apache.avalon.excalibur.pool.Poolable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.james.core.AbstractJamesService;
 import org.apache.james.services.MailServer;
 import org.apache.james.services.UsersRepository;
 import org.apache.james.services.UsersStore;
-import org.apache.james.util.watchdog.Watchdog;
 
 import java.util.HashMap;
 
@@ -129,31 +125,6 @@
     }
 
     /**
-     * @see org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory#newHandler()
-     */
-    protected ConnectionHandler newHandler()
-            throws Exception {
-        RemoteManagerHandler theHandler = (RemoteManagerHandler)theHandlerPool.get();
-        ContainerUtil.enableLogging(theHandler, getLogger());
-
-        Watchdog theWatchdog = theWatchdogFactory.getWatchdog(theHandler.getWatchdogTarget());
-
-        theHandler.setConfigurationData(theConfigData);
-        theHandler.setWatchdog(theWatchdog);
-        return theHandler;
-    }
-
-    /**
-     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory#releaseConnectionHandler(ConnectionHandler)
-     */
-    public void releaseConnectionHandler( ConnectionHandler connectionHandler ) {
-        if (!(connectionHandler instanceof RemoteManagerHandler)) {
-            throw new IllegalArgumentException("Attempted to return non-RemoteManagerHandler to pool.");
-        }
-        theHandlerPool.put((Poolable)connectionHandler);
-    }
-
-    /**
      * The factory for producing handlers.
      */
     private static class RemoteManagerHandlerFactory
@@ -229,5 +200,12 @@
             return RemoteManager.this.prompt;
         }
 
+    }
+
+    /**
+     * @see org.apache.james.core.AbstractJamesService#getConfigurationData()
+     */
+    protected Object getConfigurationData() {
+        return theConfigData;
     }
 }

Modified: james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java (original)
+++ james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java Sat May  6 10:09:57 2006
@@ -17,20 +17,17 @@
 
 package org.apache.james.remotemanager;
 
-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.james.Constants;
+import org.apache.james.core.AbstractJamesHandler;
 import org.apache.james.services.JamesUser;
 import org.apache.james.services.User;
 import org.apache.james.services.UsersRepository;
 import org.apache.james.userrepository.DefaultUser;
-import org.apache.james.util.watchdog.Watchdog;
-import org.apache.james.util.watchdog.WatchdogTarget;
 import org.apache.mailet.MailAddress;
 
 import javax.mail.internet.ParseException;
+
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.IOException;
@@ -51,8 +48,7 @@
  *
  */
 public class RemoteManagerHandler
-    extends AbstractLogEnabled
-    implements ConnectionHandler, Poolable {
+    extends AbstractJamesHandler {
 
     /**
      * The text string for the ADDUSER command
@@ -150,85 +146,18 @@
     private BufferedReader in;
 
     /**
-     * The writer to which outgoing messages are written.
-     */
-    private PrintWriter out;
-
-    /**
-     * The thread executing this handler
-     */
-    private Thread handlerThread;
-
-    /**
-     * The TCP/IP socket over which the RemoteManager interaction
-     * is occurring
-     */
-    private Socket socket;
-
-    /**
-     * The watchdog being used by this handler to deal with idle timeouts.
-     */
-    private Watchdog theWatchdog;
-
-    /**
-     * The watchdog target that idles out this handler.
-     */
-    private WatchdogTarget theWatchdogTarget = new RemoteManagerWatchdogTarget();
-
-    /**
      * Set the configuration data for the handler.
      *
      * @param theData the configuration data
      */
-    void setConfigurationData(RemoteManagerHandlerConfigurationData theData) {
-        theConfigData = theData;
-
-        // Reset the users repository to the default.
-        users = theConfigData.getUsersRepository();
-    }
-
-    /**
-     * Set the Watchdog for use by this handler.
-     *
-     * @param theWatchdog the watchdog
-     */
-    void setWatchdog(Watchdog theWatchdog) {
-        this.theWatchdog = theWatchdog;
-    }
-
-    /**
-     * Gets the Watchdog Target that should be used by Watchdogs managing
-     * this connection.
-     *
-     * @return the WatchdogTarget
-     */
-    WatchdogTarget getWatchdogTarget() {
-        return theWatchdogTarget;
-    }
-
-    /**
-     * Idle out this connection
-     */
-    void idleClose() {
-        if (getLogger() != null) {
-            getLogger().error("Remote Manager Connection has idled out.");
-        }
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (Exception e) {
-            // ignored
-        } finally {
-            socket = null;
-        }
-
-        synchronized (this) {
-            // Interrupt the thread to recover from internal hangs
-            if (handlerThread != null) {
-                handlerThread.interrupt();
-                handlerThread = null;
-            }
+    public void setConfigurationData(Object theData) {
+        if (theData instanceof RemoteManagerHandlerConfigurationData) {
+            theConfigData = (RemoteManagerHandlerConfigurationData) theData;
+    
+            // Reset the users repository to the default.
+            users = theConfigData.getUsersRepository();
+        } else {
+            throw new IllegalArgumentException("Configuration object does not implement RemoteManagerHandlerConfigurationData");
         }
     }
 
@@ -998,57 +927,4 @@
         return true;
     }
 
-    /**
-     * This method logs at a "DEBUG" level the response string that
-     * was sent to the RemoteManager client.  The method is provided largely
-     * as syntactic sugar to neaten up the code base.  It is declared
-     * private and final to encourage compiler inlining.
-     *
-     * @param responseString the response string sent to the client
-     */
-    private final void logResponseString(String responseString) {
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Sent: " + responseString);
-        }
-    }
-
-    /**
-     * Write and flush a response string.  The response is also logged.
-     * Should be used for the last line of a multi-line response or
-     * for a single line response.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedFlushedResponse(String responseString) {
-        out.println(responseString);
-        out.flush();
-        logResponseString(responseString);
-    }
-
-    /**
-     * Write a response string.  The response is also logged.
-     * Used for multi-line responses.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedResponse(String responseString) {
-        out.println(responseString);
-        logResponseString(responseString);
-    }
-
-    /**
-     * A private inner class which serves as an adaptor
-     * between the WatchdogTarget interface and this
-     * handler class.
-     */
-    private class RemoteManagerWatchdogTarget
-        implements WatchdogTarget {
-
-        /**
-         * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
-         */
-        public void execute() {
-            RemoteManagerHandler.this.idleClose();
-        }
-    }
 }

Modified: james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java (original)
+++ james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java Sat May  6 10:09:57 2006
@@ -17,15 +17,12 @@
 
 package org.apache.james.smtpserver;
 
-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.james.Constants;
+import org.apache.james.core.AbstractJamesHandler;
 import org.apache.james.util.CRLFTerminatedReader;
 import org.apache.james.util.InternetPrintWriter;
 import org.apache.james.util.watchdog.Watchdog;
-import org.apache.james.util.watchdog.WatchdogTarget;
 import org.apache.mailet.Mail;
 import org.apache.mailet.dates.RFC822DateFormat;
 
@@ -35,7 +32,6 @@
 import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
 import java.net.Socket;
 import java.net.SocketException;
 import java.util.ArrayList;
@@ -52,8 +48,8 @@
  * @version CVS $Revision$ $Date$
  */
 public class SMTPHandler
-    extends AbstractLogEnabled
-    implements ConnectionHandler, Poolable, SMTPSession {
+    extends AbstractJamesHandler
+    implements SMTPSession {
 
     /**
      * The constants to indicate the current processing mode of the session
@@ -111,27 +107,11 @@
     private boolean sessionEnded = false;
 
     /**
-     * The thread executing this handler
-     */
-    private Thread handlerThread;
-
-    /**
-     * The TCP/IP socket over which the SMTP
-     * dialogue is occurring.
-     */
-    private Socket socket;
-
-    /**
      * The incoming stream of bytes coming from the socket.
      */
     private InputStream in;
 
     /**
-     * The writer to which outgoing messages are written.
-     */
-    private PrintWriter out;
-
-    /**
      * A Reader wrapper for the incoming stream of bytes coming from the socket.
      */
     private CRLFTerminatedReader inReader;
@@ -191,16 +171,6 @@
     private HashMap state = new HashMap();
 
     /**
-     * The watchdog being used by this handler to deal with idle timeouts.
-     */
-    private Watchdog theWatchdog;
-
-    /**
-     * The watchdog target that idles out this handler.
-     */
-    private WatchdogTarget theWatchdogTarget = new SMTPWatchdogTarget();
-
-    /**
      * The per-handler response buffer used to marshal responses.
      */
     private StringBuffer responseBuffer = new StringBuffer(256);
@@ -210,52 +180,14 @@
      *
      * @param theData the per-service configuration data for this handler
      */
-    void setConfigurationData(SMTPHandlerConfigurationData theData) {
-        theConfigData = theData;
-    }
-
-    /**
-     * Set the Watchdog for use by this handler.
-     *
-     * @param theWatchdog the watchdog
-     */
-    void setWatchdog(Watchdog theWatchdog) {
-        this.theWatchdog = theWatchdog;
-    }
-
-    /**
-     * Gets the Watchdog Target that should be used by Watchdogs managing
-     * this connection.
-     *
-     * @return the WatchdogTarget
-     */
-    WatchdogTarget getWatchdogTarget() {
-        return theWatchdogTarget;
-    }
-
-    /**
-     * Idle out this connection
-     */
-    void idleClose() {
-        if (getLogger() != null) {
-            getLogger().error("SMTP Connection has idled out.");
-        }
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (Exception e) {
-            // ignored
-        }
-
-        synchronized (this) {
-            // Interrupt the thread to recover from internal hangs
-            if (handlerThread != null) {
-                handlerThread.interrupt();
-            }
+    public void setConfigurationData(Object theData) {
+        if (theData instanceof SMTPHandlerConfigurationData) {
+            theConfigData = (SMTPHandlerConfigurationData) theData;
+        } else {
+            throw new IllegalArgumentException("Configuration object does not implement SMTPHandlerConfigurationData");
         }
     }
-
+    
     /**
      * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
      */
@@ -512,62 +444,6 @@
             handlerThread = null;
         }
 
-    }
-
-
-    /**
-     * This method logs at a "DEBUG" level the response string that
-     * was sent to the SMTP client.  The method is provided largely
-     * as syntactic sugar to neaten up the code base.  It is declared
-     * private and final to encourage compiler inlining.
-     *
-     * @param responseString the response string sent to the client
-     */
-    private final void logResponseString(String responseString) {
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Sent: " + responseString);
-        }
-    }
-
-    /**
-     * Write and flush a response string.  The response is also logged.
-     * Should be used for the last line of a multi-line response or
-     * for a single line response.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedFlushedResponse(String responseString) {
-        out.println(responseString);
-        out.flush();
-        logResponseString(responseString);
-    }
-
-    /**
-     * Write a response string.  The response is also logged.
-     * Used for multi-line responses.
-     *
-     * @param responseString the response string sent to the client
-     */
-    final void writeLoggedResponse(String responseString) {
-        out.println(responseString);
-        logResponseString(responseString);
-    }
-
-
-    /**
-     * A private inner class which serves as an adaptor
-     * between the WatchdogTarget interface and this
-     * handler class.
-     */
-    private class SMTPWatchdogTarget
-        implements WatchdogTarget {
-
-        /**
-         * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
-         */
-        public void execute() {
-            SMTPHandler.this.idleClose();
-        }
     }
 
    /**

Modified: james/server/trunk/src/java/org/apache/james/smtpserver/SMTPServer.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/smtpserver/SMTPServer.java?rev=400340&r1=400339&r2=400340&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/smtpserver/SMTPServer.java (original)
+++ james/server/trunk/src/java/org/apache/james/smtpserver/SMTPServer.java Sat May  6 10:09:57 2006
@@ -19,7 +19,6 @@
 
 import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
 import org.apache.avalon.excalibur.pool.ObjectFactory;
-import org.apache.avalon.excalibur.pool.Poolable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.container.ContainerUtil;
@@ -30,7 +29,6 @@
 import org.apache.james.services.MailServer;
 import org.apache.james.services.UsersRepository;
 import org.apache.james.util.NetMatcher;
-import org.apache.james.util.watchdog.Watchdog;
 import org.apache.mailet.MailetContext;
 
 /**
@@ -246,16 +244,8 @@
      */
     protected ConnectionHandler newHandler()
             throws Exception {
-        SMTPHandler theHandler = (SMTPHandler)theHandlerPool.get();
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Getting SMTPHandler from pool.");
-        }
-        Watchdog theWatchdog = theWatchdogFactory.getWatchdog(theHandler.getWatchdogTarget());
-
-        theHandler.setConfigurationData(theConfigData);
-
-        theHandler.setWatchdog(theWatchdog);
+        
+        SMTPHandler theHandler = (SMTPHandler) super.newHandler();
 
         //pass the handler chain to every SMTPhandler
         theHandler.setHandlerChain(handlerChain);
@@ -264,19 +254,6 @@
     }
 
     /**
-     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory#releaseConnectionHandler(ConnectionHandler)
-     */
-    public void releaseConnectionHandler( ConnectionHandler connectionHandler ) {
-        if (!(connectionHandler instanceof SMTPHandler)) {
-            throw new IllegalArgumentException("Attempted to return non-SMTPHandler to pool.");
-        }
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Returning SMTPHandler to pool.");
-        }
-        theHandlerPool.put((Poolable)connectionHandler);
-    }
-
-    /**
      * The factory for producing handlers.
      */
     private static class SMTPHandlerFactory
@@ -389,5 +366,12 @@
             return SMTPServer.this.heloEhloEnforcement;
         }
 
+    }
+
+    /**
+     * @see org.apache.james.core.AbstractJamesService#getConfigurationData()
+     */
+    protected Object getConfigurationData() {
+        return theConfigData;
     }
 }



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