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