KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > logging > Log4jLogger


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: Log4jLogger.java,v 1.5 2005/03/24 10:51:20 slobodan Exp $
22  */

23 package com.lutris.logging;
24
25 import java.io.File JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.PrintWriter JavaDoc;
28 import java.util.Hashtable JavaDoc;
29
30 import org.apache.log4j.BasicConfigurator;
31 import org.apache.log4j.ConsoleAppender;
32 import org.apache.log4j.Level;
33 import org.apache.log4j.Logger;
34 import org.apache.log4j.PatternLayout;
35 import org.apache.log4j.RollingFileAppender;
36 import org.apache.log4j.spi.LoggerRepository;
37 import org.apache.log4j.xml.DOMConfigurator;
38
39 import com.lutris.util.Config;
40 import com.lutris.util.ConfigException;
41
42 /**
43  * Log4j implementation of the <CODE>Logger</CODE>. This is
44  * general-purpose logging facility. A client that needs additional
45  * functionality can either extend this class or provide there own
46  * implementationm of <CODE>Logger</CODE>. <P>
47  *
48  * Currently this is a bare-bones class that writes INFO and above
49  * levels to stderr and all others to a log file.
50  *
51  * @author Vladimir Puskas
52  * @author Predrag Djoic
53  * @author Sinisa Milosevic
54  * @see com.lutris.logging.Logger
55  * @see com.lutris.logging.LogChannel
56  */

