Source code: org/progeeks/util/log/Log.java
1 /*
2 * $Id: Log.java,v 1.1 2002/11/26 07:08:52 pspeed Exp $
3 *
4 * Copyright (c) 2001-2002, Paul Speed
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1) Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2) Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3) Neither the names "Progeeks", "Meta-JB", nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 package org.progeeks.util.log;
34
35 import java.lang.reflect.*;
36 import java.util.*;
37
38 import org.apache.log4j.AppenderSkeleton;
39 import org.apache.log4j.BasicConfigurator;
40 import org.apache.log4j.Category;
41 import org.apache.log4j.NDC;
42 import org.apache.log4j.Priority;
43 import org.apache.log4j.PropertyConfigurator;
44 import org.apache.log4j.spi.LoggingEvent;
45
46 //import Configuration;
47
48
49 /**
50 * System logging class. Allows for multiple log levels and a
51 * hierarchy of named categories. Each category can have its own
52 * log format.
53 *
54 * Example code:
55 * <pre>
56 * public class MyTestClass {
57 * static Log log = Log.getLog( MyTestClass.class );
58 *
59 * public void someMethod() {
60 * log.debug( "Entering someMethod()" );
61 * log.info( "Some operation being performed." );
62 * }
63 * }
64 * </pre>
65 *
66 * @version $Revision: 1.1 $
67 * @author Paul Speed
68 * @since 1.0
69 */
70 public class Log
71 {
72 public static final String KEY_LOG_CONFIG = "log.config";
73 public static final String DEFAULT_CONFIG = "log.config";
74
75 /**
76 * The log4j Category that this instance of Log writes to
77 */
78 private Category category;
79
80 /**
81 * Flag set to true if the log class has been initialized.
82 */
83 private static boolean initialized = false;
84
85 /**
86 * Initializes the Logger with basic configuration. If the
87 * "log.config" System property is set then it will use that value
88 * as a configuration file name. Otherwise, the default configuration
89 * will be used.
90 */
91 public static synchronized void initialize()
92 {
93 if( initialized )
94 return;
95
96 initialized = true;
97
98 // Initialize logging from a file if the property "log.config"
99 // has been set.
100 String configFile = System.getProperty( KEY_LOG_CONFIG );
101 if( configFile != null )
102 {
103 // Setup with the properties file
104 PropertyConfigurator.configure( configFile );
105 }
106 else
107 {
108 // See if there is a default log configuration in
109 // the configuration resources.
110 Properties props = getDefaultConfiguration(); //null;
111
112 if( props != null )
113 {
114 // Setup with the properties file
115 PropertyConfigurator.configure( props );
116 }
117 else
118 {
119 // Set up a simple configuration that logs on the console.
120 BasicConfigurator.configure();
121 }
122 }
123 }
124
125 /**
126 * Uses dynamic class loading and refelection to attempt to get the
127 * configuration class. This allows it to work even if
128 * no Configuration.class file exists.
129 */
130 private static Properties getDefaultConfiguration()
131 {
132 try
133 {
134 Class configClass = Class.forName( "Configuration" );
135
136 // Find its loadProperties method.
137 Method m = configClass.getMethod( "loadProperties", new Class[] { String.class } );
138
139 return( (Properties)m.invoke( null, new Object[] { DEFAULT_CONFIG } ) );
140 }
141 catch( ClassNotFoundException e )
142 {
143 return( null );
144 }
145 catch( Exception e )
146 {
147 // This shouldn't happen.
148 e.printStackTrace();
149 return( null );
150 }
151 }
152
153 /**
154 * Gets a log instance for writing messages of the specified category. If
155 * a name refers to an already retrieved category then the log objects will
156 * refer to the same category instance.
157 *
158 * Note: right now that doesn't make much since, but when log4j is implemented
159 * then categories become a very powerful log filter.
160 *
161 * @param categoryName The name of the category to which the logger will
162 * be associated.
163 */
164 public static Log getLog( String categoryName )
165 {
166 return( new Log( Category.getInstance( categoryName ) ) );
167 }
168
169 /**
170 * Shorthand for getLog( c.getName() );
171 *
172 * @param c The class used to retrieve the category name.
173 */
174 public static Log getLog( Class c )
175 {
176 return( getLog( c.getName() ) );
177 }
178
179 /**
180 * Pushes a new diagnostic context onto the context stack. All logged messages
181 * in this thread will now be within this context.
182 *
183 * @param context The name of the diagnostic context.
184 */
185 public static void push( String context )
186 {
187 NDC.push( context );
188 }
189
190 /**
191 * Clients should call this method before leaving a diagnostic context.
192 *
193 * @return The previously pushed diagnostic context.
194 */
195 public static String pop()
196 {
197 return( NDC.pop() );
198 }
199
200 /**
201 * Threads should call this to remove the diagnostic context before exitting.
202 */
203 public static void end()
204 {
205 NDC.remove();
206 }
207
208 private Log( Category category )
209 {
210 this.category = category;
211 }
212
213 /**
214 * Returns the current category name for this Log instance.
215 */
216 public String getCategoryName()
217 {
218 return( category.getName() );
219 }
220
221 /**
222 * Log a message at the debug priority level.
223 *
224 * @param message The message object to log.
225 */
226 public void debug( Object message )
227 {
228 category.debug( message );
229 }
230
231 /**
232 * Log a message at the debug priority level including the stack trace of
233 * the specified Throwable.
234 *
235 * @param message The message object to log.
236 * @param t The throwable to log, including its stack trace.
237 */
238 public void debug( Object message, Throwable t )
239 {
240 category.debug( message, t );
241 }
242
243 /**
244 * Log a message at the error priority level.
245 *
246 * @param message The message object to log.
247 */
248 public void error( Object message )
249 {
250 category.error( message );
251 }
252
253 /**
254 * Log a message at the error priority level including the stack trace of
255 * the specified Throwable.
256 *
257 * @param message The message object to log.
258 * @param t The throwable to log, including its stack trace.
259 */
260 public void error( Object message, Throwable t )
261 {
262 category.error( message, t );
263 }
264
265 /**
266 * Log a message at the fatal priority level.
267 *
268 * @param message The message object to log.
269 */
270 public void fatal( Object message )
271 {
272 category.fatal( message );
273 }
274
275 /**
276 * Log a message at the fatal priority level including the stack trace of
277 * the specified Throwable.
278 *
279 * @param message The message object to log.
280 * @param t The throwable to log, including its stack trace.
281 */
282 public void fatal( Object message, Throwable t )
283 {
284 category.fatal( message, t );
285 }
286
287 /**
288 * Log a message at the info priority level.
289 *
290 * @param message The message object to log.
291 */
292 public void info( Object message )
293 {
294 category.info( message );
295 }
296
297 /**
298 * Log a message at the info priority level including the stack trace of
299 * the specified Throwable.
300 *
301 * @param message The message object to log.
302 * @param t The throwable to log, including its stack trace.
303 */
304 public void info( Object message, Throwable t )
305 {
306 category.info( message, t );
307 }
308
309 /**
310 * Log a message at the warn priority level.
311 *
312 * @param message The message object to log.
313 */
314 public void warn( Object message )
315 {
316 category.warn( message );
317 }
318
319 /**
320 * Log a message at the warn priority level including the stack trace of
321 * the specified Throwable.
322 *
323 * @param message The message object to log.
324 * @param t The throwable to log, including its stack trace.
325 */
326 public void warn( Object message, Throwable t )
327 {
328 category.warn( message, t );
329 }
330
331 /**
332 * Returns true if the current category is logging at the debug level.
333 */
334 public boolean isDebugEnabled()
335 {
336 return( category.isDebugEnabled() );
337 }
338
339 /**
340 * Returns true if the current category is logging at the info level.
341 */
342 public boolean isInfoEnabled()
343 {
344 return( category.isInfoEnabled() );
345 }
346 }