package org.infoglue.deliver.controllers.kernel.impl.simple;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.infoglue.cms.controllers.kernel.impl.simple.BaseController;
import org.infoglue.cms.entities.kernel.BaseEntityVO;
public class LogModifierController extends BaseController
{
private static final Logger classLogger = Logger.getLogger(LogModifierController.class);
private static LogModifierController controller;
private Map<Logger, ModificationInformation> currentModifications;
private Appender debugAppender;
private Map<Integer, Level> levels;
private static synchronized void initController()
{
if (controller == null)
{
controller = new LogModifierController();
}
}
public static LogModifierController getController()
{
if (controller == null)
{
initController();
}
return controller;
}
private LogModifierController()
{
this.currentModifications = new HashMap<Logger, ModificationInformation>();
initDebugAppender();
}
private void initDebugAppender()
{
if (debugAppender == null)
{
debugAppender = Logger.getLogger("org.infoglue.debug-dummy").getAppender("INFOGLUE-DEBUG");
if (debugAppender == null)
{
classLogger.warn("Did not find a debug appender. There should be an appender named INFOGLUE-DEBUG and it should be referenced by a category named org.infoglue.debug-dummy. Will use a Console appender instead.");
Layout layout = new PatternLayout("%d{dd MMM yyyy HH:mm:ss.SSS} [Debug log] [%-5p] [%t] [%c] - %m%n");
ConsoleAppender appender = new ConsoleAppender(layout);
appender.setThreshold(Level.TRACE);
debugAppender = appender;
}
}
}
private void populateLevels()
{
classLogger.debug("Populating levels");
levels = new TreeMap<Integer, Level>();
levels.put(Level.TRACE.toInt(), Level.TRACE);
levels.put(Level.DEBUG.toInt(), Level.DEBUG);
levels.put(Level.INFO.toInt(), Level.INFO);
levels.put(Level.WARN.toInt(), Level.WARN);
levels.put(Level.ERROR.toInt(), Level.ERROR);
levels.put(Level.FATAL.toInt(), Level.FATAL);
levels.put(Level.OFF.toInt(), Level.OFF);
}
public Map<Integer, Level> getLevels()
{
if (levels == null)
{
populateLevels();
}
return levels;
}
public void changeLogLevel(String loggerName, Integer loggerLevel)
{
Logger logger = Logger.getLogger(loggerName);
Level level = loggerLevel == null ? null : Level.toLevel(loggerLevel);
changeLogLevel(logger, level);
}
public void changeLogLevel(String loggerName, Level level)
{
Logger logger = Logger.getLogger(loggerName);
changeLogLevel(logger, level);
}
public void changeLogLevel(Logger logger, Integer loggerLevel)
{
Level level = loggerLevel == null ? null : Level.toLevel(loggerLevel);
changeLogLevel(logger, level);
}
public synchronized void changeLogLevel(Logger logger, Level level)
{
if (logger == null)
{
classLogger.warn("Tried to change logging level without the required information. Logger: " + logger + ". Level " + level);
}
else
{
if (level == null)
{
clearModifications(logger);
}
else
{
ModificationInformation currentState = currentModifications.get(logger);
if (currentState == null)
{
classLogger.info("Logger has not been modified. Logger: " + logger.getName() + ". New level: " + level);
currentState = new ModificationInformation();
currentState.originalLevel = logger.getLevel();
currentState.currentLevel = level;
logger.setLevel(level);
currentModifications.put(logger, currentState);
logger.addAppender(debugAppender);
}
else
{
classLogger.info("Logger has been modified. Logger: " + logger.getName() + ". New level: " + level);
currentState.currentLevel = level;
logger.setLevel(level);
}
}
}
}
public void clearModifications(String loggerName)
{
clearModifications(Logger.getLogger(loggerName));
}
public synchronized void clearModifications(Logger logger)
{
ModificationInformation currentState = currentModifications.get(logger);
if (currentState == null)
{
classLogger.info("No modifications to clear in logger. Logger: " + logger.getName());
}
else
{
classLogger.debug("Clearing modifications for Logger. Logger: " + logger.getName() + ". Modificatons: " + currentState);
logger.setLevel(currentState.originalLevel);
logger.removeAppender(debugAppender);
currentModifications.remove(logger);
}
}
public Set<Logger> getCurrentModifications()
{
return currentModifications.keySet();
}
@Override
public BaseEntityVO getNewVO()
{
return null;
}
private static class ModificationInformation
{
Level currentLevel;
Level originalLevel;
@Override
public String toString()
{
return "[currentLevel: " + currentLevel + ", originalLevel: " + originalLevel + "]";
}
}
}