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  
18  import ch.qos.logback.core.CoreConstants;
19  import ch.qos.logback.core.rolling.helper.Compressor;
20  import ch.qos.logback.core.rolling.helper.FileNamePattern;
21  import ch.qos.logback.core.rolling.helper.IntegerTokenConverter;
22  import ch.qos.logback.core.rolling.helper.RenameUtil;
23  
24  /**
25   * When rolling over, <code>FixedWindowRollingPolicy</code> renames files
26   * according to a fixed window algorithm.
27   * 
28   * For more information about this policy, please refer to the online manual at
29   * http://logback.qos.ch/manual/appenders.html#FixedWindowRollingPolicy
30   * 
31   * @author Ceki G&uuml;lc&uuml;
32   */
33  public class FixedWindowRollingPolicy extends RollingPolicyBase {
34    static final String FNP_NOT_SET = "The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. ";
35    static final String PRUDENT_MODE_UNSUPPORTED = "See also http://logback.qos.ch/codes.html#tbr_fnp_prudent_unsupported";
36    static final String SEE_PARENT_FN_NOT_SET = "Please refer to http://logback.qos.ch/codes.html#fwrp_parentFileName_not_set";
37    int maxIndex;
38    int minIndex;
39    RenameUtil util = new RenameUtil();
40    Compressor compressor;
41    
42    /**
43     * It's almost always a bad idea to have a large window size, say over 12.
44     */
45    private static int MAX_WINDOW_SIZE = 12;
46  
47    public FixedWindowRollingPolicy() {
48      minIndex = 1;
49      maxIndex = 7;
50    }
51  
52    public void start() {
53      util.setContext(this.context);
54     
55      if (fileNamePatternStr != null) {
56        fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context);
57        determineCompressionMode();
58      } else {
59        addError(FNP_NOT_SET);
60        addError(CoreConstants.SEE_FNP_NOT_SET);
61        throw new IllegalStateException(FNP_NOT_SET + CoreConstants.SEE_FNP_NOT_SET);
62      }
63  
64      if(isParentPrudent()) {
65        addError("Prudent mode is not supported with FixedWindowRollingPolicy.");
66        addError(PRUDENT_MODE_UNSUPPORTED);
67        throw new IllegalStateException("Prudent mode is not supported.");
68      }
69      
70      if (getParentsRawFileProperty() == null) {
71        addError("The File name property must be set before using this rolling policy.");
72        addError(SEE_PARENT_FN_NOT_SET);
73        throw new IllegalStateException("The \"File\" option must be set.");
74      }
75  
76      if (maxIndex < minIndex) {
77        addWarn("MaxIndex (" + maxIndex + ") cannot be smaller than MinIndex ("
78            + minIndex + ").");
79        addWarn("Setting maxIndex to equal minIndex.");
80        maxIndex = minIndex;
81      }
82  
83      if ((maxIndex - minIndex) > MAX_WINDOW_SIZE) {
84        addWarn("Large window sizes are not allowed.");
85        maxIndex = minIndex + MAX_WINDOW_SIZE;
86        addWarn("MaxIndex reduced to " + maxIndex);
87      }
88  
89      IntegerTokenConverter itc = fileNamePattern.getIntegerTokenConverter();
90  
91      if (itc == null) {
92        throw new IllegalStateException("FileNamePattern ["
93            + fileNamePattern.getPattern()
94            + "] does not contain a valid IntegerToken");
95      }
96  
97      compressor = new Compressor(compressionMode);
98      compressor.setContext(this.context);
99    }
100 
101   public void rollover() throws RolloverFailure {
102     // Inside this method it is guaranteed that the hereto active log file is
103     // closed.
104     // If maxIndex <= 0, then there is no file renaming to be done.
105     if (maxIndex >= 0) {
106       // Delete the oldest file, to keep Windows happy.
107       File file = new File(fileNamePattern.convertInt(maxIndex));
108 
109       if (file.exists()) {
110         file.delete();
111       }
112 
113       // Map {(maxIndex - 1), ..., minIndex} to {maxIndex, ..., minIndex+1}
114       for (int i = maxIndex - 1; i >= minIndex; i--) {
115         String toRenameStr = fileNamePattern.convertInt(i);
116         File toRename = new File(toRenameStr);
117         // no point in trying to rename an inexistent file
118         if (toRename.exists()) {
119           util.rename(toRenameStr, fileNamePattern.convertInt(i + 1));
120         } else {
121           addInfo("Skipping roll-over for inexistent file " + toRenameStr);
122         }
123       }
124 
125       // move active file name to min
126       switch (compressionMode) {
127       case NONE:
128         util.rename(getActiveFileName(), fileNamePattern
129             .convertInt(minIndex));
130         break;
131       case GZ:
132       case ZIP:
133         compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex));
134         break;
135       }
136     }
137   }
138 
139   /**
140    * Return the value of the <b>ActiveFile</b> option.
141    * 
142    * @see {@link setActiveFileName}.
143    */
144   public String getActiveFileName() {
145     return getParentsRawFileProperty();
146   }
147 
148   public int getMaxIndex() {
149     return maxIndex;
150   }
151 
152   public int getMinIndex() {
153     return minIndex;
154   }
155 
156   public void setMaxIndex(int maxIndex) {
157     this.maxIndex = maxIndex;
158   }
159 
160   public void setMinIndex(int minIndex) {
161     this.minIndex = minIndex;
162   }
163 }