You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sd...@apache.org on 2013/02/28 08:57:51 UTC

svn commit: r1451133 [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/appender/rolling/ core/s...

Author: sdeboy
Date: Thu Feb 28 07:57:49 2013
New Revision: 1451133

URL: http://svn.apache.org/r1451133
Log:
Implementing LOG4J2-155: add getFormat to Layout

https://issues.apache.org/jira/browse/LOG4J2-155

Exposing an advertiser attribute on existing configuration implementations and providing a default Multicast DNS advertiser implementation.

Implementing support for advertisement in socket-based appenders, FileAppender and RollingFileAppender.

While the Advertiser implementation class is specified on the configuration, enabling advertisement is on a per-appender basis, and may require additional attributes (for example, FileAppender requires and advertiseURI attribute).

With a follow-on update to Chainsaw, Chainsaw will be able to discover the published appender entries and automatically begin tailing the appender with no user configuration required.

Also committed tests which verified:
  - only appenders with 'advertise=true' are actually advertised
  - the appender is 'unadvertised' when configuration.stop() is called
  - the appender is re-advertised when configuration.reconfigure() is subsequently called
  
  Updated docs in the 'configuration' section of the manual

Added:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/Advertiser.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MulticastDNSAdvertiser.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/AdvertiserTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/InMemoryAdvertiser.java
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j-advertiser.xml
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/appender/AbstractManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.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/PatternLayout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.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/SyslogLayout.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/net/AbstractSocketManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/DatagramSocketManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/TCPSocketManager.java
    logging/log4j/log4j2/trunk/core/src/main/resources/Log4J-V2.0.xsd
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SyslogAppenderTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/net/SocketServerTest.java
    logging/log4j/log4j2/trunk/pom.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/index.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm

Modified: logging/log4j/log4j2/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/pom.xml?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/pom.xml (original)
+++ logging/log4j/log4j2/trunk/core/pom.xml Thu Feb 28 07:57:49 2013
@@ -59,6 +59,12 @@
       <optional>true</optional>
     </dependency>
     <dependency>
+      <groupId>javax.jmdns</groupId>
+      <artifactId>jmdns</artifactId>
+      <version>3.4.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>oro</groupId>
       <artifactId>oro</artifactId>
       <scope>test</scope>

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=1451133&r1=1451132&r2=1451133&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 Thu Feb 28 07:57:49 2013
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.core;
 
 import java.io.Serializable;
+import java.util.Map;
 
 /**
  * Lays out a {@linkplain LogEvent} in different formats.
@@ -26,7 +27,7 @@ import java.io.Serializable;
  * <li>
  * {@code byte[]}</li>
  * <li>
- * an implementor of {@linkplain Serializable}, like {@code byte[]}</li>
+ * an implementer of {@linkplain Serializable}, like {@code byte[]}</li>
  * <li>
  * {@linkplain String}</li>
  * <li>
@@ -83,4 +84,12 @@ public interface Layout<T extends Serial
      * @return the content type.
      */
     String getContentType();
+
+    /**
+     * Returns a description of the content format.
+     *
+     * @return a Map of key/value pairs describing the Layout-specific content format, or an empty Map if no content format descriptors are specified. 
+     * 
+     */
+    Map<String, String> getContentFormat();
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java Thu Feb 28 07:57:49 2013
@@ -95,7 +95,7 @@ public abstract class AbstractManager {
     }
 
     /**
-     * May be overriden by Managers to perform processing while the Manager is being released and the
+     * May be overridden by Managers to perform processing while the Manager is being released and the
      * lock is held.
      */
     protected void releaseSub() {
@@ -129,4 +129,14 @@ public abstract class AbstractManager {
     public String getName() {
         return name;
     }
+
+    /**
+     * Provide a description of the content format supported by this Manager.  Default implementation returns an empty (unspecified) Map.
+     *
+     * @return a Map of key/value pairs describing the Manager-specific content format, or an empty Map if no content format descriptors are specified. 
+     *
+     */
+    public Map<String, String> getContentFormat() {
+        return new HashMap<String, String>();
+    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileAppender.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileAppender.java Thu Feb 28 07:57:49 2013
@@ -16,13 +16,18 @@
  */
 package org.apache.logging.log4j.core.appender;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.config.Configuration;
 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.PluginConfiguration;
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
 import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.net.Advertiser;
 
 /**
  * File Appender.
@@ -31,11 +36,30 @@ import org.apache.logging.log4j.core.lay
 public final class FileAppender extends AbstractOutputStreamAppender {
 
     private final String fileName;
+    private final Advertiser advertiser;
+    private Object advertisement;
 
     private FileAppender(final String name, final Layout layout, final Filter filter, final FileManager manager,
-                         final String filename, final boolean handleException, final boolean immediateFlush) {
+                         final String filename, final boolean handleException, final boolean immediateFlush, Advertiser advertiser) {
         super(name, layout, filter, handleException, immediateFlush, manager);
+        if (advertiser != null)
+        {
+            Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
+            configuration.putAll(manager.getContentFormat());
+            configuration.put("contentType", layout.getContentType());
+            configuration.put("name", name);
+            advertisement = advertiser.advertise(configuration);
+        }
         this.fileName = filename;
+        this.advertiser = advertiser;
+    }
+
+    @Override
+    public void stop() {
+        super.stop();
+        if (advertiser != null) {
+            advertiser.unadvertise(advertisement);
+        }
     }
 
     /**
@@ -61,6 +85,9 @@ public final class FileAppender extends 
      * @param layout The layout to use to format the event. If no layout is provided the default PatternLayout
      * will be used.
      * @param filter The filter, if any, to use.
+     * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
+     * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
+     * @param config The Configuration               
      * @return The FileAppender.
      */
     @PluginFactory
@@ -72,14 +99,18 @@ public final class FileAppender extends 
                                               @PluginAttr("suppressExceptions") final String suppress,
                                               @PluginAttr("bufferedIO") final String bufferedIO,
                                               @PluginElement("layout") Layout layout,
-                                              @PluginElement("filters") final Filter filter) {
+                                              @PluginElement("filters") final Filter filter,
+                                              @PluginAttr("advertise") final String advertise,
+                                              @PluginAttr("advertiseURI") final String advertiseURI,
+                                              @PluginConfiguration final Configuration config) {
 
         final boolean isAppend = append == null ? true : Boolean.valueOf(append);
         final boolean isLocking = locking == null ? false : Boolean.valueOf(locking);
         boolean isBuffered = bufferedIO == null ? true : Boolean.valueOf(bufferedIO);
+        boolean isAdvertise = advertise == null ? false : Boolean.valueOf(advertise);
         if (isLocking && isBuffered) {
             if (bufferedIO != null) {
-                LOGGER.warn("Locking and buffering are mutually exclusive. No buffereing will occur for " + fileName);
+                LOGGER.warn("Locking and buffering are mutually exclusive. No buffering will occur for " + fileName);
             }
             isBuffered = false;
         }
@@ -96,13 +127,14 @@ public final class FileAppender extends 
             return null;
         }
 
-        final FileManager manager = FileManager.getFileManager(fileName, isAppend, isLocking, isBuffered);
+        final FileManager manager = FileManager.getFileManager(fileName, isAppend, isLocking, isBuffered, advertiseURI);
         if (manager == null) {
             return null;
         }
         if (layout == null) {
             layout = PatternLayout.createLayout(null, null, null, null);
         }
-        return new FileAppender(name, layout, filter, manager, fileName, handleExceptions, isFlush);
+
+        return new FileAppender(name, layout, filter, manager, fileName, handleExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FileManager.java Thu Feb 28 07:57:49 2013
@@ -24,6 +24,8 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
+import java.util.HashMap;
+import java.util.Map;
 
 
 /**
@@ -35,11 +37,13 @@ public class FileManager extends OutputS
 
     private final boolean isAppend;
     private final boolean isLocking;
+    private final String advertiseURI;
 
-    protected FileManager(final String fileName, final OutputStream os, final boolean append, final boolean locking) {
+    protected FileManager(final String fileName, final OutputStream os, final boolean append, final boolean locking, String advertiseURI) {
         super(os, fileName);
         this.isAppend = append;
         this.isLocking = locking;
+        this.advertiseURI = advertiseURI;
     }
 
     /**
@@ -48,15 +52,16 @@ public class FileManager extends OutputS
      * @param append true if the file should be appended to, false if it should be overwritten.
      * @param locking true if the file should be locked while writing, false otherwise.
      * @param bufferedIO true if the contents should be buffered as they are written.
+     * @param advertiseURI the URI to use when advertising the file
      * @return A FileManager for the File.
      */
     public static FileManager getFileManager(final String fileName, final boolean append, boolean locking,
-                                             final boolean bufferedIO) {
+                                             final boolean bufferedIO, String advertiseURI) {
 
         if (locking && bufferedIO) {
             locking = false;
         }
-        return (FileManager) getManager(fileName, new FactoryData(append, locking, bufferedIO), FACTORY);
+        return (FileManager) getManager(fileName, new FactoryData(append, locking, bufferedIO, advertiseURI), FACTORY);
     }
 
     @Override
@@ -112,23 +117,38 @@ public class FileManager extends OutputS
     }
 
     /**
+     * FileManager's content format is specified by:<p/>
+     * Key: "fileURI" Value: provided "advertiseURI" param
+     * @return Map of content format keys supporting FileManager
+     */
+    public Map<String, String> getContentFormat()
+    {
+        Map<String, String> result = new HashMap<String, String>(super.getContentFormat());
+        result.put("fileURI", advertiseURI);
+        return result;
+    }
+
+    /**
      * Factory Data.
      */
     private static class FactoryData {
         private final boolean append;
         private final boolean locking;
         private final boolean bufferedIO;
+        private final String advertiseURI;
 
         /**
          * Constructor.
          * @param append Append status.
          * @param locking Locking status.
          * @param bufferedIO Buffering flag.
+         * @param advertiseURI the URI to use when advertising the file
          */
-        public FactoryData(final boolean append, final boolean locking, final boolean bufferedIO) {
+        public FactoryData(final boolean append, final boolean locking, final boolean bufferedIO, String advertiseURI) {
             this.append = append;
             this.locking = locking;
             this.bufferedIO = bufferedIO;
+            this.advertiseURI = advertiseURI;
         }
     }
 
@@ -156,7 +176,7 @@ public class FileManager extends OutputS
                 if (data.bufferedIO) {
                     os = new BufferedOutputStream(os);
                 }
-                return new FileManager(name, os, data.append, data.locking);
+                return new FileManager(name, os, data.append, data.locking, data.advertiseURI);
             } catch (final FileNotFoundException ex) {
                 LOGGER.error("FileManager (" + name + ") " + ex);
             }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java Thu Feb 28 07:57:49 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.appender;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
@@ -30,23 +32,43 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
 import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.net.Advertiser;
 
 /**
- * An appender that writes to files andd can roll over at intervals.
+ * An appender that writes to files and can roll over at intervals.
  */
 @Plugin(name = "RollingFile", type = "Core", elementType = "appender", printObject = true)
 public final class RollingFileAppender extends AbstractOutputStreamAppender {
 
     private final String fileName;
     private final String filePattern;
+    private Object advertisement;
+    private final Advertiser advertiser;
 
 
     private RollingFileAppender(final String name, final Layout layout, final Filter filter,
                                 final RollingFileManager manager, final String fileName,
-                                final String filePattern, final boolean handleException, final boolean immediateFlush) {
+                                final String filePattern, final boolean handleException, final boolean immediateFlush,
+                                Advertiser advertiser) {
         super(name, layout, filter, handleException, immediateFlush, manager);
+        if (advertiser != null)
+        {
+            Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
+            configuration.put("contentType", layout.getContentType());
+            configuration.put("name", name);
+            advertisement = advertiser.advertise(configuration);
+        }
         this.fileName = fileName;
         this.filePattern = filePattern;
+        this.advertiser = advertiser;
+    }
+
+    @Override
+    public void stop() {
+        super.stop();
+        if (advertiser != null) {
+            advertiser.unadvertise(advertisement);
+        }
     }
 
     /**
@@ -91,6 +113,8 @@ public final class RollingFileAppender e
      * @param filter The Filter or null.
      * @param suppress "true" if exceptions should be hidden from the application, "false" otherwise.
      * The default is "true".
+     * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
+     * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
      * @param config The Configuration.
      * @return A RollingFileAppender.
      */
@@ -106,13 +130,15 @@ public final class RollingFileAppender e
                                               @PluginElement("layout") Layout layout,
                                               @PluginElement("filter") final Filter filter,
                                               @PluginAttr("suppressExceptions") final String suppress,
+                                              @PluginAttr("advertise") final String advertise,
+                                              @PluginAttr("advertiseURI") final String advertiseURI,
                                               @PluginConfiguration final Configuration config) {
 
         final boolean isAppend = append == null ? true : Boolean.valueOf(append);
         final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
         final boolean isBuffered = bufferedIO == null ? true : Boolean.valueOf(bufferedIO);
         final boolean isFlush = immediateFlush == null ? true : Boolean.valueOf(immediateFlush);
-
+        boolean isAdvertise = advertise == null ? false : Boolean.valueOf(advertise);
         if (name == null) {
             LOGGER.error("No name provided for FileAppender");
             return null;
@@ -138,7 +164,7 @@ public final class RollingFileAppender e
         }
 
         final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend,
-            isBuffered, policy, strategy);
+            isBuffered, policy, strategy, advertiseURI);
         if (manager == null) {
             return null;
         }
@@ -148,6 +174,6 @@ public final class RollingFileAppender e
         }
 
         return new RollingFileAppender(name, layout, filter, manager, fileName, filePattern,
-            handleExceptions, isFlush);
+            handleExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java Thu Feb 28 07:57:49 2013
@@ -16,14 +16,19 @@
  */
 package org.apache.logging.log4j.core.appender;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.config.Configuration;
 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.PluginConfiguration;
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
 import org.apache.logging.log4j.core.layout.SerializedLayout;
 import org.apache.logging.log4j.core.net.AbstractSocketManager;
+import org.apache.logging.log4j.core.net.Advertiser;
 import org.apache.logging.log4j.core.net.DatagramSocketManager;
 import org.apache.logging.log4j.core.net.Protocol;
 import org.apache.logging.log4j.core.net.TCPSocketManager;
@@ -34,13 +39,30 @@ import org.apache.logging.log4j.util.Eng
  */
 @Plugin(name = "Socket", type = "Core", elementType = "appender", printObject = true)
 public class SocketAppender extends AbstractOutputStreamAppender {
-
+    private Object advertisement;
+    private final Advertiser advertiser;
 
     protected SocketAppender(final String name, final Layout layout, final Filter filter,
                              final AbstractSocketManager manager, final boolean handleException,
-                             final boolean immediateFlush) {
+                             final boolean immediateFlush, Advertiser advertiser) {
         super(name, layout, filter, handleException, immediateFlush, manager);
+        if (advertiser != null)
+        {
+            Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
+            configuration.putAll(manager.getContentFormat());
+            configuration.put("contentType", layout.getContentType());
+            configuration.put("name", name);
+            advertisement = advertiser.advertise(configuration);
+        }
+        this.advertiser = advertiser;
+    }
 
+    @Override
+    public void stop() {
+        super.stop();
+        if (advertiser != null) {
+            advertiser.unadvertise(advertisement);
+        }
     }
 
     /**
@@ -55,6 +77,8 @@ public class SocketAppender extends Abst
      * The default is "true".
      * @param layout The layout to use (defaults to SerializedLayout).
      * @param filter The Filter or null.
+     * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
+     * @param config The Configuration               
      * @return A SocketAppender.
      */
     @PluginFactory
@@ -66,9 +90,12 @@ public class SocketAppender extends Abst
                                                 @PluginAttr("immediateFlush") final String immediateFlush,
                                                 @PluginAttr("suppressExceptions") final String suppress,
                                                 @PluginElement("layout") Layout layout,
-                                                @PluginElement("filters") final Filter filter) {
+                                                @PluginElement("filters") final Filter filter,
+                                                @PluginAttr("advertise") final String advertise,
+                                                @PluginConfiguration final Configuration config) {
 
         final boolean isFlush = immediateFlush == null ? true : Boolean.valueOf(immediateFlush);
+        boolean isAdvertise = advertise == null ? false : Boolean.valueOf(advertise);
         final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
         final int reconnectDelay = delay == null ? 0 : Integer.parseInt(delay);
         final int port = portNum == null ? 0 : Integer.parseInt(portNum);
@@ -87,7 +114,8 @@ public class SocketAppender extends Abst
         if (manager == null) {
             return null;
         }
-        return new SocketAppender(name, layout, filter, manager, handleExceptions, isFlush);
+
+        return new SocketAppender(name, layout, filter, manager, handleExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
     }
 
     protected static AbstractSocketManager createSocketManager(final String protocol, final String host, final int port,

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java Thu Feb 28 07:57:49 2013
@@ -27,6 +27,7 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.layout.RFC5424Layout;
 import org.apache.logging.log4j.core.layout.SyslogLayout;
 import org.apache.logging.log4j.core.net.AbstractSocketManager;
+import org.apache.logging.log4j.core.net.Advertiser;
 import org.apache.logging.log4j.core.net.Protocol;
 
 /**
@@ -40,8 +41,8 @@ public class SyslogAppender extends Sock
     private static final String RFC5424 = "RFC5424";
 
     protected SyslogAppender(final String name, final Layout layout, final Filter filter, final boolean handleException,
-                             final boolean immediateFlush, final AbstractSocketManager manager) {
-        super(name, layout, filter, manager, handleException, immediateFlush);
+                             final boolean immediateFlush, final AbstractSocketManager manager, Advertiser advertiser) {
+        super(name, layout, filter, manager, handleException, immediateFlush, advertiser);
 
     }
 
@@ -100,12 +101,14 @@ public class SyslogAppender extends Sock
                                                 @PluginElement("filters") final Filter filter,
                                                 @PluginConfiguration final Configuration config,
                                                 @PluginAttr("charset") final String charsetName,
-                                                @PluginAttr("exceptionPattern") final String exceptionPattern) {
+                                                @PluginAttr("exceptionPattern") final String exceptionPattern,
+                                                @PluginAttr("advertise") final String advertise) {
 
         final boolean isFlush = immediateFlush == null ? true : Boolean.valueOf(immediateFlush);
         final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
         final int reconnectDelay = delay == null ? 0 : Integer.parseInt(delay);
         final int port = portNum == null ? 0 : Integer.parseInt(portNum);
+        boolean isAdvertise = advertise == null ? false : Boolean.valueOf(advertise);
         final Layout<String> layout = RFC5424.equalsIgnoreCase(format) ?
             RFC5424Layout.createLayout(facility, id, ein, includeMDC, mdcId, includeNL, escapeNL, appName,
                 msgId, excludes, includes, required, charsetName, exceptionPattern, config) :
@@ -121,6 +124,6 @@ public class SyslogAppender extends Sock
             return null;
         }
 
-        return new SyslogAppender(name, layout, filter, handleExceptions, isFlush, manager);
+        return new SyslogAppender(name, layout, filter, handleExceptions, isFlush, manager, isAdvertise ? config.getAdvertiser() : null);
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java Thu Feb 28 07:57:49 2013
@@ -46,8 +46,8 @@ public class RollingFileManager extends 
 
     protected RollingFileManager(final String fileName, final String pattern, final OutputStream os,
                                  final boolean append, final long size, final long time, final TriggeringPolicy policy,
-                                 final RolloverStrategy strategy) {
-        super(fileName, os, append, false);
+                                 final RolloverStrategy strategy, String advertiseURI) {
+        super(fileName, os, append, false, advertiseURI);
         this.size = size;
         this.initialTime = time;
         this.policy = policy;
@@ -64,14 +64,15 @@ public class RollingFileManager extends 
      * @param bufferedIO true if data should be buffered.
      * @param policy The TriggeringPolicy.
      * @param strategy The RolloverStrategy.
+     * @param advertiseURI the URI to use when advertising the file
      * @return A RollingFileManager.
      */
     public static RollingFileManager getFileManager(final String fileName, final String pattern, final boolean append,
                                                     final boolean bufferedIO, final TriggeringPolicy policy,
-                                                    final RolloverStrategy strategy) {
+                                                    final RolloverStrategy strategy, String advertiseURI) {
 
         return (RollingFileManager) getManager(fileName, new FactoryData(pattern, append,
-            bufferedIO, policy, strategy), factory);
+            bufferedIO, policy, strategy, advertiseURI), factory);
     }
 
     @Override
@@ -228,20 +229,23 @@ public class RollingFileManager extends 
         private final boolean bufferedIO;
         private final TriggeringPolicy policy;
         private final RolloverStrategy strategy;
+        private final String advertiseURI;
 
         /**
          * Create the data for the factory.
          * @param pattern The pattern.
          * @param append The append flag.
          * @param bufferedIO The bufferedIO flag.
+         * @param advertiseURI
          */
         public FactoryData(final String pattern, final boolean append, final boolean bufferedIO,
-                           final TriggeringPolicy policy, final RolloverStrategy strategy) {
+                           final TriggeringPolicy policy, final RolloverStrategy strategy, String advertiseURI) {
             this.pattern = pattern;
             this.append = append;
             this.bufferedIO = bufferedIO;
             this.policy = policy;
             this.strategy = strategy;
+            this.advertiseURI = advertiseURI;
         }
     }
 
