Mercurial Hosting > luan
diff src/org/eclipse/jetty/util/RolloverFileOutputStream.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/util/RolloverFileOutputStream.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,340 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; +import java.util.Timer; +import java.util.TimerTask; + +/** + * RolloverFileOutputStream + * + * This output stream puts content in a file that is rolled over every 24 hours. + * The filename must include the string "yyyy_mm_dd", which is replaced with the + * actual date when creating and rolling over the file. + * + * Old files are retained for a number of days before being deleted. + * + * + */ +public class RolloverFileOutputStream extends FilterOutputStream +{ + private static Timer __rollover; + + final static String YYYY_MM_DD="yyyy_mm_dd"; + final static String ROLLOVER_FILE_DATE_FORMAT = "yyyy_MM_dd"; + final static String ROLLOVER_FILE_BACKUP_FORMAT = "HHmmssSSS"; + final static int ROLLOVER_FILE_RETAIN_DAYS = 31; + + private RollTask _rollTask; + private SimpleDateFormat _fileBackupFormat; + private SimpleDateFormat _fileDateFormat; + + private String _filename; + private File _file; + private boolean _append; + private int _retainDays; + + /* ------------------------------------------------------------ */ + /** + * @param filename The filename must include the string "yyyy_mm_dd", + * which is replaced with the actual date when creating and rolling over the file. + * @throws IOException + */ + public RolloverFileOutputStream(String filename) + throws IOException + { + this(filename,true,ROLLOVER_FILE_RETAIN_DAYS); + } + + /* ------------------------------------------------------------ */ + /** + * @param filename The filename must include the string "yyyy_mm_dd", + * which is replaced with the actual date when creating and rolling over the file. + * @param append If true, existing files will be appended to. + * @throws IOException + */ + public RolloverFileOutputStream(String filename, boolean append) + throws IOException + { + this(filename,append,ROLLOVER_FILE_RETAIN_DAYS); + } + + /* ------------------------------------------------------------ */ + /** + * @param filename The filename must include the string "yyyy_mm_dd", + * which is replaced with the actual date when creating and rolling over the file. + * @param append If true, existing files will be appended to. + * @param retainDays The number of days to retain files before deleting them. 0 to retain forever. + * @throws IOException + */ + public RolloverFileOutputStream(String filename, + boolean append, + int retainDays) + throws IOException + { + this(filename,append,retainDays,TimeZone.getDefault()); + } + + /* ------------------------------------------------------------ */ + /** + * @param filename The filename must include the string "yyyy_mm_dd", + * which is replaced with the actual date when creating and rolling over the file. + * @param append If true, existing files will be appended to. + * @param retainDays The number of days to retain files before deleting them. 0 to retain forever. + * @throws IOException + */ + public RolloverFileOutputStream(String filename, + boolean append, + int retainDays, + TimeZone zone) + throws IOException + { + + this(filename,append,retainDays,zone,null,null); + } + + /* ------------------------------------------------------------ */ + /** + * @param filename The filename must include the string "yyyy_mm_dd", + * which is replaced with the actual date when creating and rolling over the file. + * @param append If true, existing files will be appended to. + * @param retainDays The number of days to retain files before deleting them. 0 to retain forever. + * @param dateFormat The format for the date file substitution. The default is "yyyy_MM_dd". + * @param backupFormat The format for the file extension of backup files. The default is "HHmmssSSS". + * @throws IOException + */ + public RolloverFileOutputStream(String filename, + boolean append, + int retainDays, + TimeZone zone, + String dateFormat, + String backupFormat) + throws IOException + { + super(null); + + if (dateFormat==null) + dateFormat=ROLLOVER_FILE_DATE_FORMAT; + _fileDateFormat = new SimpleDateFormat(dateFormat); + + if (backupFormat==null) + backupFormat=ROLLOVER_FILE_BACKUP_FORMAT; + _fileBackupFormat = new SimpleDateFormat(backupFormat); + + _fileBackupFormat.setTimeZone(zone); + _fileDateFormat.setTimeZone(zone); + + if (filename!=null) + { + filename=filename.trim(); + if (filename.length()==0) + filename=null; + } + if (filename==null) + throw new IllegalArgumentException("Invalid filename"); + + _filename=filename; + _append=append; + _retainDays=retainDays; + setFile(); + + synchronized(RolloverFileOutputStream.class) + { + if (__rollover==null) + __rollover=new Timer(RolloverFileOutputStream.class.getName(),true); + + _rollTask=new RollTask(); + + Calendar now = Calendar.getInstance(); + now.setTimeZone(zone); + + GregorianCalendar midnight = + new GregorianCalendar(now.get(Calendar.YEAR), + now.get(Calendar.MONTH), + now.get(Calendar.DAY_OF_MONTH), + 23,0); + midnight.setTimeZone(zone); + midnight.add(Calendar.HOUR,1); + __rollover.scheduleAtFixedRate(_rollTask,midnight.getTime(),1000L*60*60*24); + } + } + + /* ------------------------------------------------------------ */ + public String getFilename() + { + return _filename; + } + + /* ------------------------------------------------------------ */ + public String getDatedFilename() + { + if (_file==null) + return null; + return _file.toString(); + } + + /* ------------------------------------------------------------ */ + public int getRetainDays() + { + return _retainDays; + } + + /* ------------------------------------------------------------ */ + private synchronized void setFile() + throws IOException + { + // Check directory + File file = new File(_filename); + _filename=file.getCanonicalPath(); + file=new File(_filename); + File dir= new File(file.getParent()); + if (!dir.isDirectory() || !dir.canWrite()) + throw new IOException("Cannot write log directory "+dir); + + Date now=new Date(); + + // Is this a rollover file? + String filename=file.getName(); + int i=filename.toLowerCase(Locale.ENGLISH).indexOf(YYYY_MM_DD); + if (i>=0) + { + file=new File(dir, + filename.substring(0,i)+ + _fileDateFormat.format(now)+ + filename.substring(i+YYYY_MM_DD.length())); + } + + if (file.exists()&&!file.canWrite()) + throw new IOException("Cannot write log file "+file); + + // Do we need to change the output stream? + if (out==null || !file.equals(_file)) + { + // Yep + _file=file; + if (!_append && file.exists()) + file.renameTo(new File(file.toString()+"."+_fileBackupFormat.format(now))); + OutputStream oldOut=out; + out=new FileOutputStream(file.toString(),_append); + if (oldOut!=null) + oldOut.close(); + //if(log.isDebugEnabled())log.debug("Opened "+_file); + } + } + + /* ------------------------------------------------------------ */ + private void removeOldFiles() + { + if (_retainDays>0) + { + long now = System.currentTimeMillis(); + + File file= new File(_filename); + File dir = new File(file.getParent()); + String fn=file.getName(); + int s=fn.toLowerCase(Locale.ENGLISH).indexOf(YYYY_MM_DD); + if (s<0) + return; + String prefix=fn.substring(0,s); + String suffix=fn.substring(s+YYYY_MM_DD.length()); + + String[] logList=dir.list(); + for (int i=0;i<logList.length;i++) + { + fn = logList[i]; + if(fn.startsWith(prefix)&&fn.indexOf(suffix,prefix.length())>=0) + { + File f = new File(dir,fn); + long date = f.lastModified(); + if ( ((now-date)/(1000*60*60*24))>_retainDays) + f.delete(); + } + } + } + } + + /* ------------------------------------------------------------ */ + @Override + public void write (byte[] buf) + throws IOException + { + out.write (buf); + } + + /* ------------------------------------------------------------ */ + @Override + public void write (byte[] buf, int off, int len) + throws IOException + { + out.write (buf, off, len); + } + + /* ------------------------------------------------------------ */ + /** + */ + @Override + public void close() + throws IOException + { + synchronized(RolloverFileOutputStream.class) + { + try{super.close();} + finally + { + out=null; + _file=null; + } + + _rollTask.cancel(); + } + } + + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + private class RollTask extends TimerTask + { + @Override + public void run() + { + try + { + RolloverFileOutputStream.this.setFile(); + RolloverFileOutputStream.this.removeOldFiles(); + + } + catch(IOException e) + { + // Cannot log this exception to a LOG, as RolloverFOS can be used by logging + e.printStackTrace(); + } + } + } +}