001: /**
002: * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999.
003: *
004: * This program is free software; you can redistribute it and/or modify
005: * it under the terms of the latest version of the GNU Lesser General
006: * Public License as published by the Free Software Foundation;
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public License
014: * along with this program (LICENSE.txt); if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
016: */package org.jamwiki.utils;
017:
018: import java.io.File;
019: import java.io.FileInputStream;
020: import java.net.URL;
021: import java.net.URLDecoder;
022: import java.util.Properties;
023: import java.util.logging.FileHandler;
024: import java.util.logging.Level;
025: import java.util.logging.Logger;
026:
027: /**
028: * This class provides a wrapper around the {@link java.util.logging.Logger}
029: * class, allowing additional utility methods to be included such as allowing
030: * a log message to include a Throwable object. From an implementation
031: * standpoint it would have been much easier to simply sub-class the Logger
032: * class, but that class is implemented in such a way to make sub-classes
033: * exceedingly difficult to create.
034: *
035: * @see org.jamwiki.utils.WikiLogFormatter
036: */
037: public class WikiLogger {
038:
039: private final Logger logger;
040:
041: private static FileHandler DEFAULT_LOG_HANDLER = null;
042: private static Level DEFAULT_LOG_LEVEL = null;
043: /** Log configuration property file. */
044: public final static String LOG_PROPERTIES_FILENAME = "logging.properties";
045: public final static String DEFAULT_LOG_FILENAME = "jamwiki.log.0";
046:
047: static {
048: initializeLogParams();
049: }
050:
051: /**
052: *
053: */
054: private WikiLogger(Logger logger) {
055: this .logger = logger;
056: }
057:
058: /**
059: * Return the current ClassLoader. First try to get the current thread's
060: * ClassLoader, and if that fails return the ClassLoader that loaded this
061: * class instance.
062: *
063: * @return An instance of the current ClassLoader.
064: */
065: private static ClassLoader getClassLoader() {
066: // NOTE: This method duplicates the Utilities.getClassLoader method, but
067: // is copied here to prevent this class from having any dependencies on
068: // other JAMWiki classes.
069: ClassLoader loader = null;
070: try {
071: loader = Thread.currentThread().getContextClassLoader();
072: } catch (Exception e) {
073: // ignore, try the current class's ClassLoader
074: }
075: if (loader == null) {
076: loader = WikiLogger.class.getClassLoader();
077: }
078: return loader;
079: }
080:
081: /**
082: *
083: */
084: public static String getDefaultLogFile() {
085: System.out.println(System.getProperties());
086: String logFile = System.getProperty("java.io.tmpdir")
087: + System.getProperty("file.separator")
088: + DEFAULT_LOG_FILENAME;
089: return logFile;
090: }
091:
092: /**
093: *
094: */
095: public static String getLogConfigFile() {
096: String logConfig = System.getProperty("file.separator")
097: + "WEB-INF" + System.getProperty("file.separator")
098: + "classes" + System.getProperty("file.separator")
099: + LOG_PROPERTIES_FILENAME;
100: return logConfig;
101: }
102:
103: /**
104: * Retrieve a named <code>WikiLogger</code> object.
105: *
106: * @param name The name of the log object to retrieve or create.
107: * @return A logger instance for the given name.
108: */
109: public static WikiLogger getLogger(String name) {
110: Logger logger = Logger.getLogger(name);
111: if (WikiLogger.DEFAULT_LOG_HANDLER != null) {
112: logger.addHandler(WikiLogger.DEFAULT_LOG_HANDLER);
113: logger.setLevel(DEFAULT_LOG_LEVEL);
114: }
115: return new WikiLogger(logger);
116: }
117:
118: /**
119: *
120: */
121: private static void initializeLogParams() {
122: FileInputStream stream = null;
123: try {
124: File propertyFile = WikiLogger.loadProperties();
125: stream = new FileInputStream(propertyFile);
126: Properties properties = new Properties();
127: properties.load(stream);
128: String pattern = properties
129: .getProperty("org.jamwiki.pattern");
130: int limit = new Integer(properties
131: .getProperty("org.jamwiki.limit")).intValue();
132: int count = new Integer(properties
133: .getProperty("org.jamwiki.count")).intValue();
134: boolean append = Boolean.valueOf(
135: properties.getProperty("org.jamwiki.append"))
136: .booleanValue();
137: String datePattern = properties
138: .getProperty("org.jamwiki.timestamp");
139: DEFAULT_LOG_LEVEL = Level.parse(properties
140: .getProperty("org.jamwiki.level"));
141: WikiLogger.DEFAULT_LOG_HANDLER = new FileHandler(pattern,
142: limit, count, append);
143: DEFAULT_LOG_HANDLER.setFormatter(new WikiLogFormatter(
144: datePattern));
145: DEFAULT_LOG_HANDLER.setLevel(DEFAULT_LOG_LEVEL);
146: // test the logger to verify permissions are OK
147: Logger logger = Logger
148: .getLogger(WikiLogger.class.getName());
149: logger.addHandler(WikiLogger.DEFAULT_LOG_HANDLER);
150: logger.setLevel(DEFAULT_LOG_LEVEL);
151: logger.config("JAMWiki log initialized from "
152: + propertyFile.getPath() + " with pattern "
153: + pattern);
154: } catch (Exception e) {
155: System.out
156: .println("WARNING: Unable to load custom JAMWiki logging configuration, using system default "
157: + e.getMessage());
158: WikiLogger.DEFAULT_LOG_HANDLER = null;
159: } finally {
160: if (stream != null) {
161: try {
162: stream.close();
163: } catch (Exception ex) {
164: }
165: }
166: }
167: }
168:
169: /**
170: *
171: */
172: private static File loadProperties() throws Exception {
173: ClassLoader loader = WikiLogger.getClassLoader();
174: URL url = loader.getResource(LOG_PROPERTIES_FILENAME);
175: if (url == null) {
176: throw new Exception("Log initialization file "
177: + LOG_PROPERTIES_FILENAME + " could not be found");
178: }
179: File propertyFile = new File(URLDecoder.decode(url.getFile(),
180: "UTF-8"));
181: if (!propertyFile.exists()) {
182: throw new Exception("Log initialization file "
183: + LOG_PROPERTIES_FILENAME + " could not be found");
184: }
185: return propertyFile;
186: }
187:
188: /**
189: * Log a message at the {@link java.util.logging.Level#CONFIG} level,
190: * provided that the current log level is {@link java.util.logging.Level#CONFIG}
191: * or greater.
192: *
193: * @param msg The message to be written to the log.
194: */
195: public void config(String msg) {
196: this .logger.config(msg);
197: }
198:
199: /**
200: * Log a message and an exception at the {@link java.util.logging.Level#CONFIG}
201: * level, provided that the current log level is {@link java.util.logging.Level#CONFIG}
202: * or greater.
203: *
204: * @param msg The message to be written to the log.
205: * @param thrown An exception to be written to the log.
206: */
207: public void config(String msg, Throwable thrown) {
208: this .logger.log(Level.CONFIG, msg, thrown);
209: }
210:
211: /**
212: * Log a message at the {@link java.util.logging.Level#FINE} level,
213: * provided that the current log level is {@link java.util.logging.Level#FINE}
214: * or greater.
215: *
216: * @param msg The message to be written to the log.
217: */
218: public void fine(String msg) {
219: this .logger.fine(msg);
220: }
221:
222: /**
223: * Log a message and an exception at the {@link java.util.logging.Level#FINE}
224: * level, provided that the current log level is {@link java.util.logging.Level#FINE}
225: * or greater.
226: *
227: * @param msg The message to be written to the log.
228: * @param thrown An exception to be written to the log.
229: */
230: public void fine(String msg, Throwable thrown) {
231: this .logger.log(Level.FINE, msg, thrown);
232: }
233:
234: /**
235: * Log a message at the {@link java.util.logging.Level#FINER} level,
236: * provided that the current log level is {@link java.util.logging.Level#FINER}
237: * or greater.
238: *
239: * @param msg The message to be written to the log.
240: */
241: public void finer(String msg) {
242: this .logger.finer(msg);
243: }
244:
245: /**
246: * Log a message and an exception at the {@link java.util.logging.Level#FINER}
247: * level, provided that the current log level is {@link java.util.logging.Level#FINER}
248: * or greater.
249: *
250: * @param msg The message to be written to the log.
251: * @param thrown An exception to be written to the log.
252: */
253: public void finer(String msg, Throwable thrown) {
254: this .logger.log(Level.FINER, msg, thrown);
255: }
256:
257: /**
258: * Log a message at the {@link java.util.logging.Level#FINEST} level,
259: * provided that the current log level is {@link java.util.logging.Level#FINEST}
260: * or greater.
261: *
262: * @param msg The message to be written to the log.
263: */
264: public void finest(String msg) {
265: this .logger.finest(msg);
266: }
267:
268: /**
269: * Log a message and an exception at the {@link java.util.logging.Level#FINEST}
270: * level, provided that the current log level is {@link java.util.logging.Level#FINEST}
271: * or greater.
272: *
273: * @param msg The message to be written to the log.
274: * @param thrown An exception to be written to the log.
275: */
276: public void finest(String msg, Throwable thrown) {
277: this .logger.log(Level.FINEST, msg, thrown);
278: }
279:
280: /**
281: * Log a message at the {@link java.util.logging.Level#INFO} level,
282: * provided that the current log level is {@link java.util.logging.Level#INFO}
283: * or greater.
284: *
285: * @param msg The message to be written to the log.
286: */
287: public void info(String msg) {
288: this .logger.info(msg);
289: }
290:
291: /**
292: * Log a message and an exception at the {@link java.util.logging.Level#INFO}
293: * level, provided that the current log level is {@link java.util.logging.Level#INFO}
294: * or greater.
295: *
296: * @param msg The message to be written to the log.
297: * @param thrown An exception to be written to the log.
298: */
299: public void info(String msg, Throwable thrown) {
300: this .logger.log(Level.INFO, msg, thrown);
301: }
302:
303: /**
304: * Log a message at the {@link java.util.logging.Level#SEVERE} level,
305: * provided that the current log level is {@link java.util.logging.Level#SEVERE}
306: * or greater.
307: *
308: * @param msg The message to be written to the log.
309: */
310: public void severe(String msg) {
311: this .logger.severe(msg);
312: }
313:
314: /**
315: * Log a message and an exception at the {@link java.util.logging.Level#SEVERE}
316: * level, provided that the current log level is {@link java.util.logging.Level#SEVERE}
317: * or greater.
318: *
319: * @param msg The message to be written to the log.
320: * @param thrown An exception to be written to the log.
321: */
322: public void severe(String msg, Throwable thrown) {
323: this .logger.log(Level.SEVERE, msg, thrown);
324: }
325:
326: /**
327: * Log a message at the {@link java.util.logging.Level#WARNING} level,
328: * provided that the current log level is {@link java.util.logging.Level#WARNING}
329: * or greater.
330: *
331: * @param msg The message to be written to the log.
332: */
333: public void warning(String msg) {
334: this .logger.warning(msg);
335: }
336:
337: /**
338: * Log a message and an exception at the {@link java.util.logging.Level#WARNING}
339: * level, provided that the current log level is {@link java.util.logging.Level#WARNING}
340: * or greater.
341: *
342: * @param msg The message to be written to the log.
343: * @param thrown An exception to be written to the log.
344: */
345: public void warning(String msg, Throwable thrown) {
346: this.logger.log(Level.WARNING, msg, thrown);
347: }
348: }
|