You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/12/26 20:50:04 UTC

svn commit: r1426001 [1/2] - in /logging/log4j/log4j2/trunk: ./ core/ core/src/main/java/org/apache/logging/log4j/core/ core/src/main/java/org/apache/logging/log4j/core/appender/ core/src/main/java/org/apache/logging/log4j/core/helpers/ core/src/main/j...

Author: rgoers
Date: Wed Dec 26 19:50:03 2012
New Revision: 1426001

URL: http://svn.apache.org/viewvc?rev=1426001&view=rev
Log:
LOG4J2-131 - Add SMTPAppender

Added:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/CyclicBuffer.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/PropertiesUtil.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MimeMessageBuilder.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/SMTPManager.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java
Modified:
    logging/log4j/log4j2/trunk/core/pom.xml
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Layout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/Constants.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/NameUtil.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/LineSeparatorPatternConverter.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/OutputStreamAppenderTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
    logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEmbeddedManager.java
    logging/log4j/log4j2/trunk/jcl-bridge/src/test/java/org/apache/logging/log4j/jcl/LoggerTest.java
    logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Layout.java
    logging/log4j/log4j2/trunk/log4j12-api/src/test/java/org/apache/log4j/CategoryTest.java
    logging/log4j/log4j2/trunk/pom.xml
    logging/log4j/log4j2/trunk/slf4j-impl/src/test/java/org/apache/logging/slf4j/LoggerTest.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml
    logging/log4j/log4j2/trunk/src/site/site.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml

Modified: logging/log4j/log4j2/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/pom.xml?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/pom.xml (original)
+++ logging/log4j/log4j2/trunk/core/pom.xml Wed Dec 26 19:50:03 2012
@@ -41,31 +41,26 @@
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>core</artifactId>
-      <version>4.3.0</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.codehaus.jackson</groupId>
       <artifactId>jackson-core-asl</artifactId>
-      <version>1.9.2</version>
       <optional>true</optional>
     </dependency>
     <dependency>
       <groupId>org.codehaus.jackson</groupId>
       <artifactId>jackson-mapper-asl</artifactId>
-      <version>1.9.2</version>
       <optional>true</optional>
     </dependency>
     <dependency>
       <groupId>org.fusesource.jansi</groupId>
       <artifactId>jansi</artifactId>
-      <version>1.9</version>
       <optional>true</optional>
     </dependency>
     <dependency>
       <groupId>oro</groupId>
       <artifactId>oro</artifactId>
-      <version>2.0.8</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -87,13 +82,11 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>4.7</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.mockejb</groupId>
       <artifactId>mockejb</artifactId>
-      <version>0.6-beta2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -109,9 +102,18 @@
     <dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-jms_1.1_spec</artifactId>
-      <version>1.0</version>
       <optional>true</optional>
     </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+	  <groupId>dumbster</groupId>
+	    <artifactId>dumbster</artifactId>
+	    <scope>test</scope>
+    </dependency>
   </dependencies>
   <build>
     <plugins>

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Layout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Layout.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Layout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Layout.java Wed Dec 26 19:50:03 2012
@@ -20,7 +20,7 @@ import java.io.Serializable;
 
 /**
  * Lays out a {@linkplain LogEvent} in different formats.
- * 
+ *
  * The formats are:
  * <ul>
  * <li>
@@ -32,10 +32,10 @@ import java.io.Serializable;
  * <li>
  * {@linkplain LogEvent}</li>
  * </ul>
- * 
+ *
  * @param <T>
  *            The type returned by {@link #toSerializable(LogEvent)}
- *            
+ *
  * @doubt There is still a need for a character-based layout for character based event sinks (databases, etc). Would introduce an
  *        EventEncoder, EventRenderer or something similar for the logging event to byte encoding. (RG) A layout can be configured with a
  *        Charset and then Strings can be converted to byte arrays. OTOH, it isn't possible to write byte arrays as character streams.
@@ -76,5 +76,9 @@ public interface Layout<T extends Serial
      */
     T toSerializable(LogEvent event);
 
