You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2017/05/21 08:28:04 UTC
logging-log4j2 git commit: LOG4J2-1917 - Use ServiceLoader to locate
implementations.
Repository: logging-log4j2
Updated Branches:
refs/heads/master 671f30ba3 -> 92e4b8754
LOG4J2-1917 - Use ServiceLoader to locate implementations.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/92e4b875
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/92e4b875
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/92e4b875
Branch: refs/heads/master
Commit: 92e4b875463e8dc9e4683687d3572969f39b1593
Parents: 671f30b
Author: Ralph Goers <rg...@nextiva.com>
Authored: Sun May 21 01:27:57 2017 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Sun May 21 01:27:57 2017 -0700
----------------------------------------------------------------------
log4j-api/pom.xml | 23 ++++--
.../org/apache/logging/log4j/spi/Provider.java | 73 +++++++++++++++++---
.../apache/logging/log4j/util/Activator.java | 4 +-
.../logging/log4j/util/ClassNamePredicate.java | 45 ------------
.../logging/log4j/util/ClassPredicate.java | 46 ------------
.../apache/logging/log4j/util/ProviderUtil.java | 11 +++
.../log4j/util/StackWalkerStackLocator.java | 63 -----------------
.../logging/log4j/util/ClassNamePredicate.java | 45 ++++++++++++
.../logging/log4j/util/ClassPredicate.java | 46 ++++++++++++
.../log4j/util/StackWalkerStackLocator.java | 63 +++++++++++++++++
.../org/apache/logging/log4j/TestProvider.java | 28 ++++++++
.../META-INF/log4j-provider.properties | 3 -
.../org.apache.logging.log4j.spi.Provider | 1 +
.../logging/log4j/core/impl/Log4jProvider.java | 28 ++++++++
.../META-INF/log4j-provider.properties | 18 -----
.../org.apache.logging.log4j.spi.Provider | 1 +
.../appender/AsyncAppenderNoLocationTest.java | 20 +++++-
.../org/apache/logging/slf4j/SLF4JProvider.java | 28 ++++++++
.../META-INF/log4j-provider.properties | 19 -----
.../org.apache.logging.log4j.spi.Provider | 1 +
src/changes/changes.xml | 3 +
src/site/xdoc/manual/extending.xml | 37 ++++++----
22 files changed, 378 insertions(+), 228 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-api/pom.xml b/log4j-api/pom.xml
index bacf907..0b161d6 100644
--- a/log4j-api/pom.xml
+++ b/log4j-api/pom.xml
@@ -127,6 +127,23 @@
</configuration>
</plugin>
<plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src/main/java9</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
@@ -134,12 +151,6 @@
<id>default-compile</id>
<!-- recompile everything for target VM except the module-info.java -->
<configuration>
- <excludes>
- <exclude>module-info.java</exclude>
- <exclude>**/util/ClassNamePredicate.java</exclude>
- <exclude>**/util/ClassPredicate.java</exclude>
- <exclude>**/util/StackWalkerStackLocator.java</exclude>
- </excludes>
<source>1.7</source>
<target>1.7</target>
</configuration>
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java
index 7ed3af5..a50c227 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/Provider.java
@@ -47,7 +47,10 @@ public class Provider {
private final Integer priority;
private final String className;
+ private final Class<? extends LoggerContextFactory> loggerContextFactoryClass;
private final String threadContextMap;
+ private final Class<? extends ThreadContextMap> threadContextMapClass;
+ private final String versions;
private final URL url;
private final WeakReference<ClassLoader> classLoader;
@@ -58,6 +61,36 @@ public class Provider {
priority = weight == null ? DEFAULT_PRIORITY : Integer.valueOf(weight);
className = props.getProperty(LOGGER_CONTEXT_FACTORY);
threadContextMap = props.getProperty(THREAD_CONTEXT_MAP);
+ loggerContextFactoryClass = null;
+ threadContextMapClass = null;
+ versions = null;
+ }
+
+ public Provider(Integer priority, String versions,
+ Class<? extends LoggerContextFactory> loggerContextFactoryClass) {
+ this(priority, versions, loggerContextFactoryClass, null);
+ }
+
+
+ public Provider(Integer priority, String versions,
+ Class<? extends LoggerContextFactory> loggerContextFactoryClass,
+ Class<? extends ThreadContextMap> threadContextMapClass) {
+ this.url = null;
+ this.classLoader = null;
+ this.priority = priority;
+ this.loggerContextFactoryClass = loggerContextFactoryClass;
+ this.threadContextMapClass = threadContextMapClass;
+ this.className = null;
+ this.threadContextMap = null;
+ this.versions = versions;
+ }
+
+ /**
+ * Returns the Log4j API versions supported by the implementation.
+ * @return A String containing the Log4j versions supported.
+ */
+ public String getVersions() {
+ return versions;
}
/**
@@ -76,6 +109,9 @@ public class Provider {
* @return the class name of a LoggerContextFactory implementation
*/
public String getClassName() {
+ if (loggerContextFactoryClass != null) {
+ return loggerContextFactoryClass.getName();
+ }
return className;
}
@@ -85,6 +121,9 @@ public class Provider {
* @return the LoggerContextFactory implementation class or {@code null} if there was an error loading it
*/
public Class<? extends LoggerContextFactory> loadLoggerContextFactory() {
+ if (loggerContextFactoryClass != null) {
+ return loggerContextFactoryClass;
+ }
if (className == null) {
return null;
}
@@ -109,6 +148,9 @@ public class Provider {
* @return the class name of a ThreadContextMap implementation
*/
public String getThreadContextMap() {
+ if (threadContextMapClass != null) {
+ return threadContextMapClass.getName();
+ }
return threadContextMap;
}
@@ -118,6 +160,9 @@ public class Provider {
* @return the ThreadContextMap implementation class or {@code null} if there was an error loading it
*/
public Class<? extends ThreadContextMap> loadThreadContextMap() {
+ if (threadContextMapClass != null) {
+ return threadContextMapClass;
+ }
if (threadContextMap == null) {
return null;
}
@@ -147,24 +192,30 @@ public class Provider {
@Override
public String toString() {
- String result = "Provider[";
+ StringBuilder result = new StringBuilder("Provider[");
if (!DEFAULT_PRIORITY.equals(priority)) {
- result += "priority=" + priority + ", ";
+ result.append("priority=").append(priority).append(", ");
}
if (threadContextMap != null) {
- result += "threadContextMap=" + threadContextMap + ", ";
+ result.append("threadContextMap=").append(threadContextMap).append(", ");
+ } else if (threadContextMapClass != null) {
+ result.append("threadContextMapClass=").append(threadContextMapClass.getName());
}
if (className != null) {
- result += "className=" + className + ", ";
+ result.append("className=").append(className).append(", ");
+ } else if (loggerContextFactoryClass != null) {
+ result.append("class=").append(loggerContextFactoryClass.getName());
}
- result += "url=" + url;
- final ClassLoader loader = classLoader.get();
- if (loader == null) {
- result += ", classLoader=null(not reachable)";
+ if (url != null) {
+ result.append("url=").append(url);
+ }
+ final ClassLoader loader;
+ if (classLoader == null || (loader = classLoader.get()) == null) {
+ result.append(", classLoader=null(not reachable)");
} else {
- result += ", classLoader=" + loader;
+ result.append(", classLoader=").append(loader);
}
- result += "]";
- return result;
+ result.append("]");
+ return result.toString();
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java/org/apache/logging/log4j/util/Activator.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Activator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/Activator.java
index bcf3bc4..f35ace8 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/Activator.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Activator.java
@@ -16,6 +16,7 @@
*/
package org.apache.logging.log4j.util;
+import javax.annotation.processing.ProcessingEnvironment;
import java.net.URL;
import java.security.Permission;
import java.util.List;
@@ -72,6 +73,7 @@ public class Activator implements BundleActivator, SynchronousBundleListener {
}
private void loadProvider(final BundleWiring provider) {
+ ProviderUtil.loadProviders(provider.getClassLoader());
final List<URL> urls = provider.findEntries("META-INF", "log4j-provider.properties", 0);
for (final URL url : urls) {
ProviderUtil.loadProvider(url, provider.getClassLoader());
@@ -83,7 +85,7 @@ public class Activator implements BundleActivator, SynchronousBundleListener {
ProviderUtil.STARTUP_LOCK.lock();
lockingProviderUtil = true;
final BundleWiring self = context.getBundle().adapt(BundleWiring.class);
- final List<BundleWire> required = self.getRequiredWires(LoggerContextFactory.class.getName());
+ List<BundleWire> required = self.getRequiredWires(LoggerContextFactory.class.getName());
for (final BundleWire wire : required) {
loadProvider(wire.getProviderWiring());
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassNamePredicate.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassNamePredicate.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassNamePredicate.java
deleted file mode 100644
index 063e538..0000000
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassNamePredicate.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.util;
-
-import java.util.function.Predicate;
-
-/**
- * <em>This class should be considered to be internal.</em> Used to locate the StackFrame that called the named class.
- */
-public final class ClassNamePredicate implements Predicate<StackWalker.StackFrame> {
-
- private final String fqcn;
-
- public ClassNamePredicate(String fqcn) {
- this.fqcn = fqcn;
- }
-
- private boolean next = false;
-
- @Override
- public boolean test(StackWalker.StackFrame f) {
- if (fqcn.equals(f.getClassName())) {
- next = true;
- return false;
- } else if (next) {
- next = false;
- return true;
- }
- return false;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassPredicate.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassPredicate.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassPredicate.java
deleted file mode 100644
index 3f8d15a..0000000
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ClassPredicate.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.util;
-
-import java.util.function.Predicate;
-
-/**
- * <em>This class should be considered to be internal.</em> Used to locate the StackFrame that called the named class.
- */
-
-public final class ClassPredicate implements Predicate<StackWalker.StackFrame> {
-
- private final Class<?> clazz;
-
- public ClassPredicate(Class<?> clazz) {
- this.clazz = clazz;
- }
-
- private boolean next = false;
-
- @Override
- public boolean test(StackWalker.StackFrame f) {
- if (clazz.equals(f.getDeclaringClass())) {
- next = true;
- return false;
- } else if (next) {
- next = false;
- return true;
- }
- return false;
- }
-}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
index 498bda9..b5be525 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
@@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
+import java.util.ServiceLoader;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -62,6 +63,7 @@ public final class ProviderUtil {
private static volatile ProviderUtil instance;
private ProviderUtil() {
+ loadProviders(findClassLoader());
for (final LoaderUtil.UrlResource resource : LoaderUtil.findUrlResources(PROVIDER_RESOURCE)) {
loadProvider(resource.getUrl(), resource.getClassLoader());
}
@@ -87,6 +89,15 @@ public final class ProviderUtil {
}
}
+ protected static void loadProviders(final ClassLoader cl) {
+ ServiceLoader<Provider> serviceLoader = ServiceLoader.load(Provider.class, cl);
+ for (Provider provider : serviceLoader) {
+ if (validVersion(provider.getVersions())) {
+ PROVIDERS.add(provider);
+ }
+ }
+ }
+
/**
* @deprecated Use {@link #loadProvider(java.net.URL, ClassLoader)} instead. Will be removed in 3.0.
*/
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java/org/apache/logging/log4j/util/StackWalkerStackLocator.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackWalkerStackLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackWalkerStackLocator.java
deleted file mode 100644
index dc10fef..0000000
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackWalkerStackLocator.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.util;
-
-import java.util.List;
-import java.util.Stack;
-import java.util.stream.Collectors;
-
-/**
- * <em>Consider this class private.</em> Determines the caller's class.
- */
-public class StackWalkerStackLocator implements StackLocator {
-
- private final static StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
-
- private final static StackWalker stackWalker = StackWalker.getInstance();
-
- public Class<?> getCallerClass(final String fqcn) {
- return getCallerClass(fqcn, "");
- }
-
- public Class<?> getCallerClass(final String fqcn, final String pkg) {
- return walker.walk(s -> s.filter(new ClassNamePredicate(fqcn)).findFirst()).get().getDeclaringClass();
- }
-
- public Class<?> getCallerClass(final Class<?> anchor) {
- return walker.walk(s -> s.filter(new ClassPredicate(anchor)).findFirst()).get().getDeclaringClass();
- }
-
- public Class<?> getCallerClass(final int depth) {
- ;
- return walker.walk(s -> s.skip(depth).findFirst()).get().getDeclaringClass();
- }
-
- public Stack<Class<?>> getCurrentStackTrace() {
- Stack<Class<?>> stack = new Stack<Class<?>>();
- List<Class<?>> classes = walker.walk(s -> s.map(f -> f.getDeclaringClass()).collect(Collectors.toList()));
- stack.addAll(classes);
- return stack;
- }
-
- public StackTraceElement calcLocation(final String fqcnOfLogger) {
- return stackWalker.walk(s -> s.filter(new ClassNamePredicate(fqcnOfLogger)).findFirst()).get().toStackTraceElement();
- }
-
- public StackTraceElement getStackTraceElement(final int depth) {
- return stackWalker.walk(s -> s.skip(depth).findFirst()).get().toStackTraceElement();
- }
-}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassNamePredicate.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassNamePredicate.java b/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassNamePredicate.java
new file mode 100644
index 0000000..063e538
--- /dev/null
+++ b/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassNamePredicate.java
@@ -0,0 +1,45 @@
+/*
+ * 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.util;
+
+import java.util.function.Predicate;
+
+/**
+ * <em>This class should be considered to be internal.</em> Used to locate the StackFrame that called the named class.
+ */
+public final class ClassNamePredicate implements Predicate<StackWalker.StackFrame> {
+
+ private final String fqcn;
+
+ public ClassNamePredicate(String fqcn) {
+ this.fqcn = fqcn;
+ }
+
+ private boolean next = false;
+
+ @Override
+ public boolean test(StackWalker.StackFrame f) {
+ if (fqcn.equals(f.getClassName())) {
+ next = true;
+ return false;
+ } else if (next) {
+ next = false;
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassPredicate.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassPredicate.java b/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassPredicate.java
new file mode 100644
index 0000000..3f8d15a
--- /dev/null
+++ b/log4j-api/src/main/java9/org/apache/logging/log4j/util/ClassPredicate.java
@@ -0,0 +1,46 @@
+/*
+ * 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.util;
+
+import java.util.function.Predicate;
+
+/**
+ * <em>This class should be considered to be internal.</em> Used to locate the StackFrame that called the named class.
+ */
+
+public final class ClassPredicate implements Predicate<StackWalker.StackFrame> {
+
+ private final Class<?> clazz;
+
+ public ClassPredicate(Class<?> clazz) {
+ this.clazz = clazz;
+ }
+
+ private boolean next = false;
+
+ @Override
+ public boolean test(StackWalker.StackFrame f) {
+ if (clazz.equals(f.getDeclaringClass())) {
+ next = true;
+ return false;
+ } else if (next) {
+ next = false;
+ return true;
+ }
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/main/java9/org/apache/logging/log4j/util/StackWalkerStackLocator.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java9/org/apache/logging/log4j/util/StackWalkerStackLocator.java b/log4j-api/src/main/java9/org/apache/logging/log4j/util/StackWalkerStackLocator.java
new file mode 100644
index 0000000..dc10fef
--- /dev/null
+++ b/log4j-api/src/main/java9/org/apache/logging/log4j/util/StackWalkerStackLocator.java
@@ -0,0 +1,63 @@
+/*
+ * 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.util;
+
+import java.util.List;
+import java.util.Stack;
+import java.util.stream.Collectors;
+
+/**
+ * <em>Consider this class private.</em> Determines the caller's class.
+ */
+public class StackWalkerStackLocator implements StackLocator {
+
+ private final static StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+
+ private final static StackWalker stackWalker = StackWalker.getInstance();
+
+ public Class<?> getCallerClass(final String fqcn) {
+ return getCallerClass(fqcn, "");
+ }
+
+ public Class<?> getCallerClass(final String fqcn, final String pkg) {
+ return walker.walk(s -> s.filter(new ClassNamePredicate(fqcn)).findFirst()).get().getDeclaringClass();
+ }
+
+ public Class<?> getCallerClass(final Class<?> anchor) {
+ return walker.walk(s -> s.filter(new ClassPredicate(anchor)).findFirst()).get().getDeclaringClass();
+ }
+
+ public Class<?> getCallerClass(final int depth) {
+ ;
+ return walker.walk(s -> s.skip(depth).findFirst()).get().getDeclaringClass();
+ }
+
+ public Stack<Class<?>> getCurrentStackTrace() {
+ Stack<Class<?>> stack = new Stack<Class<?>>();
+ List<Class<?>> classes = walker.walk(s -> s.map(f -> f.getDeclaringClass()).collect(Collectors.toList()));
+ stack.addAll(classes);
+ return stack;
+ }
+
+ public StackTraceElement calcLocation(final String fqcnOfLogger) {
+ return stackWalker.walk(s -> s.filter(new ClassNamePredicate(fqcnOfLogger)).findFirst()).get().toStackTraceElement();
+ }
+
+ public StackTraceElement getStackTraceElement(final int depth) {
+ return stackWalker.walk(s -> s.skip(depth).findFirst()).get().toStackTraceElement();
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/test/java/org/apache/logging/log4j/TestProvider.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/TestProvider.java b/log4j-api/src/test/java/org/apache/logging/log4j/TestProvider.java
new file mode 100644
index 0000000..f96181a
--- /dev/null
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/TestProvider.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+import org.apache.logging.log4j.spi.Provider;
+
+/**
+ * Binding for the Log4j API.
+ */
+public class TestProvider extends Provider {
+ public TestProvider() {
+ super(0, "2.6.0", TestLoggerContextFactory.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/test/resources/META-INF/log4j-provider.properties
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/resources/META-INF/log4j-provider.properties b/log4j-api/src/test/resources/META-INF/log4j-provider.properties
deleted file mode 100644
index 36fc6d6..0000000
--- a/log4j-api/src/test/resources/META-INF/log4j-provider.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-LoggerContextFactory = org.apache.logging.log4j.TestLoggerContextFactory
-Log4jAPIVersion = 2.6.0
-FactoryPriority = 0
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-api/src/test/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/resources/META-INF/services/org.apache.logging.log4j.spi.Provider b/log4j-api/src/test/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
new file mode 100644
index 0000000..5ae649a
--- /dev/null
+++ b/log4j-api/src/test/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
@@ -0,0 +1 @@
+org.apache.logging.log4j.TestProvider
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jProvider.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jProvider.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jProvider.java
new file mode 100644
index 0000000..499fb45
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.impl;
+
+import org.apache.logging.log4j.spi.Provider;
+
+/**
+ * Binding for the Log4j API.
+ */
+public class Log4jProvider extends Provider {
+ public Log4jProvider() {
+ super(10, "2.6.0", Log4jContextFactory.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-core/src/main/resources/META-INF/log4j-provider.properties
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/resources/META-INF/log4j-provider.properties b/log4j-core/src/main/resources/META-INF/log4j-provider.properties
deleted file mode 100644
index 2335e85..0000000
--- a/log4j-core/src/main/resources/META-INF/log4j-provider.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-LoggerContextFactory = org.apache.logging.log4j.core.impl.Log4jContextFactory
-Log4jAPIVersion = 2.6.0
-FactoryPriority= 10
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-core/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider b/log4j-core/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
new file mode 100644
index 0000000..c4c6c6c
--- /dev/null
+++ b/log4j-core/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
@@ -0,0 +1 @@
+org.apache.logging.log4j.core.impl.Log4jProvider
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderNoLocationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderNoLocationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderNoLocationTest.java
index ba7da83..17865a8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderNoLocationTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/AsyncAppenderNoLocationTest.java
@@ -36,11 +36,26 @@ public class AsyncAppenderNoLocationTest {
private ListAppender app;
@ClassRule
- public static LoggerContextRule init = new LoggerContextRule("log4j-asynch-no-location.xml");
+ public static LoggerContextRule init = null;
+
+ static {
+ try {
+ init = new LoggerContextRule("log4j-asynch-no-location.xml");
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
@Before
public void setUp() throws Exception {
- this.app = (ListAppender) init.getAppender("List");
+ try {
+ this.app = (ListAppender) init.getAppender("List");
+ assertNotNull("No List appender found", app);
+ } catch (Exception ex) {
+ System.out.println("init = " + init == null ? "null" : init);
+
+ }
+
}
@After
@@ -56,6 +71,7 @@ public class AsyncAppenderNoLocationTest {
logger.error("This is a test");
logger.warn("Hello world!");
Thread.sleep(100);
+ System.out.println("app = " + app == null ? "null" : app);
final List<String> list = app.getMessages();
assertNotNull("No events generated", list);
assertEquals("Incorrect number of events. Expected 2, got " + list.size(), list.size(), 2);
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java
----------------------------------------------------------------------
diff --git a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java
new file mode 100644
index 0000000..979d5e9
--- /dev/null
+++ b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java
@@ -0,0 +1,28 @@
+/*
+ * 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.slf4j;
+
+import org.apache.logging.log4j.spi.Provider;
+
+/**
+ * Bind the Log4j API to SLF4J.
+ */
+public class SLF4JProvider extends Provider {
+ public SLF4JProvider() {
+ super(15, "2.6.0", SLF4JLoggerContextFactory.class, MDCContextMap.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-to-slf4j/src/main/resources/META-INF/log4j-provider.properties
----------------------------------------------------------------------
diff --git a/log4j-to-slf4j/src/main/resources/META-INF/log4j-provider.properties b/log4j-to-slf4j/src/main/resources/META-INF/log4j-provider.properties
deleted file mode 100644
index f213cc2..0000000
--- a/log4j-to-slf4j/src/main/resources/META-INF/log4j-provider.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-LoggerContextFactory = org.apache.logging.slf4j.SLF4JLoggerContextFactory
-Log4jAPIVersion = 2.6.0
-FactoryPriority= 15
-ThreadContextMap = org.apache.logging.slf4j.MDCContextMap
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/log4j-to-slf4j/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
----------------------------------------------------------------------
diff --git a/log4j-to-slf4j/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider b/log4j-to-slf4j/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
new file mode 100644
index 0000000..c66b5c9
--- /dev/null
+++ b/log4j-to-slf4j/src/main/resources/META-INF/services/org.apache.logging.log4j.spi.Provider
@@ -0,0 +1 @@
+org.apache.logging.slf4j.SLF4JProvider
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 9681eb4..db263d1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
- "remove" - Removed
-->
<release version="2.9.0" date="2017-MM-DD" description="GA Release 2.9.0">
+ <action issue="LOG4J2-1917" dev="rgoers" type="update">
+ Support using java.util.ServiceLoader to locate Log4j 2 API providers.
+ </action>
<action issue="LOG4J2-1854" dev="mikes" type="add" due-to="Xavier Jodoin">
Support null byte delimiter in GelfLayout.
</action>
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/92e4b875/src/site/xdoc/manual/extending.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/extending.xml b/src/site/xdoc/manual/extending.xml
index 357bb67..4362cfb 100644
--- a/src/site/xdoc/manual/extending.xml
+++ b/src/site/xdoc/manual/extending.xml
@@ -33,25 +33,34 @@
<subsection name="LoggerContextFactory">
<p>
The <code>LoggerContextFactory</code> binds the Log4j API to its implementation. The Log4j
- <code>LogManager</code> locates a <code>LoggerContextFactory</code> by locating all instances of
- <code>META-INF/log4j-provider.properties</code>, a standard <code>java.util.Properties</code> file,
- and then inspecting each to verify that it specifies a value for the <var>Log4jAPIVersion</var> property
- that conforms to the version required by the <code>LogManager</code>. If more than one valid
- implementation is located the value for <var>FactoryPriority</var> will be used to identify the factory
- with the highest priority. Finally, the value of the <var>LoggerContextFactory</var> property will be
- used to locate the <code>LoggerContextFactory</code>. In Log4j 2 this is provided by
- <code>Log4jContextFactory</code>.
+ <code>LogManager</code> locates a <code>LoggerContextFactory</code> by using java.util.ServiceLoader
+ to locate all instances of <code>org.apache.logging.log4j.spi.Provider</code>. Each implementation must
+ provide a class that extends<code>org.apache.logging.log4j.spi.Provider</code> and should have a
+ no-arg constructor that delegates to Provider's constructor passing the <var>Priority</var>,
+ the API versions it is compatible with, and the class that implements
+ <code>org.apache.logging.log4j.spi.LoggerContextFactory</code>. Log4j will compare the current API
+ version and if it is compatible the implementation will be added to the list of providers. The
+ API version in <code>org.apache.logging.log4j.LogManager</code> is only changed when a feature is added
+ to the API that implementations need to be aware of. If more than one valid implementation is located
+ the value for the <var>Priority</var> will be used to identify the factory with the highest priority.
+ Finally, the class that implements <code>org.apache.logging.log4j.spi.LoggerContextFactory</code> will be
+ instantiated and bound to the LogManager. In Log4j 2 this is provided by <code>Log4jContextFactory</code>.
</p>
<p>
Applications may change the LoggerContextFactory that will be used by
</p>
<ol>
- <li>Implementing a new <code>LoggerContextFactory</code> and creating a <code>log4j-provider.properties</code>
- to reference it making sure that it has the highest priority.
- </li>
- <li>Create a new <code>log4j-provider.xml</code> and configure it with the desired
- <code>LoggerContextFactory</code> making sure that it has the highest priority.
- </li>
+ <li>Create a binding to the logging implementation.
+ <ol style="list-style-type: lower-alpha">
+ <li>Implement a new <code>LoggerContextFactory</code>.</li>
+ <li>Implement a class that extends <code>org.apache.logging.spi.Provider.</code> with a no-arg
+ constructor that calls super-class's constructor with the <var>Priority</var>, the API version(s),
+ <code>LoggerContextFactory</code> class, and optinall, a <code>ThreadContextMap</code>
+ implementation class.</li>
+ <li>Create a <code>META-INF/services/org.apache.logging.spi.Provider</code> file that contains the
+ name of the class that implements <code>org.apache.logging.spi.Provider</code>.
+ </li>
+ </ol></li>
<li>Setting the system property <var>log4j2.loggerContextFactory</var> to the name of the
<code>LoggerContextFactory</code> class to use.
</li>