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/08 00:36:12 UTC

svn commit: r404864 - in /james/server/trunk/src/java/org/apache/james: core/AbstractJamesHandler.java nntpserver/NNTPHandler.java pop3server/POP3Handler.java remotemanager/RemoteManagerHandler.java smtpserver/SMTPHandler.java

Author: bago
Date: Sun May  7 15:36:08 2006
New Revision: 404864

URL: http://svn.apache.org/viewcvs?rev=404864&view=rev
Log:
Further generalization in protocol handling. Now the 4 specific protocol handler are Avalon free (all the avalon stuff is in the AbstractJamesHandler) and they share most of the low-level protocol code.
Please note that RemoteManagerHandler now uses the CRLFInputStreamReader so it now mandate a CRLF based communication.

Modified:
    james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java
    james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java
    james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java
    james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java
    james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java

Modified: 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=404864&r1=404863&r2=404864&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java (original)
+++ james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java Sun May  7 15:36:08 2006
@@ -19,12 +19,22 @@
 
 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.util.CRLFTerminatedReader;
+import org.apache.james.util.InternetPrintWriter;
 import org.apache.james.util.watchdog.Watchdog;
 import org.apache.james.util.watchdog.WatchdogTarget;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.net.Socket;
+import java.net.SocketException;
 
 /**
  * Common Handler code
@@ -49,6 +59,21 @@
     protected PrintWriter out;
     
     /**
+     * The incoming stream of bytes coming from the socket.
+     */
+    protected InputStream in;
+
+    /**
+     * The reader associated with incoming characters.
+     */
+    protected CRLFTerminatedReader inReader;
+
+    /**
+     * The socket's output stream
+     */
+    protected OutputStream outs;
+    
+    /**
      * The watchdog being used by this handler to deal with idle timeouts.
      */
     protected Watchdog theWatchdog;
@@ -58,8 +83,199 @@
      */
     private WatchdogTarget theWatchdogTarget = new JamesWatchdogTarget();
 
-
+    /**
+     * This method will be implemented checking for the correct class
+     * type.
+     * 
+     * @param theData Configuration Bean.
+     */
     public abstract void setConfigurationData(Object theData);
+    
+
+    /**
+     * The remote host name obtained by lookup on the socket.
+     */
+    protected String remoteHost = null;
+
+    /**
+     * The remote IP address of the socket.
+     */
+    protected String remoteIP = null;
+
+    /**
+     * Helper method for accepting connections.
+     * This MUST be called in the specializations.
+     */
+    protected void initHandler( Socket connection ) throws IOException {
+        this.socket = connection;
+        remoteIP = socket.getInetAddress().getHostAddress();
+        remoteHost = socket.getInetAddress().getHostName();
+        try {
+            synchronized (this) {
+                handlerThread = Thread.currentThread();
+            }
+            in = new BufferedInputStream(socket.getInputStream(), 1024);
+            // An ASCII encoding can be used because all transmissions other
+            // that those in the message body command are guaranteed
+            // to be ASCII
+            inReader = new CRLFTerminatedReader(in, "ASCII");
+            outs = new BufferedOutputStream(socket.getOutputStream(), 1024);
+            out = new InternetPrintWriter(outs, true);
+        } catch (RuntimeException e) {
+            StringBuffer exceptionBuffer = 
+                new StringBuffer(256)
+                    .append("Unexpected exception opening from ")
+                    .append(remoteHost)
+                    .append(" (")
+                    .append(remoteIP)
+                    .append("): ")
+                    .append(e.getMessage());
+            String exceptionString = exceptionBuffer.toString();
+            getLogger().error(exceptionString, e);
+            throw e;
+        } catch (IOException e) {
+            StringBuffer exceptionBuffer = 
+                new StringBuffer(256)
+                    .append("Cannot open connection from ")
+                    .append(remoteHost)
+                    .append(" (")
+                    .append(remoteIP)
+                    .append("): ")
+                    .append(e.getMessage());
+            String exceptionString = exceptionBuffer.toString();
+            getLogger().error(exceptionString, e);
+            throw e;
+        }
+        
+        if (getLogger().isInfoEnabled()) {
+            StringBuffer infoBuffer =
+                new StringBuffer(128)
+                        .append("Connection from ")
+                        .append(remoteHost)
+                        .append(" (")
+                        .append(remoteIP)
+                        .append(")");
+            getLogger().info(infoBuffer.toString());
+        }
+    }
+
+    /**
+     * The method clean up and close the allocated resources
+     */
+    private void cleanHandler() {
+        // Clear the Watchdog
+        if (theWatchdog != null) {
+            ContainerUtil.dispose(theWatchdog);
+            theWatchdog = null;
+        }
+
+        // Clear the streams
+        try {
+            if (inReader != null) {
+                inReader.close();
+            }
+        } catch (IOException ioe) {
+            getLogger().warn("Handler: Unexpected exception occurred while closing reader: " + ioe);
+        } finally {
+            inReader = null;
+        }
+
+        in = null;
+
+        if (out != null) {
+            out.close();
+            out = null;
+        }
+        outs = null;
+
+        try {
+            if (socket != null) {
+                socket.close();
+            }
+        } catch (IOException ioe) {
+            getLogger().warn("Handler: Unexpected exception occurred while closing socket: " + ioe);
+        } finally {
+            socket = null;
+        }
+        
+        remoteIP = null;
+        remoteHost = null;
+
+        synchronized (this) {
+            handlerThread = null;
+        }
+    }
+
+    /**
+     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(java.net.Socket)
+     */
+    public void handleConnection(Socket connection) throws IOException {
+        initHandler(connection);
+
+        try {
+            
+            // Do something:
+            handleProtocol();
+            
+            getLogger().debug("Closing socket.");
+        } catch (SocketException se) {
+            if (getLogger().isErrorEnabled()) {
+                StringBuffer errorBuffer =
+                    new StringBuffer(64)
+                        .append("Socket to ")
+                        .append(remoteHost)
+                        .append(" (")
+                        .append(remoteIP)
+                        .append(") closed remotely.");
+                getLogger().error(errorBuffer.toString(), se );
+            }
+        } catch ( InterruptedIOException iioe ) {
+            if (getLogger().isErrorEnabled()) {
+                StringBuffer errorBuffer =
+                    new StringBuffer(64)
+                        .append("Socket to ")
+                        .append(remoteHost)
+                        .append(" (")
+                        .append(remoteIP)
+                        .append(") timeout.");
+                getLogger().error( errorBuffer.toString(), iioe );
+            }
+        } catch ( IOException ioe ) {
+            if (getLogger().isErrorEnabled()) {
+                StringBuffer errorBuffer =
+                    new StringBuffer(256)
+                            .append("Exception handling socket to ")
+                            .append(remoteHost)
+                            .append(" (")
+                            .append(remoteIP)
+                            .append(") : ")
+                            .append(ioe.getMessage());
+                getLogger().error( errorBuffer.toString(), ioe );
+            }
+        } catch (RuntimeException e) {
+            errorHandler(e);
+        } finally {
+            //Clear all the session state variables
+            cleanHandler();
+            resetHandler();
+        }
+    }
+
+    /**
+     * @param e 
+     */
+    protected void errorHandler(RuntimeException e) {
+        if (getLogger().isErrorEnabled()) {
+            getLogger().error( "Unexpected runtime exception: "
+                               + e.getMessage(), e );
+        }
+    }
+
+
+    protected abstract void handleProtocol() throws IOException;
+
+
+    protected abstract void resetHandler();
 
 
     /**
@@ -163,6 +379,5 @@
         }
 
     }
-
 
 }

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=404864&r1=404863&r2=404864&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 Sun May  7 15:36:08 2006
@@ -17,7 +17,6 @@
 
 package org.apache.james.nntpserver;
 
-import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.james.core.AbstractJamesHandler;
 import org.apache.james.core.MailHeaders;
 import org.apache.james.nntpserver.repository.NNTPArticle;
@@ -25,23 +24,16 @@
 import org.apache.james.util.CharTerminatedInputStream;
 import org.apache.james.util.DotStuffingInputStream;
 import org.apache.james.util.ExtraDotOutputStream;
-import org.apache.james.util.InternetPrintWriter;
 import org.apache.mailet.dates.RFC2980DateFormat;
 import org.apache.mailet.dates.RFC977DateFormat;
 import org.apache.mailet.dates.SimplifiedDateFormat;
 
 import javax.mail.MessagingException;
 
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
 import java.io.SequenceInputStream;
-import java.net.Socket;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -222,31 +214,6 @@
     private final static char[] NNTPTerminator = { '\r', '\n', '.', '\r', '\n' };
 
     /**
-     * The remote host name obtained by lookup on the socket.
-     */
-    private String remoteHost;
-
-    /**
-     * The remote IP address of the socket.
-     */
-    private String remoteIP;
-
-    /**
-     * The incoming stream of bytes coming from the socket.
-     */
-    private InputStream in;
-
-    /**
-     * The reader associated with incoming characters.
-     */
-    private BufferedReader reader;
-
-    /**
-     * The socket's output stream
-     */
-    private OutputStream outs;
-
-    /**
      * The current newsgroup.
      */
     private NNTPGroup group;
