You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2011/11/18 11:00:52 UTC

svn commit: r1203562 [2/2] - in /james/protocols/trunk/pop3: .settings/ src/main/java/org/apache/james/protocols/pop3/ src/main/java/org/apache/james/protocols/pop3/core/ src/main/java/org/apache/james/protocols/pop3/pop3server/ src/main/java/org/apach...

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/QuitCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,99 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.annotation.Resource;
+import javax.mail.Flags;
+
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageRange;
+import org.apache.james.mailbox.MailboxException;
+import org.apache.james.pop3server.POP3Response;
+import org.apache.james.pop3server.POP3Session;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+
+/**
+ * Handles QUIT command
+ */
+public class QuitCmdHandler implements CommandHandler<POP3Session> {
+    private final static String COMMAND_NAME = "QUIT";
+    protected MailboxManager mailboxManager;
+
+    @Resource(name = "mailboxmanager")
+    public void setMailboxManager(MailboxManager manager) {
+        this.mailboxManager = manager;
+    }
+
+    /**
+     * Handler method called upon receipt of a QUIT command. This method handles
+     * cleanup of the POP3Handler state.
+     */
+    @SuppressWarnings("unchecked")
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response = null;
+        if (session.getHandlerState() == POP3Session.AUTHENTICATION_READY || session.getHandlerState() == POP3Session.AUTHENTICATION_USERSET) {
+            response = new POP3Response(POP3Response.OK_RESPONSE, "Apache James POP3 Server signing off.");
+            response.setEndSession(true);
+            return response;
+        }
+        MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION);
+
+        List<Long> toBeRemoved = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST);
+        try {
+            MessageManager mailbox = session.getUserMailbox();
+
+            for (int i = 0; i < toBeRemoved.size(); i++) {
+                MessageRange range = MessageRange.one(toBeRemoved.get(i));
+                mailbox.setFlags(new Flags(Flags.Flag.DELETED), true, false, range, mailboxSession);
+                mailbox.expunge(range, mailboxSession);
+            }
+            response = new POP3Response(POP3Response.OK_RESPONSE, "Apache James POP3 Server signing off.");
+        } catch (Exception ex) {
+            response = new POP3Response(POP3Response.ERR_RESPONSE, "Some deleted messages were not removed");
+            session.getLogger().error("Some deleted messages were not removed", ex);
+        }
+        response.setEndSession(true);
+        try {
+            mailboxManager.logout(mailboxSession, false);
+        } catch (MailboxException e) {
+            // nothing todo on logout
+        }
+
+        return response;
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RetrCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,134 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.james.mailbox.Content;
+import org.apache.james.mailbox.MailboxException;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageRange;
+import org.apache.james.mailbox.MessageResult;
+import org.apache.james.mailbox.MessageResult.FetchGroup;
+import org.apache.james.pop3server.POP3Response;
+import org.apache.james.pop3server.POP3Session;
+import org.apache.james.pop3server.POP3StreamResponse;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+
+/**
+ * Handles RETR command
+ */
+public class RetrCmdHandler implements CommandHandler<POP3Session> {
+
+    private final static String COMMAND_NAME = "RETR";
+    private final static FetchGroup GROUP = new FetchGroup() {
+
+        @Override
+        public int content() {
+            return FULL_CONTENT;
+        }
+
+        @Override
+        public Set<PartContentDescriptor> getPartContentDescriptors() {
+            return null;
+        }
+        
+    };
+    /**
+     * Handler method called upon receipt of a RETR command. This command
+     * retrieves a particular mail message from the mailbox.
+     */
+    @SuppressWarnings("unchecked")
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response = null;
+        String parameters = request.getArgument();
+        if (session.getHandlerState() == POP3Session.TRANSACTION) {
+            int num = 0;
+            try {
+                num = Integer.parseInt(parameters.trim());
+            } catch (Exception e) {
+                response = new POP3Response(POP3Response.ERR_RESPONSE, "Usage: RETR [mail number]");
+                return response;
+            }
+            try {
+                List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST);
+                List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST);
+
+                MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION);
+                Long uid = uidList.get(num - 1).getUid();
+                if (deletedUidList.contains(uid) == false) {
+                    Iterator<MessageResult> results = session.getUserMailbox().getMessages(MessageRange.one(uid), GROUP, mailboxSession);
+
+                    if (results.hasNext()) {
+                        MessageResult result = results.next();
+
+                        Content content = result.getFullContent();                           
+                        InputStream in = new CRLFTerminatedInputStream(new ExtraDotInputStream(content.getInputStream()));
+                        response = new POP3StreamResponse(POP3Response.OK_RESPONSE, "Message follows", in);
+                        return response;
+
+                        
+
+                    } else {
+                        StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
+                        response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+                    }
+                } else {
+
+                    StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") already deleted.");
+                    response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+                }
+            } catch (IOException ioe) {
+                response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message.");
+            } catch (MailboxException me) {
+                response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message.");
+            } catch (IndexOutOfBoundsException iob) {
+                StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
+                response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+            } catch (NoSuchElementException e) {
+                StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
+                response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+            }
+        } else {
+            response = new POP3Response(POP3Response.ERR_RESPONSE);
+        }
+        return response;
+    }
+
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/RsetCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,110 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.james.mailbox.MailboxException;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageRange;
+import org.apache.james.mailbox.MessageResult;
+import org.apache.james.mailbox.MessageResult.FetchGroup;
+import org.apache.james.pop3server.POP3Response;
+import org.apache.james.pop3server.POP3Session;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+
+/**
+ * Handles RSET command
+ */
+public class RsetCmdHandler implements CommandHandler<POP3Session> {
+    private final static String COMMAND_NAME = "RSET";
+
+    private final static FetchGroup GROUP = new FetchGroup() {
+
+        @Override
+        public int content() {
+            return MINIMAL;
+        }
+
+        @Override
+        public Set<PartContentDescriptor> getPartContentDescriptors() {
+            return null;
+        }
+        
+    };
+    
+    /**
+     * Handler method called upon receipt of a RSET command. Calls stat() to
+     * reset the mailbox.
+     */
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response = null;
+        if (session.getHandlerState() == POP3Session.TRANSACTION) {
+            stat(session);
+            response = new POP3Response(POP3Response.OK_RESPONSE);
+        } else {
+            response = new POP3Response(POP3Response.ERR_RESPONSE);
+        }
+        return response;
+    }
+
+    /**
+     * Implements a "stat". If the handler is currently in a transaction state,
+     * this amounts to a rollback of the mailbox contents to the beginning of
+     * the transaction. This method is also called when first entering the
+     * transaction state to initialize the handler copies of the user inbox.
+     */
+    protected void stat(POP3Session session) {
+        try {
+            MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION);
+
+            List<MessageMetaData> uids = new ArrayList<MessageMetaData>();
+            Iterator<MessageResult> it = session.getUserMailbox().getMessages(MessageRange.all(), GROUP, mailboxSession);
+            while (it.hasNext()) {
+                MessageResult result = it.next();
+                uids.add(new MessageMetaData(result.getUid(), result.getSize()));
+
+            }
+            session.getState().put(POP3Session.UID_LIST, uids);
+            session.getState().put(POP3Session.DELETED_UID_LIST, new ArrayList<Long>());
+        } catch (MailboxException e) {
+            // In the event of an exception being thrown there may or may not be
+            // anything in userMailbox
+            session.getLogger().error("Unable to STAT mail box ", e);
+        }
+
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StatCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,80 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.james.pop3server.POP3Response;
+import org.apache.james.pop3server.POP3Session;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+
+/**
+ * Handles STAT command
+ */
+public class StatCmdHandler implements CommandHandler<POP3Session> {
+    private final static String COMMAND_NAME = "STAT";
+
+    /**
+     * Handler method called upon receipt of a STAT command. Returns the number
+     * of messages in the mailbox and its aggregate size.
+     */
+    @SuppressWarnings("unchecked")
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response = null;
+        if (session.getHandlerState() == POP3Session.TRANSACTION) {
+
+            List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST);
+            List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST);
+            long size = 0;
+            int count = 0;
+            if (uidList.isEmpty() == false) {
+                List<MessageMetaData> validResults = new ArrayList<MessageMetaData>();
+                for (int i = 0; i < uidList.size(); i++) {
+                    MessageMetaData data = uidList.get(i);
+                    if (deletedUidList.contains(data.getUid()) == false) {
+                        size += data.getSize();
+                        count++;
+                        validResults.add(data);
+                    }
+                }
+            }
+            StringBuilder responseBuffer = new StringBuilder(32).append(count).append(" ").append(size);
+            response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString());
+
+        } else {
+            response = new POP3Response(POP3Response.ERR_RESPONSE);
+        }
+        return response;
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/StlsCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,77 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+import org.apache.james.protocols.pop3.POP3Response;
+import org.apache.james.protocols.pop3.POP3Session;
+import org.apache.james.protocols.pop3.StartTlsPop3Response;
+
+/**
+ * Handler which offer STARTTLS implementation for POP3. STARTTLS is started
+ * with the STSL command
+ */
+public class StlsCmdHandler implements CommandHandler<POP3Session>, CapaCapability {
+    public final static String COMMAND_NAME = "STLS";
+
+    /**
+     * @see CommandHandler#onCommand(org.apache.james.protocols.api.ProtocolSession, Request)
+     */
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response;
+        // check if starttls is supported, the state is the right one and it was
+        // not started before
+        if (session.isStartTLSSupported() && session.getHandlerState() == POP3Session.AUTHENTICATION_READY && session.isTLSStarted() == false) {
+            response = new StartTlsPop3Response(POP3Response.OK_RESPONSE, "Begin TLS negotiation");
+            return response;
+
+        } else {
+            response = new POP3Response(POP3Response.ERR_RESPONSE);
+            return response;
+        }
+    }
+
+    /**
+     * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session)
+     */
+    public List<String> getImplementedCapabilities(POP3Session session) {
+        List<String> caps = new ArrayList<String>();
+        if (session.isStartTLSSupported() && session.getHandlerState() == POP3Session.AUTHENTICATION_READY) {
+            caps.add(COMMAND_NAME);
+            return caps;
+        }
+        return caps;
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/TopCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,246 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.james.mailbox.MailboxException;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageRange;
+import org.apache.james.mailbox.MessageResult;
+import org.apache.james.mailbox.MessageResult.FetchGroup;
+import org.apache.james.pop3server.POP3Response;
+import org.apache.james.pop3server.POP3Session;
+import org.apache.james.pop3server.POP3StreamResponse;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+
+/**
+ * Handles TOP command
+ */
+public class TopCmdHandler extends RetrCmdHandler implements CapaCapability {
+    private final static String COMMAND_NAME = "TOP";
+    private final static FetchGroup GROUP = new FetchGroup() {
+
+        @Override
+        public int content() {
+            return BODY_CONTENT | HEADERS;
+        }
+
+        @Override
+        public Set<PartContentDescriptor> getPartContentDescriptors() {
+            return null;
+        }
+        
+    };
+    
+    /**
+     * Handler method called upon receipt of a TOP command. This command
+     * retrieves the top N lines of a specified message in the mailbox.
+     * 
+     * The expected command format is TOP [mail message number] [number of lines
+     * to return]
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response = null;
+        String parameters = request.getArgument();
+        if (parameters == null) {
+            response = new POP3Response(POP3Response.ERR_RESPONSE, "Usage: TOP [mail number] [Line number]");
+            return response;
+        }
+
+        String argument = "";
+        String argument1 = "";
+        int pos = parameters.indexOf(" ");
+        if (pos > 0) {
+            argument = parameters.substring(0, pos);
+            argument1 = parameters.substring(pos + 1);
+        }
+
+        if (session.getHandlerState() == POP3Session.TRANSACTION) {
+            int num = 0;
+            int lines = -1;
+            try {
+                num = Integer.parseInt(argument);
+                lines = Integer.parseInt(argument1);
+            } catch (NumberFormatException nfe) {
+                response = new POP3Response(POP3Response.ERR_RESPONSE, "Usage: TOP [mail number] [Line number]");
+                return response;
+            }
+            try {
+                List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST);
+                List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST);
+
+                MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION);
+                Long uid = uidList.get(num - 1).getUid();
+                if (deletedUidList.contains(uid) == false) {
+
+                    Iterator<MessageResult> results = session.getUserMailbox().getMessages(MessageRange.one(uid), GROUP, mailboxSession);
+
+                    if (results.hasNext()) {
+                        MessageResult result = results.next();
+
+                        InputStream headersIn = result.getHeaders().getInputStream();
+                        InputStream bodyIn = new CountingBodyInputStream(new ExtraDotInputStream(new CRLFTerminatedInputStream(result.getBody().getInputStream())), lines);
+
+                        // write body
+                        InputStream in = new SequenceInputStream(Collections.enumeration(Arrays.asList(headersIn, new ByteArrayInputStream("\r\n".getBytes()), bodyIn)));
+
+                        response = new POP3StreamResponse(POP3Response.OK_RESPONSE, "Message follows", in);
+                        return response;
+
+                    } else {
+                        StringBuilder exceptionBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
+                        response = new POP3Response(POP3Response.ERR_RESPONSE, exceptionBuffer.toString());
+                    }
+
+                } else {
+                    StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") already deleted.");
+                    response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+                }
+            } catch (IOException ioe) {
+                response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message.");
+            } catch (MailboxException me) {
+                response = new POP3Response(POP3Response.ERR_RESPONSE, "Error while retrieving message.");
+            } catch (IndexOutOfBoundsException iob) {
+                StringBuilder exceptionBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
+                response = new POP3Response(POP3Response.ERR_RESPONSE, exceptionBuffer.toString());
+            } catch (NoSuchElementException iob) {
+                StringBuilder exceptionBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
+                response = new POP3Response(POP3Response.ERR_RESPONSE, exceptionBuffer.toString());
+            }
+        } else {
+            response = new POP3Response(POP3Response.ERR_RESPONSE);
+        }
+        return response;
+
+    }
+
+    /**
+     * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session)
+     */
+    public List<String> getImplementedCapabilities(POP3Session session) {
+        List<String> caps = new ArrayList<String>();
+        if (session.getHandlerState() == POP3Session.TRANSACTION) {
+            caps.add(COMMAND_NAME);
+            return caps;
+        }
+        return caps;
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+
+    /**
+     * This {@link InputStream} implementation can be used to limit the body
+     * lines which will be read from the wrapped {@link InputStream}
+     */
+    private final class CountingBodyInputStream extends FilterInputStream {
+
+        private int count = 0;
+        private int limit = -1;
+        private int lastChar;
+
+        /**
+         * 
+         * @param in
+         *            InputStream to read from
+         * @param limit
+         *            the lines to read. -1 is used for no limits
+         */
+        public CountingBodyInputStream(InputStream in, int limit) {
+            super(in);
+            this.limit = limit;
+        }
+
+        @Override
+        public int read() throws IOException {
+            if (limit != -1) {
+                if (count <= limit) {
+                    int a = in.read();
+
+                    if (lastChar == '\r' && a == '\n') {
+                        count++;
+                    }
+                    lastChar = a;
+
+                    return a;
+                } else {
+                    return -1;
+                }
+            } else {
+                return in.read();
+            }
+
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            if (limit == -1) {
+                return in.read(b, off, len);
+            } else {
+                int i;
+                for (i = 0; i < len; i++) {
+                    int a = read();
+                    if (i == 0 && a == -1) {
+                        return -1;
+                    } else {
+                        if (a == -1) {
+                            break;
+                        } else {
+                            b[off++] = (byte) a;
+                        }
+                    }
+                }
+                return i;
+            }
+        }
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            if (limit == -1) {
+                return in.read(b);
+            } else {
+                return read(b, 0, b.length);
+            }
+        }
+
+    }
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UidlCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,122 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.james.mailbox.MailboxException;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager.MetaData;
+import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup;
+import org.apache.james.pop3server.POP3Response;
+import org.apache.james.pop3server.POP3Session;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+
+/**
+ * Handles UIDL command
+ */
+public class UidlCmdHandler implements CommandHandler<POP3Session>, CapaCapability {
+    private final static String COMMAND_NAME = "UIDL";
+
+    /**
+     * Handler method called upon receipt of a UIDL command. Returns a listing
+     * of message ids to the client.
+     */
+    @SuppressWarnings("unchecked")
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response = null;
+        String parameters = request.getArgument();
+        if (session.getHandlerState() == POP3Session.TRANSACTION) {
+            List<MessageMetaData> uidList = (List<MessageMetaData>) session.getState().get(POP3Session.UID_LIST);
+            List<Long> deletedUidList = (List<Long>) session.getState().get(POP3Session.DELETED_UID_LIST);
+            MailboxSession mailboxSession = (MailboxSession) session.getState().get(POP3Session.MAILBOX_SESSION);
+            try {
+                MetaData mData = session.getUserMailbox().getMetaData(false, mailboxSession, FetchGroup.NO_COUNT);
+                long validity = mData.getUidValidity();
+                if (parameters == null) {
+                    response = new POP3Response(POP3Response.OK_RESPONSE, "unique-id listing follows");
+                    for (int i = 0; i < uidList.size(); i++) {
+                        Long uid = uidList.get(i).getUid();
+                        if (deletedUidList.contains(uid) == false) {
+                            // construct unique UIDL. See JAMES-1264
+                            StringBuilder responseBuffer = new StringBuilder(64).append(i + 1).append(" ").append(validity).append("-").append(uid);
+                            response.appendLine(responseBuffer.toString());
+                        }
+                    }
+
+                    response.appendLine(".");
+                } else {
+                    int num = 0;
+                    try {
+                        num = Integer.parseInt(parameters);
+                        Long uid = uidList.get(num - 1).getUid();
+                        if (deletedUidList.contains(uid) == false) {
+                            // construct unique UIDL. See JAMES-1264
+                            StringBuilder responseBuffer = new StringBuilder(64).append(num).append(" ").append(validity).append("-").append(uid);
+                            response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString());
+
+                        } else {
+                            StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") already deleted.");
+                            response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+                        }
+                    } catch (IndexOutOfBoundsException npe) {
+                        StringBuilder responseBuffer = new StringBuilder(64).append("Message (").append(num).append(") does not exist.");
+                        response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+                    } catch (NumberFormatException nfe) {
+                        StringBuilder responseBuffer = new StringBuilder(64).append(parameters).append(" is not a valid number");
+                        response = new POP3Response(POP3Response.ERR_RESPONSE, responseBuffer.toString());
+                    }
+                }
+            } catch (MailboxException e) {
+                response = new POP3Response(POP3Response.ERR_RESPONSE);
+                return response;
+            }
+            
+        } else {
+            response = new POP3Response(POP3Response.ERR_RESPONSE);
+        }
+        return response;
+    }
+
+    /**
+     * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session)
+     */
+    public List<String> getImplementedCapabilities(POP3Session session) {
+        List<String> caps = new ArrayList<String>();
+        if (session.getHandlerState() == POP3Session.TRANSACTION) {
+            caps.add(COMMAND_NAME);
+            return caps;
+        }
+        return caps;
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UnknownCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,58 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+import org.apache.james.protocols.pop3.POP3Response;
+import org.apache.james.protocols.pop3.POP3Session;
+
+/**
+ * Default command handler for handling unknown commands
+ */
+public class UnknownCmdHandler implements CommandHandler<POP3Session> {
+    /**
+     * The name of the command handled by the command handler
+     */
+    public static final String COMMAND_NAME = "UNKNOWN";
+
+    /**
+     * Handler method called upon receipt of an unrecognized command. Returns an
+     * error response and logs the command.
+     */
+    public Response onCommand(POP3Session session, Request request) {
+        return new POP3Response(POP3Response.ERR_RESPONSE);
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/UserCmdHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,73 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.james.pop3server.POP3Response;
+import org.apache.james.pop3server.POP3Session;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.CommandHandler;
+
+/**
+ * Handles NOOP command
+ */
+public class UserCmdHandler implements CommandHandler<POP3Session>, CapaCapability {
+
+    private final static String COMMAND_NAME = "USER";
+
+    /**
+     * Handler method called upon receipt of a USER command. Reads in the user
+     * id.
+     */
+    public Response onCommand(POP3Session session, Request request) {
+        POP3Response response = null;
+        String parameters = request.getArgument();
+        if (session.getHandlerState() == POP3Session.AUTHENTICATION_READY && parameters != null) {
+            session.setUser(parameters);
+            session.setHandlerState(POP3Session.AUTHENTICATION_USERSET);
+            response = new POP3Response(POP3Response.OK_RESPONSE);
+        } else {
+            response = new POP3Response(POP3Response.ERR_RESPONSE);
+        }
+        return response;
+    }
+
+    /**
+     * @see org.apache.james.pop3server.core.CapaCapability#getImplementedCapabilities(org.apache.james.pop3server.POP3Session)
+     */
+    public List<String> getImplementedCapabilities(POP3Session session) {
+        List<String> caps = new ArrayList<String>();
+        caps.add(COMMAND_NAME);
+        return caps;
+    }
+
+    /**
+     * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        List<String> commands = new ArrayList<String>();
+        commands.add(COMMAND_NAME);
+        return commands;
+    }
+}

Added: james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java?rev=1203562&view=auto
==============================================================================
--- james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java (added)
+++ james/protocols/trunk/pop3/src/main/java/org/apache/james/protocols/pop3/core/WelcomeMessageHandler.java Fri Nov 18 10:00:50 2011
@@ -0,0 +1,46 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.protocols.pop3.core;
+
+
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.handler.ConnectHandler;
+import org.apache.james.protocols.pop3.POP3Response;
+import org.apache.james.protocols.pop3.POP3Session;
+
+public class WelcomeMessageHandler implements ConnectHandler<POP3Session> {
+    /** POP3 Server identification string used in POP3 headers */
+    private static final String softwaretype = "JAMES POP3 Server ";// +
+                                                                    // Constants.SOFTWARE_VERSION;
+
+    /**
+     * @see org.apache.james.protocols.api.handler.ConnectHandler
+     * #onConnect(org.apache.james.pop3server.POP3Session)
+     */
+    public Response onConnect(POP3Session session) {
+        StringBuilder responseBuffer = new StringBuilder();
+        // Initially greet the connector
+        // Format is: Sat, 24 Jan 1998 13:16:09 -0500
+        responseBuffer.append(session.getConfigurationData().getHelloName()).append(" POP3 server (").append(softwaretype).append(") ready ");
+        POP3Response response = new POP3Response(POP3Response.OK_RESPONSE, responseBuffer.toString());
+        return response;
+    }
+
+}



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