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    }