001: /*
002: * Enhydra Java Application Server Project
003: *
004: * The contents of this file are subject to the Enhydra Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License on
007: * the Enhydra web site ( http://www.enhydra.org/ ).
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
011: * the License for the specific terms governing rights and limitations
012: * under the License.
013: *
014: * The Initial Developer of the Enhydra Application Server is Lutris
015: * Technologies, Inc. The Enhydra Application Server and portions created
016: * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
017: * All Rights Reserved.
018: *
019: * Contributor(s):
020: *
021: * $Id: StandardLogChannel.java,v 1.3 2006-09-08 08:33:07 sinisa Exp $
022: */
023:
024: package com.lutris.logging;
025:
026: import java.io.PrintWriter;
027: import java.io.StringWriter;
028: import java.text.DateFormat;
029: import java.text.FieldPosition;
030: import java.text.SimpleDateFormat;
031: import java.util.Date;
032:
033: /**
034: * Standard implementation of a channel associated with a logging
035: * facility. All messages for the facility are written using a channel.
036: * Care is take to avoid synchronization when possible for performance
037: * reasons.
038: *
039: * @author Mark Diekhans
040: * @see com.lutris.logging.LogChannel
041: * @see com.lutris.logging.StandardLogger
042: */
043: public class StandardLogChannel implements LogChannel {
044: /**
045: * Our symbolic name.
046: */
047: private String facility;
048:
049: /**
050: * Whether to log Name of current Thread or not
051: */
052: private boolean logThreadName = true;
053:
054: /**
055: * Format for the date.
056: */
057: private static final SimpleDateFormat dateFormatter = new SimpleDateFormat(
058: "yyyy.MM.dd HH:mm:ss");
059:
060: /**
061: * Logger object with which we are associated.
062: */
063: private StandardLogger logger;
064:
065: /**
066: * Construct a new log channel.
067: *
068: * @param chanFacility The facility that the channel is associate with.
069: * @param loggerObj The logging object that this channel will be associated
070: * with.
071: */
072: protected StandardLogChannel(String chanFacility,
073: StandardLogger loggerObj) {
074: facility = chanFacility;
075: logger = loggerObj;
076:
077: }
078:
079: /**
080: * @see LogChannel.getLevel
081: */
082: public int getLevel(String level) {
083: return logger.getLevel(level);
084: }
085:
086: /**
087: * @see LogChannel.getLogWriter#String
088: */
089: public LogWriter getLogWriter(String level) {
090: return new LogWriter(this , level);
091: }
092:
093: /**
094: * @see LogChannel.getLogWriter#int
095: */
096: public LogWriter getLogWriter(int level) {
097: return new LogWriter(this , level);
098: }
099:
100: /**
101: * @see LogChannel.isEnabled
102: */
103: public boolean isEnabled(int level) {
104: // Copy to avoid needing to be synchronized.
105: boolean[] enabledLevelFlags = logger.enabledLevelFlags;
106: return (enabledLevelFlags != null)
107: && (level >= 0 && level < enabledLevelFlags.length)
108: && enabledLevelFlags[level];
109: }
110:
111: /**
112: * @see LogChannel.isEnabled
113: */
114: public boolean isEnabled(String level) {
115: return isEnabled(logger.getLevel(level));
116: }
117:
118: /**
119: * Do the work of writing a log message. It should already be
120: * determined if the channel is enabled; but limited synchronization
121: * is required, as we ignore any error while writing. Handles
122: * multi-line messages.
123: *
124: *
125: * @param out Print output stream to write to.
126: * @param date The date to format into the message
127: * @param level Level string for message.
128: */
129: private void doWrite(PrintWriter out, Date date, int level,
130: String msg) {
131: try {
132: if (logThreadName) {
133: msg = "[" + Thread.currentThread().getName() + "] "
134: + msg;
135: }
136:
137: // Create prefix for each line.
138: StringBuffer msgBuf = new StringBuffer();
139: dateFormatter.format(date, msgBuf, new FieldPosition(
140: DateFormat.YEAR_FIELD));
141: msgBuf.append(": ");
142: msgBuf.append(facility);
143: msgBuf.append(',');
144:
145: msgBuf.append(logger.levelNames[level]);
146:
147: // Write as individual lines with the same prefix.
148: int nextIdx = 0;
149: int newlineIdx;
150:
151: synchronized (out) {
152: while (nextIdx < msg.length()) {
153: out.print(msgBuf);
154: if (nextIdx == 0) {
155: out.print(": ");
156: } else {
157: out.print("+ ");
158: }
159: newlineIdx = msg.indexOf('\n', nextIdx);
160: if (newlineIdx < 0) {
161: newlineIdx = msg.length();
162: }
163: out.write(msg, nextIdx, (newlineIdx - nextIdx));
164: out.println();
165: nextIdx = newlineIdx + 1;
166: }
167: out.flush();
168: }
169: } catch (Throwable ignore) {
170: // FIXME: Delete eventually or maybe make a fatal exception??
171: System.err
172: .println("StandardLogChannel.doWrite ignored exception:");
173: ignore.printStackTrace();
174: // All errors, including runtime ones, are ignored.
175: }
176: }
177:
178: /**
179: * @see LogChannel.write
180: */
181: public void write(int level, String msg) {
182: if (isEnabled(level)) {
183: Date date = new Date();
184: if (logger.logFileLevelFlags[level]) {
185: doWrite(logger.logFileStream, date, level, msg);
186: }
187: if (logger.stderrLevelFlags[level]) {
188: doWrite(logger.stderrStream, date, level, msg);
189: }
190: }
191: }
192:
193: /**
194: * @see LogChannel.write
195: */
196: public synchronized void write(String level, String msg) {
197: write(getLevel(level), msg);
198: }
199:
200: /**
201: * @see LogChannel.write
202: */
203: public synchronized void write(int level, String msg,
204: Throwable throwable) {
205: if (isEnabled(level)) {
206: Date date = new Date();
207: StringWriter stackBuf = new StringWriter();
208: throwable.printStackTrace(new PrintWriter(stackBuf));
209: stackBuf.flush();
210:
211: String errMsg = msg + ":" + " " + throwable.getMessage()
212: + '\n' + stackBuf;
213:
214: if (logger.logFileLevelFlags[level]) {
215: doWrite(logger.logFileStream, date, level, errMsg);
216: }
217: if (logger.stderrLevelFlags[level]) {
218: doWrite(logger.stderrStream, date, level, errMsg);
219: }
220: }
221: }
222:
223: /**
224: * @see LogChannel.write
225: */
226: public synchronized void write(String level, String msg,
227: Throwable throwable) {
228: write(getLevel(level), msg, throwable);
229: }
230: }
|