Use a supplier instead of testing twice is internal logging is enabled
- Only check once if logging is enabled in other call sites since logDiagnostic(String) already checks - Less string building - Use longer lines - Whitespace - Remove unused private constants
This commit is contained in:
@@ -34,6 +34,7 @@ import java.util.Objects;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ServiceConfigurationError;
|
import java.util.ServiceConfigurationError;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating {@link Log} instances, with discovery and
|
* Factory for creating {@link Log} instances, with discovery and
|
||||||
@@ -94,11 +95,10 @@ public abstract class LogFactory {
|
|||||||
public static final String FACTORY_PROPERTY = "org.apache.commons.logging.LogFactory";
|
public static final String FACTORY_PROPERTY = "org.apache.commons.logging.LogFactory";
|
||||||
|
|
||||||
private static final String FACTORY_LOG4J_API = "org.apache.commons.logging.impl.Log4jApiLogFactory";
|
private static final String FACTORY_LOG4J_API = "org.apache.commons.logging.impl.Log4jApiLogFactory";
|
||||||
private static final String LOG4J_API_LOGGER = "org.apache.logging.log4j.Logger";
|
|
||||||
private static final String LOG4J_TO_SLF4J_BRIDGE = "org.apache.logging.slf4j.SLF4JProvider";
|
private static final String LOG4J_TO_SLF4J_BRIDGE = "org.apache.logging.slf4j.SLF4JProvider";
|
||||||
|
|
||||||
private static final String FACTORY_SLF4J = "org.apache.commons.logging.impl.Slf4jLogFactory";
|
private static final String FACTORY_SLF4J = "org.apache.commons.logging.impl.Slf4jLogFactory";
|
||||||
private static final String SLF4J_API_LOGGER = "org.slf4j.Logger";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The fully qualified class name of the fallback {@code LogFactory}
|
* The fully qualified class name of the fallback {@code LogFactory}
|
||||||
@@ -115,8 +115,7 @@ public abstract class LogFactory {
|
|||||||
* JDK 1.3+ <a href="https://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">
|
* JDK 1.3+ <a href="https://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">
|
||||||
* 'Service Provider' specification</a>.
|
* 'Service Provider' specification</a>.
|
||||||
*/
|
*/
|
||||||
protected static final String SERVICE_ID =
|
protected static final String SERVICE_ID = "META-INF/services/org.apache.commons.logging.LogFactory";
|
||||||
"META-INF/services/org.apache.commons.logging.LogFactory";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name ({@code org.apache.commons.logging.diagnostics.dest})
|
* The name ({@code org.apache.commons.logging.diagnostics.dest})
|
||||||
@@ -133,8 +132,7 @@ public abstract class LogFactory {
|
|||||||
* Diagnostic logging should be used only to debug problematic
|
* Diagnostic logging should be used only to debug problematic
|
||||||
* configurations and should not be set in normal production use.
|
* configurations and should not be set in normal production use.
|
||||||
*/
|
*/
|
||||||
public static final String DIAGNOSTICS_DEST_PROPERTY =
|
public static final String DIAGNOSTICS_DEST_PROPERTY = "org.apache.commons.logging.diagnostics.dest";
|
||||||
"org.apache.commons.logging.diagnostics.dest";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When null (the usual case), no diagnostic output will be
|
* When null (the usual case), no diagnostic output will be
|
||||||
@@ -148,7 +146,7 @@ public abstract class LogFactory {
|
|||||||
* logDiagnostic method, so that users can clearly see which
|
* logDiagnostic method, so that users can clearly see which
|
||||||
* LogFactory class is generating the output.
|
* LogFactory class is generating the output.
|
||||||
*/
|
*/
|
||||||
private static final String diagnosticPrefix;
|
private static final String DIAGNOSTICS_PREFIX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting this system property
|
* Setting this system property
|
||||||
@@ -189,12 +187,10 @@ public abstract class LogFactory {
|
|||||||
* the need to release them (on 1.3+ JVMs only, of course ;).
|
* the need to release them (on 1.3+ JVMs only, of course ;).
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public static final String HASHTABLE_IMPLEMENTATION_PROPERTY =
|
public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = "org.apache.commons.logging.LogFactory.HashtableImpl";
|
||||||
"org.apache.commons.logging.LogFactory.HashtableImpl";
|
|
||||||
|
|
||||||
/** Name used to load the weak hash table implementation by names. */
|
/** Name used to load the weak hash table implementation by names. */
|
||||||
private static final String WEAK_HASHTABLE_CLASSNAME =
|
private static final String WEAK_HASHTABLE_CLASSNAME = "org.apache.commons.logging.impl.WeakHashtable";
|
||||||
"org.apache.commons.logging.impl.WeakHashtable";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reference to the class loader that loaded this class. This is the
|
* A reference to the class loader that loaded this class. This is the
|
||||||
@@ -251,21 +247,15 @@ public abstract class LogFactory {
|
|||||||
// output diagnostics from this class are static.
|
// output diagnostics from this class are static.
|
||||||
String classLoaderName;
|
String classLoaderName;
|
||||||
try {
|
try {
|
||||||
if (thisClassLoader == null) {
|
classLoaderName = thisClassLoader != null ? objectId(thisClassLoader) : "BOOTLOADER";
|
||||||
classLoaderName = "BOOTLOADER";
|
|
||||||
} else {
|
|
||||||
classLoaderName = objectId(thisClassLoader);
|
|
||||||
}
|
|
||||||
} catch (final SecurityException e) {
|
} catch (final SecurityException e) {
|
||||||
classLoaderName = "UNKNOWN";
|
classLoaderName = "UNKNOWN";
|
||||||
}
|
}
|
||||||
diagnosticPrefix = "[LogFactory from " + classLoaderName + "] ";
|
DIAGNOSTICS_PREFIX = "[LogFactory from " + classLoaderName + "] ";
|
||||||
DIAGNOSTICS_STREAM = initDiagnostics();
|
DIAGNOSTICS_STREAM = initDiagnostics();
|
||||||
logClassLoaderEnvironment(LogFactory.class);
|
logClassLoaderEnvironment(LogFactory.class);
|
||||||
factories = createFactoryStore();
|
factories = createFactoryStore();
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic("BOOTSTRAP COMPLETED");
|
||||||
logDiagnostic("BOOTSTRAP COMPLETED");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,7 +270,6 @@ public abstract class LogFactory {
|
|||||||
private static void cacheFactory(final ClassLoader classLoader, final LogFactory factory) {
|
private static void cacheFactory(final ClassLoader classLoader, final LogFactory factory) {
|
||||||
// Ideally we would assert(factory != null) here. However reporting
|
// Ideally we would assert(factory != null) here. However reporting
|
||||||
// errors from within a logging implementation is a little tricky!
|
// errors from within a logging implementation is a little tricky!
|
||||||
|
|
||||||
if (factory != null) {
|
if (factory != null) {
|
||||||
if (classLoader == null) {
|
if (classLoader == null) {
|
||||||
nullClassLoaderFactory = factory;
|
nullClassLoaderFactory = factory;
|
||||||
@@ -359,41 +348,30 @@ public abstract class LogFactory {
|
|||||||
// tries again with thisClassLoaderRef, because we've just tried
|
// tries again with thisClassLoaderRef, because we've just tried
|
||||||
// loading with that loader (not the TCCL). Just throw an
|
// loading with that loader (not the TCCL). Just throw an
|
||||||
// appropriate exception here.
|
// appropriate exception here.
|
||||||
|
|
||||||
final boolean implementsLogFactory = implementsLogFactory(logFactoryClass);
|
final boolean implementsLogFactory = implementsLogFactory(logFactoryClass);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Construct a good message: users may not actual expect that a custom implementation
|
// Construct a good message: users may not actual expect that a custom implementation
|
||||||
// has been specified. Several well known containers use this mechanism to adapt JCL
|
// has been specified. Several well known containers use this mechanism to adapt JCL
|
||||||
// to their native logging system.
|
// to their native logging system.
|
||||||
//
|
//
|
||||||
final StringBuilder msg = new StringBuilder();
|
final StringBuilder msg = new StringBuilder();
|
||||||
msg.append("The application has specified that a custom LogFactory implementation ");
|
msg.append("The application has specified that a custom LogFactory implementation should be used but Class '");
|
||||||
msg.append("should be used but Class '");
|
|
||||||
msg.append(factoryClassName);
|
msg.append(factoryClassName);
|
||||||
msg.append("' cannot be converted to '");
|
msg.append("' cannot be converted to '");
|
||||||
msg.append(LogFactory.class.getName());
|
msg.append(LogFactory.class.getName());
|
||||||
msg.append("'. ");
|
msg.append("'. ");
|
||||||
if (implementsLogFactory) {
|
if (implementsLogFactory) {
|
||||||
msg.append("The conflict is caused by the presence of multiple LogFactory classes ");
|
msg.append("The conflict is caused by the presence of multiple LogFactory classes in incompatible class loaders. Background can");
|
||||||
msg.append("in incompatible class loaders. ");
|
msg.append(" be found in https://commons.apache.org/logging/tech.html. If you have not explicitly specified a custom LogFactory");
|
||||||
msg.append("Background can be found in https://commons.apache.org/logging/tech.html. ");
|
msg.append(" then it is likely that the container has set one without your knowledge. In this case, consider using the ");
|
||||||
msg.append("If you have not explicitly specified a custom LogFactory then it is likely ");
|
msg.append("commons-logging-adapters.jar file or specifying the standard LogFactory from the command line. ");
|
||||||
msg.append("that the container has set one without your knowledge. ");
|
|
||||||
msg.append("In this case, consider using the commons-logging-adapters.jar file or ");
|
|
||||||
msg.append("specifying the standard LogFactory from the command line. ");
|
|
||||||
} else {
|
} else {
|
||||||
msg.append("Please check the custom implementation. ");
|
msg.append("Please check the custom implementation. ");
|
||||||
}
|
}
|
||||||
msg.append("Help can be found at https://commons.apache.org/logging/troubleshooting.html.");
|
msg.append("Help can be found at https://commons.apache.org/logging/troubleshooting.html.");
|
||||||
|
logDiagnostic(msg.toString());
|
||||||
if (isDiagnosticsEnabled()) {
|
|
||||||
logDiagnostic(msg.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ClassCastException(msg.toString());
|
throw new ClassCastException(msg.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore exception, continue. Presumably the class loader was the
|
// Ignore exception, continue. Presumably the class loader was the
|
||||||
// TCCL; the code below will try to load the class via thisClassLoaderRef.
|
// TCCL; the code below will try to load the class via thisClassLoaderRef.
|
||||||
// This will handle the case where the original calling class is in
|
// This will handle the case where the original calling class is in
|
||||||
@@ -433,8 +411,7 @@ public abstract class LogFactory {
|
|||||||
logDiagnostic("Unable to create LogFactory instance.");
|
logDiagnostic("Unable to create LogFactory instance.");
|
||||||
}
|
}
|
||||||
if (logFactoryClass != null && !LogFactory.class.isAssignableFrom(logFactoryClass)) {
|
if (logFactoryClass != null && !LogFactory.class.isAssignableFrom(logFactoryClass)) {
|
||||||
return new LogConfigurationException("The chosen LogFactory implementation does not extend LogFactory." + " Please check your configuration.",
|
return new LogConfigurationException("The chosen LogFactory implementation does not extend LogFactory. Please check your configuration.", e);
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
return new LogConfigurationException(e);
|
return new LogConfigurationException(e);
|
||||||
}
|
}
|
||||||
@@ -466,7 +443,6 @@ public abstract class LogFactory {
|
|||||||
// weak hash table implementation if it is available.
|
// weak hash table implementation if it is available.
|
||||||
storeImplementationClass = null;
|
storeImplementationClass = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storeImplementationClass == null) {
|
if (storeImplementationClass == null) {
|
||||||
storeImplementationClass = WEAK_HASHTABLE_CLASSNAME;
|
storeImplementationClass = WEAK_HASHTABLE_CLASSNAME;
|
||||||
}
|
}
|
||||||
@@ -476,7 +452,6 @@ public abstract class LogFactory {
|
|||||||
result = implementationClass.getConstructor().newInstance();
|
result = implementationClass.getConstructor().newInstance();
|
||||||
} catch (final Throwable t) {
|
} catch (final Throwable t) {
|
||||||
handleThrowable(t); // may re-throw t
|
handleThrowable(t); // may re-throw t
|
||||||
|
|
||||||
// ignore
|
// ignore
|
||||||
if (!WEAK_HASHTABLE_CLASSNAME.equals(storeImplementationClass)) {
|
if (!WEAK_HASHTABLE_CLASSNAME.equals(storeImplementationClass)) {
|
||||||
// if the user's trying to set up a custom implementation, give a clue
|
// if the user's trying to set up a custom implementation, give a clue
|
||||||
@@ -598,9 +573,7 @@ public abstract class LogFactory {
|
|||||||
try {
|
try {
|
||||||
return clazz.getClassLoader();
|
return clazz.getClassLoader();
|
||||||
} catch (final SecurityException ex) {
|
} catch (final SecurityException ex) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "Unable to get class loader for class '" + clazz + "' due to security restrictions - " + ex.getMessage());
|
||||||
logDiagnostic("Unable to get class loader for class '" + clazz + "' due to security restrictions - " + ex.getMessage());
|
|
||||||
}
|
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -633,14 +606,11 @@ public abstract class LogFactory {
|
|||||||
URL propsUrl = null;
|
URL propsUrl = null;
|
||||||
try {
|
try {
|
||||||
final Enumeration<URL> urls = getResources(classLoader, fileName);
|
final Enumeration<URL> urls = getResources(classLoader, fileName);
|
||||||
|
|
||||||
if (urls == null) {
|
if (urls == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (urls.hasMoreElements()) {
|
while (urls.hasMoreElements()) {
|
||||||
final URL url = urls.nextElement();
|
final URL url = urls.nextElement();
|
||||||
|
|
||||||
final Properties newProps = getProperties(url);
|
final Properties newProps = getProperties(url);
|
||||||
if (newProps != null) {
|
if (newProps != null) {
|
||||||
if (props == null) {
|
if (props == null) {
|
||||||
@@ -651,7 +621,6 @@ public abstract class LogFactory {
|
|||||||
if (priorityStr != null) {
|
if (priorityStr != null) {
|
||||||
priority = Double.parseDouble(priorityStr);
|
priority = Double.parseDouble(priorityStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDiagnosticsEnabled()) {
|
if (isDiagnosticsEnabled()) {
|
||||||
logDiagnostic("[LOOKUP] Properties file found at '" + url + "'" + " with priority " + priority);
|
logDiagnostic("[LOOKUP] Properties file found at '" + url + "'" + " with priority " + priority);
|
||||||
}
|
}
|
||||||
@@ -661,13 +630,11 @@ public abstract class LogFactory {
|
|||||||
if (newPriorityStr != null) {
|
if (newPriorityStr != null) {
|
||||||
newPriority = Double.parseDouble(newPriorityStr);
|
newPriority = Double.parseDouble(newPriorityStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPriority > priority) {
|
if (newPriority > priority) {
|
||||||
if (isDiagnosticsEnabled()) {
|
if (isDiagnosticsEnabled()) {
|
||||||
logDiagnostic("[LOOKUP] Properties file at '" + url + "'" + " with priority " + newPriority + " overrides file at '" + propsUrl
|
logDiagnostic("[LOOKUP] Properties file at '" + url + "'" + " with priority " + newPriority + " overrides file at '" + propsUrl
|
||||||
+ "'" + " with priority " + priority);
|
+ "'" + " with priority " + priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
propsUrl = url;
|
propsUrl = url;
|
||||||
props = newProps;
|
props = newProps;
|
||||||
priority = newPriority;
|
priority = newPriority;
|
||||||
@@ -680,11 +647,8 @@ public abstract class LogFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (final SecurityException e) {
|
} catch (final SecurityException e) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic("SecurityException thrown while trying to find/read config files.");
|
||||||
logDiagnostic("SecurityException thrown while trying to find/read config files.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDiagnosticsEnabled()) {
|
if (isDiagnosticsEnabled()) {
|
||||||
if (props == null) {
|
if (props == null) {
|
||||||
logDiagnostic("[LOOKUP] No properties file of name '" + fileName + "' found.");
|
logDiagnostic("[LOOKUP] No properties file of name '" + fileName + "' found.");
|
||||||
@@ -692,7 +656,6 @@ public abstract class LogFactory {
|
|||||||
logDiagnostic("[LOOKUP] Properties file of name '" + fileName + "' found at '" + propsUrl + '"');
|
logDiagnostic("[LOOKUP] Properties file of name '" + fileName + "' found at '" + propsUrl + '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,7 +729,7 @@ public abstract class LogFactory {
|
|||||||
// This is an odd enough situation to report about. This
|
// This is an odd enough situation to report about. This
|
||||||
// output will be a nuisance on JDK1.1, as the system
|
// output will be a nuisance on JDK1.1, as the system
|
||||||
// class loader is null in that environment.
|
// class loader is null in that environment.
|
||||||
if (contextClassLoader == null && isDiagnosticsEnabled()) {
|
if (contextClassLoader == null) {
|
||||||
logDiagnostic("Context class loader is null.");
|
logDiagnostic("Context class loader is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,17 +768,16 @@ public abstract class LogFactory {
|
|||||||
// If TCCL is still enabled at this point, we check if it resolves this class
|
// If TCCL is still enabled at this point, we check if it resolves this class
|
||||||
if (useTccl) {
|
if (useTccl) {
|
||||||
try {
|
try {
|
||||||
if (!LogFactory.class.equals(
|
if (!LogFactory.class.equals(Class.forName(LogFactory.class.getName(), false, contextClassLoader))) {
|
||||||
Class.forName(LogFactory.class.getName(), false, contextClassLoader))) {
|
logDiagnostic(() -> "The class " + LogFactory.class.getName() + " loaded by the context class loader " + objectId(contextClassLoader)
|
||||||
logDiagnostic("The class " + LogFactory.class.getName() + " loaded by the context class loader " + objectId(contextClassLoader)
|
|
||||||
+ " and this class differ. Disabling the usage of the context class loader."
|
+ " and this class differ. Disabling the usage of the context class loader."
|
||||||
+ "Background can be found in https://commons.apache.org/logging/tech.html. ");
|
+ "Background can be found in https://commons.apache.org/logging/tech.html. ");
|
||||||
logHierarchy("[BAD CL TREE] ", contextClassLoader);
|
logHierarchy("[BAD CL TREE] ", contextClassLoader);
|
||||||
useTccl = false;
|
useTccl = false;
|
||||||
}
|
}
|
||||||
} catch (final ClassNotFoundException ignored) {
|
} catch (final ClassNotFoundException ignored) {
|
||||||
logDiagnostic("The class " + LogFactory.class.getName() + " is not present in the the context class loader " + objectId(contextClassLoader)
|
logDiagnostic(() -> "The class " + LogFactory.class.getName() + " is not present in the the context class loader "
|
||||||
+ ". Disabling the usage of the context class loader."
|
+ objectId(contextClassLoader) + ". Disabling the usage of the context class loader."
|
||||||
+ "Background can be found in https://commons.apache.org/logging/tech.html. ");
|
+ "Background can be found in https://commons.apache.org/logging/tech.html. ");
|
||||||
logHierarchy("[BAD CL TREE] ", contextClassLoader);
|
logHierarchy("[BAD CL TREE] ", contextClassLoader);
|
||||||
useTccl = false;
|
useTccl = false;
|
||||||
@@ -825,28 +787,21 @@ public abstract class LogFactory {
|
|||||||
|
|
||||||
// Determine which concrete LogFactory subclass to use.
|
// Determine which concrete LogFactory subclass to use.
|
||||||
// First, try a global system property
|
// First, try a global system property
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "[LOOKUP] Looking for system property [" + FACTORY_PROPERTY +
|
||||||
logDiagnostic("[LOOKUP] Looking for system property [" + FACTORY_PROPERTY +
|
"] to define the LogFactory subclass to use...");
|
||||||
"] to define the LogFactory subclass to use...");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final String factoryClass = getSystemProperty(FACTORY_PROPERTY, null);
|
final String factoryClass = getSystemProperty(FACTORY_PROPERTY, null);
|
||||||
if (factoryClass != null) {
|
if (factoryClass != null) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "[LOOKUP] Creating an instance of LogFactory class '" + factoryClass +
|
||||||
logDiagnostic("[LOOKUP] Creating an instance of LogFactory class '" + factoryClass +
|
"' as specified by system property " + FACTORY_PROPERTY);
|
||||||
"' as specified by system property " + FACTORY_PROPERTY);
|
|
||||||
}
|
|
||||||
factory = newFactory(factoryClass, baseClassLoader, contextClassLoader);
|
factory = newFactory(factoryClass, baseClassLoader, contextClassLoader);
|
||||||
} else if (isDiagnosticsEnabled()) {
|
} else {
|
||||||
logDiagnostic("[LOOKUP] No system property [" + FACTORY_PROPERTY + "] defined.");
|
logDiagnostic(() -> "[LOOKUP] No system property [" + FACTORY_PROPERTY + "] defined.");
|
||||||
}
|
}
|
||||||
} catch (final SecurityException e) {
|
} catch (final SecurityException e) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "[LOOKUP] A security exception occurred while trying to create an instance of the custom factory class" + ": ["
|
||||||
logDiagnostic("[LOOKUP] A security exception occurred while trying to create an" +
|
+ trim(e.getMessage()) + "]. Trying alternative implementations...");
|
||||||
" instance of the custom factory class" + ": [" + trim(e.getMessage()) +
|
|
||||||
"]. Trying alternative implementations...");
|
|
||||||
}
|
|
||||||
// ignore
|
// ignore
|
||||||
} catch (final RuntimeException e) {
|
} catch (final RuntimeException e) {
|
||||||
// This is not consistent with the behavior when a bad LogFactory class is
|
// This is not consistent with the behavior when a bad LogFactory class is
|
||||||
@@ -854,25 +809,18 @@ public abstract class LogFactory {
|
|||||||
//
|
//
|
||||||
// One possible exception that can occur here is a ClassCastException when
|
// One possible exception that can occur here is a ClassCastException when
|
||||||
// the specified class wasn't castable to this LogFactory type.
|
// the specified class wasn't castable to this LogFactory type.
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "[LOOKUP] An exception occurred while trying to create an instance of the custom factory class: [" + trim(e.getMessage())
|
||||||
logDiagnostic("[LOOKUP] An exception occurred while trying to create an" +
|
+ "] as specified by a system property.");
|
||||||
" instance of the custom factory class" + ": [" +
|
|
||||||
trim(e.getMessage()) +
|
|
||||||
"] as specified by a system property.");
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
// Second, try to find a service by using the JDK 1.3 class
|
// Second, try to find a service by using the JDK 1.3 class
|
||||||
// discovery mechanism, which involves putting a file with the name
|
// discovery mechanism, which involves putting a file with the name
|
||||||
// of an interface class in the META-INF/services directory, where the
|
// of an interface class in the META-INF/services directory, where the
|
||||||
// contents of the file is a single line specifying a concrete class
|
// contents of the file is a single line specifying a concrete class
|
||||||
// that implements the desired interface.
|
// that implements the desired interface.
|
||||||
|
|
||||||
if (factory == null) {
|
if (factory == null) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic("[LOOKUP] Using ServiceLoader to define the LogFactory subclass to use...");
|
||||||
logDiagnostic("[LOOKUP] Using ServiceLoader to define the LogFactory subclass to use...");
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
final ServiceLoader<LogFactory> serviceLoader = ServiceLoader.load(LogFactory.class, baseClassLoader);
|
final ServiceLoader<LogFactory> serviceLoader = ServiceLoader.load(LogFactory.class, baseClassLoader);
|
||||||
final Iterator<LogFactory> iterator = serviceLoader.iterator();
|
final Iterator<LogFactory> iterator = serviceLoader.iterator();
|
||||||
@@ -884,55 +832,40 @@ public abstract class LogFactory {
|
|||||||
factory = iterator.next();
|
factory = iterator.next();
|
||||||
}
|
}
|
||||||
} catch (final ServiceConfigurationError | LinkageError ex) {
|
} catch (final ServiceConfigurationError | LinkageError ex) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "[LOOKUP] An exception occurred while trying to find an instance of LogFactory: [" + trim(ex.getMessage())
|
||||||
logDiagnostic("[LOOKUP] An exception occurred while trying to find an" +
|
+ "]. Trying alternative implementations...");
|
||||||
" instance of LogFactory" +
|
|
||||||
": [" + trim(ex.getMessage()) +
|
|
||||||
"]. Trying alternative implementations...");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
// note: if the specified LogFactory class wasn't compatible with LogFactory
|
// note: if the specified LogFactory class wasn't compatible with LogFactory
|
||||||
// for some reason, a ClassCastException will be caught here, and attempts will
|
// for some reason, a ClassCastException will be caught here, and attempts will
|
||||||
// continue to find a compatible class.
|
// continue to find a compatible class.
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "[LOOKUP] A security exception occurred while trying to create an instance of the custom factory class: ["
|
||||||
logDiagnostic(
|
+ trim(ex.getMessage()) + "]. Trying alternative implementations...");
|
||||||
"[LOOKUP] A security exception occurred while trying to create an" +
|
|
||||||
" instance of the custom factory class" +
|
|
||||||
": [" + trim(ex.getMessage()) +
|
|
||||||
"]. Trying alternative implementations...");
|
|
||||||
}
|
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
// Third try looking into the properties file read earlier (if found)
|
// Third try looking into the properties file read earlier (if found)
|
||||||
|
|
||||||
if (factory == null) {
|
if (factory == null) {
|
||||||
if (props != null) {
|
if (props != null) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() ->
|
||||||
logDiagnostic(
|
"[LOOKUP] Looking in properties file for entry with key '" + FACTORY_PROPERTY +
|
||||||
"[LOOKUP] Looking in properties file for entry with key '" + FACTORY_PROPERTY +
|
"' to define the LogFactory subclass to use...");
|
||||||
"' to define the LogFactory subclass to use...");
|
|
||||||
}
|
|
||||||
final String factoryClass = props.getProperty(FACTORY_PROPERTY);
|
final String factoryClass = props.getProperty(FACTORY_PROPERTY);
|
||||||
if (factoryClass != null) {
|
if (factoryClass != null) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() ->
|
||||||
logDiagnostic(
|
"[LOOKUP] Properties file specifies LogFactory subclass '" + factoryClass + "'");
|
||||||
"[LOOKUP] Properties file specifies LogFactory subclass '" + factoryClass + "'");
|
|
||||||
}
|
|
||||||
factory = newFactory(factoryClass, baseClassLoader, contextClassLoader);
|
factory = newFactory(factoryClass, baseClassLoader, contextClassLoader);
|
||||||
|
|
||||||
// TODO: think about whether we need to handle exceptions from newFactory
|
// TODO: think about whether we need to handle exceptions from newFactory
|
||||||
} else if (isDiagnosticsEnabled()) {
|
} else {
|
||||||
logDiagnostic("[LOOKUP] Properties file has no entry specifying LogFactory subclass.");
|
logDiagnostic("[LOOKUP] Properties file has no entry specifying LogFactory subclass.");
|
||||||
}
|
}
|
||||||
} else if (isDiagnosticsEnabled()) {
|
} else {
|
||||||
logDiagnostic("[LOOKUP] No properties file available to determine" + " LogFactory subclass from..");
|
logDiagnostic("[LOOKUP] No properties file available to determine LogFactory subclass from..");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
// Fourth, try one of the three provided factories first from the specified classloader
|
// Fourth, try one of the three provided factories first from the specified classloader
|
||||||
// and then from the current one.
|
// and then from the current one.
|
||||||
if (factory == null) {
|
if (factory == null) {
|
||||||
@@ -946,13 +879,9 @@ public abstract class LogFactory {
|
|||||||
logDiagnostic("Created object " + objectId(factory) + " to manage class loader " + objectId(contextClassLoader));
|
logDiagnostic("Created object " + objectId(factory) + " to manage class loader " + objectId(contextClassLoader));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() ->
|
||||||
logDiagnostic(
|
"[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT +
|
||||||
"[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT +
|
"' via the same class loader that loaded this LogFactory class (ie not looking in the context class loader).");
|
||||||
"' via the same class loader that loaded this LogFactory" +
|
|
||||||
" class (ie not looking in the context class loader).");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: unlike the above code which can try to load custom LogFactory
|
// Note: unlike the above code which can try to load custom LogFactory
|
||||||
// implementations via the TCCL, we don't try to load the default LogFactory
|
// implementations via the TCCL, we don't try to load the default LogFactory
|
||||||
// implementation via the context class loader because:
|
// implementation via the context class loader because:
|
||||||
@@ -964,13 +893,11 @@ public abstract class LogFactory {
|
|||||||
// necessarily a good idea anyway.
|
// necessarily a good idea anyway.
|
||||||
factory = newFactory(FACTORY_DEFAULT, thisClassLoaderRef.get(), contextClassLoader);
|
factory = newFactory(FACTORY_DEFAULT, thisClassLoaderRef.get(), contextClassLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (factory != null) {
|
if (factory != null) {
|
||||||
/**
|
/**
|
||||||
* Always cache using context class loader.
|
* Always cache using context class loader.
|
||||||
*/
|
*/
|
||||||
cacheFactory(contextClassLoader, factory);
|
cacheFactory(contextClassLoader, factory);
|
||||||
|
|
||||||
if (props != null) {
|
if (props != null) {
|
||||||
final Enumeration<?> names = props.propertyNames();
|
final Enumeration<?> names = props.propertyNames();
|
||||||
while (names.hasMoreElements()) {
|
while (names.hasMoreElements()) {
|
||||||
@@ -980,7 +907,6 @@ public abstract class LogFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,14 +957,10 @@ public abstract class LogFactory {
|
|||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "Unable to close stream for URL " + url);
|
||||||
logDiagnostic("Unable to close stream for URL " + url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "Unable to read URL " + url);
|
||||||
logDiagnostic("Unable to read URL " + url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -1068,9 +990,7 @@ public abstract class LogFactory {
|
|||||||
}
|
}
|
||||||
return ClassLoader.getSystemResources(name);
|
return ClassLoader.getSystemResources(name);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "Exception while trying to find configuration file " + name + ":" + e.getMessage());
|
||||||
logDiagnostic("Exception while trying to find configuration file " + name + ":" + e.getMessage());
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
} catch (final NoSuchMethodError e) {
|
} catch (final NoSuchMethodError e) {
|
||||||
// we must be running on a 1.1 JVM which doesn't support
|
// we must be running on a 1.1 JVM which doesn't support
|
||||||
@@ -1144,9 +1064,9 @@ public abstract class LogFactory {
|
|||||||
implementsLogFactory = factoryFromCustomLoader.isAssignableFrom(logFactoryClass);
|
implementsLogFactory = factoryFromCustomLoader.isAssignableFrom(logFactoryClass);
|
||||||
final String logFactoryClassName = logFactoryClass.getName();
|
final String logFactoryClassName = logFactoryClass.getName();
|
||||||
if (implementsLogFactory) {
|
if (implementsLogFactory) {
|
||||||
logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClassName + " implements LogFactory but was loaded by an incompatible class loader.");
|
logDiagnostic(() -> "[CUSTOM LOG FACTORY] " + logFactoryClassName + " implements LogFactory but was loaded by an incompatible class loader.");
|
||||||
} else {
|
} else {
|
||||||
logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClassName + " does not implement LogFactory.");
|
logDiagnostic(() -> "[CUSTOM LOG FACTORY] " + logFactoryClassName + " does not implement LogFactory.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (final SecurityException e) {
|
} catch (final SecurityException e) {
|
||||||
@@ -1155,8 +1075,9 @@ public abstract class LogFactory {
|
|||||||
// This will make it very hard to diagnose issues with JCL.
|
// This will make it very hard to diagnose issues with JCL.
|
||||||
// Consider running less securely whilst debugging this issue.
|
// Consider running less securely whilst debugging this issue.
|
||||||
//
|
//
|
||||||
logDiagnostic("[CUSTOM LOG FACTORY] SecurityException caught trying to determine whether "
|
logDiagnostic(
|
||||||
+ "the compatibility was caused by a class loader conflict: " + e.getMessage());
|
() -> "[CUSTOM LOG FACTORY] SecurityException caught trying to determine whether the compatibility was caused by a class loader conflict: "
|
||||||
|
+ e.getMessage());
|
||||||
} catch (final LinkageError e) {
|
} catch (final LinkageError e) {
|
||||||
//
|
//
|
||||||
// This should be an unusual circumstance.
|
// This should be an unusual circumstance.
|
||||||
@@ -1164,8 +1085,9 @@ public abstract class LogFactory {
|
|||||||
// Another possibility may be an exception thrown by an initializer.
|
// Another possibility may be an exception thrown by an initializer.
|
||||||
// Time for a clean rebuild?
|
// Time for a clean rebuild?
|
||||||
//
|
//
|
||||||
logDiagnostic("[CUSTOM LOG FACTORY] LinkageError caught trying to determine whether "
|
logDiagnostic(
|
||||||
+ "the compatibility was caused by a class loader conflict: " + e.getMessage());
|
() -> "[CUSTOM LOG FACTORY] LinkageError caught trying to determine whether the compatibility was caused by a class loader conflict: "
|
||||||
|
+ e.getMessage());
|
||||||
} catch (final ClassNotFoundException e) {
|
} catch (final ClassNotFoundException e) {
|
||||||
//
|
//
|
||||||
// LogFactory cannot be loaded by the class loader which loaded the custom factory implementation.
|
// LogFactory cannot be loaded by the class loader which loaded the custom factory implementation.
|
||||||
@@ -1174,7 +1096,7 @@ public abstract class LogFactory {
|
|||||||
// Running with diagnostics on should give information about the class loaders used
|
// Running with diagnostics on should give information about the class loaders used
|
||||||
// to load the custom factory.
|
// to load the custom factory.
|
||||||
//
|
//
|
||||||
logDiagnostic("[CUSTOM LOG FACTORY] LogFactory class cannot be loaded by the class loader which loaded "
|
logDiagnostic(() -> "[CUSTOM LOG FACTORY] LogFactory class cannot be loaded by the class loader which loaded "
|
||||||
+ "the custom LogFactory implementation. Is the custom factory in the right class loader?");
|
+ "the custom LogFactory implementation. Is the custom factory in the right class loader?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1217,12 +1139,12 @@ public abstract class LogFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isClassAvailable(final String className, final ClassLoader classLoader) {
|
private static boolean isClassAvailable(final String className, final ClassLoader classLoader) {
|
||||||
logDiagnostic("Checking if class '" + className + "' is available in class loader " + objectId(classLoader));
|
logDiagnostic(() -> "Checking if class '" + className + "' is available in class loader " + objectId(classLoader));
|
||||||
try {
|
try {
|
||||||
Class.forName(className, true, classLoader);
|
Class.forName(className, true, classLoader);
|
||||||
return true;
|
return true;
|
||||||
} catch (final ClassNotFoundException | LinkageError e) {
|
} catch (final ClassNotFoundException | LinkageError e) {
|
||||||
logDiagnostic("Failed to load class '" + className + "' from class loader " + objectId(classLoader) + ": " + e.getMessage());
|
logDiagnostic(() -> "Failed to load class '" + className + "' from class loader " + objectId(classLoader) + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1264,7 +1186,6 @@ public abstract class LogFactory {
|
|||||||
if (!isDiagnosticsEnabled()) {
|
if (!isDiagnosticsEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Deliberately use System.getProperty here instead of getSystemProperty; if
|
// Deliberately use System.getProperty here instead of getSystemProperty; if
|
||||||
// the overall security policy for the calling application forbids access to
|
// the overall security policy for the calling application forbids access to
|
||||||
@@ -1274,10 +1195,8 @@ public abstract class LogFactory {
|
|||||||
} catch (final SecurityException ex) {
|
} catch (final SecurityException ex) {
|
||||||
logDiagnostic("[ENV] Security setting prevent interrogation of system classpaths.");
|
logDiagnostic("[ENV] Security setting prevent interrogation of system classpaths.");
|
||||||
}
|
}
|
||||||
|
|
||||||
final String className = clazz.getName();
|
final String className = clazz.getName();
|
||||||
ClassLoader classLoader;
|
ClassLoader classLoader;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
classLoader = getClassLoader(clazz);
|
classLoader = getClassLoader(clazz);
|
||||||
} catch (final SecurityException ex) {
|
} catch (final SecurityException ex) {
|
||||||
@@ -1285,7 +1204,6 @@ public abstract class LogFactory {
|
|||||||
logDiagnostic("[ENV] Security forbids determining the class loader for " + className);
|
logDiagnostic("[ENV] Security forbids determining the class loader for " + className);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logDiagnostic("[ENV] Class " + className + " was loaded via class loader " + objectId(classLoader));
|
logDiagnostic("[ENV] Class " + className + " was loaded via class loader " + objectId(classLoader));
|
||||||
logHierarchy("[ENV] Ancestry of class loader which loaded " + className + " is ", classLoader);
|
logHierarchy("[ENV] Ancestry of class loader which loaded " + className + " is ", classLoader);
|
||||||
}
|
}
|
||||||
@@ -1313,12 +1231,43 @@ public abstract class LogFactory {
|
|||||||
*/
|
*/
|
||||||
private static void logDiagnostic(final String msg) {
|
private static void logDiagnostic(final String msg) {
|
||||||
if (DIAGNOSTICS_STREAM != null) {
|
if (DIAGNOSTICS_STREAM != null) {
|
||||||
DIAGNOSTICS_STREAM.print(diagnosticPrefix);
|
logDiagnosticDirect(msg);
|
||||||
DIAGNOSTICS_STREAM.println(msg);
|
|
||||||
DIAGNOSTICS_STREAM.flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the specified message to the internal logging destination.
|
||||||
|
* <p>
|
||||||
|
* Note that this method is private; concrete subclasses of this class
|
||||||
|
* should not call it because the diagnosticPrefix string this
|
||||||
|
* method puts in front of all its messages is LogFactory@....,
|
||||||
|
* while subclasses should put SomeSubClass@...
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Subclasses should instead compute their own prefix, then call
|
||||||
|
* logRawDiagnostic. Note that calling isDiagnosticsEnabled is
|
||||||
|
* fine for subclasses.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Note that it is safe to call this method before initDiagnostics
|
||||||
|
* is called; any output will just be ignored (as isDiagnosticsEnabled
|
||||||
|
* will return false).
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param msg is the diagnostic message to be output.
|
||||||
|
*/
|
||||||
|
private static void logDiagnostic(final Supplier<String> msg) {
|
||||||
|
if (DIAGNOSTICS_STREAM != null) {
|
||||||
|
logDiagnosticDirect(msg.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void logDiagnosticDirect(final String msg) {
|
||||||
|
DIAGNOSTICS_STREAM.print(DIAGNOSTICS_PREFIX);
|
||||||
|
DIAGNOSTICS_STREAM.println(msg);
|
||||||
|
DIAGNOSTICS_STREAM.flush();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs diagnostic messages about the given class loader
|
* Logs diagnostic messages about the given class loader
|
||||||
* and it's hierarchy. The prefix is prepended to the message
|
* and it's hierarchy. The prefix is prepended to the message
|
||||||
@@ -1332,10 +1281,8 @@ public abstract class LogFactory {
|
|||||||
}
|
}
|
||||||
ClassLoader systemClassLoader;
|
ClassLoader systemClassLoader;
|
||||||
if (classLoader != null) {
|
if (classLoader != null) {
|
||||||
final String classLoaderString = classLoader.toString();
|
logDiagnostic(prefix + objectId(classLoader) + " == '" + classLoader.toString() + "'");
|
||||||
logDiagnostic(prefix + objectId(classLoader) + " == '" + classLoaderString + "'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
systemClassLoader = ClassLoader.getSystemClassLoader();
|
systemClassLoader = ClassLoader.getSystemClassLoader();
|
||||||
} catch (final SecurityException ex) {
|
} catch (final SecurityException ex) {
|
||||||
@@ -1349,14 +1296,12 @@ public abstract class LogFactory {
|
|||||||
if (classLoader == systemClassLoader) {
|
if (classLoader == systemClassLoader) {
|
||||||
buf.append(" (SYSTEM) ");
|
buf.append(" (SYSTEM) ");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
classLoader = classLoader.getParent();
|
classLoader = classLoader.getParent();
|
||||||
} catch (final SecurityException ex) {
|
} catch (final SecurityException ex) {
|
||||||
buf.append(" --> SECRET");
|
buf.append(" --> SECRET");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append(" --> ");
|
buf.append(" --> ");
|
||||||
if (classLoader == null) {
|
if (classLoader == null) {
|
||||||
buf.append("BOOT");
|
buf.append("BOOT");
|
||||||
@@ -1447,17 +1392,12 @@ public abstract class LogFactory {
|
|||||||
// method will propagate out of this method; in particular a
|
// method will propagate out of this method; in particular a
|
||||||
// ClassCastException can be thrown.
|
// ClassCastException can be thrown.
|
||||||
final Object result = AccessController.doPrivileged((PrivilegedAction<?>) () -> createFactory(factoryClass, classLoader));
|
final Object result = AccessController.doPrivileged((PrivilegedAction<?>) () -> createFactory(factoryClass, classLoader));
|
||||||
|
|
||||||
if (result instanceof LogConfigurationException) {
|
if (result instanceof LogConfigurationException) {
|
||||||
final LogConfigurationException ex = (LogConfigurationException) result;
|
final LogConfigurationException ex = (LogConfigurationException) result;
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "An error occurred while loading the factory class:" + ex.getMessage());
|
||||||
logDiagnostic("An error occurred while loading the factory class:" + ex.getMessage());
|
|
||||||
}
|
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "Created object " + objectId(result) + " to manage class loader " + objectId(contextClassLoader));
|
||||||
logDiagnostic("Created object " + objectId(result) + " to manage class loader " + objectId(contextClassLoader));
|
|
||||||
}
|
|
||||||
return (LogFactory) result;
|
return (LogFactory) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1475,7 +1415,7 @@ public abstract class LogFactory {
|
|||||||
return (LogFactory) Class.forName(FACTORY_SLF4J, true, classLoader).getConstructor().newInstance();
|
return (LogFactory) Class.forName(FACTORY_SLF4J, true, classLoader).getConstructor().newInstance();
|
||||||
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
||||||
} finally {
|
} finally {
|
||||||
logDiagnostic(
|
logDiagnostic(() ->
|
||||||
"[LOOKUP] Log4j API to SLF4J redirection detected. Loading the SLF4J LogFactory implementation '" + FACTORY_SLF4J + "'.");
|
"[LOOKUP] Log4j API to SLF4J redirection detected. Loading the SLF4J LogFactory implementation '" + FACTORY_SLF4J + "'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1483,19 +1423,19 @@ public abstract class LogFactory {
|
|||||||
return (LogFactory) Class.forName(FACTORY_LOG4J_API, true, classLoader).getConstructor().newInstance();
|
return (LogFactory) Class.forName(FACTORY_LOG4J_API, true, classLoader).getConstructor().newInstance();
|
||||||
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
||||||
} finally {
|
} finally {
|
||||||
logDiagnostic("[LOOKUP] Loading the Log4j API LogFactory implementation '" + FACTORY_LOG4J_API + "'.");
|
logDiagnostic(() -> "[LOOKUP] Loading the Log4j API LogFactory implementation '" + FACTORY_LOG4J_API + "'.");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return (LogFactory) Class.forName(FACTORY_SLF4J, true, classLoader).getConstructor().newInstance();
|
return (LogFactory) Class.forName(FACTORY_SLF4J, true, classLoader).getConstructor().newInstance();
|
||||||
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
||||||
} finally {
|
} finally {
|
||||||
logDiagnostic("[LOOKUP] Loading the SLF4J LogFactory implementation '" + FACTORY_SLF4J + "'.");
|
logDiagnostic(() -> "[LOOKUP] Loading the SLF4J LogFactory implementation '" + FACTORY_SLF4J + "'.");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return (LogFactory) Class.forName(FACTORY_DEFAULT, true, classLoader).getConstructor().newInstance();
|
return (LogFactory) Class.forName(FACTORY_DEFAULT, true, classLoader).getConstructor().newInstance();
|
||||||
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
} catch (final LinkageError | ReflectiveOperationException ignored) {
|
||||||
} finally {
|
} finally {
|
||||||
logDiagnostic("[LOOKUP] Loading the legacy LogFactory implementation '" + FACTORY_DEFAULT + "'.");
|
logDiagnostic(() -> "[LOOKUP] Loading the legacy LogFactory implementation '" + FACTORY_DEFAULT + "'.");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1504,13 +1444,13 @@ public abstract class LogFactory {
|
|||||||
* Returns a string that uniquely identifies the specified object, including
|
* Returns a string that uniquely identifies the specified object, including
|
||||||
* its class.
|
* its class.
|
||||||
* <p>
|
* <p>
|
||||||
* The returned string is of form "className@hashCode", that is, is the same as
|
* The returned string is of form {@code "className@hashCode"}, that is, is the same as
|
||||||
* the return value of the Object.toString() method, but works even when
|
* the return value of the {@link Object#toString()} method, but works even when
|
||||||
* the specified object's class has overridden the toString method.
|
* the specified object's class has overridden the toString method.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param obj may be null.
|
* @param obj may be null.
|
||||||
* @return a string of form className@hashCode, or "null" if param o is null.
|
* @return a string of form {@code className@hashCode}, or "null" if obj is null.
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
*/
|
*/
|
||||||
public static String objectId(final Object obj) {
|
public static String objectId(final Object obj) {
|
||||||
@@ -1529,9 +1469,7 @@ public abstract class LogFactory {
|
|||||||
* @param classLoader ClassLoader for which to release the LogFactory
|
* @param classLoader ClassLoader for which to release the LogFactory
|
||||||
*/
|
*/
|
||||||
public static void release(final ClassLoader classLoader) {
|
public static void release(final ClassLoader classLoader) {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic(() -> "Releasing factory for class loader " + objectId(classLoader));
|
||||||
logDiagnostic("Releasing factory for class loader " + objectId(classLoader));
|
|
||||||
}
|
|
||||||
// factories is not final and could be replaced in this block.
|
// factories is not final and could be replaced in this block.
|
||||||
final Hashtable<ClassLoader, LogFactory> factories = LogFactory.factories;
|
final Hashtable<ClassLoader, LogFactory> factories = LogFactory.factories;
|
||||||
synchronized (factories) {
|
synchronized (factories) {
|
||||||
@@ -1559,15 +1497,12 @@ public abstract class LogFactory {
|
|||||||
* garbage collection.
|
* garbage collection.
|
||||||
*/
|
*/
|
||||||
public static void releaseAll() {
|
public static void releaseAll() {
|
||||||
if (isDiagnosticsEnabled()) {
|
logDiagnostic("Releasing factory for all class loaders.");
|
||||||
logDiagnostic("Releasing factory for all class loaders.");
|
|
||||||
}
|
|
||||||
// factories is not final and could be replaced in this block.
|
// factories is not final and could be replaced in this block.
|
||||||
final Hashtable<ClassLoader, LogFactory> factories = LogFactory.factories;
|
final Hashtable<ClassLoader, LogFactory> factories = LogFactory.factories;
|
||||||
synchronized (factories) {
|
synchronized (factories) {
|
||||||
factories.values().forEach(LogFactory::release);
|
factories.values().forEach(LogFactory::release);
|
||||||
factories.clear();
|
factories.clear();
|
||||||
|
|
||||||
if (nullClassLoaderFactory != null) {
|
if (nullClassLoaderFactory != null) {
|
||||||
nullClassLoaderFactory.release();
|
nullClassLoaderFactory.release();
|
||||||
nullClassLoaderFactory = null;
|
nullClassLoaderFactory = null;
|
||||||
@@ -1575,12 +1510,9 @@ public abstract class LogFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Utility method to safely trim a string. */
|
/** Trims the given string in a null-safe manner. */
|
||||||
private static String trim(final String src) {
|
private static String trim(final String src) {
|
||||||
if (src == null) {
|
return src != null ? src.trim() : null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return src.trim();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user