@@ -278,7 +282,7 @@ public class RollingFileManager extends 
                     os = new BufferedOutputStream(os);
                 }
                 return new RollingFileManager(name, data.pattern, os, data.append, size, time, data.policy,
-                    data.strategy);
+                    data.strategy, data.advertiseURI);
             } catch (final FileNotFoundException ex) {
                 LOGGER.error("FileManager (" + name + ") " + ex);
             }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java Thu Feb 28 07:57:49 2013
@@ -38,6 +38,7 @@ import org.apache.logging.log4j.core.loo
 import org.apache.logging.log4j.core.lookup.MapLookup;
 import org.apache.logging.log4j.core.lookup.StrLookup;
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
+import org.apache.logging.log4j.core.net.Advertiser;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.PropertiesUtil;
 
@@ -83,6 +84,11 @@ public class BaseConfiguration extends A
      */
     protected ConfigurationMonitor monitor = new DefaultConfigurationMonitor();
 
+    /**
+     * The Advertiser which exposes appender configurations to external systems.
+     */
+    protected Advertiser advertiser = new DefaultAdvertiser();
+
     private String name;
 
     private ConcurrentMap<String, Appender<?>> appenders = new ConcurrentHashMap<String, Appender<?>>();
@@ -301,10 +307,22 @@ public class BaseConfiguration extends A
         return subst;
     }
 
