http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/TcpXmlSocketServerTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/TcpXmlSocketServerTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/TcpXmlSocketServerTest.java
deleted file mode 100644
index 2290cbd..0000000
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/TcpXmlSocketServerTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.server;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-
-import org.apache.logging.log4j.core.Layout;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.net.Protocol;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-public class TcpXmlSocketServerTest extends AbstractSocketServerTest {
-    
-    private static TcpSocketServer<InputStream> server;
-
-    @BeforeClass
-    public static void setupClass() throws Exception {
-        (LoggerContext.getContext(false)).reconfigure();
-        // Use a large buffer just to test the code, the UDP test uses a tiny 
buffer
-        server = new TcpSocketServer<>(PORT_NUM, new 
XmlInputStreamLogEventBridge(1024 * 100,
-                Charset.defaultCharset()));
-        thread = server.startNewThread();
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-        try {
-            server.shutdown();
-        } catch (final IOException e) {
-            e.printStackTrace();
-        }
-        try {
-            thread.join();
-        } catch (final InterruptedException e) {
-            // ignore
-        }
-    }
-
-    public TcpXmlSocketServerTest() {
-        super(Protocol.TCP, PORT, false);
-    }
-
-    @Override
-    protected Layout<String> createLayout() {
-        return super.createXmlLayout();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
deleted file mode 100644
index d00edb2..0000000
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadIdFilter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.server;
-
-import org.apache.logging.log4j.core.Filter;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.filter.AbstractFilter;
-
-/**
- * TODO Should use thread ID cache?
- * @since 2.6
- */
-public class ThreadIdFilter extends AbstractFilter {
-
-    private static final long serialVersionUID = 1L;
-
-    public ThreadIdFilter(final Result onMatch, final Result onMismatch) {
-        super(onMatch, onMismatch);
-    }
-
-    @Override
-    public Filter.Result filter(final LogEvent event) {
-        return event.getThreadId() == Thread.currentThread().getId() ? onMatch 
: onMismatch;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadNameFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadNameFilter.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadNameFilter.java
deleted file mode 100644
index e5e176d..0000000
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadNameFilter.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.server;
-
-import org.apache.logging.log4j.core.Filter;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.filter.AbstractFilter;
-
-/**
- * TODO Should use thread name cache?
- */
-public class ThreadNameFilter extends AbstractFilter {
-
-    private static final long serialVersionUID = 1L;
-
-    public ThreadNameFilter(final Result onMatch, final Result onMismatch) {
-        super(onMatch, onMismatch);
-    }
-
-    @Override
-    public Filter.Result filter(final LogEvent event) {
-        return event.getThreadName().equals(Thread.currentThread().getName()) 
? onMatch : onMismatch;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
deleted file mode 100644
index 7c9c734..0000000
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/ThreadPriorityFilter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.server;
-
-import org.apache.logging.log4j.core.Filter;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.filter.AbstractFilter;
-
-/**
- * TODO Should use thread priority cache?
- * @since 2.6
- */
-public class ThreadPriorityFilter extends AbstractFilter {
-
-    private static final long serialVersionUID = 1L;
-
-    public ThreadPriorityFilter(final Result onMatch, final Result onMismatch) 
{
-        super(onMatch, onMismatch);
-    }
-
-    @Override
-    public Filter.Result filter(final LogEvent event) {
-        return event.getThreadPriority() == 
Thread.currentThread().getPriority() ? onMatch : onMismatch;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpJsonSocketServerTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpJsonSocketServerTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpJsonSocketServerTest.java
deleted file mode 100644
index 3f33b14..0000000
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpJsonSocketServerTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.server;
-
-import java.io.InputStream;
-import java.io.Serializable;
-
-import org.apache.logging.log4j.core.Layout;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.net.Protocol;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-public class UdpJsonSocketServerTest extends AbstractSocketServerTest {
-
-    private static UdpSocketServer<InputStream> server;
-
-    @BeforeClass
-    public static void setupClass() throws Exception {
-        (LoggerContext.getContext(false)).reconfigure();
-        server = UdpSocketServer.createJsonSocketServer(PORT_NUM);
-        thread = server.startNewThread();
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-        server.shutdown();
-        try {
-            thread.join();
-        } catch (final InterruptedException e) {
-            // ignore
-        }
-    }
-
-    public UdpJsonSocketServerTest() {
-        super(Protocol.UDP, PORT, true);
-    }
-
-    @Override
-    protected Layout<? extends Serializable> createLayout() {
-        return super.createJsonLayout();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpSerializedSocketServerTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpSerializedSocketServerTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpSerializedSocketServerTest.java
deleted file mode 100644
index 3e7ecad..0000000
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpSerializedSocketServerTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.server;
-
-import java.io.ObjectInputStream;
-import java.io.Serializable;
-
-import org.apache.logging.log4j.core.Layout;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.net.Protocol;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-
-@Ignore
-public class UdpSerializedSocketServerTest extends AbstractSocketServerTest {
-
-    private static UdpSocketServer<ObjectInputStream> server;
-
-    @BeforeClass
-    public static void setupClass() throws Exception {
-        (LoggerContext.getContext(false)).reconfigure();
-        server = UdpSocketServer.createSerializedSocketServer(PORT_NUM);
-        thread = server.startNewThread();
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-        server.shutdown();
-        try {
-            thread.join();
-        } catch (final InterruptedException e) {
-            // ignore
-        }
-    }
-
-    public UdpSerializedSocketServerTest() {
-        super(Protocol.UDP, PORT, true);
-    }
-
-    @Override
-    protected Layout<? extends Serializable> createLayout() {
-        return super.createSerializedLayout();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpXmlSocketServerTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpXmlSocketServerTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpXmlSocketServerTest.java
deleted file mode 100644
index fa54766..0000000
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/UdpXmlSocketServerTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.server;
-
-import java.io.InputStream;
-import java.io.Serializable;
-import java.nio.charset.Charset;
-
-import org.apache.logging.log4j.core.Layout;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.net.Protocol;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-public class UdpXmlSocketServerTest extends AbstractSocketServerTest {
-
-    private static UdpSocketServer<InputStream> server;
-
-    @BeforeClass
-    public static void setupClass() throws Exception {
-        (LoggerContext.getContext(false)).reconfigure();
-        // Use a tiny buffer just to test the code, the TCP test uses a large 
buffer
-        server = new UdpSocketServer<>(PORT_NUM, new 
XmlInputStreamLogEventBridge(100,
-                Charset.defaultCharset()));
-        thread = server.startNewThread();
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-        server.shutdown();
-        try {
-            thread.join();
-        } catch (final InterruptedException e) {
-            // ignore
-        }
-    }
-
-    public UdpXmlSocketServerTest() {
-        super(Protocol.UDP, PORT, true);
-    }
-
-    @Override
-    protected Layout<? extends Serializable> createLayout() {
-        return super.createXmlLayout();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-server/pom.xml b/log4j-server/pom.xml
new file mode 100644
index 0000000..2833871
--- /dev/null
+++ b/log4j-server/pom.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.logging.log4j</groupId>
+    <artifactId>log4j</artifactId>
+    <version>2.8.2-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+  <artifactId>log4j-server</artifactId>
+  <packaging>jar</packaging>
+  <name>Apache Log4j Server components</name>
+  <description>The Apache Log4j server components</description>
+  <properties>
+    <log4jParentDir>${basedir}/..</log4jParentDir>
+    <projectDir>/log4j-server</projectDir>
+  </properties>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
+    <!-- Command line for TCP and UDP servers -->
+    <dependency>
+      <groupId>com.beust</groupId>
+      <artifactId>jcommander</artifactId>
+    </dependency>
+
+    <!-- TEST DEPENDENCIES -->
+
+    <!-- Pull in useful test classes from API -->
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <!-- Include the standard NOTICE and LICENSE -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-remote-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>process</goal>
+            </goals>
+            <configuration>
+              <skip>false</skip>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            
<Export-Package>org.apache.logging.log4j.core.net.*</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changes-plugin</artifactId>
+        <version>${changes.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>changes-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+        <configuration>
+          <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
+          <useJql>true</useJql>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>${checkstyle.plugin.version}</version>
+        <configuration>
+          
<!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation>
 -->
+          <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
+          
<suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
+          <enableRulesSummary>false</enableRulesSummary>
+          <propertyExpansion>basedir=${basedir}</propertyExpansion>
+          
<propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>${javadoc.plugin.version}</version>
+        <configuration>
+          <bottom><![CDATA[<p align="center">Copyright &#169; 
{inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
+            Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather 
logo, the Apache Logging project logo,
+            and the Apache Log4j logo are trademarks of The Apache Software 
Foundation.</p>]]></bottom>
+          <!-- module link generation is completely broken in the javadoc 
plugin for a multi-module non-aggregating
+               project -->
+          <detectOfflineLinks>false</detectOfflineLinks>
+          <linksource>true</linksource>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>javadoc</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>${findbugs.plugin.version}</version>
+        <configuration>
+          <fork>true</fork>
+          <jvmArgs>-Duser.language=en</jvmArgs>
+          <threshold>Normal</threshold>
+          <effort>Default</effort>
+          
<excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>${jxr.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>jxr</report>
+            </reports>
+          </reportSet>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <version>${pmd.plugin.version}</version>
+        <configuration>
+          <targetJdk>${maven.compiler.target}</targetJdk>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>
+

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/AbstractJmsReceiver.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/AbstractJmsReceiver.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/AbstractJmsReceiver.java
new file mode 100644
index 0000000..753fc80
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/AbstractJmsReceiver.java
@@ -0,0 +1,48 @@
+/*
+ * 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.mom.jms;
+
+import org.apache.logging.log4j.core.net.server.JmsServer;
+
+/**
+ * Common JMS server functionality.
+ *
+ * @since 2.6
+ */
+public abstract class AbstractJmsReceiver {
+
+    /**
+     * Prints out usage information to {@linkplain System#err standard error}.
+     */
+    protected abstract void usage();
+
+    /**
+     * Executes a JmsServer with the given command line arguments.
+     *
+     * @param args command line arguments
+     * @throws Exception
+     */
+    protected void doMain(final String... args) throws Exception {
+        if (args.length != 4) {
+            usage();
+            System.exit(1);
+        }
+        final JmsServer server = new JmsServer(args[0], args[1], args[2], 
args[3]);
+        server.run();
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsQueueReceiver.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsQueueReceiver.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsQueueReceiver.java
new file mode 100644
index 0000000..dac46d3
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsQueueReceiver.java
@@ -0,0 +1,46 @@
+/*
+ * 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.mom.jms;
+
+/**
+ * Receives Log Events over a JMS Queue. This implementation expects that all 
messages will
+ * contain a serialized LogEvent.
+ */
+public class JmsQueueReceiver extends AbstractJmsReceiver {
+
+    private JmsQueueReceiver() {
+    }
+
+    /**
+     * Main startup for the receiver.
+     *
+     * @param args The command line arguments.
+     * @throws Exception if an error occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        final JmsQueueReceiver receiver = new JmsQueueReceiver();
+        receiver.doMain(args);
+    }
+
+    @Override
+    protected void usage() {
+        System.err.println("Wrong number of arguments.");
+        System.err.println("Usage: java " + JmsQueueReceiver.class.getName()
+            + " QueueConnectionFactoryBindingName QueueBindingName username 
password");
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsTopicReceiver.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsTopicReceiver.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsTopicReceiver.java
new file mode 100644
index 0000000..4442ab1
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/JmsTopicReceiver.java
@@ -0,0 +1,46 @@
+/*
+ * 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.mom.jms;
+
+/**
+ * Receives Topic messages that contain LogEvents. This implementation expects 
that all messages
+ * are serialized log events.
+ */
+public class JmsTopicReceiver extends AbstractJmsReceiver {
+
+    private JmsTopicReceiver() {
+    }
+
+    /**
+     * Main startup for the receiver.
+     *
+     * @param args The command line arguments.
+     * @throws Exception if an error occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        final JmsTopicReceiver receiver = new JmsTopicReceiver();
+        receiver.doMain(args);
+    }
+
+    @Override
+    protected void usage() {
+        System.err.println("Wrong number of arguments.");
+        System.err.println("Usage: java " + JmsTopicReceiver.class.getName()
+            + " TopicConnectionFactoryBindingName TopicBindingName username 
password");
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/package-info.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/package-info.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/package-info.java
new file mode 100644
index 0000000..9c3e03e
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/mom/jms/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/**
+ * Supporting network code for JMS appenders.
+ *
+ * <p>Note that you can use JmsQueueReceiver or JmsTopicReceiver as executable 
main classes to receive log events over
+ * JMS (sent via the appropriate JMS appender) that can be subsequently logged 
according to the configuration given to
+ * the running process. Of course, use of these classes as standalone 
executables are entirely optional and can
+ * be used directly in your application (e.g., through your Spring {@code 
beans.xml} configuration).</p>
+ */
+package org.apache.logging.log4j.core.net.mom.jms;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractLogEventBridge.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractLogEventBridge.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractLogEventBridge.java
new file mode 100644
index 0000000..59b889b
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractLogEventBridge.java
@@ -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.net.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * Abstract class for implementations of {@link LogEventBridge}.
+ * 
+ * @param <T>
+ *            The kind of input stream read
+ */
+public abstract class AbstractLogEventBridge<T extends InputStream> implements 
LogEventBridge<T> {
+
+    protected static final int END = -1;
+
+    protected static final Logger logger = StatusLogger.getLogger();
+
+    // The default is to return the same object as given.
+    @SuppressWarnings("unchecked")
+    @Override
+    public T wrapStream(final InputStream inputStream) throws IOException {
+        return (T) inputStream;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractSocketServer.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractSocketServer.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractSocketServer.java
new file mode 100644
index 0000000..9836694
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/AbstractSocketServer.java
@@ -0,0 +1,209 @@
+/*
+ * 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.server;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URL;
+import java.util.Objects;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.validators.PositiveInteger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LogEventListener;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
+import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
+import org.apache.logging.log4j.core.util.BasicCommandLineArguments;
+import org.apache.logging.log4j.core.util.InetAddressConverter;
+import org.apache.logging.log4j.core.util.Log4jThread;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Abstract socket server for TCP and UDP implementations.
+ *
+ * @param <T>
+ *            The kind of input stream read
+ *
+ *            TODO Make a LifeCycle
+ */
+public abstract class AbstractSocketServer<T extends InputStream> extends 
LogEventListener implements Runnable {
+
+    protected static class CommandLineArguments extends 
BasicCommandLineArguments {
+
+        @Parameter(names = { "--config", "-c" }, description = "Log4j 
configuration file location (path or URL).")
+        private String configLocation;
+
+        @Parameter(names = { "--interactive",
+                "-i" }, description = "Accepts commands on standard input 
(\"exit\" is the only command).")
+        private boolean interactive;
+
+        @Parameter(names = { "--port",
+                "-p" }, validateWith = PositiveInteger.class, description = 
"Server socket port.")
+        private int port;
+
+        @Parameter(names = { "--localbindaddress",
+                "-a" }, converter = InetAddressConverter.class, description = 
"Server socket local bind address.")
+        private InetAddress localBindAddress;
+
+        String getConfigLocation() {
+            return configLocation;
+        }
+
+        int getPort() {
+            return port;
+        }
+
+        protected boolean isInteractive() {
+            return interactive;
+        }
+
+        void setConfigLocation(final String configLocation) {
+            this.configLocation = configLocation;
+        }
+
+        void setInteractive(final boolean interactive) {
+            this.interactive = interactive;
+        }
+
+        void setPort(final int port) {
+            this.port = port;
+        }
+
+        InetAddress getLocalBindAddress() {
+            return localBindAddress;
+        }
+
+        void setLocalBindAddress(final InetAddress localBindAddress) {
+            this.localBindAddress = localBindAddress;
+        }
+    }
+
+    /**
+     * Factory that creates a Configuration for the server.
+     */
+    protected static class ServerConfigurationFactory extends 
XmlConfigurationFactory {
+
+        private final String path;
+
+        public ServerConfigurationFactory(final String path) {
+            this.path = path;
+        }
+
+        @Override
+        public Configuration getConfiguration(final LoggerContext 
loggerContext, final String name,
+                final URI configLocation) {
+            if (Strings.isNotEmpty(path)) {
+                File file = null;
+                ConfigurationSource source = null;
+                try {
+                    file = new File(path);
+                    final FileInputStream is = new FileInputStream(file);
+                    source = new ConfigurationSource(is, file);
+                } catch (final FileNotFoundException ignored) {
+                    // Ignore this error
+                }
+                if (source == null) {
+                    try {
+                        final URL url = new URL(path);
+                        source = new ConfigurationSource(url.openStream(), 
url);
+                    } catch (final IOException ignored) {
+                        // Ignore this error
+                    }
+                }
+
+                try {
+                    if (source != null) {
+                        return new XmlConfiguration(loggerContext, source);
+                    }
+                } catch (final Exception ignored) {
+                    // Ignore this error.
+                }
+                System.err.println("Unable to process configuration at " + 
path + ", using default.");
+            }
+            return super.getConfiguration(loggerContext, name, configLocation);
+        }
+    }
+
+    protected static final int MAX_PORT = 65534;
+
+    private volatile boolean active = true;
+
+    protected final LogEventBridge<T> logEventInput;
+
+    protected final Logger logger;
+
+    /**
+     * Creates a new socket server.
+     *
+     * @param port
+     *            listen to this port
+     * @param logEventInput
+     *            Use this input to read log events.
+     */
+    public AbstractSocketServer(final int port, final LogEventBridge<T> 
logEventInput) {
+        this.logger = LogManager.getLogger(this.getClass().getName() + '.' + 
port);
+        this.logEventInput = Objects.requireNonNull(logEventInput, 
"LogEventInput");
+    }
+
+    protected boolean isActive() {
+        return this.active;
+    }
+
+    protected void setActive(final boolean isActive) {
+        this.active = isActive;
+    }
+
+    /**
+     * Start this server in a new thread.
+     *
+     * @return the new thread that running this server.
+     */
+    public Thread startNewThread() {
+        final Thread thread = new Log4jThread(this);
+        thread.start();
+        return thread;
+    }
+
+    public abstract void shutdown() throws Exception;
+
+    public void awaitTermination(final Thread serverThread) throws Exception {
+        final BufferedReader reader = new BufferedReader(new 
InputStreamReader(System.in));
+        while (true) {
+            final String line = reader.readLine();
+            if (line == null
+                || line.equalsIgnoreCase("quit")
+                || line.equalsIgnoreCase("stop")
+                || line.equalsIgnoreCase("exit")) {
+                this.shutdown();
+                serverThread.join();
+                break;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/InputStreamLogEventBridge.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/InputStreamLogEventBridge.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/InputStreamLogEventBridge.java
new file mode 100644
index 0000000..11b4aa4
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/InputStreamLogEventBridge.java
@@ -0,0 +1,103 @@
+/*
+ * 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.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.LogEventListener;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.util.Strings;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+
+/**
+ * Reads and logs {@link LogEvent}s from an {@link InputStream}.
+ */
+public abstract class InputStreamLogEventBridge extends 
AbstractLogEventBridge<InputStream> {
+
+    private final int bufferSize;
+
+    private final Charset charset;
+
+    private final String eventEndMarker;
+    
+    private final ObjectReader objectReader;
+    
+    public InputStreamLogEventBridge(final ObjectMapper mapper, final int 
bufferSize, final Charset charset, final String eventEndMarker) {
+        this.bufferSize = bufferSize;
+        this.charset = charset;
+        this.eventEndMarker = eventEndMarker;
+        this.objectReader = mapper.readerFor(Log4jLogEvent.class);
+    }
+
+    abstract protected int[] getEventIndices(final String text, int 
beginIndex);
+
+    @Override
+    public void logEvents(final InputStream inputStream, final 
LogEventListener logEventListener) throws IOException {
+        String workingText = Strings.EMPTY;
+        try {
+            // Allocate buffer once
+            final byte[] buffer = new byte[bufferSize];
+            String textRemains = workingText = Strings.EMPTY;
+            while (true) {
+                // Process until the stream is EOF.
+                final int streamReadLength = inputStream.read(buffer);
+                if (streamReadLength == END) {
+                    // The input stream is EOF
+                    break;
+                }
+                final String text = workingText = textRemains + new 
String(buffer, 0, streamReadLength, charset);
+                int beginIndex = 0;
+                while (true) {
+                    // Extract and log all XML events in the buffer
+                    final int[] pair = getEventIndices(text, beginIndex);
+                    final int eventStartMarkerIndex = pair[0];
+                    if (eventStartMarkerIndex < 0) {
+                        // No more events or partial XML only in the buffer.
+                        // Save the unprocessed string part
+                        textRemains = text.substring(beginIndex);
+                        break;
+                    }
+                    final int eventEndMarkerIndex = pair[1];
+                    if (eventEndMarkerIndex > 0) {
+                        final int eventEndXmlIndex = eventEndMarkerIndex + 
eventEndMarker.length();
+                        final String textEvent = workingText = 
text.substring(eventStartMarkerIndex, eventEndXmlIndex);
+                        final LogEvent logEvent = unmarshal(textEvent);
+                        logEventListener.log(logEvent);
+                        beginIndex = eventEndXmlIndex;
+                    } else {
+                        // No more events or partial XML only in the buffer.
+                        // Save the unprocessed string part
+                        textRemains = text.substring(beginIndex);
+                        break;
+                    }
+                }
+            }
+        } catch (final IOException ex) {
+            logger.error(workingText, ex);
+        }
+    }
+
+    protected Log4jLogEvent unmarshal(final String jsonEvent) throws 
IOException {
+        return this.objectReader.readValue(jsonEvent);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
new file mode 100644
index 0000000..05fb113
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
@@ -0,0 +1,148 @@
+/*
+ * 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.server;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.ObjectMessage;
+
+import org.apache.logging.log4j.LoggingException;
+import org.apache.logging.log4j.core.AbstractLifeCycle;
+import org.apache.logging.log4j.core.LifeCycle2;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.LogEventListener;
+import org.apache.logging.log4j.core.appender.mom.JmsManager;
+import org.apache.logging.log4j.core.net.JndiManager;
+
+/**
+ * LogEventListener server that receives LogEvents over a JMS {@link 
javax.jms.Destination}.
+ *
+ * @since 2.1
+ */
+public class JmsServer extends LogEventListener implements MessageListener, 
LifeCycle2 {
+
+    private final AtomicReference<State> state = new 
AtomicReference<>(State.INITIALIZED);
+    private final JmsManager jmsManager;
+    private MessageConsumer messageConsumer;
+
+    public JmsServer(final String connectionFactoryBindingName,
+                     final String destinationBindingName,
+                     final String username,
+                     final String password) {
+        final String managerName = JmsServer.class.getName() + '@' + 
JmsServer.class.hashCode();
+        final JndiManager jndiManager = 
JndiManager.getDefaultManager(managerName);
+        jmsManager = JmsManager.getJmsManager(managerName, jndiManager, 
connectionFactoryBindingName,
+            destinationBindingName, username, password);
+    }
+
+    @Override
+    public State getState() {
+        return state.get();
+    }
+
+    @Override
+    public void onMessage(final Message message) {
+        try {
+            if (message instanceof ObjectMessage) {
+                final Object body = ((ObjectMessage) message).getObject();
+                if (body instanceof LogEvent) {
+                    log((LogEvent) body);
+                } else {
+                    LOGGER.warn("Expected ObjectMessage to contain LogEvent. 
Got type {} instead.", body.getClass());
+                }
+            } else {
+                LOGGER.warn("Received message of type {} and JMSType {} which 
cannot be handled.", message.getClass(),
+                    message.getJMSType());
+            }
+        } catch (final JMSException e) {
+            LOGGER.catching(e);
+        }
+    }
+
+    @Override
+    public void initialize() {
+    }
+
+    @Override
+    public void start() {
+        if (state.compareAndSet(State.INITIALIZED, State.STARTING)) {
+            try {
+                messageConsumer = jmsManager.createMessageConsumer();
+                messageConsumer.setMessageListener(this);
+            } catch (final JMSException e) {
+                throw new LoggingException(e);
+            }
+        }
+    }
+
+    @Override
+    public void stop() {
+        stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, 
AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT);
+    }
+
+    @Override
+    public boolean stop(final long timeout, final TimeUnit timeUnit) {
+        boolean stopped = true;
+        try {
+            messageConsumer.close();
+        } catch (final JMSException e) {
+            LOGGER.debug("Exception closing {}", messageConsumer, e);
+            stopped = false;
+        }
+        return stopped && jmsManager.stop(timeout, timeUnit);
+    }
+
+    @Override
+    public boolean isStarted() {
+        return state.get() == State.STARTED;
+    }
+
+    @Override
+    public boolean isStopped() {
+        return state.get() == State.STOPPED;
+    }
+
+    /**
+     * Starts and runs this server until the user types "exit" into standard 
input.
+     *
+     * @throws IOException
+     * @since 2.6
+     */
+    public void run() throws IOException {
+        this.start();
+        System.out.println("Type \"exit\" to quit.");
+        final BufferedReader stdin = new BufferedReader(new 
InputStreamReader(System.in, Charset.defaultCharset()));
+        while (true) {
+            final String line = stdin.readLine();
+            if (line == null || line.equalsIgnoreCase("exit")) {
+                System.out.println("Exiting. Kill the application if it does 
not exit due to daemon threads.");
+                this.stop();
+                return;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JsonInputStreamLogEventBridge.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JsonInputStreamLogEventBridge.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JsonInputStreamLogEventBridge.java
new file mode 100644
index 0000000..a0e4fdb
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/JsonInputStreamLogEventBridge.java
@@ -0,0 +1,90 @@
+/*
+ * 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.server;
+
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
+import org.apache.logging.log4j.util.Chars;
+
+/**
+ * Reads and logs JSON {@link LogEvent}s from an {@link InputStream}..
+ */
+public class JsonInputStreamLogEventBridge extends InputStreamLogEventBridge {
+
+    private static final int[] END_PAIR = new int[] { END, END };
+    private static final char EVENT_END_MARKER = '}';
+    private static final char EVENT_START_MARKER = '{';
+    private static final char JSON_ESC = '\\';
+    private static final char JSON_STR_DELIM = Chars.DQUOTE;
+    private static final boolean THREAD_CONTEXT_MAP_AS_LIST = false;
+
+    public JsonInputStreamLogEventBridge() {
+        this(1024, Charset.defaultCharset());
+    }
+
+    public JsonInputStreamLogEventBridge(final int bufferSize, final Charset 
charset) {
+        super(new Log4jJsonObjectMapper(THREAD_CONTEXT_MAP_AS_LIST, true), 
bufferSize, charset,
+                String.valueOf(EVENT_END_MARKER));
+    }
+
+    @Override
+    protected int[] getEventIndices(final String text, final int beginIndex) {
+        // Scan the text for the end of the next JSON object.
+        final int start = text.indexOf(EVENT_START_MARKER, beginIndex);
+        if (start == END) {
+            return END_PAIR;
+        }
+        final char[] charArray = text.toCharArray();
+        int stack = 0;
+        boolean inStr = false;
+        boolean inEsc = false;
+        for (int i = start; i < charArray.length; i++) {
+            final char c = charArray[i];
+            if (inEsc) {
+               // Skip this char and continue
+               inEsc = false;
+            } else {
+                switch (c) {
+                case EVENT_START_MARKER:
+                    if (!inStr) {
+                        stack++;
+                    }
+                    break;
+                case EVENT_END_MARKER:
+                    if (!inStr) {
+                        stack--;
+                    }
+                    break;
+                case JSON_STR_DELIM:
+                    inStr = !inStr;
+                    break;
+                case JSON_ESC:
+                    inEsc = true;
+                    break;
+                }
+                if (stack == 0) {
+                    return new int[] { start, i };
+                }
+            }
+        }
+        return END_PAIR;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/LogEventBridge.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/LogEventBridge.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/LogEventBridge.java
new file mode 100644
index 0000000..ba45bb6
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/LogEventBridge.java
@@ -0,0 +1,57 @@
+/*
+ * 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.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.LogEventListener;
+
+/**
+ * Reads {@link LogEvent}s from the given input stream and logs them as they 
are discovered on the given logger.
+ * 
+ * <p>
+ * Should be stateless.
+ * </p>
+ * 
+ * @param <T>
+ *            The kind of {@link InputStream} to wrap and read.
+ */
+public interface LogEventBridge<T extends InputStream> {
+
+    /**
+     * Reads {@link LogEvent}s from the given input stream and logs them as 
they are discovered on the given logger.
+     * 
+     * @param inputStream
+     *            the input stream to read
+     * @param logEventListener
+     *            TODO
+     * @throws IOException
+     */
+    void logEvents(T inputStream, LogEventListener logEventListener) throws 
IOException;
+
+    /**
+     * Wraps the given stream if needed.
+     * 
+     * @param inputStream
+     *            the stream to wrap
+     * @return the wrapped stream or the given stream.
+     * @throws IOException
+     */
+    T wrapStream(InputStream inputStream) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/ObjectInputStreamLogEventBridge.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/ObjectInputStreamLogEventBridge.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/ObjectInputStreamLogEventBridge.java
new file mode 100644
index 0000000..059f069
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/ObjectInputStreamLogEventBridge.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.net.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.LogEventListener;
+
+/**
+ * Reads and logs serialized {@link LogEvent} objects from an {@link 
ObjectInputStream}.
+ */
+public class ObjectInputStreamLogEventBridge extends 
AbstractLogEventBridge<ObjectInputStream> {
+
+    @Override
+    public void logEvents(final ObjectInputStream inputStream, final 
LogEventListener logEventListener)
+            throws IOException {
+        try {
+            logEventListener.log((LogEvent) inputStream.readObject());
+        } catch (final ClassNotFoundException e) {
+            throw new IOException(e);
+        }
+    }
+
+    @Override
+    public ObjectInputStream wrapStream(final InputStream inputStream) throws 
IOException {
+        return new ObjectInputStream(inputStream);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/SecureTcpSocketServer.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/SecureTcpSocketServer.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/SecureTcpSocketServer.java
new file mode 100644
index 0000000..87390e8
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/SecureTcpSocketServer.java
@@ -0,0 +1,37 @@
+/*
+ * 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.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+
+/**
+ * Listens for events over a secure socket connection (SSL/TLS).
+ * 
+ * @param <T>
+ *        The kind of input stream read
+ */
+public class SecureTcpSocketServer<T extends InputStream> extends 
TcpSocketServer<T> {
+
+    public SecureTcpSocketServer(final int port, final LogEventBridge<T> 
logEventInput,
+            final SslConfiguration sslConfig) throws IOException {
+        super(port, logEventInput, 
sslConfig.getSslServerSocketFactory().createServerSocket(port));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/TcpSocketServer.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/TcpSocketServer.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/TcpSocketServer.java
new file mode 100644
index 0000000..68ac1ba
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/TcpSocketServer.java
@@ -0,0 +1,314 @@
+/*
+ * 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.server;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.OptionalDataException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.validators.PositiveInteger;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.util.BasicCommandLineArguments;
+import org.apache.logging.log4j.core.util.Closer;
+import org.apache.logging.log4j.core.util.Log4jThread;
+import org.apache.logging.log4j.message.EntryMessage;
+
+/**
+ * Listens for Log4j events on a TCP server socket and passes them on to Log4j.
+ * 
+ * @param <T>
+ *        The kind of input stream read
+ * @see #main(String[])
+ */
+public class TcpSocketServer<T extends InputStream> extends 
AbstractSocketServer<T> {
+
+    protected static class CommandLineArguments extends 
AbstractSocketServer.CommandLineArguments {
+        
+        @Parameter(names = { "--backlog",
+                "-b" }, validateWith = PositiveInteger.class, description = 
"Server socket backlog.")
+        // Same default as ServerSocket
+        private int backlog = 50;
+
+        int getBacklog() {
+            return backlog;
+        }
+
+        void setBacklog(final int backlog) {
+            this.backlog = backlog;
+        }        
+
+    }
+
+    /**
+     * Thread that processes the events.
+     */
+    private class SocketHandler extends Log4jThread {
+
+        private final T inputStream;
+
+        private volatile boolean shutdown = false;
+
+        public SocketHandler(final Socket socket) throws IOException {
+            this.inputStream = 
logEventInput.wrapStream(socket.getInputStream());
+        }
+
+        @Override
+        public void run() {
+            final EntryMessage entry = logger.traceEntry();
+            boolean closed = false;
+            try {
+                try {
+                    while (!shutdown) {
+                        logEventInput.logEvents(inputStream, 
TcpSocketServer.this);
+                    }
+                } catch (final EOFException e) {
+                    closed = true;
+                } catch (final OptionalDataException e) {
+                    logger.error("OptionalDataException eof=" + e.eof + " 
length=" + e.length, e);
+                } catch (final IOException e) {
+                    logger.error("IOException encountered while reading from 
socket", e);
+                }
+                if (!closed) {
+                    Closer.closeSilently(inputStream);
+                }
+            } finally {
+                handlers.remove(Long.valueOf(getId()));
+            }
+            logger.traceExit(entry);
+        }
+
+        public void shutdown() {
+            this.shutdown = true;
+            interrupt();
+        }
+    }
+
+    /**
+     * Creates a socket server that reads JSON log events.
+     * 
+     * @param port
+     *        the port to listen
+     * @return a new a socket server
+     * @throws IOException
+     *         if an I/O error occurs when opening the socket.
+     */
+    public static TcpSocketServer<InputStream> createJsonSocketServer(final 
int port) throws IOException {
+        LOGGER.entry("createJsonSocketServer", port);
+        final TcpSocketServer<InputStream> socketServer = new 
TcpSocketServer<>(port, new JsonInputStreamLogEventBridge());
+        return LOGGER.exit(socketServer);
+    }
+
+    /**
+     * Creates a socket server that reads serialized log events.
+     * 
+     * @param port
+     *        the port to listen
+     * @return a new a socket server
+     * @throws IOException
+     *         if an I/O error occurs when opening the socket.
+     */
+    public static TcpSocketServer<ObjectInputStream> 
createSerializedSocketServer(final int port) throws IOException {
+        LOGGER.entry(port);
+        final TcpSocketServer<ObjectInputStream> socketServer = new 
TcpSocketServer<>(port, new ObjectInputStreamLogEventBridge());
+        return LOGGER.exit(socketServer);
+    }
+
+    /**
+     * Creates a socket server that reads serialized log events.
+     * 
+     * @param port the port to listen
+     * @param localBindAddress The server socket's local bin address
+     * @return a new a socket server
+     * @throws IOException
+     *         if an I/O error occurs when opening the socket.
+     * @since 2.7
+     */
+    public static TcpSocketServer<ObjectInputStream> 
createSerializedSocketServer(final int port, final int backlog,
+            final InetAddress localBindAddress) throws IOException {
+        LOGGER.entry(port);
+        final TcpSocketServer<ObjectInputStream> socketServer = new 
TcpSocketServer<>(port, backlog, localBindAddress,
+                new ObjectInputStreamLogEventBridge());
+        return LOGGER.exit(socketServer);
+    }
+
+    /**
+     * Creates a socket server that reads XML log events.
+     * 
+     * @param port
+     *        the port to listen
+     * @return a new a socket server
+     * @throws IOException
+     *         if an I/O error occurs when opening the socket.
+     */
+    public static TcpSocketServer<InputStream> createXmlSocketServer(final int 
port) throws IOException {
+        LOGGER.entry(port);
+        final TcpSocketServer<InputStream> socketServer = new 
TcpSocketServer<>(port, new XmlInputStreamLogEventBridge());
+        return LOGGER.exit(socketServer);
+    }
+
+    /**
+     * Main startup for the server. Run with "--help" for to print command 
line help on the console.
+     * 
+     * @param args
+     *        The command line arguments.
+     * @throws Exception
+     *         if an error occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        final CommandLineArguments cla = 
BasicCommandLineArguments.parseCommandLine(args, TcpSocketServer.class, new 
CommandLineArguments());
+        if (cla.isHelp()) {
+            return;
+        }
+        if (cla.getConfigLocation() != null) {
+            ConfigurationFactory.setConfigurationFactory(new 
ServerConfigurationFactory(cla.getConfigLocation()));
+        }
+        final TcpSocketServer<ObjectInputStream> socketServer = TcpSocketServer
+                .createSerializedSocketServer(cla.getPort(), cla.getBacklog(), 
cla.getLocalBindAddress());
+        final Thread serverThread = socketServer.startNewThread();
+        if (cla.isInteractive()) {
+            socketServer.awaitTermination(serverThread);
+        }
+    }
+
+    private final ConcurrentMap<Long, SocketHandler> handlers = new 
ConcurrentHashMap<>();
+
+    private final ServerSocket serverSocket;
+
+    /**
+     * Constructor.
+     * 
+     * @param port
+     *        The server socket port.
+     * @param backlog
+     *        The server socket backlog.
+     * @param localBindAddress TODO
+     * @param logEventInput
+     *        the log even input
+     * @throws IOException
+     *         if an I/O error occurs when opening the socket.
+     * @since 2.7
+     */
+    @SuppressWarnings("resource")
+    public TcpSocketServer(final int port, final int backlog, final 
InetAddress localBindAddress, final LogEventBridge<T> logEventInput) throws 
IOException {
+        this(port, logEventInput, new ServerSocket(port, backlog, 
localBindAddress));
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param port
+     *        to listen.
+     * @param logEventInput
+     *        the log even input
+     * @throws IOException
+     *         if an I/O error occurs when opening the socket.
+     */
+    public TcpSocketServer(final int port, final LogEventBridge<T> 
logEventInput) throws IOException {
+        this(port, logEventInput, extracted(port));
+    }
+
+    private static ServerSocket extracted(final int port) throws IOException {
+        return new ServerSocket(port);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param port
+     *        to listen.
+     * @param logEventInput
+     *        the log even input
+     * @param serverSocket
+     *        the socket server
+     * @throws IOException
+     *         if an I/O error occurs when opening the socket.
+     */
+    public TcpSocketServer(final int port, final LogEventBridge<T> 
logEventInput, final ServerSocket serverSocket)
+            throws IOException {
+        super(port, logEventInput);
+        this.serverSocket = serverSocket;
+    }
+
+    /**
+     * Accept incoming events and processes them.
+     */
+    @Override
+    public void run() {
+        final EntryMessage entry = logger.traceEntry();
+        while (isActive()) {
+            if (serverSocket.isClosed()) {
+                return;
+            }
+            try {
+                // Accept incoming connections.
+                logger.debug("Listening for a connection {}...", serverSocket);
+                final Socket clientSocket = serverSocket.accept();
+                logger.debug("Acepted connection on {}...", serverSocket);
+                logger.debug("Socket accepted: {}", clientSocket);
+                clientSocket.setSoLinger(true, 0);
+
+                // accept() will block until a client connects to the server.
+                // If execution reaches this point, then it means that a client
+                // socket has been accepted.
+
+                final SocketHandler handler = new SocketHandler(clientSocket);
+                handlers.put(Long.valueOf(handler.getId()), handler);
+                handler.start();
+            } catch (final IOException e) {
+                if (serverSocket.isClosed()) {
+                    // OK we're done.
+                    logger.traceExit(entry);
+                    return;
+                }
+                logger.error("Exception encountered on accept. Ignoring. Stack 
trace :", e);
+            }
+        }
+        for (final Map.Entry<Long, SocketHandler> handlerEntry : 
handlers.entrySet()) {
+            final SocketHandler handler = handlerEntry.getValue();
+            handler.shutdown();
+            try {
+                handler.join();
+            } catch (final InterruptedException ignored) {
+                // Ignore the exception
+            }
+        }
+        logger.traceExit(entry);
+    }
+
+    /**
+     * Shutdown the server.
+     * 
+     * @throws IOException if the server socket could not be closed
+     */
+    @Override
+    public void shutdown() throws IOException {
+        final EntryMessage entry = logger.traceEntry();
+        setActive(false);
+        Thread.currentThread().interrupt();
+        serverSocket.close();
+        logger.traceExit(entry);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/UdpSocketServer.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/UdpSocketServer.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/UdpSocketServer.java
new file mode 100644
index 0000000..ed04f69
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/UdpSocketServer.java
@@ -0,0 +1,169 @@
+/*
+ * 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.server;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.OptionalDataException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.util.BasicCommandLineArguments;
+
+/**
+ * Listens for Log4j events on a datagram socket and passes them on to Log4j. 
+ * 
+ * @param <T>
+ *            The kind of input stream read
+ * @see #main(String[])
+ */
+public class UdpSocketServer<T extends InputStream> extends 
AbstractSocketServer<T> {
+
+    /**
+     * Creates a socket server that reads JSON log events.
+     * 
+     * @param port
+     *            the port to listen
+     * @return a new a socket server
+     * @throws IOException
+     *             if an I/O error occurs when opening the socket.
+     */
+    public static UdpSocketServer<InputStream> createJsonSocketServer(final 
int port) throws IOException {
+        return new UdpSocketServer<>(port, new 
JsonInputStreamLogEventBridge());
+    }
+
+    /**
+     * Creates a socket server that reads serialized log events.
+     * 
+     * @param port
+     *            the port to listen
+     * @return a new a socket server
+     * @throws IOException
+     *             if an I/O error occurs when opening the socket.
+     */
+    public static UdpSocketServer<ObjectInputStream> 
createSerializedSocketServer(final int port) throws IOException {
+        return new UdpSocketServer<>(port, new 
ObjectInputStreamLogEventBridge());
+    }
+
+    /**
+     * Creates a socket server that reads XML log events.
+     * 
+     * @param port
+     *            the port to listen
+     * @return a new a socket server
+     * @throws IOException
+     *             if an I/O error occurs when opening the socket.
+     */
+    public static UdpSocketServer<InputStream> createXmlSocketServer(final int 
port) throws IOException {
+        return new UdpSocketServer<>(port, new XmlInputStreamLogEventBridge());
+    }
+
+    /**
+     * Main startup for the server. Run with "--help" for to print command 
line help on the console.
+     * 
+     * @param args
+     *            The command line arguments.
+     * @throws Exception
+     *             if an error occurs.
+     */
+    public static void main(final String[] args) throws Exception {
+        final CommandLineArguments cla = 
BasicCommandLineArguments.parseCommandLine(args, UdpSocketServer.class, new 
CommandLineArguments());
+        if (cla.isHelp()) {
+            return;
+        }
+        if (cla.getConfigLocation() != null) {
+            ConfigurationFactory.setConfigurationFactory(new 
ServerConfigurationFactory(cla.getConfigLocation()));
+        }
+        final UdpSocketServer<ObjectInputStream> socketServer = UdpSocketServer
+                .createSerializedSocketServer(cla.getPort());
+        final Thread serverThread = socketServer.startNewThread();
+        if (cla.isInteractive()) {
+            socketServer.awaitTermination(serverThread);
+        }
+    }
+
+    private final DatagramSocket datagramSocket;
+
+    // max size so we only have to deal with one packet
+    private final int maxBufferSize = 1024 * 65 + 1024;
+
+    /**
+     * Constructor.
+     * 
+     * @param port
+     *            to listen on.
+     * @param logEventInput
+     * @throws IOException
+     *             If an error occurs.
+     */
+    public UdpSocketServer(final int port, final LogEventBridge<T> 
logEventInput) throws IOException {
+        super(port, logEventInput);
+        this.datagramSocket = new DatagramSocket(port);
+    }
+
+    /**
+     * Accept incoming events and processes them.
+     */
+    @Override
+    public void run() {
+        while (isActive()) {
+            if (datagramSocket.isClosed()) {
+                // OK we're done.
+                return;
+            }
+            try {
+                final byte[] buf = new byte[maxBufferSize];
+                final DatagramPacket packet = new DatagramPacket(buf, 
buf.length);
+                datagramSocket.receive(packet);
+                final ByteArrayInputStream bais = new 
ByteArrayInputStream(packet.getData(), packet.getOffset(), packet.getLength());
+                logEventInput.logEvents(logEventInput.wrapStream(bais), this);
+            } catch (final OptionalDataException e) {
+                if (datagramSocket.isClosed()) {
+                    // OK we're done.
+                    return;
+                }
+                logger.error("OptionalDataException eof=" + e.eof + " length=" 
+ e.length, e);
+            } catch (final EOFException e) {
+                if (datagramSocket.isClosed()) {
+                    // OK we're done.
+                    return;
+                }
+                logger.info("EOF encountered");
+            } catch (final IOException e) {
+                if (datagramSocket.isClosed()) {
+                    // OK we're done.
+                    return;
+                }
+                logger.error("Exception encountered on accept. Ignoring. Stack 
Trace :", e);
+            }
+        }
+    }
+
+    /**
+     * Shutdown the server.
+     */
+    @Override
+    public void shutdown() {
+        this.setActive(false);
+        Thread.currentThread().interrupt();
+        datagramSocket.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f515fa3c/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/XmlInputStreamLogEventBridge.java
----------------------------------------------------------------------
diff --git 
a/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/XmlInputStreamLogEventBridge.java
 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/XmlInputStreamLogEventBridge.java
new file mode 100644
index 0000000..7853398
--- /dev/null
+++ 
b/log4j-server/src/main/java/org/apache/logging/log4j/core/net/server/XmlInputStreamLogEventBridge.java
@@ -0,0 +1,54 @@
+/*
+ * 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.server;
+
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
+
+/**
+ * Reads and logs {@link LogEvent}s from an {@link InputStream}.
+ */
+public class XmlInputStreamLogEventBridge extends InputStreamLogEventBridge {
+
+    private static final String EVENT_END = "</Event>";
+    private static final String EVENT_START_NS_N = "<Event>";
+    private static final String EVENT_START_NS_Y = "<Event ";
+
+    public XmlInputStreamLogEventBridge() {
+        this(1024, Charset.defaultCharset());
+    }
+
+    public XmlInputStreamLogEventBridge(final int bufferSize, final Charset 
charset) {
+        super(new Log4jXmlObjectMapper(), bufferSize, charset, EVENT_END);
+    }
+
+    @Override
+    protected int[] getEventIndices(final String text, final int beginIndex) {
+        int start = text.indexOf(EVENT_START_NS_Y, beginIndex);
+        int startLen = EVENT_START_NS_Y.length();
+        if (start < 0) {
+            start = text.indexOf(EVENT_START_NS_N, beginIndex);
+            startLen = EVENT_START_NS_N.length();
+        }
+        final int end = start < 0 ? -1 : text.indexOf(EVENT_END, start + 
startLen);
+        return new int[] { start, end };
+    }
+
+}

Reply via email to