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 2009/08/18 17:42:13 UTC
svn commit: r805459 [1/7] - in /james/server/trunk:
avalon-socket-library/src/main/java/org/apache/james/socket/
avalon-socket-library/src/main/java/org/apache/james/util/
core-library/src/main/java/org/apache/james/core/
phoenix-deployment-refactor/sr...
Author: norman
Date: Tue Aug 18 15:42:09 2009
New Revision: 805459
URL: http://svn.apache.org/viewvc?rev=805459&view=rev
Log:
Merge sandbox (smtpserver refactoring) to trunk
Added:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/util/CRLFDelimitedByteBuffer.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/ExtensibleHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/HandlersPackage.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/LineHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPResponse.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPRetCode.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPServer.xinfo
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/WiringException.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/AbstractHookableCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/AcceptRecipientIfRelayingIsAllowed.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/AddDefaultAttributesMessageHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/AuthRequiredToRelayRcptHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/CoreMessageHookLoader.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/DataLineFilter.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/DataLineMessageHookHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/PostmasterAbuseRcptHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SMTPCommandDispatcherLineHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SenderAuthIdentifyVerificationRcptHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/UsersRepositoryAuthHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/WelcomeMessageHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/esmtp/
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/esmtp/AuthCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/esmtp/EhloCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/esmtp/EhloExtension.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/esmtp/MailSizeEsmtpExtension.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/SpamTrapHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/TLDLookup.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/URIScanner.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/AuthHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/HeloHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/HookResult.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/HookResultHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/HookReturnCode.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/MailHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/MailParametersHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/MessageHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/QuitHook.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/hook/RcptHook.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/SpamTrapHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/Util.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/test/mock/MockMimeMessage.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/test/mock/mailet/
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/test/mock/mailet/MockMail.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/test/mock/mailet/MockMailContext.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/test/mock/mailet/MockMailetConfig.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/test/mock/mailet/MockMatcherConfig.java
Removed:
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/CommandsHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/MessageHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/MessageSizeException.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/ReaderInputStream.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SizeLimitedInputStream.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/AuthCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/EhloCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/CoreFilterCmdHandlerLoader.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/DataFilterCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/EhloFilterCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/HeloFilterCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/MailFilterCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/RcptFilterCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/AbstractJunkHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/JunkHandlerData.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/JunkScoreHandler.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/JunkScoreHandlerTest.java
Modified:
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesHandler.java
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java
james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java
james/server/trunk/core-library/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java
james/server/trunk/phoenix-deployment-refactor/src/main/config/james-smtphandlerchain.xml
james/server/trunk/phoenix-deployment/pom.xml
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/CommandHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandlerChain.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPServer.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPSession.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/CoreCmdHandlerLoader.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/DataCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/ExpnCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/HeloCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/HelpCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/MailCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/NoopCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/QuitCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/RcptCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/RsetCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SendMailHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/SetMimeHeaderHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/UnknownCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/VrfyCmdHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/DNSRBLHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/GreylistHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/MaxRcptHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/ResolvableEhloHeloHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/ReverseEqualsEhloHeloHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/SPFHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/SpamAssassinHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/SupressDuplicateRcptHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/TarpitHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/URIRBLHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/ValidRcptHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/ValidRcptMX.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/core/filter/fastfail/ValidSenderDomainHandler.java
james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/package.html
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/AbstractSMTPSession.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/DNSRBLHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/MaxRcptHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/ResolvableEhloHeloHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/SMTPTestConfiguration.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/SetMimeHeaderHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/TarpitHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
james/server/trunk/smtpserver-function/src/test/java/org/apache/james/smtpserver/ValidSenderDomainHandlerTest.java
Modified: james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesHandler.java?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesHandler.java (original)
+++ james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesHandler.java Tue Aug 18 15:42:09 2009
@@ -30,6 +30,7 @@
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.james.api.dnsservice.DNSService;
+import org.apache.james.util.CRLFDelimitedByteBuffer;
import org.apache.james.util.InternetPrintWriter;
import org.apache.james.util.watchdog.Watchdog;
import org.apache.james.util.watchdog.WatchdogTarget;
@@ -81,6 +82,12 @@
protected InputStream in;
/**
+ * Manage inputstream as a bytebuffer
+ */
+ private CRLFDelimitedByteBuffer bytebufferHandler;
+
+
+ /**
* The reader associated with incoming characters.
*/
protected CRLFTerminatedReader inReader;
@@ -166,7 +173,8 @@
outs = new SplitOutputStream(outs, new FileOutputStream(tcplogprefix+"out"));
in = new CopyInputStream(in, new FileOutputStream(tcplogprefix+"in"));
}
-
+ bytebufferHandler = new CRLFDelimitedByteBuffer(in);
+
// An ASCII encoding can be used because all transmissions other
// that those in the message body command are guaranteed
// to be ASCII
@@ -505,4 +513,18 @@
public String toString() {
return name;
}
+
+
+ public final byte[] readInputLine() throws IOException {
+ return bytebufferHandler.read();
+ }
+
+ public final String readInputLineAsString() throws IOException {
+ String line = bytebufferHandler.readString();
+ if (line != null && line.length() >= 2) {
+ return line.substring(0,line.length()-2);
+ } else {
+ return line;
+ }
+ }
}
Modified: james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java
URL: http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java (original)
+++ james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/AbstractJamesService.java Tue Aug 18 15:42:09 2009
@@ -677,7 +677,7 @@
*/
protected ConnectionHandler newHandler()
throws Exception {
- AbstractJamesHandler theHandler = (AbstractJamesHandler)theHandlerPool.get();
+ DelegatingJamesHandler theHandler = (DelegatingJamesHandler)theHandlerPool.get();
if (getLogger().isDebugEnabled()) {
getLogger().debug("Handler [" + theHandler + "] obtained from pool.");
@@ -796,7 +796,7 @@
* @see org.apache.avalon.excalibur.pool.ObjectFactory#newInstance()
*/
public Object newInstance() throws Exception {
- final AbstractJamesHandler delegatingJamesHandler = new DelegatingJamesHandler(newProtocolHandlerInstance());
+ final DelegatingJamesHandler delegatingJamesHandler = new DelegatingJamesHandler(newProtocolHandlerInstance(), dnsServer);
delegatingJamesHandler.setName("Handler-" + handlerCount.getAndAdd(1));
return delegatingJamesHandler;
}
Modified: james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java (original)
+++ james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/socket/DelegatingJamesHandler.java Tue Aug 18 15:42:09 2009
@@ -19,27 +19,448 @@
package org.apache.james.socket;
-import org.apache.avalon.framework.logger.Logger;
-import org.apache.james.util.watchdog.Watchdog;
-
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
+import org.apache.avalon.excalibur.pool.Poolable;
+import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.james.api.dnsservice.DNSService;
+import org.apache.james.util.InternetPrintWriter;
+import org.apache.james.util.watchdog.Watchdog;
+import org.apache.james.util.watchdog.WatchdogTarget;
/**
* Common Handler code
*/
-public class DelegatingJamesHandler extends AbstractJamesHandler implements ProtocolHandlerHelper {
+public class DelegatingJamesHandler extends AbstractLogEnabled implements ProtocolHandlerHelper, ConnectionHandler, Poolable {
+
+ private static final int DEFAULT_OUTPUT_BUFFER_SIZE = 1024;
+
+ private static final int DEFAULT_INPUT_BUFFER_SIZE = 1024;
+
+ /** Name used by default */
+ private static final String DEFAULT_NAME = "Handler-ANON";
+
+ /**
+ * The thread executing this handler
+ */
+ private Thread handlerThread;
+
+ /**
+ * The TCP/IP socket over which the service interaction
+ * is occurring
+ */
+ private Socket socket;
+
+ /**
+ * The writer to which outgoing messages are written.
+ */
+ private PrintWriter out;
+
+ /**
+ * The incoming stream of bytes coming from the socket.
+ */
+ private InputStream in;
+
+ /**
+ * The reader associated with incoming characters.
+ */
+ private CRLFTerminatedReader inReader;
+
+ /**
+ * The socket's output stream
+ */
+ private OutputStream outs;
+
+ /**
+ * The watchdog being used by this handler to deal with idle timeouts.
+ */
+ private Watchdog theWatchdog;
+
+ /**
+ * The watchdog target that idles out this handler.
+ */
+ private final WatchdogTarget theWatchdogTarget = new JamesWatchdogTarget();
+
+ /**
+ * The remote host name obtained by lookup on the socket.
+ */
+ private String remoteHost = null;
+
+ /**
+ * The remote IP address of the socket.
+ */
+ private String remoteIP = null;
+
+ /**
+ * Used for debug: if not null enable tcp stream dump.
+ */
+ private String tcplogprefix = null;
+
+ /**
+ * Names the handler.
+ * This name is used for contextual logging.
+ */
+ private String name = DEFAULT_NAME;
+
- protected ProtocolHandler protocolHandler;
+ /**
+ * The DNSService
+ */
+ private final DNSService dnsServer;
+ private final ProtocolHandler protocolHandler;
- public DelegatingJamesHandler(ProtocolHandler delegated) {
+ public DelegatingJamesHandler(final ProtocolHandler delegated, final DNSService dnsServer) {
this.protocolHandler = delegated;
+ this.dnsServer = dnsServer;
this.protocolHandler.setProtocolHandlerHelper(this);
}
+
+ /**
+ * Helper method for accepting connections.
+ * This MUST be called in the specializations.
+ *
+ * @param connection The Socket which belongs to the connection
+ * @throws IOException get thrown if an IO error is detected
+ */
+ protected void initHandler( Socket connection ) throws IOException {
+ this.socket = connection;
+ remoteIP = socket.getInetAddress().getHostAddress();
+ remoteHost = dnsServer.getHostName(socket.getInetAddress());
+
+ try {
+ synchronized (this) {
+ handlerThread = Thread.currentThread();
+ }
+ in = new BufferedInputStream(socket.getInputStream(), DEFAULT_INPUT_BUFFER_SIZE);
+ outs = new BufferedOutputStream(socket.getOutputStream(), DEFAULT_OUTPUT_BUFFER_SIZE);
+ // enable tcp dump for debug
+ if (tcplogprefix != null) {
+ outs = new SplitOutputStream(outs, new FileOutputStream(tcplogprefix+"out"));
+ in = new CopyInputStream(in, new FileOutputStream(tcplogprefix+"in"));
+ }
+
+ // An ASCII encoding can be used because all transmissions other
+ // that those in the message body command are guaranteed
+ // to be ASCII
+ inReader = new CRLFTerminatedReader(in, "ASCII");
+
+ out = new InternetPrintWriter(outs, true);
+ } catch (RuntimeException e) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(256)
+ .append("[" + toString() + "] Unexpected exception opening from ")
+ .append(remoteHost)
+ .append(" (")
+ .append(remoteIP)
+ .append("): ")
+ .append(e.getMessage());
+ String exceptionString = exceptionBuffer.toString();
+ getLogger().error(exceptionString, e);
+ throw e;
+ } catch (IOException e) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(256)
+ .append("[" + toString() + "] Cannot open connection from ")
+ .append(remoteHost)
+ .append(" (")
+ .append(remoteIP)
+ .append("): ")
+ .append(e.getMessage());
+ String exceptionString = exceptionBuffer.toString();
+ getLogger().error(exceptionString, e);
+ throw e;
+ }
+
+ if (getLogger().isInfoEnabled()) {
+ StringBuffer infoBuffer =
+ new StringBuffer(128)
+ .append("[" + toString() + "]Connection from ")
+ .append(remoteHost)
+ .append(" (")
+ .append(remoteIP)
+ .append(")");
+ getLogger().info(infoBuffer.toString());
+ }
+ }
+
+ /**
+ * The method clean up and close the allocated resources
+ */
+ private void cleanHandler() {
+ // Clear the Watchdog
+ if (theWatchdog != null) {
+ ContainerUtil.dispose(theWatchdog);
+ theWatchdog = null;
+ }
+
+ // Clear the streams
+ try {
+ if (inReader != null) {
+ inReader.close();
+ }
+ } catch (IOException ioe) {
+ getLogger().warn("[" + toString() + "] Unexpected exception occurred while closing reader: " + ioe);
+ } finally {
+ inReader = null;
+ }
+
+ in = null;
+
+ if (out != null) {
+ out.close();
+ out = null;
+ }
+ outs = null;
+
+ try {
+ if (socket != null) {
+ socket.close();
+ }
+ } catch (IOException ioe) {
+ getLogger().warn("[" + toString() + "] Unexpected exception occurred while closing socket: " + ioe);
+ } finally {
+ socket = null;
+ }
+
+ remoteIP = null;
+ remoteHost = null;
+
+ synchronized (this) {
+ handlerThread = null;
+ }
+ }
+
+ /**
+ * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(java.net.Socket)
+ */
+ public void handleConnection(Socket connection) throws IOException {
+ initHandler(connection);
+
+ final Logger logger = getLogger();
+ try {
+
+ // Do something:
+ handleProtocol();
+
+ logger.debug("[" + toString() + "] Closing socket");
+ } catch (SocketException se) {
+ // Indicates a problem at the underlying protocol level
+ if (logger.isWarnEnabled()) {
+ String message =
+ new StringBuffer(64)
+ .append("[" + toString() + "]Socket to ")
+ .append(remoteHost)
+ .append(" (")
+ .append(remoteIP)
+ .append("): ")
+ .append(se.getMessage()).toString();
+ logger.warn(message);
+ logger.debug(se.getMessage(), se);
+ }
+ } catch ( InterruptedIOException iioe ) {
+ if (logger.isErrorEnabled()) {
+ StringBuffer errorBuffer =
+ new StringBuffer(64)
+ .append("[" + toString() + "] Socket to ")
+ .append(remoteHost)
+ .append(" (")
+ .append(remoteIP)
+ .append(") timeout.");
+ logger.error( errorBuffer.toString(), iioe );
+ }
+ } catch ( IOException ioe ) {
+ if (logger.isWarnEnabled()) {
+ String message =
+ new StringBuffer(256)
+ .append("[" + toString() + "] Exception handling socket to ")
+ .append(remoteHost)
+ .append(" (")
+ .append(remoteIP)
+ .append(") : ")
+ .append(ioe.getMessage()).toString();
+ logger.warn(message);
+ logger.debug( ioe.getMessage(), ioe );
+ }
+ } catch (RuntimeException e) {
+ errorHandler(e);
+ } finally {
+ //Clear all the session state variables
+ cleanHandler();
+ resetHandler();
+ }
+ }
+
+ /**
+ * Set the Watchdog for use by this handler.
+ *
+ * @param theWatchdog the watchdog
+ */
+ public void setWatchdog(Watchdog theWatchdog) {
+ this.theWatchdog = theWatchdog;
+ }
+
+ /**
+ * Gets the Watchdog Target that should be used by Watchdogs managing
+ * this connection.
+ *
+ * @return the WatchdogTarget
+ */
+ WatchdogTarget getWatchdogTarget() {
+ return theWatchdogTarget;
+ }
+
+ /**
+ * Idle out this connection
+ */
+ void idleClose() {
+ if (getLogger() != null) {
+ getLogger().error("[" + toString() + "] Service Connection has idled out.");
+ }
+ try {
+ if (socket != null) {
+ socket.close();
+ }
+ } catch (Exception e) {
+ // ignored
+ } finally {
+ socket = null;
+ }
+
+ synchronized (this) {
+ // Interrupt the thread to recover from internal hangs
+ if (handlerThread != null) {
+ handlerThread.interrupt();
+ handlerThread = null;
+ }
+ }
+
+ }
+
+ /**
+ * This method logs at a "DEBUG" level the response string that
+ * was sent to the service client. The method is provided largely
+ * as syntactic sugar to neaten up the code base. It is declared
+ * private and final to encourage compiler inlining.
+ *
+ * @param responseString the response string sent to the client
+ */
+ private final void logResponseString(String responseString) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("[" + toString() + "] Sent: " + responseString);
+ }
+ }
+
+ /**
+ * Write and flush a response string. The response is also logged.
+ * Should be used for the last line of a multi-line response or
+ * for a single line response.
+ *
+ * @param responseString the response string sent to the client
+ */
+ public final void writeLoggedFlushedResponse(String responseString) {
+ out.println(responseString);
+ out.flush();
+ logResponseString(responseString);
+ }
+
+ /**
+ * Write a response string. The response is also logged.
+ * Used for multi-line responses.
+ *
+ * @param responseString the response string sent to the client
+ */
+ public final void writeLoggedResponse(String responseString) {
+ out.println(responseString);
+ logResponseString(responseString);
+ }
+
+ /**
+ * A private inner class which serves as an adaptor
+ * between the WatchdogTarget interface and this
+ * handler class.
+ */
+ private class JamesWatchdogTarget
+ implements WatchdogTarget {
+
+ /**
+ * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
+ */
+ public void execute() {
+ DelegatingJamesHandler.this.idleClose();
+ }
+
+ /**
+ * Used for context sensitive logging
+ */
+ @Override
+ public String toString() {
+ return DelegatingJamesHandler.this.toString();
+ }
+ }
+
+ /**
+ * If not null, this will enable dump to file for tcp connections
+ *
+ * @param streamDumpDir the dir
+ */
+ public void setStreamDumpDir(String streamDumpDir) {
+ if (streamDumpDir != null) {
+ String streamdumpDir=streamDumpDir;
+ this.tcplogprefix = streamdumpDir+"/" + getName() + "_TCP-DUMP."+System.currentTimeMillis()+".";
+ File logdir = new File(streamdumpDir);
+ if (!logdir.exists()) {
+ logdir.mkdir();
+ }
+ } else {
+ this.tcplogprefix = null;
+ }
+ }
+
+ /**
+ * The name of this handler.
+ * Used for context sensitive logging.
+ * @return the name, not null
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * The name of this handler.
+ * Note that this name should be file-system safe.
+ * Used for context sensitive logging.
+ * @param name the name to set
+ */
+ public final void setName(final String name) {
+ if (name == null) {
+ this.name = DEFAULT_NAME;
+ } else {
+ this.name = name;
+ }
+ }
+
+ /**
+ * Use for context sensitive logging.
+ * @return the name of the handler
+ */
+ @Override
+ public String toString() {
+ return name;
+ }
/**
* This method will be implemented checking for the correct class
@@ -80,7 +501,10 @@
* @see org.apache.james.socket.ProtocolHandlerHelper#defaultErrorHandler(java.lang.RuntimeException)
*/
public void defaultErrorHandler(RuntimeException e) {
- super.errorHandler(e);
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error( "[" + toString() + "] Unexpected runtime exception: "
+ + e.getMessage(), e );
+ }
}
/**
Added: james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/util/CRLFDelimitedByteBuffer.java
URL: http://svn.apache.org/viewvc/james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/util/CRLFDelimitedByteBuffer.java?rev=805459&view=auto
==============================================================================
--- james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/util/CRLFDelimitedByteBuffer.java (added)
+++ james/server/trunk/avalon-socket-library/src/main/java/org/apache/james/util/CRLFDelimitedByteBuffer.java Tue Aug 18 15:42:09 2009
@@ -0,0 +1,331 @@
+/****************************************************************
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/*
+ * A simple, synchronized, queue of CRLF-delimited lines.
+ *
+ * NOTA BENE: as bytes arrive, they are buffered internally up to a
+ * configured maximum. The maximum is intended to reflect a line length
+ * limiter, but there is a potential corner case that should be
+ * understood. If the working buffer is almost full, and a new packet
+ * arrives with enough data to overflow the buffer, the code will
+ * consider that an error and discard the entire working buffer, even
+ * though the beginning of the new packet might have terminated the
+ * currently accumulating line. And the reported position of the
+ * overflow is based upon the buffer position before scanning for lines,
+ * not an actualy line length (perhaps we need not even report the
+ * position). Since the purpose for this maximum is to prevent memory
+ * flooding attacks, this does not appear to be a particularly critical
+ * corner case. We simply need to make sure that the working buffer is
+ * at least twice the size of the maximum desired line length.
+ *
+ * After buffering the incoming data, it is scanned for CRLF. As each
+ * line is found, it is moved to an ArrayList of Line objects. When all
+ * data has been scanned, any remaining bytes are shifted within the
+ * working buffer to prepare for the next packet.
+ *
+ * The code enforces CRLF pairing (RFC 2821 #2.7.1). The Line object,
+ * which is for internal use only, can hold the bytes for each line or
+ * record an exception (line termination or line length) associated
+ * with processing the data that would otherwise have. The exceptions
+ * are rethrown during the read operation, rather than during the write
+ * operation, so that the order of responses perserves the order of
+ * input.
+ *
+ * This code does not handle dot stuffing. Dot Stuffing, Message size
+ * limiting, and buffering of the message in a file are all expected to
+ * be performed by the I/O handler associated with the DATA accumulation
+ * state.
+ */
+
+public class CRLFDelimitedByteBuffer {
+ static public class TerminationException extends java.io.IOException {
+ private int where;
+ public TerminationException(int where) {
+ super();
+ this.where = where;
+ }
+
+ public TerminationException(String s, int where) {
+ super(s);
+ this.where = where;
+ }
+
+ public int position() {
+ return where;
+ }
+ }
+
+ static public class LineLengthExceededException extends java.io.IOException {
+ public LineLengthExceededException(String s) {
+ super(s);
+ }
+ }
+
+ private InputStream input;
+
+ public CRLFDelimitedByteBuffer(InputStream input) {
+ this(input, 2048);
+ }
+
+ public CRLFDelimitedByteBuffer(InputStream input, int maxLineLength) {
+ this.input = input;
+ lines = new java.util.ArrayList();
+ workLine = new byte[maxLineLength];
+ }
+
+ synchronized public boolean isEmpty() {
+ return lines.isEmpty();
+ }
+
+ synchronized public byte[] read() throws IOException, LineLengthExceededException, TerminationException {
+ byte[] buffer = new byte[1000];
+ int length;
+ while (lines.isEmpty() && isEmpty() && (length = input.read(buffer))!=-1) {
+ write(buffer, length);
+ }
+ return lines.isEmpty() ? null : ((Line) lines.remove(0)).getBytes();
+ }
+
+ synchronized public String readString() throws IOException, LineLengthExceededException, TerminationException {
+ byte[] buffer = new byte[1000];
+ int length;
+ while (lines.isEmpty() && isEmpty() && (length = input.read(buffer))!=-1) {
+ write(buffer, length);
+ }
+ if (lines.isEmpty()) return null;
+ else {
+ byte[] bytes = ((Line) lines.remove(0)).getBytes();
+ try {
+ return new String(bytes, "US-ASCII");
+ } catch (java.io.UnsupportedEncodingException uee) {
+ return new String(bytes);
+ }
+ }
+ }
+
+ synchronized public void write(byte[] data, int length) {
+ if (canFit(length)) {
+ System.arraycopy(data, 0, workLine, writeindex, length);
+ writeindex += length;
+ buildlines();
+ }
+ }
+
+ synchronized public void write(byte data) {
+ if (canFit(1)) {
+ workLine[writeindex++] = data;
+ buildlines();
+ }
+ }
+
+ synchronized public void write(String s) {
+ write(s.getBytes(), s.getBytes().length);
+ }
+
+ private boolean canFit(int length) {
+ if (writeindex + length > workLine.length) {
+ reset();
+ lines.add(new Line(new LineLengthExceededException("Exceeded maximum line length")));
+ return false;
+ } else return true;
+ }
+
+ static private class Line {
+ java.io.IOException e;
+ byte[] bytes;
+
+ public Line(byte[] data) {
+ bytes = data;
+ }
+
+ public Line(String data) {
+ bytes = data.getBytes();
+ }
+
+ public Line(java.io.IOException e) {
+ this.e = e;
+ }
+
+ public Line(byte[] data, int offset, int length) {
+ bytes = new byte[length];
+ System.arraycopy(data, offset, bytes, 0, length);
+ }
+
+ public byte[] getBytes() throws LineLengthExceededException, TerminationException {
+ if (e != null) {
+ if (e instanceof LineLengthExceededException) throw (LineLengthExceededException) e;
+ else throw (TerminationException) e;
+ }
+ return bytes;
+ }
+ }
+
+ private java.util.ArrayList lines;
+
+ private byte[] workLine;
+ private int writeindex = 0;
+ private int readindex = 0;
+ private int scanindex = 0; // current index for matching within the working buffer
+
+ private void reset() {
+ writeindex = 0;
+ readindex = 0;
+ scanindex = 0;
+ }
+
+ private void shift() {
+ System.arraycopy(workLine, readindex, workLine, 0, writeindex - readindex);
+ writeindex -= readindex;
+ scanindex -= readindex;
+ readindex = 0;
+ }
+
+ private void buildlines() {
+ for (; scanindex < writeindex; scanindex++) {
+ if (workLine[scanindex] == '\n') {
+ final int pos = scanindex;
+ reset();
+ lines.add(new Line(new TerminationException("\"bare\" LF in data stream.", pos)));
+ break;
+ } else if (workLine[scanindex] == '\r') {
+ if (scanindex+1 == writeindex) break;
+ else if (workLine[++scanindex] == '\n') {
+ lines.add(new Line(workLine, readindex, scanindex - readindex + 1));
+ readindex = scanindex + 1;
+ } else {
+ final int pos = scanindex - 1;
+ reset();
+ lines.add(new Line(new TerminationException("\"bare\" CR in data stream.", pos)));
+ break;
+ }
+ }
+ }
+
+ if (readindex != 0) shift();
+ }
+
+ /*** THE CODE BELOW IS PURELY FOR TESTING ***/
+ /*
+ synchronized private void status() {
+ System.out.println("\n--------------------------------------------------\n");
+ if (lines.isEmpty()) System.out.println("Lines: None");
+ else {
+ System.out.println("Lines:");
+ java.util.Iterator i = lines.iterator();
+ while (i.hasNext()) {
+ Line line = (Line) i.next();
+ try {
+ System.out.println("\tData[" + line.getBytes().length + "]: " + new String(line.getBytes(), 0, line.getBytes().length, "US-ASCII"));
+ } catch (java.io.UnsupportedEncodingException uee) {
+ } catch (TerminationException te) {
+ System.out.println("\tSyntax error at character position " + te.position() + ". CR and LF must be CRLF paired. See RFC 2821 #2.7.1.");
+ } catch (LineLengthExceededException llee) {
+ System.out.println("\tLine length exceeded. See RFC 2821 #4.5.3.1.");
+ }
+ }
+ }
+
+ System.out.println("Buffer Status:");
+ System.out.println("\tworkline length: " + workLine.length);
+ System.out.println("\tnext read index: " + readindex);
+ System.out.println("\tnext scan index: " + scanindex);
+ System.out.println("\tnext write index: " + writeindex);
+
+ try {
+ System.out.println("\tOld data: " + new String(workLine, 0, readindex, "US-ASCII"));
+ System.out.println("\tData: " + new String(workLine, readindex, writeindex - readindex, "US-ASCII"));
+ } catch (java.io.UnsupportedEncodingException uee) {
+ System.err.println(uee);
+ }
+ System.out.println("\n--------------------------------------------------\n");
+ }
+
+
+ static public void main(String[] args) throws java.io.IOException {
+ CRLFDelimitedByteBuffer dbb = new CRLFDelimitedByteBuffer();
+ dbb.status();
+ dbb.write("Hello"); dbb.status();
+ dbb.write(" "); dbb.status();
+ dbb.write("World."); dbb.status();
+ dbb.write("\r"); dbb.status();
+ dbb.write("\n"); dbb.status();
+ dbb.write("\r\n"); dbb.status();
+ dbb.write("\n"); dbb.status();
+ dbb.write("\r\r"); dbb.status();
+ dbb.write("stuff\n"); dbb.status();
+ dbb.write("morestuff\r\r"); dbb.status();
+ for (int i = 0; i < 2500; i++) dbb.write("\0"); dbb.status();
+
+ while (!dbb.isEmpty()) {
+ try {
+ byte[] line = dbb.read();
+ System.out.println("Read line[" + line.length + "]: " + new String(line, 0, line.length, "US-ASCII"));
+ } catch (java.io.UnsupportedEncodingException uee) {
+ } catch (TerminationException te) {
+ System.out.println("Syntax error at character position " + te.position() + ". CR and LF must be CRLF paired. See RFC 2821 #2.7.1.");
+ } catch (LineLengthExceededException llee) {
+ System.out.println("Line length exceeded. See RFC 2821 #4.5.3.1.");
+ }
+ }
+ dbb.status();
+
+ dbb.write("This is a test.\015\012.... Three dots\015\012.\015\012");
+ dbb.status();
+
+ while (!dbb.isEmpty()) {
+ try {
+ byte[] line = dbb.read();
+ System.out.println("Read line[" + line.length + "]: " + new String(line, 0, line.length, "US-ASCII"));
+ } catch (java.io.UnsupportedEncodingException uee) {
+ } catch (TerminationException te) {
+ System.out.println("Syntax error at character position " + te.position() + ". CR and LF must be CRLF paired. See RFC 2821 #2.7.1.");
+ } catch (LineLengthExceededException llee) {
+ System.out.println("Line length exceeded. See RFC 2821 #4.5.3.1.");
+ }
+ }
+ dbb.status();
+
+ dbb.write("This is"); dbb.status();
+ dbb.write(" a tes"); dbb.status();
+ dbb.write("t.\015"); dbb.status();
+ dbb.write("\012..."); dbb.status();
+ dbb.write(". Three dot"); dbb.status();
+ dbb.write("s\015\012.\015\012"); dbb.status();
+
+ while (!dbb.isEmpty()) {
+ try {
+ String text = dbb.readString();
+ System.out.println ("read : " + text);
+ dbb.status();
+ } catch (TerminationException te) {
+ System.out.println("Syntax error at character position " + te.position() + ". CR and LF must be CRLF paired. See RFC 2821 #2.7.1.");
+ } catch (LineLengthExceededException llee) {
+ System.out.println("Line length exceeded. See RFC 2821 #4.5.3.1.");
+ }
+ }
+ }
+ */
+}
Modified: james/server/trunk/core-library/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java
URL: http://svn.apache.org/viewvc/james/server/trunk/core-library/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/core-library/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java (original)
+++ james/server/trunk/core-library/src/main/java/org/apache/james/core/MimeMessageInputStreamSource.java Tue Aug 18 15:42:09 2009
@@ -26,6 +26,7 @@
import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -110,6 +111,21 @@
}
}
+ public MimeMessageInputStreamSource(String key) throws MessagingException {
+ try {
+ file = File.createTempFile(key, ".m64");
+ sourceId = file.getCanonicalPath();
+ } catch (IOException e) {
+ throw new MessagingException("Unable to get canonical file path: " + e.getMessage(), e);
+ } finally {
+ // if sourceId is null while file is not null then we had
+ // an IOxception and we have to clean the file.
+ if (sourceId == null && file != null) {
+ file.delete();
+ }
+ }
+ }
+
/**
* Returns the unique identifier of this input stream source
*
@@ -140,6 +156,14 @@
}
/**
+ * @return
+ * @throws FileNotFoundException
+ */
+ public OutputStream getWritableOutputStream() throws FileNotFoundException {
+ return new FileOutputStream(file);
+ }
+
+ /**
* @see org.apache.avalon.framework.activity.Disposable#dispose()
*/
public void dispose() {
Modified: james/server/trunk/phoenix-deployment-refactor/src/main/config/james-smtphandlerchain.xml
URL: http://svn.apache.org/viewvc/james/server/trunk/phoenix-deployment-refactor/src/main/config/james-smtphandlerchain.xml?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/phoenix-deployment-refactor/src/main/config/james-smtphandlerchain.xml (original)
+++ james/server/trunk/phoenix-deployment-refactor/src/main/config/james-smtphandlerchain.xml Tue Aug 18 15:42:09 2009
@@ -20,9 +20,6 @@
<!-- Please note that this is EXPERIMENTAL and will be changed in future -->
<!-- releases -->
<handlerchain>
-<!-- Load the core filter command handlers-->
- <handler class="org.apache.james.smtpserver.core.filter.CoreFilterCmdHandlerLoader"></handler>
-
<!-- This connect handler can be used to enable POP3 before SMTP support -->
<!-- Plz note that only the ip get stored to indentify an authenticated client -->
<!-- The expireTime is the time after which an ipAddress is handled as expired -->
@@ -75,8 +72,7 @@
<!-- If checkAuthNetworks is set to true sender domain will be checked also for clients that -->
<!-- are allowed to relay. Default is false. -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.SPFHandler" command="MAIL,RCPT">
- <action> reject </action>
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.SPFHandler">
<checkAuthNetworks> false </checkAuthNetworks>
<blockSoftFail> false </blockSoftFail>
<blockPermError> true </blockPermError>
@@ -90,8 +86,7 @@
<!-- If checkAuthNetworks is set to true sender domain will be checked also for clients that -->
<!-- are allowed to relay. Default is false. -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.ResolvableEhloHeloHandler" command="EHLO,HELO,RCPT">
- <action> reject </action>
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.ResolvableEhloHeloHandler">
<checkAuthNetworks> false </checkAuthNetworks>
<checkAuthUsers> false </checkAuthUsers>
</handler>
@@ -101,8 +96,7 @@
<!-- If checkAuthNetworks is set to true sender domain will be checked also for clients that -->
<!-- are allowed to relay. Default is false. -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.ReverseEqualsEhloHeloHandler" command="EHLO,HELO">
- <action> reject </action>
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.ReverseEqualsEhloHeloHandler">
<checkAuthClients> false </checkAuthClients>
<checkAuthUsers> false </checkAuthUsers>
</handler>
@@ -113,8 +107,7 @@
<!-- If checkAuthNetworks is set to true sender domain will be checked also for clients that -->
<!-- are allowed to relay. Default is false. -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.ValidSenderDomainHandler" command="MAIL">
- <action> reject </action>
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.ValidSenderDomainHandler">
<checkAuthClients> false </checkAuthClients>
<checkAuthUsers> false </checkAuthUsers>
</handler>
@@ -125,7 +118,7 @@
<!-- You need to add the recipient to the validRecipient list if you want -->
<!-- to accept email for a recipient which not exist on the server -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.ValidRcptHandler" command="RCPT">
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.ValidRcptHandler">
<validRecipients> </validRecipients>
<validDomains> </validDomains>
<validRegexPattern> </validRegexPattern>
@@ -134,8 +127,7 @@
<!-- If activated you can limit the maximal recipients -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.MaxRcptHandler" command="RCPT">
- <action> reject </action>
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.MaxRcptHandler">
<maxRcpt> 10 </maxRcpt>
</handler>
-->
@@ -143,7 +135,7 @@
<!-- If uncomment this block you can enable greylisting. For more infos-->
<!-- how greylisting work see: http://projects.puremagic.com/greylisting/whitepaper.html -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.GreylistHandler" command="RCPT">
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.GreylistHandler">
<repositoryPath> db://maildb </repositoryPath>
<sqlFile>file://conf/sqlResources.xml</sqlFile>
<tempBlockTime> 1 hour </tempBlockTime>
@@ -158,7 +150,7 @@
<!-- Default is set to 0 (disabled). -->
<!-- You can also configure the time to sleep in milliseconds -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.TarpitHandler" command="RCPT">
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.TarpitHandler">
<tarpitRcptCount> 5 </tarpitRcptCount>
<tarpitSleepTime> 5000 </tarpitSleepTime>
</handler>
@@ -167,10 +159,11 @@
<!-- This handler ignore duplicated recipients per session. So the email will get only send on time even -->
<!-- if the recipient is specified more then once -->
<!--
- <handler class="org.apache.james.smtpserver.core.filter.fastfail.SuppressDuplicateRcptHandler" command="RCPT"/>
+ <handler class="org.apache.james.smtpserver.core.filter.fastfail.SuppressDuplicateRcptHandler"/>
-->
<!-- Load the core command handlers -->
+ <!-- Only touch this if you really know what you are doing -->
<handler class="org.apache.james.smtpserver.core.CoreCmdHandlerLoader"></handler>
<!-- The message handler configuration -->
@@ -192,7 +185,6 @@
<!-- The message get rejected if a domain matched . -->
<!--
<handler class="org.apache.james.smtpserver.core.filter.fastfail.URIRBLHandler">
- <action> reject </action>
<getDetail> true </getDetail>
<checkAuthNetworks> false </checkAuthNetworks>
<uriRblServers>
Modified: james/server/trunk/phoenix-deployment/pom.xml
URL: http://svn.apache.org/viewvc/james/server/trunk/phoenix-deployment/pom.xml?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/phoenix-deployment/pom.xml (original)
+++ james/server/trunk/phoenix-deployment/pom.xml Tue Aug 18 15:42:09 2009
@@ -208,7 +208,7 @@
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-rmi</artifactId>
- <version>1.3</version>
+ <version>1.4.1</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
@@ -219,7 +219,7 @@
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
- <version>1.3</version>
+ <version>1.4</version>
</dependency>
<dependency>
Modified: james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/CommandHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/CommandHandler.java?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/CommandHandler.java (original)
+++ james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/CommandHandler.java Tue Aug 18 15:42:09 2009
@@ -35,13 +35,13 @@
/**
* Handle the command
**/
- void onCommand(SMTPSession session);
+ SMTPResponse onCommand(SMTPSession session, String command, String parameters);
/**
* Return a Collection of implemented commands
*
* @return Collection which contains implemented commands
*/
- Collection getImplCommands();
+ Collection<String> getImplCommands();
}
Added: james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/ExtensibleHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/ExtensibleHandler.java?rev=805459&view=auto
==============================================================================
--- james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/ExtensibleHandler.java (added)
+++ james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/ExtensibleHandler.java Tue Aug 18 15:42:09 2009
@@ -0,0 +1,45 @@
+/****************************************************************
+ * 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.smtpserver;
+
+import java.util.List;
+
+/**
+ * Handlers extends this interface to be notified of available
+ * extensions of the given type.
+ */
+public interface ExtensibleHandler {
+
+ /**
+ * Return a List of interfaces of plugins that will
+ * extend this.
+ */
+ List getMarkerInterfaces();
+
+ /**
+ * Method called during initialization after all the handlers have been declared
+ * in the handlerchain.
+ *
+ * @param interfaceName
+ * @param extension a list of objects implementing the marker interface
+ */
+ void wireExtensions(Class interfaceName, List extension) throws WiringException;
+
+}
Added: james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/HandlersPackage.java
URL: http://svn.apache.org/viewvc/james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/HandlersPackage.java?rev=805459&view=auto
==============================================================================
--- james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/HandlersPackage.java (added)
+++ james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/HandlersPackage.java Tue Aug 18 15:42:09 2009
@@ -0,0 +1,40 @@
+/****************************************************************
+ * 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.smtpserver;
+
+import java.util.List;
+
+/**
+ * Provides a mean to bundle a set of handlers (defined by their classnames) within
+ * a single object.
+ * This is used for the default set of CoreCommands.
+ */
+public interface HandlersPackage {
+
+ /**
+ * Return a Map which contains a set of CommandHandlers
+ *
+ * @return Map
+ */
+ List<CommandHandler> getHandlers();
+
+}
Added: james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/LineHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/LineHandler.java?rev=805459&view=auto
==============================================================================
--- james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/LineHandler.java (added)
+++ james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/LineHandler.java Tue Aug 18 15:42:09 2009
@@ -0,0 +1,32 @@
+/****************************************************************
+ * 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.smtpserver;
+
+/**
+ * Custom line handlers must implement this interface
+ */
+public interface LineHandler {
+
+ /**
+ * Handle the command
+ **/
+ void onLine(SMTPSession session, byte[] line);
+
+}
Modified: james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java?rev=805459&r1=805458&r2=805459&view=diff
==============================================================================
--- james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java (original)
+++ james/server/trunk/smtpserver-function/src/main/java/org/apache/james/smtpserver/SMTPHandler.java Tue Aug 18 15:42:09 2009
@@ -21,26 +21,18 @@
package org.apache.james.smtpserver;
-import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.james.Constants;
-import org.apache.james.socket.CRLFTerminatedReader;
-import org.apache.james.socket.ProtocolHandler;
-import org.apache.james.socket.ProtocolHandlerHelper;
-import org.apache.james.util.watchdog.Watchdog;
-import org.apache.mailet.Mail;
-import org.apache.mailet.base.RFC822DateFormat;
-
import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Date;
import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
+import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
+import org.apache.james.socket.ProtocolHandler;
+import org.apache.james.socket.ProtocolHandlerHelper;
+import org.apache.james.util.CRLFDelimitedByteBuffer;
+import org.apache.mailet.base.RFC822DateFormat;
+
/**
* Provides SMTP functionality by carrying out the server side of the SMTP
* interaction.
@@ -49,119 +41,59 @@
*/
public class SMTPHandler implements ProtocolHandler, SMTPSession {
- private ProtocolHandlerHelper helper;
-
- /**
- * The constants to indicate the current processing mode of the session
- */
- private final static byte COMMAND_MODE = 1;
- private final static byte RESPONSE_MODE = 2;
- private final static byte MESSAGE_RECEIVED_MODE = 3;
- private final static byte MESSAGE_ABORT_MODE = 4;
-
- /**
- * SMTP Server identification string used in SMTP headers
- */
- private final static String SOFTWARE_TYPE = "JAMES SMTP Server "
- + Constants.SOFTWARE_VERSION;
-
- /**
- * Static Random instance used to generate SMTP ids
- */
- private final static Random random = new Random();
-
- /**
- * Static RFC822DateFormat used to generate date headers
- */
- private final static RFC822DateFormat rfc822DateFormat = new RFC822DateFormat();
-
- /**
- * The name of the currently parsed command
- */
- String curCommandName = null;
-
- /**
- * The value of the currently parsed command
- */
- String curCommandArgument = null;
-
- /**
- * The SMTPHandlerChain object set by SMTPServer
- */
- SMTPHandlerChain handlerChain = null;
+ private ProtocolHandlerHelper helper;
+ private boolean sessionEnded = false;
+ /**
+ * Static Random instance used to generate SMTP ids
+ */
+ private final static Random random = new Random();
+
+ /**
+ * Static RFC822DateFormat used to generate date headers
+ */
+ private final static RFC822DateFormat rfc822DateFormat = new RFC822DateFormat();
+
+ /**
+ * The name of the currently parsed command
+ */
+ String curCommandName = null;
+
+ /**
+ * The value of the currently parsed command
+ */
+ String curCommandArgument = null;
+
/**
- * The mode of the current session
- */
- private byte mode;
-
- /**
- * The MailImpl object set by the DATA command
+ * The hash map holds states which should be used in the whole connection
*/
- private Mail mail = null;
-
+ private HashMap connectionState = new HashMap();
+
/**
- * The session termination status
+ * If not null every line is sent to this command handler instead
+ * of the default "command parsing -> dipatching" procedure.
*/
- private boolean sessionEnded = false;
+ private LinkedList lineHandlers;
/**
- * The user name of the authenticated user associated with this SMTP transaction.
+ * Connect Handlers
*/
- private String authenticatedUser;
+ private LinkedList connectHandlers;
- /**
- * whether or not authorization is required for this connection
- */
- private boolean authRequired;
+ private SMTPHandlerConfigurationData theConfigData;
- /**
- * whether or not this connection can relay without authentication
- */
- private boolean relayingAllowed;
+ private boolean relayingAllowed;
- /**
- * Whether the remote Server must send HELO/EHLO
- */
- private boolean heloEhloEnforcement;
-
+ private boolean authSupported;
- /**
- * The SMTPGreeting
- */
- private String smtpGreeting = null;
-
- /**
- * The id associated with this particular SMTP interaction.
- */
- private String smtpID;
+ private SMTPHandlerChain handlerChain;
- /**
- * The per-service configuration data that applies to all handlers
- */
- private SMTPHandlerConfigurationData theConfigData;
+ private String authenticatedUser;
- /**
- * The hash map that holds variables for the SMTP 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();
+ private String smtpID;
- /**
- * The hash map holds states which should be used in the whole connection
- */
- private HashMap connectionState = new HashMap();
-
- /**
- * The per-handler response buffer used to marshal responses.
- */
- private StringBuffer responseBuffer = new StringBuffer(256);
-
- private boolean stopHandlerProcessing = false;
+
/**
* Set the configuration data for the handler
@@ -176,36 +108,19 @@
}
}
- /**
- * @see org.apache.james.socket.AbstractJamesHandler#handleProtocol()
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.socket.ProtocolHandler#handleProtocol()
*/
public void handleProtocol() throws IOException {
smtpID = random.nextInt(1024) + "";
relayingAllowed = theConfigData.isRelayingAllowed(helper.getRemoteIP());
- authRequired = theConfigData.isAuthRequired(helper.getRemoteIP());
- heloEhloEnforcement = theConfigData.useHeloEhloEnforcement();
- sessionEnded = false;
- smtpGreeting = theConfigData.getSMTPGreeting();
- resetState();
- resetConnectionState();
+ authSupported = theConfigData.isAuthRequired(helper.getRemoteIP());
- // if no greeting was configured use a default
- if (smtpGreeting == null) {
- // Initially greet the connector
- // Format is: Sat, 24 Jan 1998 13:16:09 -0500
-
- responseBuffer.append("220 ")
- .append(theConfigData.getHelloName())
- .append(" SMTP Server (")
- .append(SOFTWARE_TYPE)
- .append(") ready ")
- .append(rfc822DateFormat.format(new Date()));
- } else {
- responseBuffer.append("220 ")
- .append(smtpGreeting);
- }
- String responseString = clearResponseBuffer();
- helper.writeLoggedFlushedResponse(responseString);
+ // Both called in resetHandler, we don't need to call them again here.
+ // sessionEnded = false;
+ // resetState();
+ // resetConnectionState();
//the core in-protocol handling logic
//run all the connection handlers, if it fast fails, end the session
@@ -233,7 +148,6 @@
//message will not spooled.
//Session started - RUN all connect handlers
- List connectHandlers = handlerChain.getConnectHandlers();
if(connectHandlers != null) {
int count = connectHandlers.size();
for(int i = 0; i < count; i++) {
@@ -244,95 +158,80 @@
}
}
+ CRLFDelimitedByteBuffer bytebufferHandler = new CRLFDelimitedByteBuffer(helper.getInputStream());
helper.getWatchdog().start();
while(!sessionEnded) {
- //Reset the current command values
- curCommandName = null;
- curCommandArgument = null;
- mode = COMMAND_MODE;
-
//parse the command
- String cmdString = readCommandLine();
- if (cmdString == null) {
- break;
+ byte[] line = null;
+ try {
+ line = bytebufferHandler.read();
+ } catch (CRLFDelimitedByteBuffer.TerminationException e) {
+ writeSMTPResponse(new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS, "Syntax error at character position " + e.position() + ". CR and LF must be CRLF paired. See RFC 2821 #2.7.1."));
+ } catch (CRLFDelimitedByteBuffer.LineLengthExceededException e) {
+ writeSMTPResponse(new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_COMMAND_UNRECOGNIZED, "Line length exceeded. See RFC 2821 #4.5.3.1."));
}
- int spaceIndex = cmdString.indexOf(" ");
- if (spaceIndex > 0) {
- curCommandName = cmdString.substring(0, spaceIndex);
- curCommandArgument = cmdString.substring(spaceIndex + 1);
- } else {
- curCommandName = cmdString;
- }
- curCommandName = curCommandName.toUpperCase(Locale.US);
-
- //fetch the command handlers registered to the command
- List commandHandlers = handlerChain.getCommandHandlers(curCommandName);
- if(commandHandlers == null) {
- //end the session
+ if (line == null) {
break;
- } else {
- int count = commandHandlers.size();
- for(int i = 0; i < count; i++) {
- setStopHandlerProcessing(false);
- ((CommandHandler)commandHandlers.get(i)).onCommand(this);
-
- helper.getWatchdog().reset();
-
- //if the response is received, stop processing of command handlers
- if(mode != COMMAND_MODE || getStopHandlerProcessing()) {
- break;
- }
- }
-
}
- //handle messages
- if(mode == MESSAGE_RECEIVED_MODE) {
- try {
- helper.getAvalonLogger().debug("executing message handlers");
- List messageHandlers = handlerChain.getMessageHandlers();
- int count = messageHandlers.size();
- for(int i =0; i < count; i++) {
- ((MessageHandler)messageHandlers.get(i)).onMessage(this);
- //if the response is received, stop processing of command handlers
- if(mode == MESSAGE_ABORT_MODE) {
- break;
- }
- }
- } finally {
- //do the clean up
- if(mail != null) {
- ContainerUtil.dispose(mail);
-
- // remember the ehlo mode
- Object currentHeloMode = state.get(CURRENT_HELO_MODE);
-
- mail = null;
- resetState();
-
- // start again with the old helo mode
- if (currentHeloMode != null) {
- state.put(CURRENT_HELO_MODE,currentHeloMode);
- }
- }
- }
+ if (lineHandlers.size() > 0) {
+ ((LineHandler) lineHandlers.getLast()).onLine(this, line);
+ } else {
+ sessionEnded = true;
}
+ helper.getWatchdog().reset();
+
}
helper.getWatchdog().stop();
helper.getAvalonLogger().debug("Closing socket.");
}
/**
+ * @see org.apache.james.smtpserver.SMTPSession#writeSMTPResponse(org.apache.james.smtpserver.SMTPResponse)
+ */
+ public void writeSMTPResponse(SMTPResponse response) {
+ // Write a single-line or multiline response
+ if (response != null) {
+ if (response.getRawLine() != null) {
+ helper.writeLoggedFlushedResponse(response.getRawLine());
+ } else {
+ // Iterator i = esmtpextensions.iterator();
+ for (int k = 0; k < response.getLines().size(); k++) {
+ StringBuffer respBuff = new StringBuffer(256);
+ respBuff.append(response.getRetCode());
+ if (k == response.getLines().size() - 1) {
+ respBuff.append(" ");
+ respBuff.append(response.getLines().get(k));
+ helper.writeLoggedFlushedResponse(respBuff.toString());
+ } else {
+ respBuff.append("-");
+ respBuff.append(response.getLines().get(k));
+ helper.writeLoggedResponse(respBuff.toString());
+ }
+ }
+ }
+
+ if (response.isEndSession()) {
+ sessionEnded = true;
+ }
+ }
+ }
+
+ /**
* Resets the handler data to a basic state.
*/
public void resetHandler() {
- resetState();
+ // not needed anymore because state is inside the connection state
+ // resetState();
resetConnectionState();
- clearResponseBuffer();
+ // empty any previous line handler and add self (command dispatcher)
+ // as the default.
+ lineHandlers = handlerChain.getHandlers(LineHandler.class);
authenticatedUser = null;
smtpID = null;
+ sessionEnded = false;
}
/**
@@ -342,47 +241,10 @@
*/
public void setHandlerChain(SMTPHandlerChain handlerChain) {
this.handlerChain = handlerChain;
+ connectHandlers = handlerChain.getHandlers(ConnectHandler.class);
+ lineHandlers = handlerChain.getHandlers(LineHandler.class);
}
- /**
- * @see org.apache.james.smtpserver.SMTPSession#writeResponse(String)
- */
- public void writeResponse(String respString) {
- helper.writeLoggedFlushedResponse(respString);
- //TODO Explain this well
- if(mode == COMMAND_MODE) {
- mode = RESPONSE_MODE;
- }
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#getCommandName()
- */
- public String getCommandName() {
- return curCommandName;
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#getCommandArgument()
- */
- public String getCommandArgument() {
- return curCommandArgument;
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#getMail()
- */
- public Mail getMail() {
- return mail;
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#setMail(Mail)
- */
- public void setMail(Mail mail) {
- this.mail = mail;
- this.mode = MESSAGE_RECEIVED_MODE;
- }
/**
* @see org.apache.james.smtpserver.SMTPSession#getRemoteHost()
@@ -399,35 +261,36 @@
}
/**
- * @see org.apache.james.smtpserver.SMTPSession#endSession()
- */
- public void endSession() {
- sessionEnded = true;
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#isSessionEnded()
- */
- public boolean isSessionEnded() {
- return sessionEnded;
- }
-
- /**
* @see org.apache.james.smtpserver.SMTPSession#resetState()
*/
public void resetState() {
- ArrayList recipients = (ArrayList)state.get(RCPT_LIST);
- if (recipients != null) {
- recipients.clear();
+ // remember the ehlo mode between resets
+ Object currentHeloMode = getState().get(CURRENT_HELO_MODE);
+
+ getState().clear();
+
+ // start again with the old helo mode
+ if (currentHeloMode != null) {
+ getState().put(CURRENT_HELO_MODE,currentHeloMode);
}
- state.clear();
}
/**
+ * The hash map that holds variables for the SMTP 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.
+ *
* @see org.apache.james.smtpserver.SMTPSession#getState()
*/
public Map getState() {
- return state;
+ Object res = getConnectionState().get(SMTPSession.SESSION_STATE_MAP);
+ if (res == null || !(res instanceof Map)) {
+ res = new HashMap();
+ getConnectionState().put(SMTPSession.SESSION_STATE_MAP, res);
+ }
+ return (Map) res;
}
/**
@@ -451,19 +314,13 @@
}
/**
- * @see org.apache.james.smtpserver.SMTPSession#isAuthRequired()
+ * @see org.apache.james.smtpserver.SMTPSession#isAuthSupported()
*/
- public boolean isAuthRequired() {
- return authRequired;
+ public boolean isAuthSupported() {
+ return authSupported;
}
/**
- * @see org.apache.james.smtpserver.SMTPSession#useHeloEhloEnforcement()
- */
- public boolean useHeloEhloEnforcement() {
- return heloEhloEnforcement;
- }
- /**
* @see org.apache.james.smtpserver.SMTPSession#getUser()
*/
public String getUser() {
@@ -478,66 +335,11 @@
}
/**
- * @see org.apache.james.smtpserver.SMTPSession#getResponseBuffer()
- */
- public StringBuffer getResponseBuffer() {
- return responseBuffer;
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#clearResponseBuffer()
- */
- public String clearResponseBuffer() {
- String responseString = responseBuffer.toString();
- responseBuffer.delete(0,responseBuffer.length());
- return responseString;
- }
-
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#readCommandLine()
- */
- public final String readCommandLine() throws IOException {
- for (;;) try {
- String commandLine = helper.getInputReader().readLine();
- if (commandLine != null) {
- commandLine = commandLine.trim();
- }
- return commandLine;
- } catch (CRLFTerminatedReader.TerminationException te) {
- helper.writeLoggedFlushedResponse("501 Syntax error at character position " + te.position() + ". CR and LF must be CRLF paired. See RFC 2821 #2.7.1.");
- } catch (CRLFTerminatedReader.LineLengthExceededException llee) {
- helper.writeLoggedFlushedResponse("500 Line length exceeded. See RFC 2821 #4.5.3.1.");
- }
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#getWatchdog()
- */
- public Watchdog getWatchdog() {
- return helper.getWatchdog();
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#getInputStream()
- */
- public InputStream getInputStream() {
- return helper.getInputStream();
- }
-
- /**
* @see org.apache.james.smtpserver.SMTPSession#getSessionID()
*/
public String getSessionID() {
return smtpID;
}
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#abortMessage()
- */
- public void abortMessage() {
- mode = MESSAGE_ABORT_MODE;
- }
/**
* @see org.apache.james.smtpserver.SMTPSession#getRcptCount()
@@ -546,41 +348,60 @@
int count = 0;
// check if the key exists
- if (state.get(SMTPSession.RCPT_LIST) != null) {
- count = ((Collection) state.get(SMTPSession.RCPT_LIST)).size();
+ if (getState().get(SMTPSession.RCPT_LIST) != null) {
+ count = ((Collection) getState().get(SMTPSession.RCPT_LIST)).size();
}
return count;
}
- /**
- * @see org.apache.james.smtpserver.SMTPSession#setStopHandlerProcessing(boolean)
- */
- public void setStopHandlerProcessing(boolean stopHandlerProcessing) {
- this.stopHandlerProcessing = stopHandlerProcessing;
- }
-
- /**
- * @see org.apache.james.smtpserver.SMTPSession#getStopHandlerProcessing()
- */
- public boolean getStopHandlerProcessing() {
- return stopHandlerProcessing;
- }
-
public void resetConnectionState() {
connectionState.clear();
}
+ /**
+ * @see org.apache.james.smtpserver.SMTPSession#getConnectionState()
+ */
public Map getConnectionState() {
return connectionState;
}
- public void setProtocolHandlerHelper(ProtocolHandlerHelper phh) {
- this.helper = phh;
+ /**
+ * @see org.apache.james.smtpserver.SMTPSession#popLineHandler()
+ */
+ public void popLineHandler() {
+ if (lineHandlers != null) {
+ lineHandlers.removeLast();
+ }
}
- public void errorHandler(RuntimeException e) {
- helper.defaultErrorHandler(e);
+ /**
+ * @see org.apache.james.smtpserver.SMTPSession#pushLineHandler(org.apache.james.smtpserver.LineHandler)
+ */
+ public void pushLineHandler(LineHandler lineHandler) {
+ if (lineHandlers == null) {
+ lineHandlers = new LinkedList();
+ }
+ lineHandlers.addLast(lineHandler);
+ }
+
+ /**
+ * @see org.apache.james.smtpserver.SMTPSession#sleep(long)
+ */
+ public void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
+ public void errorHandler(RuntimeException e) {
+ helper.defaultErrorHandler(e);
+ }
+
+ public void setProtocolHandlerHelper(ProtocolHandlerHelper phh) {
+ helper = phh;
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org