/* This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *

* This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.rzo.yajsw.log; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.logging.FileHandler; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import org.rzo.yajsw.log.MyFileHandler.FileChangeListner; // TODO: Auto-generated Javadoc /** * The Class DateFileHandler. */ public class DateFileHandler extends Handler { /** The _handler. */ volatile MyFileHandler _handler; /** The _end date. */ volatile long _endDate; /** The _pattern. */ volatile String _pattern; /** The _limit. */ volatile int _limit; /** The _count. */ volatile int _count; /** The _append. */ volatile boolean _append; /** The format. */ final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); /** The _init. */ volatile boolean _init = false; volatile boolean _rollDate = false; volatile long _startDate = System.currentTimeMillis(); //volatile LinkedList _previousFiles = new LinkedList(); //volatile LinkedList _currentFiles = new LinkedList(); volatile LinkedList _previousDates = new LinkedList(); volatile String _currentDate = null; volatile int _maxDays = -1; /** * Instantiates a new date file handler. * * @param pattern * the pattern * @param limit * the limit * @param count * the count * @param append * the append * * @throws IOException * Signals that an I/O exception has occurred. * @throws SecurityException * the security exception */ public DateFileHandler(String pattern, int limit, int count, boolean append, boolean rollDate, PatternFormatter fileFormatter, Level logLevel, String encoding, int maxDays) { _pattern = pattern; _limit = limit; _count = count; _append = append; _rollDate = rollDate; _maxDays = maxDays; _init = true; if (encoding != null) try { setEncoding(encoding); } catch (Exception e) { e.printStackTrace(); } setFormatter(fileFormatter); setLevel(logLevel); findPreviousDates(); rotateDate(); //checkFileCount(); } /* * (non-Javadoc) * * @see java.util.logging.Handler#close() */ @Override public void close() throws SecurityException { _handler.close(); } /* * (non-Javadoc) * * @see java.util.logging.Handler#flush() */ @Override public void flush() { _handler.flush(); } /* * (non-Javadoc) * * @see java.util.logging.Handler#publish(java.util.logging.LogRecord) */ @Override public void publish(LogRecord record) { if (_rollDate) { if (_endDate < record.getMillis()) rotateDate(); if (System.currentTimeMillis() - _startDate > 25*60*60*1000) { String msg = record.getMessage(); record.setMessage("missed file rolling at: "+new Date(_endDate)+"\n"+msg); } } _handler.publish(record); } /* * (non-Javadoc) * * @see java.util.logging.Handler#setFormatter(java.util.logging.Formatter) */ @Override public void setFormatter(Formatter newFormatter) { super.setFormatter(newFormatter); if (_handler != null) _handler.setFormatter(newFormatter); } /** * Rotate date. */ private void rotateDate() { _startDate = System.currentTimeMillis(); if (_handler != null) _handler.close(); _previousDates.addLast(_currentDate); cleanupDates(); _currentDate = format.format(new Date()); String pattern = _pattern.replace("%d", _currentDate); try { File dd = MyFileHandler.generate(pattern, 0, 0, _count); if (!dd.getParentFile().exists()) dd.getParentFile().mkdirs(); } catch (IOException e1) { } Calendar next = Calendar.getInstance(); // current date // begin of next date next.set(Calendar.HOUR_OF_DAY, 0); next.set(Calendar.MINUTE, 0); next.set(Calendar.SECOND, 0); next.set(Calendar.MILLISECOND, 0); next.add(Calendar.DATE, 1); _endDate = next.getTimeInMillis(); try { _handler = new MyFileHandler(pattern, _limit, _count, _append); if (_init) { _handler.setEncoding(this.getEncoding()); _handler.setErrorManager(this.getErrorManager()); _handler.setFilter(this.getFilter()); _handler.setFormatter(this.getFormatter()); _handler.setLevel(this.getLevel()); //findFiles(); //_currentFiles.clear(); //addFiles(_handler.getCurrentFiles()); /* _handler.setNewFileListner(new FileChangeListner() { public void fileChange(File file, boolean added) { System.out.println("file change: "+added+ " "+file.getName()); if (added) addFile(file); } }); */ } } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void cleanupDates() { if (_maxDays >= 0) while (_previousDates.size() > _maxDays) { String toCleanup = _previousDates.removeFirst(); cleanupDate(toCleanup); } } private void cleanupDate(String date) { String pattern = _pattern.replace("%d", date); File f; for (int unique=0; unique<_count; unique++) { try { f = MyFileHandler.generate(pattern, 0, unique, _count); if (!f.exists()) break; } catch (IOException e1) { // should not happen, but keep silent for now } for (int generation=0; generation<_count; generation++) { try { f = MyFileHandler.generate(pattern, generation, unique, _count); if (f.exists()) { f.delete(); } else break; } catch (IOException e) { // should not happen, but keep silent for now } } } // cleanup parent folder if necessary try { // remove old lock files f = MyFileHandler.generate(pattern+".lck", 0, 0, _count); f.delete(); f = MyFileHandler.generate(pattern, 0, 0, _count); while (!f.getName().contains(date)) f = f.getParentFile(); if (f.isDirectory()) f.delete(); } catch (IOException e) { // should not happen, but keep silent for now } } private void findPreviousDates() { if (_maxDays < 0) return; Calendar date = Calendar.getInstance(); // service may not run daily // for performance: do not scan all files. // service may not run every day, but we assume it will run at least once a year int scanDays = Math.max(365, _maxDays); for (int i = 0; i 0 && _previousFiles.size()+_currentFiles.size()>_count) { File f = _previousFiles.removeLast(); if (f.exists()) f.delete(); } } private void addFile(File f) { if (!_currentFiles.contains(f)) _currentFiles.addFirst(f); checkFileCount(); } private void addFiles(LinkedList files) { while (!files.isEmpty()) addFile(files.removeLast()); } private void findFiles() throws IOException { Calendar date = Calendar.getInstance(); while (_previousFiles.size() < _count) { date.add(Calendar.DAY_OF_MONTH, -1); String pattern = _pattern.replace("%d", format.format(date.getTime())); for (int unique=0; unique<_count; unique++) { for (int generation=0; generation<_count; generation++) { File f = MyFileHandler.generate(pattern, generation, unique, _count); if (f.exists() && !_previousFiles.contains(f)) { _previousFiles.addLast(f); } else { break; } } File f = MyFileHandler.generate(pattern, 0, unique, _count); if (!f.exists() || _previousFiles.contains(f)) break; } File f = MyFileHandler.generate(pattern, 0, 0, _count); if (!f.exists()) break; } } */ }