@@ -292,123 +259,52 @@
     }
 
     /**
-     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
+     * @see org.apache.james.core.AbstractJamesHandler#handleProtocol()
      */
-    public void handleConnection( Socket connection ) throws IOException {
-        try {
-            this.socket = connection;
-            synchronized (this) {
-                handlerThread = Thread.currentThread();
-            }
-            remoteIP = socket.getInetAddress().getHostAddress();
-            remoteHost = socket.getInetAddress().getHostName();
-            in = new BufferedInputStream(socket.getInputStream(), 1024);
-            // An ASCII encoding can be used because all transmissions other
-            // that those in the message body command are guaranteed
-            // to be ASCII
-            reader = new BufferedReader(new InputStreamReader(in, "ASCII"), 512);
-            outs = new BufferedOutputStream(socket.getOutputStream(), 1024);
-            out = new InternetPrintWriter(outs, true);
-        } catch (Exception e) {
-            StringBuffer exceptionBuffer = 
-                new StringBuffer(256)
-                    .append("Cannot open connection from ")
-                    .append(remoteHost)
-                    .append(" (")
-                    .append(remoteIP)
-                    .append("): ")
-                    .append(e.getMessage());
-            String exceptionString = exceptionBuffer.toString();
-            getLogger().error(exceptionString, e );
+    protected void handleProtocol() throws IOException {
+        // section 7.1
+        if ( theConfigData.getNNTPRepository().isReadOnly() ) {
+            StringBuffer respBuffer =
+                new StringBuffer(128)
+                    .append("201 ")
+                    .append(theConfigData.getHelloName())
+                    .append(" NNTP Service Ready, posting prohibited");
+            writeLoggedFlushedResponse(respBuffer.toString());
+        } else {
+            StringBuffer respBuffer =
+                new StringBuffer(128)
+                        .append("200 ")
+                        .append(theConfigData.getHelloName())
+                        .append(" NNTP Service Ready, posting permitted");
+            writeLoggedFlushedResponse(respBuffer.toString());
         }
 
-        try {
-            // section 7.1
-            if ( theConfigData.getNNTPRepository().isReadOnly() ) {
-                StringBuffer respBuffer =
-                    new StringBuffer(128)
-                        .append("201 ")
-                        .append(theConfigData.getHelloName())
-                        .append(" NNTP Service Ready, posting prohibited");
-                writeLoggedFlushedResponse(respBuffer.toString());
-            } else {
-                StringBuffer respBuffer =
-                    new StringBuffer(128)
-                            .append("200 ")
-                            .append(theConfigData.getHelloName())
-                            .append(" NNTP Service Ready, posting permitted");
-                writeLoggedFlushedResponse(respBuffer.toString());
-            }
-
-            theWatchdog.start();
-            while (parseCommand(reader.readLine())) {
-                theWatchdog.reset();
-            }
-            theWatchdog.stop();
-
-            getLogger().info("Connection closed");
-        } catch (Exception e) {
-            // If the connection has been idled out, the
-            // socket will be closed and null.  Do NOT
-            // log the exception or attempt to send the
-            // closing connection message
-            if (socket != null) {
-                try {
-                    doQUIT(null);
-                } catch (Throwable t) {}
-                getLogger().error( "Exception during connection:" + e.getMessage(), e );
-            }
-        } finally {
-            resetHandler();
+        theWatchdog.start();
+        while (parseCommand(inReader.readLine())) {
+            theWatchdog.reset();
+        }
+        theWatchdog.stop();
+
+        getLogger().info("Connection closed");
+    }
+    
+    protected void errorHandler(RuntimeException e) {
+        super.errorHandler(e);
+        // If the connection has been idled out, the
+        // socket will be closed and null.  Do NOT
+        // log the exception or attempt to send the
+        // closing connection message
+        if (socket != null) {
+            try {
+                doQUIT(null);
+            } catch (Throwable t) {}
         }
     }
 
     /**
      * Resets the handler data to a basic state.
      */
-    private void resetHandler() {
-
-        // Clear the Watchdog
-        if (theWatchdog != null) {
-            ContainerUtil.dispose(theWatchdog);
-            theWatchdog = null;
-        }
-
-        // Clear the streams
-        try {
-            if (reader != null) {
-                reader.close();
-            }
-        } catch (IOException ioe) {
-            getLogger().warn("NNTPHandler: Unexpected exception occurred while closing reader: " + ioe);
-        } finally {
-            reader = null;
-        }
-
-        in = null;
-
-        if (out != null) {
-            out.close();
-            out = null;
-        }
-        outs = null;
-
-        remoteHost = null;
-        remoteIP = null;
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (IOException ioe) {
-            getLogger().warn("NNTPHandler: Unexpected exception occurred while closing socket: " + ioe);
-        } finally {
-            socket = null;
-        }
-
-        synchronized (this) {
-            handlerThread = null;
-        }
-
+    protected void resetHandler() {
         // Clear the selected group, article info
         group = null;
         currentArticleNumber = -1;

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=404864&r1=404863&r2=404864&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 Sun May  7 15:36:08 2006
@@ -17,7 +17,6 @@
 
 package org.apache.james.pop3server;
 
-import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.commons.collections.ListUtils;
 import org.apache.james.Constants;
 import org.apache.james.core.AbstractJamesHandler;
@@ -25,20 +24,16 @@
 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.mailet.Mail;
 
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.net.Socket;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -96,16 +91,6 @@
     private MailRepository userInbox;
 
     /**
-     * The reader associated with incoming characters.
-     */
-    private CRLFTerminatedReader in;
-
-    /**
-     * The socket's output stream
-     */
-    private OutputStream outs;
-
-    /**
      * The current transaction state of the handler
      */
     private int state;
@@ -140,155 +125,58 @@
     }
     
     /**
-     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
+     * @see org.apache.james.core.AbstractJamesHandler#handleProtocol()
      */
-    public void handleConnection( Socket connection )
-            throws IOException {
-
-        String remoteHost = "";
-        String remoteIP = "";
-
-        try {
-            this.socket = connection;
-            synchronized (this) {
-                handlerThread = Thread.currentThread();
-            }
-            // in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ASCII"), 512);
-            in = new CRLFTerminatedReader(new BufferedInputStream(socket.getInputStream(), 512), "ASCII");
-            remoteIP = socket.getInetAddress().getHostAddress ();
-            remoteHost = socket.getInetAddress().getHostName ();
-        } catch (Exception e) {
-            if (getLogger().isErrorEnabled()) {
-                StringBuffer exceptionBuffer =
-                    new StringBuffer(256)
-                            .append("Cannot open connection from ")
-                            .append(remoteHost)
-                            .append(" (")
-                            .append(remoteIP)
-                            .append("): ")
-                            .append(e.getMessage());
-                getLogger().error( exceptionBuffer.toString(), e );
-            }
+    protected void handleProtocol() throws IOException {
+        state = AUTHENTICATION_READY;
+        user = "unknown";
+        StringBuffer responseBuffer =
+            new StringBuffer(256)
+                    .append(OK_RESPONSE)
+                    .append(" ")
+                    .append(theConfigData.getHelloName())
+                    .append(" POP3 server (")
+                    .append(POP3Handler.softwaretype)
+                    .append(") ready ");
+        out.println(responseBuffer.toString());
+        out.flush();
+
+        theWatchdog.start();
+        while (parseCommand(readCommandLine())) {
+            theWatchdog.reset();
         }
-
+        theWatchdog.stop();
         if (getLogger().isInfoEnabled()) {
             StringBuffer logBuffer =
                 new StringBuffer(128)
-                        .append("Connection from ")
-                        .append(remoteHost)
-                        .append(" (")
-                        .append(remoteIP)
-                        .append(") ");
+                    .append("Connection for ")
+                    .append(user)
+                    .append(" from ")
+                    .append(remoteHost)
+                    .append(" (")
+                    .append(remoteIP)
+                    .append(") closed.");
             getLogger().info(logBuffer.toString());
         }
-
+    }
+    
+    /**
+     * @see org.apache.james.core.AbstractJamesHandler#errorHandler(java.lang.RuntimeException)
+     */
+    protected void errorHandler(RuntimeException e) {
+        super.errorHandler(e);
         try {
-            outs = new BufferedOutputStream(socket.getOutputStream(), 1024);
-            out = new InternetPrintWriter(outs, true);
-            state = AUTHENTICATION_READY;
-            user = "unknown";
-            StringBuffer responseBuffer =
-                new StringBuffer(256)
-                        .append(OK_RESPONSE)
-                        .append(" ")
-                        .append(theConfigData.getHelloName())
-                        .append(" POP3 server (")
-                        .append(POP3Handler.softwaretype)
-                        .append(") ready ");
-            out.println(responseBuffer.toString());
-            out.flush();
-
-            theWatchdog.start();
-            while (parseCommand(readCommandLine())) {
-                theWatchdog.reset();
-            }
-            theWatchdog.stop();
-            if (getLogger().isInfoEnabled()) {
-                StringBuffer logBuffer =
-                    new StringBuffer(128)
-                        .append("Connection for ")
-                        .append(user)
-                        .append(" from ")
-                        .append(remoteHost)
-                        .append(" (")
-                        .append(remoteIP)
-                        .append(") closed.");
-                getLogger().info(logBuffer.toString());
-            }
-        } catch (Exception e) {
             out.println(ERR_RESPONSE + " Error closing connection.");
             out.flush();
-            StringBuffer exceptionBuffer =
-                new StringBuffer(128)
-                        .append("Exception during connection from ")
-                        .append(remoteHost)
-                        .append(" (")
-                        .append(remoteIP)
-                        .append(") : ")
-                        .append(e.getMessage());
-            getLogger().error(exceptionBuffer.toString(), e );
-        } finally {
-            resetHandler();
+        } catch (Throwable t) {
+            
         }
     }
 
     /**
      * Resets the handler data to a basic state.
      */
-    private void resetHandler() {
-
-        if (theWatchdog != null) {
-            ContainerUtil.dispose(theWatchdog);
-            theWatchdog = null;
-        }
-
-        // Close and clear streams, sockets
-
-        try {
-            if (socket != null) {
-                socket.close();
-                socket = null;
-            }
-        } catch (IOException ioe) {
-            // Ignoring exception on close
-        } finally {
-            socket = null;
-        }
-
-        try {
-            if (in != null) {
-                in.close();
-            }
-        } catch (Exception e) {
-            // Ignored
-        } finally {
-            in = null;
-        }
-
-        try {
-            if (out != null) {
-                out.close();
-            }
-        } catch (Exception e) {
-            // Ignored
-        } finally {
-            out = null;
-        }
-
-        try {
-           if (outs != null) {
-               outs.close();
-            }
-        } catch (Exception e) {
-            // Ignored
-        } finally {
-            outs = null;
-        }
-
-        synchronized (this) {
-            handlerThread = null;
-        }
-
+    protected void resetHandler() {
         // Clear user data
         user = null;
         userInbox = null;
@@ -346,7 +234,7 @@
      */
     final String readCommandLine() throws IOException {
         for (;;) try {
-            String commandLine = in.readLine();
+            String commandLine = inReader.readLine();
             if (commandLine != null) {
                 commandLine = commandLine.trim();
             }
@@ -1020,5 +908,6 @@
     private void doUnknownCmd(String command,String argument,String argument1) {
         writeLoggedFlushedResponse(ERR_RESPONSE);
     }
+
 }
 

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=404864&r1=404863&r2=404864&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 Sun May  7 15:36:08 2006
@@ -17,7 +17,6 @@
 
 package org.apache.james.remotemanager;
 
-import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.james.Constants;
 import org.apache.james.core.AbstractJamesHandler;
 import org.apache.james.services.JamesUser;
@@ -28,12 +27,7 @@
 
 import javax.mail.internet.ParseException;
 
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
 import java.net.Socket;
 import java.util.Iterator;
 import java.util.Locale;
@@ -141,11 +135,6 @@
     private UsersRepository users;
 
     /**
-     * The reader associated with incoming commands.
-     */
-    private BufferedReader in;
-
-    /**
      * Set the configuration data for the handler.
      *
      * @param theData the configuration data
@@ -164,133 +153,86 @@
     /**
      * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
      */
-    public void handleConnection( final Socket connection )
-        throws IOException {
-
-        socket = connection;
-        String remoteIP = socket.getInetAddress().getHostAddress();
-        String remoteHost = socket.getInetAddress().getHostName();
-
-        synchronized (this) {
-            handlerThread = Thread.currentThread();
+    protected void handleProtocol() throws IOException {
+        writeLoggedResponse("JAMES Remote Administration Tool " + Constants.SOFTWARE_VERSION );
+        writeLoggedResponse("Please enter your login and password");
+        String login = null;
+        String password = null;
+        do {
+            if (login != null) {
+                final String message = "Login failed for " + login;
+                writeLoggedFlushedResponse(message);
+            }
+            writeLoggedFlushedResponse("Login id:");
+            login = inReader.readLine().trim();
+            writeLoggedFlushedResponse("Password:");
+            password = inReader.readLine().trim();
+        } while (!password.equals(theConfigData.getAdministrativeAccountData().get(login)) || password.length() == 0);
+
+        StringBuffer messageBuffer =
+            new StringBuffer(64)
+                    .append("Welcome ")
+                    .append(login)
+                    .append(". HELP for a list of commands");
+        out.println( messageBuffer.toString() );
+        out.flush();
+        if (getLogger().isInfoEnabled()) {
+            StringBuffer infoBuffer =
+                new StringBuffer(128)
+                        .append("Login for ")
+                        .append(login)
+                        .append(" successful");
+            getLogger().info(infoBuffer.toString());
         }
 
         try {
-            in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ASCII"), 512);
-            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()), 512), false);
-            if (getLogger().isInfoEnabled()) {
-                StringBuffer infoBuffer =
-                    new StringBuffer(128)
-                            .append("Access from ")
-                            .append(remoteHost)
-                            .append("(")
-                            .append(remoteIP)
-                            .append(")");
-                getLogger().info( infoBuffer.toString() );
-            }
-            writeLoggedResponse("JAMES Remote Administration Tool " + Constants.SOFTWARE_VERSION );
-            writeLoggedResponse("Please enter your login and password");
-            String login = null;
-            String password = null;
-            do {
-                if (login != null) {
-                    final String message = "Login failed for " + login;
-                    writeLoggedFlushedResponse(message);
-                }
-                writeLoggedFlushedResponse("Login id:");
-                login = in.readLine().trim();
-                writeLoggedFlushedResponse("Password:");
-                password = in.readLine().trim();
-            } while (!password.equals(theConfigData.getAdministrativeAccountData().get(login)) || password.length() == 0);
-
-            StringBuffer messageBuffer =
-                new StringBuffer(64)
-                        .append("Welcome ")
-                        .append(login)
-                        .append(". HELP for a list of commands");
-            out.println( messageBuffer.toString() );
+            out.print(theConfigData.getPrompt());
             out.flush();
-            if (getLogger().isInfoEnabled()) {
-                StringBuffer infoBuffer =
-                    new StringBuffer(128)
-                            .append("Login for ")
-                            .append(login)
-                            .append(" successful");
-                getLogger().info(infoBuffer.toString());
-            }
-
-            try {
+            theWatchdog.start();
+            while (parseCommand(inReader.readLine())) {
+                theWatchdog.reset();
                 out.print(theConfigData.getPrompt());
                 out.flush();
-                theWatchdog.start();
-                while (parseCommand(in.readLine())) {
-                    theWatchdog.reset();
-                    out.print(theConfigData.getPrompt());
-                    out.flush();
-                }
-                theWatchdog.stop();
-            } catch (IOException ioe) {
-                //We can cleanly ignore this as it's probably a socket timeout
-            } catch (Throwable thr) {
-                System.out.println("Exception: " + thr.getMessage());
-                getLogger().error("Encountered exception in handling the remote manager connection.", thr);
             }
-            StringBuffer infoBuffer =
-                new StringBuffer(64)
-                        .append("Logout for ")
-                        .append(login)
-                        .append(".");
-            getLogger().info(infoBuffer.toString());
+            theWatchdog.stop();
+        } catch (IOException ioe) {
+            //We can cleanly ignore this as it's probably a socket timeout
+        } catch (Throwable thr) {
+            System.out.println("Exception: " + thr.getMessage());
+            getLogger().error("Encountered exception in handling the remote manager connection.", thr);
+        }
+        StringBuffer infoBuffer =
+            new StringBuffer(64)
+                    .append("Logout for ")
+                    .append(login)
+                    .append(".");
+        getLogger().info(infoBuffer.toString());
 
-        } catch ( final IOException e ) {
-            out.println("Error. Closing connection");
-            out.flush();
-            if (getLogger().isErrorEnabled()) {
-                StringBuffer exceptionBuffer =
-                    new StringBuffer(128)
-                            .append("Exception during connection from ")
-                            .append(remoteHost)
-                            .append(" (")
-                            .append(remoteIP)
-                            .append("): ")
-                            .append(e.getMessage());
-                getLogger().error(exceptionBuffer.toString());
-            }
-        } finally {
-            resetHandler();
+    }
+    
+    /**
+     * @see org.apache.james.core.AbstractJamesHandler#errorHandler(java.lang.RuntimeException)
+     */
+    protected void errorHandler(RuntimeException e) {
+        out.println("Unexpected Error: "+e.getMessage());
+        out.flush();
+        if (getLogger().isErrorEnabled()) {
+            StringBuffer exceptionBuffer =
+                new StringBuffer(128)
+                        .append("Exception during connection from ")
+                        .append(remoteHost)
+                        .append(" (")
+                        .append(remoteIP)
+                        .append("): ")
+                        .append(e.getMessage());
+            getLogger().error(exceptionBuffer.toString(),e);
         }
     }
 
     /**
      * Resets the handler data to a basic state.
      */
-    private void resetHandler() {
-
-        // Clear the Watchdog
-        if (theWatchdog != null) {
-            ContainerUtil.dispose(theWatchdog);
-            theWatchdog = null;
-        }
-
-        in = null;
-        out = null;
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (IOException e) {
-            if (getLogger().isErrorEnabled()) {
-                getLogger().error("Exception closing socket: "
-                                  + e.getMessage());
-            }
-        } finally {
-            socket = null;
-        }
-
-        synchronized (this) {
-            handlerThread = null;
-        }
-
+    protected void resetHandler() {
         // Reset user repository
         users = theConfigData.getUsersRepository();
 

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=404864&r1=404863&r2=404864&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 Sun May  7 15:36:08 2006
@@ -21,19 +21,12 @@
 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.mailet.Mail;
 import org.apache.mailet.dates.RFC822DateFormat;
 
-import java.io.BufferedInputStream;
-import java.io.BufferedWriter;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStreamWriter;
-import java.net.Socket;
-import java.net.SocketException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
@@ -107,26 +100,6 @@
     private boolean sessionEnded = false;
 
     /**
-     * The incoming stream of bytes coming from the socket.
-     */
-    private InputStream in;
-
-    /**
-     * A Reader wrapper for the incoming stream of bytes coming from the socket.
-     */
-    private CRLFTerminatedReader inReader;
-
-    /**
-     * The remote host name obtained by lookup on the socket.
-     */
-    private String remoteHost;
-
-    /**
-     * The remote IP address of the socket.
-     */
-    private String remoteIP;
-
-    /**
      * The user name of the authenticated user associated with this SMTP transaction.
      */
     private String authenticatedUser;
@@ -189,261 +162,151 @@
     }
     
     /**
-     * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
+     * @see org.apache.james.core.AbstractJamesHandler#handleProtocol()
      */
-    public void handleConnection(Socket connection) throws IOException {
-
-        try {
-            this.socket = connection;
-            synchronized (this) {
-                handlerThread = Thread.currentThread();
-            }
-            in = new BufferedInputStream(socket.getInputStream(), 1024);
-            // An ASCII encoding can be used because all transmissions other
-            // that those in the DATA command are guaranteed
-            // to be ASCII
-            // inReader = new BufferedReader(new InputStreamReader(in, "ASCII"), 512);
-            inReader = new CRLFTerminatedReader(in, "ASCII");
-            remoteIP = socket.getInetAddress().getHostAddress();
-            remoteHost = socket.getInetAddress().getHostName();
-            smtpID = random.nextInt(1024) + "";
-            relayingAllowed = theConfigData.isRelayingAllowed(remoteIP);
-            authRequired = theConfigData.isAuthRequired(remoteIP);
-            heloEhloEnforcement = theConfigData.useHeloEhloEnforcement();
-            sessionEnded = false;
-            resetState();
-        } catch (Exception e) {
-            StringBuffer exceptionBuffer =
-                new StringBuffer(256)
-                    .append("Cannot open connection from ")
-                    .append(remoteHost)
-                    .append(" (")
-                    .append(remoteIP)
-                    .append("): ")
-                    .append(e.getMessage());
-            String exceptionString = exceptionBuffer.toString();
-            getLogger().error(exceptionString, e );
-            throw new RuntimeException(exceptionString);
-        }
-
-        if (getLogger().isInfoEnabled()) {
-            StringBuffer infoBuffer =
-                new StringBuffer(128)
-                        .append("Connection from ")
-                        .append(remoteHost)
-                        .append(" (")
-                        .append(remoteIP)
-                        .append(")");
-            getLogger().info(infoBuffer.toString());
-        }
-
-        try {
-
-            out = new InternetPrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()), 1024), false);
+    protected void handleProtocol() throws IOException {
+        smtpID = random.nextInt(1024) + "";
+        relayingAllowed = theConfigData.isRelayingAllowed(remoteIP);
+        authRequired = theConfigData.isAuthRequired(remoteIP);
+        heloEhloEnforcement = theConfigData.useHeloEhloEnforcement();
+        sessionEnded = false;
+        resetState();
 
-            // Initially greet the connector
-            // Format is:  Sat, 24 Jan 1998 13:16:09 -0500
+        // Initially greet the connector
+        // Format is:  Sat, 24 Jan 1998 13:16:09 -0500
 
-            responseBuffer.append("220 ")
-                          .append(theConfigData.getHelloName())
-                          .append(" SMTP Server (")
-                          .append(SOFTWARE_TYPE)
-                          .append(") ready ")
-                          .append(rfc822DateFormat.format(new Date()));
-            String responseString = clearResponseBuffer();
-            writeLoggedFlushedResponse(responseString);
-
-            //the core in-protocol handling logic
-            //run all the connection handlers, if it fast fails, end the session
-            //parse the command command, look up for the list of command handlers
-            //Execute each of the command handlers. If any command handlers writes
-            //response then, End the subsequent command handler processing and
-            //start parsing new command. Once the message is received, run all
-            //the message handlers. The message handlers can either terminate
-            //message or terminate session
-
-            //At the beginning
-            //mode = command_mode
-            //once the commandHandler writes response, the mode is changed to RESPONSE_MODE.
-            //This will cause to skip the subsequent command handlers configured for that command.
-            //For instance:
-            //There are 2 commandhandlers MailAddressChecker and MailCmdHandler for
-            //MAIL command. If MailAddressChecker validation of the MAIL FROM
-            //address is successful, the MailCmdHandlers will be executed.
-            //Incase it fails, it has to write response. Once we write response
-            //there is no need to execute the MailCmdHandler.
-            //Next, Once MAIL message is received the DataCmdHandler and any other
-            //equivalent commandHandler will call setMail method. this will change
-            //he mode to MAIL_RECEIVED_MODE. This mode will trigger the message
-            //handlers to be execute. Message handlers can abort message. In that case,
-            //message will not spooled.
-
-            //Session started - RUN all connect handlers
-            List connectHandlers = handlerChain.getConnectHandlers();
-            if(connectHandlers != null) {
-                int count = connectHandlers.size();
-                for(int i = 0; i < count; i++) {
-                    ((ConnectHandler)connectHandlers.get(i)).onConnect(this);
-                    if(sessionEnded) {
-                        break;
-                    }
+        responseBuffer.append("220 ")
+                      .append(theConfigData.getHelloName())
+                      .append(" SMTP Server (")
+                      .append(SOFTWARE_TYPE)
+                      .append(") ready ")
+                      .append(rfc822DateFormat.format(new Date()));
+        String responseString = clearResponseBuffer();
+        writeLoggedFlushedResponse(responseString);
+
+        //the core in-protocol handling logic
+        //run all the connection handlers, if it fast fails, end the session
+        //parse the command command, look up for the list of command handlers
+        //Execute each of the command handlers. If any command handlers writes
+        //response then, End the subsequent command handler processing and
+        //start parsing new command. Once the message is received, run all
+        //the message handlers. The message handlers can either terminate
+        //message or terminate session
+
+        //At the beginning
+        //mode = command_mode
+        //once the commandHandler writes response, the mode is changed to RESPONSE_MODE.
+        //This will cause to skip the subsequent command handlers configured for that command.
+        //For instance:
+        //There are 2 commandhandlers MailAddressChecker and MailCmdHandler for
+        //MAIL command. If MailAddressChecker validation of the MAIL FROM
+        //address is successful, the MailCmdHandlers will be executed.
+        //Incase it fails, it has to write response. Once we write response
+        //there is no need to execute the MailCmdHandler.
+        //Next, Once MAIL message is received the DataCmdHandler and any other
+        //equivalent commandHandler will call setMail method. this will change
+        //he mode to MAIL_RECEIVED_MODE. This mode will trigger the message
+        //handlers to be execute. Message handlers can abort message. In that case,
+        //message will not spooled.
+
+        //Session started - RUN all connect handlers
+        List connectHandlers = handlerChain.getConnectHandlers();
+        if(connectHandlers != null) {
+            int count = connectHandlers.size();
+            for(int i = 0; i < count; i++) {
+                ((ConnectHandler)connectHandlers.get(i)).onConnect(this);
+                if(sessionEnded) {
+                    break;
                 }
             }
+        }
 
-            theWatchdog.start();
-            while(!sessionEnded) {
-              //Reset the current command values
-              curCommandName = null;
-              curCommandArgument = null;
-              mode = COMMAND_MODE;
-
-              //parse the command
-              String cmdString =  readCommandLine();
-              if (cmdString == null) {
-                  break;
-              }
-              int spaceIndex = cmdString.indexOf(" ");
-              if (spaceIndex > 0) {
-                  curCommandName = cmdString.substring(0, spaceIndex);
-                  curCommandArgument = cmdString.substring(spaceIndex + 1);
-              } else {
-                  curCommandName = cmdString;
-              }
-              curCommandName = curCommandName.toUpperCase(Locale.US);
-
-              //fetch the command handlers registered to the command
-              List commandHandlers = handlerChain.getCommandHandlers(curCommandName);
-              if(commandHandlers == null) {
-                  //end the session
-                  break;
-              } else {
-                  int count = commandHandlers.size();
-                  for(int i = 0; i < count; i++) {
-                      ((CommandHandler)commandHandlers.get(i)).onCommand(this);
-                      theWatchdog.reset();
-                      //if the response is received, stop processing of command handlers
-                      if(mode != COMMAND_MODE) {
-                          break;
-                      }
+        theWatchdog.start();
+        while(!sessionEnded) {
+          //Reset the current command values
+          curCommandName = null;
+          curCommandArgument = null;
+          mode = COMMAND_MODE;
+
+          //parse the command
+          String cmdString =  readCommandLine();
+          if (cmdString == null) {
+              break;
+          }
+          int spaceIndex = cmdString.indexOf(" ");
+          if (spaceIndex > 0) {
+              curCommandName = cmdString.substring(0, spaceIndex);
+              curCommandArgument = cmdString.substring(spaceIndex + 1);
+          } else {
+              curCommandName = cmdString;
+          }
+          curCommandName = curCommandName.toUpperCase(Locale.US);
+
+          //fetch the command handlers registered to the command
+          List commandHandlers = handlerChain.getCommandHandlers(curCommandName);
+          if(commandHandlers == null) {
+              //end the session
+              break;
+          } else {
+              int count = commandHandlers.size();
+              for(int i = 0; i < count; i++) {
+                  ((CommandHandler)commandHandlers.get(i)).onCommand(this);
+                  theWatchdog.reset();
+                  //if the response is received, stop processing of command handlers
+                  if(mode != COMMAND_MODE) {
+                      break;
                   }
-
               }
 
-              //handle messages
-              if(mode == MESSAGE_RECEIVED_MODE) {
-                  getLogger().info("executing message handlers");
-                  List messageHandlers = handlerChain.getMessageHandlers();
-                  int count = messageHandlers.size();
-                  for(int i =0; i < count; i++) {
-                      ((MessageHandler)messageHandlers.get(i)).onMessage(this);
-                      //if the response is received, stop processing of command handlers
-                      if(mode == MESSAGE_ABORT_MODE) {
-                          break;
-                      }
+          }
+
+          //handle messages
+          if(mode == MESSAGE_RECEIVED_MODE) {
+              getLogger().info("executing message handlers");
+              List messageHandlers = handlerChain.getMessageHandlers();
+              int count = messageHandlers.size();
+              for(int i =0; i < count; i++) {
+                  ((MessageHandler)messageHandlers.get(i)).onMessage(this);
+                  //if the response is received, stop processing of command handlers
+                  if(mode == MESSAGE_ABORT_MODE) {
+                      break;
                   }
               }
+          }
 
-              //do the clean up
-              if(mail != null) {
-                  ContainerUtil.dispose(mail);
-                  
-                  // remember the ehlo mode
-                  Object currentHeloMode = state.get(CURRENT_HELO_MODE);
-                  
-                  mail = null;
-                  resetState();
-
-                  // start again with the old helo mode
-                  if (currentHeloMode != null) {
-                      state.put(CURRENT_HELO_MODE,currentHeloMode);
-                  }
+          //do the clean up
+          if(mail != null) {
+              ContainerUtil.dispose(mail);
+              
+              // remember the ehlo mode
+              Object currentHeloMode = state.get(CURRENT_HELO_MODE);
+              
+              mail = null;
+              resetState();
+
+              // start again with the old helo mode
+              if (currentHeloMode != null) {
+                  state.put(CURRENT_HELO_MODE,currentHeloMode);
               }
+          }
 
-            }
-            theWatchdog.stop();
-            getLogger().debug("Closing socket.");
-        } catch (SocketException se) {
-            if (getLogger().isErrorEnabled()) {
-                StringBuffer errorBuffer =
-                    new StringBuffer(64)
-                        .append("Socket to ")
-                        .append(remoteHost)
-                        .append(" (")
-                        .append(remoteIP)
-                        .append(") closed remotely.");
-                getLogger().error(errorBuffer.toString(), se );
-            }
-        } catch ( InterruptedIOException iioe ) {
-            if (getLogger().isErrorEnabled()) {
-                StringBuffer errorBuffer =
-                    new StringBuffer(64)
-                        .append("Socket to ")
-                        .append(remoteHost)
-                        .append(" (")
-                        .append(remoteIP)
-                        .append(") timeout.");
-                getLogger().error( errorBuffer.toString(), iioe );
-            }
-        } catch ( IOException ioe ) {
-            if (getLogger().isErrorEnabled()) {
-                StringBuffer errorBuffer =
-                    new StringBuffer(256)
-                            .append("Exception handling socket to ")
-                            .append(remoteHost)
-                            .append(" (")
-                            .append(remoteIP)
-                            .append(") : ")
-                            .append(ioe.getMessage());
-                getLogger().error( errorBuffer.toString(), ioe );
-            }
-        } catch (Exception e) {
-            if (getLogger().isErrorEnabled()) {
-                getLogger().error( "Exception opening socket: "
-                                   + e.getMessage(), e );
-            }
-        } finally {
-            //Clear all the session state variables
-            resetHandler();
         }
+        theWatchdog.stop();
+        getLogger().debug("Closing socket.");
     }
 
     /**
      * Resets the handler data to a basic state.
      */
-    private void resetHandler() {
+    protected void resetHandler() {
         resetState();
 
         clearResponseBuffer();
-        in = null;
-        inReader = null;
-        out = null;
+
         remoteHost = null;
         remoteIP = null;
         authenticatedUser = null;
         smtpID = null;
-
-        if (theWatchdog != null) {
-            ContainerUtil.dispose(theWatchdog);
-            theWatchdog = null;
-        }
-
-        try {
-            if (socket != null) {
-                socket.close();
-            }
-        } catch (IOException e) {
-            if (getLogger().isErrorEnabled()) {
-                getLogger().error("Exception closing socket: "
-                                  + e.getMessage());
-            }
-        } finally {
-            socket = null;
-        }
-
-        synchronized (this) {
-            handlerThread = null;
-        }
-
     }
 
    /**



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


James Handlers refactoring (Was: svn commit: r404864)

Posted by Stefano Bagnara <ap...@bago.org>.
I committed this as a work-in-progress proposal.

I'm happy with the result, so far, but it comes with a drawback.

In order to put most code in commons I had to change the "reader" used 
by the RemoteManager from a BufferedReader to a CRLFTerminatedReader.

Imho this is not a big issue and most "telnet based" protocol enforce 
this rule, but this introduce a small backward incompatibility issue.

The next step would be to separate commands in CmdHandler for 
NNTP/RemoteManager and POP3 like we did for SMPTServer.

This would be a better structure to start adding new remoteManager 
commands Norman already submitted to JIRA.

Please review the changes in *Handler and *Server and tell me what you 
think.

Stefano

PS: Overall the refactoring on the Handler stuff reduced the source size 
of James of 20K and remove a lot of duplicate code.

bago@apache.org wrote:
> Author: bago
> Date: Sun May  7 15:36:08 2006
> New Revision: 404864
> 
> URL: http://svn.apache.org/viewcvs?rev=404864&view=rev
> Log:
> Further generalization in protocol handling. Now the 4 specific protocol handler are Avalon free (all the avalon stuff is in the AbstractJamesHandler) and they share most of the low-level protocol code.
> Please note that RemoteManagerHandler now uses the CRLFInputStreamReader so it now mandate a CRLF based communication.
> 
> Modified:
>     james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java
>     james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java
>     james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java
>     james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java
>     james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java


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


Re: James Handlers refactoring (Was: svn commit: r404864)

Posted by Norman Maurer <nm...@byteaction.de>.
Am Montag, den 08.05.2006, 00:54 +0200 schrieb Stefano Bagnara:
> I committed this as a work-in-progress proposal.
> 
> I'm happy with the result, so far, but it comes with a drawback.
> 
> In order to put most code in commons I had to change the "reader" used 
> by the RemoteManager from a BufferedReader to a CRLFTerminatedReader.
> 
> Imho this is not a big issue and most "telnet based" protocol enforce 
> this rule, but this introduce a small backward incompatibility issue.
> 
> The next step would be to separate commands in CmdHandler for 
> NNTP/RemoteManager and POP3 like we did for SMPTServer.

That whould be a nice refactoring .. So it will be much easier to add
new commands without touch the "core". What about make SMTPHandler
execute more then one CmdHandler ber command ? What was the last state
for that ?

> 
> This would be a better structure to start adding new remoteManager 
> commands Norman already submitted to JIRA.
> 
Right.. I also have some new features here. But i want to wait until i
know if the refactoring will be made..

> Please review the changes in *Handler and *Server and tell me what you 
> think.
> 
After a quick review i think its a good choice  to remove ushc duplicate
code and but it in seperate classes..

> Stefano
> 
> PS: Overall the refactoring on the Handler stuff reduced the source size 
> of James of 20K and remove a lot of duplicate code.
> 
> bago@apache.org wrote:
> > Author: bago
> > Date: Sun May  7 15:36:08 2006
> > New Revision: 404864
> > 
> > URL: http://svn.apache.org/viewcvs?rev=404864&view=rev
> > Log:
> > Further generalization in protocol handling. Now the 4 specific protocol handler are Avalon free (all the avalon stuff is in the AbstractJamesHandler) and they share most of the low-level protocol code.
> > Please note that RemoteManagerHandler now uses the CRLFInputStreamReader so it now mandate a CRLF based communication.
> > 
> > Modified:
> >     james/server/trunk/src/java/org/apache/james/core/AbstractJamesHandler.java
> >     james/server/trunk/src/java/org/apache/james/nntpserver/NNTPHandler.java
> >     james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java
> >     james/server/trunk/src/java/org/apache/james/remotemanager/RemoteManagerHandler.java
> >     james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
> For additional commands, e-mail: server-dev-help@james.apache.org

bye
Norman