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 © {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 }; + } + +}
