You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2016/11/14 08:24:46 UTC
logging-log4j2 git commit: [LOG4J2-1707] and [LOG4J2-1708].
Repository: logging-log4j2
Updated Branches:
refs/heads/master 06fe5e6d1 -> 92f1c6528
[LOG4J2-1707] and [LOG4J2-1708].
[LOG4J2-1707] Allow TCP Socket Appender to set socket options.
[LOG4J2-1708]Allow Secure Socket Appender to set socket options.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/92f1c652
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/92f1c652
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/92f1c652
Branch: refs/heads/master
Commit: 92f1c65282cb37d95c7398b562ed2a80e6cfa02a
Parents: 06fe5e6
Author: Gary Gregory <gg...@apache.org>
Authored: Mon Nov 14 00:24:42 2016 -0800
Committer: Gary Gregory <gg...@apache.org>
Committed: Mon Nov 14 00:24:42 2016 -0800
----------------------------------------------------------------------
.../log4j/core/appender/SocketAppender.java | 33 ++-
.../log4j/core/appender/SyslogAppender.java | 37 ++++
.../log4j/core/net/Rfc1349TrafficClass.java | 50 +++++
.../logging/log4j/core/net/SocketOptions.java | 222 +++++++++++++++++++
.../core/net/SocketPerformancePreferences.java | 82 +++++++
.../log4j/core/net/SslSocketManager.java | 88 ++++++--
.../log4j/core/net/TcpSocketManager.java | 190 ++++++++++++----
.../SecureSocketAppenderSocketOptionsTest.java | 119 ++++++++++
.../SocketAppenderSocketOptionsTest.java | 99 +++++++++
.../log4j/core/appender/SocketAppenderTest.java | 7 +-
.../src/test/resources/log4j-socket-options.xml | 32 +++
.../test/resources/log4j-ssl-socket-options.xml | 39 ++++
src/changes/changes.xml | 6 +
13 files changed, 937 insertions(+), 67 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
index 95f9d6e..fd0badb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java
@@ -39,11 +39,11 @@ import org.apache.logging.log4j.core.net.AbstractSocketManager;
import org.apache.logging.log4j.core.net.Advertiser;
import org.apache.logging.log4j.core.net.DatagramSocketManager;
import org.apache.logging.log4j.core.net.Protocol;
+import org.apache.logging.log4j.core.net.SocketOptions;
import org.apache.logging.log4j.core.net.SslSocketManager;
import org.apache.logging.log4j.core.net.TcpSocketManager;
import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
import org.apache.logging.log4j.core.util.Booleans;
-import org.apache.logging.log4j.core.util.Constants;
/**
* An Appender that delivers events over socket connections. Supports both TCP and UDP.
@@ -88,6 +88,9 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM
@PluginAliases({ "reconnectDelay, delayMillis" })
private int reconnectDelayMillis;
+ @PluginElement("SocketOptions")
+ private SocketOptions socketOptions;
+
@PluginElement("SslConfiguration")
@PluginAliases({ "SslConfig" })
private SslConfiguration sslConfiguration;
@@ -114,7 +117,7 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM
}
final AbstractSocketManager manager = SocketAppender.createSocketManager(name, actualProtocol, host, port,
- connectTimeoutMillis, sslConfiguration, reconnectDelayMillis, immediateFail, layout, getBufferSize());
+ connectTimeoutMillis, sslConfiguration, reconnectDelayMillis, immediateFail, layout, getBufferSize(), socketOptions);
return new SocketAppender(name, layout, getFilter(), manager, isIgnoreExceptions(),
!bufferedIo || immediateFlush, advertise ? configuration.getAdvertiser() : null);
@@ -188,6 +191,11 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM
return asBuilder();
}
+ public B withSocketOptions(final SocketOptions socketOptions) {
+ this.socketOptions = socketOptions;
+ return asBuilder();
+ }
+
public B withSslConfiguration(final SslConfiguration sslConfiguration) {
this.sslConfiguration = sslConfiguration;
return asBuilder();
@@ -373,10 +381,25 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM
*
* @throws IllegalArgumentException
* if the protocol cannot be handled.
+ * @deprecated Use {@link #createSocketManager(String, Protocol, String, int, int, SslConfiguration, int, boolean, Layout, int, SocketOptions)}.
*/
+ @Deprecated
protected static AbstractSocketManager createSocketManager(final String name, Protocol protocol, final String host,
final int port, final int connectTimeoutMillis, final SslConfiguration sslConfig, final int reconnectDelayMillis,
final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
+ return createSocketManager(name, protocol, host, port, connectTimeoutMillis, sslConfig, reconnectDelayMillis, immediateFail, layout, bufferSize, null);
+ }
+
+ /**
+ * Creates an AbstractSocketManager for TCP, UDP, and SSL.
+ *
+ * @throws IllegalArgumentException
+ * if the protocol cannot be handled.
+ */
+ protected static AbstractSocketManager createSocketManager(final String name, Protocol protocol, final String host,
+ final int port, final int connectTimeoutMillis, final SslConfiguration sslConfig,
+ final int reconnectDelayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout,
+ final int bufferSize, final SocketOptions socketOptions) {
if (protocol == Protocol.TCP && sslConfig != null) {
// Upgrade TCP to SSL if an SSL config is specified.
protocol = Protocol.SSL;
@@ -386,13 +409,13 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM
}
switch (protocol) {
case TCP:
- return TcpSocketManager.getSocketManager(host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail,
- layout, bufferSize);
+ return TcpSocketManager.getSocketManager(host, port, connectTimeoutMillis, reconnectDelayMillis,
+ immediateFail, layout, bufferSize, socketOptions);
case UDP:
return DatagramSocketManager.getSocketManager(host, port, layout, bufferSize);
case SSL:
return SslSocketManager.getSocketManager(sslConfig, host, port, connectTimeoutMillis, reconnectDelayMillis,
- immediateFail, layout, bufferSize);
+ immediateFail, layout, bufferSize, socketOptions);
default:
throw new IllegalArgumentException(protocol.toString());
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java
index bfe7e3a..6df591d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java
@@ -23,10 +23,12 @@ import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.appender.SocketAppender.Builder;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAliases;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
@@ -37,6 +39,7 @@ import org.apache.logging.log4j.core.net.AbstractSocketManager;
import org.apache.logging.log4j.core.net.Advertiser;
import org.apache.logging.log4j.core.net.Facility;
import org.apache.logging.log4j.core.net.Protocol;
+import org.apache.logging.log4j.core.net.SocketOptions;
import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
import org.apache.logging.log4j.core.util.Constants;
import org.apache.logging.log4j.util.EnglishEnums;
@@ -47,6 +50,40 @@ import org.apache.logging.log4j.util.EnglishEnums;
@Plugin(name = "Syslog", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
public class SyslogAppender extends SocketAppender {
+ public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
+ implements org.apache.logging.log4j.core.util.Builder<SyslogAppender> {
+
+// @PluginAliases("reconnectionDelay") // deprecated
+// @PluginAttribute("name") final String name,
+// @PluginAttribute(value = "immediateFlush", defaultBoolean = true) final boolean immediateFlush,
+// @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions,
+// @PluginAttribute(value = "facility", defaultString = "LOCAL0") final Facility facility,
+// @PluginAttribute("id") final String id,
+// @PluginAttribute(value = "enterpriseNumber", defaultInt = Rfc5424Layout.DEFAULT_ENTERPRISE_NUMBER) final int enterpriseNumber,
+// @PluginAttribute(value = "includeMdc", defaultBoolean = true) final boolean includeMdc,
+// @PluginAttribute("mdcId") final String mdcId,
+// @PluginAttribute("mdcPrefix") final String mdcPrefix,
+// @PluginAttribute("eventPrefix") final String eventPrefix,
+// @PluginAttribute(value = "newLine") final boolean newLine,
+// @PluginAttribute("newLineEscape") final String escapeNL,
+// @PluginAttribute("appName") final String appName,
+// @PluginAttribute("messageId") final String msgId,
+// @PluginAttribute("mdcExcludes") final String excludes,
+// @PluginAttribute("mdcIncludes") final String includes,
+// @PluginAttribute("mdcRequired") final String required,
+// @PluginAttribute("format") final String format,
+// @PluginElement("Filter") final Filter filter,
+// @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charsetName,
+// @PluginAttribute("exceptionPattern") final String exceptionPattern,
+// @PluginElement("LoggerFields") final LoggerFields[] loggerFields,
+
+ @Override
+ public SyslogAppender build() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ }
+
protected static final String RFC5424 = "RFC5424";
protected SyslogAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/main/java/org/apache/logging/log4j/core/net/Rfc1349TrafficClass.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/Rfc1349TrafficClass.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/Rfc1349TrafficClass.java
new file mode 100644
index 0000000..cb071e4
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/Rfc1349TrafficClass.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+/**
+ * Enumerates the RFC 1349 TOS field.
+ *
+ * <ul>
+ * <li>1000 -- minimize delay</li>
+ * <li>0100 -- maximize throughput</li>
+ * <li>0010 -- maximize reliability</li>
+ * <li>0001 -- minimize monetary cost</li>
+ * <li>0000 -- normal service</li>
+ * <ul>
+ */
+public enum Rfc1349TrafficClass {
+
+ // @formatter:off
+ IPTOS_NORMAL(0x00),
+ IPTOS_LOWCOST(0x02),
+ IPTOS_LOWDELAY (0x10),
+ IPTOS_RELIABILITY (0x04),
+ IPTOS_THROUGHPUT (0x08);
+ // @formatter:on
+
+ private final int trafficClass;
+
+ private Rfc1349TrafficClass(final int trafficClass) {
+ this.trafficClass = trafficClass;
+ }
+
+ public int value() {
+ return trafficClass;
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketOptions.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketOptions.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketOptions.java
new file mode 100644
index 0000000..62364e5
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketOptions.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.net;
+
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.logging.log4j.core.Core;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.util.Builder;
+
+/**
+ * Holds all socket options settable via {@link Socket} methods.
+ */
+@Plugin(name = "SocketOptions", category = Core.CATEGORY_NAME, printObject = true)
+public class SocketOptions implements Builder<SocketOptions>, Cloneable {
+
+ @PluginBuilderFactory
+ public static SocketOptions newBuilder() {
+ return new SocketOptions();
+ }
+
+ @PluginBuilderAttribute
+ private Boolean keepAlive;
+
+ @PluginBuilderAttribute
+ private Boolean oobInline;
+
+ @PluginElement("PerformancePreferences")
+ private SocketPerformancePreferences performancePreferences;
+
+ @PluginBuilderAttribute
+ private Integer receiveBufferSize;
+
+ @PluginBuilderAttribute
+ private Boolean reuseAddress;
+
+ @PluginBuilderAttribute
+ private Rfc1349TrafficClass rfc1349TrafficClass;
+
+ @PluginBuilderAttribute
+ private Integer sendBufferSize;
+
+ @PluginBuilderAttribute
+ private Integer soLinger;
+
+ @PluginBuilderAttribute
+ private Integer soTimeout;
+
+ @PluginBuilderAttribute
+ private Boolean tcpNoDelay;
+
+ @PluginBuilderAttribute
+ private Integer trafficClass;
+
+ public void apply(final Socket socket) throws SocketException {
+ if (keepAlive != null) {
+ socket.setKeepAlive(keepAlive.booleanValue());
+ }
+ if (oobInline != null) {
+ socket.setOOBInline(oobInline.booleanValue());
+ }
+ if (reuseAddress != null) {
+ socket.setReuseAddress(reuseAddress.booleanValue());
+ }
+ if (performancePreferences != null) {
+ performancePreferences.apply(socket);
+ }
+ if (receiveBufferSize != null) {
+ socket.setReceiveBufferSize(receiveBufferSize.intValue());
+ }
+ if (soLinger != null) {
+ socket.setSoLinger(true, soLinger.intValue());
+ }
+ if (soTimeout != null) {
+ socket.setSoTimeout(soTimeout.intValue());
+ }
+ if (tcpNoDelay != null) {
+ socket.setTcpNoDelay(tcpNoDelay.booleanValue());
+ }
+ final Integer actualTrafficClass = getActualTrafficClass();
+ if (actualTrafficClass != null) {
+ socket.setTrafficClass(actualTrafficClass);
+ }
+ }
+
+ @Override
+ public SocketOptions build() {
+ try {
+ return (SocketOptions) clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public Integer getActualTrafficClass() {
+ if (trafficClass != null && rfc1349TrafficClass != null) {
+ throw new IllegalStateException("You MUST not set both customTrafficClass and trafficClass.");
+ }
+ if (trafficClass != null) {
+ return trafficClass;
+ }
+ if (rfc1349TrafficClass != null) {
+ return Integer.valueOf(rfc1349TrafficClass.value());
+ }
+ return null;
+ }
+
+ public SocketPerformancePreferences getPerformancePreferences() {
+ return performancePreferences;
+ }
+
+ public Integer getReceiveBufferSize() {
+ return receiveBufferSize;
+ }
+
+ public Rfc1349TrafficClass getRfc1349TrafficClass() {
+ return rfc1349TrafficClass;
+ }
+
+ public Integer getSendBufferSize() {
+ return sendBufferSize;
+ }
+
+ public Integer getSoLinger() {
+ return soLinger;
+ }
+
+ public Integer getSoTimeout() {
+ return soTimeout;
+ }
+
+ public Integer getTrafficClass() {
+ return trafficClass;
+ }
+
+ public Boolean isKeepAlive() {
+ return keepAlive;
+ }
+
+ public Boolean isOobInline() {
+ return oobInline;
+ }
+
+ public Boolean isReuseAddress() {
+ return reuseAddress;
+ }
+
+ public Boolean isTcpNoDelay() {
+ return tcpNoDelay;
+ }
+
+ public void setKeepAlive(final boolean keepAlive) {
+ this.keepAlive = Boolean.valueOf(keepAlive);
+ }
+
+ public void setOobInline(final boolean oobInline) {
+ this.oobInline = Boolean.valueOf(oobInline);
+ }
+
+ public void setPerformancePreferences(final SocketPerformancePreferences performancePreferences) {
+ this.performancePreferences = performancePreferences;
+ }
+
+ public void setReceiveBufferSize(final int receiveBufferSize) {
+ this.receiveBufferSize = receiveBufferSize;
+ }
+
+ public void setReuseAddress(final boolean reuseAddress) {
+ this.reuseAddress = Boolean.valueOf(reuseAddress);
+ }
+
+ public void setRfc1349TrafficClass(final Rfc1349TrafficClass trafficClass) {
+ this.rfc1349TrafficClass = trafficClass;
+ }
+
+ public void setSendBufferSize(final int sendBufferSize) {
+ this.sendBufferSize = sendBufferSize;
+ }
+
+ public void setSoLinger(final int soLinger) {
+ this.soLinger = soLinger;
+ }
+
+ public void setSoTimeout(final int soTimeout) {
+ this.soTimeout = soTimeout;
+ }
+
+ public void setTcpNoDelay(final boolean tcpNoDelay) {
+ this.tcpNoDelay = Boolean.valueOf(tcpNoDelay);
+ }
+
+ public void setTrafficClass(final int trafficClass) {
+ this.trafficClass = trafficClass;
+ }
+
+ @Override
+ public String toString() {
+ return "SocketOptions [keepAlive=" + keepAlive + ", oobInline=" + oobInline + ", performancePreferences="
+ + performancePreferences + ", receiveBufferSize=" + receiveBufferSize + ", reuseAddress=" + reuseAddress
+ + ", rfc1349TrafficClass=" + rfc1349TrafficClass + ", sendBufferSize=" + sendBufferSize + ", soLinger="
+ + soLinger + ", soTimeout=" + soTimeout + ", tcpNoDelay=" + tcpNoDelay + ", trafficClass="
+ + trafficClass + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketPerformancePreferences.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketPerformancePreferences.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketPerformancePreferences.java
new file mode 100644
index 0000000..c7a246a
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SocketPerformancePreferences.java
@@ -0,0 +1,82 @@
+package org.apache.logging.log4j.core.net;
+
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.logging.log4j.core.Core;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
+import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
+import org.apache.logging.log4j.core.util.Builder;
+
+/**
+ * Holds all socket options settable via {@link Socket#setPerformancePreferences(int, int, int)}.
+ * <p>
+ * The {@link Socket#setPerformancePreferences(int, int, int)} API may not be implemented by a JRE.
+ * </p>
+ */
+@Plugin(name = "SocketPerformancePreferences", category = Core.CATEGORY_NAME, printObject = true)
+public class SocketPerformancePreferences implements Builder<SocketPerformancePreferences>, Cloneable {
+
+ @PluginBuilderFactory
+ public static SocketPerformancePreferences newBuilder() {
+ return new SocketPerformancePreferences();
+ }
+
+ @PluginBuilderAttribute
+ @Required
+ private int bandwidth;
+
+ @PluginBuilderAttribute
+ @Required
+ private int connectionTime;
+
+ @PluginBuilderAttribute
+ @Required
+ private int latency;
+
+ public void apply(final Socket socket) {
+ socket.setPerformancePreferences(connectionTime, latency, bandwidth);
+ }
+
+ @Override
+ public SocketPerformancePreferences build() {
+ try {
+ return (SocketPerformancePreferences) clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public int getBandwidth() {
+ return bandwidth;
+ }
+
+ public int getConnectionTime() {
+ return connectionTime;
+ }
+
+ public int getLatency() {
+ return latency;
+ }
+
+ public void setBandwidth(final int bandwidth) {
+ this.bandwidth = bandwidth;
+ }
+
+ public void setConnectionTime(final int connectionTime) {
+ this.connectionTime = connectionTime;
+ }
+
+ public void setLatency(final int latency) {
+ this.latency = latency;
+ }
+
+ @Override
+ public String toString() {
+ return "SocketPerformancePreferences [bandwidth=" + bandwidth + ", connectionTime=" + connectionTime
+ + ", latency=" + latency + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
index ec5c64a..c9d5c6e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
@@ -43,27 +43,51 @@ public class SslSocketManager extends TcpSocketManager {
private final SslConfiguration sslConfig;
/**
- *
- *
- * @param name The unique name of this connection.
- * @param os The OutputStream.
- * @param sock The Socket.
- * @param inetAddress The Internet address of the host.
- * @param host The name of the host.
- * @param port The port number on the host.
- * @param connectTimeoutMillis the connect timeout in milliseconds.
- * @param delay Reconnection interval.
- * @param immediateFail
- * @param layout The Layout.
- * @param bufferSize The buffer size.
- */
- public SslSocketManager(final String name, final OutputStream os, final Socket sock,
- final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port,
- final int connectTimeoutMillis, final int delay, final boolean immediateFail,
- final Layout<? extends Serializable> layout, final int bufferSize) {
- super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, delay, immediateFail, layout, bufferSize);
- this.sslConfig = sslConfig;
- }
+ *
+ *
+ * @param name The unique name of this connection.
+ * @param os The OutputStream.
+ * @param sock The Socket.
+ * @param inetAddress The Internet address of the host.
+ * @param host The name of the host.
+ * @param port The port number on the host.
+ * @param connectTimeoutMillis the connect timeout in milliseconds.
+ * @param delay Reconnection interval.
+ * @param immediateFail
+ * @param layout The Layout.
+ * @param bufferSize The buffer size.
+ * @deprecated Use {@link #SslSocketManager(String, OutputStream, Socket, SslConfiguration, InetAddress, String, int, int, int, boolean, Layout, int, SocketOptions)}.
+ */
+ public SslSocketManager(final String name, final OutputStream os, final Socket sock,
+ final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port,
+ final int connectTimeoutMillis, final int delay, final boolean immediateFail,
+ final Layout<? extends Serializable> layout, final int bufferSize) {
+ super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, delay, immediateFail, layout, bufferSize, null);
+ this.sslConfig = sslConfig;
+ }
+
+ /**
+ *
+ *
+ * @param name The unique name of this connection.
+ * @param os The OutputStream.
+ * @param sock The Socket.
+ * @param inetAddress The Internet address of the host.
+ * @param host The name of the host.
+ * @param port The port number on the host.
+ * @param connectTimeoutMillis the connect timeout in milliseconds.
+ * @param delay Reconnection interval.
+ * @param immediateFail
+ * @param layout The Layout.
+ * @param bufferSize The buffer size.
+ */
+ public SslSocketManager(final String name, final OutputStream os, final Socket sock,
+ final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port,
+ final int connectTimeoutMillis, final int delay, final boolean immediateFail,
+ final Layout<? extends Serializable> layout, final int bufferSize, final SocketOptions socketOptions) {
+ super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, delay, immediateFail, layout, bufferSize, socketOptions);
+ this.sslConfig = sslConfig;
+ }
private static class SslFactoryData {
protected SslConfiguration sslConfiguration;
@@ -74,10 +98,11 @@ public class SslSocketManager extends TcpSocketManager {
private final boolean immediateFail;
private final Layout<? extends Serializable> layout;
private final int bufferSize;
+ private final SocketOptions socketOptions;
public SslFactoryData(final SslConfiguration sslConfiguration, final String host, final int port,
final int connectTimeoutMillis, final int delayMillis, final boolean immediateFail,
- final Layout<? extends Serializable> layout, final int bufferSize) {
+ final Layout<? extends Serializable> layout, final int bufferSize, final SocketOptions socketOptions) {
this.host = host;
this.port = port;
this.connectTimeoutMillis = connectTimeoutMillis;
@@ -86,12 +111,23 @@ public class SslSocketManager extends TcpSocketManager {
this.layout = layout;
this.sslConfiguration = sslConfiguration;
this.bufferSize = bufferSize;
+ this.socketOptions = socketOptions;
}
}
+ /**
+ * @deprecated Use {@link SslSocketManager#getSocketManager(SslConfiguration, String, int, int, int, boolean, Layout, int, SocketOptions)}.
+ */
+ @Deprecated
public static SslSocketManager getSocketManager(final SslConfiguration sslConfig, final String host, int port,
final int connectTimeoutMillis, int reconnectDelayMillis, final boolean immediateFail,
final Layout<? extends Serializable> layout, final int bufferSize) {
+ return getSocketManager(sslConfig, host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize, null);
+ }
+
+ public static SslSocketManager getSocketManager(final SslConfiguration sslConfig, final String host, int port,
+ final int connectTimeoutMillis, int reconnectDelayMillis, final boolean immediateFail,
+ final Layout<? extends Serializable> layout, final int bufferSize, final SocketOptions socketOptions) {
if (Strings.isEmpty(host)) {
throw new IllegalArgumentException("A host name is required");
}
@@ -102,7 +138,7 @@ public class SslSocketManager extends TcpSocketManager {
reconnectDelayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
}
return (SslSocketManager) getManager("TLS:" + host + ':' + port, new SslFactoryData(sslConfig, host, port,
- connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize), FACTORY);
+ connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize, socketOptions), FACTORY);
}
@Override
@@ -155,7 +191,7 @@ public class SslSocketManager extends TcpSocketManager {
return null;
}
return new SslSocketManager(name, os, socket, data.sslConfiguration, inetAddress, data.host, data.port, 0,
- data.delayMillis, data.immediateFail, data.layout, data.bufferSize);
+ data.delayMillis, data.immediateFail, data.layout, data.bufferSize, data.socketOptions);
}
private InetAddress resolveAddress(final String hostName) throws TlsSocketManagerFactoryException {
@@ -183,6 +219,10 @@ public class SslSocketManager extends TcpSocketManager {
socketFactory = createSslSocketFactory(data.sslConfiguration);
socket = (SSLSocket) socketFactory.createSocket(data.host, data.port);
+ final SocketOptions socketOptions = data.socketOptions;
+ if (socketOptions != null) {
+ socketOptions.apply(socket);
+ }
return socket;
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java
index 1e43cee..d7d210e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/TcpSocketManager.java
@@ -23,6 +23,7 @@ import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
+import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
@@ -32,6 +33,7 @@ import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.appender.AppenderLoggingException;
import org.apache.logging.log4j.core.appender.ManagerFactory;
import org.apache.logging.log4j.core.appender.OutputStreamManager;
+import org.apache.logging.log4j.core.net.TcpSocketManager.TcpSocketManagerFactory;
import org.apache.logging.log4j.core.util.Log4jThread;
import org.apache.logging.log4j.core.util.NullOutputStream;
import org.apache.logging.log4j.util.Strings;
@@ -41,11 +43,11 @@ import org.apache.logging.log4j.util.Strings;
*/
public class TcpSocketManager extends AbstractSocketManager {
/**
- The default reconnection delay (30000 milliseconds or 30 seconds).
+ * The default reconnection delay (30000 milliseconds or 30 seconds).
*/
- public static final int DEFAULT_RECONNECTION_DELAY_MILLIS = 30000;
+ public static final int DEFAULT_RECONNECTION_DELAY_MILLIS = 30000;
/**
- The default port number of remote logging server (4560).
+ * The default port number of remote logging server (4560).
*/
private static final int DEFAULT_PORT = 4560;
@@ -57,29 +59,81 @@ public class TcpSocketManager extends AbstractSocketManager {
private Socket socket;
+ private final SocketOptions socketOptions;
+
private final boolean retry;
private final boolean immediateFail;
-
+
private final int connectTimeoutMillis;
/**
- * The Constructor.
- * @param name The unique name of this connection.
- * @param os The OutputStream.
- * @param socket The Socket.
- * @param inetAddress The Internet address of the host.
- * @param host The name of the host.
- * @param port The port number on the host.
- * @param connectTimeoutMillis the connect timeout in milliseconds.
- * @param delay Reconnection interval.
- * @param immediateFail True if the write should fail if no socket is immediately available.
- * @param layout The Layout.
- * @param bufferSize The buffer size.
+ * Constructs.
+ *
+ * @param name
+ * The unique name of this connection.
+ * @param os
+ * The OutputStream.
+ * @param socket
+ * The Socket.
+ * @param inetAddress
+ * The Internet address of the host.
+ * @param host
+ * The name of the host.
+ * @param port
+ * The port number on the host.
+ * @param connectTimeoutMillis
+ * the connect timeout in milliseconds.
+ * @param delay
+ * Reconnection interval.
+ * @param immediateFail
+ * True if the write should fail if no socket is immediately available.
+ * @param layout
+ * The Layout.
+ * @param bufferSize
+ * The buffer size.
+ * @deprecated Use
+ * {@link TcpSocketManager#TcpSocketManager(String, OutputStream, Socket, InetAddress, String, int, int, int, boolean, Layout, int, SocketOptions)}.
+ */
+ @Deprecated
+ public TcpSocketManager(final String name, final OutputStream os, final Socket socket,
+ final InetAddress inetAddress, final String host, final int port, final int connectTimeoutMillis,
+ final int delay, final boolean immediateFail, final Layout<? extends Serializable> layout,
+ final int bufferSize) {
+ this(name, os, socket, inetAddress, host, port, connectTimeoutMillis, delay, immediateFail, layout, bufferSize,
+ null);
+ }
+
+ /**
+ * Constructs.
+ *
+ * @param name
+ * The unique name of this connection.
+ * @param os
+ * The OutputStream.
+ * @param socket
+ * The Socket.
+ * @param inetAddress
+ * The Internet address of the host.
+ * @param host
+ * The name of the host.
+ * @param port
+ * The port number on the host.
+ * @param connectTimeoutMillis
+ * the connect timeout in milliseconds.
+ * @param delay
+ * Reconnection interval.
+ * @param immediateFail
+ * True if the write should fail if no socket is immediately available.
+ * @param layout
+ * The Layout.
+ * @param bufferSize
+ * The buffer size.
*/
- public TcpSocketManager(final String name, final OutputStream os, final Socket socket, final InetAddress inetAddress,
- final String host, final int port, final int connectTimeoutMillis, final int delay,
- final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
+ public TcpSocketManager(final String name, final OutputStream os, final Socket socket,
+ final InetAddress inetAddress, final String host, final int port, final int connectTimeoutMillis,
+ final int delay, final boolean immediateFail, final Layout<? extends Serializable> layout,
+ final int bufferSize, final SocketOptions socketOptions) {
super(name, os, inetAddress, host, port, layout, true, bufferSize);
this.connectTimeoutMillis = connectTimeoutMillis;
this.reconnectionDelay = delay;
@@ -90,19 +144,51 @@ public class TcpSocketManager extends AbstractSocketManager {
reconnector = createReconnector();
reconnector.start();
}
+ this.socketOptions = socketOptions;
+ }
+
+ /**
+ * Obtains a TcpSocketManager.
+ *
+ * @param host
+ * The host to connect to.
+ * @param port
+ * The port on the host.
+ * @param connectTimeoutMillis
+ * the connect timeout in milliseconds
+ * @param reconnectDelayMillis
+ * The interval to pause between retries.
+ * @param bufferSize
+ * The buffer size.
+ * @return A TcpSocketManager.
+ * @deprecated Use {@link #getSocketManager(String, int, int, int, boolean, Layout, int, SocketOptions)}.
+ */
+ @Deprecated
+ public static TcpSocketManager getSocketManager(final String host, int port, final int connectTimeoutMillis,
+ int reconnectDelayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout,
+ final int bufferSize) {
+ return getSocketManager(host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout,
+ bufferSize, null);
}
/**
* Obtains a TcpSocketManager.
- * @param host The host to connect to.
- * @param port The port on the host.
- * @param connectTimeoutMillis the connect timeout in milliseconds
- * @param reconnectDelayMillis The interval to pause between retries.
- * @param bufferSize The buffer size.
+ *
+ * @param host
+ * The host to connect to.
+ * @param port
+ * The port on the host.
+ * @param connectTimeoutMillis
+ * the connect timeout in milliseconds
+ * @param reconnectDelayMillis
+ * The interval to pause between retries.
+ * @param bufferSize
+ * The buffer size.
* @return A TcpSocketManager.
*/
public static TcpSocketManager getSocketManager(final String host, int port, final int connectTimeoutMillis,
- int reconnectDelayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
+ int reconnectDelayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout,
+ final int bufferSize, final SocketOptions socketOptions) {
if (Strings.isEmpty(host)) {
throw new IllegalArgumentException("A host name is required");
}
@@ -112,12 +198,12 @@ public class TcpSocketManager extends AbstractSocketManager {
if (reconnectDelayMillis == 0) {
reconnectDelayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
}
- return (TcpSocketManager) getManager("TCP:" + host + ':' + port, new FactoryData(
- host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize), FACTORY);
+ return (TcpSocketManager) getManager("TCP:" + host + ':' + port, new FactoryData(host, port,
+ connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize, socketOptions), FACTORY);
}
@Override
- protected void write(final byte[] bytes, final int offset, final int length, final boolean immediateFlush) {
+ protected void write(final byte[] bytes, final int offset, final int length, final boolean immediateFlush) {
if (socket == null) {
if (reconnector != null && !immediateFail) {
reconnector.latch();
@@ -203,7 +289,7 @@ public class TcpSocketManager extends AbstractSocketManager {
this.owner = owner;
}
- public void latch() {
+ public void latch() {
try {
latch.await();
} catch (final InterruptedException ex) {
@@ -260,9 +346,11 @@ public class TcpSocketManager extends AbstractSocketManager {
}
protected Socket createSocket(final String host, final int port) throws IOException {
- final InetSocketAddress address = new InetSocketAddress(host, port);
final Socket newSocket = new Socket();
- newSocket.connect(address, connectTimeoutMillis);
+ newSocket.connect(new InetSocketAddress(host, port), connectTimeoutMillis);
+ if (socketOptions != null) {
+ socketOptions.apply(newSocket);
+ }
return newSocket;
}
@@ -277,9 +365,11 @@ public class TcpSocketManager extends AbstractSocketManager {
private final boolean immediateFail;
private final Layout<? extends Serializable> layout;
private final int bufferSize;
+ private final SocketOptions socketOptions;
- public FactoryData(final String host, final int port, final int connectTimeoutMillis, final int reconnectDelayMillis,
- final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
+ public FactoryData(final String host, final int port, final int connectTimeoutMillis,
+ final int reconnectDelayMillis, final boolean immediateFail,
+ final Layout<? extends Serializable> layout, final int bufferSize, final SocketOptions socketOptions) {
this.host = host;
this.port = port;
this.connectTimeoutMillis = connectTimeoutMillis;
@@ -287,6 +377,7 @@ public class TcpSocketManager extends AbstractSocketManager {
this.immediateFail = immediateFail;
this.layout = layout;
this.bufferSize = bufferSize;
+ this.socketOptions = socketOptions;
}
}
@@ -307,11 +398,11 @@ public class TcpSocketManager extends AbstractSocketManager {
}
try {
// LOG4J2-1042
- final Socket socket = new Socket();
- socket.connect(new InetSocketAddress(data.host, data.port), data.connectTimeoutMillis);
+ final Socket socket = createSocket(data);
os = socket.getOutputStream();
return new TcpSocketManager(name, os, socket, inetAddress, data.host, data.port,
- data.connectTimeoutMillis, data.reconnectDelayMillis, data.immediateFail, data.layout, data.bufferSize);
+ data.connectTimeoutMillis, data.reconnectDelayMillis, data.immediateFail, data.layout,
+ data.bufferSize, data.socketOptions);
} catch (final IOException ex) {
LOGGER.error("TcpSocketManager (" + name + ") " + ex, ex);
os = NullOutputStream.getInstance();
@@ -320,8 +411,33 @@ public class TcpSocketManager extends AbstractSocketManager {
return null;
}
return new TcpSocketManager(name, os, null, inetAddress, data.host, data.port, data.connectTimeoutMillis,
- data.reconnectDelayMillis, data.immediateFail, data.layout, data.bufferSize);
+ data.reconnectDelayMillis, data.immediateFail, data.layout, data.bufferSize, data.socketOptions);
+ }
+
+ static Socket createSocket(final FactoryData data) throws IOException, SocketException {
+ final Socket socket = new Socket();
+ socket.connect(new InetSocketAddress(data.host, data.port), data.connectTimeoutMillis);
+ final SocketOptions socketOptions = data.socketOptions;
+ if (socketOptions != null) {
+ socketOptions.apply(socket);
+ }
+ return socket;
}
+
+ }
+
+ /**
+ * USE AT YOUR OWN RISK, method is public for testing purpose only for now.
+ */
+ public SocketOptions getSocketOptions() {
+ return socketOptions;
+ }
+
+ /**
+ * USE AT YOUR OWN RISK, method is public for testing purpose only for now.
+ */
+ public Socket getSocket() {
+ return socket;
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
new file mode 100644
index 0000000..cc1327f
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import javax.net.ssl.SSLServerSocketFactory;
+
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
+import org.apache.logging.log4j.core.net.SocketOptions;
+import org.apache.logging.log4j.core.net.TcpSocketManager;
+import org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration;
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+import org.apache.logging.log4j.core.net.ssl.StoreConfigurationException;
+import org.apache.logging.log4j.core.net.ssl.TestConstants;
+import org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration;
+import org.apache.logging.log4j.core.util.NullOutputStream;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class SecureSocketAppenderSocketOptionsTest {
+
+ private static final int PORT;
+ private static TcpSocketTestServer tcpSocketTestServer;
+
+ private static SSLServerSocketFactory serverSocketFactory;
+ private static SslConfiguration sslConfiguration;
+
+ static {
+ PORT = AvailablePortFinder.getNextAvailable();
+ System.setProperty("SecureSocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
+ try {
+ initServerSocketFactory();
+ tcpSocketTestServer = new TcpSocketTestServer(serverSocketFactory.createServerSocket(PORT));
+ tcpSocketTestServer.start();
+ loggerContextRule = new LoggerContextRule("log4j-ssl-socket-options.xml");
+ } catch (IOException | StoreConfigurationException e) {
+ throw new IllegalStateException(e);
+ }
+
+ }
+
+ @ClassRule
+ public static final LoggerContextRule loggerContextRule;
+
+ @AfterClass
+ public static void afterClass() {
+ if (tcpSocketTestServer != null) {
+ tcpSocketTestServer.shutdown();
+ }
+ }
+
+ public static void initServerSocketFactory() throws StoreConfigurationException {
+ final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE,
+ TestConstants.KEYSTORE_PWD, null, null);
+ final TrustStoreConfiguration tsc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE,
+ TestConstants.TRUSTSTORE_PWD, null, null);
+ sslConfiguration = SslConfiguration.createSSLConfiguration(null, ksc, tsc);
+ serverSocketFactory = sslConfiguration.getSslServerSocketFactory();
+ }
+
+ @Test
+ public void testSocketOptions() throws IOException {
+ Assert.assertNotNull(loggerContextRule);
+ Assert.assertNotNull(loggerContextRule.getConfiguration());
+ final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+ Assert.assertNotNull(appender);
+ final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+ Assert.assertNotNull(manager);
+ final OutputStream outputStream = manager.getOutputStream();
+ Assert.assertFalse(outputStream instanceof NullOutputStream);
+ final SocketOptions socketOptions = manager.getSocketOptions();
+ Assert.assertNotNull(socketOptions);
+ final Socket socket = manager.getSocket();
+ Assert.assertNotNull(socket);
+ // Test config request
+ Assert.assertEquals(false, socketOptions.isKeepAlive());
+ Assert.assertEquals(null, socketOptions.isOobInline());
+ Assert.assertEquals(false, socketOptions.isReuseAddress());
+ Assert.assertEquals(false, socketOptions.isTcpNoDelay());
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
+ socketOptions.getActualTrafficClass().intValue());
+ Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
+ Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
+ Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
+ Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
+ // Test live socket
+ Assert.assertEquals(false, socket.getKeepAlive());
+ Assert.assertEquals(false, socket.getReuseAddress());
+ Assert.assertEquals(false, socket.getTcpNoDelay());
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
+ Assert.assertEquals(10000, socket.getReceiveBufferSize());
+ // This settings changes while we are running, so we cannot assert it.
+ // Assert.assertEquals(8000, socket.getSendBufferSize());
+ Assert.assertEquals(12345, socket.getSoLinger());
+ Assert.assertEquals(54321, socket.getSoTimeout());
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
new file mode 100644
index 0000000..ea3ada1
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
+import org.apache.logging.log4j.core.net.SocketOptions;
+import org.apache.logging.log4j.core.net.TcpSocketManager;
+import org.apache.logging.log4j.core.util.NullOutputStream;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class SocketAppenderSocketOptionsTest {
+
+ private static final int PORT;
+ private static TcpSocketTestServer tcpSocketTestServer;
+
+ static {
+ PORT = AvailablePortFinder.getNextAvailable();
+ System.setProperty("SocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
+ try {
+ tcpSocketTestServer = new TcpSocketTestServer(PORT);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ tcpSocketTestServer.start();
+ loggerContextRule = new LoggerContextRule("log4j-socket-options.xml");
+ }
+
+ @ClassRule
+ public static final LoggerContextRule loggerContextRule;
+
+ @AfterClass
+ public static void afterClass() {
+ if (tcpSocketTestServer != null) {
+ tcpSocketTestServer.shutdown();
+ }
+ }
+
+ @Test
+ public void testSocketOptions() throws IOException {
+ Assert.assertNotNull(loggerContextRule);
+ Assert.assertNotNull(loggerContextRule.getConfiguration());
+ final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+ Assert.assertNotNull(appender);
+ final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+ Assert.assertNotNull(manager);
+ final OutputStream outputStream = manager.getOutputStream();
+ Assert.assertFalse(outputStream instanceof NullOutputStream);
+ final SocketOptions socketOptions = manager.getSocketOptions();
+ Assert.assertNotNull(socketOptions);
+ final Socket socket = manager.getSocket();
+ Assert.assertNotNull(socket);
+ // Test config request
+ Assert.assertEquals(false, socketOptions.isKeepAlive());
+ Assert.assertEquals(false, socketOptions.isOobInline());
+ Assert.assertEquals(false, socketOptions.isReuseAddress());
+ Assert.assertEquals(false, socketOptions.isTcpNoDelay());
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
+ socketOptions.getActualTrafficClass().intValue());
+ Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
+ Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
+ Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
+ Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
+ // Test live socket
+ Assert.assertEquals(false, socket.getKeepAlive());
+ Assert.assertEquals(false, socket.getOOBInline());
+ Assert.assertEquals(false, socket.getReuseAddress());
+ Assert.assertEquals(false, socket.getTcpNoDelay());
+ Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
+ Assert.assertEquals(10000, socket.getReceiveBufferSize());
+ // This settings changes while we are running, so we cannot assert it.
+ // Assert.assertEquals(8000, socket.getSendBufferSize());
+ Assert.assertEquals(12345, socket.getSoLinger());
+ Assert.assertEquals(54321, socket.getSoTimeout());
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
index 8d7e4b1..e8d1053 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
@@ -332,8 +332,13 @@ public class SocketAppenderTest {
private volatile int count = 0;
private final BlockingQueue<LogEvent> queue;
+ @SuppressWarnings("resource")
public TcpSocketTestServer(final int port) throws IOException {
- this.serverSocket = new ServerSocket(port);
+ this(new ServerSocket(port));
+ }
+
+ public TcpSocketTestServer(ServerSocket serverSocket) {
+ this.serverSocket = serverSocket;
this.queue = new ArrayBlockingQueue<>(10);
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/test/resources/log4j-socket-options.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-socket-options.xml b/log4j-core/src/test/resources/log4j-socket-options.xml
new file mode 100644
index 0000000..3af324f
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-socket-options.xml
@@ -0,0 +1,32 @@
+<?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.
+ -->
+<Configuration status="OFF" name="MyApp">
+ <Appenders>
+ <Socket name="socket" host="localhost" port="${sys:SocketAppenderSocketOptionsTest.port}" protocol="TCP" ignoreExceptions="false">
+ <SocketOptions keepAlive="false" oobInline="false" receiveBufferSize="10000" reuseAddress="false"
+ rfc1349TrafficClass="IPTOS_LOWCOST" sendBufferSize="8000" soLinger="12345" soTimeout="54321" tcpNoDelay="false">
+ <SocketPerformancePreferences bandwidth="100" connectionTime="100" latency="100" />
+ </SocketOptions>
+ </Socket>
+ </Appenders>
+ <Loggers>
+ <Root level="debug">
+ <AppenderRef ref="socket" />
+ </Root>
+ </Loggers>
+</Configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/log4j-core/src/test/resources/log4j-ssl-socket-options.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-ssl-socket-options.xml b/log4j-core/src/test/resources/log4j-ssl-socket-options.xml
new file mode 100644
index 0000000..5b7d08d
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-ssl-socket-options.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<Configuration status="OFF" name="MyApp">
+ <Appenders>
+ <Socket name="socket" host="localhost" port="${sys:SecureSocketAppenderSocketOptionsTest.port}" protocol="SSL"
+ ignoreExceptions="false">
+ <SocketOptions keepAlive="false" receiveBufferSize="10000" reuseAddress="false" rfc1349TrafficClass="IPTOS_LOWCOST"
+ sendBufferSize="8000" soLinger="12345" soTimeout="54321" tcpNoDelay="false">
+ <SocketPerformancePreferences bandwidth="100" connectionTime="100" latency="100" />
+ </SocketOptions>
+ <Ssl>
+ <KeyStore location="src/test/resources/org/apache/logging/log4j/core/net/ssl/client.log4j2-keystore.jks"
+ password="changeit" type="JKS" />
+ <TrustStore location="src/test/resources/org/apache/logging/log4j/core/net/ssl/truststore.jks"
+ password="changeit" type="JKS" />
+ </Ssl>
+ </Socket>
+ </Appenders>
+ <Loggers>
+ <Root level="debug">
+ <AppenderRef ref="socket" />
+ </Root>
+ </Loggers>
+</Configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92f1c652/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b9aa337..037f404 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -147,6 +147,12 @@
<action issue="LOG4J2-1704" dev="ggregory" type="add">
Add a Builder to RollingRandomAccessFileAppender and deprecate RollingRandomAccessFileAppender.createAppender().
</action>
+ <action issue="LOG4J2-1707" dev="ggregory" type="add">
+ Allow TCP Socket Appender to set socket options.
+ </action>
+ <action issue="LOG4J2-1708" dev="ggregory" type="add">
+ Allow Secure Socket Appender to set socket options.
+ </action>
</release>
<release version="2.7" date="2016-10-02" description="GA Release 2.7">
<action issue="LOG4J2-1618" dev="rpopma" type="fix" due-to="Raman Gupta">