+    public void setConfigurationMonitor(ConfigurationMonitor monitor) {
+        this.monitor = monitor;
+    }
+    
     public ConfigurationMonitor getConfigurationMonitor() {
         return monitor;
     }
 
+    public void setAdvertiser(Advertiser advertiser) {
+        this.advertiser = advertiser;
+    }
+    
+    public Advertiser getAdvertiser() {
+        return advertiser;
+    }
+
     /**
      * Associates an Appender with a LoggerConfig. This method is synchronized in case a Logger with the
      * same name is being updated at the same time.
@@ -379,7 +397,7 @@ public class BaseConfiguration extends A
     }
 
     /**
-     * Remove an Appender. First removes any associations between LoggerContigs and the Appender, removes
+     * Remove an Appender. First removes any associations between LoggerConfigs and the Appender, removes
      * the Appender from this appender list and then stops the appender. This method is synchronized in
      * case an Appender with the same name is being added during the removal.
      * @param name the name of the appender to remove.

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java Thu Feb 28 07:57:49 2013
@@ -22,6 +22,7 @@ import org.apache.logging.log4j.core.Log
 import org.apache.logging.log4j.core.Logger;
 import org.apache.logging.log4j.core.filter.Filterable;
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
+import org.apache.logging.log4j.core.net.Advertiser;
 
 import java.util.Map;
 
@@ -79,5 +80,11 @@ public interface Configuration extends F
 
     void addComponent(String name, Object object);
 
+    void setConfigurationMonitor(ConfigurationMonitor monitor);
+    
     ConfigurationMonitor getConfigurationMonitor();
+    
+    void setAdvertiser(Advertiser advertiser);
+    
+    Advertiser getAdvertiser();
 }

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java?rev=1451133&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java Thu Feb 28 07:57:49 2013
@@ -0,0 +1,44 @@
+/*
+ * 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.config;
+
+import org.apache.logging.log4j.core.net.Advertiser;
+
+import java.util.Map;
+
+/**
+ * The default advertiser does not do anything.
+ */
+public class DefaultAdvertiser implements Advertiser {
+    /**
+     * Does nothing.
+     * 
+     * @return null
+     */
+    public Object advertise(Map<String, String> properties) {
+        return null;
+    }
+
+    /**
+     * Does nothing
+     * @param advertisedObject
+     */
+    public void unadvertise(Object advertisedObject) {
+        //no-op
+    }
+
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java Thu Feb 28 07:57:49 2013
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.config.plugins.PluginType;
 import org.apache.logging.log4j.core.config.plugins.ResolverUtil;
 import org.apache.logging.log4j.core.helpers.FileUtils;
+import org.apache.logging.log4j.core.net.Advertiser;
 import org.apache.logging.log4j.status.StatusConsoleListener;
 import org.apache.logging.log4j.status.StatusListener;
 import org.apache.logging.log4j.status.StatusLogger;
@@ -115,6 +116,11 @@ public class JSONConfiguration extends B
                     if (interval > 0 && configFile != null) {
                         monitor = new FileConfigurationMonitor(this, configFile, listeners, interval);
                     }
+                } else if ("advertiser".equalsIgnoreCase(entry.getKey())) {
+                    final String advertiserString = getSubst().replace(entry.getValue());
+                    if (advertiserString != null) {
+                        advertiser = (Advertiser) Class.forName(advertiserString).newInstance();
+                    }
                 }
             }
 

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java Thu Feb 28 07:57:49 2013
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.config.plugins.PluginType;
 import org.apache.logging.log4j.core.config.plugins.ResolverUtil;
 import org.apache.logging.log4j.core.helpers.FileUtils;