-
+    /**
+     * Returns the content type output by this layout. The base class
+     returns "text/plain".
+     */
+    String getContentType();
 }

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java?rev=1426001&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SMTPAppender.java Wed Dec 26 19:50:03 2012
@@ -0,0 +1,162 @@
+/*
+ * 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.log4j.core.appender;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttr;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.filter.ThresholdFilter;
+import org.apache.logging.log4j.core.layout.HTMLLayout;
+import org.apache.logging.log4j.core.net.SMTPManager;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+
+/**
+ * Send an e-mail when a specific logging event occurs, typically on errors or
+ * fatal errors.
+ *
+ * <p>
+ * The number of logging events delivered in this e-mail depend on the value of
+ * <b>BufferSize</b> option. The <code>SMTPAppender</code> keeps only the last
+ * <code>BufferSize</code> logging events in its cyclic buffer. This keeps
+ * memory requirements at a reasonable level while still delivering useful
+ * application context.
+ *
+ * By default, an email message will formatted as HTML. This can be modified by
+ * setting a layout for the appender.
+ *
+ * By default, an email message will be sent when an ERROR or higher severity
+ * message is appended. This can be modified by setting a filter for the
+ * appender.
+ */
+@Plugin(name = "SMTP", type = "Core", elementType = "appender", printObject = true)
+public class SMTPAppender extends AbstractAppender {
+    protected final SMTPManager manager;
+
+    private SMTPAppender(final String name, final Filter filter, final Layout<?> layout, final SMTPManager manager,
+                         boolean handleExceptions) {
+        super(name, filter, layout, handleExceptions);
+        this.manager = manager;
+    }
+
+    /**
+     * Create a SMTPAppender.
+     *
+     * @param name
+     *            The name of the Appender.
+     * @param to
+     *            The comma-separated list of recipient email addresses.
+     * @param cc
+     *            The comma-separated list of CC email addresses.
+     * @param bcc
+     *            The comma-separated list of BCC email addresses.
+     * @param from
+     *            The email address of the sender.
+     * @param replyTo
+     *            The comma-separated list of reply-to email addresses.
+     * @param smtpProtocol
+     *            The SMTP transport protocol (such as "smtps", defaults to
+     *            "smtp").
+     * @param smtpHost
+     *            The SMTP hostname to send to.
+     * @param smtpPortNum
+     *            The SMTP port to send to.
+     * @param smtpUsername
+     *            The username required to authenticate against the SMTP server.
+     * @param smtpPassword
+     *            The password required to authenticate against the SMTP server.
+     * @param smtpDebug
+     *            Enable mail session debuging on STDOUT.
+     * @param bufferSizeNum
+     *            How many log events should be buffered for inclusion in the
+     *            message?
+     * @param layout
+     *            The layout to use (defaults to HTMLLayout).
+     * @param filter
+     *            The Filter or null (defaults to ThresholdFilter, level of
+     *            ERROR).
+     * @param suppressExceptions
+     *            "true" if exceptions should be hidden from the application,
+     *            "false" otherwise (defaults to "true").
+     * @return The SMTPAppender.
+     */
+    @PluginFactory
+    public static SMTPAppender createAppender(@PluginAttr("name") final String name,
+                                              @PluginAttr("to") final String to,
+                                              @PluginAttr("cc") final String cc,
+                                              @PluginAttr("bcc") final String bcc,
+                                              @PluginAttr("from") final String from,
+                                              @PluginAttr("replyTo") final String replyTo,
+                                              @PluginAttr("subject") final String subject,
+                                              @PluginAttr("smtpProtocol") String smtpProtocol,
+                                              @PluginAttr("smtpHost") final String smtpHost,
+                                              @PluginAttr("smtpPort") final String smtpPortNum,
+                                              @PluginAttr("smtpUsername") final String smtpUsername,
+                                              @PluginAttr("smtpPassword") final String smtpPassword,
+                                              @PluginAttr("smtpDebug") final String smtpDebug,
+                                              @PluginAttr("bufferSize") final String bufferSizeNum,
+                                              @PluginElement("layout") Layout<?> layout,
+                                              @PluginElement("filter") Filter filter,
+                                              @PluginAttr("suppressExceptions") final String suppressExceptions) {
+        if (name == null) {
+            LOGGER.error("No name provided for SMTPAppender");
+            return null;
+        }
+
+        final boolean isHandleExceptions = suppressExceptions == null ? true : Boolean.valueOf(suppressExceptions);
+        final int smtpPort = smtpPortNum == null ? 0 : Integer.parseInt(smtpPortNum);
+        final boolean isSmtpDebug = smtpDebug == null ? false : Boolean.valueOf(smtpDebug);
+        final int bufferSize = bufferSizeNum == null ? 512 : Integer.valueOf(bufferSizeNum);
+
+        if (layout == null) {
+            layout = HTMLLayout.createLayout(null, null, null, null, null, null);
+        }
+        if (filter == null) {
+            filter = ThresholdFilter.createFilter(null, null, null);
+        }
+
+        final SMTPManager manager = SMTPManager.getSMTPManager(to, cc, bcc, from, replyTo, subject, smtpProtocol,
+            smtpHost, smtpPort, smtpUsername, smtpPassword, isSmtpDebug, filter.toString(),  bufferSize);
+        if (manager == null) {
+            return null;
+        }
+
+        return new SMTPAppender(name, filter, layout, manager, isHandleExceptions);
+    }
+
+    /**
+     * Capture all events in CyclicBuffer
+     */
+    @Override
+    public boolean isFiltered(LogEvent event) {
+        manager.add(event);
+        return super.isFiltered(event);
+    }
+
+    /**
+     * Perform SMTPAppender specific appending actions, mainly adding the event
+     * to a cyclic buffer and checking if the event triggers an e-mail to be
+     * sent.
+     */
+    public void append(LogEvent event) {
+        manager.sendEvents(getLayout());
+    }
+}
\ No newline at end of file

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/Constants.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/Constants.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/Constants.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/Constants.java Wed Dec 26 19:50:03 2012
@@ -32,6 +32,11 @@ public final class Constants {
     public static final String JNDI_CONTEXT_NAME = "java:comp/env/log4j/context-name";
 
     /**
+     * Line separator.
+     */
+    public static final String LINE_SEP = PropertiesUtil.getSystemProperty("line.separator", "\n");
+
+    /**
      * Prevent class instantiation.
      */
     private Constants() {

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/CyclicBuffer.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/CyclicBuffer.java?rev=1426001&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/CyclicBuffer.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/CyclicBuffer.java Wed Dec 26 19:50:03 2012
@@ -0,0 +1,82 @@
+/*
+ * 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.log4j.core.helpers;
+
+import java.lang.reflect.Array;
+
+/**
+ * A bounded buffer containing elements of type T. When the number of elements to be added will exceed the
+ * size of the buffer the oldest element will be overwritten. Access to the buffer is thread safe.
+ */
+public class CyclicBuffer<T> {
+    private T[] ring;
+    private int first = 0;
+    private int last = 0;
+    private int numElems = 0;
+    private final Class<T> clazz;
+
+    /**
+     * Instantiate a new CyclicBuffer of at most <code>maxSize</code>
+     * events.
+     */
+    public CyclicBuffer(Class<T> clazz, int size) throws IllegalArgumentException {
+        if (size < 1) {
+            throw new IllegalArgumentException("The maxSize argument (" + size + ") is not a positive integer.");
+        }
+        this.ring = makeArray(clazz, size);
+        this.clazz = clazz;
+    }
+
+    @SuppressWarnings("unchecked")
+    private T[] makeArray(Class<T> clazz, int size) {
+        return (T[]) Array.newInstance(clazz, size);
+    }
+
+    /**
+     * Add an item as the last event in the buffer.
+     */
+    public synchronized void add(T item) {
+        ring[last] = item;
+        if (++last == ring.length) {
+            last = 0;
+        }
+
+        if (numElems < ring.length) {
+            numElems++;
+        } else if (++first == ring.length) {
+            first = 0;
+        }
+    }
+
+    public synchronized T[] removeAll() {
+        T[] array = makeArray(clazz, numElems);
+        int index = 0;
+        while (numElems > 0) {
+            numElems--;
+            array[index++] = ring[first];
+            ring[first] = null;
+            if (++first == ring.length) {
+                first = 0;
+            }
+        }
+        return array;
+    }
+
+    public boolean isEmpty() {
+        return 0 == numElems;
+    }
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/NameUtil.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/NameUtil.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/NameUtil.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/NameUtil.java Wed Dec 26 19:50:03 2012
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.helpers;
 
+import java.security.MessageDigest;
+
 /**
  *
  */
@@ -31,4 +33,23 @@ public final class NameUtil {
         final int i = name.lastIndexOf('.');
         return i > 0 ? name.substring(0, i) : "";
     }
+
+    public static String md5(String string) {
+        try {
+            final MessageDigest digest = MessageDigest.getInstance("MD5");
+            digest.update(string.getBytes());
+            final byte[] bytes = digest.digest();
+            final StringBuilder md5 = new StringBuilder();
+            for (final byte b : bytes) {
+                final String hex = Integer.toHexString(0xff & b);
+                if (hex.length() == 1) {
+                    md5.append('0');
+                }
+                md5.append(hex);
+            }
+            return md5.toString();
+        } catch (Exception ex) {
+            return string;
+        }
+    }
 }

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/PropertiesUtil.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/PropertiesUtil.java?rev=1426001&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/PropertiesUtil.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/PropertiesUtil.java Wed Dec 26 19:50:03 2012
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.helpers;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.status.StatusLogger;
+
+import java.util.Properties;
+
+/**
+ * System Property utility methods.
+ */
+public final class PropertiesUtil {
+
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    private PropertiesUtil() {
+    }
+
+    /**
+     * Return the specified system property, returning null if an error occurs.
+     * @param key The key to locate.
+     * @return The value associated with the key.
+     */
+    public static String getSystemProperty(final String key) {
+        try {
+            return System.getProperty(key);
+        } catch (SecurityException ex) {
+            LOGGER.error("Unable to access system property {} due to security restrictions. Defaulting to null",
+                key);
+            return null;
+        }
+    }
+
+    /**
+     * Return the specified system property, returning the provided default value if the key does not exist or
+     * an error occurs.
+     * @param key The key to locate.
+     * @param defaultValue The default value.
+     * @return The value associated with the key or the default value if the key cannot be located.
+     */
+    public static String getSystemProperty(final String key, final String defaultValue) {
+        try {
+            String value = System.getProperty(key);
+            return value == null ? defaultValue : value;
+        } catch (SecurityException ex) {
+            LOGGER.warn("Unable to access system property {} due to security restrictions. Defaulting to {}",
+                key, defaultValue);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Return the system properties or an empty Properties object if an error occurs.
+     * @return The system properties.
+     */
+    public static Properties getSystemProperties() {
+        try {
+            return new Properties(System.getProperties());
+        } catch (SecurityException ex) {
+            LOGGER.error("Unable to access system properties.");
+            // Sandboxed - can't read System Properties
+            return new Properties();
+        }
+    }
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java Wed Dec 26 19:50:03 2012
@@ -56,6 +56,13 @@ public abstract class AbstractStringLayo
         return encoder.getBytes(toSerializable(event));
     }
 
+    /**
+     * @return The default content type for Strings.
+     */
+    public String getContentType() {
+        return "text/plain";
+    }
+
     protected Charset getCharset() {
         return charset;
     }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java Wed Dec 26 19:50:03 2012
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.core.Log
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.core.helpers.Transform;
 
 import java.io.IOException;
@@ -46,9 +47,7 @@ public final class HTMLLayout extends Ab
 
     private static final String TRACE_PREFIX = "<br />&nbsp;&nbsp;&nbsp;&nbsp;";
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
-
-    private static final String REGEXP = LINE_SEP.equals("\n") ? "\n" : LINE_SEP + "|\n";
+    private static final String REGEXP = Constants.LINE_SEP.equals("\n") ? "\n" : Constants.LINE_SEP + "|\n";
 
     private static final String DEFAULT_TITLE = "Log4J Log Messages";
 
@@ -115,16 +114,16 @@ public final class HTMLLayout extends Ab
     public String toSerializable(final LogEvent event) {
         final StringBuilder sbuf = new StringBuilder(BUF_SIZE);
 
-        sbuf.append(LINE_SEP).append("<tr>").append(LINE_SEP);
+        sbuf.append(Constants.LINE_SEP).append("<tr>").append(Constants.LINE_SEP);
 
         sbuf.append("<td>");
         sbuf.append(event.getMillis() - jvmStartTime);
-        sbuf.append("</td>").append(LINE_SEP);
+        sbuf.append("</td>").append(Constants.LINE_SEP);
 
         final String escapedThread = Transform.escapeTags(event.getThreadName());
         sbuf.append("<td title=\"").append(escapedThread).append(" thread\">");
         sbuf.append(escapedThread);
-        sbuf.append("</td>").append(LINE_SEP);
+        sbuf.append("</td>").append(Constants.LINE_SEP);
 
         sbuf.append("<td title=\"Level\">");
         if (event.getLevel().equals(Level.DEBUG)) {
@@ -138,7 +137,7 @@ public final class HTMLLayout extends Ab
         } else {
             sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));
         }
-        sbuf.append("</td>").append(LINE_SEP);
+        sbuf.append("</td>").append(Constants.LINE_SEP);
 
         String escapedLogger = Transform.escapeTags(event.getLoggerName());
         if (escapedLogger.length() == 0) {
@@ -146,7 +145,7 @@ public final class HTMLLayout extends Ab
         }
         sbuf.append("<td title=\"").append(escapedLogger).append(" logger\">");
         sbuf.append(escapedLogger);
-        sbuf.append("</td>").append(LINE_SEP);
+        sbuf.append("</td>").append(Constants.LINE_SEP);
 
         if (locationInfo) {
             final StackTraceElement element = event.getSource();
@@ -154,20 +153,20 @@ public final class HTMLLayout extends Ab
             sbuf.append(Transform.escapeTags(element.getFileName()));
             sbuf.append(':');
             sbuf.append(element.getLineNumber());
-            sbuf.append("</td>").append(LINE_SEP);
+            sbuf.append("</td>").append(Constants.LINE_SEP);
         }
 
         sbuf.append("<td title=\"Message\">");
         sbuf.append(Transform.escapeTags(event.getMessage().getFormattedMessage()).replaceAll(REGEXP, "<br />"));
-        sbuf.append("</td>").append(LINE_SEP);
-        sbuf.append("</tr>").append(LINE_SEP);
+        sbuf.append("</td>").append(Constants.LINE_SEP);
+        sbuf.append("</tr>").append(Constants.LINE_SEP);
 
         if (event.getContextStack().getDepth() > 0) {
             sbuf.append("<tr><td bgcolor=\"#EEEEEE\" style=\"font-size : ").append(fontSize);
             sbuf.append(";\" colspan=\"6\" ");
             sbuf.append("title=\"Nested Diagnostic Context\">");
             sbuf.append("NDC: ").append(Transform.escapeTags(event.getContextStack().toString()));
-            sbuf.append("</td></tr>").append(LINE_SEP);
+            sbuf.append("</td></tr>").append(Constants.LINE_SEP);
         }
 
         if (event.getContextMap().size() > 0) {
@@ -175,7 +174,7 @@ public final class HTMLLayout extends Ab
             sbuf.append(";\" colspan=\"6\" ");
             sbuf.append("title=\"Mapped Diagnostic Context\">");
             sbuf.append("MDC: ").append(Transform.escapeTags(event.getContextMap().toString()));
-            sbuf.append("</td></tr>").append(LINE_SEP);
+            sbuf.append("</td></tr>").append(Constants.LINE_SEP);
         }
 
         final Throwable throwable = event.getThrown();
@@ -183,12 +182,20 @@ public final class HTMLLayout extends Ab
             sbuf.append("<tr><td bgcolor=\"#993300\" style=\"color:White; font-size : ").append(fontSize);
             sbuf.append(";\" colspan=\"6\">");
             appendThrowableAsHTML(throwable, sbuf);
-            sbuf.append("</td></tr>").append(LINE_SEP);
+            sbuf.append("</td></tr>").append(Constants.LINE_SEP);
         }
 
         return sbuf.toString();
     }
 
+    @Override
+    /**
+     * @return The content type.
+     */
+    public String getContentType() {
+        return "text/html";
+    }
+
     private void appendThrowableAsHTML(final Throwable throwable, final StringBuilder sbuf) {
         final StringWriter sw = new StringWriter();
         final PrintWriter pw = new PrintWriter(sw);
@@ -220,7 +227,7 @@ public final class HTMLLayout extends Ab
                 first = false;
             }
             sbuf.append(Transform.escapeTags(line));
-            sbuf.append(LINE_SEP);
+            sbuf.append(Constants.LINE_SEP);
         }
     }
 
