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 23:58:27 UTC
svn commit: r405184 [1/2] -
/james/server/trunk/src/java/org/apache/james/pop3server/
Author: bago
Date: Mon May 8 14:58:26 2006
New Revision: 405184
URL: http://svn.apache.org/viewcvs?rev=405184&view=rev
Log:
Refactored POP3Handler to follow the same pattern of the SMTPHandler (JAMES-487)
Currently POP3Handler uses its own POP3Session, its own POP3HandlerChain and its own CommandHandler and ConnectHandler interfaces: we'll create common interfaces later.
Added:
james/server/trunk/src/java/org/apache/james/pop3server/CommandHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/ConnectHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/DeleCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/ListCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/NoopCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/POP3HandlerChain.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/POP3Session.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/PassCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/QuitCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/RetrCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/RsetCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/StatCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/TopCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/UidlCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/UnknownCmdHandler.java (with props)
james/server/trunk/src/java/org/apache/james/pop3server/UserCmdHandler.java (with props)
Modified:
james/server/trunk/src/java/org/apache/james/pop3server/POP3Handler.java
james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java
Added: james/server/trunk/src/java/org/apache/james/pop3server/CommandHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/CommandHandler.java?rev=405184&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/CommandHandler.java (added)
+++ james/server/trunk/src/java/org/apache/james/pop3server/CommandHandler.java Mon May 8 14:58:26 2006
@@ -0,0 +1,32 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You *
+ * may obtain a copy of the License at: *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
+ * implied. See the License for the specific language governing *
+ * permissions and limitations under the License. *
+ ***********************************************************************/
+
+package org.apache.james.pop3server;
+
+/**
+ * Custom command handlers must implement this interface
+ * The command handlers will be Server wide common to all the POP3Handlers,
+ * therefore the command handlers must store all the state information
+ * in the POP3Session object
+ */
+ public interface CommandHandler {
+ /*
+ * Handle the command
+ **/
+ void onCommand(POP3Session session);
+
+}
Propchange: james/server/trunk/src/java/org/apache/james/pop3server/CommandHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: james/server/trunk/src/java/org/apache/james/pop3server/ConnectHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/ConnectHandler.java?rev=405184&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/ConnectHandler.java (added)
+++ james/server/trunk/src/java/org/apache/james/pop3server/ConnectHandler.java Mon May 8 14:58:26 2006
@@ -0,0 +1,32 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You *
+ * may obtain a copy of the License at: *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
+ * implied. See the License for the specific language governing *
+ * permissions and limitations under the License. *
+ ***********************************************************************/
+
+package org.apache.james.pop3server;
+
+/**
+ * Custom connect handlers must implement this interface
+ * The connect handlers will be server-wide common to all the POP3Handlers,
+ * therefore the handlers must store all the state information
+ * in the POP3Session object
+ */
+public interface ConnectHandler {
+ /*
+ * Handle connection
+ **/
+ void onConnect(POP3Session session);
+
+}
Propchange: james/server/trunk/src/java/org/apache/james/pop3server/ConnectHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: james/server/trunk/src/java/org/apache/james/pop3server/DeleCmdHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/DeleCmdHandler.java?rev=405184&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/DeleCmdHandler.java (added)
+++ james/server/trunk/src/java/org/apache/james/pop3server/DeleCmdHandler.java Mon May 8 14:58:26 2006
@@ -0,0 +1,85 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You *
+ * may obtain a copy of the License at: *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
+ * implied. See the License for the specific language governing *
+ * permissions and limitations under the License. *
+ ***********************************************************************/
+
+package org.apache.james.pop3server;
+
+import org.apache.mailet.Mail;
+
+/**
+ * Handles DELE command
+ */
+public class DeleCmdHandler implements CommandHandler {
+
+ /**
+ * @see org.apache.james.pop3server.CommandHandler#onCommand(POP3Session)
+ */
+ public void onCommand(POP3Session session) {
+ doDELE(session,session.getCommandArgument());
+ }
+
+ /**
+ * Handler method called upon receipt of a DELE command.
+ * This command deletes a particular mail message from the
+ * mailbox.
+ *
+ * @param command the command parsed by the parseCommand method
+ * @param argument the first argument parsed by the parseCommand method
+ */
+ private void doDELE(POP3Session session,String argument) {
+ String responseString = null;
+ if (session.getHandlerState() == POP3Handler.TRANSACTION) {
+ int num = 0;
+ try {
+ num = Integer.parseInt(argument);
+ } catch (Exception e) {
+ responseString = POP3Handler.ERR_RESPONSE + " Usage: DELE [mail number]";
+ session.writeResponse(responseString);
+ return;
+ }
+ try {
+ Mail mc = (Mail) session.getUserMailbox().get(num);
+ if (mc == POP3Handler.DELETED) {
+ StringBuffer responseBuffer =
+ new StringBuffer(64)
+ .append(POP3Handler.ERR_RESPONSE)
+ .append(" Message (")
+ .append(num)
+ .append(") already deleted.");
+ responseString = responseBuffer.toString();
+ session.writeResponse(responseString);
+ } else {
+ session.getUserMailbox().set(num, POP3Handler.DELETED);
+ session.writeResponse(POP3Handler.OK_RESPONSE + " Message deleted");
+ }
+ } catch (IndexOutOfBoundsException iob) {
+ StringBuffer responseBuffer =
+ new StringBuffer(64)
+ .append(POP3Handler.ERR_RESPONSE)
+ .append(" Message (")
+ .append(num)
+ .append(") does not exist.");
+ responseString = responseBuffer.toString();
+ session.writeResponse(responseString);
+ }
+ } else {
+ responseString = POP3Handler.ERR_RESPONSE;
+ session.writeResponse(responseString);
+ }
+ }
+
+
+}
Propchange: james/server/trunk/src/java/org/apache/james/pop3server/DeleCmdHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: james/server/trunk/src/java/org/apache/james/pop3server/ListCmdHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/ListCmdHandler.java?rev=405184&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/ListCmdHandler.java (added)
+++ james/server/trunk/src/java/org/apache/james/pop3server/ListCmdHandler.java Mon May 8 14:58:26 2006
@@ -0,0 +1,143 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You *
+ * may obtain a copy of the License at: *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
+ * implied. See the License for the specific language governing *
+ * permissions and limitations under the License. *
+ ***********************************************************************/
+
+package org.apache.james.pop3server;
+
+import org.apache.mailet.Mail;
+
+import javax.mail.MessagingException;
+
+import java.util.Iterator;
+
+/**
+ * Handles LIST command
+ */
+public class ListCmdHandler implements CommandHandler {
+
+ /**
+ * @see org.apache.james.pop3server.CommandHandler#onCommand(POP3Session)
+ */
+ public void onCommand(POP3Session session) {
+ doLIST(session,session.getCommandArgument());
+ }
+
+ /**
+ * Handler method called upon receipt of a LIST command.
+ * Returns the number of messages in the mailbox and its
+ * aggregate size, or optionally, the number and size of
+ * a single message.
+ *
+ * @param command the command parsed by the parseCommand method
+ * @param argument the first argument parsed by the parseCommand method
+ */
+ private void doLIST(POP3Session session,String argument) {
+ String responseString = null;
+ if (session.getHandlerState() == POP3Handler.TRANSACTION) {
+ if (argument == null) {
+ long size = 0;
+ int count = 0;
+ try {
+ for (Iterator i = session.getUserMailbox().iterator(); i.hasNext(); ) {
+ Mail mc = (Mail) i.next();
+ if (mc != POP3Handler.DELETED) {
+ size += mc.getMessageSize();
+ count++;
+ }
+ }
+ StringBuffer responseBuffer =
+ new StringBuffer(32)
+ .append(POP3Handler.OK_RESPONSE)
+ .append(" ")
+ .append(count)
+ .append(" ")
+ .append(size);
+ responseString = responseBuffer.toString();
+ session.writeResponse(responseString);
+ count = 0;
+ for (Iterator i = session.getUserMailbox().iterator(); i.hasNext(); count++) {
+ Mail mc = (Mail) i.next();
+
+ if (mc != POP3Handler.DELETED) {
+ responseBuffer =
+ new StringBuffer(16)
+ .append(count)
+ .append(" ")
+ .append(mc.getMessageSize());
+ session.writeResponse(responseBuffer.toString());
+ }
+ }
+ session.writeResponse(".");
+ } catch (MessagingException me) {
+ responseString = POP3Handler.ERR_RESPONSE;
+ session.writeResponse(responseString);
+ }
+ } else {
+ int num = 0;
+ try {
+ num = Integer.parseInt(argument);
+ Mail mc = (Mail) session.getUserMailbox().get(num);
+ if (mc != POP3Handler.DELETED) {
+ StringBuffer responseBuffer =
+ new StringBuffer(64)
+ .append(POP3Handler.OK_RESPONSE)
+ .append(" ")
+ .append(num)
+ .append(" ")
+ .append(mc.getMessageSize());
+ responseString = responseBuffer.toString();
+ session.writeResponse(responseString);
+ } else {
+ StringBuffer responseBuffer =
+ new StringBuffer(64)
+ .append(POP3Handler.ERR_RESPONSE)
+ .append(" Message (")
+ .append(num)
+ .append(") already deleted.");
+ responseString = responseBuffer.toString();
+ session.writeResponse(responseString);
+ }
+ } catch (IndexOutOfBoundsException npe) {
+ StringBuffer responseBuffer =
+ new StringBuffer(64)
+ .append(POP3Handler.ERR_RESPONSE)
+ .append(" Message (")
+ .append(num)
+ .append(") does not exist.");
+ responseString = responseBuffer.toString();
+ session.writeResponse(responseString);
+ } catch (NumberFormatException nfe) {
+ StringBuffer responseBuffer =
+ new StringBuffer(64)
+ .append(POP3Handler.ERR_RESPONSE)
+ .append(" ")
+ .append(argument)
+ .append(" is not a valid number");
+ responseString = responseBuffer.toString();
+ session.writeResponse(responseString);
+ } catch (MessagingException me) {
+ responseString = POP3Handler.ERR_RESPONSE;
+ session.writeResponse(responseString);
+ }
+ }
+ } else {
+ responseString = POP3Handler.ERR_RESPONSE;
+ session.writeResponse(responseString);
+ }
+ }
+
+
+}
Propchange: james/server/trunk/src/java/org/apache/james/pop3server/ListCmdHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: james/server/trunk/src/java/org/apache/james/pop3server/NoopCmdHandler.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/NoopCmdHandler.java?rev=405184&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/NoopCmdHandler.java (added)
+++ james/server/trunk/src/java/org/apache/james/pop3server/NoopCmdHandler.java Mon May 8 14:58:26 2006
@@ -0,0 +1,51 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You *
+ * may obtain a copy of the License at: *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
+ * implied. See the License for the specific language governing *
+ * permissions and limitations under the License. *
+ ***********************************************************************/
+
+package org.apache.james.pop3server;
+
+/**
+ * Handles NOOP command
+ */
+public class NoopCmdHandler implements CommandHandler {
+
+ /**
+ * @see org.apache.james.pop3server.CommandHandler#onCommand(POP3Session)
+ */
+ public void onCommand(POP3Session session) {
+ doNOOP(session,session.getCommandArgument());
+ }
+
+ /**
+ * Handler method called upon receipt of a NOOP command.
+ * Like all good NOOPs, does nothing much.
+ *
+ * @param command the command parsed by the parseCommand method
+ * @param argument the first argument parsed by the parseCommand method
+ */
+ private void doNOOP(POP3Session session,String argument) {
+ String responseString = null;
+ if (session.getHandlerState() == POP3Handler.TRANSACTION) {
+ responseString = POP3Handler.OK_RESPONSE;
+ session.writeResponse(responseString);
+ } else {
+ responseString = POP3Handler.ERR_RESPONSE;
+ session.writeResponse(responseString);
+ }
+ }
+
+
+}
Propchange: james/server/trunk/src/java/org/apache/james/pop3server/NoopCmdHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
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=405184&r1=405183&r2=405184&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 Mon May 8 14:58:26 2006
@@ -17,63 +17,60 @@
package org.apache.james.pop3server;
-import org.apache.commons.collections.ListUtils;
import org.apache.james.Constants;
import org.apache.james.core.AbstractJamesHandler;
import org.apache.james.core.MailImpl;
import org.apache.james.services.MailRepository;
import org.apache.james.util.CRLFTerminatedReader;
-import org.apache.james.util.ExtraDotOutputStream;
-import org.apache.james.util.watchdog.BytesWrittenResetOutputStream;
+import org.apache.james.util.watchdog.Watchdog;
import org.apache.mailet.Mail;
import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
-import java.util.StringTokenizer;
/**
* The handler class for POP3 connections.
*
*/
public class POP3Handler
- extends AbstractJamesHandler {
+ extends AbstractJamesHandler implements POP3Session {
+
+ private final static byte COMMAND_MODE = 1;
+ private final static byte RESPONSE_MODE = 2;
// POP3 Server identification string used in POP3 headers
private static final String softwaretype = "JAMES POP3 Server "
+ Constants.SOFTWARE_VERSION;
// POP3 response prefixes
- private final static String OK_RESPONSE = "+OK"; // OK response. Requested content
+ final static String OK_RESPONSE = "+OK"; // OK response. Requested content
// will follow
- private final static String ERR_RESPONSE = "-ERR"; // Error response. Requested content
+ final static String ERR_RESPONSE = "-ERR"; // Error response. Requested content
// will not be provided. This prefix
// is followed by a more detailed
// error message
// Authentication states for the POP3 interaction
- private final static int AUTHENTICATION_READY = 0; // Waiting for user id
+ final static int AUTHENTICATION_READY = 0; // Waiting for user id
- private final static int AUTHENTICATION_USERSET = 1; // User id provided, waiting for
+ final static int AUTHENTICATION_USERSET = 1; // User id provided, waiting for
// password
- private final static int TRANSACTION = 2; // A valid user id/password combination
+ final static int TRANSACTION = 2; // A valid user id/password combination
// has been provided. In this state
// the client can access the mailbox
// of the specified user
- private static final Mail DELETED = new MailImpl(); // A placeholder for emails deleted
+ static final Mail DELETED = new MailImpl(); // A placeholder for emails deleted
// during the course of the POP3
// transaction. This Mail instance
// is used to enable fast checks as
@@ -93,12 +90,7 @@
/**
* The current transaction state of the handler
*/
- private int state;
-
- /**
- * The user id associated with the POP3 dialogue
- */
- private String user;
+ private int handlerState;
/**
* A dynamic list representing the set of
@@ -112,6 +104,53 @@
// of the transaction
/**
+ * The per-handler response buffer used to marshal responses.
+ */
+ private StringBuffer responseBuffer = new StringBuffer(256);
+
+
+ /**
+ * The name of the currently parsed command
+ */
+ String curCommandName = null;
+
+ /**
+ * The value of the currently parsed command
+ */
+ String curCommandArgument = null;
+
+ /**
+ * The POP3HandlerChain object set by POP3Server
+ */
+ POP3HandlerChain handlerChain = null;
+
+ /**
+ * The session termination status
+ */
+ private boolean sessionEnded = false;
+
+
+ /**
+ * The hash map that holds variables for the POP3 message transfer in progress.
+ *
+ * This hash map should only be used to store variable set in a particular
+ * set of sequential MAIL-RCPT-DATA commands, as described in RFC 2821. Per
+ * connection values should be stored as member variables in this class.
+ */
+ private HashMap state = new HashMap();
+
+ /**
+ * The user name of the authenticated user associated with this POP3 transaction.
+ */
+ private String authenticatedUser;
+
+ /**
+ * The mode of the current session
+ */
+ private byte mode;
+
+
+ /**
* Set the configuration data for the handler.
*
* @param theData the configuration data
@@ -128,29 +167,89 @@
* @see org.apache.james.core.AbstractJamesHandler#handleProtocol()
*/
protected void handleProtocol() throws IOException {
- state = AUTHENTICATION_READY;
- user = "unknown";
- StringBuffer responseBuffer =
- new StringBuffer(256)
- .append(OK_RESPONSE)
+ handlerState = AUTHENTICATION_READY;
+ authenticatedUser = "unknown";
+
+ resetState();
+
+ // Initially greet the connector
+ // Format is: Sat, 24 Jan 1998 13:16:09 -0500
+ responseBuffer.append(OK_RESPONSE)
.append(" ")
.append(theConfigData.getHelloName())
.append(" POP3 server (")
.append(POP3Handler.softwaretype)
.append(") ready ");
- out.println(responseBuffer.toString());
- out.flush();
+ String responseString = clearResponseBuffer();
+ writeLoggedFlushedResponse(responseString);
+
+ //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 (parseCommand(readCommandLine())) {
- theWatchdog.reset();
+ 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);
+
+ if (getLogger().isDebugEnabled()) {
+ // Don't display password in logger
+ if (!curCommandName.equals("PASS")) {
+ getLogger().debug("Command received: " + cmdString);
+ } else {
+ getLogger().debug("Command received: PASS <password omitted>");
+ }
+ }
+
+ //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.stop();
if (getLogger().isInfoEnabled()) {
StringBuffer logBuffer =
new StringBuffer(128)
.append("Connection for ")
- .append(user)
+ .append(getUser())
.append(" from ")
.append(remoteHost)
.append(" (")
@@ -178,7 +277,7 @@
*/
protected void resetHandler() {
// Clear user data
- user = null;
+ authenticatedUser = null;
userInbox = null;
if (userMailbox != null) {
userMailbox.clear();
@@ -203,7 +302,7 @@
* user inbox.
*
*/
- private void stat() {
+ public void stat() {
userMailbox = new ArrayList();
userMailbox.add(DELETED);
try {
@@ -232,7 +331,7 @@
* @return the trimmed input line
* @throws IOException if an exception is generated reading in the input characters
*/
- final String readCommandLine() throws IOException {
+ public final String readCommandLine() throws IOException {
for (;;) try {
String commandLine = inReader.readLine();
if (commandLine != null) {
@@ -251,663 +350,182 @@
* command specific handler methods. The primary purpose of this method is
* to parse the raw command string to determine exactly which handler should
* be called. It returns true if expecting additional commands, false otherwise.
- *
- * @param rawCommand the raw command string passed in over the socket
- *
- * @return whether additional commands are expected.
*/
- private boolean parseCommand(String rawCommand) {
- if (rawCommand == null) {
- return false;
- }
- boolean returnValue = true;
- String command = rawCommand;
- StringTokenizer commandLine = new StringTokenizer(command, " ");
- int arguments = commandLine.countTokens();
- if (arguments == 0) {
- return true;
- } else if(arguments > 0) {
- command = commandLine.nextToken().toUpperCase(Locale.US);
- }
- if (getLogger().isDebugEnabled()) {
- // Don't display password in logger
- if (!command.equals("PASS")) {
- getLogger().debug("Command received: " + rawCommand);
- } else {
- getLogger().debug("Command received: PASS <password omitted>");
- }
- }
- String argument = null;
- if(arguments > 1) {
- argument = commandLine.nextToken();
- }
- String argument1 = null;
- if(arguments > 2) {
- argument1 = commandLine.nextToken();
- }
-
- if (command.equals("USER")) {
- doUSER(command,argument,argument1);
- } else if (command.equals("PASS")) {
- doPASS(command,argument,argument1);
- } else if (command.equals("STAT")) {
- doSTAT(command,argument,argument1);
- } else if (command.equals("LIST")) {
- doLIST(command,argument,argument1);
- } else if (command.equals("UIDL")) {
- doUIDL(command,argument,argument1);
- } else if (command.equals("RSET")) {
- doRSET(command,argument,argument1);
- } else if (command.equals("DELE")) {
- doDELE(command,argument,argument1);
- } else if (command.equals("NOOP")) {
- doNOOP(command,argument,argument1);
- } else if (command.equals("RETR")) {
- doRETR(command,argument,argument1);
- } else if (command.equals("TOP")) {
- doTOP(command,argument,argument1);
- } else if (command.equals("QUIT")) {
- returnValue = false;
- doQUIT(command,argument,argument1);
- } else {
- doUnknownCmd(command,argument,argument1);
- }
- return returnValue;
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getRemoteHost()
+ */
+ public String getRemoteHost() {
+ return remoteHost;
}
/**
- * Handler method called upon receipt of a USER command.
- * Reads in the user id.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doUSER(String command,String argument,String argument1) {
- String responseString = null;
- if (state == AUTHENTICATION_READY && argument != null) {
- user = argument;
- state = AUTHENTICATION_USERSET;
- responseString = OK_RESPONSE;
- } else {
- responseString = ERR_RESPONSE;
- }
- writeLoggedFlushedResponse(responseString);
+ * @see org.apache.james.pop3server.POP3Session#getRemoteIPAddress()
+ */
+ public String getRemoteIPAddress() {
+ return remoteIP;
}
/**
- * Handler method called upon receipt of a PASS command.
- * Reads in and validates the password.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doPASS(String command,String argument,String argument1) {
- String responseString = null;
- if (state == AUTHENTICATION_USERSET && argument != null) {
- String passArg = argument;
- if (theConfigData.getUsersRepository().test(user, passArg)) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(OK_RESPONSE)
- .append(" Welcome ")
- .append(user);
- responseString = responseBuffer.toString();
- state = TRANSACTION;
- writeLoggedFlushedResponse(responseString);
- userInbox = theConfigData.getMailServer().getUserInbox(user);
- stat();
- } else {
- responseString = ERR_RESPONSE + " Authentication failed.";
- state = AUTHENTICATION_READY;
- writeLoggedFlushedResponse(responseString);
- }
- } else {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
+ * @see org.apache.james.pop3server.POP3Session#endSession()
+ */
+ public void endSession() {
+ sessionEnded = true;
}
/**
- * Handler method called upon receipt of a STAT command.
- * Returns the number of messages in the mailbox and its
- * aggregate size.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doSTAT(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- long size = 0;
- int count = 0;
- try {
- for (Iterator i = userMailbox.iterator(); i.hasNext(); ) {
- Mail mc = (Mail) i.next();
- if (mc != DELETED) {
- size += mc.getMessageSize();
- count++;
- }
- }
- StringBuffer responseBuffer =
- new StringBuffer(32)
- .append(OK_RESPONSE)
- .append(" ")
- .append(count)
- .append(" ")
- .append(size);
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- } catch (MessagingException me) {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
- } else {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
+ * @see org.apache.james.pop3server.POP3Session#isSessionEnded()
+ */
+ public boolean isSessionEnded() {
+ return sessionEnded;
}
/**
- * Handler method called upon receipt of a LIST command.
- * Returns the number of messages in the mailbox and its
- * aggregate size, or optionally, the number and size of
- * a single message.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doLIST(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- if (argument == null) {
- long size = 0;
- int count = 0;
- try {
- for (Iterator i = userMailbox.iterator(); i.hasNext(); ) {
- Mail mc = (Mail) i.next();
- if (mc != DELETED) {
- size += mc.getMessageSize();
- count++;
- }
- }
- StringBuffer responseBuffer =
- new StringBuffer(32)
- .append(OK_RESPONSE)
- .append(" ")
- .append(count)
- .append(" ")
- .append(size);
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- count = 0;
- for (Iterator i = userMailbox.iterator(); i.hasNext(); count++) {
- Mail mc = (Mail) i.next();
-
- if (mc != DELETED) {
- responseBuffer =
- new StringBuffer(16)
- .append(count)
- .append(" ")
- .append(mc.getMessageSize());
- out.println(responseBuffer.toString());
- }
- }
- out.println(".");
- out.flush();
- } catch (MessagingException me) {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
- } else {
- int num = 0;
- try {
- num = Integer.parseInt(argument);
- Mail mc = (Mail) userMailbox.get(num);
- if (mc != DELETED) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(OK_RESPONSE)
- .append(" ")
- .append(num)
- .append(" ")
- .append(mc.getMessageSize());
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- } else {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") already deleted.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- } catch (IndexOutOfBoundsException npe) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") does not exist.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- } catch (NumberFormatException nfe) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" ")
- .append(argument)
- .append(" is not a valid number");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- } catch (MessagingException me) {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
- }
- } else {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
+ * @see org.apache.james.pop3server.POP3Session#resetState()
+ */
+ public void resetState() {
+ state.clear();
}
/**
- * Handler method called upon receipt of a UIDL command.
- * Returns a listing of message ids to the client.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doUIDL(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- if (argument == null) {
- responseString = OK_RESPONSE + " unique-id listing follows";
- writeLoggedFlushedResponse(responseString);
- int count = 0;
- for (Iterator i = userMailbox.iterator(); i.hasNext(); count++) {
- Mail mc = (Mail) i.next();
- if (mc != DELETED) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(count)
- .append(" ")
- .append(mc.getName());
- out.println(responseBuffer.toString());
- }
- }
- out.println(".");
- out.flush();
- } else {
- int num = 0;
- try {
- num = Integer.parseInt(argument);
- Mail mc = (Mail) userMailbox.get(num);
- if (mc != DELETED) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(OK_RESPONSE)
- .append(" ")
- .append(num)
- .append(" ")
- .append(mc.getName());
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- } else {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") already deleted.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- } catch (IndexOutOfBoundsException npe) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") does not exist.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- } catch (NumberFormatException nfe) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" ")
- .append(argument)
- .append(" is not a valid number");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- }
- } else {
- writeLoggedFlushedResponse(ERR_RESPONSE);
- }
+ * @see org.apache.james.pop3server.POP3Session#getState()
+ */
+ public HashMap getState() {
+ return state;
}
/**
- * Handler method called upon receipt of a RSET command.
- * Calls stat() to reset the mailbox.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doRSET(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- stat();
- responseString = OK_RESPONSE;
- } else {
- responseString = ERR_RESPONSE;
- }
- writeLoggedFlushedResponse(responseString);
+ * @see org.apache.james.pop3server.POP3Session#getUser()
+ */
+ public String getUser() {
+ return authenticatedUser;
}
/**
- * Handler method called upon receipt of a DELE command.
- * This command deletes a particular mail message from the
- * mailbox.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doDELE(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- int num = 0;
- try {
- num = Integer.parseInt(argument);
- } catch (Exception e) {
- responseString = ERR_RESPONSE + " Usage: DELE [mail number]";
- writeLoggedFlushedResponse(responseString);
- return;
- }
- try {
- Mail mc = (Mail) userMailbox.get(num);
- if (mc == DELETED) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") already deleted.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- } else {
- userMailbox.set(num, DELETED);
- writeLoggedFlushedResponse(OK_RESPONSE + " Message deleted");
- }
- } catch (IndexOutOfBoundsException iob) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") does not exist.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- } else {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
+ * @see org.apache.james.pop3server.POP3Session#setUser(java.lang.String)
+ */
+ public void setUser(String userID) {
+ authenticatedUser = userID;
}
/**
- * Handler method called upon receipt of a NOOP command.
- * Like all good NOOPs, does nothing much.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doNOOP(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- responseString = OK_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- } else {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
+ * @see org.apache.james.pop3server.POP3Session#getResponseBuffer()
+ */
+ public StringBuffer getResponseBuffer() {
+ return responseBuffer;
}
/**
- * Handler method called upon receipt of a RETR command.
- * This command retrieves a particular mail message from the
- * mailbox.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doRETR(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- int num = 0;
- try {
- num = Integer.parseInt(argument.trim());
- } catch (Exception e) {
- responseString = ERR_RESPONSE + " Usage: RETR [mail number]";
- writeLoggedFlushedResponse(responseString);
- return;
- }
- try {
- Mail mc = (Mail) userMailbox.get(num);
- if (mc != DELETED) {
- responseString = OK_RESPONSE + " Message follows";
- writeLoggedFlushedResponse(responseString);
- try {
- ExtraDotOutputStream edouts =
- new ExtraDotOutputStream(outs);
- OutputStream nouts = new BytesWrittenResetOutputStream(edouts,
- theWatchdog,
- theConfigData.getResetLength());
- mc.getMessage().writeTo(nouts);
- nouts.flush();
- edouts.checkCRLFTerminator();
- edouts.flush();
- } finally {
- out.println(".");
- out.flush();
- }
- } else {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") already deleted.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- } catch (IOException ioe) {
- responseString = ERR_RESPONSE + " Error while retrieving message.";
- writeLoggedFlushedResponse(responseString);
- } catch (MessagingException me) {
- responseString = ERR_RESPONSE + " Error while retrieving message.";
- writeLoggedFlushedResponse(responseString);
- } catch (IndexOutOfBoundsException iob) {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") does not exist.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- } else {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
+ * @see org.apache.james.pop3server.POP3Session#clearResponseBuffer()
+ */
+ public String clearResponseBuffer() {
+ String responseString = responseBuffer.toString();
+ responseBuffer.delete(0,responseBuffer.length());
+ return responseString;
}
/**
- * 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]
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doTOP(String command,String argument,String argument1) {
- String responseString = null;
- if (state == TRANSACTION) {
- int num = 0;
- int lines = 0;
- try {
- num = Integer.parseInt(argument);
- lines = Integer.parseInt(argument1);
- } catch (NumberFormatException nfe) {
- responseString = ERR_RESPONSE + " Usage: TOP [mail number] [Line number]";
- writeLoggedFlushedResponse(responseString);
- return;
- }
- try {
- Mail mc = (Mail) userMailbox.get(num);
- if (mc != DELETED) {
- responseString = OK_RESPONSE + " Message follows";
- writeLoggedFlushedResponse(responseString);
- try {
- for (Enumeration e = mc.getMessage().getAllHeaderLines(); e.hasMoreElements(); ) {
- out.println(e.nextElement());
- }
- out.println();
- ExtraDotOutputStream edouts =
- new ExtraDotOutputStream(outs);
- OutputStream nouts = new BytesWrittenResetOutputStream(edouts,
- theWatchdog,
- theConfigData.getResetLength());
- writeMessageContentTo(mc.getMessage(),nouts,lines);
- nouts.flush();
- edouts.checkCRLFTerminator();
- edouts.flush();
- } finally {
- out.println(".");
- out.flush();
- }
- } else {
- StringBuffer responseBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") already deleted.");
- responseString = responseBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- } catch (IOException ioe) {
- responseString = ERR_RESPONSE + " Error while retrieving message.";
- writeLoggedFlushedResponse(responseString);
- } catch (MessagingException me) {
- responseString = ERR_RESPONSE + " Error while retrieving message.";
- writeLoggedFlushedResponse(responseString);
- } catch (IndexOutOfBoundsException iob) {
- StringBuffer exceptionBuffer =
- new StringBuffer(64)
- .append(ERR_RESPONSE)
- .append(" Message (")
- .append(num)
- .append(") does not exist.");
- responseString = exceptionBuffer.toString();
- writeLoggedFlushedResponse(responseString);
- }
- } else {
- responseString = ERR_RESPONSE;
- writeLoggedFlushedResponse(responseString);
- }
+ * @see org.apache.james.pop3server.POP3Session#getWatchdog()
+ */
+ public Watchdog getWatchdog() {
+ return theWatchdog;
}
/**
- * Writes the content of the message, up to a total number of lines, out to
- * an OutputStream.
+ * Sets the POP3HandlerChain
*
- * @param out the OutputStream to which to write the content
- * @param lines the number of lines to write to the stream
- *
- * @throws MessagingException if the MimeMessage is not set for this MailImpl
- * @throws IOException if an error occurs while reading or writing from the stream
+ * @param handlerChain POP3Handler object
*/
- public void writeMessageContentTo(MimeMessage message, OutputStream out, int lines)
- throws IOException, MessagingException {
- String line;
- BufferedReader br;
- if (message != null) {
- br = new BufferedReader(new InputStreamReader(message.getRawInputStream()));
- try {
- while (lines-- > 0) {
- if ((line = br.readLine()) == null) {
- break;
- }
- line += "\r\n";
- out.write(line.getBytes());
- }
- } finally {
- br.close();
- }
- } else {
- throw new MessagingException("No message set for this MailImpl.");
- }
+ public void setHandlerChain(POP3HandlerChain handlerChain) {
+ this.handlerChain = handlerChain;
}
/**
- * Handler method called upon receipt of a QUIT command.
- * This method handles cleanup of the POP3Handler state.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
- */
- private void doQUIT(String command,String argument,String argument1) {
- String responseString = null;
- if (state == AUTHENTICATION_READY || state == AUTHENTICATION_USERSET) {
- responseString = OK_RESPONSE + " Apache James POP3 Server signing off.";
- writeLoggedFlushedResponse(responseString);
- return;
- }
- List toBeRemoved = ListUtils.subtract(backupUserMailbox, userMailbox);
- try {
- userInbox.remove(toBeRemoved);
- // for (Iterator it = toBeRemoved.iterator(); it.hasNext(); ) {
- // Mail mc = (Mail) it.next();
- // userInbox.remove(mc.getName());
- //}
- responseString = OK_RESPONSE + " Apache James POP3 Server signing off.";
- writeLoggedFlushedResponse(responseString);
- } catch (Exception ex) {
- responseString = ERR_RESPONSE + " Some deleted messages were not removed";
- writeLoggedFlushedResponse(responseString);
- getLogger().error("Some deleted messages were not removed: " + ex.getMessage());
+ * @see org.apache.james.pop3server.POP3Session#writeResponse(java.lang.String)
+ */
+ public void writeResponse(String respString) {
+ writeLoggedFlushedResponse(respString);
+ //TODO Explain this well
+ if(mode == COMMAND_MODE) {
+ mode = RESPONSE_MODE;
}
}
/**
- * Handler method called upon receipt of an unrecognized command.
- * Returns an error response and logs the command.
- *
- * @param command the command parsed by the parseCommand method
- * @param argument the first argument parsed by the parseCommand method
- * @param argument1 the second argument parsed by the parseCommand method
+ * @see org.apache.james.pop3server.POP3Session#getCommandName()
*/
- private void doUnknownCmd(String command,String argument,String argument1) {
- writeLoggedFlushedResponse(ERR_RESPONSE);
+ public String getCommandName() {
+ return curCommandName;
}
-}
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getCommandArgument()
+ */
+ public String getCommandArgument() {
+ return curCommandArgument;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getConfigurationData()
+ */
+ public POP3HandlerConfigurationData getConfigurationData() {
+ return theConfigData;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getHandlerState()
+ */
+ public int getHandlerState() {
+ return handlerState;
+ }
+ /**
+ * @see org.apache.james.pop3server.POP3Session#setHandlerState(int)
+ */
+ public void setHandlerState(int handlerState) {
+ this.handlerState = handlerState;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getUserInbox()
+ */
+ public MailRepository getUserInbox() {
+ return userInbox;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#setUserInbox(org.apache.james.services.MailRepository)
+ */
+ public void setUserInbox(MailRepository userInbox) {
+ this.userInbox = userInbox;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getUserMailbox()
+ */
+ public ArrayList getUserMailbox() {
+ return userMailbox;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#setUserMailbox(java.util.ArrayList)
+ */
+ public void setUserMailbox(ArrayList userMailbox) {
+ this.userMailbox = userMailbox;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getBackupUserMailbox()
+ */
+ public List getBackupUserMailbox() {
+ return backupUserMailbox;
+ }
+
+ /**
+ * @see org.apache.james.pop3server.POP3Session#getOutputStream()
+ */
+ public OutputStream getOutputStream() {
+ return outs;
+ }
+
+}
Added: james/server/trunk/src/java/org/apache/james/pop3server/POP3HandlerChain.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/POP3HandlerChain.java?rev=405184&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/POP3HandlerChain.java (added)
+++ james/server/trunk/src/java/org/apache/james/pop3server/POP3HandlerChain.java Mon May 8 14:58:26 2006
@@ -0,0 +1,226 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You *
+ * may obtain a copy of the License at: *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
+ * implied. See the License for the specific language governing *
+ * permissions and limitations under the License. *
+ ***********************************************************************/
+
+package org.apache.james.pop3server;
+
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.configuration.DefaultConfiguration;
+import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+
+/**
+ * The POP3HandlerChain is per service object providing access
+ * ConnectHandlers, Commandhandlers and message handlers
+ */
+public class POP3HandlerChain extends AbstractLogEnabled implements Configurable, Serviceable {
+
+ private HashMap commandHandlerMap = new HashMap();
+ private ArrayList messageHandlers = new ArrayList();
+ private ArrayList connectHandlers = new ArrayList();
+
+ private final CommandHandler unknownHandler = new UnknownCmdHandler();
+ private ServiceManager serviceManager;
+
+ private final static String[] mandatoryCommands = { "USER" , "PASS", "LIST"};
+
+ public void service(ServiceManager arg0) throws ServiceException {
+ serviceManager = arg0;
+ }
+
+
+ /**
+ * loads the various handlers from the configuration
+ * @param configuration configuration under handlerchain node
+ */
+ public void configure(Configuration configuration) throws ConfigurationException {
+ addToMap(UnknownCmdHandler.UNKNOWN_COMMAND, unknownHandler);
+ if(configuration == null || configuration.getChildren("handler") == null || configuration.getChildren("handler").length == 0) {
+ configuration = new DefaultConfiguration("handlerchain");
+ Properties cmds = new Properties();
+ cmds.setProperty("USER",UserCmdHandler.class.getName());
+ cmds.setProperty("PASS",PassCmdHandler.class.getName());
+ cmds.setProperty("LIST",ListCmdHandler.class.getName());
+ cmds.setProperty("UIDL",UidlCmdHandler.class.getName());
+ cmds.setProperty("RSET",RsetCmdHandler.class.getName());
+ cmds.setProperty("DELE",DeleCmdHandler.class.getName());
+ cmds.setProperty("NOOP",NoopCmdHandler.class.getName());
+ cmds.setProperty("RETR",RetrCmdHandler.class.getName());
+ cmds.setProperty("TOP" ,TopCmdHandler.class.getName());
+ cmds.setProperty("QUIT",QuitCmdHandler.class.getName());
+ Enumeration e = cmds.keys();
+ while (e.hasMoreElements()) {
+ String cmdName = (String) e.nextElement();
+ String className = cmds.getProperty(cmdName);
+ DefaultConfiguration cmdConf = new DefaultConfiguration("handler");
+ cmdConf.setAttribute("command",cmdName);
+ cmdConf.setAttribute("class",className);
+ ((DefaultConfiguration) configuration).addChild(cmdConf);
+ }
+ }
+ if(configuration != null) {
+ Configuration[] children = configuration.getChildren("handler");
+ if ( children != null ) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ for ( int i = 0 ; i < children.length ; i++ ) {
+ String className = children[i].getAttribute("class");
+ if(className != null) {
+ //load the handler
+ try {
+ Object handler = classLoader.loadClass(className).newInstance();
+
+ //enable logging
+ ContainerUtil.enableLogging(handler, getLogger());
+
+ //servicing the handler
+ ContainerUtil.service(handler,serviceManager);
+
+ //configure the handler
+ ContainerUtil.configure(handler,children[i]);
+
+ //if it is a connect handler add it to list of connect handlers
+ if(handler instanceof ConnectHandler) {
+ connectHandlers.add((ConnectHandler)handler);
+ if (getLogger().isInfoEnabled()) {
+ getLogger().info("Added ConnectHandler: " + className);
+ }
+ }
+
+ //if it is a command handler add it to the map with key as command name
+ if(handler instanceof CommandHandler) {
+ String commandName = children[i].getAttribute("command");
+ commandName = commandName.toUpperCase(Locale.US);
+ addToMap(commandName, (CommandHandler)handler);
+ if (getLogger().isInfoEnabled()) {
+ getLogger().info("Added Commandhandler: " + className);
+ }
+
+ }
+
+ } catch (ClassNotFoundException ex) {
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error("Failed to add Commandhandler: " + className,ex);
+ }
+ } catch (IllegalAccessException ex) {
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error("Failed to add Commandhandler: " + className,ex);
+ }
+ } catch (InstantiationException ex) {
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error("Failed to add Commandhandler: " + className,ex);
+ }
+ } catch (ServiceException e) {
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error("Failed to service Commandhandler: " + className,e);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //the size must be greater than 1 because we added UnknownCmdHandler to the map
+ if(commandHandlerMap.size() < 2) {
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error("No commandhandlers configured");
+ }
+ throw new ConfigurationException("No commandhandlers configured");
+ } else {
+ boolean found = true;
+ for (int i = 0; i < mandatoryCommands.length; i++) {
+ if(!commandHandlerMap.containsKey(mandatoryCommands[i])) {
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error("No commandhandlers configured for the command:" + mandatoryCommands[i]);
+ }
+ found = false;
+ break;
+ }
+ }
+
+ if(!found) {
+ throw new ConfigurationException("No commandhandlers configured for mandatory commands");
+ }
+
+ }
+ }
+
+ /**
+ * Add it to map (key as command name, value is an array list of commandhandlers)
+ *
+ * @param commandName the command name which will be key
+ * @param cmdHandler The commandhandler object
+ */
+ private void addToMap(String commandName, CommandHandler cmdHandler) {
+ ArrayList handlers = (ArrayList)commandHandlerMap.get(commandName);
+ if(handlers == null) {
+ handlers = new ArrayList();
+ commandHandlerMap.put(commandName, handlers);
+ }
+ handlers.add(cmdHandler);
+ }
+
+ /**
+ * Returns all the configured commandhandlers for the specified command
+ *
+ * @param commandName the command name which will be key
+ * @return List of commandhandlers
+ */
+ List getCommandHandlers(String command) {
+ if (command == null) {
+ return null;
+ }
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Lookup command handler for command: " + command);
+ }
+ List handlers = (List)commandHandlerMap.get(command);
+ if(handlers == null) {
+ handlers = (List)commandHandlerMap.get(UnknownCmdHandler.UNKNOWN_COMMAND);
+ }
+
+ return handlers;
+ }
+
+ /**
+ * Returns all the configured message handlers
+ *
+ * @return List of message handlers
+ */
+ List getMessageHandlers() {
+ return messageHandlers;
+ }
+
+ /**
+ * Returns all the configured connect handlers
+ *
+ * @return List of connect handlers
+ */
+ List getConnectHandlers() {
+ return connectHandlers;
+ }
+
+}
Propchange: james/server/trunk/src/java/org/apache/james/pop3server/POP3HandlerChain.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java?rev=405184&r1=405183&r2=405184&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java (original)
+++ james/server/trunk/src/java/org/apache/james/pop3server/POP3Server.java Mon May 8 14:58:26 2006
@@ -17,9 +17,11 @@
package org.apache.james.pop3server;
+import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
import org.apache.avalon.excalibur.pool.ObjectFactory;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.james.core.AbstractJamesService;
@@ -36,6 +38,12 @@
public class POP3Server extends AbstractJamesService implements POP3ServerMBean {
/**
+ * The handler chain - POP3handlers can lookup handlerchain to obtain
+ * Command handlers , Message handlers and connection handlers
+ */
+ POP3HandlerChain handlerChain = new POP3HandlerChain();
+
+ /**
* The internal mail server service
*/
private MailServer mailServer;
@@ -58,12 +66,15 @@
private POP3HandlerConfigurationData theConfigData
= new POP3HandlerConfigurationDataImpl();
+ private ServiceManager serviceManager;
+
/**
* @see org.apache.avalon.framework.service.Serviceable#compose(ServiceManager)
*/
public void service( final ServiceManager componentManager )
throws ServiceException {
super.service(componentManager);
+ serviceManager = componentManager;
mailServer = (MailServer)componentManager.lookup( MailServer.ROLE );
users = (UsersRepository)componentManager.lookup( UsersRepository.ROLE );
}
@@ -79,6 +90,21 @@
if (getLogger().isInfoEnabled()) {
getLogger().info("The idle timeout will be reset every " + lengthReset + " bytes.");
}
+ //set the logger
+ ContainerUtil.enableLogging(handlerChain,getLogger());
+
+ try {
+ ContainerUtil.service(handlerChain,serviceManager);
+ } catch (ServiceException e) {
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error("Failed to service handlerChain",e);
+ }
+ throw new ConfigurationException("Failed to service handlerChain");
+ }
+
+ //read from the XML configuration and create and configure each of the handlers
+ ContainerUtil.configure(handlerChain,handlerConfiguration.getChild("handlerchain"));
+
}
theHandlerFactory = new POP3HandlerFactory();
}
@@ -95,6 +121,21 @@
*/
public String getServiceType() {
return "POP3 Service";
+ }
+
+
+ /**
+ * @see org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory#newHandler()
+ */
+ protected ConnectionHandler newHandler()
+ throws Exception {
+
+ POP3Handler theHandler = (POP3Handler) super.newHandler();
+
+ //pass the handler chain to every POP3handler
+ theHandler.setHandlerChain(handlerChain);
+
+ return theHandler;
}
/**
Added: james/server/trunk/src/java/org/apache/james/pop3server/POP3Session.java
URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/pop3server/POP3Session.java?rev=405184&view=auto
==============================================================================
--- james/server/trunk/src/java/org/apache/james/pop3server/POP3Session.java (added)
+++ james/server/trunk/src/java/org/apache/james/pop3server/POP3Session.java Mon May 8 14:58:26 2006
@@ -0,0 +1,212 @@
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You *
+ * may obtain a copy of the License at: *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
+ * implied. See the License for the specific language governing *
+ * permissions and limitations under the License. *
+ ***********************************************************************/
+
+package org.apache.james.pop3server;
+
+
+import org.apache.james.services.MailRepository;
+import org.apache.james.util.watchdog.Watchdog;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * All the handlers access this interface to communicate with
+ * POP3Handler object
+ */
+
+public interface POP3Session {
+
+ /**
+ * Writes response string to the client
+ *
+ * @param respString String that needs to send to the client
+ */
+ void writeResponse(String respString);
+
+ /**
+ * Reads a line of characters off the command line.
+ *
+ * @return the trimmed input line
+ * @throws IOException if an exception is generated reading in the input characters
+ */
+ String readCommandLine() throws IOException;
+
+
+ /**
+ * Returns ResponseBuffer, this optimizes the unecessary creation of resources
+ * by each handler object
+ *
+ * @return responseBuffer
+ */
+ StringBuffer getResponseBuffer();
+
+ /**
+ * Clears the response buffer, returning the String of characters in the buffer.
+ *
+ * @return the data in the response buffer
+ */
+ String clearResponseBuffer();
+
+ /**
+ * Returns currently process command name
+ *
+ * @return current command name
+ */
+ String getCommandName();
+
+ /**
+ * Returns currently process command argument
+ *
+ * @return current command argument
+ */
+ String getCommandArgument();
+
+ /**
+ * Returns host name of the client
+ *
+ * @return hostname of the client
+ */
+ String getRemoteHost();
+
+ /**
+ * Returns host ip address of the client
+ *
+ * @return host ip address of the client
+ */
+ String getRemoteIPAddress();
+
+ /**
+ * this makes the session to close
+ *
+ */
+ void endSession();
+
+ /**
+ * Returns the session status
+ *
+ * @return if the session is open or closed
+ */
+ boolean isSessionEnded();
+
+ /**
+ * Returns Map that consists of the state of the POP3Session
+ *
+ * @return map of the current POP3Session state
+ */
+ HashMap getState();
+
+ /**
+ * Resets message-specific, but not authenticated user, state.
+ *
+ */
+ void resetState();
+
+ /**
+ * Returns POP3Handler service wide configuration
+ *
+ * @return POP3HandlerConfigurationData
+ */
+ POP3HandlerConfigurationData getConfigurationData();
+
+ /**
+ * Returns the user name associated with this POP3 interaction.
+ *
+ * @return the user name
+ */
+ String getUser();
+
+ /**
+ * Sets the user name associated with this POP3 interaction.
+ *
+ * @param userID the user name
+ */
+ void setUser(String user);
+
+ /**
+ * Returns Watchdog object used for handling timeout
+ *
+ * @return Watchdog object
+ */
+ Watchdog getWatchdog();
+
+ /**
+ * Returns the current handler state
+ *
+ * @return handler state
+ */
+ int getHandlerState();
+
+ /**
+ * Sets the new handler state
+ *
+ * @param handlerState state
+ */
+ void setHandlerState(int handlerState);
+
+ /**
+ * Returns the current user inbox
+ *
+ * @return MailRepository
+ */
+ MailRepository getUserInbox();
+
+ /**
+ * Sets the user's mail repository
+ *
+ * @param userInbox userInbox
+ */
+ void setUserInbox(MailRepository userInbox);
+
+ /**
+ * Returns the mail list contained in the mailbox
+ *
+ * @return mailbox content
+ */
+ ArrayList getUserMailbox();
+
+ /**
+ * Sets a new mailbox content
+ *
+ * @param userMailbox mailbox
+ */
+ void setUserMailbox(ArrayList userMailbox);
+
+ /**
+ * Inizialize the mailbox
+ */
+ void stat();
+
+ /**
+ * Returns the backup mailbox
+ *
+ * @return list backup
+ */
+ List getBackupUserMailbox();
+
+ /**
+ * Returns the raw output stream
+ *
+ * @return the raw outputstream
+ */
+ OutputStream getOutputStream();
+
+}
+
Propchange: james/server/trunk/src/java/org/apache/james/pop3server/POP3Session.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org