+import org.apache.logging.log4j.core.net.Advertiser;
 import org.apache.logging.log4j.status.StatusConsoleListener;
 import org.apache.logging.log4j.status.StatusListener;
 import org.apache.logging.log4j.status.StatusLogger;
@@ -139,6 +140,19 @@ public class XMLConfiguration extends Ba
                     if (interval > 0 && configFile != null) {
                         monitor = new FileConfigurationMonitor(this, configFile, listeners, interval);
                     }
+                } else if ("advertiser".equalsIgnoreCase(entry.getKey())) {
+                    final String advertiserString = getSubst().replace(entry.getValue());
+                    if (advertiserString != null) {
+                        try {
+                            advertiser = (Advertiser) Class.forName(advertiserString).newInstance();
+                        } catch (InstantiationException e) {
+                            System.err.println("InstantiationException attempting to instantiate advertiser: " + advertiserString);
+                        } catch (IllegalAccessException e) {
+                            System.err.println("IllegalAccessException attempting to instantiate advertiser: " + advertiserString);
+                        } catch (ClassNotFoundException e) {
+                            System.err.println("ClassNotFoundException attempting to instantiate advertiser: " + advertiserString);
+                        }
+                    }
                 }
             }
             final Iterator<StatusListener> iter = ((StatusLogger) LOGGER).getListeners();

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=1451133&r1=1451132&r2=1451133&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 Thu Feb 28 07:57:49 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.layout;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
@@ -111,7 +113,7 @@ public final class HTMLLayout extends Ab
      * Format as a String.
      *
      * @param event The Logging Event.
