KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > util > RolloverFileOutputStream


1 // ========================================================================
2
// $Id: RolloverFileOutputStream.java,v 1.14 2005/08/13 00:01:28 gregwilkins Exp $
3
// Copyright 1997-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
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 implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.util;
17
18 import java.io.File JavaDoc;
19 import java.io.FileOutputStream JavaDoc;
20 import java.io.FilterOutputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.OutputStream JavaDoc;
23 import java.lang.ref.WeakReference JavaDoc;
24 import java.text.SimpleDateFormat JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Calendar JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.GregorianCalendar JavaDoc;
29 import java.util.ListIterator JavaDoc;
30 import java.util.StringTokenizer JavaDoc;
31
32 import org.apache.commons.logging.Log;
33 import org.mortbay.log.LogFactory;
34
35 /* ------------------------------------------------------------ */
36 /** A File OutputStream that rolls overs.
37  * If the passed filename contains the string "yyyy_mm_dd" on daily intervals.
38  * @version $Id: RolloverFileOutputStream.java,v 1.14 2005/08/13 00:01:28 gregwilkins Exp $
39  * @author Greg Wilkins (gregw)
40  */

41 public class RolloverFileOutputStream extends FilterOutputStream JavaDoc
42 {
43     static Log log = LogFactory.getLog(RolloverFileOutputStream.class);
44     static Rollover __rollover;
45     final static String JavaDoc YYYY_MM_DD="yyyy_mm_dd";
46     final static ArrayList JavaDoc __rollovers = new ArrayList JavaDoc();
47
48     private SimpleDateFormat JavaDoc _fileBackupFormat =
49         new SimpleDateFormat JavaDoc(System.getProperty("ROLLOVERFILE_BACKUP_FORMAT","HHmmssSSS"));
50     private SimpleDateFormat JavaDoc _fileDateFormat =
51         new SimpleDateFormat JavaDoc(System.getProperty("ROLLOVERFILE_DATE_FORMAT","yyyy_MM_dd"));
52
53     private String JavaDoc _filename;
54     private File JavaDoc _file;
55     private boolean _append;
56     private int _retainDays;
57     private WeakReference JavaDoc _ref;
58     
59     /* ------------------------------------------------------------ */
60     public RolloverFileOutputStream(String JavaDoc filename)
61         throws IOException JavaDoc
62     {
63         this(filename,true,Integer.getInteger("ROLLOVERFILE_RETAIN_DAYS",31).intValue());
64     }
65     
66     /* ------------------------------------------------------------ */
67     public RolloverFileOutputStream(String JavaDoc filename, boolean append)
68         throws IOException JavaDoc
69     {
70         this(filename,append,Integer.getInteger("ROLLOVERFILE_RETAIN_DAYS",31).intValue());
71     }
72     
73     /* ------------------------------------------------------------ */
74     public RolloverFileOutputStream(String JavaDoc filename,
75                                     boolean append,
76                                     int retainDays)
77         throws IOException JavaDoc
78     {
79         super(null);
80         
81         if (filename!=null)
82         {
83             filename=filename.trim();
84             if (filename.length()==0)
85                 filename=null;
86         }
87         if (filename==null)
88             throw new IllegalArgumentException JavaDoc("Invalid filename");
89
90         _filename=filename;
91         _append=append;
92         _retainDays=retainDays;
93         _ref=new WeakReference JavaDoc(this);
94         setFile();
95         
96         synchronized(__rollovers)
97         {
98             if (__rollover==null)
99             {
100                 __rollover=new Rollover();
101                 __rollover.start();
102             }
103             __rollovers.add(_ref);
104         }
105     }
106
107     /* ------------------------------------------------------------ */
108     public String JavaDoc getFilename()
109     {
110         return _filename;
111     }
112     
113     /* ------------------------------------------------------------ */
114     public String JavaDoc getDatedFilename()
115     {
116         if (_file==null)
117             return null;
118         return _file.toString();
119     }
120     
121     /* ------------------------------------------------------------ */
122     public int getRetainDays()
123     {
124         return _retainDays;
125     }
126
127     /* ------------------------------------------------------------ */
128     private synchronized void setFile()
129         throws IOException JavaDoc
130     {
131         // Check directory
132
File JavaDoc file = new File JavaDoc(_filename);
133         _filename=file.getCanonicalPath();
134         file=new File JavaDoc(_filename);
135         File JavaDoc dir= new File JavaDoc(file.getParent());
136         if (!dir.isDirectory() || !dir.canWrite())
137             throw new IOException JavaDoc("Cannot write log directory "+dir);
138             
139         Date JavaDoc now=new Date JavaDoc();
140         
141         // Is this a rollover file?
142
String JavaDoc filename=file.getName();
143         int i=filename.toLowerCase().indexOf(YYYY_MM_DD);
144         if (i>=0)
145         {
146             file=new File JavaDoc(dir,
147                           filename.substring(0,i)+
148                           _fileDateFormat.format(now)+
149                           filename.substring(i+YYYY_MM_DD.length()));
150         }
151             
152         if (file.exists()&&!file.canWrite())
153             throw new IOException JavaDoc("Cannot write log file "+file);
154
155         // Do we need to change the output stream?
156
if (out==null || !file.equals(_file))
157         {
158             // Yep
159
_file=file;
160             if (!_append && file.exists())
161                 file.renameTo(new File JavaDoc(file.toString()+"."+_fileBackupFormat.format(now)));
162             OutputStream JavaDoc oldOut=out;
163             out=new FileOutputStream JavaDoc(file.toString(),_append);
164             if (oldOut!=null)
165                 oldOut.close();
166             if(log.isDebugEnabled())log.debug("Opened "+_file);
167         }
168     }
169
170     /* ------------------------------------------------------------ */
171     private void removeOldFiles()
172     {
173         if (_retainDays>0)
174         {
175             Calendar JavaDoc retainDate = Calendar.getInstance();
176             retainDate.add(Calendar.DATE,-_retainDays);
177             int borderYear = retainDate.get(java.util.Calendar.YEAR);
178             int borderMonth = retainDate.get(java.util.Calendar.MONTH) + 1;
179             int borderDay = retainDate.get(java.util.Calendar.DAY_OF_MONTH);
180
181             File JavaDoc file= new File JavaDoc(_filename);
182             File JavaDoc dir = new File JavaDoc(file.getParent());
183             String JavaDoc fn=file.getName();
184             int s=fn.toLowerCase().indexOf(YYYY_MM_DD);
185             if (s<0)
186                 return;
187             String JavaDoc prefix=fn.substring(0,s);
188             String JavaDoc suffix=fn.substring(s+YYYY_MM_DD.length());
189
190             String JavaDoc[] logList=dir.list();
191             for (int i=0;i<logList.length;i++)
192             {
193                 fn = logList[i];
194                 if(fn.startsWith(prefix)&&fn.indexOf(suffix,prefix.length())>=0)
195                 {
196                     try
197                     {
198                         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc (fn.substring(prefix.length(), prefix.length()+YYYY_MM_DD.length()), "_.");
199                         int nYear = Integer.parseInt(st.nextToken());
200                         int nMonth = Integer.parseInt(st.nextToken());
201                         int nDay = Integer.parseInt(st.nextToken());
202                         
203                         if (nYear<borderYear ||
204                             (nYear==borderYear && nMonth<borderMonth) ||
205                             (nYear==borderYear &&
206                              nMonth==borderMonth &&
207                              nDay<=borderDay))
208                         {
209                             log.info("Log age "+fn);
210                             new File JavaDoc(dir,fn).delete();
211                         }
212                     }
213                     catch(Exception JavaDoc e)
214                     {
215                         if (log.isDebugEnabled())
216                             e.printStackTrace();
217                     }
218                 }
219             }
220         }
221     }
222
223     /* ------------------------------------------------------------ */
224     public void write (byte[] buf)
225             throws IOException JavaDoc
226      {
227             out.write (buf);
228      }
229
230     /* ------------------------------------------------------------ */
231     public void write (byte[] buf, int off, int len)
232             throws IOException JavaDoc
233      {
234             out.write (buf, off, len);
235      }
236     
237     /* ------------------------------------------------------------ */
238     /**
239      */

240     public void close()
241         throws IOException JavaDoc
242     {
243         synchronized(__rollovers)
244         {
245             __rollovers.remove(_ref);
246             _ref=null;
247             try{super.close();}
248             finally
249             {
250                 out=null;
251                 _file=null;
252             }
253
254             // this will kill the thread when the last stream is removed.
255
if ( __rollovers.size() == 0 ) {
256                 __rollover.timeToStop();
257                 __rollover.interrupt();
258                 __rollover = null;
259             }
260         }
261     }
262     
263     
264     /* ------------------------------------------------------------ */
265     /* ------------------------------------------------------------ */
266     /* ------------------------------------------------------------ */
267     private class Rollover extends Thread JavaDoc
268     {
269         private boolean timeToStop = false;
270         
271         Rollover()
272         {
273             setName("Rollover");
274             setDaemon(true);
275         }
276         
277         synchronized void timeToStop()
278         {
279             timeToStop = true;
280         }
281
282         public void run()
283         {
284             while(!timeToStop)
285             {
286                 try
287                 {
288                     // Sleep until midnight
289
Calendar JavaDoc now = Calendar.getInstance();
290                     GregorianCalendar JavaDoc midnight =
291                         new GregorianCalendar JavaDoc(now.get(Calendar.YEAR),
292                                               now.get(Calendar.MONTH),
293                                               now.get(Calendar.DAY_OF_MONTH),
294                                               23,0);
295                     midnight.add(Calendar.HOUR,1);
296                     long sleeptime=
297                         midnight.getTime().getTime()-
298                         now.getTime().getTime();
299                     if(log.isDebugEnabled())log.debug("Rollover sleep until "+midnight.getTime());
300                     Thread.sleep(sleeptime);
301                 }
302                 catch(InterruptedException JavaDoc e)
303                 {
304                     if (!timeToStop)
305                         e.printStackTrace();
306                 }
307                     
308                 synchronized(__rollovers)
309                 {
310                     ListIterator JavaDoc iter = __rollovers.listIterator();
311                     while (iter.hasNext())
312                     {
313                         WeakReference JavaDoc ref =
314                             (WeakReference JavaDoc)iter.next();
315                         RolloverFileOutputStream rfos =
316                             (RolloverFileOutputStream)ref.get();
317
318                         if (rfos==null)
319                             iter.remove();
320                         else
321                         {
322                             try
323                             {
324                                 rfos.setFile();
325                                 rfos.removeOldFiles();
326                             }
327                             catch(IOException JavaDoc e)
328                             {
329                                 if (!timeToStop)
330                                     e.printStackTrace();
331                             }
332                         }
333                     }
334                 }
335             }
336         }
337     }
338 }
339
340
341
342
343
344
Popular Tags