001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.logging;
019
020
021 import java.lang.reflect.Constructor;
022 import java.util.Hashtable;
023
024 import org.apache.commons.logging.impl.NoOpLog;
025
026
027 /**
028 * <p>Factory for creating {@link Log} instances. Applications should call
029 * the <code>makeNewLogInstance()</code> method to instantiate new instances
030 * of the configured {@link Log} implementation class.</p>
031 *
032 * <p>By default, calling <code>getInstance()</code> will use the following
033 * algorithm:</p>
034 * <ul>
035 * <li>If Log4J is available, return an instance of
036 * <code>org.apache.commons.logging.impl.Log4JLogger</code>.</li>
037 * <li>If JDK 1.4 or later is available, return an instance of
038 * <code>org.apache.commons.logging.impl.Jdk14Logger</code>.</li>
039 * <li>Otherwise, return an instance of
040 * <code>org.apache.commons.logging.impl.NoOpLog</code>.</li>
041 * </ul>
042 *
043 * <p>You can change the default behavior in one of two ways:</p>
044 * <ul>
045 * <li>On the startup command line, set the system property
046 * <code>org.apache.commons.logging.log</code> to the name of the
047 * <code>org.apache.commons.logging.Log</code> implementation class
048 * you want to use.</li>
049 * <li>At runtime, call <code>LogSource.setLogImplementation()</code>.</li>
050 * </ul>
051 *
052 * @deprecated Use {@link LogFactory} instead - The default factory
053 * implementation performs exactly the same algorithm as this class did
054 *
055 * @author Rod Waldhoff
056 * @version $Id: LogSource.java 424107 2006-07-20 23:15:42Z skitching $
057 */
058 public class LogSource {
059
060 // ------------------------------------------------------- Class Attributes
061
062 static protected Hashtable logs = new Hashtable();
063
064 /** Is log4j available (in the current classpath) */
065 static protected boolean log4jIsAvailable = false;
066
067 /** Is JDK 1.4 logging available */
068 static protected boolean jdk14IsAvailable = false;
069
070 /** Constructor for current log class */
071 static protected Constructor logImplctor = null;
072
073
074 // ----------------------------------------------------- Class Initializers
075
076 static {
077
078 // Is Log4J Available?
079 try {
080 if (null != Class.forName("org.apache.log4j.Logger")) {
081 log4jIsAvailable = true;
082 } else {
083 log4jIsAvailable = false;
084 }
085 } catch (Throwable t) {
086 log4jIsAvailable = false;
087 }
088
089 // Is JDK 1.4 Logging Available?
090 try {
091 if ((null != Class.forName("java.util.logging.Logger")) &&
092 (null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger"))) {
093 jdk14IsAvailable = true;
094 } else {
095 jdk14IsAvailable = false;
096 }
097 } catch (Throwable t) {
098 jdk14IsAvailable = false;
099 }
100
101 // Set the default Log implementation
102 String name = null;
103 try {
104 name = System.getProperty("org.apache.commons.logging.log");
105 if (name == null) {
106 name = System.getProperty("org.apache.commons.logging.Log");
107 }
108 } catch (Throwable t) {
109 }
110 if (name != null) {
111 try {
112 setLogImplementation(name);
113 } catch (Throwable t) {
114 try {
115 setLogImplementation
116 ("org.apache.commons.logging.impl.NoOpLog");
117 } catch (Throwable u) {
118 ;
119 }
120 }
121 } else {
122 try {
123 if (log4jIsAvailable) {
124 setLogImplementation
125 ("org.apache.commons.logging.impl.Log4JLogger");
126 } else if (jdk14IsAvailable) {
127 setLogImplementation
128 ("org.apache.commons.logging.impl.Jdk14Logger");
129 } else {
130 setLogImplementation
131 ("org.apache.commons.logging.impl.NoOpLog");
132 }
133 } catch (Throwable t) {
134 try {
135 setLogImplementation
136 ("org.apache.commons.logging.impl.NoOpLog");
137 } catch (Throwable u) {
138 ;
139 }
140 }
141 }
142
143 }
144
145
146 // ------------------------------------------------------------ Constructor
147
148
149 /** Don't allow others to create instances */
150 private LogSource() {
151 }
152
153
154 // ---------------------------------------------------------- Class Methods
155
156
157 /**
158 * Set the log implementation/log implementation factory
159 * by the name of the class. The given class
160 * must implement {@link Log}, and provide a constructor that
161 * takes a single {@link String} argument (containing the name
162 * of the log).
163 */
164 static public void setLogImplementation(String classname) throws
165 LinkageError, ExceptionInInitializerError,
166 NoSuchMethodException, SecurityException,
167 ClassNotFoundException {
168 try {
169 Class logclass = Class.forName(classname);
170 Class[] argtypes = new Class[1];
171 argtypes[0] = "".getClass();
172 logImplctor = logclass.getConstructor(argtypes);
173 } catch (Throwable t) {
174 logImplctor = null;
175 }
176 }
177
178
179 /**
180 * Set the log implementation/log implementation factory
181 * by class. The given class must implement {@link Log},
182 * and provide a constructor that takes a single {@link String}
183 * argument (containing the name of the log).
184 */
185 static public void setLogImplementation(Class logclass) throws
186 LinkageError, ExceptionInInitializerError,
187 NoSuchMethodException, SecurityException {
188 Class[] argtypes = new Class[1];
189 argtypes[0] = "".getClass();
190 logImplctor = logclass.getConstructor(argtypes);
191 }
192
193
194 /** Get a <code>Log</code> instance by class name */
195 static public Log getInstance(String name) {
196 Log log = (Log) (logs.get(name));
197 if (null == log) {
198 log = makeNewLogInstance(name);
199 logs.put(name, log);
200 }
201 return log;
202 }
203
204
205 /** Get a <code>Log</code> instance by class */
206 static public Log getInstance(Class clazz) {
207 return getInstance(clazz.getName());
208 }
209
210
211 /**
212 * Create a new {@link Log} implementation, based
213 * on the given <i>name</i>.
214 * <p>
215 * The specific {@link Log} implementation returned
216 * is determined by the value of the
217 * <tt>org.apache.commons.logging.log</tt> property.
218 * The value of <tt>org.apache.commons.logging.log</tt> may be set to
219 * the fully specified name of a class that implements
220 * the {@link Log} interface. This class must also
221 * have a public constructor that takes a single
222 * {@link String} argument (containing the <i>name</i>
223 * of the {@link Log} to be constructed.
224 * <p>
225 * When <tt>org.apache.commons.logging.log</tt> is not set,
226 * or when no corresponding class can be found,
227 * this method will return a Log4JLogger
228 * if the log4j Logger class is
229 * available in the {@link LogSource}'s classpath, or a
230 * Jdk14Logger if we are on a JDK 1.4 or later system, or
231 * NoOpLog if neither of the above conditions is true.
232 *
233 * @param name the log name (or category)
234 */
235 static public Log makeNewLogInstance(String name) {
236
237 Log log = null;
238 try {
239 Object[] args = new Object[1];
240 args[0] = name;
241 log = (Log) (logImplctor.newInstance(args));
242 } catch (Throwable t) {
243 log = null;
244 }
245 if (null == log) {
246 log = new NoOpLog(name);
247 }
248 return log;
249
250 }
251
252
253 /**
254 * Returns a {@link String} array containing the names of
255 * all logs known to me.
256 */
257 static public String[] getLogNames() {
258 return (String[]) (logs.keySet().toArray(new String[logs.size()]));
259 }
260
261
262 }