001: /*
002: * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: */
007: package winstone;
008:
009: import java.io.IOException;
010: import java.io.OutputStream;
011: import java.io.OutputStreamWriter;
012: import java.io.PrintWriter;
013: import java.io.StringWriter;
014: import java.io.Writer;
015: import java.text.DateFormat;
016: import java.text.SimpleDateFormat;
017: import java.util.Date;
018: import java.util.HashMap;
019: import java.util.Map;
020:
021: /**
022: * A utility class for logging event and status messages. It maintains a
023: * collection of streams for different types of messages, but any messages with
024: * unknown or unspecified stream go to the default stream.
025: *
026: * @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
027: * @version $Id: Logger.java,v 1.8 2006/11/09 06:01:43 rickknowles Exp $
028: */
029: public class Logger {
030: private static final String LINE_SEPARATOR = System
031: .getProperty("line.separator");
032:
033: public final static String DEFAULT_STREAM = "Winstone";
034: public static int MIN = 1;
035: public static int ERROR = 2;
036: public static int WARNING = 3;
037: public static int INFO = 5;
038: public static int SPEED = 6;
039: public static int DEBUG = 7;
040: public static int FULL_DEBUG = 8;
041: public static int MAX = 9;
042:
043: protected static Boolean semaphore = new Boolean(true);
044: protected static boolean initialised = false;
045: protected static Writer defaultStream;
046: protected static Map namedStreams;
047: // protected static Collection nullStreams;
048: protected static int currentDebugLevel;
049: protected final static DateFormat sdfLog = new SimpleDateFormat(
050: "yyyy/MM/dd HH:mm:ss");
051: protected static boolean showThrowingThread;
052:
053: /**
054: * Initialises default streams
055: */
056: public static void init(int level) {
057: init(level, System.out, false);
058: }
059:
060: /**
061: * Initialises default streams
062: */
063: public static void init(int level, OutputStream defaultStream,
064: boolean showThrowingThreadArg) {
065: synchronized (semaphore) {
066: if (!initialised) { // recheck in case we were blocking on another init
067: initialised = false;
068: currentDebugLevel = level;
069: namedStreams = new HashMap();
070: // nullStreams = new ArrayList();
071: initialised = true;
072: setStream(DEFAULT_STREAM, defaultStream);
073: showThrowingThread = showThrowingThreadArg;
074: }
075: }
076: }
077:
078: /**
079: * Allocates a stream for redirection to a file etc
080: */
081: public static void setStream(String name, OutputStream stream) {
082: setStream(name, stream != null ? new OutputStreamWriter(stream)
083: : null);
084: }
085:
086: /**
087: * Allocates a stream for redirection to a file etc
088: */
089: public static void setStream(String name, Writer stream) {
090: if (name == null) {
091: name = DEFAULT_STREAM;
092: }
093: if (!initialised) {
094: init(INFO);
095: }
096: synchronized (semaphore) {
097: if (name.equals(DEFAULT_STREAM)) {
098: defaultStream = stream;
099: } else if (stream == null) {
100: namedStreams.remove(name);
101: } else {
102: namedStreams.put(name, stream);
103: }
104: }
105: }
106:
107: /**
108: * Forces a flush of the contents to file, display, etc
109: */
110: public static void flush(String name) {
111: if (!initialised) {
112: init(INFO);
113: }
114:
115: Writer stream = getStreamByName(name);
116: if (stream != null) {
117: try {
118: stream.flush();
119: } catch (IOException err) {
120: }
121: }
122: }
123:
124: private static Writer getStreamByName(String streamName) {
125: if ((streamName != null) && streamName.equals(DEFAULT_STREAM)) {
126: // As long as the stream has not been nulled, assign the default if not found
127: synchronized (semaphore) {
128: Writer stream = (Writer) namedStreams.get(streamName);
129: if ((stream == null)
130: && !namedStreams.containsKey(streamName)) {
131: stream = defaultStream;
132: }
133: return stream;
134: }
135: } else {
136: return defaultStream;
137: }
138:
139: }
140:
141: public static void setCurrentDebugLevel(int level) {
142: if (!initialised) {
143: init(level);
144: } else
145: synchronized (semaphore) {
146: currentDebugLevel = level;
147: }
148: }
149:
150: /**
151: * Writes a log message to the requested stream, and immediately flushes
152: * the contents of the stream.
153: */
154: private static void logInternal(String streamName, String message,
155: Throwable error) {
156:
157: if (!initialised) {
158: init(INFO);
159: }
160:
161: Writer stream = getStreamByName(streamName);
162: if (stream != null) {
163: Writer fullMessage = new StringWriter();
164: String date = null;
165: synchronized (sdfLog) {
166: date = sdfLog.format(new Date());
167: }
168: try {
169: fullMessage.write("[");
170: fullMessage.write(streamName);
171: fullMessage.write(" ");
172: fullMessage.write(date);
173: fullMessage.write("] - ");
174: if (showThrowingThread) {
175: fullMessage.write("[");
176: fullMessage.write(Thread.currentThread().getName());
177: fullMessage.write("] - ");
178: }
179: fullMessage.write(message);
180: if (error != null) {
181: fullMessage.write(LINE_SEPARATOR);
182: PrintWriter pw = new PrintWriter(fullMessage);
183: error.printStackTrace(pw);
184: pw.flush();
185: }
186: fullMessage.write(LINE_SEPARATOR);
187:
188: stream.write(fullMessage.toString());
189: stream.flush();
190: } catch (IOException err) {
191: System.err.println(Launcher.RESOURCES.getString(
192: "Logger.StreamWriteError", message));
193: err.printStackTrace(System.err);
194: }
195: }
196: }
197:
198: public static void log(int level, WinstoneResourceBundle resources,
199: String messageKey) {
200: if (currentDebugLevel < level) {
201: return;
202: } else {
203: logInternal(DEFAULT_STREAM,
204: resources.getString(messageKey), null);
205: }
206: }
207:
208: public static void log(int level, WinstoneResourceBundle resources,
209: String messageKey, Throwable error) {
210: if (currentDebugLevel < level) {
211: return;
212: } else {
213: logInternal(DEFAULT_STREAM,
214: resources.getString(messageKey), error);
215: }
216: }
217:
218: public static void log(int level, WinstoneResourceBundle resources,
219: String messageKey, String param) {
220: if (currentDebugLevel < level) {
221: return;
222: } else {
223: logInternal(DEFAULT_STREAM, resources.getString(messageKey,
224: param), null);
225: }
226: }
227:
228: public static void log(int level, WinstoneResourceBundle resources,
229: String messageKey, String params[]) {
230: if (currentDebugLevel < level) {
231: return;
232: } else {
233: logInternal(DEFAULT_STREAM, resources.getString(messageKey,
234: params), null);
235: }
236: }
237:
238: public static void log(int level, WinstoneResourceBundle resources,
239: String messageKey, String param, Throwable error) {
240: if (currentDebugLevel < level) {
241: return;
242: } else {
243: logInternal(DEFAULT_STREAM, resources.getString(messageKey,
244: param), error);
245: }
246: }
247:
248: public static void log(int level, WinstoneResourceBundle resources,
249: String messageKey, String params[], Throwable error) {
250: if (currentDebugLevel < level) {
251: return;
252: } else {
253: logInternal(DEFAULT_STREAM, resources.getString(messageKey,
254: params), error);
255: }
256: }
257:
258: public static void log(int level, WinstoneResourceBundle resources,
259: String streamName, String messageKey, String params[],
260: Throwable error) {
261: if (currentDebugLevel < level) {
262: return;
263: } else {
264: logInternal(streamName, resources.getString(messageKey,
265: params), error);
266: }
267: }
268:
269: public static void logDirectMessage(int level, String streamName,
270: String message, Throwable error) {
271: if (currentDebugLevel < level) {
272: return;
273: } else {
274: logInternal(streamName, message, error);
275: }
276: }
277: }
|