1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Copyright 2001-2004 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.impl;
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.reflect.Constructor;
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.reflect.InvocationTargetException;
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.reflect.Method;
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.net.URL;
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Enumeration;
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Hashtable;
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.Vector;
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.logging.Log;
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.logging.LogConfigurationException;
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.logging.LogFactory;
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>Concrete subclass of {@link LogFactory} that implements the
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * following algorithm to dynamically select a logging implementation
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class to instantiate a wrapper for.</p>
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <ul>
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>Use a factory configuration attribute named
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *     <code>org.apache.commons.logging.Log</code> to identify the
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *     requested implementation class.</li>
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>Use the <code>org.apache.commons.logging.Log</code> system property
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *     to identify the requested implementation class.</li>
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>If <em>Log4J</em> is available, return an instance of
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *     <code>org.apache.commons.logging.impl.Log4JLogger</code>.</li>
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>If <em>JDK 1.4 or later</em> is available, return an instance of
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *     <code>org.apache.commons.logging.impl.Jdk14Logger</code>.</li>
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>Otherwise, return an instance of
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *     <code>org.apache.commons.logging.impl.SimpleLog</code>.</li>
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </ul>
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>If the selected {@link Log} implementation class has a
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>setLogFactory()</code> method that accepts a {@link LogFactory}
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * parameter, this method will be called on each newly created instance
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to identify the associated factory.  This makes factory configuration
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * attributes available to the Log instance, if it so desires.</p>
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>This factory will remember previously created <code>Log</code> instances
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * for the same name, and will return them on repeated requests to the
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>getInstance()</code> method.</p>
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Rod Waldhoff
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Craig R. McClanahan
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Richard A. Sitze
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Brian Stansberry
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Revision: 399224 $ $Date: 2006-05-03 10:25:54 +0100 (Wed, 03 May 2006) $
66d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *
67d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * @deprecated Please use {@link java.net.URL#openConnection} instead.
68d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
69d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     for further details.
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
72d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath@Deprecated
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class LogFactoryImpl extends LogFactory {
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** Log4JLogger class name */
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String LOGGING_IMPL_LOG4J_LOGGER = "org.apache.commons.logging.impl.Log4JLogger";
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** Jdk14Logger class name */
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String LOGGING_IMPL_JDK14_LOGGER = "org.apache.commons.logging.impl.Jdk14Logger";
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** Jdk13LumberjackLogger class name */
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String LOGGING_IMPL_LUMBERJACK_LOGGER = "org.apache.commons.logging.impl.Jdk13LumberjackLogger";
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /** SimpleLog class name */
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String LOGGING_IMPL_SIMPLE_LOGGER = "org.apache.commons.logging.impl.SimpleLog";
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String PKG_IMPL="org.apache.commons.logging.impl.";
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final int PKG_LEN = PKG_IMPL.length();
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // ----------------------------------------------------------- Constructors
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Public no-arguments constructor required by the lookup mechanism.
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public LogFactoryImpl() {
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        super();
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        initDiagnostics();  // method on this object
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("Instance created.");
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // ----------------------------------------------------- Manifest Constants
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The name (<code>org.apache.commons.logging.Log</code>) of the system
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * property identifying our {@link Log} implementation class.
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public static final String LOG_PROPERTY =
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        "org.apache.commons.logging.Log";
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The deprecated system property used for backwards compatibility with
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * old versions of JCL.
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected static final String LOG_PROPERTY_OLD =
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        "org.apache.commons.logging.log";
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The name (<code>org.apache.commons.logging.Log.allowFlawedContext</code>)
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * of the system property which can be set true/false to
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * determine system behaviour when a bad context-classloader is encountered.
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * When set to false, a LogConfigurationException is thrown if
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * LogFactoryImpl is loaded via a child classloader of the TCCL (this
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * should never happen in sane systems).
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Default behaviour: true (tolerates bad context classloaders)
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See also method setAttribute.
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public static final String ALLOW_FLAWED_CONTEXT_PROPERTY =
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        "org.apache.commons.logging.Log.allowFlawedContext";
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The name (<code>org.apache.commons.logging.Log.allowFlawedDiscovery</code>)
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * of the system property which can be set true/false to
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * determine system behaviour when a bad logging adapter class is
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * encountered during logging discovery. When set to false, an
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * exception will be thrown and the app will fail to start. When set
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * to true, discovery will continue (though the user might end up
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * with a different logging implementation than they expected).
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Default behaviour: true (tolerates bad logging adapters)
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See also method setAttribute.
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public static final String ALLOW_FLAWED_DISCOVERY_PROPERTY =
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        "org.apache.commons.logging.Log.allowFlawedDiscovery";
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The name (<code>org.apache.commons.logging.Log.allowFlawedHierarchy</code>)
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * of the system property which can be set true/false to
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * determine system behaviour when a logging adapter class is
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * encountered which has bound to the wrong Log class implementation.
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * When set to false, an exception will be thrown and the app will fail
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * to start. When set to true, discovery will continue (though the user
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * might end up with a different logging implementation than they expected).
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Default behaviour: true (tolerates bad Log class hierarchy)
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See also method setAttribute.
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public static final String ALLOW_FLAWED_HIERARCHY_PROPERTY =
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        "org.apache.commons.logging.Log.allowFlawedHierarchy";
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The names of classes that will be tried (in order) as logging
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * adapters. Each class is expected to implement the Log interface,
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * and to throw NoClassDefFound or ExceptionInInitializerError when
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * loaded if the underlying logging library is not available. Any
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * other error indicates that the underlying logging library is available
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * but broken/unusable for some reason.
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String[] classesToDiscover = {
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            LOGGING_IMPL_LOG4J_LOGGER,
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            "org.apache.commons.logging.impl.Jdk14Logger",
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            "org.apache.commons.logging.impl.Jdk13LumberjackLogger",
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            "org.apache.commons.logging.impl.SimpleLog"
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    };
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // ----------------------------------------------------- Instance Variables
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Determines whether logging classes should be loaded using the thread-context
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * classloader, or via the classloader that loaded this LogFactoryImpl class.
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean useTCCL = true;
193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The string prefixed to every message output by the logDiagnostic method.
196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private String diagnosticPrefix;
198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Configuration attributes.
202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Hashtable attributes = new Hashtable();
204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The {@link org.apache.commons.logging.Log} instances that have
208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * already been created, keyed by logger name.
209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Hashtable instances = new Hashtable();
211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Name of the class implementing the Log interface.
215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private String logClassName;
217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The one-argument constructor of the
221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * {@link org.apache.commons.logging.Log}
222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * implementation class that will be used to create new instances.
223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This value is initialized by <code>getLogConstructor()</code>,
224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * and then returned repeatedly.
225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Constructor logConstructor = null;
227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The signature of the Constructor to be used.
231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Class logConstructorSignature[] =
233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    { java.lang.String.class };
234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The one-argument <code>setLogFactory</code> method of the selected
238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * {@link org.apache.commons.logging.Log} method, if it exists.
239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Method logMethod = null;
241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The signature of the <code>setLogFactory</code> method to be used.
245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Class logMethodSignature[] =
247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    { LogFactory.class };
248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See getBaseClassLoader and initConfiguration.
251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean allowFlawedContext;
253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See handleFlawedDiscovery and initConfiguration.
256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean allowFlawedDiscovery;
258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See handleFlawedHierarchy and initConfiguration.
261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean allowFlawedHierarchy;
263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // --------------------------------------------------------- Public Methods
265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Return the configuration attribute with the specified name (if any),
269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * or <code>null</code> if there is no such attribute.
270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name Name of the attribute to return
272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public Object getAttribute(String name) {
274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (attributes.get(name));
276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Return an array containing the names of all currently defined
282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * configuration attributes.  If there are no such attributes, a zero
283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * length array is returned.
284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public String[] getAttributeNames() {
286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Vector names = new Vector();
288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Enumeration keys = attributes.keys();
289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (keys.hasMoreElements()) {
290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            names.addElement((String) keys.nextElement());
291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String results[] = new String[names.size()];
293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for (int i = 0; i < results.length; i++) {
294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            results[i] = (String) names.elementAt(i);
295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (results);
297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Convenience method to derive a name from the specified class and
303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * call <code>getInstance(String)</code> with it.
304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param clazz Class for which a suitable Log name will be derived
306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @exception LogConfigurationException if a suitable <code>Log</code>
308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  instance cannot be returned
309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public Log getInstance(Class clazz) throws LogConfigurationException {
311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (getInstance(clazz.getName()));
313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>Construct (if necessary) and return a <code>Log</code> instance,
319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * using the factory's current set of configuration attributes.</p>
320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p><strong>NOTE</strong> - Depending upon the implementation of
322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * the <code>LogFactory</code> you are using, the <code>Log</code>
323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * instance you are returned may or may not be local to the current
324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * application, and may or may not be returned again on a subsequent
325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * call with the same name argument.</p>
326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name Logical name of the <code>Log</code> instance to be
328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  returned (the meaning of this name is only known to the underlying
329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  logging implementation that is being wrapped)
330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @exception LogConfigurationException if a suitable <code>Log</code>
332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  instance cannot be returned
333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public Log getInstance(String name) throws LogConfigurationException {
335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Log instance = (Log) instances.get(name);
337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (instance == null) {
338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            instance = newInstance(name);
339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            instances.put(name, instance);
340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (instance);
342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Release any internal references to previously created
348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * {@link org.apache.commons.logging.Log}
349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * instances returned by this factory.  This is useful in environments
350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * like servlet containers, which implement application reloading by
351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * throwing away a ClassLoader.  Dangling references to objects in that
352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * class loader would prevent garbage collection.
353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void release() {
355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        logDiagnostic("Releasing all known loggers");
357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        instances.clear();
358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Remove any configuration attribute associated with the specified name.
363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * If there is no such attribute, no action is taken.
364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name Name of the attribute to remove
366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void removeAttribute(String name) {
368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        attributes.remove(name);
370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Set the configuration attribute with the specified name.  Calling
376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * this with a <code>null</code> value is equivalent to calling
377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <code>removeAttribute(name)</code>.
378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This method can be used to set logging configuration programmatically
380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * rather than via system properties. It can also be used in code running
381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * within a container (such as a webapp) to configure behaviour on a
382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * per-component level instead of globally as system properties would do.
383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * To use this method instead of a system property, call
384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <pre>
385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * LogFactory.getFactory().setAttribute(...)
386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * </pre>
387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This must be done before the first Log object is created; configuration
388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * changes after that point will be ignored.
389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This method is also called automatically if LogFactory detects a
391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * commons-logging.properties file; every entry in that file is set
392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * automatically as an attribute here.
393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name Name of the attribute to set
395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value Value of the attribute to set, or <code>null</code>
396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  to remove any setting for this attribute
397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void setAttribute(String name, Object value) {
399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (logConstructor != null) {
401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("setAttribute: call too late; configuration already performed.");
402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            attributes.remove(name);
406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            attributes.put(name, value);
408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (name.equals(TCCL_KEY)) {
411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            useTCCL = Boolean.valueOf(value.toString()).booleanValue();
412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // ------------------------------------------------------
418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // Static Methods
419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    //
420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // These methods only defined as workarounds for a java 1.2 bug;
421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // theoretically none of these are needed.
422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // ------------------------------------------------------
423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Gets the context classloader.
426069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This method is a workaround for a java 1.2 compiler bug.
427069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @since 1.1
428069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
429069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected static ClassLoader getContextClassLoader() throws LogConfigurationException {
430069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return LogFactory.getContextClassLoader();
431069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
432069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
433069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
434069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
435069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Workaround for bug in Java1.2; in theory this method is not needed.
436069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See LogFactory.isDiagnosticsEnabled.
437069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
438069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected static boolean isDiagnosticsEnabled() {
439069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return LogFactory.isDiagnosticsEnabled();
440069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
441069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
442069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
443069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
444069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Workaround for bug in Java1.2; in theory this method is not needed.
445069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * See LogFactory.getClassLoader.
446069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @since 1.1
447069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
448069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected static ClassLoader getClassLoader(Class clazz) {
449069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return LogFactory.getClassLoader(clazz);
450069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
451069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
452069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
453069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // ------------------------------------------------------ Protected Methods
454069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
455069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
456069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Calculate and cache a string that uniquely identifies this instance,
457069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * including which classloader the object was loaded from.
458069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
459069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This string will later be prefixed to each "internal logging" message
460069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * emitted, so that users can clearly see any unexpected behaviour.
461069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
462069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Note that this method does not detect whether internal logging is
463069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * enabled or not, nor where to output stuff if it is; that is all
464069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * handled by the parent LogFactory class. This method just computes
465069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * its own unique prefix for log messages.
466069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
467069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private void initDiagnostics() {
468069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // It would be nice to include an identifier of the context classloader
469069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // that this LogFactoryImpl object is responsible for. However that
470069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // isn't possible as that information isn't available. It is possible
471069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // to figure this out by looking at the logging from LogFactory to
472069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // see the context & impl ids from when this object was instantiated,
473069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // in order to link the impl id output as this object's prefix back to
474069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // the context it is intended to manage.
475069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Note that this prefix should be kept consistent with that
476069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // in LogFactory.
477069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Class clazz = this.getClass();
478069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ClassLoader classLoader = getClassLoader(clazz);
479069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String classLoaderName;
480069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
481069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (classLoader == null) {
482069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                classLoaderName = "BOOTLOADER";
483069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
484069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                classLoaderName = objectId(classLoader);
485069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
486069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch(SecurityException e) {
487069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            classLoaderName = "UNKNOWN";
488069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
489069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        diagnosticPrefix = "[LogFactoryImpl@" + System.identityHashCode(this) + " from " + classLoaderName + "] ";
490069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
491069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
492069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
493069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
494069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Output a diagnostic message to a user-specified destination (if the
495069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * user has enabled diagnostic logging).
496069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
497069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param msg diagnostic message
498069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @since 1.1
499069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
500069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected void logDiagnostic(String msg) {
501069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
502069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logRawDiagnostic(diagnosticPrefix + msg);
503069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
504069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
505069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
506069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
507069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Return the fully qualified Java classname of the {@link Log}
508069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * implementation we will be using.
509069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
510069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @deprecated  Never invoked by this class; subclasses should not assume
511069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *              it will be.
512069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
513069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected String getLogClassName() {
514069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
515069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (logClassName == null) {
516069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            discoverLogImplementation(getClass().getName());
517069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
518069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
519069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return logClassName;
520069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
521069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
522069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
523069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
524069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>Return the <code>Constructor</code> that can be called to instantiate
525069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * new {@link org.apache.commons.logging.Log} instances.</p>
526069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
527069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p><strong>IMPLEMENTATION NOTE</strong> - Race conditions caused by
528069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * calling this method from more than one thread are ignored, because
529069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * the same <code>Constructor</code> instance will ultimately be derived
530069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * in all circumstances.</p>
531069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
532069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @exception LogConfigurationException if a suitable constructor
533069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  cannot be returned
534069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
535069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @deprecated  Never invoked by this class; subclasses should not assume
536069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *              it will be.
537069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
538069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Constructor getLogConstructor()
539069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws LogConfigurationException {
540069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
541069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Return the previously identified Constructor (if any)
542069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (logConstructor == null) {
543069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            discoverLogImplementation(getClass().getName());
544069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
545069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
546069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return logConstructor;
547069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
548069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
549069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
550069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
551069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Is <em>JDK 1.3 with Lumberjack</em> logging available?
552069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
553069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @deprecated  Never invoked by this class; subclasses should not assume
554069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *              it will be.
555069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
556069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected boolean isJdk13LumberjackAvailable() {
557069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return isLogLibraryAvailable(
558069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "Jdk13Lumberjack",
559069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "org.apache.commons.logging.impl.Jdk13LumberjackLogger");
560069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
561069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
562069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
563069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
564069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>Return <code>true</code> if <em>JDK 1.4 or later</em> logging
565069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * is available.  Also checks that the <code>Throwable</code> class
566069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * supports <code>getStackTrace()</code>, which is required by
567069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Jdk14Logger.</p>
568069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
569069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @deprecated  Never invoked by this class; subclasses should not assume
570069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *              it will be.
571069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
572069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected boolean isJdk14Available() {
573069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return isLogLibraryAvailable(
574069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "Jdk14",
575069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "org.apache.commons.logging.impl.Jdk14Logger");
576069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
577069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
578069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
579069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
580069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Is a <em>Log4J</em> implementation available?
581069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
582069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @deprecated  Never invoked by this class; subclasses should not assume
583069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *              it will be.
584069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
585069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected boolean isLog4JAvailable() {
586069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return isLogLibraryAvailable(
587069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "Log4J",
588069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                LOGGING_IMPL_LOG4J_LOGGER);
589069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
590069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
591069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
592069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
593069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Create and return a new {@link org.apache.commons.logging.Log}
594069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * instance for the specified name.
595069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
596069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name Name of the new logger
597069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
598069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @exception LogConfigurationException if a new instance cannot
599069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  be created
600069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
601069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected Log newInstance(String name) throws LogConfigurationException {
602069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
603069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Log instance = null;
604069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
605069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (logConstructor == null) {
606069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                instance = discoverLogImplementation(name);
607069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
608069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            else {
609069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                Object params[] = { name };
610069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                instance = (Log) logConstructor.newInstance(params);
611069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
612069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
613069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (logMethod != null) {
614069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                Object params[] = { this };
615069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logMethod.invoke(instance, params);
616069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
617069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
618069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return (instance);
619069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
620069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch (LogConfigurationException lce) {
621069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
622069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // this type of exception means there was a problem in discovery
623069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // and we've already output diagnostics about the issue, etc.;
624069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // just pass it on
625069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw (LogConfigurationException) lce;
626069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
627069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch (InvocationTargetException e) {
628069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // A problem occurred invoking the Constructor or Method
629069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // previously discovered
630069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            Throwable c = e.getTargetException();
631069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (c != null) {
632069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new LogConfigurationException(c);
633069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
634069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new LogConfigurationException(e);
635069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
636069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch (Throwable t) {
637069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // A problem occurred invoking the Constructor or Method
638069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // previously discovered
639069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new LogConfigurationException(t);
640069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
641069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
642069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
643069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
644069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    //  ------------------------------------------------------ Private Methods
645069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
646069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
647069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Utility method to check whether a particular logging library is
648069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * present and available for use. Note that this does <i>not</i>
649069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * affect the future behaviour of this class.
650069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
651069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean isLogLibraryAvailable(String name, String classname) {
652069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
653069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("Checking for '" + name + "'.");
654069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
655069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
656069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            Log log = createLogFromClass(
657069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        classname,
658069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        this.getClass().getName(), // dummy category
659069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        false);
660069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
661069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (log == null) {
662069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
663069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic("Did not find '" + name + "'.");
664069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
665069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return false;
666069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
667069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
668069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic("Found '" + name + "'.");
669069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
670069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return true;
671069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
672069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch(LogConfigurationException e) {
673069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
674069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("Logging system '" + name + "' is available but not useable.");
675069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
676069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
677069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
678069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
679069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
680069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
681069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Attempt to find an attribute (see method setAttribute) or a
682069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * system property with the provided name and return its value.
683069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
684069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The attributes associated with this object are checked before
685069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * system properties in case someone has explicitly called setAttribute,
686069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * or a configuration property has been set in a commons-logging.properties
687069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * file.
688069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
689069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return the value associated with the property, or null.
690069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
691069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private String getConfigurationValue(String property) {
692069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
693069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("[ENV] Trying to get configuration for item " + property);
694069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
695069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
696069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Object valueObj =  getAttribute(property);
697069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (valueObj != null) {
698069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
699069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("[ENV] Found LogFactory attribute [" + valueObj + "] for " + property);
700069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
701069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return valueObj.toString();
702069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
703069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
704069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
705069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("[ENV] No LogFactory attribute found for " + property);
706069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
707069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
708069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
709069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            String value = System.getProperty(property);
710069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (value != null) {
711069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
712069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic("[ENV] Found system property [" + value + "] for " + property);
713069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
714069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return value;
715069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
716069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
717069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
718069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("[ENV] No system property found for property " + property);
719069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
720069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch (SecurityException e) {
721069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
722069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("[ENV] Security prevented reading system property " + property);
723069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
724069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
725069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
726069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
727069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("[ENV] No configuration defined for item " + property);
728069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
729069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
730069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return null;
731069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
732069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
733069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
734069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Get the setting for the user-configurable behaviour specified by key.
735069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * If nothing has explicitly been set, then return dflt.
736069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
737069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean getBooleanConfiguration(String key, boolean dflt) {
738069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String val = getConfigurationValue(key);
739069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (val == null)
740069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return dflt;
741069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return Boolean.valueOf(val).booleanValue();
742069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
743069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
744069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
745069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Initialize a number of variables that control the behaviour of this
746069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * class and that can be tweaked by the user. This is done when the first
747069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * logger is created, not in the constructor of this class, because we
748069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * need to give the user a chance to call method setAttribute in order to
749069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * configure this object.
750069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
751069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private void initConfiguration() {
752069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        allowFlawedContext = getBooleanConfiguration(ALLOW_FLAWED_CONTEXT_PROPERTY, true);
753069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        allowFlawedDiscovery = getBooleanConfiguration(ALLOW_FLAWED_DISCOVERY_PROPERTY, true);
754069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        allowFlawedHierarchy = getBooleanConfiguration(ALLOW_FLAWED_HIERARCHY_PROPERTY, true);
755069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
756069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
757069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
758069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
759069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Attempts to create a Log instance for the given category name.
760069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Follows the discovery process described in the class javadoc.
761069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
762069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param logCategory the name of the log category
763069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
764069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws LogConfigurationException if an error in discovery occurs,
765069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * or if no adapter at all can be instantiated
766069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
767069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private Log discoverLogImplementation(String logCategory)
768069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    throws LogConfigurationException
769069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    {
770069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
771069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("Discovering a Log implementation...");
772069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
773069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
774069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        initConfiguration();
775069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
776069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Log result = null;
777069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
778069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // See if the user specified the Log implementation to use
779069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String specifiedLogClassName = findUserSpecifiedLogClassName();
780069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
781069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (specifiedLogClassName != null) {
782069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
783069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("Attempting to load user-specified log class '" +
784069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    specifiedLogClassName + "'...");
785069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
786069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
787069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result = createLogFromClass(specifiedLogClassName,
788069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                        logCategory,
789069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                        true);
790069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (result == null) {
791069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                StringBuffer messageBuffer =  new StringBuffer("User-specified log class '");
792069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                messageBuffer.append(specifiedLogClassName);
793069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                messageBuffer.append("' cannot be found or is not useable.");
794069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
795069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // Mistyping or misspelling names is a common fault.
796069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // Construct a good error message, if we can
797069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (specifiedLogClassName != null) {
798069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LOG4J_LOGGER);
799069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_JDK14_LOGGER);
800069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LUMBERJACK_LOGGER);
801069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_SIMPLE_LOGGER);
802069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
803069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new LogConfigurationException(messageBuffer.toString());
804069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
805069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
806069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return result;
807069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
808069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
809069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // No user specified log; try to discover what's on the classpath
810069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //
811069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Note that we deliberately loop here over classesToDiscover and
812069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // expect method createLogFromClass to loop over the possible source
813069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // classloaders. The effect is:
814069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //   for each discoverable log adapter
815069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //      for each possible classloader
816069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //          see if it works
817069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //
818069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // It appears reasonable at first glance to do the opposite:
819069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //   for each possible classloader
820069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //     for each discoverable log adapter
821069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //        see if it works
822069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //
823069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // The latter certainly has advantages for user-installable logging
824069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // libraries such as log4j; in a webapp for example this code should
825069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // first check whether the user has provided any of the possible
826069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // logging libraries before looking in the parent classloader.
827069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Unfortunately, however, Jdk14Logger will always work in jvm>=1.4,
828069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // and SimpleLog will always work in any JVM. So the loop would never
829069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // ever look for logging libraries in the parent classpath. Yet many
830069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // users would expect that putting log4j there would cause it to be
831069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // detected (and this is the historical JCL behaviour). So we go with
832069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // the first approach. A user that has bundled a specific logging lib
833069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // in a webapp should use a commons-logging.properties file or a
834069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // service file in META-INF to force use of that logging lib anyway,
835069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // rather than relying on discovery.
836069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
837069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
838069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic(
839069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "No user-specified Log implementation; performing discovery" +
840069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            	" using the standard supported logging implementations...");
841069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
842069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for(int i=0; (i<classesToDiscover.length) && (result == null); ++i) {
843069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result = createLogFromClass(classesToDiscover[i], logCategory, true);
844069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
845069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
846069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (result == null) {
847069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new LogConfigurationException
848069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        ("No suitable Log implementation");
849069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
850069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
851069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return result;
852069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
853069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
854069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
855069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
856069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Appends message if the given name is similar to the candidate.
857069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param messageBuffer <code>StringBuffer</code> the message should be appended to,
858069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * not null
859069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name the (trimmed) name to be test against the candidate, not null
860069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param candidate the candidate name (not null)
861069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
862069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private void informUponSimilarName(final StringBuffer messageBuffer, final String name,
863069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            final String candidate) {
864069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (name.equals(candidate)) {
865069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // Don't suggest a name that is exactly the same as the one the
866069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // user tried...
867069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return;
868069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
869069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
870069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // If the user provides a name that is in the right package, and gets
871069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // the first 5 characters of the adapter class right (ignoring case),
872069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // then suggest the candidate adapter class name.
873069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (name.regionMatches(true, 0, candidate, 0, PKG_LEN + 5)) {
874069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            messageBuffer.append(" Did you mean '");
875069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            messageBuffer.append(candidate);
876069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            messageBuffer.append("'?");
877069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
878069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
879069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
880069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
881069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
882069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Checks system properties and the attribute map for
883069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * a Log implementation specified by the user under the
884069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * property names {@link #LOG_PROPERTY} or {@link #LOG_PROPERTY_OLD}.
885069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
886069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return classname specified by the user, or <code>null</code>
887069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
888069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private String findUserSpecifiedLogClassName()
889069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    {
890069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
891069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("Trying to get log class from attribute '" + LOG_PROPERTY + "'");
892069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
893069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String specifiedClass = (String) getAttribute(LOG_PROPERTY);
894069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
895069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (specifiedClass == null) { // @deprecated
896069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
897069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("Trying to get log class from attribute '" +
898069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                              LOG_PROPERTY_OLD + "'");
899069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
900069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            specifiedClass = (String) getAttribute(LOG_PROPERTY_OLD);
901069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
902069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
903069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (specifiedClass == null) {
904069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
905069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("Trying to get log class from system property '" +
906069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                          LOG_PROPERTY + "'");
907069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
908069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            try {
909069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                specifiedClass = System.getProperty(LOG_PROPERTY);
910069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch (SecurityException e) {
911069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
912069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic("No access allowed to system property '" +
913069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        LOG_PROPERTY + "' - " + e.getMessage());
914069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
915069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
916069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
917069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
918069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (specifiedClass == null) { // @deprecated
919069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
920069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("Trying to get log class from system property '" +
921069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                          LOG_PROPERTY_OLD + "'");
922069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
923069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            try {
924069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                specifiedClass = System.getProperty(LOG_PROPERTY_OLD);
925069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch (SecurityException e) {
926069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
927069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic("No access allowed to system property '" +
928069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        LOG_PROPERTY_OLD + "' - " + e.getMessage());
929069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
930069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
931069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
932069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
933069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Remove any whitespace; it's never valid in a classname so its
934069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // presence just means a user mistake. As we know what they meant,
935069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // we may as well strip the spaces.
936069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (specifiedClass != null) {
937069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            specifiedClass = specifiedClass.trim();
938069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
939069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
940069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return specifiedClass;
941069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
942069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
943069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
944069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
945069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Attempts to load the given class, find a suitable constructor,
946069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * and instantiate an instance of Log.
947069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
948069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param logAdapterClassName classname of the Log implementation
949069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
950069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param logCategory  argument to pass to the Log implementation's
951069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * constructor
952069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
953069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param affectState  <code>true</code> if this object's state should
954069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * be affected by this method call, <code>false</code> otherwise.
955069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
956069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  an instance of the given class, or null if the logging
957069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * library associated with the specified adapter is not available.
958069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
959069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws LogConfigurationException if there was a serious error with
960069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * configuration and the handleFlawedDiscovery method decided this
961069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * problem was fatal.
962069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
963069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private Log createLogFromClass(String logAdapterClassName,
964069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                   String logCategory,
965069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                   boolean affectState)
966069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throws LogConfigurationException {
967069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
968069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
969069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("Attempting to instantiate '" + logAdapterClassName + "'");
970069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
971069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
972069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Object[] params = { logCategory };
973069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Log logAdapter = null;
974069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Constructor constructor = null;
975069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
976069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Class logAdapterClass = null;
977069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ClassLoader currentCL = getBaseClassLoader();
978069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
979069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for(;;) {
980069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // Loop through the classloader hierarchy trying to find
981069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // a viable classloader.
982069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic(
983069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    "Trying to load '"
984069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + logAdapterClassName
985069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + "' from classloader "
986069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + objectId(currentCL));
987069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            try {
988069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
989069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // Show the location of the first occurrence of the .class file
990069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // in the classpath. This is the location that ClassLoader.loadClass
991069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // will load the class from -- unless the classloader is doing
992069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // something weird.
993069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    URL url;
994069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    String resourceName = logAdapterClassName.replace('.', '/') + ".class";
995069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    if (currentCL != null) {
996069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        url = currentCL.getResource(resourceName );
997069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    } else {
998069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        url = ClassLoader.getSystemResource(resourceName + ".class");
999069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    }
1000069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1001069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    if (url == null) {
1002069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        logDiagnostic("Class '" + logAdapterClassName + "' [" + resourceName + "] cannot be found.");
1003069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    } else {
1004069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        logDiagnostic("Class '" + logAdapterClassName + "' was found at '" + url + "'");
1005069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    }
1006069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1007069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1008069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                Class c = null;
1009069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                try {
1010069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    c = Class.forName(logAdapterClassName, true, currentCL);
1011069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } catch (ClassNotFoundException originalClassNotFoundException) {
1012069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // The current classloader was unable to find the log adapter
1013069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // in this or any ancestor classloader. There's no point in
1014069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // trying higher up in the hierarchy in this case..
1015069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    String msg = "" + originalClassNotFoundException.getMessage();
1016069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic(
1017069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        "The log adapter '"
1018069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + logAdapterClassName
1019069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + "' is not available via classloader "
1020069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + objectId(currentCL)
1021069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + ": "
1022069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + msg.trim());
1023069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    try {
1024069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // Try the class classloader.
1025069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // This may work in cases where the TCCL
1026069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // does not contain the code executed or JCL.
1027069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // This behaviour indicates that the application
1028069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // classloading strategy is not consistent with the
1029069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // Java 1.2 classloading guidelines but JCL can
1030069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // and so should handle this case.
1031069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        c = Class.forName(logAdapterClassName);
1032069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    } catch (ClassNotFoundException secondaryClassNotFoundException) {
1033069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        // no point continuing: this adapter isn't available
1034069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        msg = "" + secondaryClassNotFoundException.getMessage();
1035069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        logDiagnostic(
1036069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            "The log adapter '"
1037069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            + logAdapterClassName
1038069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            + "' is not available via the LogFactoryImpl class classloader: "
1039069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            + msg.trim());
1040069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        break;
1041069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    }
1042069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1043069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1044069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                constructor = c.getConstructor(logConstructorSignature);
1045069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                Object o = constructor.newInstance(params);
1046069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1047069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // Note that we do this test after trying to create an instance
1048069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // [rather than testing Log.class.isAssignableFrom(c)] so that
1049069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // we don't complain about Log hierarchy problems when the
1050069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // adapter couldn't be instantiated anyway.
1051069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (o instanceof Log) {
1052069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logAdapterClass = c;
1053069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logAdapter = (Log) o;
1054069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    break;
1055069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1056069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1057069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // Oops, we have a potential problem here. An adapter class
1058069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // has been found and its underlying lib is present too, but
1059069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // there are multiple Log interface classes available making it
1060069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // impossible to cast to the type the caller wanted. We
1061069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // certainly can't use this logger, but we need to know whether
1062069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // to keep on discovering or terminate now.
1063069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //
1064069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // The handleFlawedHierarchy method will throw
1065069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // LogConfigurationException if it regards this problem as
1066069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // fatal, and just return if not.
1067069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                handleFlawedHierarchy(currentCL, c);
1068069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch (NoClassDefFoundError e) {
1069069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // We were able to load the adapter but it had references to
1070069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // other classes that could not be found. This simply means that
1071069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // the underlying logger library is not present in this or any
1072069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // ancestor classloader. There's no point in trying higher up
1073069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // in the hierarchy in this case..
1074069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                String msg = "" + e.getMessage();
1075069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic(
1076069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    "The log adapter '"
1077069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + logAdapterClassName
1078069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + "' is missing dependencies when loaded via classloader "
1079069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + objectId(currentCL)
1080069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + ": "
1081069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + msg.trim());
1082069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
1083069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch (ExceptionInInitializerError e) {
1084069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // A static initializer block or the initializer code associated
1085069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // with a static variable on the log adapter class has thrown
1086069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // an exception.
1087069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //
1088069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // We treat this as meaning the adapter's underlying logging
1089069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // library could not be found.
1090069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                String msg = "" + e.getMessage();
1091069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic(
1092069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    "The log adapter '"
1093069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + logAdapterClassName
1094069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + "' is unable to initialize itself when loaded via classloader "
1095069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + objectId(currentCL)
1096069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + ": "
1097069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + msg.trim());
1098069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
1099069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch(LogConfigurationException e) {
1100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // call to handleFlawedHierarchy above must have thrown
1101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // a LogConfigurationException, so just throw it on
1102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw e;
1103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch(Throwable t) {
1104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // handleFlawedDiscovery will determine whether this is a fatal
1105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // problem or not. If it is fatal, then a LogConfigurationException
1106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // will be thrown.
1107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                handleFlawedDiscovery(logAdapterClassName, currentCL, t);
1108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (currentCL == null) {
1111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
1112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // try the parent classloader
1115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            currentCL = currentCL.getParent();
1116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if ((logAdapter != null) && affectState) {
1119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // We've succeeded, so set instance fields
1120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.logClassName   = logAdapterClassName;
1121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.logConstructor = constructor;
1122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // Identify the <code>setLogFactory</code> method (if there is one)
1124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            try {
1125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.logMethod = logAdapterClass.getMethod("setLogFactory",
1126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                               logMethodSignature);
1127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic("Found method setLogFactory(LogFactory) in '"
1128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                              + logAdapterClassName + "'");
1129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch (Throwable t) {
1130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.logMethod = null;
1131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic(
1132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    "[INFO] '" + logAdapterClassName
1133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + "' from classloader " + objectId(currentCL)
1134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + " does not declare optional method "
1135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    + "setLogFactory(LogFactory)");
1136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic(
1139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "Log adapter '" + logAdapterClassName
1140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                + "' from classloader " + objectId(logAdapterClass.getClassLoader())
1141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                + " has been selected for use.");
1142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return logAdapter;
1145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
1149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Return the classloader from which we should try to load the logging
1150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * adapter classes.
1151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
1152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * This method usually returns the context classloader. However if it
1153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * is discovered that the classloader which loaded this class is a child
1154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * of the context classloader <i>and</i> the allowFlawedContext option
1155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * has been set then the classloader which loaded this class is returned
1156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * instead.
1157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
1158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The only time when the classloader which loaded this class is a
1159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * descendant (rather than the same as or an ancestor of the context
1160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * classloader) is when an app has created custom classloaders but
1161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * failed to correctly set the context classloader. This is a bug in
1162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * the calling application; however we provide the option for JCL to
1163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * simply generate a warning rather than fail outright.
1164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
1166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private ClassLoader getBaseClassLoader() throws LogConfigurationException {
1167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ClassLoader thisClassLoader = getClassLoader(LogFactoryImpl.class);
1168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (useTCCL == false) {
1170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return thisClassLoader;
1171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ClassLoader contextClassLoader = getContextClassLoader();
1174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ClassLoader baseClassLoader = getLowestClassLoader(
1176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                contextClassLoader, thisClassLoader);
1177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (baseClassLoader == null) {
1179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           // The two classloaders are not part of a parent child relationship.
1180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           // In some classloading setups (e.g. JBoss with its
1181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           // UnifiedLoaderRepository) this can still work, so if user hasn't
1182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           // forbidden it, just return the contextClassLoader.
1183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           if (allowFlawedContext) {
1184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project              if (isDiagnosticsEnabled()) {
1185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   logDiagnostic(
1186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                           "[WARNING] the context classloader is not part of a"
1187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                           + " parent-child relationship with the classloader that"
1188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                           + " loaded LogFactoryImpl.");
1189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project              }
1190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project              // If contextClassLoader were null, getLowestClassLoader() would
1191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project              // have returned thisClassLoader.  The fact we are here means
1192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project              // contextClassLoader is not null, so we can just return it.
1193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project              return contextClassLoader;
1194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           }
1195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           else {
1196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new LogConfigurationException(
1197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                "Bad classloader hierarchy; LogFactoryImpl was loaded via"
1198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                + " a classloader that is not related to the current context"
1199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                + " classloader.");
1200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           }
1201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (baseClassLoader != contextClassLoader) {
1204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // We really should just use the contextClassLoader as the starting
1205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // point for scanning for log adapter classes. However it is expected
1206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // that there are a number of broken systems out there which create
1207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // custom classloaders but fail to set the context classloader so
1208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // we handle those flawed systems anyway.
1209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (allowFlawedContext) {
1210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
1211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic(
1212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            "Warning: the context classloader is an ancestor of the"
1213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            + " classloader that loaded LogFactoryImpl; it should be"
1214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            + " the same or a descendant. The application using"
1215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            + " commons-logging should ensure the context classloader"
1216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                            + " is used correctly.");
1217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
1219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new LogConfigurationException(
1220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        "Bad classloader hierarchy; LogFactoryImpl was loaded via"
1221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + " a classloader that is not related to the current context"
1222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + " classloader.");
1223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return baseClassLoader;
1227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
1230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Given two related classloaders, return the one which is a child of
1231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * the other.
1232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
1233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param c1 is a classloader (including the null classloader)
1234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param c2 is a classloader (including the null classloader)
1235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return c1 if it has c2 as an ancestor, c2 if it has c1 as an ancestor,
1237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * and null if neither is an ancestor of the other.
1238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
1239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private ClassLoader getLowestClassLoader(ClassLoader c1, ClassLoader c2) {
1240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // TODO: use AccessController when dealing with classloaders here
1241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (c1 == null)
1243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return c2;
1244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (c2 == null)
1246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return c1;
1247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ClassLoader current;
1249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // scan c1's ancestors to find c2
1251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        current = c1;
1252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (current != null) {
1253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (current == c2)
1254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return c1;
1255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            current = current.getParent();
1256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // scan c2's ancestors to find c1
1259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        current = c2;
1260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (current != null) {
1261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (current == c1)
1262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return c2;
1263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            current = current.getParent();
1264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return null;
1267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
1270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Generates an internal diagnostic logging of the discovery failure and
1271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * then throws a <code>LogConfigurationException</code> that wraps
1272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * the passed <code>Throwable</code>.
1273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param logAdapterClassName is the class name of the Log implementation
1275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * that could not be instantiated. Cannot be <code>null</code>.
1276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param classLoader is the classloader that we were trying to load the
1278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * logAdapterClassName from when the exception occurred.
1279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param discoveryFlaw is the Throwable created by the classloader
1281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws LogConfigurationException    ALWAYS
1283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
1284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private void handleFlawedDiscovery(String logAdapterClassName,
1285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                       ClassLoader classLoader,
1286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                       Throwable discoveryFlaw) {
1287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (isDiagnosticsEnabled()) {
1289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            logDiagnostic("Could not instantiate Log '"
1290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                      + logAdapterClassName + "' -- "
1291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                      + discoveryFlaw.getClass().getName() + ": "
1292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                      + discoveryFlaw.getLocalizedMessage());
1293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (!allowFlawedDiscovery) {
1296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new LogConfigurationException(discoveryFlaw);
1297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
1302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Report a problem loading the log adapter, then either return
1303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * (if the situation is considered recoverable) or throw a
1304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * LogConfigurationException.
1305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *  <p>
1306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * There are two possible reasons why we successfully loaded the
1307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * specified log adapter class then failed to cast it to a Log object:
1308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <ol>
1309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <li>the specific class just doesn't implement the Log interface
1310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *     (user screwed up), or
1311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <li> the specified class has bound to a Log class loaded by some other
1312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *      classloader; Log@classloaderX cannot be cast to Log@classloaderY.
1313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * </ol>
1314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <p>
1315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Here we try to figure out which case has occurred so we can give the
1316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * user some reasonable feedback.
1317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param badClassLoader is the classloader we loaded the problem class from,
1319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * ie it is equivalent to badClass.getClassLoader().
1320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param badClass is a Class object with the desired name, but which
1322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * does not implement Log correctly.
1323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
1324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws LogConfigurationException when the situation
1325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * should not be recovered from.
1326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
1327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private void handleFlawedHierarchy(ClassLoader badClassLoader, Class badClass)
1328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    throws LogConfigurationException {
1329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean implementsLog = false;
1331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String logInterfaceName = Log.class.getName();
1332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        Class interfaces[] = badClass.getInterfaces();
1333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for (int i = 0; i < interfaces.length; i++) {
1334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (logInterfaceName.equals(interfaces[i].getName())) {
1335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                implementsLog = true;
1336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
1337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (implementsLog) {
1341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // the class does implement an interface called Log, but
1342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // it is in the wrong classloader
1343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
1344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                try {
1345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    ClassLoader logInterfaceClassLoader = getClassLoader(Log.class);
1346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic(
1347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        "Class '" + badClass.getName()
1348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + "' was found in classloader "
1349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + objectId(badClassLoader)
1350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + ". It is bound to a Log interface which is not"
1351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + " the one loaded from classloader "
1352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + objectId(logInterfaceClassLoader));
1353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } catch (Throwable t) {
1354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic(
1355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        "Error while trying to output diagnostics about"
1356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        + " bad class '" + badClass + "'");
1357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (!allowFlawedHierarchy) {
1361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                StringBuffer msg = new StringBuffer();
1362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("Terminating logging for this context ");
1363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("due to bad log hierarchy. ");
1364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("You have more than one version of '");
1365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append(Log.class.getName());
1366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("' visible.");
1367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
1368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic(msg.toString());
1369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new LogConfigurationException(msg.toString());
1371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
1374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                StringBuffer msg = new StringBuffer();
1375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("Warning: bad log hierarchy. ");
1376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("You have more than one version of '");
1377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append(Log.class.getName());
1378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("' visible.");
1379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic(msg.toString());
1380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
1382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // this is just a bad adapter class
1383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (!allowFlawedDiscovery) {
1384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                StringBuffer msg = new StringBuffer();
1385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("Terminating logging for this context. ");
1386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("Log class '");
1387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append(badClass.getName());
1388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("' does not implement the Log interface.");
1389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isDiagnosticsEnabled()) {
1390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    logDiagnostic(msg.toString());
1391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new LogConfigurationException(msg.toString());
1394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isDiagnosticsEnabled()) {
1397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                StringBuffer msg = new StringBuffer();
1398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("[WARNING] Log class '");
1399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append(badClass.getName());
1400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                msg.append("' does not implement the Log interface.");
1401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                logDiagnostic(msg.toString());
1402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
1406