View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2009, 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 ch.qos.logback.core.FileAppender;
20  import ch.qos.logback.core.rolling.helper.CompressionMode;
21  
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 http://logback.qos.ch/codes.html#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 http://logback.qos.ch/codes.html#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 setFile(String file) {
84      // http://jira.qos.ch/browse/LBCORE-94
85      // allow setting the file name to null if mandated by prudent mode
86      if (file != null && ((triggeringPolicy != null) || (rollingPolicy != null))) {
87        addError("File property must be set before any triggeringPolicy or rollingPolicy properties");
88        addError("Visit http://logback.qos.ch/codes.html#rfa_file_after for more information");
89      }
90      super.setFile(file);
91    }
92  
93    @Override
94    public String getFile() {
95      return rollingPolicy.getActiveFileName();
96    }
97  
98    /**
99     * Implemented by delegating most of the rollover work to a rolling policy.
100    */
101   public synchronized void rollover() {
102     // Note: This method needs to be synchronized because it needs exclusive
103     // access while it closes and then re-opens the target file.
104     //
105     // make sure to close the hereto active log file! Renaming under windows
106     // does not work for open files.
107     this.closeWriter();
108 
109     try {
110       rollingPolicy.rollover();
111     } catch (RolloverFailure rf) {
112       addWarn("RolloverFailure occurred. Deferring roll-over.");
113       // we failed to roll-over, let us not truncate and risk data loss
114       this.append = true;
115     }
116 
117     try {
118       // update the currentlyActiveFile
119       // http://jira.qos.ch/browse/LBCORE-90
120       currentlyActiveFile = new File(rollingPolicy.getActiveFileName());
121 
122       // This will also close the file. This is OK since multiple
123       // close operations are safe.
124       this.openFile(rollingPolicy.getActiveFileName());
125     } catch (IOException e) {
126       addError("setFile(" + fileName + ", false) call failed.", e);
127     }
128   }
129 
130   /**
131    * This method differentiates RollingFileAppender from its super class.
132    */
133   @Override
134   protected void subAppend(E event) {
135     // The roll-over check must precede actual writing. This is the
136     // only correct behavior for time driven triggers.
137 
138     // We need to synchronize on triggeringPolicy so that only one rollover
139     // occurs at a time
140     synchronized (triggeringPolicy) {
141       if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) {
142         rollover();
143       }
144     }
145 
146     super.subAppend(event);
147   }
148 
149   public RollingPolicy getRollingPolicy() {
150     return rollingPolicy;
151   }
152 
153   public TriggeringPolicy<E> getTriggeringPolicy() {
154     return triggeringPolicy;
155   }
156 
157   /**
158    * Sets the rolling policy. In case the 'policy' argument also implements
159    * {@link TriggeringPolicy}, then the triggering policy for this appender is
160    * automatically set to be the policy argument.
161    * 
162    * @param policy
163    */
164   @SuppressWarnings("unchecked")
165   public void setRollingPolicy(RollingPolicy policy) {
166     rollingPolicy = policy;
167     if (rollingPolicy instanceof TriggeringPolicy) {
168       triggeringPolicy = (TriggeringPolicy<E>) policy;
169     }
170 
171   }
172 
173   public void setTriggeringPolicy(TriggeringPolicy<E> policy) {
174     triggeringPolicy = policy;
175     if (policy instanceof RollingPolicy) {
176       rollingPolicy = (RollingPolicy) policy;
177     }
178   }
179 }