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.util.Date;
18  
19  import ch.qos.logback.core.CoreConstants;
20  import ch.qos.logback.core.rolling.helper.*;
21  
22  /**
23   * When rolling over, <code>FixedWindowRollingPolicy</code> renames files
24   * according to a fixed window algorithm.
25   * 
26   * For more information about this policy, please refer to the online manual at
27   * http://logback.qos.ch/manual/appenders.html#FixedWindowRollingPolicy
28   * 
29   * @author Ceki G&uuml;lc&uuml;
30   */
31  public class FixedWindowRollingPolicy extends RollingPolicyBase {
32    static final String FNP_NOT_SET = "The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. ";
33    static final String PRUDENT_MODE_UNSUPPORTED = "See also http://logback.qos.ch/codes.html#tbr_fnp_prudent_unsupported";
34    static final String SEE_PARENT_FN_NOT_SET = "Please refer to http://logback.qos.ch/codes.html#fwrp_parentFileName_not_set";
35    int maxIndex;
36    int minIndex;
37    RenameUtil util = new RenameUtil();
38    Compressor compressor;
39  
40    public static String ZIP_ENTRY_DATE_PATTERN = "yyyy-MM-dd_HHmm";
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      if(compressionMode == CompressionMode.ZIP) {
98        String zipEntryFileNamePatternStr = transformFileNamePatternFromInt2Date(fileNamePatternStr);
99        zipEntryFileNamePattern = new FileNamePattern(zipEntryFileNamePatternStr, context);
100     }
101     compressor = new Compressor(compressionMode);
102     compressor.setContext(this.context);
103     super.start();
104   }
105 
106   private String transformFileNamePatternFromInt2Date(String fileNamePatternStr) {
107     String slashified = FileFilterUtil.slashify(fileNamePatternStr);
108     String stemOfFileNamePattern = FileFilterUtil.afterLastSlash(slashified);
109     return stemOfFileNamePattern.replace("%i", "%d{"+ZIP_ENTRY_DATE_PATTERN+"}");
110   }
111 
112   public void rollover() throws RolloverFailure {
113 
114     // Inside this method it is guaranteed that the hereto active log file is
115     // closed.
116     // If maxIndex <= 0, then there is no file renaming to be done.
117     if (maxIndex >= 0) {
118       // Delete the oldest file, to keep Windows happy.
119       File file = new File(fileNamePattern.convertInt(maxIndex));
120 
121       if (file.exists()) {
122         file.delete();
123       }
124 
125       // Map {(maxIndex - 1), ..., minIndex} to {maxIndex, ..., minIndex+1}
126       for (int i = maxIndex - 1; i >= minIndex; i--) {
127         String toRenameStr = fileNamePattern.convertInt(i);
128         File toRename = new File(toRenameStr);
129         // no point in trying to rename an inexistent file
130         if (toRename.exists()) {
131           util.rename(toRenameStr, fileNamePattern.convertInt(i + 1));
132         } else {
133           addInfo("Skipping roll-over for inexistent file " + toRenameStr);
134         }
135       }
136 
137       // move active file name to min
138       switch (compressionMode) {
139       case NONE:
140         util.rename(getActiveFileName(), fileNamePattern
141             .convertInt(minIndex));
142         break;
143       case GZ:
144         compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex), null);
145         break;
146       case ZIP:
147         compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex), zipEntryFileNamePattern.convert(new Date()));
148         break;
149       }
150     }
151   }
152 
153   /**
154    * Return the value of the parent's RawFile property.
155    */
156   public String getActiveFileName() {
157     return getParentsRawFileProperty();
158   }
159 
160   public int getMaxIndex() {
161     return maxIndex;
162   }
163 
164   public int getMinIndex() {
165     return minIndex;
166   }
167 
168   public void setMaxIndex(int maxIndex) {
169     this.maxIndex = maxIndex;
170   }
171 
172   public void setMinIndex(int minIndex) {
173     this.minIndex = minIndex;
174   }
175 }