001: /*
002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/logger/FileLogger.java,v 1.8 2002/06/09 02:19:43 remm Exp $
003: * $Revision: 1.8 $
004: * $Date: 2002/06/09 02:19:43 $
005: *
006: * ====================================================================
007: *
008: * The Apache Software License, Version 1.1
009: *
010: * Copyright (c) 1999 The Apache Software Foundation. All rights
011: * reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions
015: * are met:
016: *
017: * 1. Redistributions of source code must retain the above copyright
018: * notice, this list of conditions and the following disclaimer.
019: *
020: * 2. Redistributions in binary form must reproduce the above copyright
021: * notice, this list of conditions and the following disclaimer in
022: * the documentation and/or other materials provided with the
023: * distribution.
024: *
025: * 3. The end-user documentation included with the redistribution, if
026: * any, must include the following acknowlegement:
027: * "This product includes software developed by the
028: * Apache Software Foundation (http://www.apache.org/)."
029: * Alternately, this acknowlegement may appear in the software itself,
030: * if and wherever such third-party acknowlegements normally appear.
031: *
032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
033: * Foundation" must not be used to endorse or promote products derived
034: * from this software without prior written permission. For written
035: * permission, please contact apache@apache.org.
036: *
037: * 5. Products derived from this software may not be called "Apache"
038: * nor may "Apache" appear in their names without prior written
039: * permission of the Apache Group.
040: *
041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
052: * SUCH DAMAGE.
053: * ====================================================================
054: *
055: * This software consists of voluntary contributions made by many
056: * individuals on behalf of the Apache Software Foundation. For more
057: * information on the Apache Software Foundation, please see
058: * <http://www.apache.org/>.
059: *
060: * [Additional notices, if required by prior licensing conditions]
061: *
062: */
063:
064: package org.apache.catalina.logger;
065:
066: import java.io.File;
067: import java.io.FileWriter;
068: import java.io.IOException;
069: import java.io.PrintWriter;
070: import java.sql.Timestamp;
071: import org.apache.catalina.Lifecycle;
072: import org.apache.catalina.LifecycleEvent;
073: import org.apache.catalina.LifecycleException;
074: import org.apache.catalina.LifecycleListener;
075: import org.apache.catalina.util.LifecycleSupport;
076: import org.apache.catalina.util.StringManager;
077:
078: /**
079: * Implementation of <b>Logger</b> that appends log messages to a file
080: * named {prefix}.{date}.{suffix} in a configured directory, with an
081: * optional preceding timestamp.
082: *
083: * @author Craig R. McClanahan
084: * @version $Revision: 1.8 $ $Date: 2002/06/09 02:19:43 $
085: */
086:
087: public class FileLogger extends LoggerBase implements Lifecycle {
088:
089: // ----------------------------------------------------- Instance Variables
090:
091: /**
092: * The as-of date for the currently open log file, or a zero-length
093: * string if there is no open log file.
094: */
095: private String date = "";
096:
097: /**
098: * The directory in which log files are created.
099: */
100: private String directory = "logs";
101:
102: /**
103: * The descriptive information about this implementation.
104: */
105: protected static final String info = "org.apache.catalina.logger.FileLogger/1.0";
106:
107: /**
108: * The lifecycle event support for this component.
109: */
110: protected LifecycleSupport lifecycle = new LifecycleSupport(this );
111:
112: /**
113: * The prefix that is added to log file filenames.
114: */
115: private String prefix = "catalina.";
116:
117: /**
118: * The string manager for this package.
119: */
120: private StringManager sm = StringManager
121: .getManager(Constants.Package);
122:
123: /**
124: * Has this component been started?
125: */
126: private boolean started = false;
127:
128: /**
129: * The suffix that is added to log file filenames.
130: */
131: private String suffix = ".log";
132:
133: /**
134: * Should logged messages be date/time stamped?
135: */
136: private boolean timestamp = false;
137:
138: /**
139: * The PrintWriter to which we are currently logging, if any.
140: */
141: private PrintWriter writer = null;
142:
143: // ------------------------------------------------------------- Properties
144:
145: /**
146: * Return the directory in which we create log files.
147: */
148: public String getDirectory() {
149:
150: return (directory);
151:
152: }
153:
154: /**
155: * Set the directory in which we create log files.
156: *
157: * @param directory The new log file directory
158: */
159: public void setDirectory(String directory) {
160:
161: String oldDirectory = this .directory;
162: this .directory = directory;
163: support.firePropertyChange("directory", oldDirectory,
164: this .directory);
165:
166: }
167:
168: /**
169: * Return the log file prefix.
170: */
171: public String getPrefix() {
172:
173: return (prefix);
174:
175: }
176:
177: /**
178: * Set the log file prefix.
179: *
180: * @param prefix The new log file prefix
181: */
182: public void setPrefix(String prefix) {
183:
184: String oldPrefix = this .prefix;
185: this .prefix = prefix;
186: support.firePropertyChange("prefix", oldPrefix, this .prefix);
187:
188: }
189:
190: /**
191: * Return the log file suffix.
192: */
193: public String getSuffix() {
194:
195: return (suffix);
196:
197: }
198:
199: /**
200: * Set the log file suffix.
201: *
202: * @param suffix The new log file suffix
203: */
204: public void setSuffix(String suffix) {
205:
206: String oldSuffix = this .suffix;
207: this .suffix = suffix;
208: support.firePropertyChange("suffix", oldSuffix, this .suffix);
209:
210: }
211:
212: /**
213: * Return the timestamp flag.
214: */
215: public boolean getTimestamp() {
216:
217: return (timestamp);
218:
219: }
220:
221: /**
222: * Set the timestamp flag.
223: *
224: * @param timestamp The new timestamp flag
225: */
226: public void setTimestamp(boolean timestamp) {
227:
228: boolean oldTimestamp = this .timestamp;
229: this .timestamp = timestamp;
230: support.firePropertyChange("timestamp", new Boolean(
231: oldTimestamp), new Boolean(this .timestamp));
232:
233: }
234:
235: // --------------------------------------------------------- Public Methods
236:
237: /**
238: * Writes the specified message to a servlet log file, usually an event
239: * log. The name and type of the servlet log is specific to the
240: * servlet container.
241: *
242: * @param msg A <code>String</code> specifying the message to be written
243: * to the log file
244: */
245: public void log(String msg) {
246:
247: // Construct the timestamp we will use, if requested
248: Timestamp ts = new Timestamp(System.currentTimeMillis());
249: String tsString = ts.toString().substring(0, 19);
250: String tsDate = tsString.substring(0, 10);
251:
252: // If the date has changed, switch log files
253: if (!date.equals(tsDate)) {
254: synchronized (this ) {
255: if (!date.equals(tsDate)) {
256: close();
257: date = tsDate;
258: open();
259: }
260: }
261: }
262:
263: // Log this message, timestamped if necessary
264: if (writer != null) {
265: if (timestamp) {
266: writer.println(tsString + " " + msg);
267: } else {
268: writer.println(msg);
269: }
270: }
271:
272: }
273:
274: // -------------------------------------------------------- Private Methods
275:
276: /**
277: * Close the currently open log file (if any)
278: */
279: private void close() {
280:
281: if (writer == null)
282: return;
283: writer.flush();
284: writer.close();
285: writer = null;
286: date = "";
287:
288: }
289:
290: /**
291: * Open the new log file for the date specified by <code>date</code>.
292: */
293: private void open() {
294:
295: // Create the directory if necessary
296: File dir = new File(directory);
297: if (!dir.isAbsolute())
298: dir = new File(System.getProperty("catalina.base"),
299: directory);
300: dir.mkdirs();
301:
302: // Open the current log file
303: try {
304: String pathname = dir.getAbsolutePath() + File.separator
305: + prefix + date + suffix;
306: writer = new PrintWriter(new FileWriter(pathname, true),
307: true);
308: } catch (IOException e) {
309: writer = null;
310: }
311:
312: }
313:
314: // ------------------------------------------------------ Lifecycle Methods
315:
316: /**
317: * Add a lifecycle event listener to this component.
318: *
319: * @param listener The listener to add
320: */
321: public void addLifecycleListener(LifecycleListener listener) {
322:
323: lifecycle.addLifecycleListener(listener);
324:
325: }
326:
327: /**
328: * Get the lifecycle listeners associated with this lifecycle. If this
329: * Lifecycle has no listeners registered, a zero-length array is returned.
330: */
331: public LifecycleListener[] findLifecycleListeners() {
332:
333: return lifecycle.findLifecycleListeners();
334:
335: }
336:
337: /**
338: * Remove a lifecycle event listener from this component.
339: *
340: * @param listener The listener to add
341: */
342: public void removeLifecycleListener(LifecycleListener listener) {
343:
344: lifecycle.removeLifecycleListener(listener);
345:
346: }
347:
348: /**
349: * Prepare for the beginning of active use of the public methods of this
350: * component. This method should be called after <code>configure()</code>,
351: * and before any of the public methods of the component are utilized.
352: *
353: * @exception LifecycleException if this component detects a fatal error
354: * that prevents this component from being used
355: */
356: public void start() throws LifecycleException {
357:
358: // Validate and update our current component state
359: if (started)
360: throw new LifecycleException(sm
361: .getString("fileLogger.alreadyStarted"));
362: lifecycle.fireLifecycleEvent(START_EVENT, null);
363: started = true;
364:
365: }
366:
367: /**
368: * Gracefully terminate the active use of the public methods of this
369: * component. This method should be the last one called on a given
370: * instance of this component.
371: *
372: * @exception LifecycleException if this component detects a fatal error
373: * that needs to be reported
374: */
375: public void stop() throws LifecycleException {
376:
377: // Validate and update our current component state
378: if (!started)
379: throw new LifecycleException(sm
380: .getString("fileLogger.notStarted"));
381: lifecycle.fireLifecycleEvent(STOP_EVENT, null);
382: started = false;
383:
384: close();
385:
386: }
387:
388: }
|