[Git][java-team/jboss-logmanager][master] 5 commits: Declare compliance with Debian Policy 4.1.5.
Markus Koschany
gitlab at salsa.debian.org
Sat Jul 7 21:19:55 BST 2018
Markus Koschany pushed to branch master at Debian Java Maintainers / jboss-logmanager
Commits:
83b3aec3 by Markus Koschany at 2018-07-07T22:08:49+02:00
Declare compliance with Debian Policy 4.1.5.
- - - - -
af8bae6a by Markus Koschany at 2018-07-07T22:10:13+02:00
Update copyright years.
- - - - -
a32bc41a by Markus Koschany at 2018-07-07T22:13:12+02:00
New upstream version 2.1.4
- - - - -
1fc29553 by Markus Koschany at 2018-07-07T22:13:19+02:00
Update upstream source from tag 'upstream/2.1.4'
Update to upstream version '2.1.4'
with Debian dir 2cfd41246a1c1bf14e2def85fec62562510e0ec2
- - - - -
2a2b20fc by Markus Koschany at 2018-07-07T22:13:54+02:00
Update changelog
- - - - -
16 changed files:
- debian/changelog
- debian/control
- debian/copyright
- pom.xml
- src/main/java/org/jboss/logmanager/LogContext.java
- src/main/java/org/jboss/logmanager/LoggerNode.java
- src/main/java/org/jboss/logmanager/config/LogContextConfigurationImpl.java
- src/main/java/org/jboss/logmanager/formatters/Formatters.java
- + src/main/java/org/jboss/logmanager/handlers/ClientSocketFactory.java
- src/main/java/org/jboss/logmanager/handlers/SocketHandler.java
- src/main/java/org/jboss/logmanager/handlers/SyslogHandler.java
- src/main/java/org/jboss/logmanager/handlers/TcpOutputStream.java
- src/main/java/org/jboss/logmanager/handlers/UdpOutputStream.java
- + src/test/java/org/jboss/logmanager/LogContextCloseTests.java
- src/test/java/org/jboss/logmanager/formatters/PatternFormatterTests.java
- src/test/java/org/jboss/logmanager/handlers/PeriodicRotatingFileHandlerTests.java
Changes:
=====================================
debian/changelog
=====================================
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+jboss-logmanager (2.1.4-1) unstable; urgency=medium
+
+ * New upstream version 2.1.4.
+ * Declare compliance with Debian Policy 4.1.5.
+
+ -- Markus Koschany <apo at debian.org> Sat, 07 Jul 2018 22:13:30 +0200
+
jboss-logmanager (2.1.2-1) unstable; urgency=medium
* New upstream version 2.1.2.
=====================================
debian/control
=====================================
--- a/debian/control
+++ b/debian/control
@@ -18,7 +18,7 @@ Build-Depends:
libmaven-source-plugin-java,
libwildfly-common-java,
maven-debian-helper (>= 1.5)
-Standards-Version: 4.1.4
+Standards-Version: 4.1.5
Vcs-Git: https://anonscm.debian.org/git/pkg-java/jboss-logmanager.git
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/jboss-logmanager.git
Homepage: https://github.com/jboss-logging/jboss-logmanager
=====================================
debian/copyright
=====================================
--- a/debian/copyright
+++ b/debian/copyright
@@ -3,7 +3,7 @@ Upstream-Name: JBoss Log Manager
Source: https://github.com/jboss-logging/jboss-logmanager
Files: *
-Copyright: 2014-2016, Red Hat, Inc.
+Copyright: 2014-2018, Red Hat, Inc.
License: Apache-2.0
Files: debian/*
=====================================
pom.xml
=====================================
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
<groupId>org.jboss.logmanager</groupId>
<artifactId>jboss-logmanager</artifactId>
<packaging>jar</packaging>
- <version>2.1.2.Final</version>
+ <version>2.1.4.Final</version>
<parent>
<groupId>org.jboss</groupId>
@@ -47,9 +47,9 @@
<properties>
<!-- Dependency versions -->
<version.javax.json>1.0</version.javax.json>
- <version.org.byteman>3.0.10</version.org.byteman>
+ <version.org.byteman>4.0.3</version.org.byteman>
<version.org.glassfish.javax.json>1.0.4</version.org.glassfish.javax.json>
- <version.org.jboss.modules.jboss-modules>1.7.0.Beta3</version.org.jboss.modules.jboss-modules>
+ <version.org.jboss.modules.jboss-modules>1.7.0.Final</version.org.jboss.modules.jboss-modules>
<version.org.wildfly.common.wildfly-common>1.2.0.Final</version.org.wildfly.common.wildfly-common>
<version.junit.junit>4.12</version.junit.junit>
=====================================
src/main/java/org/jboss/logmanager/LogContext.java
=====================================
--- a/src/main/java/org/jboss/logmanager/LogContext.java
+++ b/src/main/java/org/jboss/logmanager/LogContext.java
@@ -21,18 +21,20 @@ package org.jboss.logmanager;
import java.lang.ref.WeakReference;
import java.security.Permission;
+import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
+import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-
import java.util.logging.Level;
import java.util.logging.LoggingMXBean;
import java.util.logging.LoggingPermission;
@@ -40,7 +42,8 @@ import java.util.logging.LoggingPermission;
/**
* A logging context, for producing isolated logging environments.
*/
-public final class LogContext implements Protectable {
+ at SuppressWarnings("unused")
+public final class LogContext implements Protectable, AutoCloseable {
private static final LogContext SYSTEM_CONTEXT = new LogContext(false);
static final Permission CREATE_CONTEXT_PERMISSION = new RuntimePermission("createLogContext", null);
@@ -98,6 +101,8 @@ public final class LogContext implements Protectable {
}
private final AtomicReference<Map<String, LevelRef>> levelMapReference;
+ // Guarded by treeLock
+ private final Set<AutoCloseable> closeHandlers;
/**
* This lock is taken any time a change is made which affects multiple nodes in the hierarchy.
@@ -109,6 +114,7 @@ public final class LogContext implements Protectable {
levelMapReference = new AtomicReference<Map<String, LevelRef>>(LazyHolder.INITIAL_LEVEL_MAP);
rootLogger = new LoggerNode(this);
loggerNames = new ConcurrentSkipListMap<String, AtomicInteger>();
+ closeHandlers = new LinkedHashSet<>();
}
/**
@@ -340,6 +346,20 @@ public final class LogContext implements Protectable {
granted.remove();
}
+ @Override
+ public void close() throws Exception {
+ synchronized (treeLock) {
+ // First we want to close all loggers
+ recursivelyClose(rootLogger);
+ // Next process the close handlers associated with this log context
+ for (AutoCloseable handler : closeHandlers) {
+ handler.close();
+ }
+ // Finally clear any logger names
+ loggerNames.clear();
+ }
+ }
+
/**
* Returns an enumeration of the logger names that have been created. This does not return names of loggers that
* may have been garbage collected. Logger names added after the enumeration has been retrieved may also be added to
@@ -383,6 +403,49 @@ public final class LogContext implements Protectable {
};
}
+ /**
+ * Adds a handler invoked during the {@linkplain #close() close} of this log context. The close handlers will be
+ * invoked in the order they are added.
+ * <p>
+ * The loggers associated with this context will always be closed.
+ * </p>
+ *
+ * @param closeHandler the close handler to use
+ */
+ public void addCloseHandler(final AutoCloseable closeHandler) {
+ synchronized (treeLock) {
+ closeHandlers.add(closeHandler);
+ }
+ }
+
+ /**
+ * Gets the current close handlers associated with this log context.
+ *
+ * @return the current close handlers
+ */
+ public Set<AutoCloseable> getCloseHandlers() {
+ synchronized (treeLock) {
+ return new LinkedHashSet<>(closeHandlers);
+ }
+ }
+
+ /**
+ * Clears any current close handlers associated with log context, then adds the handlers to be invoked during
+ * the {@linkplain #close() close} of this log context. The close handlers will be invoked in the order they are
+ * added.
+ * <p>
+ * The loggers associated with this context will always be closed.
+ * </p>
+ *
+ * @param closeHandlers the close handlers to use
+ */
+ public void setCloseHandlers(final Collection<AutoCloseable> closeHandlers) {
+ synchronized (treeLock) {
+ this.closeHandlers.clear();
+ this.closeHandlers.addAll(closeHandlers);
+ }
+ }
+
protected void incrementRef(final String name) {
AtomicInteger counter = loggerNames.get(name);
if (counter == null) {
@@ -426,6 +489,15 @@ public final class LogContext implements Protectable {
return strong ? new CopyOnWriteMap<String, LoggerNode>() : new CopyOnWriteWeakMap<String, LoggerNode>();
}
+ private void recursivelyClose(final LoggerNode loggerNode) {
+ synchronized (treeLock) {
+ for (LoggerNode child : loggerNode.getChildren()) {
+ recursivelyClose(child);
+ }
+ loggerNode.close();
+ }
+ }
+
private interface LevelRef {
Level get();
}
=====================================
src/main/java/org/jboss/logmanager/LoggerNode.java
=====================================
--- a/src/main/java/org/jboss/logmanager/LoggerNode.java
+++ b/src/main/java/org/jboss/logmanager/LoggerNode.java
@@ -24,7 +24,6 @@ import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
@@ -35,7 +34,7 @@ import java.util.logging.Level;
/**
* A node in the tree of logger names. Maintains weak references to children and a strong reference to its parent.
*/
-final class LoggerNode {
+final class LoggerNode implements AutoCloseable {
/**
* The log context.
@@ -144,6 +143,26 @@ final class LoggerNode {
children = context.createChildMap();
}
+ @Override
+ public void close() {
+ synchronized (context.treeLock) {
+ // Reset everything to defaults
+ filter = null;
+ if ("".equals(fullName)) {
+ level = Level.INFO;
+ effectiveLevel = Level.INFO.intValue();
+ } else {
+ level = null;
+ effectiveLevel = Level.INFO.intValue();
+ }
+ handlersUpdater.clear(this);
+ useParentFilter = false;
+ useParentHandlers = true;
+ attachmentsUpdater.get(this).clear();
+ children.clear();
+ }
+ }
+
/**
* Get or create a relative logger node. The name is relatively qualified to this node.
*
@@ -380,13 +399,8 @@ final class LoggerNode {
V old;
do {
oldAttachments = attachments;
- if (oldAttachments.isEmpty() || oldAttachments.size() == 1 && oldAttachments.containsKey(key)) {
- old = (V) oldAttachments.get(key);
- newAttachments = Collections.<Logger.AttachmentKey, Object>singletonMap(key, value);
- } else {
- newAttachments = new HashMap<Logger.AttachmentKey, Object>(oldAttachments);
- old = (V) newAttachments.put(key, value);
- }
+ newAttachments = new HashMap<>(oldAttachments);
+ old = (V) newAttachments.put(key, value);
} while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
return old;
}
@@ -403,15 +417,11 @@ final class LoggerNode {
Map<Logger.AttachmentKey, Object> newAttachments;
do {
oldAttachments = attachments;
- if (oldAttachments.isEmpty()) {
- newAttachments = Collections.<Logger.AttachmentKey, Object>singletonMap(key, value);
- } else {
- if (oldAttachments.containsKey(key)) {
- return (V) oldAttachments.get(key);
- }
- newAttachments = new HashMap<Logger.AttachmentKey, Object>(oldAttachments);
- newAttachments.put(key, value);
+ if (oldAttachments.containsKey(key)) {
+ return (V) oldAttachments.get(key);
}
+ newAttachments = new HashMap<>(oldAttachments);
+ newAttachments.put(key, value);
} while (! attachmentsUpdater.compareAndSet(this, oldAttachments, newAttachments));
return null;
}
@@ -434,16 +444,6 @@ final class LoggerNode {
if (size == 1) {
// special case - the new map is empty
newAttachments = Collections.emptyMap();
- } else if (size == 2) {
- // special case - the new map is a singleton
- final Iterator<Map.Entry<Logger.AttachmentKey,Object>> it = oldAttachments.entrySet().iterator();
- // find the entry that we are not removing
- Map.Entry<Logger.AttachmentKey, Object> entry = it.next();
- if (entry.getKey() == key) {
- // must be the next one
- entry = it.next();
- }
- newAttachments = Collections.singletonMap(entry.getKey(), entry.getValue());
} else {
newAttachments = new HashMap<Logger.AttachmentKey, Object>(oldAttachments);
}
=====================================
src/main/java/org/jboss/logmanager/config/LogContextConfigurationImpl.java
=====================================
--- a/src/main/java/org/jboss/logmanager/config/LogContextConfigurationImpl.java
+++ b/src/main/java/org/jboss/logmanager/config/LogContextConfigurationImpl.java
@@ -85,6 +85,7 @@ final class LogContextConfigurationImpl implements LogContextConfiguration {
LogContextConfigurationImpl(final LogContext logContext) {
this.logContext = logContext;
+ logContext.addCloseHandler(new LogContextConfigurationCloseHandler());
}
public LogContext getLogContext() {
@@ -738,4 +739,43 @@ final class LogContextConfigurationImpl implements LogContextConfiguration {
ObjectProducer resolveFilter(String expression) {
return resolveFilter(expression, false);
}
+
+ private class LogContextConfigurationCloseHandler implements AutoCloseable {
+
+ @Override
+ public void close() {
+ final LogContextConfigurationImpl configuration = LogContextConfigurationImpl.this;
+ // Remove all the loggers first
+ for (String name : configuration.getLoggerNames()) {
+ configuration.removeLoggerConfiguration(name);
+ }
+
+ // Remove all handlers next
+ for (String name : configuration.getHandlerNames()) {
+ configuration.removeHandlerConfiguration(name);
+ }
+
+ // Remove all filters
+ for (String name : configuration.getFilterNames()) {
+ configuration.removeFilterConfiguration(name);
+ }
+
+ // Remove all formatters
+ for (String name : configuration.getFormatterNames()) {
+ configuration.removeFormatterConfiguration(name);
+ }
+
+ // Remove all error managers
+ for (String name : configuration.getErrorManagerNames()) {
+ configuration.removeErrorManagerConfiguration(name);
+ }
+
+ // Finally remove all POJO's
+ for (String name : configuration.getPojoNames()) {
+ configuration.removePojoConfiguration(name);
+ }
+
+ configuration.commit();
+ }
+ }
}
=====================================
src/main/java/org/jboss/logmanager/formatters/Formatters.java
=====================================
--- a/src/main/java/org/jboss/logmanager/formatters/Formatters.java
+++ b/src/main/java/org/jboss/logmanager/formatters/Formatters.java
@@ -34,6 +34,7 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
+import java.util.TreeMap;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
@@ -1073,9 +1074,13 @@ public final class Formatters {
public static FormatStep mdcFormatStep(final String key, final boolean leftJustify, final int minimumWidth, final boolean truncateBeginning, final int maximumWidth) {
return new JustifyingFormatStep(leftJustify, minimumWidth, truncateBeginning, maximumWidth) {
public void renderRaw(final StringBuilder builder, final ExtLogRecord record) {
- final String value = record.getMdc(key);
- if (value != null) {
- builder.append(value);
+ if (key == null) {
+ builder.append(new TreeMap<>(record.getMdcCopy()));
+ } else {
+ final String value = record.getMdc(key);
+ if (value != null) {
+ builder.append(value);
+ }
}
}
};
=====================================
src/main/java/org/jboss/logmanager/handlers/ClientSocketFactory.java
=====================================
--- /dev/null
+++ b/src/main/java/org/jboss/logmanager/handlers/ClientSocketFactory.java
@@ -0,0 +1,134 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ *
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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.jboss.logmanager.handlers;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import javax.net.SocketFactory;
+
+/**
+ * A factory used to create writable sockets.
+ *
+ * @author <a href="mailto:jperkins at redhat.com">James R. Perkins</a>
+ */
+public interface ClientSocketFactory {
+
+ /**
+ * Creates a datagram socket for UDP communication.
+ *
+ * @return the newly created socket
+ *
+ * @throws SocketException if binding the socket fails
+ */
+ DatagramSocket createDatagramSocket() throws SocketException;
+
+ /**
+ * Creates a TCP socket.
+ *
+ * @return the newly created socket
+ *
+ * @throws IOException if an error occurs creating the socket
+ */
+ Socket createSocket() throws IOException;
+
+ /**
+ * Returns the address being used to create sockets.
+ *
+ * @return the address being used
+ */
+ InetAddress getAddress();
+
+ /**
+ * Returns the port being used to create sockets.
+ *
+ * @return the port being used
+ */
+ int getPort();
+
+ /**
+ * A convenience method to return the socket address.
+ * <p>
+ * The default implementation simply returns {@code new InetSocketAddress(getAddress(), getPort())}.
+ * </p>
+ *
+ * @return a socket address
+ */
+ default SocketAddress getSocketAddress() {
+ return new InetSocketAddress(getAddress(), getPort());
+ }
+
+ /**
+ * Creates a new default implementation of the factory which uses {@link SocketFactory#getDefault()} for TCP
+ * sockets and {@code new DatagramSocket()} for UDP sockets.
+ *
+ * @param address the address to bind to
+ * @param port the port to bind to
+ *
+ * @return the client socket factory
+ */
+ static ClientSocketFactory of(final InetAddress address, final int port) {
+ return of(SocketFactory.getDefault(), address, port);
+ }
+
+ /**
+ * Creates a new default implementation of the factory which uses the provided
+ * {@linkplain SocketFactory#createSocket(InetAddress, int) socket factory} to create TCP connections and
+ * {@code new DatagramSocket()} for UDP sockets.
+ *
+ * @param socketFactory the socket factory used for TCP connections, if {@code null} the
+ * {@linkplain SocketFactory#getDefault() default} socket factory will be used
+ * @param address the address to bind to
+ * @param port the port to bind to
+ *
+ * @return the client socket factory
+ */
+ static ClientSocketFactory of(final SocketFactory socketFactory, final InetAddress address, final int port) {
+ if (address == null || port < 0) {
+ throw new IllegalArgumentException(String.format("The address cannot be null (%s) and the port must be a positive integer (%d)", address, port));
+ }
+ final SocketFactory factory = (socketFactory == null ? SocketFactory.getDefault() : socketFactory);
+ return new ClientSocketFactory() {
+ @Override
+ public DatagramSocket createDatagramSocket() throws SocketException {
+ return new DatagramSocket();
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ return factory.createSocket(address, port);
+ }
+
+ @Override
+ public InetAddress getAddress() {
+ return address;
+ }
+
+ @Override
+ public int getPort() {
+ return port;
+ }
+ };
+ }
+}
=====================================
src/main/java/org/jboss/logmanager/handlers/SocketHandler.java
=====================================
--- a/src/main/java/org/jboss/logmanager/handlers/SocketHandler.java
+++ b/src/main/java/org/jboss/logmanager/handlers/SocketHandler.java
@@ -68,6 +68,7 @@ public class SocketHandler extends ExtHandler {
private final Object outputLock = new Object();
// All the following fields are guarded by outputLock
+ private ClientSocketFactory clientSocketFactory;
private SocketFactory socketFactory;
private InetAddress address;
private int port;
@@ -143,6 +144,7 @@ public class SocketHandler extends ExtHandler {
* @param port the port to connect to
*
* @throws UnknownHostException if an error occurs resolving the hostname
+ * @see #SocketHandler(ClientSocketFactory, Protocol)
*/
public SocketHandler(final SocketFactory socketFactory, final Protocol protocol, final String hostname, final int port) throws UnknownHostException {
this(socketFactory, protocol, InetAddress.getByName(hostname), port);
@@ -157,14 +159,35 @@ public class SocketHandler extends ExtHandler {
* @param protocol the protocol to connect with
* @param address the address to connect to
* @param port the port to connect to
+ *
+ * @see #SocketHandler(ClientSocketFactory, Protocol)
*/
public SocketHandler(final SocketFactory socketFactory, final Protocol protocol, final InetAddress address, final int port) {
+ this.socketFactory = socketFactory;
+ this.clientSocketFactory = null;
this.address = address;
this.port = port;
- this.protocol = protocol;
+ this.protocol = (protocol == null ? Protocol.TCP : protocol);
+ initialize = true;
+ writer = null;
+ blockOnReconnect = false;
+ }
+
+ /**
+ * Creates a socket handler.
+ *
+ * @param clientSocketFactory the client socket factory used to create sockets
+ * @param protocol the protocol to connect with
+ */
+ public SocketHandler(final ClientSocketFactory clientSocketFactory, final Protocol protocol) {
+ this.clientSocketFactory = clientSocketFactory;
+ if (clientSocketFactory != null) {
+ address = clientSocketFactory.getAddress();
+ port = clientSocketFactory.getPort();
+ }
+ this.protocol = (protocol == null ? Protocol.TCP : protocol);
initialize = true;
writer = null;
- this.socketFactory = socketFactory;
blockOnReconnect = false;
}
@@ -229,19 +252,28 @@ public class SocketHandler extends ExtHandler {
/**
* Sets the address to connect to.
+ * <p>
+ * Note that is resets the {@linkplain #setClientSocketFactory(ClientSocketFactory) client socket factory}.
+ * </p>
*
* @param address the address
*/
public void setAddress(final InetAddress address) {
checkAccess(this);
synchronized (outputLock) {
+ if (!this.address.equals(address)) {
+ initialize = true;
+ clientSocketFactory = null;
+ }
this.address = address;
- initialize = true;
}
}
/**
* Sets the address to connect to by doing a lookup on the hostname.
+ * <p>
+ * Note that is resets the {@linkplain #setClientSocketFactory(ClientSocketFactory) client socket factory}.
+ * </p>
*
* @param hostname the host name used to resolve the address
*
@@ -277,6 +309,7 @@ public class SocketHandler extends ExtHandler {
checkAccess(this);
synchronized (outputLock) {
this.blockOnReconnect = blockOnReconnect;
+ initialize = true;
}
}
@@ -293,7 +326,7 @@ public class SocketHandler extends ExtHandler {
* Sets the protocol to use. If the value is {@code null} the protocol will be set to
* {@linkplain Protocol#TCP TCP}.
* <p>
- * Note that is resets the {@linkplain #setSocketFactory(SocketFactory) socket factory}.
+ * Note that is resets the {@linkplain #setSocketFactory(SocketFactory) socket factory} if it was previously set.
* </p>
*
* @param protocol the protocol to use
@@ -304,10 +337,11 @@ public class SocketHandler extends ExtHandler {
if (protocol == null) {
this.protocol = Protocol.TCP;
}
- // Reset the socket factory
- socketFactory = null;
+ if (this.protocol != protocol) {
+ socketFactory = null;
+ initialize = true;
+ }
this.protocol = protocol;
- initialize = true;
}
}
@@ -322,14 +356,20 @@ public class SocketHandler extends ExtHandler {
/**
* Sets the port to connect to.
+ * <p>
+ * Note that is resets the {@linkplain #setClientSocketFactory(ClientSocketFactory) client socket factory}.
+ * </p>
*
* @param port the port
*/
public void setPort(final int port) {
checkAccess(this);
synchronized (outputLock) {
+ if (this.port != port) {
+ initialize = true;
+ clientSocketFactory = null;
+ }
this.port = port;
- initialize = true;
}
}
@@ -338,15 +378,33 @@ public class SocketHandler extends ExtHandler {
* connections.
* <p>
* Note that if the {@linkplain #setProtocol(Protocol) protocol} is set the socket factory will be set to
- * {@code null} and reset.
+ * {@code null} and reset. Setting a value here also resets the
+ * {@linkplain #setClientSocketFactory(ClientSocketFactory) client socket factory}.
* </p>
*
* @param socketFactory the socket factory
+ *
+ * @see #setClientSocketFactory(ClientSocketFactory)
*/
public void setSocketFactory(final SocketFactory socketFactory) {
checkAccess(this);
synchronized (outputLock) {
this.socketFactory = socketFactory;
+ this.clientSocketFactory = null;
+ initialize = true;
+ }
+ }
+
+ /**
+ * Sets the client socket factory used to create sockets. If {@code null} the
+ * {@linkplain #setAddress(InetAddress) address} and {@linkplain #setPort(int) port} are required to be set.
+ *
+ * @param clientSocketFactory the client socket factory to use
+ */
+ public void setClientSocketFactory(final ClientSocketFactory clientSocketFactory) {
+ checkAccess(this);
+ synchronized (outputLock) {
+ this.clientSocketFactory = clientSocketFactory;
initialize = true;
}
}
@@ -388,19 +446,11 @@ public class SocketHandler extends ExtHandler {
private OutputStream createOutputStream() {
if (address != null || port >= 0) {
try {
+ final ClientSocketFactory socketFactory = getClientSocketFactory();
if (protocol == Protocol.UDP) {
- return new UdpOutputStream(address, port);
- }
- 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 UdpOutputStream(socketFactory);
}
- return new TcpOutputStream(socketFactory, address, port, blockOnReconnect);
+ return new TcpOutputStream(socketFactory, blockOnReconnect);
} catch (IOException e) {
reportError("Failed to create socket output stream", e, ErrorManager.OPEN_FAILURE);
}
@@ -408,6 +458,28 @@ public class SocketHandler extends ExtHandler {
return null;
}
+ private ClientSocketFactory getClientSocketFactory() {
+ synchronized (outputLock) {
+ if (clientSocketFactory != null) {
+ return clientSocketFactory;
+ }
+ if (address == null || port <= 0) {
+ throw new IllegalStateException("An address and port greater than 0 is required.");
+ }
+ final ClientSocketFactory clientSocketFactory;
+ if (socketFactory == null) {
+ if (protocol == Protocol.SSL_TCP) {
+ clientSocketFactory = ClientSocketFactory.of(SSLSocketFactory.getDefault(), address, port);
+ } else {
+ clientSocketFactory = ClientSocketFactory.of(address, port);
+ }
+ } else {
+ clientSocketFactory = ClientSocketFactory.of(socketFactory, address, port);
+ }
+ return clientSocketFactory;
+ }
+ }
+
private void writeHead(final Writer writer) {
try {
final Formatter formatter = getFormatter();
=====================================
src/main/java/org/jboss/logmanager/handlers/SyslogHandler.java
=====================================
--- a/src/main/java/org/jboss/logmanager/handlers/SyslogHandler.java
+++ b/src/main/java/org/jboss/logmanager/handlers/SyslogHandler.java
@@ -35,6 +35,8 @@ import java.util.logging.ErrorManager;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.regex.Pattern;
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLSocketFactory;
import org.jboss.logmanager.ExtHandler;
import org.jboss.logmanager.ExtLogRecord;
@@ -324,6 +326,7 @@ public class SyslogHandler extends ExtHandler {
private boolean truncate;
private int maxLen;
private boolean blockOnReconnect;
+ private ClientSocketFactory clientSocketFactory;
/**
* The default class constructor.
@@ -668,6 +671,19 @@ public class SyslogHandler extends ExtHandler {
}
/**
+ * Sets the client socket factory used to create sockets.
+ *
+ * @param clientSocketFactory the client socket factory to use
+ */
+ public void setClientSocketFactory(final ClientSocketFactory clientSocketFactory) {
+ checkAccess(this);
+ synchronized (outputLock) {
+ this.clientSocketFactory = clientSocketFactory;
+ initializeConnection = true;
+ }
+ }
+
+ /**
* Checks whether or not characters below decimal 32, traditional US-ASCII control values expect {@code DEL}, are
* being escaped or not.
*
@@ -1084,14 +1100,11 @@ public class SyslogHandler extends ExtHandler {
final OutputStream out;
// Check the sockets
try {
- if (protocol == Protocol.TCP) {
- out = new TcpOutputStream(serverAddress, port, blockOnReconnect);
- } else if (protocol == Protocol.UDP) {
- out = new UdpOutputStream(serverAddress, port);
- } else if (protocol == Protocol.SSL_TCP) {
- out = new SslTcpOutputStream(serverAddress, port, blockOnReconnect);
+ final ClientSocketFactory clientSocketFactory = getClientSocketFactory();
+ if (protocol == Protocol.UDP) {
+ out = new UdpOutputStream(clientSocketFactory);
} else {
- throw new IllegalStateException("Invalid protocol: " + protocol);
+ out = new TcpOutputStream(clientSocketFactory, blockOnReconnect);
}
setOutputStream(out, false);
} catch (IOException e) {
@@ -1296,6 +1309,16 @@ public class SyslogHandler extends ExtHandler {
return buffer.toArray();
}
+ private ClientSocketFactory getClientSocketFactory() {
+ synchronized (outputLock) {
+ if (clientSocketFactory != null) {
+ return clientSocketFactory;
+ }
+ final SocketFactory socketFactory = (protocol == Protocol.SSL_TCP ? SSLSocketFactory.getDefault() : SocketFactory.getDefault());
+ return ClientSocketFactory.of(socketFactory, serverAddress, port);
+ }
+ }
+
private static String checkPrintableAscii(final String name, final String value) {
if (value != null && PRINTABLE_ASCII_PATTERN.matcher(value).find()) {
final String upper = Character.toUpperCase(name.charAt(0)) + name.substring(1);
=====================================
src/main/java/org/jboss/logmanager/handlers/TcpOutputStream.java
=====================================
--- a/src/main/java/org/jboss/logmanager/handlers/TcpOutputStream.java
+++ b/src/main/java/org/jboss/logmanager/handlers/TcpOutputStream.java
@@ -54,9 +54,7 @@ public class TcpOutputStream extends OutputStream implements FlushableCloseable
protected final Object outputLock = new Object();
- private final SocketFactory socketFactory;
- private final InetAddress address;
- private final int port;
+ private final ClientSocketFactory socketFactory;
private final Deque<Exception> errors = new ArrayDeque<Exception>(maxErrors);
// Guarded by outputLock
@@ -108,13 +106,11 @@ public class TcpOutputStream extends OutputStream implements FlushableCloseable
*
* @param socket the socket used to write the output to
*
- * @deprecated Use {@link #TcpOutputStream(javax.net.SocketFactory, java.net.InetAddress, int)}
+ * @deprecated Use {@link #TcpOutputStream(ClientSocketFactory, boolean)}
*/
@Deprecated
protected TcpOutputStream(final Socket socket) {
this.socketFactory = null;
- this.address = null;
- this.port = -1;
this.socket = socket;
reconnectThread = null;
connected = true;
@@ -152,12 +148,21 @@ public class TcpOutputStream extends OutputStream implements FlushableCloseable
* a reconnect will be attempted on the next write.
*/
protected TcpOutputStream(final SocketFactory socketFactory, final InetAddress address, final int port, final boolean blockOnReconnect) throws IOException {
+ this(ClientSocketFactory.of(socketFactory, address, port), blockOnReconnect);
+ }
+
+ /**
+ * Creates a new TCP stream which uses the {@link ClientSocketFactory#createSocket()} to create the socket.
+ *
+ * @param socketFactory the socket factory used to create TCP sockets
+ * @param blockOnReconnect {@code true} to block when attempting to reconnect the socket or {@code false} to
+ * reconnect asynchronously
+ */
+ public TcpOutputStream(final ClientSocketFactory socketFactory, final boolean blockOnReconnect) {
this.socketFactory = socketFactory;
- this.address = address;
- this.port = port;
this.blockOnReconnect = blockOnReconnect;
try {
- socket = socketFactory.createSocket(address, port);
+ socket = this.socketFactory.createSocket();
connected = true;
} catch (IOException e) {
connected = false;
@@ -166,7 +171,7 @@ public class TcpOutputStream extends OutputStream implements FlushableCloseable
@Override
public void write(final int b) throws IOException {
- write(new byte[]{(byte) b}, 0, 1);
+ write(new byte[] {(byte) b}, 0, 1);
}
@Override
@@ -208,7 +213,9 @@ public class TcpOutputStream extends OutputStream implements FlushableCloseable
public void flush() throws IOException {
synchronized (outputLock) {
try {
- socket.getOutputStream().flush();
+ if (socket != null) {
+ socket.getOutputStream().flush();
+ }
} catch (SocketException e) {
// This should likely never be hit, but should attempt to reconnect if it does happen
if (isReconnectAllowed()) {
@@ -230,7 +237,9 @@ public class TcpOutputStream extends OutputStream implements FlushableCloseable
if (reconnectThread != null) {
reconnectThread.interrupt();
}
- socket.close();
+ if (socket != null) {
+ socket.close();
+ }
}
}
@@ -345,7 +354,7 @@ public class TcpOutputStream extends OutputStream implements FlushableCloseable
while (socketFactory != null && !connected) {
Socket socket = null;
try {
- socket = socketFactory.createSocket(address, port);
+ socket = socketFactory.createSocket();
synchronized (outputLock) {
// Unlikely but if we've been interrupted due to a close, we should shutdown
if (Thread.currentThread().isInterrupted()) {
=====================================
src/main/java/org/jboss/logmanager/handlers/UdpOutputStream.java
=====================================
--- a/src/main/java/org/jboss/logmanager/handlers/UdpOutputStream.java
+++ b/src/main/java/org/jboss/logmanager/handlers/UdpOutputStream.java
@@ -24,31 +24,39 @@ import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
/**
* An output stream that writes data to a {@link java.net.DatagramSocket DatagramSocket}.
*
* @author <a href="mailto:jperkins at redhat.com">James R. Perkins</a>
*/
+ at SuppressWarnings("WeakerAccess")
public class UdpOutputStream extends OutputStream implements FlushableCloseable {
private final DatagramSocket socket;
+ private final SocketAddress socketAddress;
public UdpOutputStream(final InetAddress address, final int port) throws IOException {
- socket = new DatagramSocket();
- socket.connect(address, port);
+ this(ClientSocketFactory.of(address, port));
+ }
+
+ public UdpOutputStream(final ClientSocketFactory socketManager) throws SocketException {
+ socket = socketManager.createDatagramSocket();
+ socketAddress = socketManager.getSocketAddress();
}
@Override
public void write(final int b) throws IOException {
final byte[] msg = new byte[] {(byte) b};
- final DatagramPacket packet = new DatagramPacket(msg, 1);
+ final DatagramPacket packet = new DatagramPacket(msg, 1, socketAddress);
socket.send(packet);
}
@Override
public void write(final byte[] b) throws IOException {
if (b != null) {
- final DatagramPacket packet = new DatagramPacket(b, b.length);
+ final DatagramPacket packet = new DatagramPacket(b, b.length, socketAddress);
socket.send(packet);
}
}
@@ -56,7 +64,7 @@ public class UdpOutputStream extends OutputStream implements FlushableCloseable
@Override
public void write(final byte[] b, final int off, final int len) throws IOException {
if (b != null) {
- final DatagramPacket packet = new DatagramPacket(b, off, len);
+ final DatagramPacket packet = new DatagramPacket(b, off, len, socketAddress);
socket.send(packet);
}
}
=====================================
src/test/java/org/jboss/logmanager/LogContextCloseTests.java
=====================================
--- /dev/null
+++ b/src/test/java/org/jboss/logmanager/LogContextCloseTests.java
@@ -0,0 +1,396 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ *
+ * Copyright 2017 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed 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.jboss.logmanager;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.UUID;
+import java.util.logging.ErrorManager;
+import java.util.logging.Filter;
+import java.util.logging.Formatter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import org.jboss.logmanager.config.ErrorManagerConfiguration;
+import org.jboss.logmanager.config.FilterConfiguration;
+import org.jboss.logmanager.config.FormatterConfiguration;
+import org.jboss.logmanager.config.HandlerConfiguration;
+import org.jboss.logmanager.config.LogContextConfiguration;
+import org.jboss.logmanager.config.LoggerConfiguration;
+import org.jboss.logmanager.config.PojoConfiguration;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author <a href="mailto:jperkins at redhat.com">James R. Perkins</a>
+ */
+public class LogContextCloseTests {
+
+ @Before
+ public void resetTestObjects() {
+ TestErrorManager.POJO_OBJECT = null;
+ TestFilter.POJO_OBJECT = null;
+ TestFormatter.POJO_OBJECT = null;
+ TestHandler.ERROR_MANAGER = null;
+ TestHandler.FILTER = null;
+ TestHandler.FORMATTER = null;
+ TestHandler.HANDLERS = null;
+ TestHandler.IS_CLOSED = false;
+ TestHandler.POJO_OBJECT = null;
+ }
+
+
+ @Test
+ public void testCloseLogContext() throws Exception {
+ LogContext logContext = LogContext.create();
+
+ // Create a test handler to use
+ final TestHandler handler = new TestHandler();
+ handler.setErrorManager(new TestErrorManager());
+ handler.setFilter(new TestFilter());
+ handler.setFormatter(new TestFormatter());
+ handler.setLevel(org.jboss.logmanager.Level.TRACE);
+
+ final Logger rootLogger = logContext.getLogger("");
+ rootLogger.setLevel(org.jboss.logmanager.Level.WARN);
+ final Logger testLogger = logContext.getLogger(LogContextCloseTests.class.getName());
+ testLogger.setLevel(Level.FINE);
+ final Logger randomLogger = logContext.getLogger(UUID.randomUUID().toString());
+ randomLogger.setUseParentFilters(true);
+
+ rootLogger.addHandler(handler);
+
+ logContext.close();
+
+ // Loggers should have no handlers and have been reset
+ Assert.assertEquals(Level.INFO, rootLogger.getLevel());
+ final Handler[] handlers = randomLogger.getHandlers();
+ Assert.assertTrue(handlers == null || handlers.length == 0);
+
+ assertEmptyContext(logContext, rootLogger, testLogger, randomLogger);
+ }
+
+ @Test
+ public void testCloseLogContextConfiguration() throws Exception {
+ final LogContext logContext = LogContext.create();
+ final LogContextConfiguration logContextConfiguration = LogContextConfiguration.Factory.create(logContext);
+
+ // Add a POJO to ensure it gets removed
+ final PojoConfiguration pojoConfiguration = logContextConfiguration.addPojoConfiguration(null,
+ PojoObject.class.getName(), "pojo");
+
+ // Create an error manager
+ final ErrorManagerConfiguration errorManagerConfiguration = logContextConfiguration.addErrorManagerConfiguration(null,
+ TestErrorManager.class.getName(), "error-manager");
+ errorManagerConfiguration.setPropertyValueString("pojoObject", pojoConfiguration.getName());
+
+ // Create a filter
+ final FilterConfiguration filterConfiguration = logContextConfiguration.addFilterConfiguration(null,
+ TestFilter.class.getName(), "filter");
+ filterConfiguration.setPropertyValueString("pojoObject", pojoConfiguration.getName());
+
+ // Create a formatter
+ final FormatterConfiguration formatterConfiguration = logContextConfiguration.addFormatterConfiguration(null,
+ TestFormatter.class.getName(), "formatter");
+ formatterConfiguration.setPropertyValueString("pojoObject", pojoConfiguration.getName());
+
+ // Create a handler
+ final HandlerConfiguration handlerConfiguration = logContextConfiguration.addHandlerConfiguration(null,
+ TestHandler.class.getName(), "handler");
+ handlerConfiguration.setPropertyValueString("pojoObject", pojoConfiguration.getName());
+ handlerConfiguration.setFilter(filterConfiguration.getName());
+ handlerConfiguration.setErrorManagerName(errorManagerConfiguration.getName());
+ handlerConfiguration.setFormatterName(formatterConfiguration.getName());
+
+ // Create the root-logger configuration
+ final LoggerConfiguration rootLoggerConfig = logContextConfiguration.addLoggerConfiguration("");
+ rootLoggerConfig.setFilter(filterConfiguration.getName());
+ rootLoggerConfig.addHandlerName(handlerConfiguration.getName());
+ rootLoggerConfig.setLevel("WARN");
+
+ final LoggerConfiguration testLoggerConfig = logContextConfiguration.addLoggerConfiguration(LogContextCloseTests.class.getName());
+ testLoggerConfig.setLevel("DEBUG");
+ testLoggerConfig.addHandlerName(handlerConfiguration.getName());
+
+ final LoggerConfiguration randomLoggerConfig = logContextConfiguration.addLoggerConfiguration(UUID.randomUUID().toString());
+ randomLoggerConfig.setLevel("ERROR");
+ randomLoggerConfig.setUseParentHandlers(false);
+
+
+ logContextConfiguration.commit();
+
+ // Create the loggers on the log context to test they've been reset, note this is required to be done before
+ // the context is closed, but after a commit
+ final Logger rootLogger = logContext.getLogger(rootLoggerConfig.getName());
+ final Logger testLogger = logContext.getLogger(testLoggerConfig.getName());
+ final Logger randomLogger = logContext.getLogger(randomLoggerConfig.getName());
+
+ logContext.close();
+
+ assertEmptyNames("error manager", logContextConfiguration.getErrorManagerNames());
+ assertEmptyNames("filter", logContextConfiguration.getFilterNames());
+ assertEmptyNames("formatter", logContextConfiguration.getFormatterNames());
+ assertEmptyNames("handler", logContextConfiguration.getHandlerNames());
+ assertEmptyNames("logger", logContextConfiguration.getLoggerNames());
+ assertEmptyNames("POJO", logContextConfiguration.getPojoNames());
+
+ assertEmptyContext(logContext, rootLogger, testLogger, randomLogger);
+ // The handler is really the only object available for context since it has a close on it
+ Assert.assertNull("Expected the handler to be reset.", TestHandler.FORMATTER);
+
+ // Assert the handler itself has been closed
+ Assert.assertTrue("The handler was expected to be closed", TestHandler.IS_CLOSED);
+ }
+
+ @Test
+ public void testCloseWithAttachment() throws Exception {
+ LogContext logContext = LogContext.create();
+ final Logger.AttachmentKey<String> key = new Logger.AttachmentKey<>();
+ final String value = "test value";
+ Logger rootLogger = logContext.getLogger("");
+ Assert.assertNull(rootLogger.attach(key, value));
+
+ // Close and ensure the context is clean
+ logContext.close();
+ Assert.assertNull(rootLogger.getAttachment(key));
+ assertEmptyContext(logContext, rootLogger);
+
+ // Test attachIfAbsent()
+ logContext = LogContext.create();
+ rootLogger = logContext.getLogger("");
+ Assert.assertNull(rootLogger.attachIfAbsent(key, value));
+
+ // Close and ensure the context is clean
+ logContext.close();
+ Assert.assertNull(rootLogger.getAttachment(key));
+ assertEmptyContext(logContext, rootLogger);
+
+ // Test detach()
+ logContext = LogContext.create();
+ rootLogger = logContext.getLogger("");
+ Assert.assertNull(rootLogger.attach(key, value));
+ Assert.assertEquals(value, rootLogger.detach(key));
+ logContext.close();
+ Assert.assertNull(rootLogger.getAttachment(key));
+ assertEmptyContext(logContext, rootLogger);
+ }
+
+ private void assertEmptyContext(final LogContext logContext, final Logger... loggers) {
+ // Inspect the log context and ensure it's "empty"
+ final LoggerNode rootLogger = logContext.getRootLoggerNode();
+ final Handler[] handlers = rootLogger.getHandlers();
+ Assert.assertTrue("Expected the handlers to be removed.", handlers == null || handlers.length == 0);
+ Assert.assertNull("Expected the filter to be null", rootLogger.getFilter());
+ Assert.assertEquals("Expected the level to be INFO for logger the root logger", Level.INFO, rootLogger.getLevel());
+ Assert.assertFalse("Expected the useParentFilters to be false for the root logger", rootLogger.getUseParentFilters());
+ Assert.assertTrue("Expected the useParentHandlers to be true for the root logger", rootLogger.getUseParentHandlers());
+ final Collection<LoggerNode> children = rootLogger.getChildren();
+ if (!children.isEmpty()) {
+ final StringBuilder msg = new StringBuilder("Expected no children to be remaining on the root logger. Remaining loggers: ");
+ final Iterator<LoggerNode> iter = children.iterator();
+ while (iter.hasNext()) {
+ msg.append('\'').append(iter.next().getFullName()).append('\'');
+ if (iter.hasNext()) {
+ msg.append(", ");
+ }
+ }
+ Assert.fail(msg.toString());
+ }
+
+ for (Logger logger : loggers) {
+ assertLoggerReset(logger);
+ }
+ }
+
+ private void assertLoggerReset(final Logger logger) {
+ String loggerName = logger.getName();
+ final Level expectedLevel;
+ if ("".equals(loggerName)) {
+ loggerName = "root";
+ expectedLevel = Level.INFO;
+ } else {
+ expectedLevel = null;
+ }
+ final Handler[] handlers = logger.getHandlers();
+ Assert.assertNull("Expected the filter to be null for logger " + loggerName, logger.getFilter());
+ Assert.assertTrue("Empty handlers expected for logger " + loggerName, handlers == null || handlers.length == 0);
+ Assert.assertEquals("Expected the level to be " + expectedLevel + " for logger " + loggerName, expectedLevel, logger.getLevel());
+ Assert.assertFalse("Expected the useParentFilters to be false for logger " + loggerName, logger.getUseParentFilters());
+ Assert.assertTrue("Expected the useParentHandlers to be true for logger " + loggerName, logger.getUseParentHandlers());
+ }
+
+ private void assertEmptyNames(final String description, final Collection<String> names) {
+ Assert.assertTrue(String.format("The configuration should not have any %s names, but found: %s", description, names),
+ names.isEmpty());
+ }
+
+
+ @SuppressWarnings("unused")
+ public static class TestFilter implements Filter {
+ private static PojoObject POJO_OBJECT;
+
+ @Override
+ public boolean isLoggable(final LogRecord record) {
+ return true;
+ }
+
+ public void setPojoObject(final PojoObject pojoObject) {
+ POJO_OBJECT = pojoObject;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public static class TestFormatter extends Formatter {
+ private static PojoObject POJO_OBJECT;
+
+ public void setPojoObject(final PojoObject pojoObject) {
+ POJO_OBJECT = pojoObject;
+ }
+
+ @Override
+ public String format(final LogRecord record) {
+ return ExtLogRecord.wrap(record).getFormattedMessage();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public static class TestErrorManager extends ErrorManager {
+ private static PojoObject POJO_OBJECT;
+
+ public void setPojoObject(final PojoObject pojoObject) {
+ POJO_OBJECT = pojoObject;
+ }
+ }
+
+ @SuppressWarnings({"unused", "WeakerAccess"})
+ public static class TestHandler extends ExtHandler {
+ private static PojoObject POJO_OBJECT;
+ private static Handler[] HANDLERS;
+ private static Formatter FORMATTER;
+ private static Filter FILTER;
+ private static ErrorManager ERROR_MANAGER;
+ private static boolean IS_CLOSED;
+
+ public TestHandler() {
+ IS_CLOSED = false;
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ // Null out static values
+ POJO_OBJECT = null;
+ FORMATTER = null;
+ HANDLERS = null;
+ FORMATTER = null;
+ FILTER = null;
+ ERROR_MANAGER = null;
+ IS_CLOSED = true;
+ super.close();
+ }
+
+ @Override
+ public Handler[] setHandlers(final Handler[] newHandlers) throws SecurityException {
+ HANDLERS = Arrays.copyOf(newHandlers, newHandlers.length);
+ return super.setHandlers(newHandlers);
+ }
+
+ @Override
+ public void addHandler(final Handler handler) throws SecurityException {
+ if (handler == null) {
+ throw new RuntimeException("Cannot add a null handler");
+ }
+ if (HANDLERS == null) {
+ HANDLERS = new Handler[] {handler};
+ } else {
+ final int len = HANDLERS.length + 1;
+ HANDLERS = Arrays.copyOf(HANDLERS, len);
+ HANDLERS[len - 1] = handler;
+ }
+ super.addHandler(handler);
+ }
+
+ @Override
+ public void removeHandler(final Handler handler) throws SecurityException {
+ if (handler == null) {
+ throw new RuntimeException("Cannot remove a null handler");
+ }
+ if (HANDLERS == null) {
+ throw new RuntimeException("Attempting to remove a handler that does not exist: " + handler);
+ } else {
+ if (HANDLERS.length == 1) {
+ HANDLERS = null;
+ } else {
+ boolean success = false;
+ final Handler[] newHandlers = new Handler[HANDLERS.length - 1];
+ int newIndex = 0;
+ for (int i = 0; i < HANDLERS.length; i++) {
+ final Handler current = HANDLERS[i];
+ if (!success && i > newHandlers.length) {
+ break;
+ }
+ if (handler != current) {
+ newHandlers[newIndex++] = current;
+ } else {
+ success = true;
+ }
+ }
+ if (!success) {
+ throw new RuntimeException("Failed to remove handler " + handler + " as it did no appear to exist.");
+ }
+ }
+ }
+ super.removeHandler(handler);
+ }
+
+ @Override
+ public void setFormatter(final Formatter newFormatter) throws SecurityException {
+ FORMATTER = newFormatter;
+ super.setFormatter(newFormatter);
+ }
+
+ @Override
+ public void setFilter(final Filter newFilter) throws SecurityException {
+ FILTER = newFilter;
+ super.setFilter(newFilter);
+ }
+
+ @Override
+ public void setErrorManager(final ErrorManager em) {
+ ERROR_MANAGER = em;
+ super.setErrorManager(em);
+ }
+
+ @Override
+ public void setLevel(final Level newLevel) throws SecurityException {
+ super.setLevel(newLevel);
+ }
+
+ public void setPojoObject(final PojoObject pojoObject) {
+ POJO_OBJECT = pojoObject;
+ }
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ public static class PojoObject {
+ }
+}
=====================================
src/test/java/org/jboss/logmanager/formatters/PatternFormatterTests.java
=====================================
--- a/src/test/java/org/jboss/logmanager/formatters/PatternFormatterTests.java
+++ b/src/test/java/org/jboss/logmanager/formatters/PatternFormatterTests.java
@@ -20,6 +20,7 @@
package org.jboss.logmanager.formatters;
import org.jboss.logmanager.ExtLogRecord;
+import org.jboss.logmanager.MDC;
import org.jboss.logmanager.NDC;
import org.junit.Assert;
import org.junit.Test;
@@ -114,6 +115,28 @@ public class PatternFormatterTests {
}
@Test
+ public void mdc() throws Exception {
+ try {
+ MDC.put("primaryKey", "primaryValue");
+ MDC.put("key1", "value1");
+ MDC.put("key2", "value2");
+ final ExtLogRecord record = createLogRecord("test");
+
+ PatternFormatter formatter = new PatternFormatter("%X{key1}");
+ Assert.assertEquals("value1", formatter.format(record));
+
+ formatter = new PatternFormatter("%X{not.found}");
+ Assert.assertEquals("", formatter.format(record));
+
+ formatter = new PatternFormatter("%X");
+ String formatted = formatter.format(record);
+ Assert.assertEquals("{key1=value1, key2=value2, primaryKey=primaryValue}", formatted);
+ } finally {
+ MDC.clear();
+ }
+ }
+
+ @Test
public void threads() throws Exception {
final ExtLogRecord record = createLogRecord("test");
record.setThreadName("testThreadName");
=====================================
src/test/java/org/jboss/logmanager/handlers/PeriodicRotatingFileHandlerTests.java
=====================================
--- a/src/test/java/org/jboss/logmanager/handlers/PeriodicRotatingFileHandlerTests.java
+++ b/src/test/java/org/jboss/logmanager/handlers/PeriodicRotatingFileHandlerTests.java
@@ -100,7 +100,7 @@ public class PeriodicRotatingFileHandlerTests extends AbstractHandlerTest {
targetClass = "java.nio.file.Files",
targetMethod = "move",
targetLocation = "AT ENTRY",
- condition = "$2.getFileName().toString().matches(\"periodic-rotating-file-handler\\.log\\.\\d+\")",
+ condition = "$2.getFileName().toString().matches(\"periodic-rotating-file-handler\\\\.log\\\\.\\\\d+\")",
action = "throw new IOException(\"Fail on purpose\")")
public void testFailedRotate() throws Exception {
final Calendar cal = Calendar.getInstance();
View it on GitLab: https://salsa.debian.org/java-team/jboss-logmanager/compare/0ca3ff00484e8c3b38c577408a7e49935da307f2...2a2b20fc94dfc23410856aedeac4933ff34a02fe
--
View it on GitLab: https://salsa.debian.org/java-team/jboss-logmanager/compare/0ca3ff00484e8c3b38c577408a7e49935da307f2...2a2b20fc94dfc23410856aedeac4933ff34a02fe
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20180707/84f59835/attachment.html>
More information about the pkg-java-commits
mailing list