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