diff --git a/src/main/java/org/jboss/logmanager/handlers/SocketHandler.java b/src/main/java/org/jboss/logmanager/handlers/SocketHandler.java index be4b2367..a1b4d67d 100644 --- a/src/main/java/org/jboss/logmanager/handlers/SocketHandler.java +++ b/src/main/java/org/jboss/logmanager/handlers/SocketHandler.java @@ -65,8 +65,6 @@ public enum Protocol { @SuppressWarnings("WeakerAccess") public static final int DEFAULT_PORT = 4560; - private final boolean configureSocketFactory; - private final Object outputLock = new Object(); // All the following fields are guarded by outputLock @@ -134,6 +132,22 @@ public SocketHandler(final Protocol protocol, final InetAddress address, final i this(null, protocol, address, port); } + /** + * Creates a socket handler. + * + * @param socketFactory the socket factory to use for creating {@linkplain Protocol#TCP TCP} or + * {@linkplain Protocol#SSL_TCP SSL TCP} connections, if {@code null} a default factory will + * be used + * @param protocol the protocol to connect with + * @param hostname the hostname to connect to + * @param port the port to connect to + * + * @throws UnknownHostException if an error occurs resolving the hostname + */ + public SocketHandler(final SocketFactory socketFactory, final Protocol protocol, final String hostname, final int port) throws UnknownHostException { + this(socketFactory, protocol, InetAddress.getByName(hostname), port); + } + /** * Creates a socket handler. * @@ -151,7 +165,6 @@ public SocketHandler(final SocketFactory socketFactory, final Protocol protocol, initialize = true; writer = null; this.socketFactory = socketFactory; - configureSocketFactory = (socketFactory == null); blockOnReconnect = false; } @@ -200,6 +213,7 @@ public void close() throws SecurityException { synchronized (outputLock) { safeClose(writer); writer = null; + initialize = true; } super.close(); } @@ -276,17 +290,22 @@ public Protocol getProtocol() { } /** - * Sets the protocol to use. + * Sets the protocol to use. If the value is {@code null} the protocol will be set to + * {@linkplain Protocol#TCP TCP}. + *
+ * Note that is resets the {@linkplain #setSocketFactory(SocketFactory) socket factory}. + *
* * @param protocol the protocol to use */ public void setProtocol(final Protocol protocol) { checkAccess(this); synchronized (outputLock) { - // If the socket factory wasn't set, we may need to configure the correct factory - if (configureSocketFactory && this.protocol != protocol) { - socketFactory = null; + if (protocol == null) { + this.protocol = Protocol.TCP; } + // Reset the socket factory + socketFactory = null; this.protocol = protocol; initialize = true; } @@ -314,6 +333,24 @@ public void setPort(final int port) { } } + /** + * Sets the socket factory to use for creating {@linkplain Protocol#TCP TCP} or {@linkplain Protocol#SSL_TCP SSL} + * connections. + *+ * Note that if the {@linkplain #setProtocol(Protocol) protocol} is set the socket factory will be set to + * {@code null} and reset. + *
+ * + * @param socketFactory the socket factory + */ + public void setSocketFactory(final SocketFactory socketFactory) { + checkAccess(this); + synchronized (outputLock) { + this.socketFactory = socketFactory; + initialize = true; + } + } + private void initialize() { final Writer current = this.writer; boolean okay = false; @@ -351,13 +388,19 @@ private void initialize() { private OutputStream createOutputStream() { if (address != null || port >= 0) { try { - if (protocol == Protocol.SSL_TCP) { - return new SslTcpOutputStream(getSocketFactory(), address, port, blockOnReconnect); - } else if (protocol == Protocol.UDP) { + if (protocol == Protocol.UDP) { return new UdpOutputStream(address, port); - } else { - return new TcpOutputStream(getSocketFactory(), address, port, blockOnReconnect); } + SocketFactory socketFactory = this.socketFactory; + if (socketFactory == null) { + if (protocol == Protocol.SSL_TCP) { + this.socketFactory = socketFactory = SSLSocketFactory.getDefault(); + } else { + // Assume we want a TCP connection + this.socketFactory = socketFactory = SocketFactory.getDefault(); + } + } + return new TcpOutputStream(socketFactory, address, port, blockOnReconnect); } catch (IOException e) { reportError("Failed to create socket output stream", e, ErrorManager.OPEN_FAILURE); } @@ -400,16 +443,4 @@ private void safeFlush(Flushable f) { } catch (Throwable ignored) { } } - - private SocketFactory getSocketFactory() { - SocketFactory socketFactory = this.socketFactory; - if (socketFactory == null) { - if (protocol == Protocol.TCP) { - this.socketFactory = socketFactory = SocketFactory.getDefault(); - } else if (protocol == Protocol.SSL_TCP) { - this.socketFactory = socketFactory = SSLSocketFactory.getDefault(); - } - } - return socketFactory; - } -} +} \ No newline at end of file diff --git a/src/test/java/org/jboss/logmanager/handlers/SocketHandlerTests.java b/src/test/java/org/jboss/logmanager/handlers/SocketHandlerTests.java index 9a2eea01..da0737d0 100644 --- a/src/test/java/org/jboss/logmanager/handlers/SocketHandlerTests.java +++ b/src/test/java/org/jboss/logmanager/handlers/SocketHandlerTests.java @@ -5,8 +5,16 @@ import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; +import java.util.logging.Handler; + +import javax.net.ssl.SSLContext; import org.jboss.logmanager.ExtLogRecord; +import org.jboss.logmanager.LogContext; +import org.jboss.logmanager.Logger; +import org.jboss.logmanager.config.FormatterConfiguration; +import org.jboss.logmanager.config.HandlerConfiguration; +import org.jboss.logmanager.config.LogContextConfiguration; import org.jboss.logmanager.formatters.PatternFormatter; import org.jboss.logmanager.handlers.SocketHandler.Protocol; import org.junit.Assert; @@ -158,6 +166,43 @@ public void testTcpReconnect() throws Exception { } } + @Test + public void testTlsConfig() throws Exception { + try (SimpleServer server = SimpleServer.createTlsServer(port)) { + final LogContext logContext = LogContext.create(); + final LogContextConfiguration logContextConfiguration = LogContextConfiguration.Factory.create(logContext); + // Create the formatter + final FormatterConfiguration formatterConfiguration = logContextConfiguration.addFormatterConfiguration( + null, PatternFormatter.class.getName(), "pattern"); + formatterConfiguration.setPropertyValueString("pattern", "%s\n"); + // Create the handler + final HandlerConfiguration handlerConfiguration = logContextConfiguration.addHandlerConfiguration( + null, SocketHandler.class.getName(), "socket", + "protocol", "hostname", "port"); + handlerConfiguration.setPropertyValueString("protocol", Protocol.SSL_TCP.name()); + handlerConfiguration.setPropertyValueString("hostname", address.getHostAddress()); + handlerConfiguration.setPropertyValueString("port", Integer.toString(port)); + handlerConfiguration.setPropertyValueString("autoFlush", "true"); + handlerConfiguration.setPropertyValueString("encoding", "utf-8"); + handlerConfiguration.setFormatterName(formatterConfiguration.getName()); + + logContextConfiguration.addLoggerConfiguration("").addHandlerName(handlerConfiguration.getName()); + + logContextConfiguration.commit(); + + final Handler instance = handlerConfiguration.getInstance(); + Assert.assertTrue(instance instanceof SocketHandler); + ((SocketHandler) instance).setSocketFactory(SSLContext.getDefault().getSocketFactory()); + + // Create the root logger + final Logger logger = logContext.getLogger(""); + logger.info("Test TCP handler " + port + " 1"); + String msg = server.timeoutPoll(); + Assert.assertNotNull(msg); + Assert.assertEquals("Test TCP handler " + port + " 1", msg); + } + } + private SocketHandler createHandler(final Protocol protocol) throws UnsupportedEncodingException { final SocketHandler handler = new SocketHandler(protocol, address, port); handler.setAutoFlush(true);