/** * Mad-Advertisement * Copyright (C) 2011 Thorsten Marx <thmarx@gmx.net> * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package net.mad.ads.base.api.utils.logging.handler; import java.io.*; import java.text.SimpleDateFormat; import java.util.*; import java.util.logging.*; import java.util.logging.Formatter; /** * File handler that supports different kind of rolling than * java.util.logging.FileHandler. Supported rolling methods are: by date (day). * * Example of entries in the logging file (system property * "java.util.logging.config.file"): * * <table align="center" bgcolor="#ddddff" border=1 cellpadding="10" cellspacing="0"> * <tr> * <td> * * <pre> * logging.RollingFileHandler.level = FINEST * logging.RollingFileHandler.prefix = MyApp_ * logging.RollingFileHandler.dateFormat = yyyyMMdd * logging.RollingFileHandler.suffix = .log * logging.RollingFileHanlder.cycle=day * logging.RollingFileHandler.formatter = java.util.logging.SimpleFormatter * </pre> * * </td> * </tr> * </table> * * @version $Revision:$ ($Date:$) * @author $Author:$ */ public class RollingFileHandler extends StreamHandler { /** File prefix. */ private static String prefix = null; /** Date format to use in file name. */ private static String dateFormat = "yyyy-MM-dd"; // default /** File suffix. */ private static String suffix = null; /** Time in milliseconds for the next cycle */ private static long nextCycle = 0; /** Time cycle (for file roling) */ private static String cycle = "day"; // default public RollingFileHandler(String prefix, String suffix) { this.suffix = suffix; this.prefix = prefix; openFile(); } /** * Constructor. */ public RollingFileHandler() { super(); LogManager manager = LogManager.getLogManager(); String className = RollingFileHandler.class.getName(); prefix = manager.getProperty(className + ".prefix"); String dfs = manager.getProperty(className + ".dateFormat"); suffix = manager.getProperty(className + ".suffix"); String c = manager.getProperty(className + ".cycle"); String formatter = manager.getProperty(className + ".formatter"); if (dfs != null) { dateFormat = dfs; } if (c != null) { if (c.equalsIgnoreCase("day") || c.equalsIgnoreCase("week") || c.equalsIgnoreCase("month") || c.equalsIgnoreCase("year")) { cycle = c; } } if (formatter != null) { try { setFormatter((Formatter) Class.forName(formatter).newInstance()); } catch (Exception e) { e.printStackTrace(System.err); } } openFile(); }// RollingFileHandler() /** * Open existing or create new log file. */ private synchronized void openFile() { // create file name: String dateString = dateFormat; // default (to note error in file name) Date currentDate = new Date(); try { SimpleDateFormat sdf = new SimpleDateFormat(dateFormat, Locale.getDefault()); dateString = sdf.format(currentDate); } catch (IllegalArgumentException iae) { /* ignore wrong date format */ } // compute next cycle: Date nextDate = null; GregorianCalendar gc = new GregorianCalendar(); gc.setTime(currentDate); if (cycle.equalsIgnoreCase("week")) { gc.add(Calendar.WEEK_OF_YEAR, 1); nextDate = gc.getTime(); } else if (cycle.equalsIgnoreCase("month")) { gc.add(Calendar.MONTH, 1); int month = gc.get(Calendar.MONTH); int year = gc.get(Calendar.YEAR); GregorianCalendar gc2 = new GregorianCalendar(year, month, 1); nextDate = gc2.getTime(); } else if (cycle.equalsIgnoreCase("year")) { gc.add(Calendar.YEAR, 1); int year = gc.get(Calendar.YEAR); GregorianCalendar gc2 = new GregorianCalendar(year, 0, 1); nextDate = gc2.getTime(); } else { // day by default gc.add(Calendar.DAY_OF_MONTH, 1); nextDate = gc.getTime(); } // to zero time: gc = new GregorianCalendar(); gc.setTime(nextDate); gc.set(Calendar.HOUR, 0); gc.set(Calendar.HOUR_OF_DAY, 0); gc.set(Calendar.MINUTE, 0); gc.set(Calendar.SECOND, 0); gc.set(Calendar.MILLISECOND, 0); nextDate = gc.getTime(); nextCycle = nextDate.getTime(); // create new file: String fileName = prefix + dateString + suffix; File file = new File(fileName); // create file: if (!file.exists()) { try { file.createNewFile(); } catch (IOException ioe) { ioe.printStackTrace(System.err); } } // set log file as OutputStream: try { FileOutputStream fos = new FileOutputStream(file, true); setOutputStream(fos); } catch (FileNotFoundException fnfe) { reportError(null, fnfe, ErrorManager.OPEN_FAILURE); fnfe.printStackTrace(System.err); setOutputStream(System.out); // fallback stream } }// openFile() /** * Overwrites super. */ public synchronized void publish(LogRecord record) { if (!isLoggable(record)) { return; } super.publish(record); flush(); // check if we need to rotate if (System.currentTimeMillis() >= nextCycle) { // next cycle? role(); } }// publish() /** * Role file. Close current file and possibly create new file. */ final private synchronized void role() { Level oldLevel = getLevel(); setLevel(Level.OFF); super.close(); openFile(); setLevel(oldLevel); }// rotate() }// RollingFileHandler