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     *  &lt;java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}"&gt;
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *     ...
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *     &lt;sysproperty
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *        key="org.apache.commons.logging.LogFactory.HashtableImpl"
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *        value="org.apache.commons.logging.AltHashtable"/&gt;
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  &lt;/java&gt;
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