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    package org.apache.commons.discovery.log;
018    
019    import java.io.PrintStream;
020    import java.text.DateFormat;
021    import java.text.SimpleDateFormat;
022    import java.util.Date;
023    
024    import org.apache.commons.logging.Log;
025    
026    
027    /**
028     * <p>Simple implementation of Log that sends all enabled log messages,
029     * for all defined loggers, to System.err.
030     * </p>
031     * 
032     * <p>Hacked from commons-logging SimpleLog for use in discovery.
033     * This is intended to be enough of a Log implementation to bootstrap
034     * Discovery.
035     * </p>
036     * 
037     * <p>One property: <code>org.apache.commons.discovery.log.level</code>.
038     * valid values: all, trace, debug, info, warn, error, fatal, off.
039     * </p>
040     * 
041     * @author Richard A. Sitze
042     * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
043     * @author Rod Waldhoff
044     * @author Robert Burrell Donkin
045     *
046     * @version $Id: SimpleLog.java 480374 2006-11-29 03:33:25Z niallp $
047     */
048    public class SimpleLog implements Log {
049          // ---------------------------------------------------- Log Level Constants
050    
051        /** "Trace" level logging. */
052        public static final int LOG_LEVEL_TRACE  = 1;
053        /** "Debug" level logging. */
054        public static final int LOG_LEVEL_DEBUG  = 2;
055        /** "Info" level logging. */
056        public static final int LOG_LEVEL_INFO   = 3;
057        /** "Warn" level logging. */
058        public static final int LOG_LEVEL_WARN   = 4;
059        /** "Error" level logging. */
060        public static final int LOG_LEVEL_ERROR  = 5;
061        /** "Fatal" level logging. */
062        public static final int LOG_LEVEL_FATAL  = 6;
063    
064        /** Enable all logging levels */
065        public static final int LOG_LEVEL_ALL    = (LOG_LEVEL_TRACE - 1);
066    
067        /** Enable no logging levels */
068        public static final int LOG_LEVEL_OFF    = (LOG_LEVEL_FATAL + 1);
069    
070        // ------------------------------------------------------- Class Attributes
071    
072        static protected final String PROP_LEVEL =
073            "org.apache.commons.discovery.log.level";
074    
075        /** Include the instance name in the log message? */
076        static protected boolean showLogName = false;
077    
078        /** Include the short name ( last component ) of the logger in the log
079            message. Default to true - otherwise we'll be lost in a flood of
080            messages without knowing who sends them.
081        */
082        static protected boolean showShortName = true;
083    
084        /** Include the current time in the log message */
085        static protected boolean showDateTime = false;
086    
087        /** Used to format times */
088        static protected DateFormat dateFormatter = null;
089    
090        /** The current log level */
091        static protected int logLevel = LOG_LEVEL_INFO;
092        
093        
094        /**
095         * Use 'out' instead of 'err' for logging
096         * to keep in-sync with test messages.
097         */
098        static private PrintStream out = System.out;
099    
100        // ------------------------------------------------------------ Initializer
101    
102        // initialize class attributes
103        static {
104            if(showDateTime) {
105                dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS zzz");
106            }
107    
108            try {
109            // set log level from properties
110            String lvl = System.getProperty(PROP_LEVEL);
111    
112            if("all".equalsIgnoreCase(lvl)) {
113                setLevel(SimpleLog.LOG_LEVEL_ALL);
114            } else if("trace".equalsIgnoreCase(lvl)) {
115                setLevel(SimpleLog.LOG_LEVEL_TRACE);
116            } else if("debug".equalsIgnoreCase(lvl)) {
117                setLevel(SimpleLog.LOG_LEVEL_DEBUG);
118            } else if("info".equalsIgnoreCase(lvl)) {
119                setLevel(SimpleLog.LOG_LEVEL_INFO);
120            } else if("warn".equalsIgnoreCase(lvl)) {
121                setLevel(SimpleLog.LOG_LEVEL_WARN);
122            } else if("error".equalsIgnoreCase(lvl)) {
123                setLevel(SimpleLog.LOG_LEVEL_ERROR);
124            } else if("fatal".equalsIgnoreCase(lvl)) {
125                setLevel(SimpleLog.LOG_LEVEL_FATAL);
126            } else if("off".equalsIgnoreCase(lvl)) {
127                setLevel(SimpleLog.LOG_LEVEL_OFF);
128            }
129          } catch (SecurityException ignored) {
130          //do nothing. We get here if running discovery
131          //under a servlet with restricted security rights, and
132          //cannot read the system property.
133         //In which case, the default is what you get to keep.      
134          }
135    
136        }
137    
138        // -------------------------------------------------------- Properties
139    
140        /**
141         * <p> Set logging level. </p>
142         *
143         * @param currentLogLevel new logging level
144         */
145        public static void setLevel(int currentLogLevel) {
146            logLevel = currentLogLevel;
147        }
148    
149        /**
150         * <p> Get logging level. </p>
151         */
152        public static int getLevel() {
153            return logLevel;
154        }
155    
156        /**
157         * Is the given log level currently enabled?
158         *
159         * @param level is this level enabled?
160         */
161        protected static boolean isLevelEnabled(int level) {
162            // log level are numerically ordered so can use simple numeric
163            // comparison
164            return (level >= getLevel());
165        }
166    
167    
168    
169        // ------------------------------------------------------------- Attributes
170    
171        /** The name of this simple log instance */
172        protected String logName = null;
173    
174        private String prefix=null;
175    
176        
177        // ------------------------------------------------------------ Constructor
178        
179        /**
180         * Construct a simple log with given name.
181         *
182         * @param name log name
183         */
184        public SimpleLog(String name) {
185            logName = name;
186        }
187    
188    
189        // -------------------------------------------------------- Logging Methods
190    
191    
192        /**
193         * <p> Do the actual logging.
194         * This method assembles the message
195         * and then prints to <code>System.err</code>.</p>
196         */
197        protected void log(int type, Object message, Throwable t) {
198            // use a string buffer for better performance
199            StringBuffer buf = new StringBuffer();
200    
201            // append date-time if so configured
202            if(showDateTime) {
203                buf.append(dateFormatter.format(new Date()));
204                buf.append(" ");
205            }
206    
207            // append a readable representation of the log leve
208            switch(type) {
209                case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break;
210                case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break;
211                case SimpleLog.LOG_LEVEL_INFO:  buf.append("[INFO ] "); break;
212                case SimpleLog.LOG_LEVEL_WARN:  buf.append("[WARN ] "); break;
213                case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break;
214                case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break;
215            }
216    
217            // append the name of the log instance if so configured
218            if( showShortName) {
219                if( prefix==null ) {
220                    // cut all but the last component of the name for both styles
221                    prefix = logName.substring( logName.lastIndexOf(".") +1) + " - ";
222                    prefix = prefix.substring( prefix.lastIndexOf("/") +1) + "-";
223                }
224                buf.append( prefix );
225            } else if(showLogName) {
226                buf.append(String.valueOf(logName)).append(" - ");
227            }
228    
229            // append the message
230            buf.append(String.valueOf(message));
231    
232            // append stack trace if not null
233            if(t != null) {
234                buf.append(" <");
235                buf.append(t.toString());
236                buf.append(">");
237            }
238    
239            // print to System.err
240            out.println(buf.toString());
241            
242            if (t != null)
243                t.printStackTrace(System.err);
244        }
245    
246    
247        // -------------------------------------------------------- Log Implementation
248    
249    
250        /**
251         * <p> Log a message with debug log level.</p>
252         */
253        public final void debug(Object message) {
254            if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
255                log(SimpleLog.LOG_LEVEL_DEBUG, message, null);
256            }
257        }
258    
259    
260        /**
261         * <p> Log an error with debug log level.</p>
262         */
263        public final void debug(Object message, Throwable t) {
264            if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
265                log(SimpleLog.LOG_LEVEL_DEBUG, message, t);
266            }
267        }
268    
269    
270        /**
271         * <p> Log a message with debug log level.</p>
272         */
273        public final void trace(Object message) {
274            if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
275                log(SimpleLog.LOG_LEVEL_TRACE, message, null);
276            }
277        }
278    
279    
280        /**
281         * <p> Log an error with debug log level.</p>
282         */
283        public final void trace(Object message, Throwable t) {
284            if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
285                log(SimpleLog.LOG_LEVEL_TRACE, message, t);
286            }
287        }
288    
289    
290        /**
291         * <p> Log a message with info log level.</p>
292         */
293        public final void info(Object message) {
294            if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
295                log(SimpleLog.LOG_LEVEL_INFO,message,null);
296            }
297        }
298    
299    
300        /**
301         * <p> Log an error with info log level.</p>
302         */
303        public final void info(Object message, Throwable t) {
304            if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
305                log(SimpleLog.LOG_LEVEL_INFO, message, t);
306            }
307        }
308    
309    
310        /**
311         * <p> Log a message with warn log level.</p>
312         */
313        public final void warn(Object message) {
314            if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
315                log(SimpleLog.LOG_LEVEL_WARN, message, null);
316            }
317        }
318    
319    
320        /**
321         * <p> Log an error with warn log level.</p>
322         */
323        public final void warn(Object message, Throwable t) {
324            if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
325                log(SimpleLog.LOG_LEVEL_WARN, message, t);
326            }
327        }
328    
329    
330        /**
331         * <p> Log a message with error log level.</p>
332         */
333        public final void error(Object message) {
334            if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
335                log(SimpleLog.LOG_LEVEL_ERROR, message, null);
336            }
337        }
338    
339    
340        /**
341         * <p> Log an error with error log level.</p>
342         */
343        public final void error(Object message, Throwable t) {
344            if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
345                log(SimpleLog.LOG_LEVEL_ERROR, message, t);
346            }
347        }
348    
349    
350        /**
351         * <p> Log a message with fatal log level.</p>
352         */
353        public final void fatal(Object message) {
354            if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
355                log(SimpleLog.LOG_LEVEL_FATAL, message, null);
356            }
357        }
358    
359    
360        /**
361         * <p> Log an error with fatal log level.</p>
362         */
363        public final void fatal(Object message, Throwable t) {
364            if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
365                log(SimpleLog.LOG_LEVEL_FATAL, message, t);
366            }
367        }
368    
369    
370        /**
371         * <p> Are debug messages currently enabled? </p>
372         *
373         * <p> This allows expensive operations such as <code>String</code>
374         * concatenation to be avoided when the message will be ignored by the
375         * logger. </p>
376         */
377        public final boolean isDebugEnabled() {
378            return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG);
379        }
380    
381    
382        /**
383         * <p> Are error messages currently enabled? </p>
384         *
385         * <p> This allows expensive operations such as <code>String</code>
386         * concatenation to be avoided when the message will be ignored by the
387         * logger. </p>
388         */
389        public final boolean isErrorEnabled() {
390            return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR);
391        }
392    
393    
394        /**
395         * <p> Are fatal messages currently enabled? </p>
396         *
397         * <p> This allows expensive operations such as <code>String</code>
398         * concatenation to be avoided when the message will be ignored by the
399         * logger. </p>
400         */
401        public final boolean isFatalEnabled() {
402            return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL);
403        }
404    
405    
406        /**
407         * <p> Are info messages currently enabled? </p>
408         *
409         * <p> This allows expensive operations such as <code>String</code>
410         * concatenation to be avoided when the message will be ignored by the
411         * logger. </p>
412         */
413        public final boolean isInfoEnabled() {
414            return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO);
415        }
416    
417    
418        /**
419         * <p> Are trace messages currently enabled? </p>
420         *
421         * <p> This allows expensive operations such as <code>String</code>
422         * concatenation to be avoided when the message will be ignored by the
423         * logger. </p>
424         */
425        public final boolean isTraceEnabled() {
426            return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE);
427        }
428    
429    
430        /**
431         * <p> Are warn messages currently enabled? </p>
432         *
433         * <p> This allows expensive operations such as <code>String</code>
434         * concatenation to be avoided when the message will be ignored by the
435         * logger. </p>
436         */
437        public final boolean isWarnEnabled() {
438            return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN);
439        }
440    }