/* * Copyright (C) 2008 Universidade Federal de Campina Grande * * This file is part of OurGrid. * * OurGrid 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 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 Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.ourgrid.common.logger; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Map; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Layout; import org.apache.log4j.spi.LoggingEvent; import org.ourgrid.common.util.CommonUtils; /** * This class is a consumer of log events. It's responsible to write the * information existent into the each log event in the specified file, with the * specified layout. */ public class MGLogWriter4j extends AppenderSkeleton { private Layout layout; private File logFile; private BufferedWriter bw; private ArrayList<LoggingEvent> logBuffer = new ArrayList<LoggingEvent>(); public static final int TIMEOUT = 10000; private Dispatcher dispatcher; /** * HashMap containing writers that had been instantiated */ private static Map<String,MGLogWriter4j> writers = CommonUtils.createSerializableMap(); /** * MyAppender Constructor * * @param layout the layout to format log messages * @param fileName the file to write log */ private MGLogWriter4j(Layout layout, String fileName, boolean newFile) { this.layout = layout; try { logFile = new File(fileName); if (newFile) { logFile.delete(); logFile.createNewFile(); } } catch (Exception e) { System.err.println("Cannot create log file: \"" + this.logFile.getAbsolutePath() + "\""); } dispatcher = new Dispatcher(this); dispatcher.start(); } /** * Return an instance of MGLogWriter4j. We have one instance per file. * * @param layout the layout to format log messages. * @param fileName the file to write log. * @param newFile Determines if an existent file must be overwritten. * @return an instance of MGLogWriter. */ public static MGLogWriter4j getInstance(Layout layout, String fileName, boolean newFile) { File myFile = new File(fileName); MGLogWriter4j mglw = writers.get(myFile.getAbsolutePath()); if (mglw == null) { mglw = new MGLogWriter4j(layout, fileName, newFile); writers.put(myFile.getAbsolutePath(), mglw); } return mglw; } /** * Get all LoggingEvent buffered and write's it all on disk, in a log file. * Then the log buffer is reseted. */ protected void writeBufferedLogs() { synchronized (logBuffer) { try { bw = new BufferedWriter(new FileWriter(logFile, true)); while (!logBuffer.isEmpty()) { bw.write(layout.format(logBuffer.get(0))); logBuffer.remove(0); } } catch (IOException ioe) { System.out.println("Cannot write to log file: \"" + this.logFile.getAbsolutePath() + "\""); } finally { try { bw.close(); } catch (IOException e) { System.out.println("Cannot close log file: \"" + this.logFile.getAbsolutePath() + "\""); } } } } /* * (non-Javadoc) * * @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent) */ protected void append(LoggingEvent event) { // set the Local Information of an event event.getLocationInformation(); synchronized (logBuffer) { logBuffer.add(event); logBuffer.notifyAll(); } } /* * (non-Javadoc) * * @see org.apache.log4j.Appender#close() */ public void close() { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see org.apache.log4j.Appender#requiresLayout() */ public boolean requiresLayout() { return true; } /** * This class is a thread that make the MGLogWriter4j waits a sleep time to * write buffered logs. */ private class Dispatcher extends Thread { private MGLogWriter4j appender; public Dispatcher(MGLogWriter4j appender) { this.appender = appender; this.setDaemon(true); this.setName("Log Writer"); } public void run() { while (true) { try { Thread.sleep(MGLogWriter4j.TIMEOUT); } catch (InterruptedException e) { // does nothing } appender.writeBufferedLogs(); } } } }