-     * @return A String containging the LogEvent as HTML.
+     * @return A String containing the LogEvent as HTML.
      */
     public String toSerializable(final LogEvent event) {
         final StringBuilder sbuf = new StringBuilder(BUF_SIZE);
@@ -190,6 +192,15 @@ public final class HTMLLayout extends Ab
         return sbuf.toString();
     }
 
+    /**
+     * HTMLLayout's format is sufficiently specified via the content type.  The format could be defined via a DTD, 
+     * but isn't at this time - returning empty Map/unspecified.
+     * @return empty Map
+     */
+    public Map<String, String> getContentFormat() {
+        return new HashMap<String, String>();
+    }
+
     @Override
     /**
      * @return The content type.

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java Thu Feb 28 07:57:49 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.layout;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
@@ -125,6 +127,22 @@ public final class PatternLayout extends
     }
 
     /**
+     * PatternLayout's content format is specified by:<p/>
+     * Key: "structured" Value: "false"<p/>
+     * Key: "formatType" Value: "conversion" (format uses the keywords supported by OptionConverter)<p/>
+     * Key: "format" Value: provided "conversionPattern" param
+     * @return Map of content format keys supporting PatternLayout
+     */
+    public Map<String, String> getContentFormat()
+    {
+        Map<String, String> result = new HashMap<String, String>();
+        result.put("structured", "false");
+        result.put("formatType", "conversion");
+        result.put("format", conversionPattern);
+        return result;
+    }
+
+    /**
      * Formats a logging event to a writer.
      *
      *

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java Thu Feb 28 07:57:49 2013
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.layout;
 
+import java.util.HashMap;
 import org.apache.logging.log4j.LoggingException;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.Configuration;
@@ -185,6 +186,20 @@ public final class RFC5424Layout extends
     }
 
     /**
+     * RFC5424Layout's content format is specified by:<p/>
+     * Key: "structured" Value: "true"<p/>
+     * Key: "format" Value: "RFC5424"<p/>
+     * @return Map of content format keys supporting RFC5424Layout
+     */
+    public Map<String, String> getContentFormat()
+    {
+        Map<String, String> result = new HashMap<String, String>();
+        result.put("structured", "true");
+        result.put("formatType", "RFC5424");
+        return result;
+    }
+
+    /**
      * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the RFC 5424 Syslog specification.
      *
      * @param event The LogEvent.

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=1451133&r1=1451132&r2=1451133&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 Thu Feb 28 07:57:49 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.layout;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
@@ -48,7 +50,7 @@ public final class SerializedLayout exte
     }
 
     /**
-     * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the log4j.dtd.
+     * Formats a {@link org.apache.logging.log4j.core.LogEvent} as a serialized byte array of the LogEvent object.
      *
      * @param event The LogEvent.
      * @return the formatted LogEvent.
@@ -95,6 +97,14 @@ public final class SerializedLayout exte
     }
 
     /**
+     * SerializedLayout's format is sufficiently specified via the content type, use empty Map/unspecified.
+     * @return empty Map
+     */
+    public Map<String, String> getContentFormat() {
+        return new HashMap<String, String>();    
+    }
+
+    /**
      * SerializedLayout returns a binary stream.
      * @return The content type.
      */

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java Thu Feb 28 07:57:49 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.layout;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
@@ -67,7 +69,7 @@ public class SyslogLayout extends Abstra
     }
 
     /**
-     * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the log4j.dtd.
+     * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the BSD Log record format.
      *
      * @param event The LogEvent
      * @return the event formatted as a String.
@@ -122,6 +124,24 @@ public class SyslogLayout extends Abstra
     }
 
     /**
+     * SyslogLayout's content format is specified by:<p/>
+     * Key: "structured" Value: "false"<p/>
+     * Key: "dateFormat" Value: "MMM dd HH:mm:ss "<p/>
+     * Key: "format" Value: "<LEVEL>TIMESTAMP PROP(HOSTNAME) MESSAGE"<p/>
+     * Key: "formatType" Value: "logfilepatternreceiver" (format uses the keywords supported by LogFilePatternReceiver)
+     * @return Map of content format keys supporting SyslogLayout
+     */
+    public Map<String, String> getContentFormat()
+    {
+        Map<String, String> result = new HashMap<String, String>();
+        result.put("structured", "false");
+        result.put("formatType", "logfilepatternreceiver");
+        result.put("dateFormat", dateFormat.toPattern());
+        result.put("format", "<LEVEL>TIMESTAMP PROP(HOSTNAME) MESSAGE");
+        return result;
+    }
+
+    /**
      * Create a SyslogLayout.
      * @param facility The Facility is used to try to classify the message.
      * @param includeNL If true a newline will be appended to the result.

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=1451133&r1=1451132&r2=1451133&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 Thu Feb 28 07:57:49 2013
@@ -24,6 +24,7 @@ import java.io.StringReader;
 import java.io.StringWriter;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -61,9 +62,9 @@ import org.apache.logging.log4j.message.
  * appender where it is embedded.
  * <p/>
  * <p>The <code>version</code> attribute helps components to correctly
- * intrepret output generated by XMLLayout. The value of this
+ * interpret output generated by XMLLayout. The value of this
  * attribute should be "1.1" for output generated by log4j versions
- * prior to log4j 1.2 (final release) and "1.2" for relase 1.2 and
+ * prior to log4j 1.2 (final release) and "1.2" for release 1.2 and
  * later.
  * <p/>
  * Appenders using this layout should have their encoding
@@ -216,6 +217,19 @@ public class XMLLayout extends AbstractS
         return sbuf.toString().getBytes(getCharset());
     }
 
+    /**
+     * XMLLayout's content format is specified by:<p/>
+     * Key: "dtd" Value: "log4j.dtd"<p/>
+     * Key: "version" Value: "1.2"
+     * @return Map of content format keys supporting XMLLayout
+     */
+    public Map<String, String> getContentFormat() {
+        Map<String, String> result = new HashMap<String, String>();
+        result.put("dtd", "log4j.dtd");
+        result.put("version", "1.2");
+        return result;
+    }
+
     @Override
     /**
      * @return The content type.

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/AbstractSocketManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/AbstractSocketManager.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/AbstractSocketManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/AbstractSocketManager.java Thu Feb 28 07:57:49 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.net;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.appender.OutputStreamManager;
 
 import java.io.OutputStream;
@@ -55,4 +57,18 @@ public abstract class AbstractSocketMana
         this.port = port;
     }
 
+    /**
+     * AbstractSocketManager's content format is specified by:<p/>
+     * Key: "port" Value: provided "port" param<p/>
+     * Key: "address" Value: provided "address" param
+     * @return Map of content format keys supporting AbstractSocketManager
+     */
+    public Map<String, String> getContentFormat()
+    {
+        Map<String, String> result = new HashMap<String, String>(super.getContentFormat());
+        result.put("port", Integer.toString(port));
+        result.put("address", address.getHostAddress());
+        
+        return result;
+    }
 }

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/Advertiser.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/Advertiser.java?rev=1451133&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/Advertiser.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/Advertiser.java Thu Feb 28 07:57:49 2013
@@ -0,0 +1,24 @@
+/*
+ * 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.util.Map;
+
+public interface Advertiser {
+    Object advertise(Map<String, String> properties);
+    void unadvertise(Object advertisedObject);
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/DatagramSocketManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/DatagramSocketManager.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/DatagramSocketManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/DatagramSocketManager.java Thu Feb 28 07:57:49 2013
@@ -16,6 +16,10 @@
  */
 package org.apache.logging.log4j.core.net;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 
 import java.io.OutputStream;
