View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.logging;
19  
20  import java.lang.reflect.Constructor;
21  import java.util.Hashtable;
22  
23  import org.apache.commons.logging.impl.NoOpLog;
24  
25  /**
26   * Factory for creating {@link Log} instances.  Applications should call
27   * the <code>makeNewLogInstance()</code> method to instantiate new instances
28   * of the configured {@link Log} implementation class.
29   * <p>
30   * By default, calling <code>getInstance()</code> will use the following
31   * algorithm:
32   * <ul>
33   * <li>If Log4J is available, return an instance of
34   *     <code>org.apache.commons.logging.impl.Log4JLogger</code>.</li>
35   * <li>If JDK 1.4 or later is available, return an instance of
36   *     <code>org.apache.commons.logging.impl.Jdk14Logger</code>.</li>
37   * <li>Otherwise, return an instance of
38   *     <code>org.apache.commons.logging.impl.NoOpLog</code>.</li>
39   * </ul>
40   * <p>
41   * You can change the default behavior in one of two ways:
42   * <ul>
43   * <li>On the startup command line, set the system property
44   *     <code>org.apache.commons.logging.log</code> to the name of the
45   *     <code>org.apache.commons.logging.Log</code> implementation class
46   *     you want to use.</li>
47   * <li>At runtime, call <code>LogSource.setLogImplementation()</code>.</li>
48   * </ul>
49   *
50   * @deprecated Use {@link LogFactory} instead - The default factory
51   *  implementation performs exactly the same algorithm as this class did
52   *
53   * @version $Id: LogSource.java 1432675 2013-01-13 17:53:30Z tn $
54   */
55  public class LogSource {
56  
57      // ------------------------------------------------------- Class Attributes
58  
59      static protected Hashtable logs = new Hashtable();
60  
61      /** Is log4j available (in the current classpath) */
62      static protected boolean log4jIsAvailable = false;
63  
64      /** Is JDK 1.4 logging available */
65      static protected boolean jdk14IsAvailable = false;
66  
67      /** Constructor for current log class */
68      static protected Constructor logImplctor = null;
69  
70      // ----------------------------------------------------- Class Initializers
71  
72      static {
73  
74          // Is Log4J Available?
75          try {
76              log4jIsAvailable = null != Class.forName("org.apache.log4j.Logger");
77          } catch (Throwable t) {
78              log4jIsAvailable = false;
79          }
80  
81          // Is JDK 1.4 Logging Available?
82          try {
83              jdk14IsAvailable = null != Class.forName("java.util.logging.Logger") &&
84                                 null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger");
85          } catch (Throwable t) {
86              jdk14IsAvailable = false;
87          }
88  
89          // Set the default Log implementation
90          String name = null;
91          try {
92              name = System.getProperty("org.apache.commons.logging.log");
93              if (name == null) {
94                  name = System.getProperty("org.apache.commons.logging.Log");
95              }
96          } catch (Throwable t) {
97          }
98          if (name != null) {
99              try {
100                 setLogImplementation(name);
101             } catch (Throwable t) {
102                 try {
103                     setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
104                 } catch (Throwable u) {
105                     // ignored
106                 }
107             }
108         } else {
109             try {
110                 if (log4jIsAvailable) {
111                     setLogImplementation("org.apache.commons.logging.impl.Log4JLogger");
112                 } else if (jdk14IsAvailable) {
113                     setLogImplementation("org.apache.commons.logging.impl.Jdk14Logger");
114                 } else {
115                     setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
116                 }
117             } catch (Throwable t) {
118                 try {
119                     setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
120                 } catch (Throwable u) {
121                     // ignored
122                 }
123             }
124         }
125 
126     }
127 
128     // ------------------------------------------------------------ Constructor
129 
130     /** Don't allow others to create instances. */
131     private LogSource() {
132     }
133 
134     // ---------------------------------------------------------- Class Methods
135 
136     /**
137      * Set the log implementation/log implementation factory
138      * by the name of the class.  The given class must implement {@link Log},
139      * and provide a constructor that takes a single {@link String} argument
140      * (containing the name of the log).
141      */
142     static public void setLogImplementation(String classname)
143         throws LinkageError, NoSuchMethodException, SecurityException, ClassNotFoundException {
144         try {
145             Class logclass = Class.forName(classname);
146             Class[] argtypes = new Class[1];
147             argtypes[0] = "".getClass();
148             logImplctor = logclass.getConstructor(argtypes);
149         } catch (Throwable t) {
150             logImplctor = null;
151         }
152     }
153 
154     /**
155      * Set the log implementation/log implementation factory by class.
156      * The given class must implement {@link Log}, and provide a constructor
157      * that takes a single {@link String} argument (containing the name of the log).
158      */
159     static public void setLogImplementation(Class logclass)
160         throws LinkageError, ExceptionInInitializerError, NoSuchMethodException, SecurityException {
161         Class[] argtypes = new Class[1];
162         argtypes[0] = "".getClass();
163         logImplctor = logclass.getConstructor(argtypes);
164     }
165 
166     /** Get a <code>Log</code> instance by class name. */
167     static public Log getInstance(String name) {
168         Log log = (Log) logs.get(name);
169         if (null == log) {
170             log = makeNewLogInstance(name);
171             logs.put(name, log);
172         }
173         return log;
174     }
175 
176     /** Get a <code>Log</code> instance by class. */
177     static public Log getInstance(Class clazz) {
178         return getInstance(clazz.getName());
179     }
180 
181     /**
182      * Create a new {@link Log} implementation, based on the given <i>name</i>.
183      * <p>
184      * The specific {@link Log} implementation returned is determined by the
185      * value of the <tt>org.apache.commons.logging.log</tt> property. The value
186      * of <tt>org.apache.commons.logging.log</tt> may be set to the fully specified
187      * name of a class that implements the {@link Log} interface. This class must
188      * also have a public constructor that takes a single {@link String} argument
189      * (containing the <i>name</i> of the {@link Log} to be constructed.
190      * <p>
191      * When <tt>org.apache.commons.logging.log</tt> is not set, or when no corresponding
192      * class can be found, this method will return a Log4JLogger if the log4j Logger
193      * class is available in the {@link LogSource}'s classpath, or a Jdk14Logger if we
194      * are on a JDK 1.4 or later system, or NoOpLog if neither of the above conditions is true.
195      *
196      * @param name the log name (or category)
197      */
198     static public Log makeNewLogInstance(String name) {
199         Log log;
200         try {
201             Object[] args = { name };
202             log = (Log) logImplctor.newInstance(args);
203         } catch (Throwable t) {
204             log = null;
205         }
206         if (null == log) {
207             log = new NoOpLog(name);
208         }
209         return log;
210     }
211 
212     /**
213      * Returns a {@link String} array containing the names of
214      * all logs known to me.
215      */
216     static public String[] getLogNames() {
217         return (String[]) logs.keySet().toArray(new String[logs.size()]);
218     }
219 }