001    /*
002      Copyright (C) 2001-2003 Laurent Martelli <laurent@aopsys.com>
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
017    
018    package org.objectweb.jac.util;
019    
020    import java.io.FileOutputStream;
021    import java.io.PrintStream;
022    import java.text.DateFormat;
023    import java.text.SimpleDateFormat;
024    import java.util.Date;
025    import java.util.Hashtable;
026    import java.util.Map;
027    import java.util.Set;
028    
029    /**
030     * The <code>Log</code> class provides a means to send some
031     * informational, debugging or error messages like
032     * <code>System.out.println</code> but traces can be enabled or
033     * disabled at runtime.
034     *
035     * <p>JAC supports a -V launching option that allows the user to
036     * enable a given trace category (for instance, by using <code>-V
037     * jac</code>, the user can see what happens in the JAC core system.
038     *
039     * @author <a href="mailto:laurent@aopsys.com">Laurent Martelli</a> */
040    
041    public final class Log{
042    
043        // enabled traces
044        static Hashtable levels = new Hashtable();
045    
046        static PrintStream out = System.out;
047    
048        static String logHeader = "";
049    
050        static Date date = new Date();
051        static DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS ");
052    
053        /**
054         * Sets the logging file.
055         *
056         * @param name the file name if null=>log to the standard output
057         * @param header a string to prepend to each line logged.
058         */
059        public static void setFileName(String name, String header) {
060            try {
061                logHeader = header;
062                out = new PrintStream(new FileOutputStream(name));
063            } catch(Exception e) {
064                out = System.out;
065                e.printStackTrace();
066            }
067        }
068    
069        /**
070         * Traces with a level lower than <code>levels[category]</code> are
071         * discarded.
072         *
073         * @param category a string representing the category to trace
074         * @param level the level of the trace (1 is always printed)
075         * @param message the message to print out */
076    
077        public static void trace(String category, int level, String message) {
078            if (!(category!=null && levels.containsKey(category))) {
079                levels.put(category, new Integer(0));
080            }
081            if (level<=((Integer)levels.get(category)).intValue()) {
082                date.setTime(System.currentTimeMillis());
083                out.print(dateFormat.format(date));
084                out.print(logHeader);
085                out.print(category);
086                out.print(": ");
087                out.println(message);
088            }
089        }
090    
091        /**
092         * Print the stack trace of an exception with a level lower than
093         * <code>levels[category]</code> are discarded.
094         *
095         * @param category a string representing the category to trace
096         * @param level the level of the trace (1 is always printed)
097         * @param exception the exception */
098    
099        public static void trace(String category, int level, Throwable exception) {
100            if (category!=null && levels.containsKey(category)) {
101                if (level<=((Integer)levels.get(category)).intValue()) {
102                    out.println(logHeader+category+": StackTrace");
103                    exception.printStackTrace(out);
104                }
105            } else {
106                levels.put(category, new Integer(0));
107            }
108        }
109    
110    
111        /**
112         * Prints a stack trace.
113         *
114         * @param category a string representing the category to trace
115         * @param level the level of the trace (1 is always printed)
116         */
117        public static void stack(String category, int level) {
118            if (category!=null && levels.containsKey(category)) {
119                if (level<=((Integer)levels.get(category)).intValue()) {
120                    out.println(logHeader+category+": StackTrace");
121                    new Exception().printStackTrace(out);
122                }
123            } else {
124                levels.put(category, new Integer(0));
125            }
126        }
127    
128        public static void stack(String category) {
129            stack(category,1);
130        }
131    
132        /**
133         * Traces with a level equals to 1.
134         *
135         * @param category a string representing the category to trace
136         * @param message the message to print out
137         * @see #trace(String,int,String) */
138    
139        public static void trace(String category, String message) {
140            Log.trace(category, 1, message);
141        }
142    
143        /**
144         * Print a stack trace with a level equals to 1.
145         *
146         * @param category a string representing the category to trace
147         * @param exception the message to print out
148         * @see #trace(String,int,String) */
149    
150        public static void trace(String category, Throwable exception) {
151            Log.trace(category, 1, exception);
152        }
153    
154        /**
155         * Traces an error into the <code>System.err</code> stream.
156         *
157         * @param message the error message to print out */
158    
159        public static void error(String message) {
160            out.println(logHeader+"ERROR: "+message);
161        }
162    
163        /**
164         * Traces a warning into the <code>System.err</code> stream.
165         *
166         * @param message the warning message to print out
167         * @param level warning level (0=important, 1=normal, 2=low, ...)
168         */
169        public static void warning(String message, int level) {
170            if (level<=1) {
171                out.println(logHeader+"WARNING: "+message);
172            }
173        }
174    
175        /**
176         * Traces a warning into the <code>System.err</code> stream.
177         *
178         * @param message the warning message to print out
179         */
180        public static void warning(String message) {
181            warning(message, 1);
182        }
183    
184        /**
185         * Traces a warning into the <code>System.err</code> stream only if
186         * the given category is enable to trace.
187         *
188         * @param message the warning message to print out
189         */
190        public static void warning(String category, String message) {
191            warning(category+": "+message, 1);
192        }
193    
194        /**
195         * Traces a warning into the <code>System.err</code> stream only if
196         * the given category is enable to trace.
197         *
198         * @param message the warning message to print out
199         */
200        public static void warning(String category, int level, String message) {
201            warning(category+": "+message, level);
202        }
203    
204        /**
205         * Sets the verbose level of a given category.
206         *
207         * <p>The higher, the more traces are printed out.
208         *
209         * @param category the category to set the level of
210         * @param level the category verbose level */
211    
212        public static void setLevel(String category, int level) {
213            levels.put(category, new Integer(level));
214        }
215    
216        /**
217         * Returns a Map category -> enabled saying which traces are enables
218         */
219        public static Map getLevels() {
220            return levels;
221        }
222    
223        public static Set getCategories(Object substance) {
224            return levels.keySet();
225        }
226    
227        public static String dump() {
228            return Strings.hex(levels)+" : "+levels;
229        }
230    }