logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rgo...@apache.org
Subject svn commit: r1426989 - in /logging/log4j/log4j2/trunk/core: ./ src/test/java/org/apache/dumbster/ src/test/java/org/apache/logging/dumbster/ src/test/java/org/apache/logging/dumbster/smtp/ src/test/java/org/apache/logging/log4j/core/appender/
Date Sun, 30 Dec 2012 21:08:06 GMT
Author: rgoers
Date: Sun Dec 30 21:08:05 2012
New Revision: 1426989

URL: http://svn.apache.org/viewvc?rev=1426989&view=rev
Log:
Add dumbster classes to project and fix race condition

Added:
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/dumbster/
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SimpleSmtpServer.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpActionType.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpMessage.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpRequest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpResponse.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpState.java
Modified:
    logging/log4j/log4j2/trunk/core/pom.xml
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java

Modified: logging/log4j/log4j2/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/pom.xml?rev=1426989&r1=1426988&r2=1426989&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/pom.xml (original)
+++ logging/log4j/log4j2/trunk/core/pom.xml Sun Dec 30 21:08:05 2012
@@ -109,11 +109,6 @@
       <artifactId>mail</artifactId>
       <optional>true</optional>
     </dependency>
-    <dependency>
-	  <groupId>dumbster</groupId>
-	    <artifactId>dumbster</artifactId>
-	    <scope>test</scope>
-    </dependency>
   </dependencies>
   <build>
     <plugins>

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SimpleSmtpServer.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SimpleSmtpServer.java?rev=1426989&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SimpleSmtpServer.java
(added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SimpleSmtpServer.java
Sun Dec 30 21:08:05 2012
@@ -0,0 +1,276 @@
+/*
+ * 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.logging.dumbster.smtp;
+
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.IOException;
+
+/**
+ * Dummy SMTP server for testing purposes.
+ *
+ * @todo constructor allowing user to pass preinitialized ServerSocket
+ */
+public class SimpleSmtpServer implements Runnable {
+    /**
+     * Stores all of the email received since this instance started up.
+     */
+    private List receivedMail;
+
+    /**
+     * Default SMTP port is 25.
+     */
+    public static final int DEFAULT_SMTP_PORT = 25;
+
+    /**
+     * Indicates whether this server is stopped or not.
+     */
+    private volatile boolean stopped = true;
+
+    /**
+     * Handle to the server socket this server listens to.
+     */
+    private ServerSocket serverSocket;
+
+    /**
+     * Port the server listens on - set to the default SMTP port initially.
+     */
+    private int port = DEFAULT_SMTP_PORT;
+
+    /**
+     * Timeout listening on server socket.
+     */
+    private static final int TIMEOUT = 500;
+
+    /**
+     * Constructor.
+     *
+     * @param port port number
+     */
+    public SimpleSmtpServer(int port) {
+        receivedMail = new ArrayList();
+        this.port = port;
+    }
+
+    /**
+     * Main loop of the SMTP server.
+     */
+    public void run() {
+        stopped = false;
+        try {
+            try {
+                serverSocket = new ServerSocket(port);
+                serverSocket.setSoTimeout(TIMEOUT); // Block for maximum of 1.5 seconds
+            } finally {
+                synchronized (this) {
+                    // Notify when server socket has been created
+                    notifyAll();
+                }
+            }
+
+            // Server: loop until stopped
+            while (!isStopped()) {
+                // Start server socket and listen for client connections
+                Socket socket = null;
+                try {
+                    socket = serverSocket.accept();
+                } catch (Exception e) {
+                    if (socket != null) {
+                        socket.close();
+                    }
+                    continue; // Non-blocking socket timeout occurred: try accept() again
+                }
+
+                // Get the input and output streams
+                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+                PrintWriter out = new PrintWriter(socket.getOutputStream());
+
+                synchronized (this) {
+          /*
+           * We synchronize over the handle method and the list update because the client
call completes inside
+           * the handle method and we have to prevent the client from reading the list until
we've updated it.
+           * For higher concurrency, we could just change handle to return void and update
the list inside the method
+           * to limit the duration that we hold the lock.
+           */
+                    List msgs = handleTransaction(out, input);
+                    receivedMail.addAll(msgs);
+                }
+                socket.close();
+            }
+        } catch (Exception e) {
+            /** @todo Should throw an appropriate exception here. */
+            e.printStackTrace();
+        } finally {
+            if (serverSocket != null) {
+                try {
+                    serverSocket.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * Check if the server has been placed in a stopped state. Allows another thread to
+     * stop the server safely.
+     *
+     * @return true if the server has been sent a stop signal, false otherwise
+     */
+    public synchronized boolean isStopped() {
+        return stopped;
+    }
+
+    /**
+     * Stops the server. Server is shutdown after processing of the current request is complete.
+     */
+    public synchronized void stop() {
+        // Mark us closed
+        stopped = true;
+        try {
+            // Kick the server accept loop
+            serverSocket.close();
+        } catch (IOException e) {
+            // Ignore
+        }
+    }
+
+    /**
+     * Handle an SMTP transaction, i.e. all activity between initial connect and QUIT command.
+     *
+     * @param out   output stream
+     * @param input input stream
+     * @return List of SmtpMessage
+     * @throws IOException
+     */
+    private List handleTransaction(PrintWriter out, BufferedReader input) throws IOException
{
+        // Initialize the state machine
+        SmtpState smtpState = SmtpState.CONNECT;
+        SmtpRequest smtpRequest = new SmtpRequest(SmtpActionType.CONNECT, "", smtpState);
+
+        // Execute the connection request
+        SmtpResponse smtpResponse = smtpRequest.execute();
+
+        // Send initial response
+        sendResponse(out, smtpResponse);
+        smtpState = smtpResponse.getNextState();
+
+        List msgList = new ArrayList();
+        SmtpMessage msg = new SmtpMessage();
+
+        while (smtpState != SmtpState.CONNECT) {
+            String line = input.readLine();
+
+            if (line == null) {
+                break;
+            }
+
+            // Create request from client input and current state
+            SmtpRequest request = SmtpRequest.createRequest(line, smtpState);
+            // Execute request and create response object
+            SmtpResponse response = request.execute();
+            // Move to next internal state
+            smtpState = response.getNextState();
+            // Send reponse to client
+            sendResponse(out, response);
+
+            // Store input in message
+            String params = request.getParams();
+            msg.store(response, params);
+
+            // If message reception is complete save it
+            if (smtpState == SmtpState.QUIT) {
+                msgList.add(msg);
+                msg = new SmtpMessage();
+            }
+        }
+
+        return msgList;
+    }
+
+    /**
+     * Send response to client.
+     *
+     * @param out          socket output stream
+     * @param smtpResponse response object
+     */
+    private static void sendResponse(PrintWriter out, SmtpResponse smtpResponse) {
+        if (smtpResponse.getCode() > 0) {
+            int code = smtpResponse.getCode();
+            String message = smtpResponse.getMessage();
+            out.print(code + " " + message + "\r\n");
+            out.flush();
+        }
+    }
+
+    /**
+     * Get email received by this instance since start up.
+     *
+     * @return List of String
+     */
+    public synchronized Iterator getReceivedEmail() {
+        return receivedMail.iterator();
+    }
+
+    /**
+     * Get the number of messages received.
+     *
+     * @return size of received email list
+     */
+    public synchronized int getReceivedEmailSize() {
+        return receivedMail.size();
+    }
+
+    /**
+     * Creates an instance of SimpleSmtpServer and starts it. Will listen on the default
port.
+     *
+     * @return a reference to the SMTP server
+     */
+    public static SimpleSmtpServer start() {
+        return start(DEFAULT_SMTP_PORT);
+    }
+
+    /**
+     * Creates an instance of SimpleSmtpServer and starts it.
+     *
+     * @param port port number the server should listen to
+     * @return a reference to the SMTP server
+     */
+    public static SimpleSmtpServer start(int port) {
+        SimpleSmtpServer server = new SimpleSmtpServer(port);
+        Thread t = new Thread(server);
+
+
+        // Block until the server socket is created
+        synchronized (server) {
+            t.start();
+            try {
+                server.wait();
+            } catch (InterruptedException e) {
+                // Ignore don't care.
+            }
+        }
+        return server;
+    }
+
+}

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpActionType.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpActionType.java?rev=1426989&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpActionType.java
(added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpActionType.java
Sun Dec 30 21:08:05 2012
@@ -0,0 +1,201 @@
+/*
+ * 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.logging.dumbster.smtp;
+
+/**
+ * Represents an SMTP action or command.
+ */
+public class SmtpActionType {
+    /**
+     * Internal value for the action type.
+     */
+    private byte value;
+
+    /**
+     * Internal representation of the CONNECT action.
+     */
+    private static final byte CONNECT_BYTE = (byte) 1;
+    /**
+     * Internal representation of the EHLO action.
+     */
+    private static final byte EHLO_BYTE = (byte) 2;
+    /**
+     * Internal representation of the MAIL FROM action.
+     */
+    private static final byte MAIL_BYTE = (byte) 3;
+    /**
+     * Internal representation of the RCPT action.
+     */
+    private static final byte RCPT_BYTE = (byte) 4;
+    /**
+     * Internal representation of the DATA action.
+     */
+    private static final byte DATA_BYTE = (byte) 5;
+    /**
+     * Internal representation of the DATA END (.) action.
+     */
+    private static final byte DATA_END_BYTE = (byte) 6;
+    /**
+     * Internal representation of the QUIT action.
+     */
+    private static final byte QUIT_BYTE = (byte) 7;
+    /**
+     * Internal representation of an unrecognized action: body text gets this action type.
+     */
+    private static final byte UNREC_BYTE = (byte) 8;
+    /**
+     * Internal representation of the blank line action: separates headers and body text.
+     */
+    private static final byte BLANK_LINE_BYTE = (byte) 9;
+
+    /**
+     * Internal representation of the stateless RSET action.
+     */
+    private static final byte RSET_BYTE = (byte) -1;
+    /**
+     * Internal representation of the stateless VRFY action.
+     */
+    private static final byte VRFY_BYTE = (byte) -2;
+    /**
+     * Internal representation of the stateless EXPN action.
+     */
+    private static final byte EXPN_BYTE = (byte) -3;
+    /**
+     * Internal representation of the stateless HELP action.
+     */
+    private static final byte HELP_BYTE = (byte) -4;
+    /**
+     * Internal representation of the stateless NOOP action.
+     */
+    private static final byte NOOP_BYTE = (byte) -5;
+
+    /**
+     * CONNECT action.
+     */
+    public static final SmtpActionType CONNECT = new SmtpActionType(CONNECT_BYTE);
+    /**
+     * EHLO action.
+     */
+    public static final SmtpActionType EHLO = new SmtpActionType(EHLO_BYTE);
+    /**
+     * MAIL action.
+     */
+    public static final SmtpActionType MAIL = new SmtpActionType(MAIL_BYTE);
+    /**
+     * RCPT action.
+     */
+    public static final SmtpActionType RCPT = new SmtpActionType(RCPT_BYTE);
+    /**
+     * DATA action.
+     */
+    public static final SmtpActionType DATA = new SmtpActionType(DATA_BYTE);
+    /**
+     * "." action.
+     */
+    public static final SmtpActionType DATA_END = new SmtpActionType(DATA_END_BYTE);
+    /**
+     * Body text action.
+     */
+    public static final SmtpActionType UNRECOG = new SmtpActionType(UNREC_BYTE);
+    /**
+     * QUIT action.
+     */
+    public static final SmtpActionType QUIT = new SmtpActionType(QUIT_BYTE);
+    /**
+     * Header/body separator action.
+     */
+    public static final SmtpActionType BLANK_LINE = new SmtpActionType(BLANK_LINE_BYTE);
+
+    /**
+     * Stateless RSET action.
+     */
+    public static final SmtpActionType RSET = new SmtpActionType(RSET_BYTE);
+    /**
+     * Stateless VRFY action.
+     */
+    public static final SmtpActionType VRFY = new SmtpActionType(VRFY_BYTE);
+    /**
+     * Stateless EXPN action.
+     */
+    public static final SmtpActionType EXPN = new SmtpActionType(EXPN_BYTE);
+    /**
+     * Stateless HELP action.
+     */
+    public static final SmtpActionType HELP = new SmtpActionType(HELP_BYTE);
+    /**
+     * Stateless NOOP action.
+     */
+    public static final SmtpActionType NOOP = new SmtpActionType(NOOP_BYTE);
+
+    /**
+     * Create a new SMTP action type. Private to ensure no invalid values.
+     *
+     * @param value one of the _BYTE values
+     */
+    private SmtpActionType(byte value) {
+        this.value = value;
+    }
+
+    /**
+     * Indicates whether the action is stateless or not.
+     *
+     * @return true iff the action is stateless
+     */
+    public boolean isStateless() {
+        return value < 0;
+    }
+
+    /**
+     * String representation of this SMTP action type.
+     *
+     * @return a String
+     */
+    public String toString() {
+        switch (value) {
+            case CONNECT_BYTE:
+                return "Connect";
+            case EHLO_BYTE:
+                return "EHLO";
+            case MAIL_BYTE:
+                return "MAIL";
+            case RCPT_BYTE:
+                return "RCPT";
+            case DATA_BYTE:
+                return "DATA";
+            case DATA_END_BYTE:
+                return ".";
+            case QUIT_BYTE:
+                return "QUIT";
+            case RSET_BYTE:
+                return "RSET";
+            case VRFY_BYTE:
+                return "VRFY";
+            case EXPN_BYTE:
+                return "EXPN";
+            case HELP_BYTE:
+                return "HELP";
+            case NOOP_BYTE:
+                return "NOOP";
+            case UNREC_BYTE:
+                return "Unrecognized command / data";
+            case BLANK_LINE_BYTE:
+                return "Blank line";
+            default:
+                return "Unknown";
+        }
+    }
+}

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpMessage.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpMessage.java?rev=1426989&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpMessage.java
(added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpMessage.java
Sun Dec 30 21:08:05 2012
@@ -0,0 +1,156 @@
+/*
+ * 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.logging.dumbster.smtp;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * Container for a complete SMTP message - headers and message body.
+ */
+public class SmtpMessage {
+    /**
+     * Headers: Map of List of String hashed on header name.
+     */
+    private Map headers;
+    /**
+     * Message body.
+     */
+    private StringBuffer body;
+
+    /**
+     * Constructor. Initializes headers Map and body buffer.
+     */
+    public SmtpMessage() {
+        headers = new HashMap(10);
+        body = new StringBuffer();
+    }
+
+    /**
+     * Update the headers or body depending on the SmtpResponse object and line of input.
+     *
+     * @param response SmtpResponse object
+     * @param params   remainder of input line after SMTP command has been removed
+     */
+    public void store(SmtpResponse response, String params) {
+        if (params != null) {
+            if (SmtpState.DATA_HDR.equals(response.getNextState())) {
+                int headerNameEnd = params.indexOf(':');
+                if (headerNameEnd >= 0) {
+                    String name = params.substring(0, headerNameEnd).trim();
+                    String value = params.substring(headerNameEnd + 1).trim();
+                    addHeader(name, value);
+                }
+            } else if (SmtpState.DATA_BODY == response.getNextState()) {
+                body.append(params);
+            }
+        }
+    }
+
+    /**
+     * Get an Iterator over the header names.
+     *
+     * @return an Iterator over the set of header names (String)
+     */
+    public Iterator getHeaderNames() {
+        Set nameSet = headers.keySet();
+        return nameSet.iterator();
+    }
+
+    /**
+     * Get the value(s) associated with the given header name.
+     *
+     * @param name header name
+     * @return value(s) associated with the header name
+     */
+    public String[] getHeaderValues(String name) {
+        List values = (List) headers.get(name);
+        if (values == null) {
+            return new String[0];
+        } else {
+            return (String[]) values.toArray(new String[0]);
+        }
+    }
+
+    /**
+     * Get the first values associated with a given header name.
+     *
+     * @param name header name
+     * @return first value associated with the header name
+     */
+    public String getHeaderValue(String name) {
+        List values = (List) headers.get(name);
+        if (values == null) {
+            return null;
+        } else {
+            Iterator iterator = values.iterator();
+            return (String) iterator.next();
+        }
+    }
+
+    /**
+     * Get the message body.
+     *
+     * @return message body
+     */
+    public String getBody() {
+        return body.toString();
+    }
+
+    /**
+     * Adds a header to the Map.
+     *
+     * @param name  header name
+     * @param value header value
+     */
+    private void addHeader(String name, String value) {
+        List valueList = (List) headers.get(name);
+        if (valueList == null) {
+            valueList = new ArrayList(1);
+            headers.put(name, valueList);
+        }
+        valueList.add(value);
+    }
+
+    /**
+     * String representation of the SmtpMessage.
+     *
+     * @return a String
+     */
+    public String toString() {
+        StringBuffer msg = new StringBuffer();
+        for (Iterator i = headers.keySet().iterator(); i.hasNext(); ) {
+            String name = (String) i.next();
+            List values = (List) headers.get(name);
+            for (Iterator j = values.iterator(); j.hasNext(); ) {
+                String value = (String) j.next();
+                msg.append(name);
+                msg.append(": ");
+                msg.append(value);
+                msg.append('\n');
+            }
+        }
+        msg.append('\n');
+        msg.append(body);
+        msg.append('\n');
+        return msg.toString();
+    }
+}

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpRequest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpRequest.java?rev=1426989&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpRequest.java
(added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpRequest.java
Sun Dec 30 21:08:05 2012
@@ -0,0 +1,230 @@
+/*
+ * 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.logging.dumbster.smtp;
+
+/**
+ * Contains an SMTP client request. Handles state transitions using the following state transition
table.
+ * <PRE>
+ * -----------+-------------------------------------------------------------------------------------------------
+ * |                                 State
+ * Action    +-------------+-----------+-----------+--------------+---------------+---------------+------------
+ * | CONNECT     | GREET     | MAIL      | RCPT         | DATA_HDR      | DATA_BODY     |
QUIT
+ * -----------+-------------+-----------+-----------+--------------+---------------+---------------+------------
+ * connect    | 220/GREET   | 503/GREET | 503/MAIL  | 503/RCPT     | 503/DATA_HDR  | 503/DATA_BODY
| 503/QUIT
+ * ehlo       | 503/CONNECT | 250/MAIL  | 503/MAIL  | 503/RCPT     | 503/DATA_HDR  | 503/DATA_BODY
| 503/QUIT
+ * mail       | 503/CONNECT | 503/GREET | 250/RCPT  | 503/RCPT     | 503/DATA_HDR  | 503/DATA_BODY
| 250/RCPT
+ * rcpt       | 503/CONNECT | 503/GREET | 503/MAIL  | 250/RCPT     | 503/DATA_HDR  | 503/DATA_BODY
| 503/QUIT
+ * data       | 503/CONNECT | 503/GREET | 503/MAIL  | 354/DATA_HDR | 503/DATA_HDR  | 503/DATA_BODY
| 503/QUIT
+ * data_end   | 503/CONNECT | 503/GREET | 503/MAIL  | 503/RCPT     | 250/QUIT      | 250/QUIT
     | 503/QUIT
+ * unrecog    | 500/CONNECT | 500/GREET | 500/MAIL  | 500/RCPT     | ---/DATA_HDR  | ---/DATA_BODY
| 500/QUIT
+ * quit       | 503/CONNECT | 503/GREET | 503/MAIL  | 503/RCPT     | 503/DATA_HDR  | 503/DATA_BODY
| 250/CONNECT
+ * blank_line | 503/CONNECT | 503/GREET | 503/MAIL  | 503/RCPT     | ---/DATA_BODY | ---/DATA_BODY
| 503/QUIT
+ * rset       | 250/GREET   | 250/GREET | 250/GREET | 250/GREET    | 250/GREET     | 250/GREET
    | 250/GREET
+ * vrfy       | 252/CONNECT | 252/GREET | 252/MAIL  | 252/RCPT     | 252/DATA_HDR  | 252/DATA_BODY
| 252/QUIT
+ * expn       | 252/CONNECT | 252/GREET | 252/MAIL  | 252/RCPT     | 252/DATA_HDR  | 252/DATA_BODY
| 252/QUIT
+ * help       | 211/CONNECT | 211/GREET | 211/MAIL  | 211/RCPT     | 211/DATA_HDR  | 211/DATA_BODY
| 211/QUIT
+ * noop       | 250/CONNECT | 250/GREET | 250/MAIL  | 250/RCPT     | 250|DATA_HDR  | 250/DATA_BODY
| 250/QUIT
+ * </PRE>
+ */
+public class SmtpRequest {
+    /**
+     * SMTP action received from client.
+     */
+    private SmtpActionType action;
+    /**
+     * Current state of the SMTP state table.
+     */
+    private SmtpState state;
+    /**
+     * Additional information passed from the client with the SMTP action.
+     */
+    private String params;
+
+    /**
+     * Create a new SMTP client request.
+     *
+     * @param actionType type of action/command
+     * @param params     remainder of command line once command is removed
+     * @param state      current SMTP server state
+     */
+    public SmtpRequest(SmtpActionType actionType, String params, SmtpState state) {
+        this.action = actionType;
+        this.state = state;
+        this.params = params;
+    }
+
+    /**
+     * Execute the SMTP request returning a response. This method models the state transition
table for the SMTP server.
+     *
+     * @return reponse to the request
+     */
+    public SmtpResponse execute() {
+        SmtpResponse response = null;
+        if (action.isStateless()) {
+            if (SmtpActionType.EXPN == action || SmtpActionType.VRFY == action) {
+                response = new SmtpResponse(252, "Not supported", this.state);
+            } else if (SmtpActionType.HELP == action) {
+                response = new SmtpResponse(211, "No help available", this.state);
+            } else if (SmtpActionType.NOOP == action) {
+                response = new SmtpResponse(250, "OK", this.state);
+            } else if (SmtpActionType.VRFY == action) {
+                response = new SmtpResponse(252, "Not supported", this.state);
+            } else if (SmtpActionType.RSET == action) {
+                response = new SmtpResponse(250, "OK", SmtpState.GREET);
+            } else {
+                response = new SmtpResponse(500, "Command not recognized", this.state);
+            }
+        } else { // Stateful commands
+            if (SmtpActionType.CONNECT == action) {
+                if (SmtpState.CONNECT == state) {
+                    response = new SmtpResponse(220, "localhost Dumbster SMTP service ready",
SmtpState.GREET);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else if (SmtpActionType.EHLO == action) {
+                if (SmtpState.GREET == state) {
+                    response = new SmtpResponse(250, "OK", SmtpState.MAIL);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else if (SmtpActionType.MAIL == action) {
+                if (SmtpState.MAIL == state || SmtpState.QUIT == state) {
+                    response = new SmtpResponse(250, "OK", SmtpState.RCPT);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else if (SmtpActionType.RCPT == action) {
+                if (SmtpState.RCPT == state) {
+                    response = new SmtpResponse(250, "OK", this.state);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else if (SmtpActionType.DATA == action) {
+                if (SmtpState.RCPT == state) {
+                    response = new SmtpResponse(354, "Start mail input; end with <CRLF>.<CRLF>",
SmtpState.DATA_HDR);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else if (SmtpActionType.UNRECOG == action) {
+                if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
+                    response = new SmtpResponse(-1, "", this.state);
+                } else {
+                    response = new SmtpResponse(500, "Command not recognized", this.state);
+                }
+            } else if (SmtpActionType.DATA_END == action) {
+                if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
+                    response = new SmtpResponse(250, "OK", SmtpState.QUIT);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else if (SmtpActionType.BLANK_LINE == action) {
+                if (SmtpState.DATA_HDR == state) {
+                    response = new SmtpResponse(-1, "", SmtpState.DATA_BODY);
+                } else if (SmtpState.DATA_BODY == state) {
+                    response = new SmtpResponse(-1, "", this.state);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else if (SmtpActionType.QUIT == action) {
+                if (SmtpState.QUIT == state) {
+                    response = new SmtpResponse(221, "localhost Dumbster service closing
transmission channel",
+                        SmtpState.CONNECT);
+                } else {
+                    response = new SmtpResponse(503, "Bad sequence of commands: " + action,
this.state);
+                }
+            } else {
+                response = new SmtpResponse(500, "Command not recognized", this.state);
+            }
+        }
+        return response;
+    }
+
+    /**
+     * Create an SMTP request object given a line of the input stream from the client and
the current internal state.
+     *
+     * @param s     line of input
+     * @param state current state
+     * @return a populated SmtpRequest object
+     */
+    public static SmtpRequest createRequest(String s, SmtpState state) {
+        SmtpActionType action = null;
+        String params = null;
+
+        if (state == SmtpState.DATA_HDR) {
+            if (s.equals(".")) {
+                action = SmtpActionType.DATA_END;
+            } else if (s.length() < 1) {
+                action = SmtpActionType.BLANK_LINE;
+            } else {
+                action = SmtpActionType.UNRECOG;
+                params = s;
+            }
+        } else if (state == SmtpState.DATA_BODY) {
+            if (s.equals(".")) {
+                action = SmtpActionType.DATA_END;
+            } else {
+                action = SmtpActionType.UNRECOG;
+                if (s.length() < 1) {
+                    params = "\n";
+                } else {
+                    params = s;
+                }
+            }
+        } else {
+            String su = s.toUpperCase();
+            if (su.startsWith("EHLO ") || su.startsWith("HELO")) {
+                action = SmtpActionType.EHLO;
+                params = s.substring(5);
+            } else if (su.startsWith("MAIL FROM:")) {
+                action = SmtpActionType.MAIL;
+                params = s.substring(10);
+            } else if (su.startsWith("RCPT TO:")) {
+                action = SmtpActionType.RCPT;
+                params = s.substring(8);
+            } else if (su.startsWith("DATA")) {
+                action = SmtpActionType.DATA;
+            } else if (su.startsWith("QUIT")) {
+                action = SmtpActionType.QUIT;
+            } else if (su.startsWith("RSET")) {
+                action = SmtpActionType.RSET;
+            } else if (su.startsWith("NOOP")) {
+                action = SmtpActionType.NOOP;
+            } else if (su.startsWith("EXPN")) {
+                action = SmtpActionType.EXPN;
+            } else if (su.startsWith("VRFY")) {
+                action = SmtpActionType.VRFY;
+            } else if (su.startsWith("HELP")) {
+                action = SmtpActionType.HELP;
+            } else {
+                action = SmtpActionType.UNRECOG;
+            }
+        }
+
+        SmtpRequest req = new SmtpRequest(action, params, state);
+        return req;
+    }
+
+    /**
+     * Get the parameters of this request (remainder of command line once the command is
removed.
+     *
+     * @return parameters
+     */
+    public String getParams() {
+        return params;
+    }
+}

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpResponse.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpResponse.java?rev=1426989&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpResponse.java
(added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpResponse.java
Sun Dec 30 21:08:05 2012
@@ -0,0 +1,75 @@
+/*
+ * 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.logging.dumbster.smtp;
+
+/**
+ * SMTP response container.
+ */
+public class SmtpResponse {
+    /**
+     * Response code - see RFC-2821.
+     */
+    private int code;
+    /**
+     * Response message.
+     */
+    private String message;
+    /**
+     * New state of the SMTP server once the request has been executed.
+     */
+    private SmtpState nextState;
+
+    /**
+     * Constructor.
+     *
+     * @param code    response code
+     * @param message response message
+     * @param next    next state of the SMTP server
+     */
+    public SmtpResponse(int code, String message, SmtpState next) {
+        this.code = code;
+        this.message = message;
+        this.nextState = next;
+    }
+
+    /**
+     * Get the response code.
+     *
+     * @return response code
+     */
+    public int getCode() {
+        return code;
+    }
+
+    /**
+     * Get the response message.
+     *
+     * @return response message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * Get the next SMTP server state.
+     *
+     * @return state
+     */
+    public SmtpState getNextState() {
+        return nextState;
+    }
+}

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpState.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpState.java?rev=1426989&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpState.java
(added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/dumbster/smtp/SmtpState.java
Sun Dec 30 21:08:05 2012
@@ -0,0 +1,120 @@
+/*
+ * 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.logging.dumbster.smtp;
+
+/**
+ * SMTP server state.
+ */
+public class SmtpState {
+    /**
+     * Internal representation of the state.
+     */
+    private byte value;
+
+    /**
+     * Internal representation of the CONNECT state.
+     */
+    private static final byte CONNECT_BYTE = (byte) 1;
+    /**
+     * Internal representation of the GREET state.
+     */
+    private static final byte GREET_BYTE = (byte) 2;
+    /**
+     * Internal representation of the MAIL state.
+     */
+    private static final byte MAIL_BYTE = (byte) 3;
+    /**
+     * Internal representation of the RCPT state.
+     */
+    private static final byte RCPT_BYTE = (byte) 4;
+    /**
+     * Internal representation of the DATA_HEADER state.
+     */
+    private static final byte DATA_HEADER_BYTE = (byte) 5;
+    /**
+     * Internal representation of the DATA_BODY state.
+     */
+    private static final byte DATA_BODY_BYTE = (byte) 6;
+    /**
+     * Internal representation of the QUIT state.
+     */
+    private static final byte QUIT_BYTE = (byte) 7;
+
+    /**
+     * CONNECT state: waiting for a client connection.
+     */
+    public static final SmtpState CONNECT = new SmtpState(CONNECT_BYTE);
+    /**
+     * GREET state: wating for a ELHO message.
+     */
+    public static final SmtpState GREET = new SmtpState(GREET_BYTE);
+    /**
+     * MAIL state: waiting for the MAIL FROM: command.
+     */
+    public static final SmtpState MAIL = new SmtpState(MAIL_BYTE);
+    /**
+     * RCPT state: waiting for a RCPT &lt;email address&gt; command.
+     */
+    public static final SmtpState RCPT = new SmtpState(RCPT_BYTE);
+    /**
+     * Waiting for headers.
+     */
+    public static final SmtpState DATA_HDR = new SmtpState(DATA_HEADER_BYTE);
+    /**
+     * Processing body text.
+     */
+    public static final SmtpState DATA_BODY = new SmtpState(DATA_BODY_BYTE);
+    /**
+     * End of client transmission.
+     */
+    public static final SmtpState QUIT = new SmtpState(QUIT_BYTE);
+
+    /**
+     * Create a new SmtpState object. Private to ensure that only valid states can be created.
+     *
+     * @param value one of the _BYTE values.
+     */
+    private SmtpState(byte value) {
+        this.value = value;
+    }
+
+    /**
+     * String representation of this SmtpState.
+     *
+     * @return a String
+     */
+    public String toString() {
+        switch (value) {
+            case CONNECT_BYTE:
+                return "CONNECT";
+            case GREET_BYTE:
+                return "GREET";
+            case MAIL_BYTE:
+                return "MAIL";
+            case RCPT_BYTE:
+                return "RCPT";
+            case DATA_HEADER_BYTE:
+                return "DATA_HDR";
+            case DATA_BODY_BYTE:
+                return "DATA_BODY";
+            case QUIT_BYTE:
+                return "QUIT";
+            default:
+                return "Unknown";
+        }
+    }
+}

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java?rev=1426989&r1=1426988&r2=1426989&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java
(original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java
Sun Dec 30 21:08:05 2012
@@ -29,8 +29,8 @@ import org.apache.logging.log4j.core.hel
 import org.apache.logging.log4j.core.net.MimeMessageBuilder;
 import org.junit.Test;
 
-import com.dumbster.smtp.SimpleSmtpServer;
-import com.dumbster.smtp.SmtpMessage;
+import org.apache.logging.dumbster.smtp.SimpleSmtpServer;
+import org.apache.logging.dumbster.smtp.SmtpMessage;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;



Mime
View raw message