001: /**
002: * $RCSfile$
003: * $Revision: 7655 $
004: * $Date: 2007-03-22 13:50:33 -0700 (Thu, 22 Mar 2007) $
005: *
006: * Copyright (C) 1999-2004 Jive Software. All rights reserved.
007: *
008: * This software is the proprietary information of Jive Software.
009: * Use is subject to license terms.
010: */package org.jivesoftware.util;
011:
012: import org.jivesoftware.util.log.Hierarchy;
013: import org.jivesoftware.util.log.LogTarget;
014: import org.jivesoftware.util.log.Logger;
015: import org.jivesoftware.util.log.Priority;
016: import org.jivesoftware.util.log.format.ExtendedPatternFormatter;
017: import org.jivesoftware.util.log.output.io.StreamTarget;
018: import org.jivesoftware.util.log.output.io.rotate.RevolvingFileStrategy;
019: import org.jivesoftware.util.log.output.io.rotate.RotateStrategyBySize;
020: import org.jivesoftware.util.log.output.io.rotate.RotatingFileTarget;
021:
022: import java.io.File;
023: import java.io.IOException;
024: import java.io.PrintWriter;
025: import java.io.StringWriter;
026: import java.util.ArrayList;
027: import java.util.List;
028: import java.util.logging.Handler;
029: import java.util.logging.Level;
030: import java.util.logging.LogRecord;
031:
032: /**
033: * Simple wrapper to the incorporated LogKit to log under a single logging name.
034: *
035: * @author Bruce Ritchie
036: */
037: public class Log {
038:
039: private static final Logger debugLog = Hierarchy
040: .getDefaultHierarchy().getLoggerFor("Jive-DEBUG");
041: private static final Logger infoLog = Hierarchy
042: .getDefaultHierarchy().getLoggerFor("Jive-INFO");
043: private static final Logger warnLog = Hierarchy
044: .getDefaultHierarchy().getLoggerFor("Jive-WARN");
045: private static final Logger errorLog = Hierarchy
046: .getDefaultHierarchy().getLoggerFor("Jive-ERR");
047:
048: private static String logNameDebug = null;
049: private static String logNameInfo = null;
050: private static String logNameWarn = null;
051: private static String logNameError = null;
052: private static String debugPattern = null;
053: private static String infoPattern = null;
054: private static String warnPattern = null;
055: private static String errorPattern = null;
056: private static String logDirectory = null;
057:
058: private static long maxDebugSize = 1024;
059: private static long maxInfoSize = 1024;
060: private static long maxWarnSize = 1024;
061: private static long maxErrorSize = 1024;
062:
063: private static boolean debugEnabled;
064:
065: static {
066: initLog();
067: }
068:
069: private Log() {
070: }
071:
072: /**
073: * This method is used to initialize the Log class. For normal operations this method
074: * should <b>never</b> be called, rather it's only publically available so that the class
075: * can be reset by the setup process once the home directory has been specified.
076: */
077: public static void initLog() {
078: try {
079: logDirectory = JiveGlobals.getXMLProperty("log.directory");
080: if (logDirectory == null) {
081: if (JiveGlobals.getHomeDirectory() != null) {
082: File openfireHome = new File(JiveGlobals
083: .getHomeDirectory());
084: if (openfireHome.exists()
085: && openfireHome.canWrite()) {
086: logDirectory = (new File(openfireHome, "logs"))
087: .toString();
088: }
089: }
090: }
091:
092: if (!logDirectory.endsWith(File.separator)) {
093: logDirectory = logDirectory + File.separator;
094: }
095:
096: // Make sure the logs directory exists. If not, make it:
097: File logDir = new File(logDirectory);
098: if (!logDir.exists()) {
099: logDir.mkdir();
100: }
101:
102: logNameDebug = logDirectory + "debug.log";
103: logNameInfo = logDirectory + "info.log";
104: logNameWarn = logDirectory + "warn.log";
105: logNameError = logDirectory + "error.log";
106:
107: debugPattern = JiveGlobals
108: .getXMLProperty("log.debug.format");
109: infoPattern = JiveGlobals.getXMLProperty("log.info.format");
110: warnPattern = JiveGlobals.getXMLProperty("log.warn.format");
111: errorPattern = JiveGlobals
112: .getXMLProperty("log.error.format");
113:
114: try {
115: maxDebugSize = Long.parseLong(JiveGlobals
116: .getXMLProperty("log.debug.size"));
117: } catch (NumberFormatException e) { /* ignore */
118: }
119: try {
120: maxInfoSize = Long.parseLong(JiveGlobals
121: .getXMLProperty("log.info.size"));
122: } catch (NumberFormatException e) { /* ignore */
123: }
124: try {
125: maxWarnSize = Long.parseLong(JiveGlobals
126: .getXMLProperty("log.warn.size"));
127: } catch (NumberFormatException e) { /* ignore */
128: }
129: try {
130: maxErrorSize = Long.parseLong(JiveGlobals
131: .getXMLProperty("log.error.size"));
132: } catch (NumberFormatException e) { /* ignore */
133: }
134:
135: debugEnabled = "true".equals(JiveGlobals
136: .getXMLProperty("log.debug.enabled"));
137: } catch (Exception e) {
138: // we'll get an exception if home isn't setup yet - we ignore that since
139: // it's sure to be logged elsewhere :)
140: }
141:
142: if (debugPattern == null) {
143: debugPattern = "%{time:yyyy.MM.dd HH:mm:ss} %{message}\\n%{throwable}";
144: }
145: if (infoPattern == null) {
146: infoPattern = "%{time:yyyy.MM.dd HH:mm:ss} %{message}\\n%{throwable}";
147: }
148: if (warnPattern == null) {
149: warnPattern = "%{time:yyyy.MM.dd HH:mm:ss} %{message}\\n%{throwable}";
150: }
151: if (errorPattern == null) {
152: errorPattern = "%{time:yyyy.MM.dd HH:mm:ss} [%{method}] %{message}\\n%{throwable}";
153: }
154:
155: createLogger(debugPattern, logNameDebug, maxDebugSize,
156: debugLog, Priority.DEBUG);
157: createLogger(infoPattern, logNameInfo, maxInfoSize, infoLog,
158: Priority.INFO);
159: createLogger(warnPattern, logNameWarn, maxWarnSize, warnLog,
160: Priority.WARN);
161: createLogger(errorPattern, logNameError, maxErrorSize,
162: errorLog, Priority.ERROR);
163:
164: // set up the ties into jdk logging
165: Handler jdkLogHandler = new JiveLogHandler();
166: jdkLogHandler.setLevel(Level.ALL);
167: java.util.logging.Logger.getLogger("")
168: .addHandler(jdkLogHandler);
169: }
170:
171: private static void createLogger(String pattern, String logName,
172: long maxLogSize, Logger logger, Priority priority) {
173: // debug log file
174: ExtendedPatternFormatter formatter = new ExtendedPatternFormatter(
175: pattern);
176: StreamTarget target = null;
177: Exception ioe = null;
178:
179: try {
180: // home was not setup correctly
181: if (logName == null) {
182: throw new IOException(
183: "LogName was null - OpenfireHome not set?");
184: } else {
185: RevolvingFileStrategy fileStrategy = new RevolvingFileStrategy(
186: logName, 5);
187: RotateStrategyBySize rotateStrategy = new RotateStrategyBySize(
188: maxLogSize * 1024);
189: target = new RotatingFileTarget(formatter,
190: rotateStrategy, fileStrategy);
191: }
192: } catch (IOException e) {
193: ioe = e;
194: // can't log to file, log to stderr
195: target = new StreamTarget(System.err, formatter);
196: }
197:
198: logger.setLogTargets(new LogTarget[] { target });
199: logger.setPriority(priority);
200:
201: if (ioe != null) {
202: logger.debug("Error occurred opening log file: "
203: + ioe.getMessage());
204: }
205: }
206:
207: public static void setProductName(String productName) {
208: debugPattern = productName + " " + debugPattern;
209: infoPattern = productName + " " + infoPattern;
210: warnPattern = productName + " " + warnPattern;
211: errorPattern = productName + " " + errorPattern;
212:
213: createLogger(debugPattern, logNameDebug, maxDebugSize,
214: debugLog, Priority.DEBUG);
215: createLogger(infoPattern, logNameInfo, maxInfoSize, infoLog,
216: Priority.INFO);
217: createLogger(warnPattern, logNameWarn, maxWarnSize, warnLog,
218: Priority.WARN);
219: createLogger(errorPattern, logNameError, maxErrorSize,
220: errorLog, Priority.ERROR);
221: }
222:
223: public static boolean isErrorEnabled() {
224: return errorLog.isErrorEnabled();
225: }
226:
227: public static boolean isFatalEnabled() {
228: return errorLog.isFatalErrorEnabled();
229: }
230:
231: public static boolean isDebugEnabled() {
232: return debugEnabled;
233: }
234:
235: public static void setDebugEnabled(boolean enabled) {
236: JiveGlobals.setXMLProperty("log.debug.enabled", Boolean
237: .toString(enabled));
238: debugEnabled = enabled;
239: }
240:
241: public static boolean isInfoEnabled() {
242: return infoLog.isInfoEnabled();
243: }
244:
245: public static boolean isWarnEnabled() {
246: return warnLog.isWarnEnabled();
247: }
248:
249: public static void debug(String s) {
250: if (isDebugEnabled()) {
251: debugLog.debug(s);
252: }
253: }
254:
255: public static void debug(Throwable throwable) {
256: if (isDebugEnabled()) {
257: debugLog.debug("", throwable);
258: }
259: }
260:
261: public static void debug(String s, Throwable throwable) {
262: if (isDebugEnabled()) {
263: debugLog.debug(s, throwable);
264: }
265: }
266:
267: public static void markDebugLogFile(String username) {
268: RotatingFileTarget target = (RotatingFileTarget) debugLog
269: .getLogTargets()[0];
270: markLogFile(username, target);
271: }
272:
273: public static void rotateDebugLogFile() {
274: RotatingFileTarget target = (RotatingFileTarget) debugLog
275: .getLogTargets()[0];
276: try {
277: target.rotate();
278: } catch (IOException e) {
279: System.err
280: .println("Warning: There was an error rotating the Jive debug log file. "
281: + "Logging may not work correctly until a restart happens.");
282: }
283: }
284:
285: public static void info(String s) {
286: if (isInfoEnabled()) {
287: infoLog.info(s);
288: }
289: }
290:
291: public static void info(Throwable throwable) {
292: if (isInfoEnabled()) {
293: infoLog.info("", throwable);
294: }
295: }
296:
297: public static void info(String s, Throwable throwable) {
298: if (isInfoEnabled()) {
299: infoLog.info(s, throwable);
300: }
301: }
302:
303: public static void markInfoLogFile(String username) {
304: RotatingFileTarget target = (RotatingFileTarget) infoLog
305: .getLogTargets()[0];
306: markLogFile(username, target);
307: }
308:
309: public static void rotateInfoLogFile() {
310: RotatingFileTarget target = (RotatingFileTarget) infoLog
311: .getLogTargets()[0];
312: try {
313: target.rotate();
314: } catch (IOException e) {
315: System.err
316: .println("Warning: There was an error rotating the Jive info log file. "
317: + "Logging may not work correctly until a restart happens.");
318: }
319: }
320:
321: public static void warn(String s) {
322: if (isWarnEnabled()) {
323: warnLog.warn(s);
324: }
325: }
326:
327: public static void warn(Throwable throwable) {
328: if (isWarnEnabled()) {
329: warnLog.warn("", throwable);
330: }
331: }
332:
333: public static void warn(String s, Throwable throwable) {
334: if (isWarnEnabled()) {
335: warnLog.warn(s, throwable);
336: }
337: }
338:
339: public static void markWarnLogFile(String username) {
340: RotatingFileTarget target = (RotatingFileTarget) warnLog
341: .getLogTargets()[0];
342: markLogFile(username, target);
343: }
344:
345: public static void rotateWarnLogFile() {
346: RotatingFileTarget target = (RotatingFileTarget) warnLog
347: .getLogTargets()[0];
348: try {
349: target.rotate();
350: } catch (IOException e) {
351: System.err
352: .println("Warning: There was an error rotating the Jive warn log file. "
353: + "Logging may not work correctly until a restart happens.");
354: }
355: }
356:
357: public static void error(String s) {
358: if (isErrorEnabled()) {
359: errorLog.error(s);
360: if (isDebugEnabled()) {
361: printToStdErr(s, null);
362: }
363: }
364: }
365:
366: public static void error(Throwable throwable) {
367: if (isErrorEnabled()) {
368: errorLog.error("", throwable);
369: if (isDebugEnabled()) {
370: printToStdErr(null, throwable);
371: }
372: }
373: }
374:
375: public static void error(String s, Throwable throwable) {
376: if (isErrorEnabled()) {
377: errorLog.error(s, throwable);
378: if (isDebugEnabled()) {
379: printToStdErr(s, throwable);
380: }
381: }
382: }
383:
384: public static void markErrorLogFile(String username) {
385: RotatingFileTarget target = (RotatingFileTarget) errorLog
386: .getLogTargets()[0];
387: markLogFile(username, target);
388: }
389:
390: public static void rotateErrorLogFile() {
391: RotatingFileTarget target = (RotatingFileTarget) errorLog
392: .getLogTargets()[0];
393: try {
394: target.rotate();
395: } catch (IOException e) {
396: System.err
397: .println("Warning: There was an error rotating the Jive error log file. "
398: + "Logging may not work correctly until a restart happens.");
399: }
400: }
401:
402: public static void fatal(String s) {
403: if (isFatalEnabled()) {
404: errorLog.fatalError(s);
405: if (isDebugEnabled()) {
406: printToStdErr(s, null);
407: }
408: }
409: }
410:
411: public static void fatal(Throwable throwable) {
412: if (isFatalEnabled()) {
413: errorLog.fatalError("", throwable);
414: if (isDebugEnabled()) {
415: printToStdErr(null, throwable);
416: }
417: }
418: }
419:
420: public static void fatal(String s, Throwable throwable) {
421: if (isFatalEnabled()) {
422: errorLog.fatalError(s, throwable);
423: if (isDebugEnabled()) {
424: printToStdErr(s, throwable);
425: }
426: }
427: }
428:
429: /**
430: * Returns the directory that log files exist in. The directory name will
431: * have a File.separator as the last character in the string.
432: *
433: * @return the directory that log files exist in.
434: */
435: public static String getLogDirectory() {
436: return logDirectory;
437: }
438:
439: private static void markLogFile(String username,
440: RotatingFileTarget target) {
441: List args = new ArrayList();
442: args.add(username);
443: args.add(JiveGlobals.formatDateTime(new java.util.Date()));
444: target.write(LocaleUtils.getLocalizedString(
445: "log.marker_inserted_by", args)
446: + "\n");
447: }
448:
449: private static void printToStdErr(String s, Throwable throwable) {
450: if (s != null) {
451: System.err.println(s);
452: }
453: if (throwable != null) {
454: StringWriter sw = new StringWriter();
455: PrintWriter pw = new PrintWriter(sw);
456: throwable.printStackTrace(pw);
457: System.err.print(sw.toString());
458: System.err.print("\n");
459: }
460: }
461:
462: private static final class JiveLogHandler extends Handler {
463:
464: public void publish(LogRecord record) {
465:
466: Level level = record.getLevel();
467: Throwable throwable = record.getThrown();
468:
469: if (Level.SEVERE.equals(level)) {
470:
471: if (throwable != null) {
472: Log.error(record.getMessage(), throwable);
473: } else {
474: Log.error(record.getMessage());
475: }
476:
477: } else if (Level.WARNING.equals(level)) {
478:
479: if (throwable != null) {
480: Log.warn(record.getMessage(), throwable);
481: } else {
482: Log.warn(record.getMessage());
483: }
484:
485: } else if (Level.INFO.equals(level)) {
486:
487: if (throwable != null) {
488: Log.info(record.getMessage(), throwable);
489: } else {
490: Log.info(record.getMessage());
491: }
492:
493: } else {
494: // else FINE,FINER,FINEST
495:
496: if (throwable != null) {
497: Log.debug(record.getMessage(), throwable);
498: } else {
499: Log.debug(record.getMessage());
500: }
501:
502: }
503: }
504:
505: public void flush() {
506: // do nothing
507: }
508:
509: public void close() throws SecurityException {
510: // do nothing
511: }
512: }
513:
514: }
|