/**
* Copyright (C) 2001-2003 France Telecom R&D
*
* 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 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.objectweb.util.monolog.wrapper.log4jMini;
import org.apache.log4j.Category;
import org.apache.log4j.PropertyConfigurator;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Handler;
import org.objectweb.util.monolog.api.HandlerFactory;
import org.objectweb.util.monolog.api.Level;
import org.objectweb.util.monolog.api.LevelFactory;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.util.monolog.api.LoggerFactory;
import org.objectweb.util.monolog.api.TopicalLogger;
import org.objectweb.util.monolog.api.MonologFactory;
import org.objectweb.util.monolog.wrapper.common.Configurable;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;
import java.util.Enumeration;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileNotFoundException;
public class MonologLoggerFactory implements MonologFactory {
static Hashtable monologCategories;
public static final String LOG4J_CF_PROP = "log4j.categoryFactory";
public static final String LOG4J_CF_VALUE
= "org.objectweb.util.monolog.wrapper.log4j.MonologCategoryFactory";
/**
* This static code initializes the BasicLevel fields.
*/
static {
BasicLevel.INHERIT = -1;
BasicLevel.DEBUG = org.apache.log4j.Priority.DEBUG_INT;
BasicLevel.INFO = org.apache.log4j.Priority.INFO_INT;
BasicLevel.WARN = org.apache.log4j.Priority.WARN_INT;
BasicLevel.ERROR = org.apache.log4j.Priority.ERROR_INT;
BasicLevel.FATAL = org.apache.log4j.Priority.FATAL_INT;
BasicLevel.LEVEL_INHERIT = new LevelImpl("INHERIT", BasicLevel.INHERIT);
BasicLevel.LEVEL_DEBUG = new LevelImpl("DEBUG", BasicLevel.DEBUG);
BasicLevel.LEVEL_INFO = new LevelImpl("INFO", BasicLevel.INFO);
BasicLevel.LEVEL_WARN = new LevelImpl("WARN", BasicLevel.WARN);
BasicLevel.LEVEL_ERROR = new LevelImpl("ERROR", BasicLevel.ERROR);
BasicLevel.LEVEL_FATAL = new LevelImpl("FATAL", BasicLevel.FATAL);
monologCategories = new Hashtable();
Category root = Category.getRoot();
}
/**
* This field references the level instances by their names.<br/>
* key = a level name<br/>
* value = the unique Level instance linked to the name.
*/
protected Hashtable nameToLevel = null;
/**
* This field reference the level names by their integer value.<br/>
* key = a java.lang.Integer which the value is the level<br/>
* value = a String or an ArrayList of String. The strings represent the
* name which match to the integer value. Indeed both name can be associated
* to the same integer value.
*/
protected Hashtable intToNames = null;
/**
* This field references the handler instance by their names.<br/>
* key = a String object which is an handler name.
* value = the unique handler instance which has the key for name.
*/
protected Hashtable handlers = null;
/**
* The root logger of the logger hierarchy
*/
protected Logger rootLogger = null;
public MonologLoggerFactory() {
intToNames = new Hashtable();
nameToLevel = new Hashtable();
defineDefaultLevels();
handlers = new Hashtable();
rootLogger = new MonologCategory(Category.getRoot());
}
/**
* It initializes the default monolog level:
* <ul>
* <li>DEBUG: 10 000</li>
* <li>INFO: 20 000</li>
* <li>WARN: 30 000</li>
* <li>ERROR: 40 000</li>
* <li>FATAL: 50 000</li>
* </ul>
*/
protected void defineDefaultLevels() {
defineLevel("INHERIT", -1);
defineLevel("DEBUG", 10000);
defineLevel("INFO", 20000);
defineLevel("WARN", 30000);
defineLevel("ERROR", 40000);
defineLevel("FATAL", 50000);
}
// IMPLEMENTATION OF THE Configurable INTERFACE //
/**
* This method permits to configure the factory.
*/
public void configure(Properties prop) throws Exception {
if (prop==null) {
return;
}
String conf = prop.getProperty(LOG_CONFIGURATION_TYPE,
prop.getProperty("log4jConfiguration", DEFAULT));
if (PROPERTY.equals(conf)) {
// Fetch the configuration file name
String filename = prop.getProperty(LOG_CONFIGURATION_FILE,
prop.getProperty("log4jConfigurationFile", ""));
Properties log4jfileprop = null;
// Check if the file name designs a path valid into the
// classpath, or designs a path valid into the file system.
// In both case load the property file
if (prop.getProperty(LOG_CONFIGURATION_FILE_USE_CLASSPATH, "false")
.equalsIgnoreCase("true")
|| prop.getProperty("findFileInClassPath", "false")
.equalsIgnoreCase("true")) {
if (!"log4j.properties".equals(filename)) {
// valid into the classpath
log4jfileprop = getProperties(filename);
log4jfileprop.put(LOG4J_CF_PROP, LOG4J_CF_VALUE);
PropertyConfigurator.configure(log4jfileprop);
}
// else the file is already loaded by the Category class
}
else {
// valid into the file system
log4jfileprop = new Properties();
log4jfileprop.load(new FileInputStream(filename));
log4jfileprop.put(LOG4J_CF_PROP, LOG4J_CF_VALUE);
PropertyConfigurator.configure(log4jfileprop);
}
}
else if (XML.equals(conf)) {
throw new Exception(
"xml log4jConfiguration is not suported in the log4jME wrapper");
}
}
// Return null if properties are not reachable
private Properties getProperties(String name) throws IOException {
InputStream is = ClassLoader.getSystemResourceAsStream(name);
if (is != null) {
Properties props = new Properties();
props.load(is);
return props;
}
throw new FileNotFoundException("Not found in classpath: " + name);
}
// IMPLEMENTATION OF INTERFACE LoggerFactory
public Logger[] getLoggers() {
Logger[] logs = new TopicalLogger[monologCategories.size() + 1];
logs[0] = rootLogger;
int i=1;
for(Enumeration en = monologCategories.elements(); en.hasMoreElements();) {
logs[i++] = (TopicalLogger) en.nextElement();
}
return logs;
}
public String getTopicPrefix() {
return null;
}
public Logger getLogger(String key) {
if (key == null || key.length() == 0 || key.equalsIgnoreCase("root")) {
return rootLogger;
}
Logger log = (Logger) monologCategories.get(key);
if (log == null) {
log = new MonologCategory(Category.getInstance(key));
monologCategories.put(key, log);
}
return log;
}
public synchronized Logger getLogger(String key, String rbn) {
return getLogger(key);
}
public String getResourceBundleName() {
return "";
}
public void setResourceBundleName(String rbn) {
}
// IMPLEMENTATION OF THE LevelFactory INTERFACE //
//-----------------------------------------------//
public Level defineLevel(String name, int value) {
return defineLevel(new LevelImpl(name, value));
}
public Level defineLevel(String name, String value) {
return defineLevel(new LevelImpl(name, value, this));
}
public Level getLevel(String name) {
return (Level) nameToLevel.get(name);
}
public Level getLevel(int value) {
Object temp = intToNames.get(new Integer(value));
if (temp == null) {
return null;
}
else if (temp instanceof String) {
return getLevel((String) temp);
}
else if (temp instanceof Vector) {
return getLevel((String) ((Vector) temp).elementAt(0));
}
return null;
}
public Level[] getLevels() {
if (nameToLevel==null) {
return new Level[0];
}
Level[] result = new Level[nameToLevel.size()];
int i = 0;
for (Enumeration e= nameToLevel.elements(); e.hasMoreElements() ; i++) {
result[i] = (Level)(e.nextElement());
}
return result;
}
public void removeLevel(String name) {
Level removed = (Level) nameToLevel.remove(name);
if (removed != null) {
Integer i = new Integer(removed.getIntValue());
Object temp = intToNames.get(i);
if (temp instanceof String) {
intToNames.remove(i);
}
else if (temp instanceof Vector) {
((Vector) temp).removeElement(name);
}
}
}
// OTHER METHODS //
//---------------//
/**
* Insert a level into the data structure.<br/>
* If the level name is already used with other integer value, the null
* value is returned.<br/>
* If the level name is already used with the same integer value, the level
* found in the data structure is returned.<br/>
*
* @param l the Level instance which must be inserted.
* @return the Level instance or a null value.
*/
private Level defineLevel(Level l) {
//System.out.println("def(" + l + ") begin");
String name = l.getName();
int value = l.getIntValue();
Level res = (Level) nameToLevel.get(name);
if (res != null) {
// The name is already defined.
return (res.getIntValue() == value ? res : null);
}
else {
res = l;
nameToLevel.put(name, res);
Integer i = new Integer(value);
Object temp = intToNames.get(i);
if (temp != null) {
if (temp instanceof String) {
if (!((String) temp).equalsIgnoreCase(name)) {
// The int value has already another name
// Add the new name to the other
Vector al = new Vector(5);
al.addElement(temp);
al.addElement(name);
intToNames.put(i, al);
}
}
else if (temp instanceof Vector) {
// The int value has already several another name
Vector al = (Vector) temp;
if (!al.contains(name)) {
// Add the new name to the others
al.addElement(name);
}
}
}
else {
// The int value does not have any name
intToNames.put(i, name);
}
}
//System.out.println("def(" + l + ") end");
return res;
}
// IMPLEMENTATION OF THE HandlerFactory INTERFACE //
//------------------------------------------------//
public Handler createHandler(String hn, String handlertype) {
Handler res = (Handler) handlers.get(hn);
if (res != null) {
return null;
}
res = new FileHandler(handlertype, hn);
handlers.put(hn, res);
return res;
}
public Handler[] getHandlers() {
if (handlers==null) {
return new Handler[0];
}
Handler[] result = new Handler[handlers.size()];
int i = 0;
for (Enumeration e= handlers.elements(); e.hasMoreElements() ; i++) {
result[i] = (Handler)(e.nextElement());
}
return result;
}
public Handler getHandler(String hn) {
return (Handler) handlers.get(hn);
}
public Handler removeHandler(String hn) {
return (Handler) handlers.remove(hn);
}
}