KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log > output > io > rotate > RevolvingFileStrategy


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  *
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.log.output.io.rotate;
18
19 import java.io.File JavaDoc;
20 import java.text.DecimalFormat JavaDoc;
21 import java.text.FieldPosition JavaDoc;
22 import java.text.NumberFormat JavaDoc;
23
24 /**
25  * strategy for naming log files based on appending revolving suffix.
26  * If the initial rotation is not specified then the class will attempt to
27  * calculate the rotation number via the following algorithm.
28  *
29  * It will search for the file with the highest number in the rotation. It will
30  * then increment its rotation number and use that number. If all files in rotation
31  * are present then it will then set the initial rotation to the next rotation after
32  * the most recently created file.
33  *
34  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
35  * @author <a HREF="mailto:bh22351@i-one.at">Bernhard Huber</a>
36  * @author Peter Donald
37  * @author <a HREF="mailto:david.gray@hic.gov.au">David Gray</a>
38  */

39 public class RevolvingFileStrategy
40     implements FileStrategy
41 {
42     ///revolving suffix formatting pattern. ie. "'.'000000"
43
private static final String JavaDoc PATTERN = "'.'000000";
44
45     ///a revolving suffix formatter
46
private DecimalFormat JavaDoc m_decimalFormat;
47
48     ///current revolving suffix
49
private int m_rotation;
50
51     ///max revolving value.
52
private int m_maxRotations;
53
54     ///the base file name.
55
private File JavaDoc m_baseFile;
56
57     /**
58      * Creation of a new instane ofthe revolving file strategy.
59      * @param baseFile the base file
60      * @param maxRotations the maximum number of rotations ??
61      */

62     public RevolvingFileStrategy( final File JavaDoc baseFile, final int maxRotations )
63     {
64         this( baseFile, -1, maxRotations );
65     }
66
67     /**
68      * Creation of a new instane ofthe revolving file strategy.
69      * @param baseFile the base file
70      * @param initialRotation the number of initial rotations ??
71      * @param maxRotations the maximum number of rotations??
72      */

73     public RevolvingFileStrategy( final File JavaDoc baseFile,
74                                   final int initialRotation,
75                                   final int maxRotations )
76     {
77         m_decimalFormat = new DecimalFormat JavaDoc( PATTERN );
78
79         m_baseFile = baseFile;
80         m_rotation = initialRotation;
81         m_maxRotations = maxRotations;
82
83         if( -1 == m_maxRotations )
84         {
85             m_maxRotations = Integer.MAX_VALUE;
86         }
87
88         if( -1 == initialRotation )
89         {
90             m_rotation = calculateInitialRotation();
91         }
92
93         if( m_rotation > m_maxRotations )
94         {
95             m_rotation = m_maxRotations;
96         }
97
98         if( m_rotation < 0 )
99         {
100             m_rotation = 0;
101         }
102     }
103
104     /**
105      * Calculate the real file name from the base filename.
106      *
107      * @return File the calculated file name
108      */

109     public File JavaDoc nextFile()
110     {
111         final StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
112         final FieldPosition JavaDoc position =
113             new FieldPosition JavaDoc( NumberFormat.INTEGER_FIELD );
114         sb.append( m_baseFile );
115
116         final StringBuffer JavaDoc result =
117             m_decimalFormat.format( m_rotation, sb, position );
118         m_rotation += 1;
119
120         if( m_rotation >= m_maxRotations )
121         {
122             m_rotation = 0;
123         }
124
125         return new File JavaDoc( result.toString() );
126     }
127
128     /**
129      * Retrieve the current rotation number.
130      *
131      * @return the current rotation number.
132      */

133     public int getCurrentRotation()
134     {
135         return m_rotation;
136     }
137
138     /**
139      * Method that searches through files that
140      * match the pattern for resolving file and determine
141      * the last generation written to.
142      *
143      * @return the initial rotation
144      */

145     private int calculateInitialRotation()
146     {
147         final File JavaDoc[] matchingFiles = getMatchingFiles();
148         if( null == matchingFiles || 0 == matchingFiles.length )
149         {
150             return 0;
151         }
152
153         final int[] rotations = calculateRotations( matchingFiles );
154
155         //First we go through and look for maximumRotation
156
int maxRotation = 0;
157         for( int i = 0; i < rotations.length; i++ )
158         {
159             final int rotation = rotations[ i ];
160             if( rotation > maxRotation )
161             {
162                 maxRotation = rotation;
163             }
164         }
165
166         //If the max rotation present on filessytem
167
//is less than max rotation possible then return that
168
//rotation
169
if( m_maxRotations != maxRotation )
170         {
171             return maxRotation + 1;
172         }
173
174         //Okay now we need to calculate the youngest file for our rotation
175
long time = matchingFiles[ 0 ].lastModified();
176
177         //index of oldest file
178
int oldest = rotations[ 0 ];
179         for( int i = 0; i < matchingFiles.length; i++ )
180         {
181             final File JavaDoc file = matchingFiles[ i ];
182             final long lastModified = file.lastModified();
183             if( lastModified < time )
184             {
185                 time = lastModified;
186                 oldest = rotations[ i ];
187             }
188         }
189
190         return oldest;
191     }
192
193     /**
194      * Generate an array of rotation numbers for all the files specified.
195      *
196      * @param matchingFiles the files to generate rotation numbers for
197      * @return the array containing rotations
198      */

199     private int[] calculateRotations( final File JavaDoc[] matchingFiles )
200     {
201         final int[] results = new int[ matchingFiles.length ];
202
203         for( int i = 0; i < matchingFiles.length; i++ )
204         {
205             final File JavaDoc file = matchingFiles[ i ];
206
207             // The files may be returned in any order
208
//therefore calc the rotation number
209
try
210             {
211                 results[ i ] = calculateRotationForFile( file );
212             }
213             catch( final NumberFormatException JavaDoc nfe )
214             {
215                 //If bad log file detected then set to -1
216
results[ i ] = -1;
217             }
218         }
219         return results;
220     }
221
222     /**
223      * Return the rotation for the specified file
224      *
225      * @param file the file to check
226      * @return the rotation of the file
227      */

228     private int calculateRotationForFile( final File JavaDoc file )
229     {
230         final String JavaDoc filename = file.toString();
231         final int length = filename.length();
232         final int minDigits =
233             m_decimalFormat.getMinimumIntegerDigits();
234         final String JavaDoc rotation = filename.substring( length - minDigits );
235
236         return Integer.parseInt( rotation );
237     }
238
239     /**
240      * Get a list of files that could have been part of the rotation.
241      *
242      * @return the list of files that match
243      */

244     private File JavaDoc[] getMatchingFiles()
245     {
246         // First get the path of the base file. Note that this path includes
247
// the path and the base of the file name itself.
248
final String JavaDoc fullFilePathName = m_baseFile.getPath();
249
250         // Try to find the last path separator (if it exists)
251
final int fileSeparatorPosition = fullFilePathName.lastIndexOf( File.separator );
252
253         // If the last path separator does not exist the baseFile is a pure file name
254
File JavaDoc basePath;
255         String JavaDoc baseFileName;
256         if( fileSeparatorPosition < 0 )
257         {
258             // assume the current directory
259
basePath = new File JavaDoc( "." );
260             baseFileName = fullFilePathName;
261         }
262         else
263         {
264             // Extract the sub-directory structure
265
String JavaDoc m_parentPath = fullFilePathName.substring( 0, fileSeparatorPosition );
266             baseFileName = fullFilePathName.substring( fileSeparatorPosition + 1 );
267             basePath = new File JavaDoc( m_parentPath );
268         }
269
270         return basePath.listFiles( new BaseFileNameFilter( baseFileName ) );
271     }
272 }
273
Popular Tags