You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2023/10/01 22:38:57 UTC
[logging-log4j2] branch main updated (675fa46629 -> 589dcdaabf)
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
from 675fa46629 Clean up some warnings
new 9f88fe5884 Clean up more warnings
new 78f728af51 Add some javadocs
new 589dcdaabf Clean up and better document LoaderUtil
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../log4j/config/PropertiesConfiguration.java | 2 +-
.../apache/logging/log4j/util/LoaderUtilTest.java | 4 +-
.../apache/logging/log4j/spi/LoggingSystem.java | 2 +-
.../java/org/apache/logging/log4j/util/Cast.java | 12 +
.../org/apache/logging/log4j/util/LoaderUtil.java | 425 +++++++++++++--------
.../apache/logging/log4j/util/PropertiesUtil.java | 14 +-
.../log4j/util/PropertyFilePropertySource.java | 14 +-
.../log4j/core/config/AbstractConfiguration.java | 7 +
.../logging/log4j/core/config/AppenderControl.java | 2 +-
.../log4j/core/config/ConfigurationSource.java | 14 +-
.../log4j/core/config/CronScheduledFuture.java | 10 +-
.../log4j/core/config/DefaultAdvertiser.java | 2 +-
.../log4j/core/net/UrlConnectionFactory.java | 4 +-
13 files changed, 313 insertions(+), 199 deletions(-)
[logging-log4j2] 01/03: Clean up more warnings
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 9f88fe588424a95b8add17cc844157f0b7c37f50
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sun Oct 1 14:29:02 2023 -0500
Clean up more warnings
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../apache/logging/log4j/core/config/AppenderControl.java | 2 +-
.../logging/log4j/core/config/ConfigurationSource.java | 14 +++-----------
.../logging/log4j/core/config/CronScheduledFuture.java | 10 +++++-----
.../logging/log4j/core/config/DefaultAdvertiser.java | 2 +-
.../logging/log4j/core/net/UrlConnectionFactory.java | 4 ++--
5 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java
index ccf85f291a..8a2b27eb8a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java
@@ -119,7 +119,7 @@ public class AppenderControl extends AbstractFilterable {
recursive.set(this);
callAppender0(event);
} finally {
- recursive.set(null);
+ recursive.remove();
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java
index 409faaae50..73ee81c508 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java
@@ -177,15 +177,15 @@ public class ConfigurationSource {
}
private boolean isFile() {
- return source == null ? false : source.getFile() != null;
+ return source != null && source.getFile() != null;
}
private boolean isURL() {
- return source == null ? false : source.getURI() != null;
+ return source != null && source.getURI() != null;
}
private boolean isLocation() {
- return source == null ? false : source.getLocation() != null;
+ return source != null && source.getLocation() != null;
}
/**
@@ -198,14 +198,6 @@ public class ConfigurationSource {
return source == null ? null : source.getURL();
}
- /**
- * @deprecated Not used internally, no replacement. TODO remove and make source final.
- */
- @Deprecated
- public void setSource(final Source source) {
- this.source = source;
- }
-
public void setData(final byte[] data) {
this.data = data;
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/CronScheduledFuture.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/CronScheduledFuture.java
index 63f060be64..a48b3fa7a8 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/CronScheduledFuture.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/CronScheduledFuture.java
@@ -23,6 +23,8 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.apache.logging.log4j.util.Cast;
+
/**
*
*/
@@ -68,19 +70,17 @@ public class CronScheduledFuture<V> implements ScheduledFuture<V> {
}
@Override
- @SuppressWarnings("unchecked")
public V get() throws InterruptedException, ExecutionException {
- return (V) futureData.scheduledFuture.get();
+ return Cast.cast(futureData.scheduledFuture.get());
}
@Override
- @SuppressWarnings("unchecked")
public V get(final long timeout, final TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
- return (V) futureData.scheduledFuture.get(timeout, unit);
+ return Cast.cast(futureData.scheduledFuture.get(timeout, unit));
}
- private class FutureData {
+ private static class FutureData {
private final ScheduledFuture<?> scheduledFuture;
private final Date runDate;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java
index 94951c2338..21e6ec99fb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultAdvertiser.java
@@ -41,7 +41,7 @@ public class DefaultAdvertiser implements Advertiser {
/**
* Does nothing.
- * @param advertisedObject
+ * @param advertisedObject ignored
*/
@Override
public void unadvertise(final Object advertisedObject) {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/UrlConnectionFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/UrlConnectionFactory.java
index c37315e784..79e3f5c00a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/UrlConnectionFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/UrlConnectionFactory.java
@@ -32,6 +32,7 @@ import org.apache.logging.log4j.core.net.ssl.LaxHostnameVerifier;
import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
import org.apache.logging.log4j.core.net.ssl.SslConfigurationFactory;
import org.apache.logging.log4j.core.util.AuthorizationProvider;
+import org.apache.logging.log4j.util.Cast;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.PropertyEnvironment;
import org.apache.logging.log4j.util.Strings;
@@ -57,7 +58,6 @@ public class UrlConnectionFactory {
private static final String NO_PROTOCOLS = "_none";
public static final String ALLOWED_PROTOCOLS = "log4j2.Configuration.allowedProtocols";
- @SuppressWarnings("unchecked")
public static <T extends URLConnection> T createConnection(final URL url, final long lastModifiedMillis,
final SslConfiguration sslConfiguration, final AuthorizationProvider authorizationProvider)
throws IOException {
@@ -110,7 +110,7 @@ public class UrlConnectionFactory {
} else {
urlConnection = url.openConnection();
}
- return (T) urlConnection;
+ return Cast.cast(urlConnection);
}
public static URLConnection createConnection(final URL url) throws IOException {
[logging-log4j2] 03/03: Clean up and better document LoaderUtil
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 589dcdaabf21a6da07d8979cc25ded5ed975d8b4
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sun Oct 1 17:38:44 2023 -0500
Clean up and better document LoaderUtil
This makes a few updates here. First, javadoc comments have been updated to properly document all the potential exceptions they throw. Next, unchecked exception variants of methods here have been created. Furthermore, use of SecurityManager has been overhauled to be more consistent. Finally, some unused functionality was removed.
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../log4j/config/PropertiesConfiguration.java | 2 +-
.../apache/logging/log4j/util/LoaderUtilTest.java | 4 +-
.../apache/logging/log4j/spi/LoggingSystem.java | 2 +-
.../org/apache/logging/log4j/util/LoaderUtil.java | 425 +++++++++++++--------
.../apache/logging/log4j/util/PropertiesUtil.java | 14 +-
.../log4j/util/PropertyFilePropertySource.java | 14 +-
6 files changed, 282 insertions(+), 179 deletions(-)
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
index eee359c47e..95ed6f578e 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
@@ -592,7 +592,7 @@ public class PropertiesConfiguration extends Log4j1Configuration {
private static <T> T newInstanceOf(final String className, final String type) {
try {
return LoaderUtil.newInstanceOf(className);
- } catch (ReflectiveOperationException ex) {
+ } catch (ReflectiveOperationException | LinkageError | RuntimeException ex) {
LOGGER.error("Unable to create {} {} due to {}:{}", type, className, ex.getClass().getSimpleName(), ex.getMessage(), ex);
return null;
}
diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilTest.java
index 59db7bf47e..5ae0bc64ae 100644
--- a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilTest.java
+++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/LoaderUtilTest.java
@@ -49,10 +49,10 @@ public class LoaderUtilTest {
};
thread.setContextClassLoader(loader);
try {
- assertEquals(0, LoaderUtil.findUrlResources("Log4j-charsets.properties", false).size());
+ assertEquals(0, LoaderUtil.findUrlResources("Log4j-charsets.properties").size());
LoaderUtil.forceTcclOnly = false;
- assertEquals(1, LoaderUtil.findUrlResources("Log4j-charsets.properties", false).size());
+ assertEquals(1, LoaderUtil.findUrlResources("Log4j-charsets.properties").size());
} finally {
thread.setContextClassLoader(tccl);
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java
index a85dfd514c..b6e3a93922 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggingSystem.java
@@ -221,7 +221,7 @@ public class LoggingSystem {
}
private static List<Provider> loadLegacyProviders() {
- return LoaderUtil.findUrlResources(PROVIDER_RESOURCE, false)
+ return LoaderUtil.findUrlResources(PROVIDER_RESOURCE)
.stream()
.map(urlResource -> loadLegacyProvider(urlResource.getUrl(), urlResource.getClassLoader()))
.filter(Objects::nonNull)
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
index 37c4de0784..7a405fdafc 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
@@ -17,6 +17,7 @@
package org.apache.logging.log4j.util;
import java.io.IOException;
+import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.security.AccessController;
@@ -41,26 +42,37 @@ public final class LoaderUtil {
private static final ClassLoader[] EMPTY_CLASS_LOADER_ARRAY = {};
- private static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
-
// this variable must be lazily loaded; otherwise, we get a nice circular class loading problem where LoaderUtil
// wants to use PropertiesUtil, but then PropertiesUtil wants to use LoaderUtil.
private static Boolean ignoreTCCL;
+ private static final RuntimePermission GET_CLASS_LOADER = new RuntimePermission("getClassLoader");
private static final boolean GET_CLASS_LOADER_DISABLED;
- protected static Boolean forceTcclOnly;
+ static Boolean forceTcclOnly;
private static final PrivilegedAction<ClassLoader> TCCL_GETTER = new ThreadContextClassLoaderGetter();
+ private static final PrivilegedAction<ClassLoader[]> CLASSLOADER_ACCUMULATOR = new ClassLoaderAccumulator();
static {
- if (SECURITY_MANAGER != null) {
+ if (System.getSecurityManager() != null) {
boolean getClassLoaderDisabled;
try {
- SECURITY_MANAGER.checkPermission(new RuntimePermission("getClassLoader"));
+ AccessController.checkPermission(GET_CLASS_LOADER);
+ // seems like we'll be ok
getClassLoaderDisabled = false;
} catch (final SecurityException ignored) {
- getClassLoaderDisabled = true;
+ try {
+ // let's see if we can obtain that permission
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ AccessController.checkPermission(GET_CLASS_LOADER);
+ return null;
+ }, null, GET_CLASS_LOADER);
+ getClassLoaderDisabled = false;
+ } catch (final SecurityException ignore) {
+ // no chance
+ getClassLoaderDisabled = true;
+ }
}
GET_CLASS_LOADER_DISABLED = getClassLoaderDisabled;
} else {
@@ -73,6 +85,7 @@ public final class LoaderUtil {
/**
* Returns the ClassLoader to use.
+ *
* @return the ClassLoader.
*/
public static ClassLoader getClassLoader() {
@@ -81,31 +94,18 @@ public final class LoaderUtil {
// TODO: this method could use some explanation
public static ClassLoader getClassLoader(final Class<?> class1, final Class<?> class2) {
- final ClassLoader threadContextClassLoader = getThreadContextClassLoader();
- final ClassLoader loader1 = class1 == null ? null : class1.getClassLoader();
- final ClassLoader loader2 = class2 == null ? null : class2.getClassLoader();
-
- if (isChild(threadContextClassLoader, loader1)) {
- return isChild(threadContextClassLoader, loader2) ? threadContextClassLoader : loader2;
- }
- return isChild(loader1, loader2) ? loader1 : loader2;
- }
-
- /**
- * Gets the current Thread ClassLoader. Returns the system ClassLoader if the TCCL is {@code null}. If the system
- * ClassLoader is {@code null} as well, then the ClassLoader for this class is returned. If running with a
- * {@link SecurityManager} that does not allow access to the Thread ClassLoader or system ClassLoader, then the
- * ClassLoader for this class is returned.
- *
- * @return the current ThreadContextClassLoader.
- */
- public static ClassLoader getThreadContextClassLoader() {
- if (GET_CLASS_LOADER_DISABLED) {
- // we can at least get this class's ClassLoader regardless of security context
- // however, if this is null, there's really no option left at this point
- return LoaderUtil.class.getClassLoader();
- }
- return SECURITY_MANAGER == null ? TCCL_GETTER.run() : AccessController.doPrivileged(TCCL_GETTER);
+ PrivilegedAction<ClassLoader> action = () -> {
+ final ClassLoader loader1 = class1 == null ? null : class1.getClassLoader();
+ final ClassLoader loader2 = class2 == null ? null : class2.getClassLoader();
+ final ClassLoader referenceLoader = GET_CLASS_LOADER_DISABLED
+ ? getThisClassLoader()
+ : Thread.currentThread().getContextClassLoader();
+ if (isChild(referenceLoader, loader1)) {
+ return isChild(referenceLoader, loader2) ? referenceLoader : loader2;
+ }
+ return isChild(loader1, loader2) ? loader1 : loader2;
+ };
+ return AccessController.doPrivileged(action, null, GET_CLASS_LOADER);
}
/**
@@ -129,66 +129,101 @@ public final class LoaderUtil {
}
/**
+ * Looks up the ClassLoader for this current thread. If this class does not have the runtime permission
+ * {@code getClassLoader}, then the only ClassLoader this attempts to look up is the loader behind this
+ * class. When a SecurityManager is installed, this attempts to make a privileged call to get the current
+ * {@linkplain Thread#getContextClassLoader() thread context ClassLoader}, falling back to either the
+ * ClassLoader of this class or the {@linkplain ClassLoader#getSystemClassLoader() system ClassLoader}.
+ * When no SecurityManager is present, the same lookups are performed without use of {@link AccessController}.
+ * If none of these strategies can obtain a ClassLoader, then this returns {@code null}.
*
+ * @return the current thread's ClassLoader, a fallback loader, or null if no fallback can be determined
*/
+ public static ClassLoader getThreadContextClassLoader() {
+ if (GET_CLASS_LOADER_DISABLED) {
+ // we can at least get this class's ClassLoader regardless of security context
+ // however, if this is null, there's really no option left at this point
+ try {
+ return getThisClassLoader();
+ } catch (final SecurityException ignored) {
+ return null;
+ }
+ }
+ return AccessController.doPrivileged(TCCL_GETTER, null, GET_CLASS_LOADER);
+ }
+
+ public static ClassLoader[] getClassLoaders() {
+ return AccessController.doPrivileged(CLASSLOADER_ACCUMULATOR, null, GET_CLASS_LOADER);
+ }
+
+ private static ClassLoader getThisClassLoader() {
+ return LoaderUtil.class.getClassLoader();
+ }
+
private static class ThreadContextClassLoaderGetter implements PrivilegedAction<ClassLoader> {
@Override
public ClassLoader run() {
- final ClassLoader cl = Thread.currentThread().getContextClassLoader();
- if (cl != null) {
- return cl;
+ final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (contextClassLoader != null) {
+ return contextClassLoader;
+ }
+ final ClassLoader thisClassLoader = getThisClassLoader();
+ if (thisClassLoader != null || GET_CLASS_LOADER_DISABLED) {
+ return thisClassLoader;
}
- final ClassLoader ccl = LoaderUtil.class.getClassLoader();
- return ccl == null && !GET_CLASS_LOADER_DISABLED ? ClassLoader.getSystemClassLoader() : ccl;
+ return ClassLoader.getSystemClassLoader();
}
}
- public static ClassLoader[] getClassLoaders() {
- final Collection<ClassLoader> classLoaders = new LinkedHashSet<>();
- final ClassLoader tcl = getThreadContextClassLoader();
- if (tcl != null) {
- classLoaders.add(tcl);
- }
- final ModuleLayer layer = LoaderUtil.class.getModule().getLayer();
- if (layer == null) {
- if (!isForceTccl()) {
- accumulateClassLoaders(LoaderUtil.class.getClassLoader(), classLoaders);
- accumulateClassLoaders(tcl == null ? null : tcl.getParent(), classLoaders);
- final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
- if (systemClassLoader != null) {
- classLoaders.add(systemClassLoader);
- }
+ private static class ClassLoaderAccumulator implements PrivilegedAction<ClassLoader[]> {
+ @Override
+ public ClassLoader[] run() {
+ final Collection<ClassLoader> classLoaders = new LinkedHashSet<>();
+ final ClassLoader tcl = TCCL_GETTER.run();
+ if (tcl != null) {
+ classLoaders.add(tcl);
}
- } else {
- accumulateLayerClassLoaders(layer, classLoaders);
- if (layer != ModuleLayer.boot()) {
- for (final Module module : ModuleLayer.boot().modules()) {
- accumulateClassLoaders(module.getClassLoader(), classLoaders);
+ final ModuleLayer layer = LoaderUtil.class.getModule().getLayer();
+ if (layer == null) {
+ if (!isForceTccl()) {
+ accumulateClassLoaders(getThisClassLoader(), classLoaders);
+ accumulateClassLoaders(tcl == null ? null : tcl.getParent(), classLoaders);
+ final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+ if (systemClassLoader != null) {
+ classLoaders.add(systemClassLoader);
+ }
+ }
+ } else {
+ accumulateLayerClassLoaders(layer, classLoaders);
+ if (layer != ModuleLayer.boot()) {
+ for (final Module module : ModuleLayer.boot().modules()) {
+ accumulateClassLoaders(module.getClassLoader(), classLoaders);
+ }
}
}
+ return classLoaders.toArray(EMPTY_CLASS_LOADER_ARRAY);
}
- return classLoaders.toArray(EMPTY_CLASS_LOADER_ARRAY);
- }
- private static void accumulateLayerClassLoaders(final ModuleLayer layer, final Collection<ClassLoader> classLoaders) {
- for (final Module module : layer.modules()) {
- accumulateClassLoaders(module.getClassLoader(), classLoaders);
- }
- if (layer.parents().size() > 0) {
- for (final ModuleLayer parent : layer.parents()) {
- accumulateLayerClassLoaders(parent, classLoaders);
+ private static void accumulateLayerClassLoaders(final ModuleLayer layer, final Collection<ClassLoader> classLoaders) {
+ for (final Module module : layer.modules()) {
+ accumulateClassLoaders(module.getClassLoader(), classLoaders);
+ }
+ if (!layer.parents().isEmpty()) {
+ for (final ModuleLayer parent : layer.parents()) {
+ accumulateLayerClassLoaders(parent, classLoaders);
+ }
}
}
- }
- /**
- * Adds the provided loader to the loaders collection, and traverses up the tree until either a null
- * value or a classloader which has already been added is encountered.
- */
- private static void accumulateClassLoaders(final ClassLoader loader, final Collection<ClassLoader> loaders) {
- // Some implementations may use null to represent the bootstrap class loader.
- if (loader != null && loaders.add(loader)) {
- accumulateClassLoaders(loader.getParent(), loaders);
+ /**
+ * Adds the provided loader to the loaders collection, and traverses up the tree until either a null
+ * value or a classloader which has already been added is encountered.
+ */
+ private static void accumulateClassLoaders(final ClassLoader loader, final Collection<ClassLoader> loaders) {
+ // Some implementations may use null to represent the bootstrap class loader.
+ if (loader != null && loaders.add(loader)) {
+ accumulateClassLoaders(loader.getParent(), loaders);
+ }
}
}
@@ -201,8 +236,8 @@ public final class LoaderUtil {
*/
public static boolean isClassAvailable(final String className) {
try {
- final Class<?> clazz = loadClass(className);
- return clazz != null;
+ loadClass(className);
+ return true;
} catch (final ClassNotFoundException | LinkageError e) {
return false;
} catch (final Throwable e) {
@@ -212,110 +247,192 @@ public final class LoaderUtil {
}
/**
- * Loads a class by name. This method respects the {@value LoggingSystemProperty#LOADER_IGNORE_THREAD_CONTEXT_LOADER}
- * Log4j property. If this property is specified and set to anything besides {@code false}, then this class's
- * ClassLoader will be used as specified by {@link Class#forName(String)}.
+ * Loads and initializes a class given its fully qualified class name. This method respects the
+ * {@link LoggingSystemProperty#LOADER_IGNORE_THREAD_CONTEXT_LOADER} Log4j property. If this property is specified
+ * and set to anything besides {@code false}, then this class's ClassLoader will be used.
*
- * @param className The class name.
- * @return the Class for the given name.
- * @throws ClassNotFoundException if the specified class name could not be found
+ * @param className fully qualified class name to load
+ * @return the loaded class
+ * @throws ClassNotFoundException if the specified class name could not be found
+ * @throws ExceptionInInitializerError if an exception is thrown during class initialization
+ * @throws LinkageError if the linkage of the class fails for any other reason
* @since 2.1
*/
public static Class<?> loadClass(final String className) throws ClassNotFoundException {
- if (isIgnoreTccl()) {
- return Class.forName(className);
+ ClassLoader classLoader = isIgnoreTccl() ? getThisClassLoader() : getThreadContextClassLoader();
+ if (classLoader == null) {
+ classLoader = getThisClassLoader();
}
+ return Class.forName(className, true, classLoader);
+ }
+
+ /**
+ * Loads and initializes a class given its fully qualified class name. All checked reflective operation
+ * exceptions are translated into equivalent {@link LinkageError} classes.
+ *
+ * @param className fully qualified class name to load
+ * @return the loaded class
+ * @throws NoClassDefFoundError if the specified class name could not be found
+ * @throws ExceptionInInitializerError if an exception is thrown during class initialization
+ * @throws LinkageError if the linkage of the class fails for any other reason
+ * @see #loadClass(String)
+ * @since 3.0.0
+ */
+ public static Class<?> loadClassUnchecked(final String className) {
try {
- final ClassLoader tccl = getThreadContextClassLoader();
- if (tccl != null) {
- return tccl.loadClass(className);
- }
- } catch (final Throwable ignored) {
+ return loadClass(className);
+ } catch (final ClassNotFoundException e) {
+ final NoClassDefFoundError error = new NoClassDefFoundError(e.getMessage());
+ error.initCause(e);
+ throw error;
}
- return Class.forName(className);
}
/**
* Loads and instantiates a Class using the default constructor.
*
- * @param <T> the type of the class modeled by the {@code Class} object.
+ * @param <T> the type of the class modeled by the {@code Class} object.
* @param clazz The class.
* @return new instance of the class.
- * @throws IllegalAccessException if the class can't be instantiated through a public constructor
- * @throws InstantiationException if there was an exception whilst instantiating the class
- * @throws InvocationTargetException if there was an exception whilst constructing the class
+ * @throws NoSuchMethodException if no zero-arg constructor exists
+ * @throws SecurityException if this class is not allowed to access declared members of the provided class
+ * @throws IllegalAccessException if the class can't be instantiated through a public constructor
+ * @throws InstantiationException if the provided class is abstract or an interface
+ * @throws InvocationTargetException if an exception is thrown by the constructor
+ * @throws ExceptionInInitializerError if an exception was thrown while initializing the class
* @since 2.7
*/
public static <T> T newInstanceOf(final Class<T> clazz)
- throws InstantiationException, IllegalAccessException, InvocationTargetException {
+ throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ final Constructor<T> constructor = clazz.getDeclaredConstructor();
+ return constructor.newInstance();
+ }
+
+ /**
+ * Creates an instance of the provided class using the default constructor. All checked reflective operation
+ * exceptions are translated into {@link LinkageError} or {@link InternalException}.
+ *
+ * @param clazz class to instantiate
+ * @param <T> the type of the object being instantiated
+ * @return instance of the class
+ * @throws NoSuchMethodError if no zero-arg constructor exists
+ * @throws SecurityException if this class is not allowed to access declared members of the provided class
+ * @throws InternalException if an exception is thrown by the constructor
+ * @throws InstantiationError if the provided class is abstract or an interface
+ * @throws IllegalAccessError if the class cannot be accessed
+ * @since 3.0.0
+ */
+ public static <T> T newInstanceOfUnchecked(final Class<T> clazz) {
try {
- return clazz.getConstructor().newInstance();
- } catch (final NoSuchMethodException ignored) {
- // FIXME: looking at the code for Class.newInstance(), this seems to do the same thing as above
- return clazz.newInstance();
+ return newInstanceOf(clazz);
+ } catch (final NoSuchMethodException e) {
+ final NoSuchMethodError error = new NoSuchMethodError(e.getMessage());
+ error.initCause(e);
+ throw error;
+ } catch (final InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ throw new InternalException(cause);
+ } catch (final InstantiationException e) {
+ final InstantiationError error = new InstantiationError(e.getMessage());
+ error.initCause(e);
+ throw error;
+ } catch (final IllegalAccessException e) {
+ final IllegalAccessError error = new IllegalAccessError(e.getMessage());
+ error.initCause(e);
+ throw error;
}
}
/**
* Loads and instantiates a Class using the default constructor.
*
- * @param className The class name.
- * @param <T> The class's type.
- * @return new instance of the class.
- * @throws ClassNotFoundException if the class isn't available to the usual ClassLoaders
- * @throws IllegalAccessException if the class can't be instantiated through a public constructor
- * @throws InstantiationException if there was an exception whilst instantiating the class
- * @throws InvocationTargetException if there was an exception whilst constructing the class
+ * @param className fully qualified class name to load, initialize, and construct
+ * @param <T> type the class must be compatible with
+ * @return new instance of the class
+ * @throws ClassNotFoundException if the class isn't available to the usual ClassLoaders
+ * @throws ExceptionInInitializerError if an exception was thrown while initializing the class
+ * @throws LinkageError if the linkage of the class fails for any other reason
+ * @throws ClassCastException if the class is not compatible with the generic type parameter provided
+ * @throws NoSuchMethodException if no zero-arg constructor exists
+ * @throws SecurityException if this class is not allowed to access declared members of the provided class
+ * @throws IllegalAccessException if the class can't be instantiated through a public constructor
+ * @throws InstantiationException if the provided class is abstract or an interface
+ * @throws InvocationTargetException if an exception is thrown by the constructor
* @since 2.1
*/
- @SuppressWarnings("unchecked")
public static <T> T newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException,
- InstantiationException, InvocationTargetException {
- return newInstanceOf((Class<T>) loadClass(className));
+ InstantiationException, InvocationTargetException, NoSuchMethodException {
+ final Class<T> clazz = Cast.cast(loadClass(className));
+ return newInstanceOf(clazz);
+ }
+
+ /**
+ * Loads and instantiates a class by name using its default constructor. All checked reflective operation
+ * exceptions are translated into corresponding {@link LinkageError} classes.
+ *
+ * @param className fully qualified class name to load, initialize, and construct
+ * @param <T> type the class must be compatible with
+ * @return new instance of the class
+ * @throws NoClassDefFoundError if the specified class name could not be found
+ * @throws ExceptionInInitializerError if an exception is thrown during class initialization
+ * @throws ClassCastException if the class is not compatible with the generic type parameter provided
+ * @throws NoSuchMethodError if no zero-arg constructor exists
+ * @throws SecurityException if this class is not allowed to access declared members of the provided class
+ * @throws InternalException if an exception is thrown by the constructor
+ * @throws InstantiationError if the provided class is abstract or an interface
+ * @throws IllegalAccessError if the class cannot be accessed
+ * @throws LinkageError if the linkage of the class fails for any other reason
+ */
+ public static <T> T newInstanceOfUnchecked(final String className) {
+ final Class<T> clazz = Cast.cast(loadClassUnchecked(className));
+ return newInstanceOfUnchecked(clazz);
}
/**
* Loads and instantiates a derived class using its default constructor.
*
* @param className The class name.
- * @param clazz The class to cast it to.
- * @param <T> The type of the class to check.
+ * @param clazz The class to cast it to.
+ * @param <T> The type of the class to check.
* @return new instance of the class cast to {@code T}
- * @throws ClassNotFoundException if the class isn't available to the usual ClassLoaders
- * @throws IllegalAccessException if the class can't be instantiated through a public constructor
- * @throws InstantiationException if there was an exception whilst instantiating the class
- * @throws InvocationTargetException if there was an exception whilst constructing the class
- * @throws ClassCastException if the constructed object isn't type compatible with {@code T}
+ * @throws ClassNotFoundException if the class isn't available to the usual ClassLoaders
+ * @throws ExceptionInInitializerError if an exception is thrown during class initialization
+ * @throws LinkageError if the linkage of the class fails for any other reason
+ * @throws ClassCastException if the constructed object isn't type compatible with {@code T}
+ * @throws NoSuchMethodException if no zero-arg constructor exists
+ * @throws SecurityException if this class is not allowed to access declared members of the provided class
+ * @throws IllegalAccessException if the class can't be instantiated through a public constructor
+ * @throws InstantiationException if the provided class is abstract or an interface
+ * @throws InvocationTargetException if there was an exception whilst constructing the class
* @since 2.1
*/
- public static <T> T newCheckedInstanceOf(final String className, final Class<T> clazz)
- throws ClassNotFoundException, InvocationTargetException, InstantiationException,
- IllegalAccessException {
+ public static <T> T newCheckedInstanceOf(final String className, final Class<T> clazz) throws ClassNotFoundException,
+ InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
return newInstanceOf(loadClass(className).asSubclass(clazz));
}
/**
- * Loads and instantiates a class given by a property name.
+ * Loads the provided class by name as a checked subtype of the given class. All checked reflective operation
+ * exceptions are translated into corresponding {@link LinkageError} classes.
*
- * @param propertyName The property name to look up a class name for.
- * @param clazz The class to cast it to.
- * @param <T> The type to cast it to.
- * @return new instance of the class given in the property or {@code null} if the property was unset.
- * @throws ClassNotFoundException if the class isn't available to the usual ClassLoaders
- * @throws IllegalAccessException if the class can't be instantiated through a public constructor
- * @throws InstantiationException if there was an exception whilst instantiating the class
- * @throws InvocationTargetException if there was an exception whilst constructing the class
- * @throws ClassCastException if the constructed object isn't type compatible with {@code T}
- * @since 2.5
+ * @param className fully qualified class name to load
+ * @param supertype supertype of the class being loaded
+ * @param <T> type of instance to return
+ * @return new instance of the requested class
+ * @throws NoClassDefFoundError if the provided class name could not be found
+ * @throws ExceptionInInitializerError if an exception is thrown during class initialization
+ * @throws ClassCastException if the loaded class is not a subtype of the provided class
+ * @throws NoSuchMethodError if no zero-arg constructor exists
+ * @throws SecurityException if this class is not allowed to access declared members of the provided class
+ * @throws InternalException if an exception is thrown by the constructor
+ * @throws InstantiationError if the provided class is abstract or an interface
+ * @throws IllegalAccessError if the class cannot be accessed
+ * @throws LinkageError if the linkage of the class fails for any other reason
+ * @since 3.0.0
*/
- public static <T> T newCheckedInstanceOfProperty(final String propertyName, final Class<T> clazz)
- throws ClassNotFoundException, InvocationTargetException, InstantiationException,
- IllegalAccessException {
- final String className = PropertiesUtil.getProperties().getStringProperty(propertyName);
- if (className == null) {
- return null;
- }
- return newCheckedInstanceOf(className, clazz);
+ public static <T> T newInstanceOfUnchecked(final String className, final Class<T> supertype) {
+ final Class<? extends T> clazz = loadClassUnchecked(className).asSubclass(supertype);
+ return newInstanceOfUnchecked(clazz);
}
private static boolean isIgnoreTccl() {
@@ -330,11 +447,13 @@ public final class LoaderUtil {
private static boolean isForceTccl() {
if (forceTcclOnly == null) {
// PropertiesUtil.getProperties() uses that code path so don't use that!
+ final String key = LoggingSystemProperty.LOADER_FORCE_THREAD_CONTEXT_LOADER.getSystemKey();
+ final SecurityManager securityManager = System.getSecurityManager();
try {
- forceTcclOnly = System.getSecurityManager() == null ?
- Boolean.getBoolean(LoggingSystemProperty.LOADER_FORCE_THREAD_CONTEXT_LOADER.getSystemKey()) :
- AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean(
- LoggingSystemProperty.LOADER_FORCE_THREAD_CONTEXT_LOADER.getSystemKey()));
+ if (securityManager != null) {
+ securityManager.checkPropertyAccess(key);
+ }
+ forceTcclOnly = Boolean.getBoolean(key);
} catch (final SecurityException se) {
forceTcclOnly = false;
}
@@ -350,11 +469,7 @@ public final class LoaderUtil {
* @since 2.1
*/
public static Collection<URL> findResources(final String resource) {
- return findResources(resource, true);
- }
-
- public static Collection<URL> findResources(final String resource, final boolean useTccl) {
- final Collection<UrlResource> urlResources = findUrlResources(resource, useTccl);
+ final Collection<UrlResource> urlResources = findUrlResources(resource);
final Collection<URL> resources = new LinkedHashSet<>(urlResources.size());
for (final UrlResource urlResource : urlResources) {
resources.add(urlResource.getUrl());
@@ -366,18 +481,13 @@ public final class LoaderUtil {
* This method will only find resources that follow the JPMS rules for encapsulation. Resources
* on the class path should be found as normal along with resources with no package name in all
* modules. Resources within packages in modules must declare those resources open to org.apache.logging.log4j.
+ *
* @param resource The resource to locate.
* @return The located resources.
*/
- public static Collection<UrlResource> findUrlResources(final String resource, final boolean useTccl) {
- // @formatter:off
- final ClassLoader[] candidates = {
- getThreadContextClassLoader(),
- isForceTccl() ? null : LoaderUtil.class.getClassLoader(),
- isForceTccl() || GET_CLASS_LOADER_DISABLED ? null : ClassLoader.getSystemClassLoader()};
- // @formatter:on
+ public static Collection<UrlResource> findUrlResources(final String resource) {
final Collection<UrlResource> resources = new LinkedHashSet<>();
- for (final ClassLoader cl : candidates) {
+ for (final ClassLoader cl : getClassLoaders()) {
if (cl != null) {
try {
final Enumeration<URL> resourceEnum = cl.getResources(resource);
@@ -423,10 +533,7 @@ public final class LoaderUtil {
final UrlResource that = (UrlResource) o;
- if (classLoader != null ? !classLoader.equals(that.classLoader) : that.classLoader != null) {
- return false;
- }
- return url != null ? url.equals(that.url) : that.url == null;
+ return Objects.equals(classLoader, that.classLoader) && Objects.equals(url, that.url);
}
@Override
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
index e777f03ef0..58077430f4 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
@@ -112,12 +112,12 @@ public class PropertiesUtil implements PropertyEnvironment {
private PropertiesUtil(final String contextName, final String propertiesFileName, final boolean useTccl) {
final List<PropertySource> sources = new ArrayList<>();
if (propertiesFileName.endsWith(".json") || propertiesFileName.endsWith(".jsn")) {
- final PropertySource source = getJsonPropertySource(propertiesFileName, useTccl, 50);
+ final PropertySource source = getJsonPropertySource(propertiesFileName, 50);
if (source != null) {
sources.add(source);
}
} else {
- final PropertySource source = new PropertiesPropertySource(PropertyFilePropertySource.loadPropertiesFile(propertiesFileName, useTccl),
+ final PropertySource source = new PropertiesPropertySource(PropertyFilePropertySource.loadPropertiesFile(propertiesFileName),
null, 60, true);
sources.add(source);
}
@@ -173,10 +173,10 @@ public class PropertiesUtil implements PropertyEnvironment {
private static Environment getEnvironment(final String namespace, final boolean useTccl) {
final List<PropertySource> sources = new ArrayList<>();
final String fileName = String.format("log4j2.%s.properties", namespace);
- final Properties properties = PropertyFilePropertySource.loadPropertiesFile(fileName, useTccl);
+ final Properties properties = PropertyFilePropertySource.loadPropertiesFile(fileName);
PropertySource source = new PropertiesPropertySource(properties, 50);
sources.add(source);
- source = getJsonPropertySource(String.format("log4j2.%s.json", namespace), useTccl, 60);
+ source = getJsonPropertySource(String.format("log4j2.%s.json", namespace), 60);
if (source != null) {
sources.add(source);
}
@@ -344,7 +344,7 @@ public class PropertiesUtil implements PropertyEnvironment {
return sources;
}
- private static PropertySource getJsonPropertySource(final String fileName, final boolean useTccl, int priority) {
+ private static PropertySource getJsonPropertySource(final String fileName, int priority) {
if (fileName.startsWith("file://")) {
try {
final URL url = new URL(fileName);
@@ -365,7 +365,7 @@ public class PropertiesUtil implements PropertyEnvironment {
LowLevelLogUtil.logException("Unable to read " + fileName, ioe);
}
} else {
- for (final URL url : LoaderUtil.findResources(fileName, useTccl)) {
+ for (final URL url : LoaderUtil.findResources(fileName)) {
try (final InputStream in = url.openStream()) {
return parseJsonProperties(new String(in.readAllBytes(),
StandardCharsets.UTF_8), PropertySource.SYSTEM_CONTEXT, priority);
@@ -440,7 +440,7 @@ public class PropertiesUtil implements PropertyEnvironment {
private Environment(final String contextName, final List<PropertySource> propertySources) {
try {
- final Properties sysProps = PropertyFilePropertySource.loadPropertiesFile(LOG4J_SYSTEM_PROPERTIES_FILE_NAME, false);
+ final Properties sysProps = PropertyFilePropertySource.loadPropertiesFile(LOG4J_SYSTEM_PROPERTIES_FILE_NAME);
for (String key : sysProps.stringPropertyNames()) {
if (System.getProperty(key) == null) {
System.setProperty(key, sysProps.getProperty(key));
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyFilePropertySource.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyFilePropertySource.java
index dd08cf5d9d..7c10d4eee2 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyFilePropertySource.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertyFilePropertySource.java
@@ -29,20 +29,16 @@ import java.util.Properties;
public class PropertyFilePropertySource extends PropertiesPropertySource {
public PropertyFilePropertySource(final String fileName) {
- this(fileName, true, false);
+ this(fileName, false);
}
- public PropertyFilePropertySource(final String fileName, final boolean useTccl) {
- this(fileName, useTccl, false);
+ public PropertyFilePropertySource(final String fileName, final boolean includeInvalid) {
+ super(loadPropertiesFile(fileName), SYSTEM_CONTEXT, 20, includeInvalid);
}
- public PropertyFilePropertySource(final String fileName, final boolean useTccl, final boolean includeInvalid) {
- super(loadPropertiesFile(fileName, useTccl), SYSTEM_CONTEXT, 20, includeInvalid);
- }
-
- static Properties loadPropertiesFile(final String fileName, final boolean useTccl) {
+ static Properties loadPropertiesFile(final String fileName) {
final Properties props = new Properties();
- for (final URL url : LoaderUtil.findResources(fileName, useTccl)) {
+ for (final URL url : LoaderUtil.findResources(fileName)) {
try (final InputStream in = url.openStream()) {
props.load(in);
} catch (final IOException e) {
[logging-log4j2] 02/03: Add some javadocs
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 78f728af516564031cbcd0d2a6733c3d6dc44ec2
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sun Oct 1 17:31:21 2023 -0500
Add some javadocs
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../src/main/java/org/apache/logging/log4j/util/Cast.java | 12 ++++++++++++
.../logging/log4j/core/config/AbstractConfiguration.java | 7 +++++++
2 files changed, 19 insertions(+)
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Cast.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/Cast.java
index c525bc42d0..8a1dc40975 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/Cast.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Cast.java
@@ -18,7 +18,19 @@ package org.apache.logging.log4j.util;
@InternalApi
public final class Cast {
+
+ /**
+ * Returns the provided object cast to the generic parameter type or null when the argument is null.
+ *
+ * @param o object to cast
+ * @param <T> the type to cast
+ * @return object after casting or null if the object was null
+ * @throws ClassCastException if the object cannot be cast to the provided type
+ */
public static <T> T cast(final Object o) {
+ if (o == null) {
+ return null;
+ }
@SuppressWarnings("unchecked") final T t = (T) o;
return t;
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index bb434ab654..ebf083b0da 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -94,8 +94,15 @@ import org.apache.logging.log4j.util.ServiceRegistry;
*/
public abstract class AbstractConfiguration extends AbstractFilterable implements Configuration {
+ /**
+ * The instance factory for this configuration. This may be a child factory to a LoggerContext
+ * in most cases, though this might be a root level factory for null configurations.
+ */
protected final ConfigurableInstanceFactory instanceFactory;
+ /**
+ * The configuration processor for transforming a node tree into plugin instances.
+ */
protected final ConfigurationProcessor configurationProcessor;
/**