@@ -233,35 +240,35 @@ public final class HTMLLayout extends Ab
         final StringBuilder sbuf = new StringBuilder();
         sbuf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" ");
         sbuf.append("\"http://www.w3.org/TR/html4/loose.dtd\">");
-        sbuf.append(LINE_SEP);
-        sbuf.append("<html>").append(LINE_SEP);
-        sbuf.append("<head>").append(LINE_SEP);
-        sbuf.append("<title>").append(title).append("</title>").append(LINE_SEP);
-        sbuf.append("<style type=\"text/css\">").append(LINE_SEP);
-        sbuf.append("<!--").append(LINE_SEP);
+        sbuf.append(Constants.LINE_SEP);
+        sbuf.append("<html>").append(Constants.LINE_SEP);
+        sbuf.append("<head>").append(Constants.LINE_SEP);
+        sbuf.append("<title>").append(title).append("</title>").append(Constants.LINE_SEP);
+        sbuf.append("<style type=\"text/css\">").append(Constants.LINE_SEP);
+        sbuf.append("<!--").append(Constants.LINE_SEP);
         sbuf.append("body, table {font-family:").append(font).append("; font-size: ");
-        sbuf.append(headerSize).append(";}").append(LINE_SEP);
-        sbuf.append("th {background: #336699; color: #FFFFFF; text-align: left;}").append(LINE_SEP);
-        sbuf.append("-->").append(LINE_SEP);
-        sbuf.append("</style>").append(LINE_SEP);
-        sbuf.append("</head>").append(LINE_SEP);
-        sbuf.append("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">").append(LINE_SEP);
-        sbuf.append("<hr size=\"1\" noshade>").append(LINE_SEP);
-        sbuf.append("Log session start time " + new java.util.Date() + "<br>").append(LINE_SEP);
-        sbuf.append("<br>").append(LINE_SEP);
+        sbuf.append(headerSize).append(";}").append(Constants.LINE_SEP);
+        sbuf.append("th {background: #336699; color: #FFFFFF; text-align: left;}").append(Constants.LINE_SEP);
+        sbuf.append("-->").append(Constants.LINE_SEP);
+        sbuf.append("</style>").append(Constants.LINE_SEP);
+        sbuf.append("</head>").append(Constants.LINE_SEP);
+        sbuf.append("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">").append(Constants.LINE_SEP);
+        sbuf.append("<hr size=\"1\" noshade>").append(Constants.LINE_SEP);
+        sbuf.append("Log session start time " + new java.util.Date() + "<br>").append(Constants.LINE_SEP);
+        sbuf.append("<br>").append(Constants.LINE_SEP);
         sbuf.append(
             "<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">");
-        sbuf.append(LINE_SEP);
-        sbuf.append("<tr>").append(LINE_SEP);
-        sbuf.append("<th>Time</th>").append(LINE_SEP);
-        sbuf.append("<th>Thread</th>").append(LINE_SEP);
-        sbuf.append("<th>Level</th>").append(LINE_SEP);
-        sbuf.append("<th>Logger</th>").append(LINE_SEP);
+        sbuf.append(Constants.LINE_SEP);
+        sbuf.append("<tr>").append(Constants.LINE_SEP);
+        sbuf.append("<th>Time</th>").append(Constants.LINE_SEP);
+        sbuf.append("<th>Thread</th>").append(Constants.LINE_SEP);
+        sbuf.append("<th>Level</th>").append(Constants.LINE_SEP);
+        sbuf.append("<th>Logger</th>").append(Constants.LINE_SEP);
         if (locationInfo) {
-            sbuf.append("<th>File:Line</th>").append(LINE_SEP);
+            sbuf.append("<th>File:Line</th>").append(Constants.LINE_SEP);
         }
-        sbuf.append("<th>Message</th>").append(LINE_SEP);
-        sbuf.append("</tr>").append(LINE_SEP);
+        sbuf.append("<th>Message</th>").append(Constants.LINE_SEP);
+        sbuf.append("</tr>").append(Constants.LINE_SEP);
         return sbuf.toString().getBytes(getCharset());
     }
 
@@ -272,8 +279,8 @@ public final class HTMLLayout extends Ab
     @Override
     public byte[] getFooter() {
         final StringBuilder sbuf = new StringBuilder();
-        sbuf.append("</table>").append(LINE_SEP);
-        sbuf.append("<br>").append(LINE_SEP);
+        sbuf.append("</table>").append(Constants.LINE_SEP);
+        sbuf.append("<br>").append(Constants.LINE_SEP);
         sbuf.append("</body></html>");
         return sbuf.toString().getBytes(getCharset());
     }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java Wed Dec 26 19:50:03 2012
@@ -94,6 +94,14 @@ public final class SerializedLayout exte
     }
 
     /**
+     * SerializedLayout returns a binary stream.
+     * @return The content type.
+     */
+    public String getContentType() {
+        return "application/octet-stream";
+    }
+
+    /**
      * The stream header will be written in the Manager so skip it here.
      */
     private class PrivateObjectOutputStream extends ObjectOutputStream {

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java Wed Dec 26 19:50:03 2012
@@ -214,6 +214,14 @@ public class XMLLayout extends AbstractS
         return sbuf.toString().getBytes(getCharset());
     }
 
+    @Override
+    /**
+     * @return The content type.
+     */
+    public String getContentType() {
+        return "text/xml";
+    }
+
     List<String> getThrowableString(final Throwable throwable) {
         final StringWriter sw = new StringWriter();
         final PrintWriter pw = new PrintWriter(sw);

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MimeMessageBuilder.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MimeMessageBuilder.java?rev=1426001&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MimeMessageBuilder.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MimeMessageBuilder.java Wed Dec 26 19:50:03 2012
@@ -0,0 +1,84 @@
+/*
+ * 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.log4j.core.net;
+
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+
+/**
+ *  Helper class for SMTPManager
+ */
+public class MimeMessageBuilder {
+    private final MimeMessage message;
+
+    public MimeMessageBuilder(Session session) {
+        message = new MimeMessage(session);
+    }
+
+    public MimeMessageBuilder setFrom(final String from) throws MessagingException {
+        InternetAddress address = parseAddress(from);
+
+        if (null != address) {
+            message.setFrom(address);
+        } else {
+            message.setFrom();
+        }
+        return this;
+    }
+
+    public MimeMessageBuilder setReplyTo(final String replyTo) throws MessagingException {
+        InternetAddress[] addresses = parseAddresses(replyTo);
+
+        if (null != addresses) {
+            message.setReplyTo(addresses);
+        }
+        return this;
+    }
+
+    public MimeMessageBuilder setRecipients(final Message.RecipientType recipientType, final String recipients)
+        throws MessagingException {
+        InternetAddress[] addresses = parseAddresses(recipients);
+
+        if (null != addresses) {
+            message.setRecipients(recipientType, addresses);
+        }
+        return this;
+    }
+
+    public MimeMessageBuilder setSubject(final String subject) throws MessagingException {
+        if (subject != null) {
+            message.setSubject(subject, "UTF-8");
+        }
+        return this;
+    }
+
+    public MimeMessage getMimeMessage() {
+        return message;
+    }
+
+    private static InternetAddress parseAddress(String address) throws AddressException {
+        return address == null ? null : new InternetAddress(address);
+    }
+
+    private static InternetAddress[] parseAddresses(String addresses) throws AddressException {
+        return addresses == null ? null : InternetAddress.parse(addresses, true);
+    }
+}
\ No newline at end of file

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/SMTPManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/SMTPManager.java?rev=1426001&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/SMTPManager.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/SMTPManager.java Wed Dec 26 19:50:03 2012
@@ -0,0 +1,326 @@
+/*
+ * 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.log4j.core.net;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.Properties;
+
+import javax.activation.DataSource;
+import javax.mail.Authenticator;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.PasswordAuthentication;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.mail.internet.MimeUtility;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.logging.log4j.LoggingException;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.AbstractManager;
+import org.apache.logging.log4j.core.appender.ManagerFactory;
+import org.apache.logging.log4j.core.helpers.CyclicBuffer;
+import org.apache.logging.log4j.core.helpers.NameUtil;
+import org.apache.logging.log4j.core.helpers.PropertiesUtil;
+
+public class SMTPManager extends AbstractManager {
+    private static final SMTPManagerFactory factory = new SMTPManagerFactory();
+
+    private final Session session;
+
+    private CyclicBuffer<LogEvent> buffer;
+
+    private volatile MimeMessage message;
+
+    private final FactoryData data;
+
+    protected SMTPManager(final String name, final Session session, final MimeMessage message,
+                          final FactoryData data) {
+        super(name);
+        this.session = session;
+        this.message = message;
+        this.data = data;
+        this.buffer = new CyclicBuffer<LogEvent>(LogEvent.class, data.numElements);
+    }
+
+    public void add(LogEvent event) {
+        buffer.add(event);
+    }
+
+    public static SMTPManager getSMTPManager(final String to, final String cc, final String bcc,
+                                             final String from, final String replyTo,
+                                             final String subject, String protocol, final String host,
+                                             final int port, final String username, final String password,
+                                             final boolean isDebug, final String filterName, final int numElements) {
+        if (protocol == null || protocol.length() == 0) {
+            protocol = "smtp";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        if (to != null) {
+            sb.append(to);
+        }
+        sb.append(":");
+        if (cc != null) {
+            sb.append(cc);
+        }
+        sb.append(":");
+        if (bcc != null) {
+            sb.append(bcc);
+        }
+        sb.append(":");
+        if (from != null) {
+            sb.append(from);
+        }
+        sb.append(":");
+        if (replyTo != null) {
+            sb.append(replyTo);
+        }
+        sb.append(":");
+        if (subject != null) {
+            sb.append(subject);
+        }
+        sb.append(":");
+        sb.append(protocol).append(":").append(host).append(":").append("port").append(":");
+        if (username != null) {
+            sb.append(username);
+        }
+        sb.append(":");
+        if (password != null) {
+            sb.append(password);
+        }
+        sb.append(isDebug ? ":debug:" : "::");
+        sb.append(filterName);
+
+        String name = "SMTP:" + NameUtil.md5(sb.toString());
+
+        return (SMTPManager) getManager(name, factory, new FactoryData(to, cc, bcc, from, replyTo, subject,
+            protocol, host, port, username, password, isDebug, numElements));
+    }
+
+    /**
+     * Send the contents of the cyclic buffer as an e-mail message.
+     */
+    public void sendEvents(Layout<?> layout) {
+        if (message == null) {
+            connect();
+        }
+        try {
+            byte[] rawBytes = formatContentToBytes(buffer, layout);
+
+            String contentType = layout.getContentType();
+            String encoding = getEncoding(rawBytes, contentType);
+            byte[] encodedBytes = encodeContentToBytes(rawBytes, encoding);
+
+            InternetHeaders headers = getHeaders(contentType, encoding);
+            MimeMultipart mp = getMimeMultipart(encodedBytes, headers);
+
+            sendMultipartMessage(message, mp);
+        } catch (MessagingException e) {
+            LOGGER.error("Error occurred while sending e-mail notification.", e);
+            throw new LoggingException("Error occurred while sending email", e);
+        } catch (IOException e) {
+            LOGGER.error("Error occurred while sending e-mail notification.", e);
+            throw new LoggingException("Error occurred while sending email", e);
+        } catch (RuntimeException e) {
+            LOGGER.error("Error occurred while sending e-mail notification.", e);
+            throw new LoggingException("Error occurred while sending email", e);
+        }
+    }
+
+    protected byte[] formatContentToBytes(CyclicBuffer<LogEvent> cb, Layout<?> layout) throws IOException {
+        ByteArrayOutputStream raw = new ByteArrayOutputStream();
+        writeContent(cb, layout, raw);
+        return raw.toByteArray();
+    }
+
+    private void writeContent(CyclicBuffer<LogEvent> cb, Layout<?> layout, ByteArrayOutputStream out)
+        throws IOException {
+        writeHeader(layout, out);
+        writeBuffer(cb, layout, out);
+        writeFooter(layout, out);
+    }
+
+    protected void writeHeader(Layout<?> layout, OutputStream out) throws IOException {
+        byte[] header = layout.getHeader();
+        if (header != null) {
+            out.write(header);
+        }
+    }
+
+    protected void writeBuffer(CyclicBuffer<LogEvent> cb, Layout<?> layout, OutputStream out) throws IOException {
+        LogEvent[] events = cb.removeAll();
+        for (LogEvent event : events) {
+            byte[] bytes = layout.toByteArray(event);
+            out.write(bytes);
+        }
+    }
+
+    protected void writeFooter(Layout<?> layout, OutputStream out) throws IOException {
+        byte[] footer = layout.getFooter();
+        if (footer != null) {
+            out.write(footer);
+        }
+    }
+
+    protected String getEncoding(byte[] rawBytes, String contentType) {
+        DataSource dataSource = new ByteArrayDataSource(rawBytes, contentType);
+        return MimeUtility.getEncoding(dataSource);
+    }
+
+    protected byte[] encodeContentToBytes(byte[] rawBytes, String encoding) throws MessagingException, IOException {
+        ByteArrayOutputStream encoded = new ByteArrayOutputStream();
+        encodeContent(rawBytes, encoding, encoded);
+        return encoded.toByteArray();
+    }
+
+    protected void encodeContent(byte[] bytes, String encoding, ByteArrayOutputStream out)
+        throws MessagingException, IOException {
+        OutputStream encoder = MimeUtility.encode(out, encoding);
+        encoder.write(bytes);
+        encoder.close();
+    }
+
+    protected InternetHeaders getHeaders(String contentType, String encoding) {
+        InternetHeaders headers = new InternetHeaders();
+        headers.setHeader("Content-Type", contentType + "; charset=UTF-8");
+        headers.setHeader("Content-Transfer-Encoding", encoding);
+        return headers;
+    }
+
+    protected MimeMultipart getMimeMultipart(byte[] encodedBytes, InternetHeaders headers) throws MessagingException {
+        MimeMultipart mp = new MimeMultipart();
+        MimeBodyPart part = new MimeBodyPart(headers, encodedBytes);
+        mp.addBodyPart(part);
+        return mp;
+    }
+
+    protected void sendMultipartMessage(MimeMessage message, MimeMultipart mp) throws MessagingException {
+        synchronized (message) {
+            message.setContent(mp);
+            message.setSentDate(new Date());
+            Transport.send(message);
+        }
+    }
+
+    private static class FactoryData {
+        private final String to;
+        private final String cc;
+        private final String bcc;
+        private final String from;
+        private final String replyto;
+        private final String subject;
+        private final String protocol;
+        private final String host;
+        private final int port;
+        private final String username;
+        private final String password;
+        private final boolean isDebug;
+        private final int numElements;
+
+        public FactoryData(final String to, final String cc, final String bcc, final String from, final String replyTo,
+                           final String subject, final String protocol, final String host, final int port,
+                           final String username, final String password, final boolean isDebug, final int numElements) {
+            this.to = to;
+            this.cc = cc;
+            this.bcc = bcc;
+            this.from = from;
+            this.replyto = replyTo;
+            this.subject = subject;
+            this.protocol = protocol;
+            this.host = host;
+            this.port = port;
+            this.username = username;
+            this.password = password;
+            this.isDebug = isDebug;
+            this.numElements = numElements;
+        }
+    }
+
+    private synchronized void connect() {
+        if (message != null) {
+            return;
+        }
+        try {
+            message = new MimeMessageBuilder(session).setFrom(data.from).setReplyTo(data.replyto)
+                .setRecipients(Message.RecipientType.TO, data.to).setRecipients(Message.RecipientType.CC, data.cc)
+                .setRecipients(Message.RecipientType.BCC, data.bcc).setSubject(data.subject).getMimeMessage();
+        } catch (MessagingException e) {
+            LOGGER.error("Could not set SMTPAppender message options.", e);
+            message = null;
+        }
+    }
+
+    private static class SMTPManagerFactory implements ManagerFactory<SMTPManager, FactoryData> {
+
+        public SMTPManager createManager(final String name, final FactoryData data) {
+            final String prefix = "mail." + data.protocol;
+
+            Properties properties = PropertiesUtil.getSystemProperties();
+            properties.put("mail.transport.protocol", data.protocol);
+
+            if (null != data.host) {
+                properties.put(prefix + ".host", data.host);
+            }
+            if (data.port > 0) {
+                properties.put(prefix + ".port", String.valueOf(data.port));
+            }
+
+            final Authenticator authenticator = buildAuthenticator(data.username, data.password);
+            if (null != authenticator) {
+                properties.put(prefix + ".auth", "true");
+            }
+
+            final Session session = Session.getInstance(properties, authenticator);
+            session.setProtocolForAddress("rfc822", data.protocol);
+            session.setDebug(data.isDebug);
+            MimeMessage message;
+
+            try {
+                message = new MimeMessageBuilder(session).setFrom(data.from).setReplyTo(data.replyto)
+                    .setRecipients(Message.RecipientType.TO, data.to).setRecipients(Message.RecipientType.CC, data.cc)
+                    .setRecipients(Message.RecipientType.BCC, data.bcc).setSubject(data.subject).getMimeMessage();
+            } catch (MessagingException e) {
+                LOGGER.error("Could not set SMTPAppender message options.", e);
+                message = null;
+            }
+
+            return new SMTPManager(name, session, message, data);
+        }
+
+        private Authenticator buildAuthenticator(final String username, final String password) {
+            if (null != password && null != username) {
+                return new Authenticator() {
+                    private final PasswordAuthentication passwordAuthentication = new PasswordAuthentication(username, password);
+
+                    protected PasswordAuthentication getPasswordAuthentication() {
+                        return passwordAuthentication;
+                    }
+                };
+            }
+            return null;
+        }
+    }
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/LineSeparatorPatternConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/LineSeparatorPatternConverter.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/LineSeparatorPatternConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/LineSeparatorPatternConverter.java Wed Dec 26 19:50:03 2012
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.pa
 
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.helpers.Constants;
 
 /**
  * Formats a line separator.
@@ -26,7 +27,6 @@ import org.apache.logging.log4j.core.con
 @ConverterKeys({"n" })
 public final class LineSeparatorPatternConverter extends LogEventPatternConverter {
 
-  private static final String LINE_SEP = System.getProperty("line.separator");
   /**
    * Singleton.
    */
@@ -43,7 +43,7 @@ public final class LineSeparatorPatternC
    */
   private LineSeparatorPatternConverter() {
     super("Line Sep", "lineSep");
-    lineSep = LINE_SEP;
+    lineSep = Constants.LINE_SEP;
   }
 
   /**

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java Wed Dec 26 19:50:03 2012
@@ -31,6 +31,7 @@ import org.apache.logging.log4j.MarkerMa
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.core.helpers.NetUtils;
 import org.apache.logging.log4j.message.MessageFactory;
 import org.apache.logging.log4j.message.ParameterizedMessageFactory;
@@ -185,7 +186,7 @@ public class LoggerTest {
         testLogger.debug("Hello, {}", "World");
         final List<String> msgs = host.getMessages();
         assertTrue("Incorrect number of events. Expected 1, actual " + msgs.size(), msgs.size() == 1);
-        String expected = NetUtils.getLocalHostname() + System.getProperty("line.separator");
+        String expected = NetUtils.getLocalHostname() + Constants.LINE_SEP;
         assertTrue("Incorrect hostname - expected " + expected + " actual - " + msgs.get(0),
             msgs.get(0).endsWith(expected));
 

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java Wed Dec 26 19:50:03 2012
@@ -19,6 +19,7 @@ package org.apache.logging.log4j.core.ap
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.message.SimpleMessage;
@@ -39,8 +40,6 @@ import static org.junit.Assert.*;
  */
 public class ConsoleAppenderTest {
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
-
     private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
     @BeforeClass
@@ -68,7 +67,7 @@ public class ConsoleAppenderTest {
         System.setOut(ps);
         final String msg = baos.toString();
         assertNotNull("No message", msg);
-        assertTrue("Incorrect message: " + msg , msg.endsWith("Test" + LINE_SEP));
+        assertTrue("Incorrect message: " + msg , msg.endsWith("Test" + Constants.LINE_SEP));
         app.stop();
         assertFalse("Appender did not stop", app.isStarted());
     }

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/OutputStreamAppenderTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/OutputStreamAppenderTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/OutputStreamAppenderTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/OutputStreamAppenderTest.java Wed Dec 26 19:50:03 2012
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.ap
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.layout.PatternLayout;
@@ -34,8 +35,6 @@ import static org.junit.Assert.assertNot
  */
 public class OutputStreamAppenderTest {
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
-
     @Test
     public void testAppender() {
         final Layout layout = PatternLayout.createLayout(null, null, null, null);
@@ -47,7 +46,7 @@ public class OutputStreamAppenderTest {
         app.append(event);
         final String msg = app.toString();
         assertNotNull("No message", msg);
-        assertTrue("Incorrect message: " + msg , msg.endsWith("Test" + LINE_SEP));
+        assertTrue("Incorrect message: " + msg , msg.endsWith("Test" + Constants.LINE_SEP));
         app.stop();
         assertFalse("Appender did not stop", app.isStarted());
     }

Added: 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=1426001&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SMTPAppenderTest.java Wed Dec 26 19:50:03 2012
@@ -0,0 +1,165 @@
+/*
+ * 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.log4j.core.appender;
+
+import javax.mail.Address;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.internet.InternetAddress;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.helpers.CyclicBuffer;
+import org.apache.logging.log4j.core.net.MimeMessageBuilder;
+import org.junit.Test;
+
+import com.dumbster.smtp.SimpleSmtpServer;
+import com.dumbster.smtp.SmtpMessage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertArrayEquals;
+
+public class SMTPAppenderTest {
+
+    private static final String HOST = "localhost";
+    private static final String PORT = "8199";
+    private static final int PORTNUM = Integer.parseInt(PORT);
+
+    @Test
+    public void testMessageFactorySetFrom() throws MessagingException {
+        final MimeMessageBuilder builder = new MimeMessageBuilder(null);
+        final String address = "testing@example.com";
+
+        assertNull(builder.getMimeMessage().getFrom());
+
+        builder.setFrom(null);
+        assertArrayEquals(new Address[] { InternetAddress.getLocalAddress(null) }, builder.getMimeMessage().getFrom());
+
+        builder.setFrom(address);
+        assertArrayEquals(new Address[] { new InternetAddress(address) }, builder.getMimeMessage().getFrom());
+    }
+
+    @Test
+    public void testMessageFactorySetReplyTo() throws MessagingException {
+        final MimeMessageBuilder builder = new MimeMessageBuilder(null);
+        final String addresses = "testing1@example.com,testing2@example.com";
+
+        assertNull(builder.getMimeMessage().getReplyTo());
+
+        builder.setReplyTo(null);
+        assertNull(builder.getMimeMessage().getReplyTo());
+
+        builder.setReplyTo(addresses);
+        assertArrayEquals(InternetAddress.parse(addresses), builder.getMimeMessage().getReplyTo());
+    }
+
+    @Test
+    public void testMessageFactorySetRecipients() throws MessagingException {
+        final MimeMessageBuilder builder = new MimeMessageBuilder(null);
+        final String addresses = "testing1@example.com,testing2@example.com";
+
+        assertNull(builder.getMimeMessage().getRecipients(Message.RecipientType.TO));
+
+        builder.setRecipients(Message.RecipientType.TO, null);
+        assertNull(builder.getMimeMessage().getRecipients(Message.RecipientType.TO));
+
+        builder.setRecipients(Message.RecipientType.TO, addresses);
+        assertArrayEquals(InternetAddress.parse(addresses), builder.getMimeMessage().getRecipients(Message.RecipientType.TO));
+    }
+
+    @Test
+    public void testMessageFactorySetSubject() throws MessagingException {
+        final MimeMessageBuilder builder = new MimeMessageBuilder(null);
+        final String subject = "Test Subject";
+
+        assertNull(builder.getMimeMessage().getSubject());
+
+        builder.setSubject(null);
+        assertNull(builder.getMimeMessage().getSubject());
+
+        builder.setSubject(subject);
+        assertEquals(subject, builder.getMimeMessage().getSubject());
+    }
+
+    @Test
+    public void testCyclicBuffer() {
+        final CyclicBuffer<Integer> buffer = new CyclicBuffer<Integer>(Integer.class, 3);
+
+        assertTrue(buffer.isEmpty());
+        buffer.add(1);
+        assertFalse(buffer.isEmpty());
+        Integer[] items = buffer.removeAll();
+        assertTrue("Incorrect number of items", items.length == 1);
+
+        assertTrue(buffer.isEmpty());
+        buffer.add(1);
+        buffer.add(2);
+        buffer.add(3);
+        buffer.add(4);
+        items = buffer.removeAll();
+        assertTrue("Incorrect number of items", items.length == 3);
+        assertTrue(buffer.isEmpty());
+    }
+
+
+    @Test
+    public void testDelivery() {
+        final SMTPAppender appender = SMTPAppender.createAppender("Test", "to@example.com", "cc@example.com", "bcc@example.com", "from@example.com",
+            "replyTo@example.com", "Subject", null, HOST, PORT, null, null, "false", "3", null, null,
+            "true");
+        appender.start();
+
+        final LoggerContext context = (LoggerContext) LogManager.getContext();
+        final Logger root = context.getLogger("SMTPAppenderTest");
+        root.addAppender(appender);
+        root.setAdditive(false);
+        root.setLevel(Level.DEBUG);
+
+        final SimpleSmtpServer server = SimpleSmtpServer.start(PORTNUM);
+
+        root.debug("Debug message #1");
+        root.debug("Debug message #2");
+        root.debug("Debug message #3");
+        root.error("Error with exception", new RuntimeException("Exception message"));
+
+        server.stop();
+        assertTrue(server.getReceivedEmailSize() == 1);
+        SmtpMessage email = (SmtpMessage) server.getReceivedEmail().next();
+
+        assertEquals("to@example.com", email.getHeaderValue("To"));
+        assertEquals("cc@example.com", email.getHeaderValue("Cc"));
+        // assertEquals("bcc@example.com", email.getHeaderValue("Bcc")); // BCC
+        // can't be tested with Dumpster 1.6
+        assertEquals("from@example.com", email.getHeaderValue("From"));
+        assertEquals("replyTo@example.com", email.getHeaderValue("Reply-To"));
+        assertEquals("Subject", email.getHeaderValue("Subject"));
+
+        String body = email.getBody();
+        assertFalse(body.contains("Debug message #1"));
+        assertTrue(body.contains("Debug message #2"));
+        assertTrue(body.contains("Debug message #3"));
+        assertTrue(body.contains("Error with exception"));
+        assertTrue(body.contains("RuntimeException"));
+        assertTrue(body.contains("Exception message"));
+    }
+}
+

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java Wed Dec 26 19:50:03 2012
@@ -23,6 +23,7 @@ import org.apache.logging.log4j.core.Log
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.Logger;
 
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.junit.Before;
@@ -57,8 +58,6 @@ public class PatternParserTest {
     private static String nestedPattern =
         "%highlight{%d{dd MMM yyyy HH:mm:ss,SSS}{GMT+0} [%t] %-5level: %msg%n%throwable}";
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
-
     private static final String KEY = "Converter";
     private PatternParser parser;
 
@@ -104,7 +103,7 @@ public class PatternParserTest {
             formatter.format(event, buf);
         }
         final String str = buf.toString();
-        final String expected = "INFO  [PatternParserTest        :97  ] - Hello, world" + LINE_SEP;
+        final String expected = "INFO  [PatternParserTest        :96  ] - Hello, world" + Constants.LINE_SEP;
         assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
     }
 
@@ -122,7 +121,7 @@ public class PatternParserTest {
             formatter.format(event, buf);
         }
         final String str = buf.toString();
-        final String expected = String.format("] INFO : Hello, world%s\u001B[m", LINE_SEP);
+        final String expected = String.format("] INFO : Hello, world%s\u001B[m", Constants.LINE_SEP);
         assertTrue(" Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
     }
 

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest.java Wed Dec 26 19:50:03 2012
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.LogManag
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.junit.Test;
@@ -32,7 +33,6 @@ import static org.junit.Assert.assertEqu
  */
 public class RegexReplacementConverterTest {
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
     @Test
     public void testReplacement() {
         ThreadContext.put("MyKey", "Apache");
@@ -46,7 +46,7 @@ public class RegexReplacementConverterTe
         final RegexReplacementConverter converter = RegexReplacementConverter.newInstance(ctx.getConfiguration(),
             options);
         converter.format(event, sb);
-        assertEquals("org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest This is a test" + LINE_SEP,
-            sb.toString());
+        assertEquals("org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest This is a test" +
+            Constants.LINE_SEP, sb.toString());
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java Wed Dec 26 19:50:03 2012
@@ -20,6 +20,7 @@ import org.apache.logging.log4j.LogManag
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.test.appender.ListAppender;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
@@ -44,9 +45,8 @@ public class RegexReplacementTest {
     private static ListAppender app;
     private static ListAppender app2;
     private static LoggerContext ctx;
-    
-    private static final String LINE_SEP = System.getProperty("line.separator");
-    private static final String EXPECTED = "/RegexReplacementTest" + LINE_SEP;
+
+    private static final String EXPECTED = "/RegexReplacementTest" + Constants.LINE_SEP;
 
     @BeforeClass
     public static void setupClass() {
@@ -87,7 +87,7 @@ public class RegexReplacementTest {
         msgs = app.getMessages();
         assertNotNull(msgs);
         assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
-        assertEquals("LoggerTest This is a test for Apache" + LINE_SEP , msgs.get(0));
+        assertEquals("LoggerTest This is a test for Apache" + Constants.LINE_SEP , msgs.get(0));
         app.clear();
 
     }

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java Wed Dec 26 19:50:03 2012
@@ -20,6 +20,7 @@ import org.apache.logging.log4j.LogManag
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.test.appender.ListAppender;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
@@ -43,9 +44,9 @@ public class StyleConverterTest {
     private static ListAppender app;
     private static LoggerContext ctx;
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
-
-    private static final String EXPECTED = "\u001B[1;31mERROR\u001B[m \u001B[1;36mLoggerTest\u001B[m o.a.l.l.c.p.StyleConverterTest org.apache.logging.log4j.core.pattern.StyleConverterTest" + LINE_SEP;
+    private static final String EXPECTED =
+        "\u001B[1;31mERROR\u001B[m \u001B[1;36mLoggerTest\u001B[m o.a.l.l.c.p.StyleConverterTest org.apache.logging.log4j.core.pattern.StyleConverterTest"
+        + Constants.LINE_SEP;
 
     @BeforeClass
     public static void setupClass() {

Modified: logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEmbeddedManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEmbeddedManager.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEmbeddedManager.java (original)
+++ logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEmbeddedManager.java Wed Dec 26 19:50:03 2012
@@ -24,6 +24,7 @@ import org.apache.flume.node.nodemanager
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 import org.apache.logging.log4j.core.config.ConfigurationException;
 import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.helpers.NameUtil;
 
 import java.security.MessageDigest;
 import java.util.Locale;
@@ -106,22 +107,7 @@ public class FlumeEmbeddedManager extend
                 props.append(prop.getName()).append("=").append(prop.getValue());
                 sep = ",";
             }
-            try {
-                final MessageDigest digest = MessageDigest.getInstance("MD5");
-                digest.update(sb.toString().getBytes());
-                final byte[] bytes = digest.digest();
-                final StringBuilder md5 = new StringBuilder();
-                for (final byte b : bytes) {
-                    final String hex = Integer.toHexString(0xff & b);
-                    if (hex.length() == 1) {
-                        md5.append('0');
-                    }
-                    md5.append(hex);
-                }
-                sb.append(md5.toString());
-            } catch (final Exception ex) {
-                sb.append(props);
-            }
+            sb.append(NameUtil.md5(props.toString()));
         }
         return (FlumeEmbeddedManager) getManager(sb.toString(), factory,
             new FactoryData(name, agents, properties, batchSize, dataDir));

Modified: logging/log4j/log4j2/trunk/jcl-bridge/src/test/java/org/apache/logging/log4j/jcl/LoggerTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/jcl-bridge/src/test/java/org/apache/logging/log4j/jcl/LoggerTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/jcl-bridge/src/test/java/org/apache/logging/log4j/jcl/LoggerTest.java (original)
+++ logging/log4j/log4j2/trunk/jcl-bridge/src/test/java/org/apache/logging/log4j/jcl/LoggerTest.java Wed Dec 26 19:50:03 2012
@@ -21,6 +21,7 @@ import org.apache.commons.logging.LogFac
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.test.appender.ListAppender;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
@@ -43,8 +44,6 @@ public class LoggerTest {
 
     private static final String CONFIG = "log4j-test1.xml";
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
-
     @BeforeClass
     public static void setupClass() {
         System.setProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY, CONFIG);
@@ -65,13 +64,13 @@ public class LoggerTest {
     @Test
     public void testLog() {
         logger.debug("Test message");
-        verify("List", "o.a.l.l.j.LoggerTest Test message MDC{}" + LINE_SEP);
+        verify("List", "o.a.l.l.j.LoggerTest Test message MDC{}" + Constants.LINE_SEP);
         logger.debug("Exception: " , new NullPointerException("Test"));
-        verify("List", "o.a.l.l.j.LoggerTest Exception:  MDC{}" + LINE_SEP);
+        verify("List", "o.a.l.l.j.LoggerTest Exception:  MDC{}" + Constants.LINE_SEP);
         logger.info("Info Message");
-        verify("List", "o.a.l.l.j.LoggerTest Info Message MDC{}" + LINE_SEP);
+        verify("List", "o.a.l.l.j.LoggerTest Info Message MDC{}" + Constants.LINE_SEP);
         logger.info("Info Message {}");
-        verify("List", "o.a.l.l.j.LoggerTest Info Message {} MDC{}" + LINE_SEP);
+        verify("List", "o.a.l.l.j.LoggerTest Info Message {} MDC{}" + Constants.LINE_SEP);
     }
 
     private void verify(final String name, final String expected) {

Modified: logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Layout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Layout.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Layout.java (original)
+++ logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/Layout.java Wed Dec 26 19:50:03 2012
@@ -17,6 +17,7 @@
 package org.apache.log4j;
 
 import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.core.helpers.Constants;
 
 /**
  *
@@ -25,8 +26,7 @@ public abstract class Layout {
 
     // Note that the line.separator property can be looked up even by
     // applets.
-    public final static String LINE_SEP = System.getProperty("line.separator");
-    public final static int LINE_SEP_LEN = LINE_SEP.length();
+    public final static int LINE_SEP_LEN = Constants.LINE_SEP.length();
 
 
     /**

Modified: logging/log4j/log4j2/trunk/log4j12-api/src/test/java/org/apache/log4j/CategoryTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j12-api/src/test/java/org/apache/log4j/CategoryTest.java?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j12-api/src/test/java/org/apache/log4j/CategoryTest.java (original)
+++ logging/log4j/log4j2/trunk/log4j12-api/src/test/java/org/apache/log4j/CategoryTest.java Wed Dec 26 19:50:03 2012
@@ -20,6 +20,7 @@ package org.apache.log4j;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.helpers.Constants;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.ObjectMessage;
 import org.apache.logging.log4j.test.appender.ListAppender;
@@ -45,8 +46,6 @@ public class CategoryTest {
 
     static ConfigurationFactory cf = new BasicConfigurationFactory();
 
-    private static final String LINE_SEP = System.getProperty("line.separator");
-
     private static ListAppender appender = new ListAppender("List");
 
     @BeforeClass
@@ -175,7 +174,7 @@ public class CategoryTest {
         final String msg = msgs.get(0);
         appender.clear();
         final String threadName = Thread.currentThread().getName();
-        final String expected = "ERROR o.a.l.CategoryTest [" + threadName + "] Test Message" + LINE_SEP;
+        final String expected = "ERROR o.a.l.CategoryTest [" + threadName + "] Test Message" + Constants.LINE_SEP;
         assertTrue("Incorrect message \"" + msg + "\"" + " expected \"" + expected +"\"", msg.endsWith(expected));
     }
 

Modified: logging/log4j/log4j2/trunk/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/pom.xml?rev=1426001&r1=1426000&r2=1426001&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/pom.xml (original)
+++ logging/log4j/log4j2/trunk/pom.xml Wed Dec 26 19:50:03 2012
@@ -97,6 +97,7 @@
     <logback.version>1.0.7</logback.version>
     <log4jParentDir>${basedir}</log4jParentDir>
     <Log4jReleaseVersion>2.0-beta3</Log4jReleaseVersion>
+    <jackson.version>1.9.2</jackson.version>
     <!-- Configuration properties for the OSGi maven-bundle-plugin -->
     <osgi.symbolicName>org.apache.logging.${project.artifactId}</osgi.symbolicName>
     <osgi.export>org.apache.logging.log4j.*;version=${project.version};-noimport:=true</osgi.export>
@@ -178,6 +179,57 @@
         <artifactId>log4j-1.2-api</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.osgi</groupId>
+        <artifactId>core</artifactId>
+        <version>4.3.0</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>oro</groupId>
+        <artifactId>oro</artifactId>
+        <version>2.0.8</version>
+      </dependency>
+      <dependency>
+        <groupId>org.fusesource.jansi</groupId>
+        <artifactId>jansi</artifactId>
+        <version>1.9</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.jackson</groupId>
+        <artifactId>jackson-core-asl</artifactId>
+        <version>${jackson.version}</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <groupId>org.codehaus.jackson</groupId>
+        <artifactId>jackson-mapper-asl</artifactId>
+        <version>${jackson.version}</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <groupId>javax.mail</groupId>
+        <artifactId>mail</artifactId>
+        <version>1.4.5</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-jms_1.1_spec</artifactId>
+        <version>1.0</version>
+      </dependency>
+      <dependency>
+        <groupId>org.mockejb</groupId>
+        <artifactId>mockejb</artifactId>
+        <version>0.6-beta2</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>dumbster</groupId>
+        <artifactId>dumbster</artifactId>
+        <version>1.6</version>
+        <scope>test</scope>
+      </dependency>
  	    <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>servlet-api</artifactId>
@@ -187,7 +239,7 @@
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
-        <version>4.3.1</version>
+        <version>4.7</version>
         <scope>test</scope>
       </dependency>
     </dependencies>