57 public class Log4jLogger extends com.lutris.logging.Logger {
58
59     /**
60      * Table of level names to level numbers. While level configuration
61      * is local to a facility, a global table is kept assigning numbers
62      * to each level name.
63      */

64     private Hashtable JavaDoc levelNumbers = new Hashtable JavaDoc();
65
66     /**
67      * Table translating level number to name and the largest entry in the
68      * array that is valid. Will be expanded if needed.
69      */

70     protected String JavaDoc[] levelNames = new String JavaDoc[MAX_STD_LEVEL * 2];
71     protected int numLevels = 0;
72
73     /**
74      * Table of levels that are to be enabled.
75      * Accessed directly by the channel. If null, ignored.
76      */

77     protected boolean[] enabledLevelFlags = null;
78
79     /**
80      * Table of levels that are to be written to the log file.
81      * Accessed directly by the channel. If null, ignored.
82      */

83     protected boolean[] logFileLevelFlags = null;
84
85     /**
86      * Table of levels that are to be written to stderr
87      * Accessed directly by the channel. If null, then
88      * the default behavior of writing serious standard
89      * levels to stderr is in affect.
90      */

91     protected boolean[] stderrLevelFlags = null;
92         
93     /**
94      * Default Log4j configuration file
95      */

96         protected String JavaDoc DEFAULT_LOG_CONFIG_FILE = "log4j.xml";
97         
98     /**
99      * Log file name.
100      */

101     File JavaDoc activeLogFile;
102
103     /**
104      * Log file writter. Use directly by channels.
105      */

106     PrintWriter JavaDoc logFileStream;
107
108     /**
109      * Stderr writter. Use directly by channels.
110      */

111     PrintWriter JavaDoc stderrStream;
112
113     /**
114      * Table of <CODE>StandardLogChannel<CODE> objects, indexed by facility
115      * name.
116      */

117     private Hashtable JavaDoc logChannels = new Hashtable JavaDoc();
118
119     String JavaDoc defaultSeparatorLine ="";
120     Hashtable JavaDoc appSeparatorLine = new Hashtable JavaDoc();
121     
122     /**
123      * Construct a new logger. Configuration is not done now, to allow
124      * the logger to be created very early.
125      *
126      * @param makeCentral Make this object the central logging object.
127      */

128     public Log4jLogger(boolean makeCentral) {
129         int level;
130
131         for (level = 0; level <= MAX_STD_LEVEL; level++) {
132             String JavaDoc name = standardLevelNames[level];
133
134             levelNumbers.put(name, new Integer JavaDoc(level));
135             levelNames[level] = name;
136         }
137         numLevels = level;
138         if (makeCentral) {
139             centralLogger = this;
140         }
141     }
142
143     /**
144      * Get maximum level number in a set of level names.
145      *
146      * @param levels String names of levels.
147      * @return The maximum level number
148      */

149     private int getMaxLevel(String JavaDoc[] levels) {
150         int levelNum;
151         int maxLevelNum = 0;
152
153         for (int idx = 0; idx < levels.length; idx++) {
154             levelNum = getLevel(levels[idx]);
155             if (levelNum > maxLevelNum) {
156                 maxLevelNum = levelNum;
157             }
158         }
159         return maxLevelNum;
160     }
161
162     /**
163      * Generate a boolean array for all of the listed levels, indicating
164      * if they are enabled.
165      *
166      * @param levels String names of levels.
167      * @param maxLevelNum Size to make the array.
168      */

169     private boolean[] getLevelStateArray(String JavaDoc[] levels, int maxLevelNum) {
170         int levelNum;
171         // Initialize the stated.
172
boolean[] levelNums = new boolean[maxLevelNum + 1];
173
174         for (int idx = 0; idx < levels.length; idx++) {
175             levelNums[getLevel(levels[idx])] = true;
176         }
177         return levelNums;
178     }
179
180     /**
181      * Configure the logger. All current configuration is discarded.
182      * This is a simplistic initial implementation that just allows
183      * directing to a single log file or stderr on a level basis.
184      * A more complete interface will be provided in the future.
185      *
186      * @param logFile The log file to write to.
187      * @param fileLevels List of levels that will be written to the file.
188      * @param stderrLevels List of levels that will be written to stderr.
189      * The same level may appear in both lists.
190      * @exception java.io.IOException If an error occurs opening the log file.
191      */

192     public synchronized void configure(String JavaDoc log4jConfFile)
193         throws ConfigException {
194         try {
195             DOMConfigurator.configure(log4jConfFile);
196         } catch (javax.xml.parsers.FactoryConfigurationError JavaDoc fce) {
197             throw new ConfigException("Cannot configure Log4jLogger:",
198                     fce);
199         }
200
201   }
202
203     /**
204      * This method configures Logger if configure data was not found in config
205      * file (at command line)
206      */

207     static private void configureLogger() {
208         // do the basic configuration:
209
BasicConfigurator.configure();
210         Logger root = Logger.getRootLogger();
211
212         // remove predefined appenders from basic configuration:
213
root.removeAllAppenders();
214         LoggerRepository repository = root.getLoggerRepository();
215
216         // set level for log info:
217
repository.setThreshold(Level.INFO);
218         RollingFileAppender multiserverAppender = null;
219         RollingFileAppender accessAppender = null;
220         // strale@uns.ns.ac.yu, 29 nov 2002
221
ConsoleAppender conAppender = null;
222         // set path to log files:
223
String JavaDoc enhydraLogs = System.getProperty("enhydra.home")
224                 + File.separator + "logs" + File.separator;
225         String JavaDoc multiserverLogFile = enhydraLogs + "multiserver.log";
226         String JavaDoc accessLogFile = enhydraLogs + "access.log";
227
228         try {
229
230             /* create default appenders:
231              * %d(ISO8601) - date in format quick to write
232              * %t - time
233              * %C(1) - full class name (one level) i.e.: com.lutris.Enhydra -> Enhydra
234              * %p - priority of the input
235              * %c - category of the input
236              * %m - massage
237              * %n - new line
238              */

239             multiserverAppender = new RollingFileAppender(new PatternLayout("%d{ISO8601}: [%t], %C(1) %p, %c: %m%n"),
240                     multiserverLogFile);
241             accessAppender = new RollingFileAppender(new PatternLayout("%m%n"),
242                     accessLogFile);
243             conAppender = new ConsoleAppender(new PatternLayout("%d{ISO8601}: [%t], %C(1) %p, %c: %m%n"));
244         } catch (IOException JavaDoc e) {
245             e.printStackTrace();
246         }
247         root.addAppender(multiserverAppender);
248         // create new logger for with "REQUEST" category that log to access.log:
249
Logger requestLogger = Logger.getLogger("REQUEST");
250
251         // does not apply root appender to REQUEST logger:
252
requestLogger.setAdditivity(false);
253         requestLogger.addAppender(accessAppender);
254         Logger sysOutLogger = Logger.getLogger("SysOut");
255
256         sysOutLogger.setAdditivity(false);
257         sysOutLogger.addAppender(conAppender);
258     }
259
260     /**
261      * Create a log channel.
262      */

263     private synchronized Log4jLogChannel createChannel(String JavaDoc facility) {
264          
265       String JavaDoc sepLine= (String JavaDoc)appSeparatorLine.get(facility);
266         if(sepLine==null)
267           sepLine=defaultSeparatorLine;
268         Log4jLogChannel channel
269                 = (Log4jLogChannel) logChannels.get(facility);
270
271         if (channel == null) {
272             channel = new Log4jLogChannel(facility,
273                     Logger.getLogger(facility),sepLine);
274             logChannels.put(facility, channel);
275         }
276        
277         return channel;
278     }
279
280     /**
281      * Get the log channel object for a facility. For a given facility,
282      * the same object is always returned.
283      *
284      * @param facility Facility the channel is associated with.
285      */

286     public LogChannel getChannel(String JavaDoc facility) {
287     
288     
289         Log4jLogChannel channel
290                 = (Log4jLogChannel) logChannels.get(facility);
291
292         if (channel == null) {
293             // Slow path, synchronized
294
channel = createChannel(facility);
295         }
296         return channel;
297     }
298
299     /**
300      * Create a log level.
301      */

302     private synchronized Integer JavaDoc createLevel(String JavaDoc level) {
303         Integer JavaDoc intLevel = (Integer JavaDoc) levelNumbers.get(level);
304
305         if (intLevel == null) {
306             intLevel = new Integer JavaDoc(numLevels);
307             levelNames[numLevels] = level;
308             levelNumbers.put(level, intLevel);
309             numLevels++;
310         }
311         return intLevel;
312     }
313
314     /**
315      * Convert a symbolic level to an integer identifier,
316      * creating it if it doesn't exist
317      *
318      * @param level Symbolic level that is to be checked.
319      * @return The numeric level identifier
320      */

321     public synchronized int getLevel(String JavaDoc level) {
322         Integer JavaDoc intLevel = (Integer JavaDoc) levelNumbers.get(level);
323
324         if (intLevel == null) {
325             // Slow path, synchronized
326
intLevel = createLevel(level);
327         }
328         return intLevel.intValue();
329     }
330
331     /**
332      * Convert an int to a symbolic level name.
333      *
334      * @param level an int level.
335      * @return The String symolic level name or null if there is not one.
336      */

337     public String JavaDoc getLevelName(int level) {
338         if ((level >= 0) && (level < numLevels)) {
339             return levelNames[level];
340         } else {
341             return null;
342         }
343     }
344
345     /**
346      * Configure Logger with given config section
347      *
348      * @param logConfig containing parameters for configuring logger
349      */

350     public void configure(Config logConfig) throws ConfigException {
351           
352         String JavaDoc fileName = null;
353         File JavaDoc logConfigFile = null;
354         if (logConfig.containsKey("Log4j")) {
355             fileName = logConfig.getString("Log4j");
356             logConfigFile = new File JavaDoc(fileName);
357             if (!logConfigFile.exists()){
358                 fileName = logConfig.getConfigFile().getFile().getParent()+File.separator+fileName;
359                 logConfigFile = new File JavaDoc(fileName);
360                 if (!logConfigFile.exists()){
361                             fileName = logConfig.getConfigFile().getFile().getParent();
362                         if (null != fileName) {
363                             fileName += File.separator + DEFAULT_LOG_CONFIG_FILE;
364                         }
365                     }
366             }
367
368         } else if (null != logConfig.getConfigFile()) {
369             fileName = logConfig.getConfigFile().getFile().getParent();
370             if (null != fileName) {
371                 fileName += File.separator + DEFAULT_LOG_CONFIG_FILE;
372             }
373         } else {
374             throw new ConfigException("Cannot configure logger. Config file is null.");
375         }
376         if (logConfig.containsKey("SeparatorLine")) {
377         
378       String JavaDoc app=logConfig.getString("Server.AppClass");
379       String JavaDoc separator = logConfig.getString("SeparatorLine");
380       int index =app.lastIndexOf(".");
381       String JavaDoc temp=app.substring(index);
382       appSeparatorLine.put(temp.substring(1) ,separator);
383           }
384       configure(fileName);
385     }
386 }
387
Popular Tags