package org.mobicents.slee.runtime.facilities; import java.util.StringTokenizer; import javax.slee.InvalidArgumentException; import javax.slee.facilities.FacilityException; import javax.slee.facilities.TraceLevel; import javax.slee.facilities.Tracer; import javax.slee.management.NotificationSource; import javax.slee.management.TraceNotification; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.mobicents.slee.container.management.jmx.TraceMBeanImpl; /** * * Start time:21:04:04 2009-03-09<br> * Project: mobicents-jainslee-server-core<br> * Implementation of Tracer object that allows slee comopnents to send * notification on some interesting ocasions. * * @author <a href="mailto:baranowb@gmail.com">baranowb - Bartosz Baranowski</a> * @author martins */ public class TracerImpl implements Tracer { public static final TraceLevel DEFAULT_TRACE_LEVEL = TraceLevel.INFO; public final static String ROOT_TRACER_NAME = ""; private enum SpecificLevel { finer, config } private SpecificLevel specificLevel = null; private final Logger logger; private final MNotificationSource notificationSource; private final TraceMBeanImpl traceMBean; private final String name; private final String parentName; private boolean requestedBySource = false; /** * */ public TracerImpl(MNotificationSource notificationSource, TraceMBeanImpl traceMBean) { this(ROOT_TRACER_NAME, null, notificationSource, traceMBean); // specs require every root logger must have INFO level, but we don't // want that if log4j config imposes a WARN, ERROR or OFF level, even if // in that case we don't comply with the specs. this means tck will not // pass if log4j logger says INFO is not enabled (e.g. WARN level set) if (this.logger.isInfoEnabled()) { this.logger.setLevel(Level.INFO); } } /** * */ public TracerImpl(String name, String parentName, MNotificationSource notificationSource, TraceMBeanImpl traceMBean) { this.name = name; this.parentName = parentName; this.logger = Logger.getLogger(tracerNameToLog4JLoggerName(name, notificationSource.getNotificationSource())); this.notificationSource = notificationSource; this.traceMBean = traceMBean; } /** * Generates the log4j logger name for the tracer with specified named and notification source. * * @param tracerName * @param notificationSource * @return */ private String tracerNameToLog4JLoggerName(String tracerName, NotificationSource notificationSource) { return "javax.slee."+notificationSource.toString() + ( tracerName.equals(ROOT_TRACER_NAME) ? "" : ("." + tracerName) ); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#config(java.lang.String) */ public void config(String message) throws NullPointerException, FacilityException { sendNotification(TraceLevel.CONFIG, message, null); logger.info(message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#config(java.lang.String, java.lang.Throwable) */ public void config(String message, Throwable t) throws NullPointerException, FacilityException { sendNotification(TraceLevel.CONFIG, message, t); logger.info(message,t); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#fine(java.lang.String) */ public void fine(String message) throws NullPointerException, FacilityException { sendNotification(TraceLevel.FINE, message, null); logger.debug(message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#fine(java.lang.String, java.lang.Throwable) */ public void fine(String message, Throwable t) throws NullPointerException, FacilityException { sendNotification(TraceLevel.FINE, message, t); logger.debug(message,t); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#finer(java.lang.String) */ public void finer(String message) throws NullPointerException, FacilityException { sendNotification(TraceLevel.FINER, message, null); logger.debug(message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#finer(java.lang.String, java.lang.Throwable) */ public void finer(String message, Throwable t) throws NullPointerException, FacilityException { sendNotification(TraceLevel.FINER, message, t); logger.debug(message,t); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#finest(java.lang.String) */ public void finest(String message) throws NullPointerException, FacilityException { sendNotification(TraceLevel.FINEST, message, null); logger.trace(message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#finest(java.lang.String, java.lang.Throwable) */ public void finest(String message, Throwable t) throws NullPointerException, FacilityException { sendNotification(TraceLevel.FINEST, message, t); logger.trace(message,t); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#getParentTracerName() */ public String getParentTracerName() { return parentName; } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#getTraceLevel() */ public TraceLevel getTraceLevel() throws FacilityException { final Level level = logger.getEffectiveLevel(); if (level != null) { switch (level.toInt()) { case Level.DEBUG_INT: if (specificLevel == SpecificLevel.finer) { return TraceLevel.FINER; } else { return TraceLevel.FINE; } case Level.INFO_INT: if (specificLevel == SpecificLevel.config) { return TraceLevel.CONFIG; } else { return TraceLevel.INFO; } case Level.WARN_INT: specificLevel = null; return TraceLevel.WARNING; case Level.ERROR_INT: specificLevel = null; return TraceLevel.SEVERE; case Level.TRACE_INT: specificLevel = null; return TraceLevel.FINEST; case Level.OFF_INT: specificLevel = null; return TraceLevel.OFF; default: break; } }; specificLevel = null; return DEFAULT_TRACE_LEVEL; } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#getTracerName() */ public String getTracerName() { return name; } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#info(java.lang.String) */ public void info(String message) throws NullPointerException, FacilityException { sendNotification(TraceLevel.INFO, message, null); logger.info(message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#info(java.lang.String, java.lang.Throwable) */ public void info(String message, Throwable t) throws NullPointerException, FacilityException { sendNotification(TraceLevel.INFO, message, t); logger.info(message,t); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isConfigEnabled() */ public boolean isConfigEnabled() throws FacilityException { return isTraceable(TraceLevel.CONFIG); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isFineEnabled() */ public boolean isFineEnabled() throws FacilityException { return isTraceable(TraceLevel.FINE); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isFinerEnabled() */ public boolean isFinerEnabled() throws FacilityException { return isTraceable(TraceLevel.FINER); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isFinestEnabled() */ public boolean isFinestEnabled() throws FacilityException { return isTraceable(TraceLevel.FINEST); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isInfoEnabled() */ public boolean isInfoEnabled() throws FacilityException { return isTraceable(TraceLevel.INFO); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isSevereEnabled() */ public boolean isSevereEnabled() throws FacilityException { return isTraceable(TraceLevel.SEVERE); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isTraceable(javax.slee.facilities.TraceLevel) */ public boolean isTraceable(TraceLevel traceLevel) throws NullPointerException, FacilityException { if (traceLevel == null) { throw new NullPointerException("null trace level"); } return !this.getTraceLevel().isHigherLevel(traceLevel); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#isWarningEnabled() */ public boolean isWarningEnabled() throws FacilityException { return isTraceable(TraceLevel.WARNING); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#severe(java.lang.String) */ public void severe(String message) throws NullPointerException, FacilityException { sendNotification(TraceLevel.SEVERE, message, null); logger.error(message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#severe(java.lang.String, java.lang.Throwable) */ public void severe(String message, Throwable t) throws NullPointerException, FacilityException { sendNotification(TraceLevel.SEVERE, message, t); logger.error(message,t); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#trace(javax.slee.facilities.TraceLevel, java.lang.String) */ public void trace(TraceLevel traceLevel, String message) throws NullPointerException, IllegalArgumentException, FacilityException { sendNotification(traceLevel, message, null); logger.log(tracerToLog4JLevel(traceLevel), message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#trace(javax.slee.facilities.TraceLevel, java.lang.String, java.lang.Throwable) */ public void trace(TraceLevel traceLevel, String message, Throwable t) throws NullPointerException, IllegalArgumentException, FacilityException { sendNotification(traceLevel, message, t); logger.log(tracerToLog4JLevel(traceLevel), message,t); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#warning(java.lang.String) */ public void warning(String message) throws NullPointerException, FacilityException { sendNotification(TraceLevel.WARNING, message, null); logger.warn(message); } /* (non-Javadoc) * @see javax.slee.facilities.Tracer#warning(java.lang.String, java.lang.Throwable) */ public void warning(String message, Throwable t) throws NullPointerException, FacilityException { sendNotification(TraceLevel.WARNING, message, t); logger.warn(message,t); } /** * THis is internaly called, by 1.1 tracers * * @param src */ void sendNotification(javax.slee.facilities.TraceLevel level, String message, Throwable t) { if (!isTraceable(level)) { return; } traceMBean.sendNotification(new TraceNotification(notificationSource.getNotificationSource().getTraceNotificationType(), traceMBean, notificationSource.getNotificationSource(), getTracerName(), level, message, t, notificationSource.getNextSequence(), System.currentTimeMillis())); } /** * This checks if the specified tracer name is ok. * * @param tracerName * @param notificationSource * @throws NullPointerException * @throws InvalidArgumentException */ public static void checkTracerName(String tracerName, NotificationSource notificationSource) throws NullPointerException,InvalidArgumentException { if (tracerName.equals("")) { // This is root return; } StringTokenizer stringTokenizer = new StringTokenizer(tracerName, ".", true); String lastToken = null; while (stringTokenizer.hasMoreTokens()) { String token = stringTokenizer.nextToken(); if (lastToken == null) { // this is start lastToken = token; } if (lastToken.equals(token) && token.equals(".")) { throw new InvalidArgumentException("Passed tracer:" + tracerName + ", name for source: " + notificationSource + ", is illegal"); } lastToken = token; } if (lastToken.equals(".")) { throw new IllegalArgumentException("Passed tracer:" + tracerName + ", name for source: " + notificationSource + ", is illegal"); } } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Tracer{ notificationSource = "+notificationSource.getNotificationSource()+" , name = "+getTracerName()+" , parent = "+getParentTracerName()+" , level = "+getTraceLevel()+" }"; } private Level tracerToLog4JLevel(TraceLevel traceLevel) { if (traceLevel.isFine() || traceLevel.isFiner()) { return Level.DEBUG; } if (traceLevel.isInfo() || traceLevel.isConfig()) { return Level.INFO; } if (traceLevel.isFinest()) { return Level.TRACE; } if(traceLevel.isWarning()) { return Level.WARN; } if(traceLevel.isSevere()) { return Level.ERROR; } if(traceLevel.isOff()) { return Level.OFF; } return Level.INFO; } /** * @param level */ public void setTraceLevel(TraceLevel level) { if (level.isConfig()) { specificLevel = SpecificLevel.config; } else if (level.isFiner()) { specificLevel = SpecificLevel.finer; } logger.setLevel(tracerToLog4JLevel(level)); } /** * */ public void unsetTraceLevel() { logger.setLevel(null); specificLevel = null; } /** * @return */ public boolean isExplicitlySetTracerLevel() { if (getParentTracerName() == null) { // root return false; } else { // get level set in log4j return logger.getLevel() != null; } } /** * Sets * @param requestedBySource the requestedBySource to set */ public void setRequestedBySource(boolean requestedBySource) { this.requestedBySource = requestedBySource; } /** * Retrieves * @return the requestedBySource */ public boolean isRequestedBySource() { return requestedBySource; } }