package org.jboss.windup.config.operation;
import java.util.Set;
import org.ocpsoft.logging.Logger;
import org.ocpsoft.logging.Logger.Level;
import org.ocpsoft.rewrite.config.DefaultOperationBuilder;
import org.ocpsoft.rewrite.context.EvaluationContext;
import org.ocpsoft.rewrite.event.Rewrite;
import org.ocpsoft.rewrite.param.ParameterStore;
import org.ocpsoft.rewrite.param.Parameterized;
import org.ocpsoft.rewrite.param.ParameterizedPattern;
import org.ocpsoft.rewrite.param.RegexParameterizedPatternBuilder;
/**
* Logging utility class. Usage:
* <code>
* Log.message(Level.INFO, "Client requested path: {p}")
* </code>
*
* @see {@link Log#message(Level, String)}
*/
public class Log extends DefaultOperationBuilder implements Parameterized
{
private final Logger log;
private final Level level;
private final RegexParameterizedPatternBuilder messageBuilder;
private Log(Logger log, Level level, String message)
{
Class<?> caller = findClassCaller();
if (caller == null)
caller = Log.class;
log = Logger.getLogger(caller);
if (level == null)
level = Level.INFO;
if (message == null)
message = "(null)";
this.log = log;
this.level = level;
this.messageBuilder = new RegexParameterizedPatternBuilder(message);
}
private Log(Level level, String message)
{
this(null, level, message);
}
/**
* Log a message at the given {@link Level}.
* <p>
* The message may be parameterized:
* <p>
* For example, assuming a given {@link Condition} has been configured to use a parameter "p"}:
* <p>
* <code>
* Path.matches("/{p}")
* </code>
* <p>
* The parameter "p" may be referenced in the log message:
* <p>
* <code>
* Log.message(Level.INFO, "Client requested path: {p}")
* </code>
* <p>
*
* @param level the log {@link Level} to which the message be written
* @param message {@link ParameterizedPattern} to be written to the log.
*
* @see {@link ConfigurationRuleParameterBuilder#where(String)}
*/
public static Log message(Level level, String message)
{
return new Log(level, message);
}
public static Log message(Class<?> cls, Level level, String message)
{
return new Log(Logger.getLogger(cls), level, message);
}
@Override
public void perform(Rewrite event, EvaluationContext context)
{
// Quite verbose. TODO: ... See https://github.com/ocpsoft/logging/issues/1
switch (level)
{
case TRACE:
if (log.isTraceEnabled())
log.trace(messageBuilder.build(event, context));
break;
case DEBUG:
if (log.isDebugEnabled())
log.debug(messageBuilder.build(event, context));
break;
case INFO:
if (log.isInfoEnabled())
log.info(messageBuilder.build(event, context));
break;
case WARN:
if (log.isWarnEnabled())
log.warn(messageBuilder.build(event, context));
break;
case ERROR:
if (log.isErrorEnabled())
log.error(messageBuilder.build(event, context));
break;
}
}
@Override
public Set<String> getRequiredParameterNames()
{
return messageBuilder.getRequiredParameterNames();
}
@Override
public void setParameterStore(ParameterStore store)
{
messageBuilder.setParameterStore(store);
}
@Override
public String toString()
{
return "LOG[" + level + ", " + messageBuilder.toString() + "]";
}
/**
* Finds the calling class - looks for most recent call outside of this class (and descendants).
*/
private static Class<? extends StackTraceElement> findClassCaller()
{
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for( int i = 2; i < stackTrace.length; i++ )
{
StackTraceElement call = stackTrace[i];
if (!Log.class.isAssignableFrom(call.getClass()))
return call.getClass();
}
return null;
}
}