package org.jactr.core.utils; /* * default logging */ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class RollingFileWriter extends Writer { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(RollingFileWriter.class); final private long _maxFileSize; // 1 // M final private long _maxBackups; final private File _directory; final private String _fileName; final private String _prefix; final private String _extension; private File _file; private Writer _fileWriter; public RollingFileWriter(File directory, String fileName) { this(directory, fileName, 1024 * 1024, 3); } public RollingFileWriter(File directory, String fileName, long maxSize, long backups) { _maxBackups = backups; _maxFileSize = maxSize; _directory = directory; _fileName = fileName; int index = _fileName.lastIndexOf('.'); if (index >= 0) { _prefix = _fileName.substring(0, index); _extension = _fileName.substring(index + 1); } else { _prefix = _fileName; _extension = ""; } createStreams(); } private void createStreams() { _file = new File(_directory, _fileName); try { _fileWriter = new BufferedWriter(new FileWriter(_file)); } catch (IOException ioe) { LOGGER.error("could not create file writer for " + _file.getName() + ", using stderr", ioe); _fileWriter = new PrintWriter(System.err, true); } } private SortedMap<Integer, File> findLogs() { SortedMap<Integer, File> sortedFiles = new TreeMap<Integer, File>(); for (File file : _directory.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.startsWith(_prefix) && name.endsWith(_extension); } })) sortedFiles.put(getIndex(file), file); return sortedFiles; } /* * close old stream */ private void closeInternalStream() { try { _fileWriter.close(); } catch (IOException e) { LOGGER.error("RollingWriterLogger.rollOver threw IOException : ", e); } _fileWriter = null; _file = null; } /** * return number suffix {name}-{number}.{extension} * * @param file * @return */ private int getIndex(File file) { String fileName = file.getName(); if (_extension.length() != 0) fileName = fileName.substring(0, fileName.indexOf(_extension)-1); fileName = fileName.substring(_prefix.length()); try { return Integer .parseInt(fileName.substring(fileName.lastIndexOf('-') + 1)); } catch (Exception e) { return 0; } } private void rollOver() { closeInternalStream(); SortedMap<Integer, File> files = findLogs(); if (files.size() == _maxBackups + 1) { /* * delete the oldest */ Integer last = files.lastKey(); files.remove(last).delete(); } List<File> reverse = new ArrayList<File>(files.values()); Collections.reverse(reverse); Iterator<File> itr = reverse.iterator(); /* * rename to the next index */ while (itr.hasNext()) { File file = itr.next(); file.renameTo(new File(_directory, _prefix + "-" + reverse.size() + "." + _extension)); itr.remove(); } } private void checkForRollOver() { if (_file.length() >= _maxFileSize) { rollOver(); createStreams(); } } synchronized public void flush() { try { _fileWriter.flush(); } catch (IOException ioe) { LOGGER.error("Could not flush to " + _file.getName(), ioe); } checkForRollOver(); } @Override synchronized public void close() throws IOException { flush(); closeInternalStream(); } @Override synchronized public void write(char[] cbuf, int off, int len) throws IOException { _fileWriter.write(cbuf, off, len); checkForRollOver(); } }