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