/*
* This file is part of aion-emu <aion-emu.com>.
*
* aion-emu is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* aion-emu 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with aion-emu. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aionemu.commons.services;
import java.io.File;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Handler;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import org.apache.log4j.Hierarchy;
import org.apache.log4j.xml.DOMConfigurator;
import com.aionemu.commons.log4j.JuliToLog4JHandler;
import com.aionemu.commons.log4j.ThrowableAsMessageAwareFactory;
import com.aionemu.commons.log4j.exceptions.Log4jInitializationError;
/**
* This class represents simple wrapper for loggers that initializes logging system.
* <p/>
*
* Default {@link org.apache.log4j.spi.LoggerFactory} can by configured by system property
* {@value #LOGGER_FACTORY_CLASS_PROPERTY}
* <p/>
*
* Default logger factory is {@link com.aionemu.commons.log4j.ThrowableAsMessageAwareFactory}
*
* @author SoulKeeper
*/
public class LoggingService
{
/**
* Property that represents {@link org.apache.log4j.spi.LoggerFactory} class
*/
public static final String LOGGER_FACTORY_CLASS_PROPERTY = "log4j.loggerfactory";
/**
* Default log4j configuration file
*/
public static final String LOGGER_CONFIG_FILE = "config/log4j.xml";
/**
* Is Logging initialized or not?
*/
private static boolean initialized;
/**
* Initializes logging system with {@link #LOGGER_CONFIG_FILE default} config file
*
* @throws com.aionemu.commons.log4j.exceptions.Log4jInitializationError
* if can't initialize logging
*/
public static void init() throws Log4jInitializationError
{
File f = new File(LOGGER_CONFIG_FILE);
if(!f.exists())
{
throw new Log4jInitializationError("Missing file " + f.getPath());
}
try
{
init(f.toURI().toURL());
}
catch(MalformedURLException e)
{
throw new Log4jInitializationError("Can't initalize logging", e);
}
}
/**
* Initializes logging system with config file from URL
*
* @param url
* config file location
* @throws com.aionemu.commons.log4j.exceptions.Log4jInitializationError
* if can't initialize logging
*/
public static void init(URL url) throws Log4jInitializationError
{
synchronized(LoggingService.class)
{
if(initialized)
{
return;
}
else
{
initialized = true;
}
}
try
{
DOMConfigurator.configure(url);
}
catch(Exception e)
{
throw new Log4jInitializationError("Can't initialize logging", e);
}
overrideDefaultLoggerFactory();
// Initialize JULI to Log4J bridge
Logger logger = LogManager.getLogManager().getLogger("");
for(Handler h : logger.getHandlers())
{
logger.removeHandler(h);
}
logger.addHandler(new JuliToLog4JHandler());
}
/**
* This method uses some reflection to hack default log4j log facrory.
* <p/>
*
* Log4j uses this Hierarchy for loggers that don't have exact name match and element categoryFactory for loggers
* with names that matches specified names in log4j.xml.
* <p/>
*
* See log4j.xml for detailed description of Log4j behaviour.
*/
private static void overrideDefaultLoggerFactory()
{
// Hack here, we have to overwrite default logger factory
Hierarchy lr = (Hierarchy) org.apache.log4j.LogManager.getLoggerRepository();
try
{
Field field = lr.getClass().getDeclaredField("defaultFactory");
field.setAccessible(true);
String cn = System.getProperty(LOGGER_FACTORY_CLASS_PROPERTY, ThrowableAsMessageAwareFactory.class
.getName());
Class<?> c = Class.forName(cn);
field.set(lr, c.newInstance());
field.setAccessible(false);
}
catch(NoSuchFieldException e)
{
// never thrown
e.printStackTrace();
}
catch(IllegalAccessException e)
{
// never thrown
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
throw new Log4jInitializationError("Can't found log4j logger factory class", e);
}
catch(InstantiationException e)
{
throw new Log4jInitializationError("Can't instantiate log4j logger factory", e);
}
}
}