001: /*
002: * Copyright 2003 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package velosurf.util;
018:
019: import java.io.FileWriter;
020: import java.io.IOException;
021: import java.io.OutputStream;
022: import java.io.PrintStream;
023: import java.io.PrintWriter;
024: import java.io.StringWriter;
025: import java.io.Writer;
026: import java.io.FileNotFoundException;
027: import java.text.SimpleDateFormat;
028: import java.util.Date;
029:
030: /** This class is the logger used by velosurf.
031: *
032: * @author <a href=mailto:claude.brisson@gmail.com>Claude Brisson</a>
033: */
034: public class Logger {
035: /**
036: * trace messages loglevel.
037: */
038: public final static int TRACE_ID = 0;
039:
040: /**
041: * debug messages loglevel.
042: */
043: public final static int DEBUG_ID = 1;
044:
045: /**
046: * info messages loglevel.
047: */
048: public final static int INFO_ID = 2;
049:
050: /**
051: * warn messages loglevel.
052: */
053: public final static int WARN_ID = 3;
054:
055: /**
056: * error messages loglevel.
057: */
058: public final static int ERROR_ID = 4;
059:
060: /**
061: * fatal messages loglevel.
062: */
063: public final static int FATAL_ID = 5;
064:
065: /**
066: * Current log level.
067: */
068: private static int logLevel = INFO_ID;
069:
070: /**
071: * whether to display timestamps.
072: */
073: private static boolean displayTimestamps = false;
074:
075: /**
076: * whether the logger captures stdout.
077: */
078: private static boolean captureStdout = false;
079:
080: /**
081: * whether the logger captures stderr.
082: */
083: private static boolean captureStderr;
084:
085: /**
086: * max number of lines to log in asynchronous mode.
087: */
088: private static int asyncLimit = 50;
089:
090: /**
091: * Did someone give me an otput writer?
092: */
093: private static boolean initialized = false;
094:
095: /** Sets the log level.
096: * @param logLevel log level
097: */
098: public static void setLogLevel(int logLevel) {
099: Logger.logLevel = logLevel;
100: }
101:
102: /** whether to display timestamps.
103: * @param timestamps
104: */
105: public static void setDisplayTimestamps(boolean timestamps) {
106: displayTimestamps = timestamps;
107: }
108:
109: /** Gets the current log level.
110: * @return the current log level
111: */
112: public static int getLogLevel() {
113: return logLevel;
114: }
115:
116: /** date format for timestamps.
117: */
118: static SimpleDateFormat format = null;
119: /** asynchronous log used at start.
120: */
121: static StringWriter asyncLog = null;
122: /** log output printwriter.
123: */
124: static PrintWriter log = null;
125: static {
126: try {
127: format = new SimpleDateFormat("[yyyy/MM/dd HH:mm:ss]");
128: // initialize with an asynchronous buffer
129: asyncLog = new StringWriter();
130: log = new PrintWriter(asyncLog);
131: info("log initialized");
132: } catch (Throwable e) {
133: System.err.println("no log!");
134: e.printStackTrace(System.err);
135: }
136: }
137:
138: /** stdout old value.
139: */
140: static PrintStream oldStdout = null;
141: /** stderr old value.
142: */
143: static PrintStream oldStderr = null;
144:
145: /** logs a string.
146: *
147: * @param s string
148: */
149: static private void log(String s) {
150: log.println(header() + s);
151: log.flush();
152: }
153:
154: /** logs an exception with a string.
155: *
156: * @param s string
157: * @param e exception
158: */
159: static public void log(String s, Throwable e) {
160: error(s);
161: e.printStackTrace(log);
162: log.flush();
163: }
164:
165: /** log an exception.
166: *
167: * @param e exception
168: */
169: static public void log(Throwable e) {
170: String msg = e.getMessage();
171: log((msg != null ? msg : ""), e);
172: }
173:
174: static int lines = 0;
175:
176: /** log a string using a verbose level.
177: *
178: * @param level verbose level
179: * @param s string to log
180: */
181: static public void log(int level, String s) {
182: if (level < logLevel)
183: return;
184: String prefix = "";
185: switch (level) {
186: case TRACE_ID:
187: prefix = " [trace] ";
188: break;
189: case DEBUG_ID:
190: prefix = " [debug] ";
191: break;
192: case INFO_ID:
193: prefix = " [info] ";
194: break;
195: case WARN_ID:
196: prefix = " [warn] ";
197: break;
198: case ERROR_ID:
199: prefix = " [error] ";
200: break;
201: case FATAL_ID:
202: prefix = " [fatal] ";
203: break;
204: }
205: log(prefix + s);
206: if (notify && level >= notifLevel && notifier != null) {
207: String msg = prefix + s;
208: int cr = msg.indexOf('\n');
209: String subject = (cr == -1 ? msg : msg.substring(0, cr));
210: notifier.sendNotification(subject, msg);
211: }
212: lines++;
213: // no more than 100 lines in asynchronous mode
214: if (asyncLog != null && lines > asyncLimit) {
215: log2Stderr();
216: flushAsyncLog();
217: warn("More than " + asyncLimit
218: + " lines in asynchronous logging mode...");
219: warn("Automatically switching to stderr");
220: }
221: }
222:
223: /** logs a tracing string.
224: *
225: * @param s tracing string
226: */
227: static public void trace(String s) {
228: log(TRACE_ID, s);
229: }
230:
231: /** logs a debug string.
232: *
233: * @param s debug string
234: */
235: static public void debug(String s) {
236: log(DEBUG_ID, s);
237: }
238:
239: /** logs an info string.
240: *
241: * @param s info string
242: */
243: static public void info(String s) {
244: log(INFO_ID, s);
245: }
246:
247: /** logs a warning string.
248: *
249: * @param s warning string
250: */
251: static public void warn(String s) {
252: log(WARN_ID, s);
253: }
254:
255: /** logs an error string.
256: *
257: * @param s error string
258: */
259: static public void error(String s) {
260: log(ERROR_ID, s);
261: }
262:
263: /** logs a fatal error string.
264: *
265: * @param s fatal error string
266: */
267: static public void fatal(String s) {
268: log(ERROR_ID, s);
269: }
270:
271: /** get the output writer.
272: *
273: * @return writer
274: */
275: static public PrintWriter getWriter() {
276: return log;
277: }
278:
279: /** set the output writer.
280: *
281: * @param out PrintWriter or Writer or OutputStream
282: */
283: static public void setWriter(Object out) {
284: if (log != null) {
285: log.flush();
286: log.close();
287: }
288: if (out instanceof PrintWriter)
289: log = (PrintWriter) out;
290: else if (out instanceof Writer)
291: log = new PrintWriter((Writer) out);
292: else if (out instanceof OutputStream)
293: log = new PrintWriter((OutputStream) out);
294: else
295: throw new RuntimeException(
296: "Logger.setWriter: PANIC! class "
297: + out.getClass().getName()
298: + " cannot be used to build a PrintWriter!");
299: if (asyncLog != null)
300: flushAsyncLog();
301: initialized = true;
302: }
303:
304: /** redirects stdout towards output writer.
305: */
306: static public void startCaptureStdout() {
307: oldStdout = System.out;
308: System.setOut(new PrintStream(new WriterOutputStream(log)));
309: captureStdout = true;
310: }
311:
312: /** stop redirecting stdout.
313: */
314: static public void stopCaptureStdout() {
315: if (captureStdout)
316: System.setOut(oldStdout);
317: captureStdout = false;
318: }
319:
320: /** redirects stderr towards the output writer.
321: */
322: static public void startCaptureStderr() {
323: oldStderr = System.err;
324: System.setErr(new PrintStream(new WriterOutputStream(log)));
325: captureStderr = true;
326: }
327:
328: /** stops redirecting stderr.
329: */
330: static public void stopCaptureStderr() {
331: if (captureStderr)
332: System.setErr(oldStderr);
333: captureStderr = false;
334: }
335:
336: /** log to stdout.
337: */
338: static public void log2Stdout() {
339: stopCaptureStdout();
340: stopCaptureStderr();
341: log = new PrintWriter(System.out);
342: flushAsyncLog();
343: }
344:
345: /** log to stderr.
346: */
347: static public void log2Stderr() {
348: stopCaptureStdout();
349: stopCaptureStderr();
350: log = new PrintWriter(System.err);
351: flushAsyncLog();
352: }
353:
354: /** log to file.
355: */
356: static public void log2File(String file)
357: throws FileNotFoundException, IOException {
358: log = new PrintWriter(new FileWriter(file, true));
359: log.println();
360: log
361: .println("=================================================");
362: flushAsyncLog();
363: }
364:
365: /** returns "Velosurf ".
366: *
367: * @return return the header
368: */
369: static private String header() {
370: return displayTimestamps ? format.format(new Date())
371: + " Velosurf " : " Velosurf ";
372: }
373:
374: /** flush the asynchronous log in the output writer.
375: */
376: static private void flushAsyncLog() {
377: if (asyncLog != null) {
378: try {
379: log(asyncLog.toString());
380: asyncLog.close();
381: asyncLog = null;
382: } catch (IOException ioe) {
383: log(ioe);
384: }
385: }
386: }
387:
388: /** queries the initialized state.
389: *
390: */
391: static public boolean isInitialized() {
392: return initialized;
393: }
394:
395: /** dumps the current stack.
396: */
397: static public void dumpStack() {
398: try {
399: throw new Exception("dumpStack");
400: } catch (Exception e) {
401: e.printStackTrace(log);
402: }
403: }
404:
405: static private MailNotifier notifier = null;
406: static private int notifLevel = ERROR_ID;
407: static private boolean notify = false;
408:
409: static public void setNotificationParams(String host,
410: String sender, String recipient) {
411: if (notifier != null) {
412: notifier.stop();
413: }
414: notifier = new MailNotifier(host, sender, recipient);
415: }
416:
417: static public void setNotificationLevel(int level) {
418: notifLevel = level;
419: }
420:
421: static public int getNotificationLevel(int level) {
422: return notifLevel;
423: }
424:
425: static public void enableNotifications(boolean enable) {
426: if (enable == notify) {
427: return;
428: }
429: if (enable) {
430: if (notifier == null) {
431: Logger
432: .error("Please set notification params before enabling notification!");
433: return;
434: }
435: notifier.start();
436: } else {
437: if (notifier != null) {
438: notifier.stop();
439: }
440: }
441: notify = enable;
442: }
443:
444: }
|