📄 logfactory.java
字号:
} else {
// is == null
if (isDiagnosticsEnabled()) {
logDiagnostic(
"[LOOKUP] No resource file with name '" + SERVICE_ID
+ "' found.");
}
}
} catch( Exception ex ) {
// note: if the specified LogFactory class wasn't compatible with LogFactory
// for some reason, a ClassCastException will be caught here, and attempts will
// 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"
+ ": [" + trim(ex.getMessage())
+ "]. Trying alternative implementations...");
}
; // ignore
}
}
// Third try looking into the properties file read earlier (if found)
if (factory == null) {
if (props != null) {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"[LOOKUP] Looking in properties file for entry with key '"
+ FACTORY_PROPERTY
+ "' to define the LogFactory subclass to use...");
}
String factoryClass = props.getProperty(FACTORY_PROPERTY);
if (factoryClass != null) {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"[LOOKUP] Properties file specifies LogFactory subclass '"
+ factoryClass + "'");
}
factory = newFactory(factoryClass, baseClassLoader, contextClassLoader);
// TODO: think about whether we need to handle exceptions from newFactory
} else {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"[LOOKUP] Properties file has no entry specifying LogFactory subclass.");
}
}
} else {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"[LOOKUP] No properties file available to determine"
+ " LogFactory subclass from..");
}
}
}
// Fourth, try the fallback implementation class
if (factory == null) {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT
+ "' via the same classloader that loaded this LogFactory"
+ " class (ie not looking in the context classloader).");
}
// 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
// implementation via the context classloader because:
// * that can cause problems (see comments in newFactory method)
// * no-one should be customising the code of the default class
// Yes, we do give up the ability for the child to ship a newer
// version of the LogFactoryImpl class and have it used dynamically
// by an old LogFactory class in the parent, but that isn't
// necessarily a good idea anyway.
factory = newFactory(FACTORY_DEFAULT, thisClassLoader, contextClassLoader);
}
if (factory != null) {
/**
* Always cache using context class loader.
*/
cacheFactory(contextClassLoader, factory);
if( props!=null ) {
Enumeration names = props.propertyNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String value = props.getProperty(name);
factory.setAttribute(name, value);
}
}
}
return factory;
}
/**
* Convenience method to return a named logger, without the application
* having to care about factories.
*
* @param clazz Class from which a log name will be derived
*
* @exception LogConfigurationException if a suitable <code>Log</code>
* instance cannot be returned
*/
public static Log getLog(Class clazz)
throws LogConfigurationException {
return (getFactory().getInstance(clazz));
}
/**
* Convenience method to return a named logger, without the application
* having to care about factories.
*
* @param name Logical name of the <code>Log</code> instance to be
* returned (the meaning of this name is only known to the underlying
* logging implementation that is being wrapped)
*
* @exception LogConfigurationException if a suitable <code>Log</code>
* instance cannot be returned
*/
public static Log getLog(String name)
throws LogConfigurationException {
return (getFactory().getInstance(name));
}
/**
* Release any internal references to previously created {@link LogFactory}
* instances that have been associated with the specified class loader
* (if any), after calling the instance method <code>release()</code> on
* each of them.
*
* @param classLoader ClassLoader for which to release the LogFactory
*/
public static void release(ClassLoader classLoader) {
if (isDiagnosticsEnabled()) {
logDiagnostic("Releasing factory for classloader " + objectId(classLoader));
}
synchronized (factories) {
if (classLoader == null) {
if (nullClassLoaderFactory != null) {
nullClassLoaderFactory.release();
nullClassLoaderFactory = null;
}
} else {
LogFactory factory = (LogFactory) factories.get(classLoader);
if (factory != null) {
factory.release();
factories.remove(classLoader);
}
}
}
}
/**
* Release any internal references to previously created {@link LogFactory}
* instances, after calling the instance method <code>release()</code> on
* each of them. This is useful in environments like servlet containers,
* which implement application reloading by throwing away a ClassLoader.
* Dangling references to objects in that class loader would prevent
* garbage collection.
*/
public static void releaseAll() {
if (isDiagnosticsEnabled()) {
logDiagnostic("Releasing factory for all classloaders.");
}
synchronized (factories) {
Enumeration elements = factories.elements();
while (elements.hasMoreElements()) {
LogFactory element = (LogFactory) elements.nextElement();
element.release();
}
factories.clear();
if (nullClassLoaderFactory != null) {
nullClassLoaderFactory.release();
nullClassLoaderFactory = null;
}
}
}
// ------------------------------------------------------ Protected Methods
/**
* Safely get access to the classloader for the specified class.
* <p>
* Theoretically, calling getClassLoader can throw a security exception,
* and so should be done under an AccessController in order to provide
* maximum flexibility. However in practice people don't appear to use
* security policies that forbid getClassLoader calls. So for the moment
* all code is written to call this method rather than Class.getClassLoader,
* so that we could put AccessController stuff in this method without any
* disruption later if we need to.
* <p>
* Even when using an AccessController, however, this method can still
* throw SecurityException. Commons-logging basically relies on the
* ability to access classloaders, ie a policy that forbids all
* classloader access will also prevent commons-logging from working:
* currently this method will throw an exception preventing the entire app
* from starting up. Maybe it would be good to detect this situation and
* just disable all commons-logging? Not high priority though - as stated
* above, security policies that prevent classloader access aren't common.
* <p>
* Note that returning an object fetched via an AccessController would
* technically be a security flaw anyway; untrusted code that has access
* to a trusted JCL library could use it to fetch the classloader for
* a class even when forbidden to do so directly.
*
* @since 1.1
*/
protected static ClassLoader getClassLoader(Class clazz) {
try {
return clazz.getClassLoader();
} catch(SecurityException ex) {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"Unable to get classloader for class '" + clazz
+ "' due to security restrictions - " + ex.getMessage());
}
throw ex;
}
}
/**
* Returns the current context classloader.
* <p>
* In versions prior to 1.1, this method did not use an AccessController.
* In version 1.1, an AccessController wrapper was incorrectly added to
* this method, causing a minor security flaw.
* <p>
* In version 1.1.1 this change was reverted; this method no longer uses
* an AccessController. User code wishing to obtain the context classloader
* must invoke this method via AccessController.doPrivileged if it needs
* support for that.
*
* @return the context classloader associated with the current thread,
* or null if security doesn't allow it.
*
* @throws LogConfigurationException if there was some weird error while
* attempting to get the context classloader.
*
* @throws SecurityException if the current java security policy doesn't
* allow this class to access the context classloader.
*/
protected static ClassLoader getContextClassLoader()
throws LogConfigurationException {
return directGetContextClassLoader();
}
/**
* Calls LogFactory.directGetContextClassLoader under the control of an
* AccessController class. This means that java code running under a
* security manager that forbids access to ClassLoaders will still work
* if this class is given appropriate privileges, even when the caller
* doesn't have such privileges. Without using an AccessController, the
* the entire call stack must have the privilege before the call is
* allowed.
*
* @return the context classloader associated with the current thread,
* or null if security doesn't allow it.
*
* @throws LogConfigurationException if there was some weird error while
* attempting to get the context classloader.
*
* @throws SecurityException if the current java security policy doesn't
* allow this class to access the context classloader.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -