View Javadoc

1   /**
2    * Logback: the generic, reliable, fast and flexible logging framework.
3    * 
4    * Copyright (C) 2000-2008, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  package ch.qos.logback.core.rolling;
11  
12  import java.io.File;
13  import java.io.IOException;
14  
15  import ch.qos.logback.core.FileAppender;
16  import ch.qos.logback.core.rolling.helper.CompressionMode;
17  
18  /**
19   * <code>RollingFileAppender</code> extends {@link FileAppender} to backup the
20   * log files depending on {@link RollingPolicy} and {@link TriggeringPolicy}.
21   * <p>
22   * 
23   * For more information about this appender, please refer to the online manual
24   * at http://logback.qos.ch/manual/appenders.html#RollingFileAppender
25   * 
26   * @author Heinz Richter
27   * @author Ceki G&uuml;lc&uuml;
28   */
29  public class RollingFileAppender<E> extends FileAppender<E> {
30    File activeFileCache;
31    TriggeringPolicy<E> triggeringPolicy;
32    RollingPolicy rollingPolicy;
33  
34    /**
35     * The default constructor simply calls its {@link FileAppender#FileAppender
36     * parents constructor}.
37     */
38    public RollingFileAppender() {
39    }
40  
41    public void start() {
42      if (triggeringPolicy == null) {
43        addWarn("No TriggeringPolicy was set for the RollingFileAppender named "
44            + getName());
45        addWarn("For more information, please visit http://logback.qos.ch/codes.html#rfa_no_tp");
46        return;
47      }
48  
49      if (rollingPolicy == null) {
50        addError("No RollingPolicy was set for the RollingFileAppender named "
51            + getName());
52        addError("For more information, please visit http://logback.qos.ch/codes.html#rfa_no_rp");
53        return;
54      }
55      
56      if(isPrudent()) {
57        if(rawFileProperty() !=  null) {
58          addWarn("Setting \"File\" property to null on account of prudent mode");
59          setFile(null);    
60        }
61        if(rollingPolicy.getCompressionMode() != CompressionMode.NONE) {
62          addError("Compression is not supported in prudent mode. Aborting");
63          return;
64        }
65      }
66  
67      activeFileCache = new File(getFile());
68      addInfo("Active log file name: " + getFile());
69      super.start();
70    }
71  
72    @Override
73    public String getFile() {
74      return rollingPolicy.getActiveFileName();
75    }
76  
77    /**
78     * Implements the usual roll over behaviour.
79     * 
80     * <p>If <code>MaxBackupIndex</code> is positive, then files {<code>File.1</code>,
81     * ..., <code>File.MaxBackupIndex -1</code>} are renamed to {<code>File.2</code>,
82     * ..., <code>File.MaxBackupIndex</code>}. Moreover, <code>File</code> is
83     * renamed <code>File.1</code> and closed. A new <code>File</code> is
84     * created to receive further log output.
85     * 
86     * <p>If <code>MaxBackupIndex</code> is equal to zero, then the
87     * <code>File</code> is truncated with no backup files created.
88     * 
89     */
90    public void rollover() {
91      // Note: synchronization at this point is unnecessary as the doAppend
92      // is already synched
93  
94      //
95      // make sure to close the hereto active log file! Renaming under windows
96      // does not work for open files.
97      this.closeWriter();
98  
99      // By default, the newly created file will be created in truncate mode.
100     // (See the setFile() call a few lines below.)
101     // FIXME don't change the append mode
102     // this.append = false;
103     
104     try {
105       rollingPolicy.rollover();
106     } catch (RolloverFailure rf) {
107       addWarn("RolloverFailure occurred. Deferring roll-over.");
108       // we failed to roll-over, let us not truncate and risk data loss
109       this.append = true;
110     }
111 
112     try {
113       // This will also close the file. This is OK since multiple
114       // close operations are safe.
115       this.openFile(rollingPolicy.getActiveFileName());
116     } catch (IOException e) {
117       addError("setFile(" + fileName + ", false) call failed.", e);
118     }
119   }
120 
121   /**
122    * This method differentiates RollingFileAppender from its super class.
123    */
124   protected void subAppend(E event) {
125     // The roll-over check must precede actual writing. This is the
126     // only correct behavior for time driven triggers.
127     if (triggeringPolicy.isTriggeringEvent(activeFileCache, event)) {
128       rollover();
129     }
130 
131     super.subAppend(event);
132   }
133 
134   public RollingPolicy getRollingPolicy() {
135     return rollingPolicy;
136   }
137 
138   public TriggeringPolicy getTriggeringPolicy() {
139     return triggeringPolicy;
140   }
141 
142   /**
143    * Sets the rolling policy. In case the 'policy' argument also implements
144    * {@link TriggeringPolicy}, then the triggering policy for this appender is
145    * automatically set to be the policy argument.
146    * 
147    * @param policy
148    */
149   @SuppressWarnings("unchecked")
150   public void setRollingPolicy(RollingPolicy policy) {
151     rollingPolicy = policy;
152     if (rollingPolicy instanceof TriggeringPolicy) {
153       triggeringPolicy = (TriggeringPolicy<E>) policy;
154     }
155 
156   }
157 
158   public void setTriggeringPolicy(TriggeringPolicy<E> policy) {
159     triggeringPolicy = policy;
160     if (policy instanceof RollingPolicy) {
161       rollingPolicy = (RollingPolicy) policy;
162     }
163   }
164 }