📄 logfactory.java
字号:
} } // 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. * * @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; } } /** * 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. */ protected static ClassLoader getContextClassLoader() throws LogConfigurationException { return (ClassLoader)AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return directGetContextClassLoader(); } }); } /** * Return the thread context class loader if available; otherwise return * null. * <p> * Most/all code should call getContextClassLoader rather than calling * this method directly. * <p> * The thread context class loader is available for JDK 1.2 * or later, if certain security conditions are met. * <p> * Note that no internal logging is done within this method because * this method is called every time LogFactory.getLogger() is called, * and we don't want too much output generated here. * * @exception LogConfigurationException if a suitable class loader * cannot be identified. * * @exception SecurityException if the java security policy forbids * access to the context classloader from one of the classes in the * current call stack. * @since 1.1 */ protected static ClassLoader directGetContextClassLoader() throws LogConfigurationException { ClassLoader classLoader = null; try { // Are we running on a JDK 1.2 or later system? Method method = Thread.class.getMethod("getContextClassLoader", (Class[]) null); // Get the thread context class loader (if there is one) try { classLoader = (ClassLoader)method.invoke(Thread.currentThread(), (Object[]) null); } catch (IllegalAccessException e) { throw new LogConfigurationException ("Unexpected IllegalAccessException", e); } catch (InvocationTargetException e) { /** * InvocationTargetException is thrown by 'invoke' when * the method being invoked (getContextClassLoader) throws * an exception. * * getContextClassLoader() throws SecurityException when * the context class loader isn't an ancestor of the * calling class's class loader, or if security * permissions are restricted. * * In the first case (not related), we want to ignore and * keep going. We cannot help but also ignore the second * with the logic below, but other calls elsewhere (to * obtain a class loader) will trigger this exception where * we can make a distinction. */ if (e.getTargetException() instanceof SecurityException) { ; // ignore } else { // Capture 'e.getTargetException()' exception for details // alternate: log 'e.getTargetException()', and pass back 'e'. throw new LogConfigurationException ("Unexpected InvocationTargetException", e.getTargetException()); } } } catch (NoSuchMethodException e) { // Assume we are running on JDK 1.1 classLoader = getClassLoader(LogFactory.class); // We deliberately don't log a message here to outputStream; // this message would be output for every call to LogFactory.getLog() // when running on JDK1.1 // // if (outputStream != null) { // outputStream.println( // "Method Thread.getContextClassLoader does not exist;" // + " assuming this is JDK 1.1, and that the context" // + " classloader is the same as the class that loaded" // + " the concrete LogFactory class."); // } } // Return the selected class loader
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -