/*
* (c) Rob Gordon 2005
*/
package org.oddjob.logging.cache;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.oddjob.Stateful;
import org.oddjob.logging.ArchiveNameResolver;
import org.oddjob.logging.LogArchive;
import org.oddjob.logging.LogArchiver;
import org.oddjob.logging.LogLevel;
import org.oddjob.logging.LogListener;
import org.oddjob.state.StateListener;
import org.oddjob.state.StateEvent;
/**
* An base implementation of a Cache for LogEvents.
* <p>
* @author Rob Gordon
*/
abstract public class AbstractArchiverCache implements LogArchiverCache {
private static final Logger logger = Logger.getLogger(AbstractArchiverCache.class);
/**
* Map of archive name to archive.
*/
private final Map<String, LogArchiveImpl> archives =
new HashMap<String, LogArchiveImpl>();
/**
* Keep track of children and archives so we can delete an archive.
*/
private final SimpleCounter counter = new SimpleCounter();
private final int maxHistory;
private final ArchiveNameResolver resolver;
private final StateListener stateListener = new StateListener() {
@Override
public void jobStateChange(StateEvent event) {
if (event.getState().isDestroyed()) {
removeArchive(event.getSource());
}
}
};
/**
* Default constructor.
*/
public AbstractArchiverCache(ArchiveNameResolver resolver) {
this(resolver, LogArchiver.MAX_HISTORY);
}
/**
* Construct a LogArchiver with the given amount of history.
*
* @param maxHistory The number of lines to store for each logger
*/
public AbstractArchiverCache(ArchiveNameResolver resolver, int maxHistory) {
this.resolver = resolver;
this.maxHistory = maxHistory;
}
/*
* (non-Javadoc)
* @see org.oddjob.logging.FunctionalLogArchiver#getMaxHistory()
*/
public int getMaxHistory() {
return maxHistory;
}
/*
* (non-Javadoc)
* @see org.oddjob.logging.FunctionalLogArchiver#getLastMessageNumber(java.lang.String)
*/
public long getLastMessageNumber(String archive) {
LogArchive logArchive = archives.get(archive);
if (logArchive == null) {
throw new IllegalArgumentException("Archive [" + archive + "] does not exist in this LogArchiver.");
}
return logArchive.getLastMessageNumber();
}
/**
* Add a listener.
*
* @param l The listener
* @param archive The component
* @param level The level
* @param last The last message number.
* @param history The max messages required.
*/
public void addLogListener(LogListener l, Object component,
LogLevel level, long last, int history) {
String archive = resolver.resolveName(component);
LogArchive logArchive = archives.get(archive);
if (logArchive == null) {
l.logEvent(LogArchiver.NO_LOG_AVAILABLE);
return;
}
logger.debug("Adding LogListener [" + l + "] for ["
+ logArchive.getArchive() + "]");
logArchive.addListener(l, level, last, history);
}
/**
* Remove a listener.
*
* @param l The listener.
* @param archive The archive.
*/
public void removeLogListener(LogListener l, Object component) {
String archive = resolver.resolveName(component);
LogArchive logArchive = archives.get(archive);
if (logArchive == null) {
return ;
}
logger.debug("Removing LogListener ["
+ l + "] from [" + logArchive.getArchive() + "]");
logArchive.removeListener(l);
}
/**
* Does this Archiver contain the given archive.
*
* @param archive The archive.
* @return true if it does, false if it doesn't.
*/
public boolean hasArchive(String archive) {
return archives.containsKey(archive);
}
protected boolean hasArchiveFor(Object component) {
return hasArchive(resolver.resolveName(component));
}
protected ArchiveNameResolver getResolver() {
return resolver;
}
/**
* Add an archive this Log Archiver.
*
* @param archive The archive name.
*/
protected void addArchive(Object component) {
final String archiveName = resolver.resolveName(component);
if (archiveName == null) {
return;
}
logger.debug("Adding archive [" + archiveName + "] for [" + component + "]");
counter.add(archiveName, new Runnable() {
public void run() {
LogArchiveImpl logArchive = new LogArchiveImpl(archiveName, getMaxHistory());
archives.put(archiveName, logArchive);
logger.debug("Adding archive for [" + archiveName + "]");
}
});
if (component instanceof Stateful) {
((Stateful) component).addStateListener(stateListener);
}
}
/**
* Remove an archive from this LogArchive.
*
* @param archive
*/
protected void removeArchive(Object component) {
final String archiveName = resolver.resolveName(component);
if (archiveName == null) {
return;
}
logger.debug("Removing log archive [" + archiveName +
"] for [" + component + "]");
counter.remove(archiveName, new Runnable() {
public void run() {
logger.debug("Deleting log archive [" + archiveName + "]");
archives.remove(archiveName);
}
});
}
/**
* Add an event to the cache.
*
* @param archive The archive.
* @param level The level.
* @param message The message.
*/
public void addEvent(String archive, LogLevel level, String message) {
LogArchiveImpl logArchive = archives.get(archive);
if (logArchive == null) {
throw new IllegalArgumentException("Archive [" + archive + "] does not exist in this LogArchiver.");
}
logArchive.addEvent(level, message);
}
public abstract void destroy();
}