/*******************************************************************************
*
* Copyright (c) 2010-2011 Sonatype, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
*
*
*
*******************************************************************************/
package org.hudsonci.maven.eventspy_30;
import org.apache.maven.eventspy.EventSpy;
import org.codehaus.plexus.logging.AbstractLogger;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.LoggerManager;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.codehaus.plexus.logging.Logger.LEVEL_DEBUG;
import static org.codehaus.plexus.logging.Logger.LEVEL_DISABLED;
import static org.codehaus.plexus.logging.Logger.LEVEL_ERROR;
import static org.codehaus.plexus.logging.Logger.LEVEL_FATAL;
import static org.codehaus.plexus.logging.Logger.LEVEL_INFO;
import static org.codehaus.plexus.logging.Logger.LEVEL_WARN;
/**
* Bridges logging over {@link org.hudsonci.maven.eventspy.common.Callback}.
*
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
* @since 2.1.0
*/
public class LoggerManagerImpl
implements LoggerManager
{
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerManagerImpl.class);
private final EventSpy spy;
private final LoggerManager delegate;
private int threshold = LEVEL_DEBUG;
public LoggerManagerImpl(final EventSpy spy, final LoggerManager delegate) {
this.spy = checkNotNull(spy);
this.delegate = checkNotNull(delegate);
}
//
// TODO: Figure out if we need to invoke more delegate methods... to get the default logging working.
//
public void setThreshold(final int threshold) {
this.threshold = threshold;
}
/**
* Same as {@link #setThreshold}, we do not track logger adapters.
*/
public void setThresholds(final int threshold) {
setThreshold(threshold);
}
public int getThreshold() {
return threshold;
}
public int getThreshold(final String role) {
return getThreshold();
}
/**
* Not supported.
*/
public int getThreshold(final String role, final String roleHint) {
return getThreshold();
}
public Logger getLoggerForComponent(final String role) {
return getLoggerForComponent(role, null);
}
public Logger getLoggerForComponent(final String role, final String roleHint) {
checkNotNull(role);
Logger logger = new LoggerImpl(getThreshold(), toLoggerName(role, roleHint),
delegate.getLoggerForComponent(role, roleHint));
log.debug("Created logger: {}", logger);
return logger;
}
/**
* Not supported.
*/
public void returnComponentLogger(final String role, final String hint) {
if (log.isDebugEnabled()) {
log.debug("Ignoring logger return; name={}", toLoggerName(role,hint));
}
}
public void returnComponentLogger(final String role) {
returnComponentLogger(role, null);
}
/**
* Not supported.
*/
public int getActiveLoggerCount() {
return -1;
}
private String toLoggerName(final String role, final String roleHint) {
if (roleHint == null) {
return role;
}
else {
return String.format("%s#%s", role, roleHint);
}
}
/**
* Container for log event details.
*/
public static class LogEvent
{
private final Logger logger;
private final int level;
private final String message;
private final Throwable cause;
public LogEvent(final Logger logger, final int level, final String message, final Throwable cause) {
this.logger = checkNotNull(logger);
checkArgument(level >= LEVEL_DEBUG && level <= LEVEL_DISABLED);
this.level = level;
this.message = checkNotNull(message);
// cause might be null
this.cause = cause;
}
public Logger getLogger() {
return logger;
}
public int getLevel() {
return level;
}
public String getMessage() {
return message;
}
public Throwable getCause() {
return cause;
}
public void delegate() {
switch (level) {
case LEVEL_DEBUG:
logger.debug(message, cause);
break;
case LEVEL_INFO:
logger.info(message, cause);
break;
case LEVEL_WARN:
logger.warn(message, cause);
break;
case LEVEL_ERROR:
logger.error(message, cause);
break;
case LEVEL_FATAL:
logger.fatalError(message, cause);
break;
default:
throw new Error();
}
}
@Override
public String toString() {
return "LogEvent{" +
logger.getName() +
": level=" + level +
", message='" + message + '\'' +
", cause=" + cause +
'}';
}
}
/**
* Logger which turns method calls into {@link LogEvent} instances for processing.
*/
private class LoggerImpl
extends AbstractLogger
{
private Logger delegate;
public LoggerImpl(final int threshold, final String name, final Logger delegate) {
super(threshold, name);
this.delegate = checkNotNull(delegate);
}
private void emitLog(final int level, final String message, final Throwable cause) {
if (threshold <= level) {
LogEvent event = new LogEvent(delegate, level, message, cause);
// FIXME: Figure out how to pipe to handler.
// FIXME: Log events can come in before we are fully opened, as well as after we are closed
// FIXME: May also avoid threshold check here and always pass on and only delegate if in range?
// FIXME: If we are going to leave the output as-is then probably always want to delegate here?
log.debug("{}", event);
}
}
public void debug(final String message, final Throwable cause) {
emitLog(LEVEL_DEBUG, message, cause);
}
public void info(final String message, final Throwable cause) {
emitLog(LEVEL_INFO, message, cause);
}
public void warn(final String message, final Throwable cause) {
emitLog(LEVEL_WARN, message, cause);
}
public void error(final String message, final Throwable cause) {
emitLog(LEVEL_ERROR, message, cause);
}
public void fatalError(final String message, final Throwable cause) {
emitLog(LEVEL_FATAL, message, cause);
}
public Logger getChildLogger(final String name) {
return new LoggerImpl(getThreshold(), String.format("%s.%s", getName(), name), delegate.getChildLogger(name));
}
@Override
public String toString() {
return "LoggerImpl{" +
"name='" + getName() + '\'' +
", threshold=" + threshold +
'}';
}
}
}