package org.dresdenocl.logging.internal;
import java.net.URL;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.log4j.Appender;
import org.apache.log4j.Category;
import org.apache.log4j.Hierarchy;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.spi.HierarchyEventListener;
import org.apache.log4j.spi.RootLogger;
import org.eclipse.core.runtime.Plugin;
import org.dresdenocl.logging.ILogManager;
import org.dresdenocl.logging.LoggingPlugin;
import org.dresdenocl.logging.appender.ErrorLogAppender;
import org.dresdenocl.logging.appender.PluginLogFileAppender;
/**
* Default implementation of the <code>ILogManager</code> interface.
*
* @author Matthias Braeuer
* @version 1.0 13.03.2007
*/
public class DefaultLogManager implements ILogManager {
// a logger for this class
private static final Logger logger = Logger
.getLogger(DefaultLogManager.class);
// the plugin that belongs to this log manager
private Plugin plugin;
// the log4j hierarchy managed by this log manager
private Hierarchy hierarchy;
// flag indicating whether this log manager has been disposed
private boolean disposed;
/**
* Creates a new <code>DefaultLogManager</code> instance for the given
* {@link Plugin}. A log4j {@link Hierarchy} object will be created
* specifically for this <code>LogManager</code>.
*
* @param aPlugin the corresponding Eclipse plugin, must NOT be
* <code>null</code>
*/
public DefaultLogManager(final Plugin aPlugin) {
if (logger.isDebugEnabled()) {
logger.debug("DefaultLogManager(plugin=" + aPlugin + ") - enter"); //$NON-NLS-1$ //$NON-NLS-2$
}
// precondition check
if (aPlugin == null) {
throw new IllegalArgumentException("The parameter 'plugin' was null!"); //$NON-NLS-1$
}
// set the plugin
this.plugin = aPlugin;
// instantiate a new log4j hierarchy with log level set to WARN
hierarchy = new Hierarchy(new RootLogger(Level.WARN));
// add a special hierarchy listener to configure the Eclipse appenders if
// necessary
hierarchy.addHierarchyEventListener(new PluginEventListener());
// configure the hierarchy
new PropertyConfigurator().doConfigure(getLoggerPropertiesUrl(), hierarchy);
if (logger.isDebugEnabled()) {
logger.debug("DefaultLogManager() - exit"); //$NON-NLS-1$
}
}
/**
* Helper method to find a custom version of the logger properties in the
* associated plugin. If no custom properties are found, the URL of the
* default properties in this plugin is returned.
*
* @return a <code>URL</code> instance
*/
private URL getLoggerPropertiesUrl() {
if (logger.isDebugEnabled()) {
logger.debug("getLoggerPropertiesUrl() - enter"); //$NON-NLS-1$
}
URL url;
// try to load the config file from the main path of the plugin
url = plugin.getBundle().getEntry("/" + DEFAULT_CONFIG_FILE_NAME); //$NON-NLS-1$
// try to load a resource from the plugin
if (url == null) {
url = plugin.getBundle().getResource(DEFAULT_CONFIG_FILE_NAME);
}
// default to own logger properties
if (url == null) {
url = LoggingPlugin.getDefault().getBundle().getEntry(
"/" + DEFAULT_CONFIG_FILE_NAME); //$NON-NLS-1$
}
if (logger.isDebugEnabled()) {
logger.debug("getLoggerPropertiesUrl() - exit - return value=" + url); //$NON-NLS-1$
}
return url;
}
/**
* Returns the logger with the given name managed by the log4j
* {@link Hierarchy} encapsulated by this log manager.
*
* @param name the name of the desired logger
*
* @return a <code>Logger</code> instance
*/
public Logger getLogger(final String name) {
return hierarchy.getLogger(name);
}
/**
* Delegates to the encapsulated {@link Hierarchy log4j hierarchy}'s
* {@link Hierarchy#getLogger(String)} method by passing the
* {@link Class#getCanonicalName() canonical name} of the given class.
*
* @param clazz the class to return a logger for
*
* @return a <code>Logger</code> instance
*/
public Logger getLogger(final Class<?> clazz) {
return hierarchy.getLogger(clazz.getCanonicalName());
}
/**
* Returns the root logger of the encapsulated
* {@link Hierarchy log4j hierarchy}.
*
* @return a <code>Logger</code> instance
*/
public Logger getRootLogger() {
return hierarchy.getRootLogger();
}
/**
* Shuts down the encapsulated {@link Hierarchy log4j hierarchy}.
*/
public void dispose() {
if (logger.isDebugEnabled()) {
logger.debug("dispose() - enter"); //$NON-NLS-1$
}
// prevent expensive shutdown calls on all the hierarchy's appenders
if (!disposed) {
hierarchy.shutdown();
disposed = true;
}
if (logger.isDebugEnabled()) {
logger.debug("dispose() - exit"); //$NON-NLS-1$
}
}
/**
* Returns a string representation of this log manager using the Jakarta
* Commons Lang library.
*
* @return a <code>String</code> instance
*/
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append(
"plugin", plugin).append("disposed", disposed).toString(); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Returns the plugin associated with this log manager.
*
* @return a <code>Plugin</code> instance or <code>null</code> if no
* plugin has been set
*/
protected Plugin getPlugin() {
return plugin;
}
/**
* A custom hierarchy event listener that will set the necessary properties
* for the special plugin-based log4j appenders. Note that we don't need to
* check whether the plugin belonging to this LogManager is null because in
* this case the listener would not have been attached to the log4j hierarchy.
*/
protected class PluginEventListener implements HierarchyEventListener {
/**
* Logger for this class.
*/
private final Logger logger = Logger.getLogger(PluginEventListener.class);
/**
* Called when a new appender is added for a particular level. Internally it
* checks if the appender is one of our custom ones and sets its custom
* properties.
*
* @param category level
* @param appender appender added for this level
*/
public void addAppenderEvent(final Category category,
final Appender appender) {
if (logger.isDebugEnabled()) {
logger
.debug("addAppenderEvent(cat=" + category + ", appender=" + appender + ") - enter"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if (appender instanceof ErrorLogAppender) {
((ErrorLogAppender) appender).setLog(getPlugin().getLog());
}
else if (appender instanceof PluginLogFileAppender) {
((PluginLogFileAppender) appender).setStateLocation(getPlugin()
.getStateLocation());
}
if (logger.isDebugEnabled()) {
logger.debug("addAppenderEvent() - exit"); //$NON-NLS-1$
}
}
/**
* Called when an appender is removed from for a particular level. Does
* nothing.
*
* @param category level
* @param appender appender added for this level
*/
public void removeAppenderEvent(final Category category,
final Appender appender) {
// no implementation necessary
}
}
}