Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/log4j/DailyFileAppender1.java


1   /*
2    * Copyright (C) The Apache Software Foundation. All rights reserved.
3    *
4    * This software is published under the terms of the Apache Software
5    * License version 1.1, a copy of which has been included with this
6    * distribution in the LICENSE.APL file.  */
7   
8   
9   
10  package org.apache.log4j;
11  
12  import java.io.IOException;
13  import java.io.Writer;
14  import java.io.FileWriter;
15  import java.io.File;
16  import java.io.OutputStream;
17  import java.io.OutputStreamWriter;
18  import java.text.SimpleDateFormat;
19  import java.util.Date;
20  import org.apache.log4j.helpers.OptionConverter;
21  import org.apache.log4j.helpers.QuietWriter;
22  import org.apache.log4j.helpers.CountingQuietWriter;
23  import org.apache.log4j.spi.LoggingEvent;
24  import org.apache.log4j.spi.ErrorCode;
25  
26  /**
27     DailyFileAppender extends FileAppender to use filenames formatted with
28     date/time information. The filename is recomputed every day at midnight.
29     Note that the filename doesn't have to change every day, making it possible
30     to have logfiles which are per-week or per-month.
31  
32     The appender computes the proper filename using the formats specified in
33     <a href="http://java.sun.com/j2se/1.3/docs/api/java/text/SimpleDateFormat.html">
34     java.text.SimpleDateFormat</a>. The format requires that most static text is
35     enclosed in single quotes, which are removed. The examples below show how
36     quotes are used to embed static information in the format.
37  
38     Sample filenames:
39  
40  <code>
41       Filename pattern                     Filename
42       "'/logs/trace-'yyyy-MM-dd'.log'"     /logs/trace-2000-12-31.log
43       "'/logs/trace-'yyyy-ww'.log'"        /logs/trace-2000-52.log
44  </code>
45  
46     @author <a HREF="mailto:eirik.lygre@evita.no">Eirik Lygre</a>
47  */
48  public class DailyFileAppender extends FileAppender {
49  
50    /**
51       A string constant used in naming the option for setting the
52       filename pattern. Current value of this string constant is
53       <strong>FileNamePattern</strong>.
54     */
55    static final public String FILE_NAME_PATTERN_OPTION = "FilePattern";
56    
57    /**
58       The filename pattern
59    */
60    private String fileNamePattern = null;
61  
62    /**
63       The actual formatted filename that is currently being written to
64    */
65    private String currentFileName = null;
66  
67    /**
68       The timestamp when we shall next recompute the filename
69    */
70    private long nextFilenameComputingMillis = System.currentTimeMillis () - 1;
71  
72    /**
73       The default constructor does no longer set a default layout nor a
74       default output target.  */
75    public
76    DailyFileAppender() {
77    }
78  
79    /**
80      Instantiate a RollingFileAppender and open the file designated by
81      <code>filename</code>. The opened filename will become the ouput
82      destination for this appender.
83  
84      <p>If the <code>append</code> parameter is true, the file will be
85      appended to. Otherwise, the file desginated by
86      <code>filename</code> will be truncated before being opened.
87    */
88    public DailyFileAppender (Layout layout,String filename,boolean append) throws IOException {
89      super(layout, filename, append);
90    }
91  
92    /**
93       Instantiate a FileAppender and open the file designated by
94      <code>filename</code>. The opened filename will become the output
95      destination for this appender.
96  
97      <p>The file will be appended to.  */
98    public DailyFileAppender (Layout layout,String filename) throws IOException {
99      super(layout, filename);
100   }
101   
102   /**
103      Set the current output file.
104 
105      The function will compute a new filename, and open a new file only
106      when the name has changed.
107 
108      The function is automatically called once a day, to allow for
109      daily files -- the purpose of this class.
110   */
111 
112   public
113   synchronized
114   void setFile(String fileName, boolean append) throws IOException {
115 
116     /* Compute filename, but only if fileNamePattern is specified */
117     if (fileNamePattern == null) {
118       errorHandler.error("Missing file pattern (" + FILE_NAME_PATTERN_OPTION + ") in setFile().");
119       return;
120     }
121 
122     Date now = new Date();
123 
124     fileName = new SimpleDateFormat(fileNamePattern).format (now);
125     if (fileName.equals(currentFileName))
126       return;
127 
128     /* Set up next filename checkpoint */
129     DailyFileAppenderCalendar c = new DailyFileAppenderCalendar();
130     c.rollToNextDay ();
131     nextFilenameComputingMillis = c.getTimeInMillis ();
132 
133     currentFileName = fileName;
134 
135     super.setFile(fileName, append);
136   }
137 
138   /**
139      This method differentiates RollingFileAppender from its super
140      class.  
141 
142   */
143   protected
144   void subAppend(LoggingEvent event) {
145      
146      if (System.currentTimeMillis () >= nextFilenameComputingMillis) {
147       try {
148         setFile (super.fileName, super.fileAppend);
149       }
150       catch(IOException e) {
151         System.err.println("setFile(null, false) call failed.");
152         e.printStackTrace();
153       }
154     }
155 
156     super.subAppend(event);
157   } 
158 
159   /**
160      Retuns the option names for this component, namely {@link
161      #FILE_NAME_PATTERN_OPTION} in
162      addition to the options of {@link FileAppender#getOptionStrings
163      FileAppender}.
164   */
165   public
166   String[] getOptionStrings() {
167 
168     return OptionConverter.concatanateArrays(super.getOptionStrings(),
169      new String[] {FILE_NAME_PATTERN_OPTION});
170   }
171 
172   /**
173      Set the options for the appender
174   */
175   public
176   void setOption(String key, String value) {
177     super.setOption(key, value);    
178     if(key.equalsIgnoreCase(FILE_NAME_PATTERN_OPTION)) {
179       fileNamePattern = value;
180     }
181   }
182   
183   /**
184      If the a value for {@link #FILE_OPTION} is non-null, then {@link
185      #setFile} is called with the values of {@link #FILE_OPTION} and
186      {@link #APPEND_OPTION}.
187 
188      @since 0.8.1 */
189   public
190   void activateOptions() {
191     try {
192      setFile(null, super.fileAppend);
193     }
194     catch(java.io.IOException e) {
195      errorHandler.error("setFile(null,"+fileAppend+") call failed.",
196            e, ErrorCode.FILE_OPEN_FAILURE);
197     }
198   }
199 }
200 
201 /**
202    DailyFileAppenderCalendar is a helper class to DailyFileAppender. Using
203    this class, it is easy to compute and access the next Millis()
204  
205    It subclasses the standard
206    <a href="http://java.sun.com/j2se/1.3/docs/api/java/text/GregorianCalendar.html">
207    java.util.GregorianCalendar</a>-object, to allow access to the protected
208    function getTimeInMillis(), which it then exports.
209 
210    @author <a HREF="mailto:eirik.lygre@evita.no">Eirik Lygre</a>
211 */
212 class DailyFileAppenderCalendar extends java.util.GregorianCalendar
213 {
214   /**
215      Returns the current time in Millis
216   */
217   public long getTimeInMillis() {
218     return super.getTimeInMillis();
219   }
220 
221   /**
222      Roll the date to the next hour, with minute, second and millisecond
223      set to zero.
224   */
225   public void rollToNextDay () {
226     this.add(java.util.Calendar.DATE, 0);
227     this.add(java.util.Calendar.HOUR, 0);
228     this.set(java.util.Calendar.MINUTE, 0);
229     this.set(java.util.Calendar.SECOND, 0);
230     this.set(java.util.Calendar.MILLISECOND, 0);
231   }
232 }