/* * Created on Nov 28, 2006 Copyright (C) 2001-6, Anthony Harrison anh23@pitt.edu * (jactr.org) 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. You should have * received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.jactr.core.logging.impl; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.concurrent.ExecutorServices; import org.jactr.core.logging.ILogger; import org.jactr.core.logging.LogEvent; import org.jactr.core.logging.Logger; import org.jactr.core.model.IModel; import org.jactr.core.model.event.IModelListener; import org.jactr.core.model.event.ModelEvent; import org.jactr.core.model.event.ModelListenerAdaptor; import org.jactr.core.runtime.ACTRRuntime; import org.jactr.core.utils.RollingFileWriter; import org.jactr.core.utils.parameter.IParameterized; import org.jactr.core.utils.parameter.ParameterHandler; import org.jactr.instrument.IInstrument; /** * demuxing logger * * @author developer */ public class DefaultModelLogger implements IInstrument, ILogger, IParameterized { /** * logger definition */ static private final Log LOGGER = LogFactory .getLog(DefaultModelLogger.class); static public final String ALL = "all"; static public final String BACKUPS = "NumberOfBackups"; static public final String SIZE = "MaxFileSize"; private Map<String, ILogger> _outputStreams; private Collection<IModel> _listeningTo; private Map<String, PrintWriter> _commonStreams; private Map<String, String> _logToStream; /* * so that we can flush intelligently. */ private IModelListener _modelListener; private long _maxSize = 1024 * 1024; private int _maxBackups = 3; public DefaultModelLogger() { super(); _commonStreams = new TreeMap<String, PrintWriter>(); _outputStreams = new TreeMap<String, ILogger>(); _logToStream = new TreeMap<String, String>(); _listeningTo = new ArrayList<IModel>(); _commonStreams.put("err", new PrintWriter(System.err, true)); _commonStreams.put("out", new PrintWriter(System.out)); _modelListener = new ModelListenerAdaptor() { public void cycleStopped(ModelEvent me) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Flushing"); flush(); } public void modelStopped(ModelEvent me) { flush(); } }; } public void log(LogEvent log) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Got log event " + log); ILogger pw = getLoggerForStream(log.getStreamName()); if (pw != null) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Logging to " + pw + " : " + log); pw.log(log); // pw.flush(); } // if(log.getStreamName().equals(Logger.Stream.TIME.toString())) // flush(); } public String getParameter(String key) { return null; } synchronized public void setLoggerForStream(String stream, ILogger logger) { if (logger != null) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Associative " + stream + " with " + logger); _outputStreams.put(stream, logger); } else _outputStreams.remove(stream); } synchronized public ILogger getLoggerForStream(String stream) { ILogger logger = _outputStreams.get(stream); if (logger == null) logger = _outputStreams.get(ALL); return logger; } public Collection<String> getPossibleParameters() { ArrayList<String> streams = new ArrayList<String>( Logger.Stream.values().length); for (Logger.Stream stream : Logger.Stream.values()) streams.add(stream.name()); return Collections.unmodifiableCollection(streams); } public Collection<String> getSetableParameters() { return getPossibleParameters(); } public void setParameter(String key, String value) { boolean dirty = false; if (BACKUPS.equalsIgnoreCase(key)) { _maxBackups = ParameterHandler.numberInstance().coerce(value).intValue(); dirty = true; } else if (SIZE.equalsIgnoreCase(key)) { _maxSize = (long) (ParameterHandler.numberInstance().coerce(value) .doubleValue() * 1024 * 1024); dirty = true; } else { createStream(key, value); _logToStream.put(key, value); } if (dirty) { /* * we need to recreate the streams */ _commonStreams.clear(); _outputStreams.clear(); for (Map.Entry<String, String> entry : _logToStream.entrySet()) createStream(entry.getKey(), entry.getValue()); } } private void createStream(String log, String stream) { PrintWriter pw = _commonStreams.get(stream); if (pw == null) { Writer w = new RollingFileWriter(ACTRRuntime.getRuntime() .getWorkingDirectory(), stream, _maxSize, _maxBackups); pw = new PrintWriter(w); _commonStreams.put(stream, pw); } if (pw != null) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Setting stream " + log + " to " + pw); setLoggerForStream(log, new PrintWriterLogger(pw)); } } /** * @see org.jactr.core.utils.IInstallable#install(org.jactr.core.model.IModel) */ public void install(IModel model) { Logger.addLogger(model, this); _listeningTo.add(model); model.addListener(_modelListener, ExecutorServices .getExecutor(ExecutorServices.BACKGROUND)); } /** * @see org.jactr.core.utils.IInstallable#uninstall(org.jactr.core.model.IModel) */ public void uninstall(IModel model) { _listeningTo.remove(model); model.removeListener(_modelListener); Logger.removeLogger(model, this); synchronized (this) { if (_listeningTo.size() == 0) _outputStreams.clear(); } } synchronized public void flush() { /* * zip through them all and flush.. */ for (ILogger logger : _outputStreams.values()) logger.flush(); } /** * @see org.jactr.instrument.IInstrument#initialize() */ public void initialize() { // noop } }