/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.hibernate.eclipse.logging;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.log4j.Appender;
import org.apache.log4j.Category;
import org.apache.log4j.Hierarchy;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.spi.HierarchyEventListener;
import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.RepositorySelector;
import org.apache.log4j.spi.RootLogger;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Plugin;
import org.hibernate.console.execution.DefaultExecutionContext;
import org.hibernate.console.execution.ExecutionContext;
import org.hibernate.console.execution.ExecutionContext.Command;
/**
* PluginLogManager
* This class encapsulates a Log4J Hierarchy and centralizes all Logger access.
* @author Manoel Marques
*/
public class PluginLogManager {
private IPath stateLocation;
private Hierarchy hierarchy;
private HashMap<String, ILogListener> hookedPlugins = new HashMap<String, ILogListener>();
private LoggingHelper helper;
private class PluginEventListener implements HierarchyEventListener {
/**
* 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(Category cat, Appender appender) {
if (appender instanceof PluginFileAppender) {
((PluginFileAppender)appender).setStateLocation(stateLocation);
}
}
/**
* Called when a appender is removed from for a particular level.
* Does nothing.
* @param category level
* @param appender appender added for this level
*/
public void removeAppenderEvent(Category cat, Appender appender) {
}
}
/**
* Creates a new PluginLogManager. Saves the plug-in log and state location.
* Creates a new Hierarchy and add a new PluginEventListener to it.
* Configure the hierarchy with the properties passed.
* Add this object to the list of active plug-in log managers.
* @param plugin the plug-in object
* @param properties log configuration properties
*/
public PluginLogManager(Plugin plugin, LoggingHelper helper, final URL log4jUrl) {
this.stateLocation = plugin.getStateLocation();
this.hierarchy = new Hierarchy(new RootLogger(Level.DEBUG));
this.hierarchy.addHierarchyEventListener(new PluginEventListener());
LogManager.setRepositorySelector(new RepositorySelector() {
public LoggerRepository getLoggerRepository() {
return hierarchy;
}
}, "hibernate-tools"); //$NON-NLS-1$
ExecutionContext ec = new DefaultExecutionContext("logConfiguration", getClass().getClassLoader()); //$NON-NLS-1$
ec.execute(new Command(){
@Override
public Object execute() {
OptionConverter.selectAndConfigure(log4jUrl, null, hierarchy);
return null;
}});
this.helper = helper;
helper.addLogManager(this);
}
/**
* Hooks a plug-in into this PluginLogManager. When the hooked plug-in uses the
* Eclipse log API, it will be channeled to this logging framework.
* @param id logger name (usually the the plug-in id)
* @param pluginLog plug-in log
*/
public boolean hookPlugin(String id, ILog pluginLog) {
synchronized(this.hookedPlugins) {
if (pluginLog == null || id == null || this.hookedPlugins.containsKey(id))
return false;
PluginLogListener listener = new PluginLogListener(pluginLog,getLogger(id));
this.hookedPlugins.put(id,listener);
}
return true;
}
/**
* Unhooks a plug-in from this PluginLogManager. The Eclipse log API
* won't be channeled to this logging framework anymore.
* @param id logger name (usually the the plug-in id)
*/
public boolean unHookPlugin(String id) {
synchronized(this.hookedPlugins) {
if (id == null || !this.hookedPlugins.containsKey(id))
return false;
PluginLogListener listener = (PluginLogListener) this.hookedPlugins.get(id);
listener.dispose();
this.hookedPlugins.remove(id);
}
return true;
}
/**
* Checks if this PluginLogManager is disabled for this level.
* @param level level value
* @return boolean true if it is disabled
*/
public boolean isDisabled(int level) {
return this.hierarchy.isDisabled(level);
}
/**
* Enable logging for logging requests with level l or higher.
* By default all levels are enabled.
* @param level level object
*/
public void setThreshold(Level level) {
this.hierarchy.setThreshold(level);
}
/**
* The string version of setThreshold(Level level)
* @param level level string
*/
public void setThreshold(String level) {
this.hierarchy.setThreshold(level);
}
/**
* Get the repository-wide threshold.
* @return Level
*/
public Level getThreshold() {
return this.hierarchy.getThreshold();
}
/**
* Returns a new logger instance named as the first parameter
* using the default factory. If a logger of that name already exists,
* then it will be returned. Otherwise, a new logger will be instantiated
* and then linked with its existing ancestors as well as children.
* @param name logger name
* @return Logger
*/
public Logger getLogger(String name) {
return this.hierarchy.getLogger(name);
}
/**
* The same as getLogger(String name) but using a factory instance instead of
* a default factory.
* @param name logger name
* @param factory factory instance
* @return Logger
*/
public Logger getLogger(String name, LoggerFactory factory) {
return this.hierarchy.getLogger(name,factory);
}
/**
* Returns the root of this hierarchy.
* @return Logger
*/
public Logger getRootLogger() {
return this.hierarchy.getRootLogger();
}
/**
* Checks if this logger exists.
* @return Logger
*/
public Logger exists(String name) {
return this.hierarchy.exists(name);
}
/**
* Removes appenders and disposes the logger hierarchy
*
*/
public void shutdown() {
internalShutdown();
helper.removeLogManager(this);
}
/**
* Used by LoggingHelper to shutdown without removing it from the LoggingHelper list
*
*/
void internalShutdown() {
synchronized(this.hookedPlugins) {
Iterator<String> it = this.hookedPlugins.keySet().iterator();
while (it.hasNext()) {
String id = it.next();
PluginLogListener listener = (PluginLogListener) this.hookedPlugins.get(id);
listener.dispose();
}
this.hookedPlugins.clear();
}
this.hierarchy.shutdown();
}
/**
* Returns all the loggers in this manager.
* @return Enumeration logger enumeration
*/
public Enumeration<?> getCurrentLoggers() {
return this.hierarchy.getCurrentLoggers();
}
/**
* Resets configuration values to its defaults.
*
*/
public void resetConfiguration() {
this.hierarchy.resetConfiguration();
}
}