Index: log4j-core/src/main/java/org/apache/logging/log4j/core/helpers/Loader.java
===================================================================
--- log4j-core/src/main/java/org/apache/logging/log4j/core/helpers/Loader.java (revision 1588849)
+++ log4j-core/src/main/java/org/apache/logging/log4j/core/helpers/Loader.java (working copy)
@@ -17,10 +17,8 @@
package org.apache.logging.log4j.core.helpers;
import java.io.InputStream;
-import java.lang.ClassCastException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
-
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusLogger;
@@ -249,8 +247,7 @@
// using the TCCL should work the same as the default ClassLoader (i.e., init or not)
return Class.forName(className, true, getTCL());
} catch (final Throwable e) {
- LOGGER.catching(Level.DEBUG, e);
- LOGGER.trace("TCCL didn't work. Trying Class.forName({}).", className);
+ LOGGER.trace("TCCL didn't work. Trying Class.forName({}).", className, e);
return loadClassWithDefaultClassLoader(className);
}
}
Index: log4j-jdk/pom.xml
===================================================================
--- log4j-jdk/pom.xml (revision 0)
+++ log4j-jdk/pom.xml (working copy)
@@ -0,0 +1,71 @@
+
+
+
+
+
+ log4j
+ org.apache.logging.log4j
+ 2.0-rc2-SNAPSHOT
+
+ 4.0.0
+
+ log4j-jdk
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+
+
+ org.apache.logging.log4j
+ log4j-core
+
+
+ org.apache.logging.log4j
+ log4j-core
+ test-jar
+
+
+ org.hamcrest
+ hamcrest-all
+ 1.3
+ test
+
+
+ junit
+ junit
+
+
+
+
+
+
+ org.apache.felix
+ maven-bundle-plugin
+
+
+ org.apache.logging.log4j.jdk
+
+
+
+
+
+
+
\ No newline at end of file
Property changes on: log4j-jdk/pom.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/JavaLogManager.java
===================================================================
--- log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/JavaLogManager.java (revision 0)
+++ log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/JavaLogManager.java (working copy)
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.jdk;
+
+import java.util.logging.Logger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.message.MessageFormatMessageFactory;
+import org.apache.logging.log4j.spi.LoggerContext;
+
+/**
+ * Custom implementation of LogManager to aid in bridging the JDK logging system to Log4j 2.
+ *
+ * Make sure to set the system property {@code java.util.logging.manager} to
+ * {@code org.apache.logging.log4j.jdk.JavaLogManager} for this to take effect.
+ */
+public class JavaLogManager extends java.util.logging.LogManager {
+
+ public static final String ANONYMOUS_LOGGER_NAME = "anonymous";
+
+ @Override
+ public boolean addLogger(final Logger logger) {
+ final LoggerContext context = LogManager.getContext();
+ final String name = getLoggerName(logger);
+ if (context.hasLogger(name)) {
+ // already registered
+ return false;
+ } else {
+ final org.apache.logging.log4j.Logger log = context.getLogger(name);
+ return log != null;
+ }
+ }
+
+ private static String getLoggerName(final Logger logger) {
+ final String name = logger.getName();
+ return name != null ? name : ANONYMOUS_LOGGER_NAME;
+ }
+
+ @Override
+ public Logger getLogger(final String name) {
+ // TODO: could we do some caching here? or is it pointless?
+ final org.apache.logging.log4j.Logger logger = LogManager.getLogger(name, new MessageFormatMessageFactory());
+ return new LoggerWrapper(logger);
+ }
+
+ @Override
+ public void reset() throws SecurityException {
+ // nothing to reset
+ }
+
+ protected JavaLogManager() {
+ super();
+ }
+}
Property changes on: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/JavaLogManager.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LogHandler.java
===================================================================
--- log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LogHandler.java (revision 0)
+++ log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LogHandler.java (working copy)
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.jdk;
+
+import java.util.ResourceBundle;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.jdk.util.Levels;
+import org.apache.logging.log4j.message.LocalizedMessageFactory;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.MessageFactory;
+import org.apache.logging.log4j.message.MessageFormatMessageFactory;
+
+/**
+ * Handler implementation for {@code java.util.logging}.
+ */
+public class LogHandler extends Handler {
+
+ @Override
+ public void publish(final LogRecord record) {
+ if (record == null || record.getMessage() == null) {
+ return;
+ }
+ final Logger logger = getLoggerForRecord(record);
+ final Level level = Levels.toLevel(record.getLevel());
+ final Marker marker = Levels.toMarker(record.getLevel());
+ if (logger.isEnabled(level, marker)) {
+ final Message message = logger.getMessageFactory().newMessage(record.getMessage(), record.getParameters());
+ logger.log(level, marker, message, record.getThrown());
+ }
+ }
+
+ private static Logger getLoggerForRecord(final LogRecord record) {
+ final String name = record.getLoggerName() != null
+ ? record.getLoggerName()
+ : JavaLogManager.ANONYMOUS_LOGGER_NAME;
+ final ResourceBundle bundle = record.getResourceBundle();
+ final MessageFactory factory = bundle != null
+ ? new LocalizedMessageFactory(bundle)
+ : new MessageFormatMessageFactory();
+ return LogManager.getLogger(name, factory);
+ }
+
+ @Override
+ public void flush() {
+ // handled internally by appenders
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ // handled by LoggerContext life cycles
+ }
+
+ // FIXME: this shouldn't be a singleton
+ private LogHandler() {
+ }
+
+ private static final class Holder {
+ private static final LogHandler HANDLER = new LogHandler();
+ }
+
+ public static LogHandler getInstance() {
+ return Holder.HANDLER;
+ }
+}
Property changes on: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LogHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggerWrapper.java
===================================================================
--- log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggerWrapper.java (revision 0)
+++ log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggerWrapper.java (working copy)
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.jdk;
+
+import java.util.ResourceBundle;
+import java.util.logging.LogRecord;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.jdk.util.Levels;
+import org.apache.logging.log4j.message.LocalizedMessageFactory;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.MessageFactory;
+import org.apache.logging.log4j.message.MessageFormatMessageFactory;
+
+/**
+ * Adapter class for JDK Loggers.
+ */
+public class LoggerWrapper extends java.util.logging.Logger {
+
+ private final Logger logger;
+
+ /**
+ * Constructs a named LoggerWrapper with no L10n ResourceBundle.
+ *
+ * @param name the name of the Logger.
+ */
+ protected LoggerWrapper(final String name) {
+ this(name, null);
+ }
+
+ /**
+ * Constructs a named LoggerWrapper with the specified L10n ResourceBundle name.
+ *
+ * @param name the name of the Logger.
+ * @param resourceBundleName the name of the L10n ResourceBundle to use.
+ */
+ protected LoggerWrapper(final String name, final String resourceBundleName) {
+ super(name, resourceBundleName);
+ final ResourceBundle bundle = getResourceBundle();
+ final MessageFactory messageFactory = bundle != null
+ ? new LocalizedMessageFactory(bundle)
+ : new MessageFormatMessageFactory();
+ this.logger = LogManager.getLogger(name, messageFactory);
+ }
+
+ protected LoggerWrapper(final Logger logger) {
+ super(logger.getName(), null);
+ this.logger = logger;
+ }
+
+ @Override
+ public void log(final LogRecord record) {
+ if (record == null || record.getMessage() == null) {
+ return;
+ }
+ final Level level = Levels.toLevel(record.getLevel());
+ final Marker marker = Levels.toMarker(record.getLevel());
+ if (logger.isEnabled(level, marker)) {
+ final Message message = logger.getMessageFactory().newMessage(record.getMessage(), record.getParameters());
+ logger.log(level, marker, message, record.getThrown());
+ }
+ }
+
+ @Override
+ public void setLevel(final java.util.logging.Level newLevel) throws SecurityException {
+ // TODO: use log4j-core for more internals like this
+ throw new UnsupportedOperationException("There is no way to set the logger level via log4j-api.");
+ }
+
+ @Override
+ public java.util.logging.Level getLevel() {
+ return Levels.toJavaLevel(logger.getLevel());
+ }
+
+ @Override
+ public boolean isLoggable(final java.util.logging.Level level) {
+ return logger.isEnabled(Levels.toLevel(level), Levels.toMarker(level));
+ }
+
+ @Override
+ public String getName() {
+ return logger.getName();
+ }
+}
Property changes on: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggerWrapper.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggingSystem.java
===================================================================
--- log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggingSystem.java (revision 0)
+++ log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggingSystem.java (working copy)
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.jdk;
+
+import java.lang.ref.Reference;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.LogManager;
+import java.util.logging.LoggingPermission;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.jdk.util.ReflectionUtils;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * Anchor point for initializing the {@code java.util.logging} system.
+ */
+public final class LoggingSystem {
+
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
+ private static final Lock LOCK = new ReentrantLock();
+
+ private static final Class LOG_MANAGER_CLASS = LogManager.class;
+ private static final Class LOGGER_CLASS = java.util.logging.Logger.class;
+
+ private static final Class> LOGGER_CONTEXT_CLASS;
+ private static final Method LOG_MANAGER_CONTEXTS_METHOD;
+ private static final Method LOGGER_SET_LOG_MANAGER_METHOD;
+ private static final Field LOG_MANAGER_FIELD;
+ private static final Field LOGGER_CONTEXT_NAMED_LOGGERS_FIELD;
+
+ private static final LogManager LOG_MANAGER = new JavaLogManager();
+
+ static {
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new LoggingPermission("control", null));
+ }
+ try {
+ LOG_MANAGER_CONTEXTS_METHOD = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ @Override
+ public Method run() throws Exception {
+ final Method m = findContextsMethod();
+ m.setAccessible(true);
+ return m;
+ }
+
+ });
+ LOGGER_SET_LOG_MANAGER_METHOD = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ @Override
+ public Method run() throws Exception {
+ final Method m = findSetLogManagerMethod();
+ m.setAccessible(true);
+ return m;
+ }
+ });
+ LOG_MANAGER_FIELD = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ @Override
+ public Field run() throws Exception {
+ final Field f = findLogManagerField();
+ ReflectionUtils.forceModifiableField(f);
+ return f;
+ }
+ });
+ LOGGER_CONTEXT_CLASS = ReflectionUtils.loadClass("java.util.logging.LogManager$LoggerContext");
+ LOGGER_CONTEXT_NAMED_LOGGERS_FIELD = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ @Override
+ public Field run() throws Exception {
+ final Field f = findNamedLoggersField();
+ f.setAccessible(true);
+ return f;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ LOGGER.catching(e.getCause());
+ throw new ExceptionInInitializerError(e);
+ } catch (ClassNotFoundException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /**
+ * Injects the Log4j 2 LogManager into the global LogManager. All active Loggers are updated accordingly to
+ * prevent strange behavior.
+ */
+ public static void inject() {
+ if (!(LogManager.getLogManager() instanceof JavaLogManager)) {
+ // so the user didn't set the java.util.logging.manager system property? guess we have to manually
+ // inject our own implementation thanks to the inflexible API
+ LOCK.lock();
+ try {
+ updateLoggers(findExistingLoggers(swapLogManager()));
+ } catch (final Exception e) {
+ LOGGER.error("There was a problem starting the JavaLogManager.", e);
+ } finally {
+ LOCK.unlock();
+ }
+ }
+ }
+
+ private static Method findContextsMethod() throws NoSuchMethodException {
+ try {
+ return LOG_MANAGER_CLASS.getDeclaredMethod("contexts");
+ } catch (NoSuchMethodException e) {
+ LOGGER.debug("No method named LogManager.contexts() found. Looking for a compatible method.");
+ // well, let's just look for the method returning a List
+ final Method[] methods = LOG_MANAGER_CLASS.getDeclaredMethods();
+ for (final Method method : methods) {
+ if (List.class.isAssignableFrom(method.getReturnType())) {
+ return method;
+ }
+ }
+ throw e;
+ }
+ }
+
+ private static Method findSetLogManagerMethod() throws NoSuchMethodException {
+ try {
+ return LOGGER_CLASS.getDeclaredMethod("setLogManager", LogManager.class);
+ } catch (final NoSuchMethodException e) {
+ LOGGER.debug("No method named Logger.setLogManager found. Looking for a compatible method.");
+ // well, now we can try to just find the method
+ final Method[] methods = LOGGER_CLASS.getDeclaredMethods();
+ for (final Method method : methods) {
+ if (method.getName().startsWith("set")) {
+ final Class>[] paramTypes = method.getParameterTypes();
+ if (paramTypes.length == 1 && LOG_MANAGER_CLASS.isAssignableFrom(paramTypes[0])) {
+ return method;
+ }
+ }
+ }
+ throw e;
+ }
+ }
+
+ private static Field findLogManagerField() throws NoSuchFieldException {
+ try {
+ return LOG_MANAGER_CLASS.getDeclaredField("manager");
+ } catch (final NoSuchFieldException e) {
+ LOGGER.debug("No field named LogManager.manager found. Looking for compatible field.");
+ final Field[] fields = LOG_MANAGER_CLASS.getDeclaredFields();
+ for (final Field field : fields) {
+ if (LOG_MANAGER_CLASS.isAssignableFrom(field.getType())) {
+ return field;
+ }
+ }
+ throw e;
+ }
+ }
+
+ private static Field findNamedLoggersField() throws NoSuchFieldException {
+ try {
+ return LOGGER_CONTEXT_CLASS.getDeclaredField("namedLoggers");
+ } catch (final NoSuchFieldException e) {
+ LOGGER.debug("No field named LogManager$LoggerContext.namedLoggers found. Looking for another Map.");
+ // well, let's just look for the Hashtable (seriously?) or Map of named logger references
+ final Field[] fields = LOGGER_CONTEXT_CLASS.getDeclaredFields();
+ for (final Field field : fields) {
+ if (Map.class.isAssignableFrom(field.getType())) {
+ // TODO: might want to check the generic parameters if possible
+ return field;
+ }
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Swaps the global LogManager instance with a Log4j 2 implementation.
+ *
+ * @return the old LogManager.
+ * @throws IllegalAccessException if there is a problem injecting the LogManager.
+ */
+ private static LogManager swapLogManager() throws IllegalAccessException {
+ final LogManager old = LogManager.getLogManager();
+ LOG_MANAGER_FIELD.set(null, LOG_MANAGER);
+ return old;
+ }
+
+ /**
+ * Collects and returns all the active named Loggers from the given LogManager.
+ *
+ * @param old the LogManager to collect active Loggers from.
+ * @return the active Loggers.
+ * @throws InvocationTargetException if there is a problem obtaining the LoggerContexts.
+ * @throws IllegalAccessException if there is a problem obtaining the Logger cache.
+ */
+ private static Iterable findExistingLoggers(final LogManager old)
+ throws InvocationTargetException, IllegalAccessException {
+ final Collection loggers = new HashSet();
+ final Iterable> contexts = (Iterable>) LOG_MANAGER_CONTEXTS_METHOD.invoke(old);
+ for (final Object context : contexts) {
+ final Map, ?> namedLoggers =
+ (Map, ?>) LOGGER_CONTEXT_NAMED_LOGGERS_FIELD.get(context);
+ for (final Object value : namedLoggers.values()) {
+ final Reference> ref = (Reference>) value;
+ final Object logger = ref.get();
+ if (logger != null) {
+ loggers.add((java.util.logging.Logger) logger);
+ }
+ }
+ }
+ return loggers;
+ }
+
+ /**
+ * Updates the collection of Loggers to use the Log4j 2 LogManager.
+ *
+ * @param loggers the loggers to update.
+ * @throws IllegalAccessException if there is a problem accessing the appropriate methods.
+ * @throws InvocationTargetException if there is a problem while invoking those methods.
+ */
+ private static void updateLoggers(final Iterable loggers)
+ throws IllegalAccessException, InvocationTargetException {
+ for (final java.util.logging.Logger logger : loggers) {
+ LOGGER_SET_LOG_MANAGER_METHOD.invoke(logger, LOG_MANAGER);
+ logger.addHandler(LogHandler.getInstance());
+ }
+ }
+
+ private LoggingSystem() {
+ }
+
+}
Property changes on: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/LoggingSystem.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/Levels.java
===================================================================
--- log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/Levels.java (revision 0)
+++ log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/Levels.java (working copy)
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.jdk.util;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+
+/**
+ * Utility class to convert between JDK Levels and Log4j 2 Levels.
+ */
+public final class Levels {
+
+ private static final Marker JUL = MarkerManager.getMarker("java.util.logging");
+
+ private static final int JDK_OFF = java.util.logging.Level.OFF.intValue(); // OFF
+ private static final int JDK_SEVERE = java.util.logging.Level.SEVERE.intValue(); // ERROR
+ private static final int JDK_WARNING = java.util.logging.Level.WARNING.intValue(); // WARN
+ private static final int JDK_INFO = java.util.logging.Level.INFO.intValue(); // INFO
+ private static final int JDK_CONFIG = java.util.logging.Level.CONFIG.intValue(); // INFO
+ private static final int JDK_FINE = java.util.logging.Level.FINE.intValue(); // DEBUG
+ private static final int JDK_FINER = java.util.logging.Level.FINER.intValue(); // DEBUG
+ private static final int JDK_FINEST = java.util.logging.Level.FINEST.intValue(); // TRACE
+ private static final int JDK_ALL = java.util.logging.Level.ALL.intValue(); // ALL
+
+ /**
+ * Converts a JDK logging Level to a Log4j logging Level.
+ *
+ * @param level JDK Level to convert.
+ * @return converted Level.
+ */
+ public static Level toLevel(final java.util.logging.Level level) {
+ final int value = level.intValue();
+ if (value == JDK_OFF) { // Integer.MAX_VALUE
+ return Level.OFF;
+ }
+ if (value == JDK_ALL) { // Integer.MIN_VALUE
+ return Level.ALL;
+ }
+ if (value <= JDK_FINEST) { // up to 300
+ return Level.TRACE;
+ }
+ if (value <= JDK_FINER) { // 301 to 400
+ return Level.DEBUG;
+ }
+ if (value <= JDK_FINE) { // 401 to 500
+ return Level.DEBUG;
+ }
+ if (value <= JDK_CONFIG) { // 501 to 700
+ return Level.INFO;
+ }
+ if (value <= JDK_INFO) { // 701 to 800
+ return Level.INFO;
+ }
+ if (value <= JDK_WARNING) { // 801 to 900
+ return Level.WARN;
+ }
+ if (value <= JDK_SEVERE) { // 901 to 1000
+ return Level.ERROR;
+ }
+ // 1001+
+ return Level.FATAL;
+ }
+
+ /**
+ * Converts a Log4j logging Level to a JDK logging Level.
+ *
+ * @param level Log4j Level to convert.
+ * @return converted Level.
+ */
+ public static java.util.logging.Level toJavaLevel(final Level level) {
+ if (level == Level.OFF) {
+ return java.util.logging.Level.OFF;
+ }
+ if (level == Level.TRACE) {
+ return java.util.logging.Level.FINEST;
+ }
+ if (level == Level.DEBUG) {
+ return java.util.logging.Level.FINE;
+ }
+ if (level == Level.INFO) {
+ return java.util.logging.Level.INFO;
+ }
+ if (level == Level.WARN) {
+ return java.util.logging.Level.WARNING;
+ }
+ if (level == Level.ERROR || level == Level.FATAL) {
+ return java.util.logging.Level.SEVERE;
+ }
+ if (level == Level.ALL) {
+ return java.util.logging.Level.ALL;
+ }
+ return java.util.logging.Level.parse(level.name());
+ }
+
+ /**
+ * Converts a custom JDK logging Level to an appropriate Log4j Marker.
+ *
+ * @param level JDK Level to convert.
+ * @return the corresponding Marker for the Level.
+ */
+ public static Marker toMarker(final java.util.logging.Level level) {
+ return MarkerManager.getMarker(
+ java.util.logging.Level.class.getName() + '.' + level.getName()
+ ).add(JUL);
+ }
+
+ private Levels() {
+ }
+}
Property changes on: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/Levels.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/ReflectionUtils.java
===================================================================
--- log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/ReflectionUtils.java (revision 0)
+++ log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/ReflectionUtils.java (working copy)
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.jdk.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ReflectPermission;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * Utility methods involving reflection.
+ */
+public final class ReflectionUtils {
+
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
+ /**
+ * @see java.lang.ClassLoader#findLoadedClass(String) ClassLoader.findLoadedClass
+ */
+ private static final Method findLoadedClass;
+
+ /**
+ * @see java.lang.reflect.Field#modifiers Field.modifiers
+ */
+ private static final Field fieldModifiers;
+
+ static {
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
+ }
+ try {
+ findLoadedClass = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ @Override
+ public Method run() throws Exception {
+ final Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
+ m.setAccessible(true);
+ return m;
+ }
+ });
+ fieldModifiers = AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ @Override
+ public Field run() throws Exception {
+ final Field f = Field.class.getDeclaredField("modifiers");
+ f.setAccessible(true);
+ return f;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ LOGGER.catching(e.getCause());
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /**
+ * Checks whether a class has been loaded already.
+ *
+ * @param className binary name of class to check.
+ * @return whether or not the class is already loaded by this ClassLoader or any of its parents.
+ */
+ public static boolean isClassLoaded(final String className) {
+ try {
+ return findLoadedClass.invoke(ReflectionUtils.class.getClassLoader(), className) != null;
+ } catch (final Exception e) {
+ LOGGER.catching(e);
+ return false;
+ }
+ }
+
+ /**
+ * Loads a class using the System ClassLoader or the ThreadContext ClassLoader.
+ *
+ * @param className name of class to load.
+ * @return loaded class.
+ * @throws ClassNotFoundException if no class could be found matching the given class name.
+ */
+ public static Class> loadClass(final String className) throws ClassNotFoundException {
+ try {
+ return AccessController.doPrivileged(new LoadClass(className));
+ } catch (PrivilegedActionException e) {
+ final Throwable cause = e.getCause();
+ LOGGER.error("Cannot load class [{}]", className, cause);
+ if (cause instanceof ClassNotFoundException) {
+ throw (ClassNotFoundException) cause;
+ } else {
+ throw new ClassNotFoundException("Unable to load class: " + className, cause);
+ }
+ }
+ }
+
+ /**
+ * Helper class for {@link #loadClass(String) loadClass}.
+ */
+ private static class LoadClass implements PrivilegedExceptionAction> {
+
+ private final String className;
+
+ private LoadClass(final String className) {
+ this.className = className;
+ }
+
+ @Override
+ public Class> run() throws Exception {
+ try {
+ return ClassLoader.getSystemClassLoader()
+ .loadClass(className);
+ } catch (ClassNotFoundException e) {
+ return Thread.currentThread()
+ .getContextClassLoader()
+ .loadClass(className);
+ }
+ }
+
+ }
+ /**
+ * Modifies a field to make it modifiable. That is, this method will make a field accessible along with removing
+ * the {@code final} modifier if necessary. This method should seldom be used due to how badly this defeats the
+ * purpose of the Java language.
+ *
+ * @param field the field to make modifiable.
+ * @throws PrivilegedActionException if there was a problem forcing access to the field.
+ */
+ public static void forceModifiableField(final Field field) throws PrivilegedActionException {
+ AccessController.doPrivileged(new ForceModifiableField(field));
+ }
+
+ /**
+ * Helper class for {@link #forceModifiableField(java.lang.reflect.Field) forceModifiableField}.
+ */
+ private static class ForceModifiableField implements PrivilegedExceptionAction {
+
+ private final Field field;
+
+ private ForceModifiableField(final Field field) {
+ this.field = field;
+ }
+
+ @Override
+ public Void run() throws Exception {
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ if (Modifier.isFinal(field.getModifiers())) {
+ fieldModifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ }
+ return null;
+ }
+
+ }
+
+ /**
+ * This is a utility class and should not be instantiated.
+ */
+ private ReflectionUtils() {
+ }
+}
Property changes on: log4j-jdk/src/main/java/org/apache/logging/log4j/jdk/util/ReflectionUtils.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/test/java/org/apache/logging/log4j/jdk/LoggingSystemTest.java
===================================================================
--- log4j-jdk/src/test/java/org/apache/logging/log4j/jdk/LoggingSystemTest.java (revision 0)
+++ log4j-jdk/src/test/java/org/apache/logging/log4j/jdk/LoggingSystemTest.java (working copy)
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.jdk;
+
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Basic integration tests.
+ */
+public class LoggingSystemTest {
+
+ private static Logger logger;
+
+ @BeforeClass
+ public static void setUpClass() {
+ logger = Logger.getLogger("test");
+ logger.setLevel(Level.FINE);
+ logger.fine("Test log message #1.");
+ final Handler[] beforeHandlers = logger.getHandlers();
+ for (final Handler handler : beforeHandlers) {
+ assertThat(handler, is(not(instanceOf(LogHandler.class))));
+ }
+ LoggingSystem.inject();
+ logger.fine("Test log message #2.");
+ final Handler[] afterHandlers = logger.getHandlers();
+ assertThat(afterHandlers, hasItemInArray(instanceOf(LogHandler.class)));
+ }
+
+ @Test
+ public void testInject() throws Exception {
+ final Logger test = Logger.getLogger("test");
+ assertThat(test, is(not(theInstance(logger))));
+ test.fine("Test log message #3.");
+ }
+}
Property changes on: log4j-jdk/src/test/java/org/apache/logging/log4j/jdk/LoggingSystemTest.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: log4j-jdk/src/test/resources/log4j2-test.xml
===================================================================
--- log4j-jdk/src/test/resources/log4j2-test.xml (revision 0)
+++ log4j-jdk/src/test/resources/log4j2-test.xml (working copy)
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
Property changes on: log4j-jdk/src/test/resources/log4j2-test.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: pom.xml
===================================================================
--- pom.xml (revision 1588849)
+++ pom.xml (working copy)
@@ -913,6 +913,7 @@
log4j-samples
log4j-bom
log4j-plugin-processor
+ log4j-jdk