1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/* 2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Copyright 2001-2006 The Apache Software Foundation. 3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * you may not use this file except in compliance with the License. 6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * You may obtain a copy of the License at 7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * See the License for the specific language governing permissions and 14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * limitations under the License. 15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.commons.logging; 18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.BufferedReader; 21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.FileOutputStream; 22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.IOException; 23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.InputStream; 24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.InputStreamReader; 25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.PrintStream; 26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.reflect.InvocationTargetException; 27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.reflect.Method; 28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.net.URL; 29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.security.AccessController; 30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.security.PrivilegedAction; 31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Enumeration; 32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Hashtable; 33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Properties; 34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/** 37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>Factory for creating {@link Log} instances, with discovery and 38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * configuration features similar to that employed by standard Java APIs 39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * such as JAXP.</p> 40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation is heavily 42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * based on the SAXParserFactory and DocumentBuilderFactory implementations 43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.</p> 44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Craig R. McClanahan 46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Costin Manolache 47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Richard A. Sitze 48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Revision: 399431 $ $Date: 2006-05-03 21:58:34 +0100 (Wed, 03 May 2006) $ 49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic abstract class LogFactory { 52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ----------------------------------------------------- Manifest Constants 55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The name (<code>priority</code>) of the key in the config file used to 58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * specify the priority of that particular config file. The associated value 59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * is a floating-point number; higher values take priority over lower values. 60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static final String PRIORITY_KEY = "priority"; 62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The name (<code>use_tccl</code>) of the key in the config file used 65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to specify whether logging classes should be loaded via the thread 66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * context class loader (TCCL), or not. By default, the TCCL is used. 67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static final String TCCL_KEY = "use_tccl"; 69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The name (<code>org.apache.commons.logging.LogFactory</code>) of the property 72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * used to identify the LogFactory implementation 73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class name. This can be used as a system property, or as an entry in a 74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * configuration properties file. 75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static final String FACTORY_PROPERTY = 77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "org.apache.commons.logging.LogFactory"; 78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The fully qualified class name of the fallback <code>LogFactory</code> 81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * implementation class to use, if no other can be found. 82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static final String FACTORY_DEFAULT = 84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "org.apache.commons.logging.impl.LogFactoryImpl"; 85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The name (<code>commons-logging.properties</code>) of the properties file to search for. 88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static final String FACTORY_PROPERTIES = 90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "commons-logging.properties"; 91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * JDK1.3+ <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider"> 94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 'Service Provider' specification</a>. 95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static final String SERVICE_ID = 98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "META-INF/services/org.apache.commons.logging.LogFactory"; 99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The name (<code>org.apache.commons.logging.diagnostics.dest</code>) 102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * of the property used to enable internal commons-logging 103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * diagnostic output, in order to get information on what logging 104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * implementations are being discovered, what classloaders they 105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * are loaded through, etc. 106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If a system property of this name is set then the value is 108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * assumed to be the name of a file. The special strings 109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * STDOUT or STDERR (case-sensitive) indicate output to 110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * System.out and System.err respectively. 111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Diagnostic logging should be used only to debug problematic 113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * configurations and should not be set in normal production use. 114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static final String DIAGNOSTICS_DEST_PROPERTY = 116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "org.apache.commons.logging.diagnostics.dest"; 117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * When null (the usual case), no diagnostic output will be 120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * generated by LogFactory or LogFactoryImpl. When non-null, 121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * interesting events will be written to the specified object. 122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static PrintStream diagnosticsStream = null; 124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * A string that gets prefixed to every message output by the 127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * logDiagnostic method, so that users can clearly see which 128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * LogFactory class is generating the output. 129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static String diagnosticPrefix; 131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>Setting this system property 134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * (<code>org.apache.commons.logging.LogFactory.HashtableImpl</code>) 135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * value allows the <code>Hashtable</code> used to store 136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloaders to be substituted by an alternative implementation. 137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <strong>Note:</strong> <code>LogFactory</code> will print: 140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code><pre> 141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * [ERROR] LogFactory: Load of custom hashtable failed</em> 142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </pre></code> 143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to system error and then continue using a standard Hashtable. 144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <strong>Usage:</strong> Set this property when Java is invoked 147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * and <code>LogFactory</code> will attempt to load a new instance 148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * of the given implementation class. 149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * For example, running the following ant scriplet: 150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code><pre> 151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}"> 152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ... 153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <sysproperty 154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * key="org.apache.commons.logging.LogFactory.HashtableImpl" 155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * value="org.apache.commons.logging.AltHashtable"/> 156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </java> 157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </pre></code> 158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * will mean that <code>LogFactory</code> will load an instance of 159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>org.apache.commons.logging.AltHashtable</code>. 160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * A typical use case is to allow a custom 163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Hashtable implementation using weak references to be substituted. 164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This will allow classloaders to be garbage collected without 165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the need to release them (on 1.3+ JVMs only, of course ;) 166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = 169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "org.apache.commons.logging.LogFactory.HashtableImpl"; 170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** Name used to load the weak hashtable implementation by names */ 171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static final String WEAK_HASHTABLE_CLASSNAME = 172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "org.apache.commons.logging.impl.WeakHashtable"; 173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * A reference to the classloader that loaded this class. This is the 176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * same as LogFactory.class.getClassLoader(). However computing this 177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * value isn't quite as simple as that, as we potentially need to use 178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * AccessControllers etc. It's more efficient to compute it once and 179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * cache it here. 180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static ClassLoader thisClassLoader; 182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ----------------------------------------------------------- Constructors 184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Protected constructor that is not available for public use. 188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected LogFactory() { 190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // --------------------------------------------------------- Public Methods 193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Return the configuration attribute with the specified name (if any), 197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or <code>null</code> if there is no such attribute. 198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param name Name of the attribute to return 200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public abstract Object getAttribute(String name); 202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Return an array containing the names of all currently defined 206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * configuration attributes. If there are no such attributes, a zero 207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * length array is returned. 208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public abstract String[] getAttributeNames(); 210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Convenience method to derive a name from the specified class and 214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * call <code>getInstance(String)</code> with it. 215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param clazz Class for which a suitable Log name will be derived 217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception LogConfigurationException if a suitable <code>Log</code> 219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instance cannot be returned 220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public abstract Log getInstance(Class clazz) 222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws LogConfigurationException; 223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>Construct (if necessary) and return a <code>Log</code> instance, 227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * using the factory's current set of configuration attributes.</p> 228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p><strong>NOTE</strong> - Depending upon the implementation of 230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the <code>LogFactory</code> you are using, the <code>Log</code> 231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instance you are returned may or may not be local to the current 232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * application, and may or may not be returned again on a subsequent 233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * call with the same name argument.</p> 234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param name Logical name of the <code>Log</code> instance to be 236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * returned (the meaning of this name is only known to the underlying 237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * logging implementation that is being wrapped) 238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception LogConfigurationException if a suitable <code>Log</code> 240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instance cannot be returned 241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public abstract Log getInstance(String name) 243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws LogConfigurationException; 244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Release any internal references to previously created {@link Log} 248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instances returned by this factory. This is useful in environments 249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * like servlet containers, which implement application reloading by 250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * throwing away a ClassLoader. Dangling references to objects in that 251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class loader would prevent garbage collection. 252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public abstract void release(); 254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Remove any configuration attribute associated with the specified name. 258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If there is no such attribute, no action is taken. 259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param name Name of the attribute to remove 261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public abstract void removeAttribute(String name); 263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Set the configuration attribute with the specified name. Calling 267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * this with a <code>null</code> value is equivalent to calling 268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>removeAttribute(name)</code>. 269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param name Name of the attribute to set 271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param value Value of the attribute to set, or <code>null</code> 272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to remove any setting for this attribute 273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public abstract void setAttribute(String name, Object value); 275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ------------------------------------------------------- Static Variables 278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The previously constructed <code>LogFactory</code> instances, keyed by 282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the <code>ClassLoader</code> with which it was created. 283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static Hashtable factories = null; 285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Prevously constructed <code>LogFactory</code> instance as in the 288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>factories</code> map, but for the case where 289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>getClassLoader</code> returns <code>null</code>. 290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This can happen when: 291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <ul> 292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>using JDK1.1 and the calling code is loaded via the system 293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloader (very common)</li> 294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>using JDK1.2+ and the calling code is loaded via the boot 295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloader (only likely for embedded systems work).</li> 296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </ul> 297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Note that <code>factories</code> is a <i>Hashtable</i> (not a HashMap), 298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * and hashtables don't allow null as a key. 299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static LogFactory nullClassLoaderFactory = null; 301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Create the hashtable which will be used to store a map of 304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * (context-classloader -> logfactory-object). Version 1.2+ of Java 305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * supports "weak references", allowing a custom Hashtable class 306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to be used which uses only weak references to its keys. Using weak 307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * references can fix memory leaks on webapp unload in some cases (though 308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * not all). Version 1.1 of Java does not support weak references, so we 309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * must dynamically determine which we are using. And just for fun, this 310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * code also supports the ability for a system property to specify an 311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * arbitrary Hashtable implementation name. 312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Note that the correct way to ensure no memory leaks occur is to ensure 314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * that LogFactory.release(contextClassLoader) is called whenever a 315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * webapp is undeployed. 316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static final Hashtable createFactoryStore() { 318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Hashtable result = null; 319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String storeImplementationClass 320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project = System.getProperty(HASHTABLE_IMPLEMENTATION_PROPERTY); 321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (storeImplementationClass == null) { 322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project storeImplementationClass = WEAK_HASHTABLE_CLASSNAME; 323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Class implementationClass = Class.forName(storeImplementationClass); 326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project result = (Hashtable) implementationClass.newInstance(); 327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (Throwable t) { 329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ignore 330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!WEAK_HASHTABLE_CLASSNAME.equals(storeImplementationClass)) { 331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // if the user's trying to set up a custom implementation, give a clue 332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // use internal logging to issue the warning 334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[ERROR] LogFactory: Load of custom hashtable failed"); 335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // we *really* want this output, even if diagnostics weren't 337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // explicitly enabled by the user. 338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project System.err.println("[ERROR] LogFactory: Load of custom hashtable failed"); 339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (result == null) { 343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project result = new Hashtable(); 344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return result; 346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // --------------------------------------------------------- Static Methods 350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>Construct (if necessary) and return a <code>LogFactory</code> 353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instance, using the following ordered lookup procedure to determine 354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the name of the implementation class to be loaded.</p> 355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <ul> 356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>The <code>org.apache.commons.logging.LogFactory</code> system 357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * property.</li> 358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>The JDK 1.3 Service Discovery mechanism</li> 359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>Use the properties file <code>commons-logging.properties</code> 360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * file, if found in the class path of this class. The configuration 361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * file is in standard <code>java.util.Properties</code> format and 362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * contains the fully qualified name of the implementation class 363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the key being the system property defined above.</li> 364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>Fall back to a default implementation class 365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * (<code>org.apache.commons.logging.impl.LogFactoryImpl</code>).</li> 366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </ul> 367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p><em>NOTE</em> - If the properties file method of identifying the 369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>LogFactory</code> implementation class is utilized, all of the 370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * properties defined in this file will be set as configuration attributes 371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * on the corresponding <code>LogFactory</code> instance.</p> 372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p><em>NOTE</em> - In a multithreaded environment it is possible 374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * that two different instances will be returned for the same 375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloader environment. 376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception LogConfigurationException if the implementation class is not 379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * available or cannot be instantiated. 380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static LogFactory getFactory() throws LogConfigurationException { 382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Identify the class loader we will be using 383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader contextClassLoader = getContextClassLoader(); 384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (contextClassLoader == null) { 386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This is an odd enough situation to report about. This 387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // output will be a nuisance on JDK1.1, as the system 388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // classloader is null in that environment. 389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("Context classloader is null."); 391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Return any previously registered factory for this class loader 395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project LogFactory factory = getCachedFactory(contextClassLoader); 396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factory != null) { 397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return factory; 398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] LogFactory implementation requested for the first time for context classloader " 403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + objectId(contextClassLoader)); 404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logHierarchy("[LOOKUP] ", contextClassLoader); 405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Load properties file. 408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // If the properties file exists, then its contents are used as 410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // "attributes" on the LogFactory implementation class. One particular 411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // property may also control which LogFactory concrete subclass is 412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // used, but only if other discovery mechanisms fail.. 413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // As the properties file (if it exists) will be used one way or 415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // another in the end we may as well look for it first. 416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Properties props = getConfigurationFile(contextClassLoader, FACTORY_PROPERTIES); 418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Determine whether we will be using the thread context class loader to 420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // load logging classes or not by checking the loaded properties file (if any). 421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader baseClassLoader = contextClassLoader; 422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (props != null) { 423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String useTCCLStr = props.getProperty(TCCL_KEY); 424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (useTCCLStr != null) { 425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // The Boolean.valueOf(useTCCLStr).booleanValue() formulation 426069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // is required for Java 1.2 compatability. 427069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (Boolean.valueOf(useTCCLStr).booleanValue() == false) { 428069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Don't use current context classloader when locating any 429069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // LogFactory or Log classes, just use the class that loaded 430069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // this abstract class. When this class is deployed in a shared 431069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // classpath of a container, it means webapps cannot deploy their 432069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // own logging implementations. It also means that it is up to the 433069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // implementation whether to load library-specific config files 434069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // from the TCCL or not. 435069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project baseClassLoader = thisClassLoader; 436069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 437069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 438069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 439069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 440069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Determine which concrete LogFactory subclass to use. 441069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // First, try a global system property 442069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 443069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 444069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Looking for system property [" + FACTORY_PROPERTY 445069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "] to define the LogFactory subclass to use..."); 446069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 447069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 448069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 449069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String factoryClass = System.getProperty(FACTORY_PROPERTY); 450069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factoryClass != null) { 451069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 452069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 453069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Creating an instance of LogFactory class '" + factoryClass 454069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' as specified by system property " + FACTORY_PROPERTY); 455069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 456069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 457069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); 458069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 459069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 460069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 461069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] No system property [" + FACTORY_PROPERTY 462069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "] defined."); 463069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 464069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 465069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (SecurityException e) { 466069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 467069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 468069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] A security exception occurred while trying to create an" 469069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " instance of the custom factory class" 470069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + ": [" + e.getMessage().trim() 471069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "]. Trying alternative implementations..."); 472069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 473069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ; // ignore 474069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(RuntimeException e) { 475069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This is not consistent with the behaviour when a bad LogFactory class is 476069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // specified in a services file. 477069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 478069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // One possible exception that can occur here is a ClassCastException when 479069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // the specified class wasn't castable to this LogFactory type. 480069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 481069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 482069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] An exception occurred while trying to create an" 483069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " instance of the custom factory class" 484069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + ": [" + e.getMessage().trim() 485069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "] as specified by a system property."); 486069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 487069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw e; 488069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 489069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 490069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 491069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Second, try to find a service by using the JDK1.3 class 492069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // discovery mechanism, which involves putting a file with the name 493069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // of an interface class in the META-INF/services directory, where the 494069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // contents of the file is a single line specifying a concrete class 495069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // that implements the desired interface. 496069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 497069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factory == null) { 498069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 499069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 500069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Looking for a resource file of name [" + SERVICE_ID 501069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "] to define the LogFactory subclass to use..."); 502069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 503069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 504069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project InputStream is = getResourceAsStream(contextClassLoader, 505069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project SERVICE_ID); 506069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 507069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if( is != null ) { 508069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This code is needed by EBCDIC and other strange systems. 509069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // It's a fix for bugs reported in xerces 510069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project BufferedReader rd; 511069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 512069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); 513069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (java.io.UnsupportedEncodingException e) { 514069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project rd = new BufferedReader(new InputStreamReader(is)); 515069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 516069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 517069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String factoryClassName = rd.readLine(); 518069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project rd.close(); 519069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 520069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factoryClassName != null && 521069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ! "".equals(factoryClassName)) { 522069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 523069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 524069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Creating an instance of LogFactory class " + factoryClassName 525069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " as specified by file '" + SERVICE_ID 526069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' which was present in the path of the context" 527069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " classloader."); 528069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 529069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory = newFactory(factoryClassName, baseClassLoader, contextClassLoader ); 530069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 531069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 532069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // is == null 533069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 534069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 535069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] No resource file with name '" + SERVICE_ID 536069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' found."); 537069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 538069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 539069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch( Exception ex ) { 540069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // note: if the specified LogFactory class wasn't compatible with LogFactory 541069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // for some reason, a ClassCastException will be caught here, and attempts will 542069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // continue to find a compatible class. 543069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 544069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 545069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] A security exception occurred while trying to create an" 546069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " instance of the custom factory class" 547069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + ": [" + ex.getMessage().trim() 548069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "]. Trying alternative implementations..."); 549069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 550069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ; // ignore 551069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 552069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 553069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 554069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 555069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Third try looking into the properties file read earlier (if found) 556069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 557069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factory == null) { 558069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (props != null) { 559069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 560069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 561069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Looking in properties file for entry with key '" 562069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + FACTORY_PROPERTY 563069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' to define the LogFactory subclass to use..."); 564069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 565069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String factoryClass = props.getProperty(FACTORY_PROPERTY); 566069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factoryClass != null) { 567069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 568069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 569069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Properties file specifies LogFactory subclass '" 570069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + factoryClass + "'"); 571069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 572069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); 573069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 574069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // TODO: think about whether we need to handle exceptions from newFactory 575069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 576069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 577069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 578069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Properties file has no entry specifying LogFactory subclass."); 579069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 580069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 581069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 582069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 583069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 584069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] No properties file available to determine" 585069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " LogFactory subclass from.."); 586069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 587069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 588069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 589069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 590069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 591069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Fourth, try the fallback implementation class 592069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 593069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factory == null) { 594069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 595069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 596069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT 597069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' via the same classloader that loaded this LogFactory" 598069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " class (ie not looking in the context classloader)."); 599069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 600069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 601069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Note: unlike the above code which can try to load custom LogFactory 602069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // implementations via the TCCL, we don't try to load the default LogFactory 603069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // implementation via the context classloader because: 604069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // * that can cause problems (see comments in newFactory method) 605069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // * no-one should be customising the code of the default class 606069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Yes, we do give up the ability for the child to ship a newer 607069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // version of the LogFactoryImpl class and have it used dynamically 608069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // by an old LogFactory class in the parent, but that isn't 609069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // necessarily a good idea anyway. 610069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory = newFactory(FACTORY_DEFAULT, thisClassLoader, contextClassLoader); 611069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 612069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 613069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factory != null) { 614069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 615069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Always cache using context class loader. 616069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 617069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project cacheFactory(contextClassLoader, factory); 618069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 619069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if( props!=null ) { 620069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Enumeration names = props.propertyNames(); 621069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while (names.hasMoreElements()) { 622069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String name = (String) names.nextElement(); 623069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String value = props.getProperty(name); 624069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory.setAttribute(name, value); 625069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 626069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 627069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 628069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 629069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return factory; 630069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 631069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 632069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 633069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 634069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Convenience method to return a named logger, without the application 635069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * having to care about factories. 636069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 637069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param clazz Class from which a log name will be derived 638069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 639069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception LogConfigurationException if a suitable <code>Log</code> 640069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instance cannot be returned 641069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 642069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static Log getLog(Class clazz) 643069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws LogConfigurationException { 644069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 645069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // BEGIN android-added 646069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return getLog(clazz.getName()); 647069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // END android-added 648069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // BEGIN android-deleted 649069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project //return (getFactory().getInstance(clazz)); 650069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // END android-deleted 651069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 652069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 653069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 654069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 655069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 656069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Convenience method to return a named logger, without the application 657069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * having to care about factories. 658069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 659069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param name Logical name of the <code>Log</code> instance to be 660069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * returned (the meaning of this name is only known to the underlying 661069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * logging implementation that is being wrapped) 662069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 663069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception LogConfigurationException if a suitable <code>Log</code> 664069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instance cannot be returned 665069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 666069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static Log getLog(String name) 667069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws LogConfigurationException { 668069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 669069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // BEGIN android-added 670069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return new org.apache.commons.logging.impl.Jdk14Logger(name); 671069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // END android-added 672069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // BEGIN android-deleted 673069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project //return (getFactory().getInstance(name)); 674069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // END android-deleted 675069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 676069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 677069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 678069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 679069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 680069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Release any internal references to previously created {@link LogFactory} 681069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instances that have been associated with the specified class loader 682069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * (if any), after calling the instance method <code>release()</code> on 683069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * each of them. 684069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 685069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param classLoader ClassLoader for which to release the LogFactory 686069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 687069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static void release(ClassLoader classLoader) { 688069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 689069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 690069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("Releasing factory for classloader " + objectId(classLoader)); 691069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 692069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project synchronized (factories) { 693069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader == null) { 694069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (nullClassLoaderFactory != null) { 695069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project nullClassLoaderFactory.release(); 696069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project nullClassLoaderFactory = null; 697069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 698069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 699069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project LogFactory factory = (LogFactory) factories.get(classLoader); 700069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factory != null) { 701069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory.release(); 702069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factories.remove(classLoader); 703069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 704069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 705069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 706069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 707069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 708069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 709069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 710069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 711069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Release any internal references to previously created {@link LogFactory} 712069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * instances, after calling the instance method <code>release()</code> on 713069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * each of them. This is useful in environments like servlet containers, 714069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * which implement application reloading by throwing away a ClassLoader. 715069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Dangling references to objects in that class loader would prevent 716069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * garbage collection. 717069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 718069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static void releaseAll() { 719069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 720069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 721069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("Releasing factory for all classloaders."); 722069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 723069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project synchronized (factories) { 724069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Enumeration elements = factories.elements(); 725069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while (elements.hasMoreElements()) { 726069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project LogFactory element = (LogFactory) elements.nextElement(); 727069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project element.release(); 728069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 729069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factories.clear(); 730069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 731069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (nullClassLoaderFactory != null) { 732069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project nullClassLoaderFactory.release(); 733069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project nullClassLoaderFactory = null; 734069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 735069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 736069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 737069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 738069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 739069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 740069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ------------------------------------------------------ Protected Methods 741069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 742069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 743069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Safely get access to the classloader for the specified class. 744069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 745069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Theoretically, calling getClassLoader can throw a security exception, 746069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * and so should be done under an AccessController in order to provide 747069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * maximum flexibility. However in practice people don't appear to use 748069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * security policies that forbid getClassLoader calls. So for the moment 749069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * all code is written to call this method rather than Class.getClassLoader, 750069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * so that we could put AccessController stuff in this method without any 751069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * disruption later if we need to. 752069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 753069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Even when using an AccessController, however, this method can still 754069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * throw SecurityException. Commons-logging basically relies on the 755069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ability to access classloaders, ie a policy that forbids all 756069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloader access will also prevent commons-logging from working: 757069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * currently this method will throw an exception preventing the entire app 758069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * from starting up. Maybe it would be good to detect this situation and 759069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * just disable all commons-logging? Not high priority though - as stated 760069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * above, security policies that prevent classloader access aren't common. 761069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 762069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 763069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 764069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static ClassLoader getClassLoader(Class clazz) { 765069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 766069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return clazz.getClassLoader(); 767069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(SecurityException ex) { 768069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 769069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 770069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Unable to get classloader for class '" + clazz 771069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' due to security restrictions - " + ex.getMessage()); 772069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 773069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw ex; 774069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 775069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 776069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 777069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 778069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Calls LogFactory.directGetContextClassLoader under the control of an 779069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * AccessController class. This means that java code running under a 780069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * security manager that forbids access to ClassLoaders will still work 781069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * if this class is given appropriate privileges, even when the caller 782069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * doesn't have such privileges. Without using an AccessController, the 783069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the entire call stack must have the privilege before the call is 784069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * allowed. 785069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 786069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the context classloader associated with the current thread, 787069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or null if security doesn't allow it. 788069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 789069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws LogConfigurationException if there was some weird error while 790069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * attempting to get the context classloader. 791069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 792069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws SecurityException if the current java security policy doesn't 793069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * allow this class to access the context classloader. 794069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 795069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static ClassLoader getContextClassLoader() 796069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws LogConfigurationException { 797069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 798069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (ClassLoader)AccessController.doPrivileged( 799069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project new PrivilegedAction() { 800069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object run() { 801069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return directGetContextClassLoader(); 802069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 803069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project }); 804069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 805069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 806069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 807069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Return the thread context class loader if available; otherwise return 808069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * null. 809069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 810069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Most/all code should call getContextClassLoader rather than calling 811069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * this method directly. 812069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 813069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The thread context class loader is available for JDK 1.2 814069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or later, if certain security conditions are met. 815069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 816069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Note that no internal logging is done within this method because 817069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * this method is called every time LogFactory.getLogger() is called, 818069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * and we don't want too much output generated here. 819069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 820069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception LogConfigurationException if a suitable class loader 821069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * cannot be identified. 822069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 823069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception SecurityException if the java security policy forbids 824069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * access to the context classloader from one of the classes in the 825069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * current call stack. 826069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 827069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 828069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static ClassLoader directGetContextClassLoader() 829069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws LogConfigurationException 830069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project { 831069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader classLoader = null; 832069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 833069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 834069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Are we running on a JDK 1.2 or later system? 835069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Method method = Thread.class.getMethod("getContextClassLoader", 836069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (Class[]) null); 837069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 838069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Get the thread context class loader (if there is one) 839069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 840069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project classLoader = (ClassLoader)method.invoke(Thread.currentThread(), 841069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (Object[]) null); 842069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (IllegalAccessException e) { 843069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new LogConfigurationException 844069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Unexpected IllegalAccessException", e); 845069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (InvocationTargetException e) { 846069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 847069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * InvocationTargetException is thrown by 'invoke' when 848069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the method being invoked (getContextClassLoader) throws 849069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * an exception. 850069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 851069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * getContextClassLoader() throws SecurityException when 852069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the context class loader isn't an ancestor of the 853069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * calling class's class loader, or if security 854069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * permissions are restricted. 855069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 856069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * In the first case (not related), we want to ignore and 857069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * keep going. We cannot help but also ignore the second 858069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the logic below, but other calls elsewhere (to 859069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * obtain a class loader) will trigger this exception where 860069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * we can make a distinction. 861069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 862069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (e.getTargetException() instanceof SecurityException) { 863069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ; // ignore 864069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 865069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Capture 'e.getTargetException()' exception for details 866069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // alternate: log 'e.getTargetException()', and pass back 'e'. 867069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new LogConfigurationException 868069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ("Unexpected InvocationTargetException", e.getTargetException()); 869069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 870069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 871069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (NoSuchMethodException e) { 872069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Assume we are running on JDK 1.1 873069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project classLoader = getClassLoader(LogFactory.class); 874069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 875069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // We deliberately don't log a message here to outputStream; 876069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // this message would be output for every call to LogFactory.getLog() 877069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // when running on JDK1.1 878069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 879069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // if (outputStream != null) { 880069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // outputStream.println( 881069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // "Method Thread.getContextClassLoader does not exist;" 882069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // + " assuming this is JDK 1.1, and that the context" 883069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // + " classloader is the same as the class that loaded" 884069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // + " the concrete LogFactory class."); 885069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // } 886069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 887069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 888069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 889069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Return the selected class loader 890069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return classLoader; 891069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 892069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 893069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 894069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Check cached factories (keyed by contextClassLoader) 895069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 896069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param contextClassLoader is the context classloader associated 897069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the current thread. This allows separate LogFactory objects 898069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * per component within a container, provided each component has 899069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * a distinct context classloader set. This parameter may be null 900069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * in JDK1.1, and in embedded systems where jcl-using code is 901069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * placed in the bootclasspath. 902069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 903069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return the factory associated with the specified classloader if 904069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * one has previously been created, or null if this is the first time 905069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * we have seen this particular classloader. 906069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 907069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static LogFactory getCachedFactory(ClassLoader contextClassLoader) 908069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project { 909069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project LogFactory factory = null; 910069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 911069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (contextClassLoader == null) { 912069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // We have to handle this specially, as factories is a Hashtable 913069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // and those don't accept null as a key value. 914069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 915069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // nb: nullClassLoaderFactory might be null. That's ok. 916069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory = nullClassLoaderFactory; 917069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 918069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factory = (LogFactory) factories.get(contextClassLoader); 919069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 920069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 921069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return factory; 922069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 923069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 924069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 925069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Remember this factory, so later calls to LogFactory.getCachedFactory 926069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * can return the previously created object (together with all its 927069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * cached Log objects). 928069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 929069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param classLoader should be the current context classloader. Note that 930069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * this can be null under some circumstances; this is ok. 931069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 932069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param factory should be the factory to cache. This should never be null. 933069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 934069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static void cacheFactory(ClassLoader classLoader, LogFactory factory) 935069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project { 936069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Ideally we would assert(factory != null) here. However reporting 937069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // errors from within a logging implementation is a little tricky! 938069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 939069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (factory != null) { 940069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader == null) { 941069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project nullClassLoaderFactory = factory; 942069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 943069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factories.put(classLoader, factory); 944069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 945069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 946069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 947069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 948069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 949069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Return a new instance of the specified <code>LogFactory</code> 950069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * implementation class, loaded by the specified class loader. 951069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If that fails, try the class loader used to load this 952069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * (abstract) LogFactory. 953069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 954069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <h2>ClassLoader conflicts</h2> 955069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Note that there can be problems if the specified ClassLoader is not the 956069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * same as the classloader that loaded this class, ie when loading a 957069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * concrete LogFactory subclass via a context classloader. 958069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 959069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The problem is the same one that can occur when loading a concrete Log 960069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * subclass via a context classloader. 961069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 962069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The problem occurs when code running in the context classloader calls 963069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class X which was loaded via a parent classloader, and class X then calls 964069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * LogFactory.getFactory (either directly or via LogFactory.getLog). Because 965069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class X was loaded via the parent, it binds to LogFactory loaded via 966069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the parent. When the code in this method finds some LogFactoryYYYY 967069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class in the child (context) classloader, and there also happens to be a 968069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * LogFactory class defined in the child classloader, then LogFactoryYYYY 969069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * will be bound to LogFactory@childloader. It cannot be cast to 970069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * LogFactory@parentloader, ie this method cannot return the object as 971069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the desired type. Note that it doesn't matter if the LogFactory class 972069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * in the child classloader is identical to the LogFactory class in the 973069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * parent classloader, they are not compatible. 974069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 975069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The solution taken here is to simply print out an error message when 976069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * this occurs then throw an exception. The deployer of the application 977069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * must ensure they remove all occurrences of the LogFactory class from 978069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the child classloader in order to resolve the issue. Note that they 979069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * do not have to move the custom LogFactory subclass; that is ok as 980069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * long as the only LogFactory class it can find to bind to is in the 981069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * parent classloader. 982069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 983069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param factoryClass Fully qualified name of the <code>LogFactory</code> 984069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * implementation class 985069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param classLoader ClassLoader from which to load this class 986069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param contextClassLoader is the context that this new factory will 987069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * manage logging for. 988069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 989069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @exception LogConfigurationException if a suitable instance 990069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * cannot be created 991069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 992069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 993069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static LogFactory newFactory(final String factoryClass, 994069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final ClassLoader classLoader, 995069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final ClassLoader contextClassLoader) 996069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throws LogConfigurationException 997069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project { 998069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Note that any unchecked exceptions thrown by the createFactory 999069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // method will propagate out of this method; in particular a 1000069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ClassCastException can be thrown. 1001069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object result = AccessController.doPrivileged( 1002069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project new PrivilegedAction() { 1003069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object run() { 1004069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return createFactory(factoryClass, classLoader); 1005069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1006069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project }); 1007069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1008069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (result instanceof LogConfigurationException) { 1009069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project LogConfigurationException ex = (LogConfigurationException) result; 1010069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1011069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1012069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "An error occurred while loading the factory class:" 1013069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + ex.getMessage()); 1014069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1015069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw ex; 1016069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1017069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1018069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1019069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Created object " + objectId(result) 1020069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " to manage classloader " + objectId(contextClassLoader)); 1021069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1022069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (LogFactory)result; 1023069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1024069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1025069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1026069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Method provided for backwards compatibility; see newFactory version that 1027069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * takes 3 parameters. 1028069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1029069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This method would only ever be called in some rather odd situation. 1030069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Note that this method is static, so overriding in a subclass doesn't 1031069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * have any effect unless this method is called from a method in that 1032069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * subclass. However this method only makes sense to use from the 1033069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * getFactory method, and as that is almost always invoked via 1034069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * LogFactory.getFactory, any custom definition in a subclass would be 1035069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * pointless. Only a class with a custom getFactory method, then invoked 1036069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * directly via CustomFactoryImpl.getFactory or similar would ever call 1037069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * this. Anyway, it's here just in case, though the "managed class loader" 1038069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * value output to the diagnostics will not report the correct value. 1039069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1040069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static LogFactory newFactory(final String factoryClass, 1041069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final ClassLoader classLoader) { 1042069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return newFactory(factoryClass, classLoader, null); 1043069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1044069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1045069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1046069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Implements the operations described in the javadoc for newFactory. 1047069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1048069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param factoryClass 1049069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1050069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param classLoader used to load the specified factory class. This is 1051069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * expected to be either the TCCL or the classloader which loaded this 1052069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class. Note that the classloader which loaded this class might be 1053069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "null" (ie the bootloader) for embedded systems. 1054069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1055069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return either a LogFactory object or a LogConfigurationException object. 1056069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 1057069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1058069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static Object createFactory(String factoryClass, ClassLoader classLoader) { 1059069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1060069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This will be used to diagnose bad configurations 1061069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // and allow a useful message to be sent to the user 1062069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Class logFactoryClass = null; 1063069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1064069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader != null) { 1065069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1066069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // First the given class loader param (thread class loader) 1067069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1068069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Warning: must typecast here & allow exception 1069069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // to be generated/caught & recast properly. 1070069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logFactoryClass = classLoader.loadClass(factoryClass); 1071069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (LogFactory.class.isAssignableFrom(logFactoryClass)) { 1072069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1073069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1074069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Loaded class " + logFactoryClass.getName() 1075069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " from classloader " + objectId(classLoader)); 1076069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1077069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1078069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1079069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This indicates a problem with the ClassLoader tree. 1080069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // An incompatible ClassLoader was used to load the 1081069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // implementation. 1082069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // As the same classes 1083069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // must be available in multiple class loaders, 1084069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // it is very likely that multiple JCL jars are present. 1085069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // The most likely fix for this 1086069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // problem is to remove the extra JCL jars from the 1087069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ClassLoader hierarchy. 1088069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1089069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1090069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1091069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Factory class " + logFactoryClass.getName() 1092069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " loaded from classloader " + objectId(logFactoryClass.getClassLoader()) 1093069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " does not extend '" + LogFactory.class.getName() 1094069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' as loaded by this classloader."); 1095069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logHierarchy("[BAD CL TREE] ", classLoader); 1096069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1097069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1098069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1099069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (LogFactory) logFactoryClass.newInstance(); 1100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (ClassNotFoundException ex) { 1102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader == thisClassLoader) { 1103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Nothing more to try, onwards. 1104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Unable to locate any class called '" + factoryClass 1107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' via classloader " + objectId(classLoader)); 1108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw ex; 1110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ignore exception, continue 1112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (NoClassDefFoundError e) { 1113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader == thisClassLoader) { 1114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Nothing more to try, onwards. 1115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Class '" + factoryClass + "' cannot be loaded" 1118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " via classloader " + objectId(classLoader) 1119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " - it depends on some other class that cannot" 1120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " be found."); 1121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw e; 1123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ignore exception, continue 1125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(ClassCastException e) { 1126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader == thisClassLoader) { 1127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // There's no point in falling through to the code below that 1128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // tries again with thisClassLoader, because we've just tried 1129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // loading with that loader (not the TCCL). Just throw an 1130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // appropriate exception here. 1131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final boolean implementsLogFactory = implementsLogFactory(logFactoryClass); 1133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Construct a good message: users may not actual expect that a custom implementation 1136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // has been specified. Several well known containers use this mechanism to adapt JCL 1137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // to their native logging system. 1138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String msg = 1140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "The application has specified that a custom LogFactory implementation should be used but " + 1141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Class '" + factoryClass + "' cannot be converted to '" 1142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + LogFactory.class.getName() + "'. "; 1143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (implementsLogFactory) { 1144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project msg = msg + "The conflict is caused by the presence of multiple LogFactory classes in incompatible classloaders. " + 1145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Background can be found in http://jakarta.apache.org/commons/logging/tech.html. " + 1146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "If you have not explicitly specified a custom LogFactory then it is likely that " + 1147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "the container has set one without your knowledge. " + 1148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "In this case, consider using the commons-logging-adapters.jar file or " + 1149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "specifying the standard LogFactory from the command line. "; 1150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project msg = msg + "Please check the custom implementation. "; 1152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project msg = msg + "Help can be found @http://jakarta.apache.org/commons/logging/troubleshooting.html."; 1154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic(msg); 1157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassCastException ex = new ClassCastException(msg); 1160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw ex; 1161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Ignore exception, continue. Presumably the classloader was the 1164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // TCCL; the code below will try to load the class via thisClassLoader. 1165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This will handle the case where the original calling class is in 1166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // a shared classpath but the TCCL has a copy of LogFactory and the 1167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // specified LogFactory implementation; we will fall back to using the 1168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // LogFactory implementation from the same classloader as this class. 1169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Issue: this doesn't handle the reverse case, where this LogFactory 1171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // is in the webapp, and the specified LogFactory implementation is 1172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // in a shared classpath. In that case: 1173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // (a) the class really does implement LogFactory (bad log msg above) 1174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // (b) the fallback code will result in exactly the same problem. 1175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /* At this point, either classLoader == null, OR 1179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classLoader was unable to load factoryClass. 1180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * In either case, we call Class.forName, which is equivalent 1182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to LogFactory.class.getClassLoader().load(name), ie we ignore 1183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the classloader parameter the caller passed, and fall back 1184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to trying the classloader associated with this class. See the 1185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * javadoc for the newFactory method for more info on the 1186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * consequences of this. 1187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Notes: 1189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * * LogFactory.class.getClassLoader() may return 'null' 1190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * if LogFactory is loaded by the bootstrap classloader. 1191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Warning: must typecast here & allow exception 1193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // to be generated/caught & recast properly. 1194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Unable to load factory class via classloader " 1197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + objectId(classLoader) 1198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " - trying the classloader associated with this LogFactory."); 1199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logFactoryClass = Class.forName(factoryClass); 1201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (LogFactory) logFactoryClass.newInstance(); 1202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (Exception e) { 1203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Check to see if we've got a bad configuration 1204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("Unable to create LogFactory instance."); 1206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (logFactoryClass != null 1208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project && !LogFactory.class.isAssignableFrom(logFactoryClass)) { 1209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return new LogConfigurationException( 1211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "The chosen LogFactory implementation does not extend LogFactory." 1212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " Please check your configuration.", 1213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project e); 1214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return new LogConfigurationException(e); 1216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Determines whether the given class actually implements <code>LogFactory</code>. 1221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Diagnostic information is also logged. 1222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <strong>Usage:</strong> to diagnose whether a classloader conflict is the cause 1224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * of incompatibility. The test used is whether the class is assignable from 1225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the <code>LogFactory</code> class loaded by the class's classloader. 1226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param logFactoryClass <code>Class</code> which may implement <code>LogFactory</code> 1227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return true if the <code>logFactoryClass</code> does extend 1228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>LogFactory</code> when that class is loaded via the same 1229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloader that loaded the <code>logFactoryClass</code>. 1230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static boolean implementsLogFactory(Class logFactoryClass) { 1232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean implementsLogFactory = false; 1233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (logFactoryClass != null) { 1234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader logFactoryClassLoader = logFactoryClass.getClassLoader(); 1236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (logFactoryClassLoader == null) { 1237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[CUSTOM LOG FACTORY] was loaded by the boot classloader"); 1238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logHierarchy("[CUSTOM LOG FACTORY] ", logFactoryClassLoader); 1240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Class factoryFromCustomLoader 1241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project = Class.forName("org.apache.commons.logging.LogFactory", false, logFactoryClassLoader); 1242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project implementsLogFactory = factoryFromCustomLoader.isAssignableFrom(logFactoryClass); 1243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (implementsLogFactory) { 1244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() 1245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " implements LogFactory but was loaded by an incompatible classloader."); 1246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName() 1248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " does not implement LogFactory."); 1249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (SecurityException e) { 1252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // The application is running within a hostile security environment. 1254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This will make it very hard to diagnose issues with JCL. 1255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Consider running less securely whilst debugging this issue. 1256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[CUSTOM LOG FACTORY] SecurityException thrown whilst trying to determine whether " + 1258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "the compatibility was caused by a classloader conflict: " 1259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + e.getMessage()); 1260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (LinkageError e) { 1261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // This should be an unusual circumstance. 1263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // LinkageError's usually indicate that a dependent class has incompatibly changed. 1264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Another possibility may be an exception thrown by an initializer. 1265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Time for a clean rebuild? 1266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[CUSTOM LOG FACTORY] LinkageError thrown whilst trying to determine whether " + 1268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "the compatibility was caused by a classloader conflict: " 1269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + e.getMessage()); 1270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (ClassNotFoundException e) { 1271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // LogFactory cannot be loaded by the classloader which loaded the custom factory implementation. 1273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // The custom implementation is not viable until this is corrected. 1274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Ensure that the JCL jar and the custom class are available from the same classloader. 1275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Running with diagnostics on should give information about the classloaders used 1276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // to load the custom factory. 1277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[CUSTOM LOG FACTORY] LogFactory class cannot be loaded by classloader which loaded the " + 1279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "custom LogFactory implementation. Is the custom factory in the right classloader?"); 1280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return implementsLogFactory; 1283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Applets may run in an environment where accessing resources of a loader is 1287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * a secure operation, but where the commons-logging library has explicitly 1288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * been granted permission for that operation. In this case, we need to 1289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * run the operation using an AccessController. 1290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static InputStream getResourceAsStream(final ClassLoader loader, 1292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final String name) 1293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project { 1294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (InputStream)AccessController.doPrivileged( 1295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project new PrivilegedAction() { 1296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object run() { 1297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (loader != null) { 1298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return loader.getResourceAsStream(name); 1299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return ClassLoader.getSystemResourceAsStream(name); 1301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project }); 1304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Given a filename, return an enumeration of URLs pointing to 1308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * all the occurrences of that filename in the classpath. 1309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This is just like ClassLoader.getResources except that the 1311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * operation is done under an AccessController so that this method will 1312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * succeed when this jarfile is privileged but the caller is not. 1313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This method must therefore remain private to avoid security issues. 1314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If no instances are found, an Enumeration is returned whose 1316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * hasMoreElements method returns false (ie an "empty" enumeration). 1317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * If resources could not be listed for some reason, null is returned. 1318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static Enumeration getResources(final ClassLoader loader, 1320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final String name) 1321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project { 1322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project PrivilegedAction action = 1323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project new PrivilegedAction() { 1324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object run() { 1325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (loader != null) { 1327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return loader.getResources(name); 1328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return ClassLoader.getSystemResources(name); 1330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(IOException e) { 1332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "Exception while trying to find configuration file " 1335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + name + ":" + e.getMessage()); 1336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return null; 1338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(NoSuchMethodError e) { 1339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // we must be running on a 1.1 JVM which doesn't support 1340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ClassLoader.getSystemResources; just return null in 1341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // this case. 1342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return null; 1343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project }; 1346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object result = AccessController.doPrivileged(action); 1347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (Enumeration) result; 1348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Given a URL that refers to a .properties file, load that file. 1352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This is done under an AccessController so that this method will 1353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * succeed when this jarfile is privileged but the caller is not. 1354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This method must therefore remain private to avoid security issues. 1355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Null is returned if the URL cannot be opened. 1357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static Properties getProperties(final URL url) { 1359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project PrivilegedAction action = 1360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project new PrivilegedAction() { 1361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object run() { 1362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project InputStream stream = url.openStream(); 1364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (stream != null) { 1365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Properties props = new Properties(); 1366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project props.load(stream); 1367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project stream.close(); 1368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return props; 1369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(IOException e) { 1371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("Unable to read URL " + url); 1373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return null; 1377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project }; 1379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (Properties) AccessController.doPrivileged(action); 1380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Locate a user-provided configuration file. 1384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The classpath of the specified classLoader (usually the context classloader) 1386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * is searched for properties files of the specified name. If none is found, 1387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * null is returned. If more than one is found, then the file with the greatest 1388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * value for its PRIORITY property is returned. If multiple files have the 1389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * same PRIORITY value then the first in the classpath is returned. 1390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This differs from the 1.0.x releases; those always use the first one found. 1392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * However as the priority is a new field, this change is backwards compatible. 1393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The purpose of the priority field is to allow a webserver administrator to 1395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * override logging settings in all webapps by placing a commons-logging.properties 1396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * file in a shared classpath location with a priority > 0; this overrides any 1397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * commons-logging.properties files without priorities which are in the 1398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * webapps. Webapps can also use explicit priorities to override a configuration 1399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * file in the shared classpath if needed. 1400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static final Properties getConfigurationFile( 1402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader classLoader, String fileName) { 1403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Properties props = null; 1405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project double priority = 0.0; 1406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project URL propsUrl = null; 1407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Enumeration urls = getResources(classLoader, fileName); 1409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (urls == null) { 1411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return null; 1412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while (urls.hasMoreElements()) { 1415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project URL url = (URL) urls.nextElement(); 1416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Properties newProps = getProperties(url); 1418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (newProps != null) { 1419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (props == null) { 1420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project propsUrl = url; 1421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project props = newProps; 1422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String priorityStr = props.getProperty(PRIORITY_KEY); 1423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project priority = 0.0; 1424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (priorityStr != null) { 1425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project priority = Double.parseDouble(priorityStr); 1426069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1427069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1428069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1429069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1430069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Properties file found at '" + url + "'" 1431069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " with priority " + priority); 1432069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1433069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1434069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String newPriorityStr = newProps.getProperty(PRIORITY_KEY); 1435069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project double newPriority = 0.0; 1436069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (newPriorityStr != null) { 1437069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project newPriority = Double.parseDouble(newPriorityStr); 1438069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1439069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1440069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (newPriority > priority) { 1441069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1442069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1443069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Properties file at '" + url + "'" 1444069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " with priority " + newPriority 1445069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " overrides file at '" + propsUrl + "'" 1446069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " with priority " + priority); 1447069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1448069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1449069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project propsUrl = url; 1450069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project props = newProps; 1451069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project priority = newPriority; 1452069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1453069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1454069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1455069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Properties file at '" + url + "'" 1456069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " with priority " + newPriority 1457069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " does not override file at '" + propsUrl + "'" 1458069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + " with priority " + priority); 1459069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1460069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1461069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1462069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1463069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1464069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1465069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch (SecurityException e) { 1466069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1467069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("SecurityException thrown while trying to find/read config files."); 1468069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1469069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1470069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1471069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1472069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (props == null) { 1473069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1474069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] No properties file of name '" + fileName 1475069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' found."); 1476069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1477069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1478069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[LOOKUP] Properties file of name '" + fileName 1479069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + "' found at '" + propsUrl + '"'); 1480069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1481069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1482069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1483069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return props; 1484069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1485069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1486069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1487069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Determines whether the user wants internal diagnostic output. If so, 1488069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * returns an appropriate writer object. Users can enable diagnostic 1489069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * output by setting the system property named {@link #DIAGNOSTICS_DEST_PROPERTY} to 1490069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * a filename, or the special values STDOUT or STDERR. 1491069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1492069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static void initDiagnostics() { 1493069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String dest; 1494069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1495069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project dest = System.getProperty(DIAGNOSTICS_DEST_PROPERTY); 1496069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (dest == null) { 1497069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return; 1498069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1499069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(SecurityException ex) { 1500069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // We must be running in some very secure environment. 1501069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // We just have to assume output is not wanted.. 1502069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return; 1503069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1504069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1505069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (dest.equals("STDOUT")) { 1506069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream = System.out; 1507069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else if (dest.equals("STDERR")) { 1508069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream = System.err; 1509069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1510069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1511069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // open the file in append mode 1512069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project FileOutputStream fos = new FileOutputStream(dest, true); 1513069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream = new PrintStream(fos); 1514069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(IOException ex) { 1515069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // We should report this to the user - but how? 1516069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return; 1517069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1518069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1519069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1520069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // In order to avoid confusion where multiple instances of JCL are 1521069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // being used via different classloaders within the same app, we 1522069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ensure each logged message has a prefix of form 1523069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // [LogFactory from classloader OID] 1524069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1525069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Note that this prefix should be kept consistent with that 1526069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // in LogFactoryImpl. However here we don't need to output info 1527069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // about the actual *instance* of LogFactory, as all methods that 1528069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // output diagnostics from this class are static. 1529069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String classLoaderName; 1530069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1531069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader classLoader = thisClassLoader; 1532069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (thisClassLoader == null) { 1533069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project classLoaderName = "BOOTLOADER"; 1534069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1535069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project classLoaderName = objectId(classLoader); 1536069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1537069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(SecurityException e) { 1538069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project classLoaderName = "UNKNOWN"; 1539069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1540069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticPrefix = "[LogFactory from " + classLoaderName + "] "; 1541069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1542069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1543069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1544069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Indicates true if the user has enabled internal logging. 1545069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1546069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * By the way, sorry for the incorrect grammar, but calling this method 1547069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * areDiagnosticsEnabled just isn't java beans style. 1548069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1549069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return true if calls to logDiagnostic will have any effect. 1550069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 1551069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1552069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static boolean isDiagnosticsEnabled() { 1553069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return diagnosticsStream != null; 1554069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1555069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1556069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1557069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Write the specified message to the internal logging destination. 1558069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1559069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Note that this method is private; concrete subclasses of this class 1560069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * should not call it because the diagnosticPrefix string this 1561069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * method puts in front of all its messages is LogFactory@...., 1562069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * while subclasses should put SomeSubClass@... 1563069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1564069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Subclasses should instead compute their own prefix, then call 1565069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * logRawDiagnostic. Note that calling isDiagnosticsEnabled is 1566069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * fine for subclasses. 1567069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1568069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Note that it is safe to call this method before initDiagnostics 1569069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * is called; any output will just be ignored (as isDiagnosticsEnabled 1570069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * will return false). 1571069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1572069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param msg is the diagnostic message to be output. 1573069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1574069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static final void logDiagnostic(String msg) { 1575069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (diagnosticsStream != null) { 1576069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream.print(diagnosticPrefix); 1577069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream.println(msg); 1578069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream.flush(); 1579069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1580069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1581069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1582069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1583069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Write the specified message to the internal logging destination. 1584069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1585069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param msg is the diagnostic message to be output. 1586069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 1587069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1588069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected static final void logRawDiagnostic(String msg) { 1589069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (diagnosticsStream != null) { 1590069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream.println(msg); 1591069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project diagnosticsStream.flush(); 1592069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1593069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1594069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1595069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1596069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Generate useful diagnostics regarding the classloader tree for 1597069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the specified class. 1598069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1599069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * As an example, if the specified class was loaded via a webapp's 1600069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloader, then you may get the following output: 1601069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <pre> 1602069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Class com.acme.Foo was loaded via classloader 11111 1603069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ClassLoader tree: 11111 -> 22222 (SYSTEM) -> 33333 -> BOOT 1604069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </pre> 1605069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1606069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This method returns immediately if isDiagnosticsEnabled() 1607069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * returns false. 1608069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1609069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param clazz is the class whose classloader + tree are to be 1610069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * output. 1611069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1612069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static void logClassLoaderEnvironment(Class clazz) { 1613069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isDiagnosticsEnabled()) { 1614069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return; 1615069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1616069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1617069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1618069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[ENV] Extension directories (java.ext.dir): " + System.getProperty("java.ext.dir")); 1619069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[ENV] Application classpath (java.class.path): " + System.getProperty("java.class.path")); 1620069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(SecurityException ex) { 1621069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("[ENV] Security setting prevent interrogation of system classpaths."); 1622069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1623069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1624069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String className = clazz.getName(); 1625069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader classLoader; 1626069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1627069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1628069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project classLoader = getClassLoader(clazz); 1629069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(SecurityException ex) { 1630069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // not much useful diagnostics we can print here! 1631069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1632069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[ENV] Security forbids determining the classloader for " + className); 1633069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return; 1634069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1635069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1636069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1637069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project "[ENV] Class " + className + " was loaded via classloader " 1638069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project + objectId(classLoader)); 1639069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logHierarchy("[ENV] Ancestry of classloader which loaded " + className + " is ", classLoader); 1640069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1641069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1642069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1643069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Logs diagnostic messages about the given classloader 1644069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * and it's hierarchy. The prefix is prepended to the message 1645069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * and is intended to make it easier to understand the logs. 1646069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param prefix 1647069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param classLoader 1648069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1649069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static void logHierarchy(String prefix, ClassLoader classLoader) { 1650069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isDiagnosticsEnabled()) { 1651069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return; 1652069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1653069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ClassLoader systemClassLoader; 1654069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader != null) { 1655069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final String classLoaderString = classLoader.toString(); 1656069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic(prefix + objectId(classLoader) + " == '" + classLoaderString + "'"); 1657069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1658069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1659069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1660069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project systemClassLoader = ClassLoader.getSystemClassLoader(); 1661069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(SecurityException ex) { 1662069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic( 1663069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project prefix + "Security forbids determining the system classloader."); 1664069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return; 1665069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1666069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader != null) { 1667069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project StringBuffer buf = new StringBuffer(prefix + "ClassLoader tree:"); 1668069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project for(;;) { 1669069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project buf.append(objectId(classLoader)); 1670069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader == systemClassLoader) { 1671069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project buf.append(" (SYSTEM) "); 1672069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1673069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1674069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project try { 1675069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project classLoader = classLoader.getParent(); 1676069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } catch(SecurityException ex) { 1677069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project buf.append(" --> SECRET"); 1678069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 1679069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1680069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1681069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project buf.append(" --> "); 1682069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (classLoader == null) { 1683069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project buf.append("BOOT"); 1684069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 1685069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1686069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1687069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic(buf.toString()); 1688069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1689069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1690069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1691069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 1692069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Returns a string that uniquely identifies the specified object, including 1693069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * its class. 1694069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 1695069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The returned string is of form "classname@hashcode", ie is the same as 1696069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the return value of the Object.toString() method, but works even when 1697069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the specified object's class has overidden the toString method. 1698069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 1699069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param o may be null. 1700069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return a string of form classname@hashcode, or "null" if param o is null. 1701069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 1702069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 1703069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public static String objectId(Object o) { 1704069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (o == null) { 1705069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return "null"; 1706069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 1707069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return o.getClass().getName() + "@" + System.identityHashCode(o); 1708069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1709069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1710069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1711069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ---------------------------------------------------------------------- 1712069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Static initialiser block to perform initialisation at class load time. 1713069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1714069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // We can't do this in the class constructor, as there are many 1715069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // static methods on this class that can be called before any 1716069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // LogFactory instances are created, and they depend upon this 1717069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // stuff having been set up. 1718069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1719069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Note that this block must come after any variable declarations used 1720069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // by any methods called from this block, as we want any static initialiser 1721069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // associated with the variable to run first. If static initialisers for 1722069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // variables run after this code, then (a) their value might be needed 1723069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // by methods called from here, and (b) they might *override* any value 1724069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // computed here! 1725069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // 1726069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // So the wisest thing to do is just to place this code at the very end 1727069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // of the class file. 1728069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // ---------------------------------------------------------------------- 1729069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 1730069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project static { 1731069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // note: it's safe to call methods before initDiagnostics. 1732069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project thisClassLoader = getClassLoader(LogFactory.class); 1733069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project initDiagnostics(); 1734069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logClassLoaderEnvironment(LogFactory.class); 1735069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project factories = createFactoryStore(); 1736069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isDiagnosticsEnabled()) { 1737069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project logDiagnostic("BOOTSTRAP COMPLETED"); 1738069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1739069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 1740069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project} 1741