View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.rolling;
15  
16  import java.io.File;
17  import java.io.IOException;
18  
19  import static ch.qos.logback.core.CoreConstants.CODES_URL;
20  import ch.qos.logback.core.FileAppender;
21  import ch.qos.logback.core.rolling.helper.CompressionMode;
22  /**
23   * <code>RollingFileAppender</code> extends {@link FileAppender} to backup the
24   * log files depending on {@link RollingPolicy} and {@link TriggeringPolicy}.
25   * <p>
26   * 
27   * For more information about this appender, please refer to the online manual
28   * at http://logback.qos.ch/manual/appenders.html#RollingFileAppender
29   * 
30   * @author Heinz Richter
31   * @author Ceki G&uuml;lc&uuml;
32   */
33  public class RollingFileAppender<E> extends FileAppender<E> {
34    File currentlyActiveFile;
35    TriggeringPolicy<E> triggeringPolicy;
36    RollingPolicy rollingPolicy;
37  
38    /**
39     * The default constructor simply calls its {@link FileAppender#FileAppender
40     * parents constructor}.
41     */
42    public RollingFileAppender() {
43    }
44  
45    public void start() {
46      if (triggeringPolicy == null) {
47        addWarn("No TriggeringPolicy was set for the RollingFileAppender named "
48            + getName());
49        addWarn("For more information, please visit "+CODES_URL+"#rfa_no_tp");
50        return;
51      }
52  
53      // we don't want to void existing log files
54      if (!append) {
55        addWarn("Append mode is mandatory for RollingFileAppender");
56        append = true;
57      }
58  
59      if (rollingPolicy == null) {
60        addError("No RollingPolicy was set for the RollingFileAppender named "
61            + getName());
62        addError("For more information, please visit "+CODES_URL+"rfa_no_rp");
63        return;
64      }
65  
66      if (isPrudent()) {
67        if (rawFileProperty() != null) {
68          addWarn("Setting \"File\" property to null on account of prudent mode");
69          setFile(null);
70        }
71        if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) {
72          addError("Compression is not supported in prudent mode. Aborting");
73          return;
74        }
75      }
76  
77      currentlyActiveFile = new File(getFile());
78      addInfo("Active log file name: " + getFile());
79      super.start();
80    }
81  
82    @Override
83    public void stop() {
84      if(rollingPolicy != null) rollingPolicy.stop();
85      if(triggeringPolicy != null) triggeringPolicy.stop();
86      super.stop();
87    }
88  
89    @Override
90    public void setFile(String file) {
91      // http://jira.qos.ch/browse/LBCORE-94
92      // allow setting the file name to null if mandated by prudent mode
93      if (file != null && ((triggeringPolicy != null) || (rollingPolicy != null))) {
94        addError("File property must be set before any triggeringPolicy or rollingPolicy properties");
95        addError("Visit "+CODES_URL+"#rfa_file_after for more information");
96      }
97      super.setFile(file);
98    }
99  
100   @Override
101   public String getFile() {
102     return rollingPolicy.getActiveFileName();
103   }
104 
105   /**
106    * Implemented by delegating most of the rollover work to a rolling policy.
107    */
108   public void rollover() {
109     synchronized (lock) {
110       // Note: This method needs to be synchronized because it needs exclusive
111       // access while it closes and then re-opens the target file.
112       //
113       // make sure to close the hereto active log file! Renaming under windows
114       // does not work for open files.
115       this.closeOutputStream();
116 
117       try {
118         rollingPolicy.rollover();
119       } catch (RolloverFailure rf) {
120         addWarn("RolloverFailure occurred. Deferring roll-over.");
121         // we failed to roll-over, let us not truncate and risk data loss
122         this.append = true;
123       }
124 
125       try {
126         // update the currentlyActiveFile
127         // http://jira.qos.ch/browse/LBCORE-90
128         currentlyActiveFile = new File(rollingPolicy.getActiveFileName());
129 
130         // This will also close the file. This is OK since multiple
131         // close operations are safe.
132         this.openFile(rollingPolicy.getActiveFileName());
133       } catch (IOException e) {
134         addError("setFile(" + fileName + ", false) call failed.", e);
135       }
136     }
137   }
138 
139   /**
140    * This method differentiates RollingFileAppender from its super class.
141    */
142   @Override
143   protected void subAppend(E event) {
144     // The roll-over check must precede actual writing. This is the
145     // only correct behavior for time driven triggers.
146 
147     // We need to synchronize on triggeringPolicy so that only one rollover
148     // occurs at a time
149     synchronized (triggeringPolicy) {
150       if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) {
151         rollover();
152       }
153     }
154 
155     super.subAppend(event);
156   }
157 
158   public RollingPolicy getRollingPolicy() {
159     return rollingPolicy;
160   }
161 
162   public TriggeringPolicy<E> getTriggeringPolicy() {
163     return triggeringPolicy;
164   }
165 
166   /**
167    * Sets the rolling policy. In case the 'policy' argument also implements
168    * {@link TriggeringPolicy}, then the triggering policy for this appender is
169    * automatically set to be the policy argument.
170    * 
171    * @param policy
172    */
173   @SuppressWarnings("unchecked")
174   public void setRollingPolicy(RollingPolicy policy) {
175     rollingPolicy = policy;
176     if (rollingPolicy instanceof TriggeringPolicy) {
177       triggeringPolicy = (TriggeringPolicy<E>) policy;
178     }
179 
180   }
181 
182   public void setTriggeringPolicy(TriggeringPolicy<E> policy) {
183     triggeringPolicy = policy;
184     if (policy instanceof RollingPolicy) {
185       rollingPolicy = (RollingPolicy) policy;
186     }
187   }
188 }