@@ -29,13 +33,14 @@ public class DatagramSocketManager exten
 
     /**
      * The Constructor.
-     * @param os The OutputStream.
      * @param name The unique name of the connection.
+     * @param os The OutputStream.
+     * @param address
      * @param host The host to connect to.
      * @param port The port on the host.
      */
-    protected DatagramSocketManager(final OutputStream os, final String name, final String host, final int port) {
-        super(name, os, null, host, port);
+    protected DatagramSocketManager(final String name, final OutputStream os, InetAddress address, final String host, final int port) {
+        super(name, os, address, host, port);
     }
 
     /**
@@ -56,6 +61,20 @@ public class DatagramSocketManager exten
     }
 
     /**
+     * DatagramSocketManager's content format is specified by:<p/>
+     * Key: "protocol" Value: "udp"
+     * @return Map of content format keys supporting DatagramSocketManager
+     */
+    public Map<String, String> getContentFormat()
+    {
+        Map<String, String> result = new HashMap<String, String>(super.getContentFormat());
+        result.put("protocol", "udp");
+        result.put("direction", "out");
+
+        return result;
+    }
+
+    /**
      * Data for the factory.
      */
     private static class FactoryData {
@@ -74,8 +93,15 @@ public class DatagramSocketManager exten
     private static class DatagramSocketManagerFactory implements ManagerFactory<DatagramSocketManager, FactoryData> {
 
         public DatagramSocketManager createManager(final String name, final FactoryData data) {
+            InetAddress address;
             final OutputStream os = new DatagramOutputStream(data.host, data.port);
-            return new DatagramSocketManager(os, name, data.host, data.port);
+            try {
+                address = InetAddress.getByName(data.host);
+            } catch (final UnknownHostException ex) {
+                LOGGER.error("Could not find address of " + data.host, ex);
+                return null;
+            }
+            return new DatagramSocketManager(name, os, address, data.host, data.port);
         }
     }
 }

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MulticastDNSAdvertiser.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MulticastDNSAdvertiser.java?rev=1451133&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MulticastDNSAdvertiser.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/MulticastDNSAdvertiser.java Thu Feb 28 07:57:49 2013
@@ -0,0 +1,232 @@
+/*
+ * 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.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.Map;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * Advertise an entity via ZeroConf/MulticastDNS and the JmDNS library.
+ *
+ */
+public class MulticastDNSAdvertiser implements Advertiser {
+    protected static final Logger LOGGER = StatusLogger.getLogger();
+    private static Object jmDNS = initializeJMDNS();
+
+    private static Class<?> jmDNSClass;
+    private static Class<?> serviceInfoClass;
+
+    public MulticastDNSAdvertiser()
+    {
+        //no arg constructor for reflection 
+    }
+
+    /**
+     * Advertise the provided entity.
+     * 
+     * Properties map provided in advertise method must include a "name" entry 
+     * but may also provide "protocol" (tcp/udp) as well as a "port" entry
+     * 
+     * @param properties the properties representing the entity to advertise
+     * @return the object which can be used to unadvertise, or null if advertisement was unsuccessful
+     */
+    public Object advertise(Map<String, String> properties) {
+        //default to tcp if "protocol" was not set
+        String protocol = properties.get("protocol");
+        String zone = "._log4j._"+(protocol != null ? protocol : "tcp") + ".local.";
+        //default to 4555 if "port" was not set
+        String portString = properties.get("port");
+        int port = (portString != null ? Integer.parseInt(portString) : 4555);
+
+        String name = properties.get("name");
+
+        //if version 3 is available, use it to construct a serviceInfo instance, otherwise support the version1 API
+        if (jmDNS != null)
+        {
+            boolean isVersion3 = false;
+            try {
+                //create method is in version 3, not version 1
+                jmDNSClass.getMethod("create", (Class[])null);
+                isVersion3 = true;
+            } catch (NoSuchMethodException e) {
+                //no-op
+            }
+            System.out.println("building: " + zone);
+            Object serviceInfo;
+            if (isVersion3) {
+                serviceInfo = buildServiceInfoVersion3(zone, port, name, properties);
+            } else {
+                serviceInfo = buildServiceInfoVersion1(zone, port, name, properties);
+            }
+
+            try {
+                Method method = jmDNSClass.getMethod("registerService", new Class[]{serviceInfoClass});
+                method.invoke(jmDNS, serviceInfo);
+            } catch(IllegalAccessException e) {
+                LOGGER.warn("Unable to invoke registerService method", e);
+            } catch(NoSuchMethodException e) {
+                LOGGER.warn("No registerService method", e);
+            } catch(InvocationTargetException e) {
+                LOGGER.warn("Unable to invoke registerService method", e);
+            }
+            return serviceInfo;
+        }
+        else
+        {
+            LOGGER.warn("JMDNS not available - will not advertise ZeroConf support");
+            return null;
+        }
+    }
+
+    /**
+     * Unadvertise the previously advertised entity
+     * @param serviceInfo
+     */
+    public void unadvertise(Object serviceInfo) {
+        if (jmDNS != null) {
+            try {
+                Method method = jmDNSClass.getMethod("unregisterService", new Class[]{serviceInfoClass});
+                method.invoke(jmDNS, serviceInfo);
+            } catch(IllegalAccessException e) {
+                LOGGER.warn("Unable to invoke unregisterService method", e);
+            } catch(NoSuchMethodException e) {
+                LOGGER.warn("No unregisterService method", e);
+            } catch(InvocationTargetException e) {
+                LOGGER.warn("Unable to invoke unregisterService method", e);
+            }
+        }
+    }
+
+    private static Object createJmDNSVersion1()
+    {
+        try {
+            return jmDNSClass.newInstance();
+        } catch (InstantiationException e) {
+            LOGGER.warn("Unable to instantiate JMDNS", e);
+        } catch (IllegalAccessException e) {
+            LOGGER.warn("Unable to instantiate JMDNS", e);
+        }
+        return null;
+    }
+
+    private static Object createJmDNSVersion3()
+    {
+        try {
+            Method jmDNSCreateMethod = jmDNSClass.getMethod("create", (Class[])null);
+            return jmDNSCreateMethod.invoke(null, (Object[])null);
+        } catch (IllegalAccessException e) {
+            LOGGER.warn("Unable to instantiate jmdns class", e);
+        } catch (NoSuchMethodException e) {
+            LOGGER.warn("Unable to access constructor", e);
+        } catch (InvocationTargetException e) {
+            LOGGER.warn("Unable to call constructor", e);
+        }
+        return null;
+    }
+
+    private Object buildServiceInfoVersion1(String zone, int port, String name, Map<String, String> properties) {
+        //version 1 uses a hashtable
+        Hashtable<String, String> hashtableProperties = new Hashtable<String, String>(properties);
+        try {
+            Class[] args = new Class[6];
+            args[0] = String.class;
+            args[1] = String.class;
+            args[2] = int.class;
+            args[3] = int.class; //weight (0)
+            args[4] = int.class; //priority (0)
+            args[5] = Hashtable.class;
+            Constructor<?> constructor  = serviceInfoClass.getConstructor(args);
+            Object[] values = new Object[6];
+            values[0] = zone;
+            values[1] = name;
+            values[2] = port;
+            values[3] = 0;
+            values[4] = 0;
+            values[5] = hashtableProperties;
+            return constructor.newInstance(values);
+        } catch (IllegalAccessException e) {
+            LOGGER.warn("Unable to construct ServiceInfo instance", e);
+        } catch (NoSuchMethodException e) {
+            LOGGER.warn("Unable to get ServiceInfo constructor", e);
+        } catch (InstantiationException e) {
+            LOGGER.warn("Unable to construct ServiceInfo instance", e);
+        } catch (InvocationTargetException e) {
+            LOGGER.warn("Unable to construct ServiceInfo instance", e);
+        }
+        return null;
+    }
+
+    private Object buildServiceInfoVersion3(String zone, int port, String name, Map<String, String> properties) {
+        try {
+            Class[] args = new Class[6];
+            args[0] = String.class; //zone/type
+            args[1] = String.class; //display name
+            args[2] = int.class; //port
+            args[3] = int.class; //weight (0)
+            args[4] = int.class; //priority (0)
+            args[5] = Map.class;
+            Method serviceInfoCreateMethod = serviceInfoClass.getMethod("create", args);
+            Object[] values = new Object[6];
+            values[0] = zone;
+            values[1] = name;
+            values[2] = port;
+            values[3] = 0;
+            values[4] = 0;
+            values[5] = properties;
+            return serviceInfoCreateMethod.invoke(null, values);
+        } catch (IllegalAccessException e) {
+            LOGGER.warn("Unable to invoke create method", e);
+        } catch (NoSuchMethodException e) {
+            LOGGER.warn("Unable to find create method", e);
+        } catch (InvocationTargetException e) {
+            LOGGER.warn("Unable to invoke create method", e);
+        }
+        return null;
+    }
+
+    private static Object initializeJMDNS() {
+        try {
+            jmDNSClass = Class.forName("javax.jmdns.JmDNS");
+            serviceInfoClass = Class.forName("javax.jmdns.ServiceInfo");
+            //if version 3 is available, use it to constuct a serviceInfo instance, otherwise support the version1 API
+            boolean isVersion3 = false;
+            try {
+                //create method is in version 3, not version 1
+                jmDNSClass.getMethod("create", (Class[])null);
+                isVersion3 = true;
+            } catch (NoSuchMethodException e) {
+                //no-op
+            }
+
+            if (isVersion3) {
+                return createJmDNSVersion3();
+            } else {
+                return createJmDNSVersion1();
+            }
+        } catch (ClassNotFoundException e) {
+            LOGGER.warn("JmDNS or serviceInfo class not found", e);
+        } catch (ExceptionInInitializerError e2) {
+            LOGGER.warn("JmDNS or serviceInfo class not found", e2);
+        }
+        return null;
+    }
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/TCPSocketManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/TCPSocketManager.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/TCPSocketManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/net/TCPSocketManager.java Thu Feb 28 07:57:49 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.net;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.logging.log4j.core.appender.AppenderRuntimeException;
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 import org.apache.logging.log4j.core.appender.OutputStreamManager;
@@ -132,7 +134,20 @@ public class TCPSocketManager extends Ab
     }
 
     /**
-     * Handles recoonecting to a Thread.
+     * TCPSocketManager's content format is specified by:<p/>
+     * Key: "protocol" Value: "tcp"
+     * @return Map of content format keys supporting TCPSocketManager
+     */
+    public Map<String, String> getContentFormat()
+    {
+        Map<String, String> result = new HashMap<String, String>(super.getContentFormat());
+        result.put("protocol", "tcp");
+        result.put("direction", "out");
+        return result;
+    }
+    
+    /**
+     * Handles reconnecting to a Thread.
      */
     private class Reconnector extends Thread {
 
@@ -214,7 +229,7 @@ public class TCPSocketManager extends Ab
         public TCPSocketManager createManager(final String name, final FactoryData data) {
 
             InetAddress address;
-            OutputStream os = null;
+            OutputStream os;
             try {
                 address = InetAddress.getByName(data.host);
             } catch (final UnknownHostException ex) {

Modified: logging/log4j/log4j2/trunk/core/src/main/resources/Log4J-V2.0.xsd
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/resources/Log4J-V2.0.xsd?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/resources/Log4J-V2.0.xsd (original)
+++ logging/log4j/log4j2/trunk/core/src/main/resources/Log4J-V2.0.xsd Thu Feb 28 07:57:49 2013
@@ -32,6 +32,7 @@
     <xs:attribute type="xs:string" name="status"/>
     <xs:attribute type="xs:string" name="strict"/>
     <xs:attribute type="xs:string" name="name"/>
+    <xs:attribute type="xs:string" name="advertiser"/>
   </xs:complexType>
   <xs:complexType name="propertiesType">
     <xs:sequence>

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderTest.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/FileAppenderTest.java Thu Feb 28 07:57:49 2013
@@ -141,7 +141,7 @@ public class FileAppenderTest {
     private static void writer(final boolean lock, final int count, final String name) throws Exception {
         final Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, null, null, null);
         final FileAppender app = FileAppender.createAppender(FILENAME, "true", Boolean.toString(lock), "test", "false",
-            "false", "false", layout, null);
+            "false", "false", layout, null, "false", null, null);
         final Thread t = Thread.currentThread();
         app.start();
         assertTrue("Appender did not start", app.isStarted());

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java Thu Feb 28 07:57:49 2013
@@ -97,7 +97,7 @@ public class SocketAppenderTest {
     public void testTCPAppender() throws Exception {
 
         final SocketAppender appender = SocketAppender.createAppender("localhost", PORT, "tcp", "-1",
-            "Test", null, null, null, null);
+            "Test", null, null, null, null, null, null);
         appender.start();
 
         // set appender on root and set level to debug
@@ -125,7 +125,7 @@ public class SocketAppenderTest {
     public void testUDPAppender() throws Exception {
 
         final SocketAppender appender = SocketAppender.createAppender("localhost", PORT, "udp", "-1",
-            "Test", null, null, null, null);
+            "Test", null, null, null, null, null, null);
         appender.start();
 
         // set appender on root and set level to debug

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SyslogAppenderTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SyslogAppenderTest.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SyslogAppenderTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/SyslogAppenderTest.java Thu Feb 28 07:57:49 2013
@@ -212,7 +212,7 @@ public class SyslogAppenderTest {
     private SyslogAppender createAppender(final String protocol, final String format) {
         return SyslogAppender.createAppender("localhost", PORT, protocol, "-1", "Test", "true", "false", "LOCAL0", "Audit",
             "18060", "true", "RequestContext", "true", null, "TestApp", "Test", null, "ipAddress,loginId", null, format, null,
-                null, null, null);
+                null, null, null, null);
     }
 
     public static class UDPSocketServer extends Thread {

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java?rev=1451133&r1=1451132&r2=1451133&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java Thu Feb 28 07:57:49 2013
@@ -52,7 +52,7 @@ public class OnStartupTriggeringPolicyTe
 
         public MyRollingManager(final TriggeringPolicy policy, final RolloverStrategy strategy) {
             super("testfile", "target/rolling1/test1-%i.log.gz", new ByteArrayOutputStream(),
-                false, 0, System.currentTimeMillis(), policy, strategy);
+                false, 0, System.currentTimeMillis(), policy, strategy, null);
         }
 
         public void setFileTime(final long timestamp) {

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/AdvertiserTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/AdvertiserTest.java?rev=1451133&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/AdvertiserTest.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/AdvertiserTest.java Thu Feb 28 07:57:49 2013
@@ -0,0 +1,124 @@
+/*
+ * 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.config;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Map;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class AdvertiserTest {
+
+    private static final String CONFIG = "log4j-advertiser.xml";
+    private static final String STATUS_LOG = "target/status.log";
+
+    @BeforeClass
+    public static void setupClass() {
+        final File file = new File(STATUS_LOG);
+        file.delete();
+        System.setProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY, CONFIG);
+        final LoggerContext ctx = (LoggerContext) LogManager.getContext();
+        final Configuration config = ctx.getConfiguration();
+        if (config instanceof XMLConfiguration) {
+            final String name = ((XMLConfiguration) config).getName();
+            if (name == null || !name.equals("XMLConfigTest")) {
+                ctx.reconfigure();
+            }
+        } else {
+            ctx.reconfigure();
+        }
+    }
+
+    @AfterClass
+    public static void cleanupClass() {
+        System.clearProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
+        final LoggerContext ctx = (LoggerContext) LogManager.getContext();
+        ctx.reconfigure();
+        StatusLogger.getLogger().reset();
+        final File file = new File(STATUS_LOG);
+        file.delete();
+    }
+
+    private void verifyExpectedEntriesAdvertised(Map<Object, Map<String, String>> entries) {
+        boolean foundFile1 = false;
+        boolean foundFile2 = false;
+        boolean foundSocket1 = false;
+        boolean foundSocket2 = false;
+        for (Map<String, String>entry:entries.values()) {
+            if (entry.get("name").equals("File1")) {
+                foundFile1 = true;
+            }
+            if (entry.get("name").equals("File2")) {
+                foundFile2 = true;
+            }
+            if (entry.get("name").equals("Socket1")) {
+                foundSocket1 = true;
+            }
+            if (entry.get("name").equals("Socket2")) {
+                foundSocket2 = true;
+            }
+        }
+        assertTrue("Entries for File1 appender do not exist", foundFile1);
+        assertTrue("Entries for File2 appender exist", !foundFile2);
+        assertTrue("Entries for Socket1 appender do not exist", foundSocket1);
+        assertTrue("Entries for Socket2 appender exist", !foundSocket2);
+    }
+
+    @Test
+    public void testAdvertisementsFound() {
+        verifyExpectedEntriesAdvertised(InMemoryAdvertiser.getAdvertisedEntries());
+    }
+    
+    @Test
+    public void testAdvertisementsRemovedOnConfigStop() {
+        verifyExpectedEntriesAdvertised(InMemoryAdvertiser.getAdvertisedEntries());
+
+        final LoggerContext ctx = (LoggerContext) LogManager.getContext();
+        ctx.stop();
+
+        Map<Object, Map<String, String>> entries = InMemoryAdvertiser.getAdvertisedEntries();
+        assertTrue("Entries found: " + entries, entries.isEmpty());
+        
+        //reconfigure for subsequent testing
+        ctx.reconfigure();
+    }
+
+    @Test
+    public void testAdvertisementsAddedOnReconfigAfterStop() {
+        verifyExpectedEntriesAdvertised(InMemoryAdvertiser.getAdvertisedEntries());
+
+        final LoggerContext ctx = (LoggerContext) LogManager.getContext();
+        ctx.stop();
+
+        Map<Object, Map<String, String>> entries = InMemoryAdvertiser.getAdvertisedEntries();
+        assertTrue("Entries found: " + entries, entries.isEmpty());
+        
+        ctx.reconfigure();
+
+        verifyExpectedEntriesAdvertised(InMemoryAdvertiser.getAdvertisedEntries());
+    }
+}

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/InMemoryAdvertiser.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/InMemoryAdvertiser.java?rev=1451133&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/InMemoryAdvertiser.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/InMemoryAdvertiser.java Thu Feb 28 07:57:49 2013
@@ -0,0 +1,43 @@
+/*
+ * 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.config;
+
+import org.apache.logging.log4j.core.net.Advertiser;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class InMemoryAdvertiser implements Advertiser {
+    private static Map<Object, Map<String, String>> properties = new HashMap<Object, Map<String, String>>();
+    
+    public static Map<Object, Map<String, String>> getAdvertisedEntries()
+    {
+        Map<Object, Map<String, String>> result = new HashMap<Object, Map<String, String>>();
+        result.putAll(properties);
+        return result;
+    }
+    
+    public Object advertise(Map<String, String> newEntry) {
+        Object object = new Object();
+        properties.put(object, new HashMap<String, String>(newEntry));
+        return object;
+    }
+
+    public void unadvertise(Object advertisedObject) {
+        properties.remove(advertisedObject);
+    }
+}