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 2022/01/09 21:26:15 UTC
[logging-log4j2] 01/02: Refactor 1.2 bridge internals to use a single private log manager and adapter.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit f64791b10cbcea8a8cf3ccbad924c74071f0211c
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Jan 9 16:26:07 2022 -0500
Refactor 1.2 bridge internals to use a single private log manager and
adapter.
- Implement LogManager.getCurrentLoggers().
- The class loader found in the bridge and passed down instead of a
FQCN.
- Adds a package private extension to LoggerRepository called
LoggerRepository2 to allow class loader propagation.
- Core availability is computed once in LogManager.
- Move Log4j to the top of POM dependencies
- Split commit 1/2 for cherry-picking to master.
---
.../java/org/apache/log4j/BasicConfigurator.java | 14 +-
.../src/main/java/org/apache/log4j/Category.java | 176 ++++-----------
.../src/main/java/org/apache/log4j/Hierarchy.java | 133 +++++++-----
.../src/main/java/org/apache/log4j/LogManager.java | 237 ++++++++-------------
.../src/main/java/org/apache/log4j/Logger.java | 26 ++-
.../java/org/apache/log4j/LoggerRepository2.java | 31 +++
.../main/java/org/apache/log4j/spi/RootLogger.java | 3 +-
.../test/java/org/apache/log4j/CategoryTest.java | 4 +-
.../test/java/org/apache/log4j/LogManagerTest.java | 12 +-
9 files changed, 283 insertions(+), 353 deletions(-)
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/BasicConfigurator.java b/log4j-1.2-api/src/main/java/org/apache/log4j/BasicConfigurator.java
index 2b7ec7f..da90e2c 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/BasicConfigurator.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/BasicConfigurator.java
@@ -18,12 +18,11 @@ package org.apache.log4j;
/**
* Provided for compatibility with Log4j 1.x.
+ *
+ * @since 0.8.1
*/
public class BasicConfigurator {
- protected BasicConfigurator() {
- }
-
public static void configure() {
LogManager.reconfigure();
}
@@ -36,10 +35,13 @@ public class BasicConfigurator {
// no-op
}
+ public static void resetConfiguration() {
+ LogManager.resetConfiguration();
+ }
+
/**
- * No-op implementation.
+ * Constructs a new instance.
*/
- public static void resetConfiguration() {
- // no-op
+ protected BasicConfigurator() {
}
}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
index 7d0cb11..286ae32 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
@@ -19,8 +19,6 @@ package org.apache.log4j;
import java.util.Enumeration;
import java.util.Map;
import java.util.ResourceBundle;
-import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.log4j.helpers.NullEnumeration;
@@ -28,18 +26,16 @@ import org.apache.log4j.legacy.core.CategoryUtil;
import org.apache.log4j.or.ObjectRenderer;
import org.apache.log4j.or.RendererMap;
import org.apache.log4j.spi.AppenderAttachable;
-import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.spi.RendererSupport;
import org.apache.logging.log4j.message.LocalizedMessage;
import org.apache.logging.log4j.message.MapMessage;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.ObjectMessage;
import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.util.StackLocatorUtil;
import org.apache.logging.log4j.util.Strings;
/**
@@ -47,26 +43,8 @@ import org.apache.logging.log4j.util.Strings;
*/
public class Category implements AppenderAttachable {
- private static PrivateAdapter adapter = new PrivateAdapter();
-
- private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP =
- new WeakHashMap<>();
-
private static final String FQCN = Category.class.getName();
- private static final boolean isCoreAvailable;
-
- static {
- boolean available;
-
- try {
- available = Class.forName("org.apache.logging.log4j.core.Logger") != null;
- } catch (Exception ex) {
- available = false;
- }
- isCoreAvailable = available;
- }
-
/**
* The name of this category.
*/
@@ -79,14 +57,14 @@ public class Category implements AppenderAttachable {
* to <code>false</code> too. See the user manual for more details.
*/
protected boolean additive = true;
-
+
/**
* The assigned level of this category. The <code>level</code> variable need not be assigned a value in which case it is
* inherited form the hierarchy.
*/
volatile protected Level level;
- private final RendererMap rendererMap;
+ private RendererMap rendererMap;
/**
* The parent of this category. All categories have at least one ancestor which is the root category.
@@ -112,7 +90,7 @@ public class Category implements AppenderAttachable {
this.name = name;
this.logger = context.getLogger(name);
this.repository = LogManager.getLoggerRepository();
- this.rendererMap = ((RendererSupport) repository).getRendererMap();
+ //this.rendererMap = ((RendererSupport) repository).getRendererMap();
}
/**
@@ -120,50 +98,22 @@ public class Category implements AppenderAttachable {
* @param name The name of the Logger.
*/
protected Category(final String name) {
- this(PrivateManager.getContext(), name);
+ this(Hierarchy.getContext(), name);
}
- private Category(final org.apache.logging.log4j.Logger logger) {
+ Category(final org.apache.logging.log4j.Logger logger) {
this.logger = logger;
- rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
+ //rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
}
public static Category getInstance(final String name) {
- return getInstance(PrivateManager.getContext(), name, adapter);
- }
-
- static Logger getInstance(final LoggerContext context, final String name) {
- return getInstance(context, name, adapter);
- }
-
- static Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) {
- final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
- Logger logger = loggers.get(name);
- if (logger != null) {
- return logger;
- }
- logger = factory.makeNewLoggerInstance(name);
- final Logger prev = loggers.putIfAbsent(name, logger);
- return prev == null ? logger : prev;
- }
-
- static Logger getInstance(final LoggerContext context, final String name, final PrivateAdapter factory) {
- final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
- Logger logger = loggers.get(name);
- if (logger != null) {
- return logger;
- }
- logger = factory.newLogger(name, context);
- final Logger prev = loggers.putIfAbsent(name, logger);
- return prev == null ? logger : prev;
+ // Depth 2 gets the call site of this method.
+ return LogManager.getLogger(name, StackLocatorUtil.getCallerClassLoader(2));
}
public static Category getInstance(@SuppressWarnings("rawtypes") final Class clazz) {
- return getInstance(clazz.getName());
- }
-
- static Logger getInstance(final LoggerContext context, @SuppressWarnings("rawtypes") final Class clazz) {
- return getInstance(context, clazz.getName());
+ // Depth 2 gets the call site of this method.
+ return LogManager.getLogger(clazz.getName(), StackLocatorUtil.getCallerClassLoader(2));
}
public final String getName() {
@@ -175,15 +125,15 @@ public class Category implements AppenderAttachable {
}
public final Category getParent() {
- if (!isCoreAvailable) {
+ if (!LogManager.isLog4jCorePresent()) {
return null;
}
- org.apache.logging.log4j.Logger parent = CategoryUtil.getParent(logger);
- LoggerContext loggerContext = CategoryUtil.getLoggerContext(logger);
+ final org.apache.logging.log4j.Logger parent = CategoryUtil.getParent(logger);
+ final LoggerContext loggerContext = CategoryUtil.getLoggerContext(logger);
if (parent == null || loggerContext == null) {
return null;
}
- final ConcurrentMap<String, Logger> loggers = getLoggersMap(loggerContext);
+ final ConcurrentMap<String, Logger> loggers = Hierarchy.getLoggersMap(loggerContext);
final Logger parentLogger = loggers.get(parent.getName());
return parentLogger == null ? new Category(parent) : parentLogger;
}
@@ -192,38 +142,23 @@ public class Category implements AppenderAttachable {
return getInstance(Strings.EMPTY);
}
- static Logger getRoot(final LoggerContext context) {
- return getInstance(context, Strings.EMPTY);
- }
-
- private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
- synchronized (CONTEXT_MAP) {
- ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context);
- if (map == null) {
- map = new ConcurrentHashMap<>();
- CONTEXT_MAP.put(context, map);
- }
- return map;
- }
- }
-
/**
* Returns all the currently defined categories in the default hierarchy as an
* {@link java.util.Enumeration Enumeration}.
- *
+ *
* <p>
* The root category is <em>not</em> included in the returned
* {@link Enumeration}.
* </p>
- *
+ *
* @return and Enumeration of the Categories.
- *
+ *
* @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
*/
@SuppressWarnings("rawtypes")
@Deprecated
public static Enumeration getCurrentCategories() {
- return LogManager.getCurrentLoggers();
+ return LogManager.getCurrentLoggers(StackLocatorUtil.getCallerClassLoader(2));
}
/**
@@ -262,7 +197,7 @@ public class Category implements AppenderAttachable {
/**
* Gets the the {@link LoggerRepository} where this <code>Category</code> instance is attached.
- *
+ *
* @deprecated Please use {@link #getLoggerRepository()} instead.
* @since 1.1
*/
@@ -273,7 +208,7 @@ public class Category implements AppenderAttachable {
/**
* Gets the the {@link LoggerRepository} where this <code>Category</code> is attached.
- *
+ *
* @since 1.2
*/
public LoggerRepository getLoggerRepository() {
@@ -305,7 +240,7 @@ public class Category implements AppenderAttachable {
}
private void setLevel(final String levelStr) {
- if (isCoreAvailable) {
+ if (LogManager.isLog4jCorePresent()) {
CategoryUtil.setLevel(logger, org.apache.logging.log4j.Level.toLevel(levelStr));
}
}
@@ -396,10 +331,10 @@ public class Category implements AppenderAttachable {
* @since 1.0
*/
synchronized void closeNestedAppenders() {
- Enumeration enumeration = this.getAllAppenders();
+ final Enumeration enumeration = this.getAllAppenders();
if (enumeration != null) {
while (enumeration.hasMoreElements()) {
- Appender a = (Appender) enumeration.nextElement();
+ final Appender a = (Appender) enumeration.nextElement();
if (a instanceof AppenderAttachable) {
a.close();
}
@@ -466,11 +401,12 @@ public class Category implements AppenderAttachable {
final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
if (logger instanceof ExtendedLogger) {
@SuppressWarnings("unchecked")
+ final
Message msg = message instanceof Message ? (Message) message : message instanceof Map ?
new MapMessage((Map) message) : new ObjectMessage(message);
((ExtendedLogger) logger).logMessage(fqcn, lvl, null, msg, t);
} else {
- ObjectRenderer renderer = get(message.getClass());
+ final ObjectRenderer renderer = get(message.getClass());
final Message msg = message instanceof Message ? (Message) message : renderer != null ?
new RenderedMessage(renderer, message) : new ObjectMessage(message);
logger.log(lvl, msg, t);
@@ -479,24 +415,24 @@ public class Category implements AppenderAttachable {
/**
* Tests if the named category exists (in the default hierarchy).
- *
+ *
* @param name The name to test.
* @return Whether the name exists.
- *
+ *
* @deprecated Please use {@link LogManager#exists(String)} instead.
* @since 0.8.5
*/
@Deprecated
- public static boolean exists(final String name) {
- return PrivateManager.getContext().hasLogger(name);
+ public static Logger exists(final String name) {
+ return LogManager.exists(name);
}
public boolean getAdditivity() {
- return isCoreAvailable ? CategoryUtil.isAdditive(logger) : false;
+ return LogManager.isLog4jCorePresent() ? CategoryUtil.isAdditive(logger) : false;
}
public void setAdditivity(final boolean additivity) {
- if (isCoreAvailable) {
+ if (LogManager.isLog4jCorePresent()) {
CategoryUtil.setAdditivity(logger, additivity);
}
}
@@ -504,7 +440,7 @@ public class Category implements AppenderAttachable {
/**
* Only the Hiearchy class can set the hiearchy of a category. Default package access is MANDATORY here.
*/
- final void setHierarchy(LoggerRepository repository) {
+ final void setHierarchy(final LoggerRepository repository) {
this.repository = repository;
}
@@ -517,10 +453,10 @@ public class Category implements AppenderAttachable {
return bundle;
}
String name = logger.getName();
- if (isCoreAvailable) {
- LoggerContext ctx = CategoryUtil.getLoggerContext(logger);
+ if (LogManager.isLog4jCorePresent()) {
+ final LoggerContext ctx = CategoryUtil.getLoggerContext(logger);
if (ctx != null) {
- final ConcurrentMap<String, Logger> loggers = getLoggersMap(ctx);
+ final ConcurrentMap<String, Logger> loggers = Hierarchy.getLoggersMap(ctx);
while ((name = getSubName(name)) != null) {
final Logger subLogger = loggers.get(name);
if (subLogger != null) {
@@ -546,7 +482,7 @@ public class Category implements AppenderAttachable {
/**
* If <code>assertion</code> parameter is {@code false}, then logs
* <code>msg</code> as an {@link #error(Object) error} statement.
- *
+ *
* <p>
* The <code>assert</code> method has been renamed to <code>assertLog</code>
* because <code>assert</code> is a language reserved word in JDK 1.4.
@@ -554,7 +490,7 @@ public class Category implements AppenderAttachable {
*
* @param assertion The assertion.
* @param msg The message to print if <code>assertion</code> is false.
- *
+ *
* @since 1.2
*/
public void assertLog(final boolean assertion, final String msg) {
@@ -629,39 +565,11 @@ public class Category implements AppenderAttachable {
}
}
- private static class PrivateAdapter extends AbstractLoggerAdapter<Logger> {
-
- @Override
- protected Logger newLogger(final String name, final org.apache.logging.log4j.spi.LoggerContext context) {
- return new Logger(context, name);
- }
-
- @Override
- protected org.apache.logging.log4j.spi.LoggerContext getContext() {
- return PrivateManager.getContext();
- }
- }
-
- /**
- * Private LogManager.
- */
- private static class PrivateManager extends org.apache.logging.log4j.LogManager {
- private static final String FQCN = Category.class.getName();
-
- public static LoggerContext getContext() {
- return getContext(FQCN, false);
- }
-
- public static org.apache.logging.log4j.Logger getLogger(final String name) {
- return getLogger(FQCN, name);
- }
- }
-
private boolean isEnabledFor(final org.apache.logging.log4j.Level level) {
return logger.isEnabled(level);
}
- private <T> ObjectRenderer get(Class<T> clazz) {
+ private <T> ObjectRenderer get(final Class<T> clazz) {
ObjectRenderer renderer = null;
for (Class<? super T> c = clazz; c != null; c = c.getSuperclass()) {
renderer = rendererMap.get(c);
@@ -676,13 +584,13 @@ public class Category implements AppenderAttachable {
return null;
}
- ObjectRenderer searchInterfaces(Class<?> c) {
+ ObjectRenderer searchInterfaces(final Class<?> c) {
ObjectRenderer renderer = rendererMap.get(c);
if (renderer != null) {
return renderer;
}
- Class<?>[] ia = c.getInterfaces();
- for (Class<?> clazz : ia) {
+ final Class<?>[] ia = c.getInterfaces();
+ for (final Class<?> clazz : ia) {
renderer = searchInterfaces(clazz);
if (renderer != null) {
return renderer;
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java b/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java
index b497706..a7a059a 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java
@@ -24,16 +24,22 @@ package org.apache.log4j;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.or.ObjectRenderer;
import org.apache.log4j.or.RendererMap;
import org.apache.log4j.spi.HierarchyEventListener;
import org.apache.log4j.spi.LoggerFactory;
-import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.RendererSupport;
import org.apache.log4j.spi.ThrowableRenderer;
import org.apache.log4j.spi.ThrowableRendererSupport;
+import org.apache.logging.log4j.core.appender.AsyncAppender;
+import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
+import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.util.Strings;
/**
* This class is specialized in retrieving loggers by name and also maintaining the logger hierarchy.
@@ -52,18 +58,77 @@ import org.apache.log4j.spi.ThrowableRendererSupport;
* provision node.
* </p>
*/
-public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRendererSupport {
+public class Hierarchy implements LoggerRepository2, RendererSupport, ThrowableRendererSupport {
+
+ private static class PrivateLoggerAdapter extends AbstractLoggerAdapter<Logger> {
+
+ @Override
+ protected org.apache.logging.log4j.spi.LoggerContext getContext() {
+ return PrivateLogManager.getContext();
+ }
+
+ @Override
+ protected Logger newLogger(final String name, final org.apache.logging.log4j.spi.LoggerContext context) {
+ return new Logger(context, name);
+ }
+ }
+
+ /**
+ * Private LogManager.
+ */
+ private static class PrivateLogManager extends org.apache.logging.log4j.LogManager {
+ private static final String FQCN = Hierarchy.class.getName();
+
+ public static LoggerContext getContext() {
+ return getContext(FQCN, false);
+ }
+
+ public static org.apache.logging.log4j.Logger getLogger(final String name) {
+ return getLogger(FQCN, name);
+ }
+ }
+
+ private static final PrivateLoggerAdapter LOGGER_ADAPTER = new PrivateLoggerAdapter();
+
+ private static final WeakHashMap<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP = new WeakHashMap<>();
+
+ static LoggerContext getContext() {
+ return PrivateLogManager.getContext();
+ }
+
+ static Logger getInstance(final LoggerContext context, final String name) {
+ return getInstance(context, name, LOGGER_ADAPTER);
+ }
+
+ static Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) {
+ return getLoggersMap(context).computeIfAbsent(name, k -> factory.makeNewLoggerInstance(name));
+ }
+
+ static Logger getInstance(final LoggerContext context, final String name, final PrivateLoggerAdapter factory) {
+ return getLoggersMap(context).computeIfAbsent(name, k -> factory.newLogger(name, context));
+ }
+
+ static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
+ synchronized (CONTEXT_MAP) {
+ return CONTEXT_MAP.computeIfAbsent(context, k -> new ConcurrentHashMap<>());
+ }
+ }
+
+ static Logger getRootLogger(final LoggerContext context) {
+ return getInstance(context, org.apache.logging.log4j.LogManager.ROOT_LOGGER_NAME);
+ }
private final LoggerFactory defaultFactory;
private final Vector listeners;
-
Hashtable ht;
Logger root;
RendererMap rendererMap;
int thresholdInt;
Level threshold;
boolean emittedNoAppenderWarning;
+
boolean emittedNoResourceBundleWarning;
+
private ThrowableRenderer throwableRenderer;
/**
@@ -132,12 +197,11 @@ public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRe
*/
@Override
public Logger exists(final String name) {
- final Object o = ht.get(new CategoryKey(name));
- if (o instanceof Logger) {
- return (Logger) o;
- } else {
+ final LoggerContext ctx = getContext();
+ if (!ctx.hasLogger(name)) {
return null;
}
+ return Logger.getLogger(name);
}
@Override
@@ -207,18 +271,13 @@ public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRe
*/
@Override
public Logger getLogger(final String name) {
- return getLogger(name, defaultFactory);
+ return getInstance(getContext(), name);
}
- /**
- * Gets an integer representation of the this repository's threshold.
- *
- * @since 1.2
- */
- // public
- // int getThresholdInt() {
- // return thresholdInt;
- // }
+ @Override
+ public Logger getLogger(final String name, final ClassLoader classLoader) {
+ return getInstance(LogManager.getContext(classLoader), name);
+ }
/**
* Gets a new logger instance named as the first parameter using <code>factory</code>.
@@ -233,36 +292,12 @@ public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRe
*/
@Override
public Logger getLogger(final String name, final LoggerFactory factory) {
- // System.out.println("getInstance("+name+") called.");
- final CategoryKey key = new CategoryKey(name);
- // Synchronize to prevent write conflicts. Read conflicts (in
- // getChainedLevel method) are possible only if variable
- // assignments are non-atomic.
- Logger logger;
+ return getInstance(getContext(), name, factory);
+ }
- synchronized (ht) {
- final Object o = ht.get(key);
- if (o == null) {
- logger = factory.makeNewLoggerInstance(name);
- logger.setHierarchy(this);
- ht.put(key, logger);
- updateParents(logger);
- return logger;
- } else if (o instanceof Logger) {
- return (Logger) o;
- } else if (o instanceof ProvisionNode) {
- // System.out.println("("+name+") ht.get(this) returned ProvisionNode");
- logger = factory.makeNewLoggerInstance(name);
- logger.setHierarchy(this);
- ht.put(key, logger);
- updateChildren((ProvisionNode) o, logger);
- updateParents(logger);
- return logger;
- } else {
- // It should be impossible to arrive here
- return null; // but let's keep the compiler happy.
- }
- }
+ @Override
+ public Logger getLogger(final String name, final LoggerFactory factory, final ClassLoader classLoader) {
+ return getInstance(LogManager.getContext(classLoader), name, factory);
}
/**
@@ -280,7 +315,7 @@ public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRe
*/
@Override
public Logger getRootLogger() {
- return root;
+ return getInstance(getContext(), org.apache.logging.log4j.LogManager.ROOT_LOGGER_NAME);
}
/**
@@ -336,7 +371,7 @@ public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRe
@Override
public void resetConfiguration() {
- getRootLogger().setLevel((Level) Level.DEBUG);
+ getRootLogger().setLevel(Level.DEBUG);
root.setResourceBundle(null);
setThreshold(Level.ALL);
@@ -393,7 +428,7 @@ public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRe
*/
@Override
public void setThreshold(final String levelStr) {
- final Level l = (Level) Level.toLevel(levelStr, null);
+ final Level l = Level.toLevel(levelStr, null);
if (l != null) {
setThreshold(l);
} else {
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java b/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java
index 3f92cdf..46bff05 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java
@@ -16,22 +16,22 @@
*/
package org.apache.log4j;
+import java.util.Collections;
import java.util.Enumeration;
+import java.util.stream.Collectors;
-import org.apache.log4j.helpers.NullEnumeration;
import org.apache.log4j.legacy.core.ContextUtil;
-import org.apache.log4j.or.ObjectRenderer;
-import org.apache.log4j.or.RendererMap;
-import org.apache.log4j.spi.HierarchyEventListener;
+import org.apache.log4j.spi.DefaultRepositorySelector;
import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.LoggerRepository;
-import org.apache.log4j.spi.RendererSupport;
+import org.apache.log4j.spi.NOPLoggerRepository;
import org.apache.log4j.spi.RepositorySelector;
+import org.apache.log4j.spi.RootLogger;
import org.apache.logging.log4j.spi.LoggerContext;
-import org.apache.logging.log4j.util.Strings;
+import org.apache.logging.log4j.util.StackLocatorUtil;
/**
- *
+ * The main entry point to Log4j 1.
*/
public final class LogManager {
@@ -61,188 +61,133 @@ public final class LogManager {
static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml";
- private static final LoggerRepository REPOSITORY = new Repository();
+ static private RepositorySelector repositorySelector;
- private static final boolean isLog4jCore;
+ private static final boolean LOG4J_CORE_PRESENT;
static {
- boolean core = false;
+ LOG4J_CORE_PRESENT = checkLog4jCore();
+ //
+ // By default we use a DefaultRepositorySelector which always returns 'hierarchy'.
+ Hierarchy hierarchy = new Hierarchy(new RootLogger(Level.DEBUG));
+ repositorySelector = new DefaultRepositorySelector(hierarchy);
+ }
+
+ private static boolean checkLog4jCore() {
try {
- if (Class.forName("org.apache.logging.log4j.core.LoggerContext") != null) {
- core = true;
- }
+ return Class.forName("org.apache.logging.log4j.core.LoggerContext") != null;
} catch (Exception ex) {
- // Ignore the exception;
+ return false;
}
- isLog4jCore = core;
}
- public static Logger getRootLogger() {
- return Category.getInstance(PrivateManager.getContext(), Strings.EMPTY);
+ public static Logger exists(final String name) {
+ return getLoggerRepository().exists(name);
}
- public static Logger getLogger(final String name) {
- return Category.getInstance(PrivateManager.getContext(), name);
+ /**
+ * Gets a LoggerContext.
+ *
+ * @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
+ * ClassLoader.
+ * @return a LoggerContext.
+ */
+ static LoggerContext getContext(final ClassLoader classLoader) {
+ return org.apache.logging.log4j.LogManager.getContext(classLoader, false);
+ }
+
+ /**
+ * Gets an enumeration of the current loggers.
+ *
+ * @return an enumeration of the current loggers.
+ */
+ @SuppressWarnings("rawtypes")
+ public static Enumeration getCurrentLoggers() {
+ return getCurrentLoggers(StackLocatorUtil.getCallerClassLoader(2));
+ }
+
+ @SuppressWarnings("rawtypes")
+ static Enumeration getCurrentLoggers(final ClassLoader classLoader) {
+ // @formatter:off
+ return Collections.enumeration(
+ LogManager.getContext(classLoader).getLoggerRegistry()
+ .getLoggers().stream().map(e -> LogManager.getLogger(e.getName(), classLoader))
+ .collect(Collectors.toList()));
+ // @formatter:on
}
public static Logger getLogger(final Class<?> clazz) {
- return Category.getInstance(PrivateManager.getContext(), clazz.getName());
+ // Depth 2 gets the call site of this method.
+ return getLoggerRepository2().getLogger(clazz.getName(), StackLocatorUtil.getCallerClassLoader(2));
+ }
+
+ public static Logger getLogger(final String name) {
+ // Depth 2 gets the call site of this method.
+ return getLoggerRepository2().getLogger(name, StackLocatorUtil.getCallerClassLoader(2));
+ }
+
+ static Logger getLogger(final String name, final ClassLoader classLoader) {
+ return getLoggerRepository2().getLogger(name, classLoader);
}
public static Logger getLogger(final String name, final LoggerFactory factory) {
- return Category.getInstance(PrivateManager.getContext(), name);
+ // Depth 2 gets the call site of this method.
+ return getLoggerRepository2().getLogger(name, factory, StackLocatorUtil.getCallerClassLoader(2));
}
- public static Logger exists(final String name) {
- final LoggerContext ctx = PrivateManager.getContext();
- if (!ctx.hasLogger(name)) {
- return null;
+ static Logger getLogger(final String name, final LoggerFactory factory, final ClassLoader classLoader) {
+ return getLoggerRepository2().getLogger(name, factory, classLoader);
+ }
+
+ public static LoggerRepository getLoggerRepository() {
+ if (repositorySelector == null) {
+ repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
}
- return Logger.getLogger(name);
+ return repositorySelector.getLoggerRepository();
}
- @SuppressWarnings("rawtypes")
- public static Enumeration getCurrentLoggers() {
- return getLoggerRepository().getCurrentLoggers();
+ static LoggerRepository2 getLoggerRepository2() {
+ // TODO Hack
+ return (LoggerRepository2) getLoggerRepository();
}
- static void reconfigure() {
- if (isLog4jCore) {
- final LoggerContext ctx = PrivateManager.getContext();
- ContextUtil.reconfigure(ctx);
- }
+ public static Logger getRootLogger() {
+ return getLoggerRepository2().getRootLogger();
}
- /**
- * No-op implementation.
- */
- public static void shutdown() {
+ static boolean isLog4jCorePresent() {
+ return LOG4J_CORE_PRESENT;
+ }
+
+ static void reconfigure() {
+ if (isLog4jCorePresent()) {
+ ContextUtil.reconfigure(Hierarchy.getContext());
+ }
}
/**
* No-op implementation.
*/
public static void resetConfiguration() {
+ // noop
}
/**
* No-op implementation.
+ *
* @param selector The RepositorySelector.
* @param guard prevents calls at the incorrect time.
* @throws IllegalArgumentException if a parameter is invalid.
*/
- public static void setRepositorySelector(final RepositorySelector selector, final Object guard)
- throws IllegalArgumentException {
- }
-
- public static LoggerRepository getLoggerRepository() {
- return REPOSITORY;
+ public static void setRepositorySelector(final RepositorySelector selector, final Object guard) throws IllegalArgumentException {
+ // noop
}
/**
- * The Repository.
+ * No-op implementation.
*/
- private static class Repository implements LoggerRepository, RendererSupport {
-
- private final RendererMap rendererMap = new RendererMap();
-
- @Override
- public RendererMap getRendererMap() {
- return rendererMap;
- }
-
- @Override
- public void addHierarchyEventListener(final HierarchyEventListener listener) {
-
- }
-
- @Override
- public boolean isDisabled(final int level) {
- return false;
- }
-
- @Override
- public void setThreshold(final Level level) {
-
- }
-
- @Override
- public void setThreshold(final String val) {
-
- }
-
- @Override
- public void emitNoAppenderWarning(final Category cat) {
-
- }
-
- @Override
- public Level getThreshold() {
- return Level.OFF;
- }
-
- @Override
- public Logger getLogger(final String name) {
- return Category.getInstance(PrivateManager.getContext(), name);
- }
-
- @Override
- public Logger getLogger(final String name, final LoggerFactory factory) {
- return Category.getInstance(PrivateManager.getContext(), name);
- }
-
- @Override
- public Logger getRootLogger() {
- return Category.getRoot(PrivateManager.getContext());
- }
-
- @Override
- public Logger exists(final String name) {
- return LogManager.exists(name);
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- public Enumeration getCurrentLoggers() {
- return NullEnumeration.getInstance();
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- public Enumeration getCurrentCategories() {
- return NullEnumeration.getInstance();
- }
-
- @Override
- public void fireAddAppenderEvent(final Category logger, final Appender appender) {
- }
-
- @Override
- public void resetConfiguration() {
- }
-
- @Override
- public void setRenderer(Class renderedClass, ObjectRenderer renderer) {
- rendererMap.put(renderedClass, renderer);
- }
+ public static void shutdown() {
+ // noop
}
- /**
- * Internal LogManager.
- */
- private static class PrivateManager extends org.apache.logging.log4j.LogManager {
- private static final String FQCN = LogManager.class.getName();
-
- public static LoggerContext getContext() {
- return getContext(FQCN, false);
- }
-
- public static org.apache.logging.log4j.Logger getLogger(final String name) {
- return getLogger(FQCN, name);
- }
- }
}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java b/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java
index 674a0c1..19c523e 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Logger.java
@@ -18,6 +18,7 @@ package org.apache.log4j;
import org.apache.log4j.spi.LoggerFactory;
import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.util.StackLocatorUtil;
/**
*
@@ -29,28 +30,31 @@ public class Logger extends Category {
*/
private static final String FQCN = Logger.class.getName();
- protected Logger(final String name) {
- super(name);
- }
-
- Logger(final LoggerContext context, final String name) {
- super(context, name);
+ public static Logger getLogger(final Class<?> clazz) {
+ // Depth 2 gets the call site of this method.
+ return LogManager.getLogger(clazz.getName(), StackLocatorUtil.getCallerClassLoader(2));
}
public static Logger getLogger(final String name) {
- return LogManager.getLogger(name);
+ // Depth 2 gets the call site of this method.
+ return LogManager.getLogger(name, StackLocatorUtil.getCallerClassLoader(2));
}
- public static Logger getLogger(final Class<?> clazz) {
- return LogManager.getLogger(clazz);
+ public static Logger getLogger(final String name, final LoggerFactory factory) {
+ // Depth 2 gets the call site of this method.
+ return LogManager.getLogger(name, factory, StackLocatorUtil.getCallerClassLoader(2));
}
public static Logger getRootLogger() {
return LogManager.getRootLogger();
}
- public static Logger getLogger(final String name, final LoggerFactory factory) {
- return LogManager.getLogger(name, factory);
+ Logger(final LoggerContext context, final String name) {
+ super(context, name);
+ }
+
+ protected Logger(final String name) {
+ super(name);
}
public boolean isTraceEnabled() {
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/LoggerRepository2.java b/log4j-1.2-api/src/main/java/org/apache/log4j/LoggerRepository2.java
new file mode 100644
index 0000000..30c88ee
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/LoggerRepository2.java
@@ -0,0 +1,31 @@
+/*
+ * 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.log4j;
+
+import org.apache.log4j.spi.LoggerFactory;
+import org.apache.log4j.spi.LoggerRepository;
+
+/**
+ * A LoggerRepository that accounts for the caller's class loader.
+ */
+interface LoggerRepository2 extends LoggerRepository {
+
+ Logger getLogger(String name, ClassLoader classLoader);
+
+ Logger getLogger(String name, LoggerFactory factory, ClassLoader classLoader);
+}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/RootLogger.java b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/RootLogger.java
index afd4619..79db491 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/RootLogger.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/RootLogger.java
@@ -34,7 +34,8 @@ public final class RootLogger extends Logger {
* The root logger names itself as "root". However, the root logger cannot be retrieved by name.
*/
public RootLogger(Level level) {
- // Note that the Log4j 2 root logger name is "".
+ // The Log4j 1 root logger name is "root".
+ // The Log4j 2 root logger name is "".
super("root");
setLevel(level);
}
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java
index a618136..a6e9510 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java
@@ -18,8 +18,8 @@
package org.apache.log4j;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Method;
@@ -74,7 +74,7 @@ public class CategoryTest {
@Test
public void testExist() throws Exception {
- assertFalse(Category.exists("Does not exist for sure"));
+ assertNull(Category.exists("Does not exist for sure"));
}
/**
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/LogManagerTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/LogManagerTest.java
index d8fcd16..b3d56b2 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/LogManagerTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/LogManagerTest.java
@@ -24,21 +24,25 @@ import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;
-import org.junit.Ignore;
import org.junit.Test;
+/**
+ * Tests {@link LogManager}.
+ */
public class LogManagerTest {
private static final String SIMPLE_NAME = LogManagerTest.class.getSimpleName();
+ List<String> getCurrentLoggerNames() {
+ return Collections.list((Enumeration<Logger>) LogManager.getCurrentLoggers()).stream().map(Logger::getName).collect(Collectors.toList());
+ }
+
@Test
- @Ignore("WIP")
public void testGetCurrentLoggers() {
Logger.getLogger(SIMPLE_NAME);
Logger.getLogger(SIMPLE_NAME + ".foo");
Logger.getLogger(SIMPLE_NAME + ".foo.bar");
- final List<String> names = Collections.list((Enumeration<Logger>) LogManager.getCurrentLoggers()).stream().map(Logger::getName)
- .collect(Collectors.toList());
+ final List<String> names = getCurrentLoggerNames();
assertTrue(names.contains(SIMPLE_NAME));
assertTrue(names.contains(SIMPLE_NAME + ".foo"));
assertTrue(names.contains(SIMPLE_NAME + ".foo.bar"));