logfactoryimpl.java
来自「logging日志的相关包 logging日志的相关包」· Java 代码 · 共 1,401 行 · 第 1/4 页
JAVA
1,401 行
// there are multiple Log interface classes available making it // impossible to cast to the type the caller wanted. We // certainly can't use this logger, but we need to know whether // to keep on discovering or terminate now. // // The handleFlawedHierarchy method will throw // LogConfigurationException if it regards this problem as // fatal, and just return if not. handleFlawedHierarchy(currentCL, c); } catch (NoClassDefFoundError e) { // We were able to load the adapter but it had references to // other classes that could not be found. This simply means that // the underlying logger library is not present in this or any // ancestor classloader. There's no point in trying higher up // in the hierarchy in this case.. String msg = "" + e.getMessage(); logDiagnostic( "The log adapter '" + logAdapterClassName + "' is missing dependencies when loaded via classloader " + objectId(currentCL) + ": " + msg.trim()); break; } catch (ExceptionInInitializerError e) { // A static initializer block or the initializer code associated // with a static variable on the log adapter class has thrown // an exception. // // We treat this as meaning the adapter's underlying logging // library could not be found. String msg = "" + e.getMessage(); logDiagnostic( "The log adapter '" + logAdapterClassName + "' is unable to initialize itself when loaded via classloader " + objectId(currentCL) + ": " + msg.trim()); break; } catch(LogConfigurationException e) { // call to handleFlawedHierarchy above must have thrown // a LogConfigurationException, so just throw it on throw e; } catch(Throwable t) { // handleFlawedDiscovery will determine whether this is a fatal // problem or not. If it is fatal, then a LogConfigurationException // will be thrown. handleFlawedDiscovery(logAdapterClassName, currentCL, t); } if (currentCL == null) { break; } // try the parent classloader currentCL = currentCL.getParent(); } if ((logAdapter != null) && affectState) { // We've succeeded, so set instance fields this.logClassName = logAdapterClassName; this.logConstructor = constructor; // Identify the <code>setLogFactory</code> method (if there is one) try { this.logMethod = logAdapterClass.getMethod("setLogFactory", logMethodSignature); logDiagnostic("Found method setLogFactory(LogFactory) in '" + logAdapterClassName + "'"); } catch (Throwable t) { this.logMethod = null; logDiagnostic( "[INFO] '" + logAdapterClassName + "' from classloader " + objectId(currentCL) + " does not declare optional method " + "setLogFactory(LogFactory)"); } logDiagnostic( "Log adapter '" + logAdapterClassName + "' from classloader " + objectId(logAdapterClass.getClassLoader()) + " has been selected for use."); } return logAdapter; } /** * Return the classloader from which we should try to load the logging * adapter classes. * <p> * This method usually returns the context classloader. However if it * is discovered that the classloader which loaded this class is a child * of the context classloader <i>and</i> the allowFlawedContext option * has been set then the classloader which loaded this class is returned * instead. * <p> * The only time when the classloader which loaded this class is a * descendant (rather than the same as or an ancestor of the context * classloader) is when an app has created custom classloaders but * failed to correctly set the context classloader. This is a bug in * the calling application; however we provide the option for JCL to * simply generate a warning rather than fail outright. * */ private ClassLoader getBaseClassLoader() throws LogConfigurationException { ClassLoader thisClassLoader = getClassLoader(LogFactoryImpl.class); if (useTCCL == false) { return thisClassLoader; } ClassLoader contextClassLoader = getContextClassLoader(); ClassLoader baseClassLoader = getLowestClassLoader( contextClassLoader, thisClassLoader); if (baseClassLoader == null) { // The two classloaders are not part of a parent child relationship. // In some classloading setups (e.g. JBoss with its // UnifiedLoaderRepository) this can still work, so if user hasn't // forbidden it, just return the contextClassLoader. if (allowFlawedContext) { if (isDiagnosticsEnabled()) { logDiagnostic( "[WARNING] the context classloader is not part of a" + " parent-child relationship with the classloader that" + " loaded LogFactoryImpl."); } // If contextClassLoader were null, getLowestClassLoader() would // have returned thisClassLoader. The fact we are here means // contextClassLoader is not null, so we can just return it. return contextClassLoader; } else { throw new LogConfigurationException( "Bad classloader hierarchy; LogFactoryImpl was loaded via" + " a classloader that is not related to the current context" + " classloader."); } } if (baseClassLoader != contextClassLoader) { // We really should just use the contextClassLoader as the starting // point for scanning for log adapter classes. However it is expected // that there are a number of broken systems out there which create // custom classloaders but fail to set the context classloader so // we handle those flawed systems anyway. if (allowFlawedContext) { if (isDiagnosticsEnabled()) { logDiagnostic( "Warning: the context classloader is an ancestor of the" + " classloader that loaded LogFactoryImpl; it should be" + " the same or a descendant. The application using" + " commons-logging should ensure the context classloader" + " is used correctly."); } } else { throw new LogConfigurationException( "Bad classloader hierarchy; LogFactoryImpl was loaded via" + " a classloader that is not related to the current context" + " classloader."); } } return baseClassLoader; } /** * Given two related classloaders, return the one which is a child of * the other. * <p> * @param c1 is a classloader (including the null classloader) * @param c2 is a classloader (including the null classloader) * * @return c1 if it has c2 as an ancestor, c2 if it has c1 as an ancestor, * and null if neither is an ancestor of the other. */ private ClassLoader getLowestClassLoader(ClassLoader c1, ClassLoader c2) { // TODO: use AccessController when dealing with classloaders here if (c1 == null) return c2; if (c2 == null) return c1; ClassLoader current; // scan c1's ancestors to find c2 current = c1; while (current != null) { if (current == c2) return c1; current = current.getParent(); } // scan c2's ancestors to find c1 current = c2; while (current != null) { if (current == c1) return c2; current = current.getParent(); } return null; } /** * Generates an internal diagnostic logging of the discovery failure and * then throws a <code>LogConfigurationException</code> that wraps * the passed <code>Throwable</code>. * * @param logAdapterClassName is the class name of the Log implementation * that could not be instantiated. Cannot be <code>null</code>. * * @param classLoader is the classloader that we were trying to load the * logAdapterClassName from when the exception occurred. * * @param discoveryFlaw is the Throwable created by the classloader * * @throws LogConfigurationException ALWAYS */ private void handleFlawedDiscovery(String logAdapterClassName, ClassLoader classLoader, Throwable discoveryFlaw) { if (isDiagnosticsEnabled()) { logDiagnostic("Could not instantiate Log '" + logAdapterClassName + "' -- " + discoveryFlaw.getClass().getName() + ": " + discoveryFlaw.getLocalizedMessage()); } if (!allowFlawedDiscovery) { throw new LogConfigurationException(discoveryFlaw); } } /** * Report a problem loading the log adapter, then either return * (if the situation is considered recoverable) or throw a * LogConfigurationException. * <p> * There are two possible reasons why we successfully loaded the * specified log adapter class then failed to cast it to a Log object: * <ol> * <li>the specific class just doesn't implement the Log interface * (user screwed up), or * <li> the specified class has bound to a Log class loaded by some other * classloader; Log@classloaderX cannot be cast to Log@classloaderY. * </ol> * <p> * Here we try to figure out which case has occurred so we can give the * user some reasonable feedback. * * @param badClassLoader is the classloader we loaded the problem class from, * ie it is equivalent to badClass.getClassLoader(). * * @param badClass is a Class object with the desired name, but which * does not implement Log correctly. * * @throws LogConfigurationException when the situation * should not be recovered from. */ private void handleFlawedHierarchy(ClassLoader badClassLoader, Class badClass) throws LogConfigurationException { boolean implementsLog = false; String logInterfaceName = Log.class.getName(); Class interfaces[] = badClass.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { if (logInterfaceName.equals(interfaces[i].getName())) { implementsLog = true; break; } } if (implementsLog) { // the class does implement an interface called Log, but // it is in the wrong classloader if (isDiagnosticsEnabled()) { try { ClassLoader logInterfaceClassLoader = getClassLoader(Log.class); logDiagnostic( "Class '" + badClass.getName() + "' was found in classloader " + objectId(badClassLoader) + ". It is bound to a Log interface which is not" + " the one loaded from classloader " + objectId(logInterfaceClassLoader)); } catch (Throwable t) { logDiagnostic( "Error while trying to output diagnostics about" + " bad class '" + badClass + "'"); } } if (!allowFlawedHierarchy) { StringBuffer msg = new StringBuffer(); msg.append("Terminating logging for this context "); msg.append("due to bad log hierarchy. "); msg.append("You have more than one version of '"); msg.append(Log.class.getName()); msg.append("' visible."); if (isDiagnosticsEnabled()) { logDiagnostic(msg.toString()); } throw new LogConfigurationException(msg.toString()); } if (isDiagnosticsEnabled()) { StringBuffer msg = new StringBuffer(); msg.append("Warning: bad log hierarchy. "); msg.append("You have more than one version of '"); msg.append(Log.class.getName()); msg.append("' visible."); logDiagnostic(msg.toString()); } } else { // this is just a bad adapter class if (!allowFlawedDiscovery) { StringBuffer msg = new StringBuffer(); msg.append("Terminating logging for this context. "); msg.append("Log class '"); msg.append(badClass.getName()); msg.append("' does not implement the Log interface."); if (isDiagnosticsEnabled()) { logDiagnostic(msg.toString()); } throw new LogConfigurationException(msg.toString()); } if (isDiagnosticsEnabled()) { StringBuffer msg = new StringBuffer(); msg.append("[WARNING] Log class '"); msg.append(badClass.getName()); msg.append("' does not implement the Log interface."); logDiagnostic(msg.toString()); } } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?