package org.mobicents.slee.runtime.facilities; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.slee.InvalidArgumentException; import javax.slee.facilities.TraceLevel; import javax.slee.facilities.Tracer; import javax.slee.management.NotificationSource; import org.mobicents.slee.container.management.jmx.TraceMBeanImpl; /** * This class holds tracers for sources. By default it create root tracer. It * implicitly creates ancestor tracers for requested name. It holds reference * TraceName->TracerImpl. It also associates parent to a child.<br> * Start time:19:20:19 2009-03-09<br> * Project: mobicents-jainslee-server-core<br> * * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski</a> * */ public class TracerStorage { private final ConcurrentHashMap<String, TracerImpl> tracers = new ConcurrentHashMap<String, TracerImpl>(); private final MNotificationSource notificationSource; private final TraceMBeanImpl traceFacility; public TracerStorage(NotificationSource notificationSource, TraceMBeanImpl traceFacility) { super(); this.notificationSource = new MNotificationSource(notificationSource); this.traceFacility = traceFacility; TracerImpl rootTracer = new TracerImpl(this.notificationSource, this.traceFacility); tracers.put(rootTracer.getTracerName(), rootTracer); } public void setTracerLevel(TraceLevel lvl, String tracerName) throws InvalidArgumentException { // FIXME: JDOC of TraceMBean - description of class show example // that setTraceLevel creates tracer, we handle creation elswhere if (!isTracerDefined(tracerName)) { throw new InvalidArgumentException("No tracer definition with name: " + tracerName + ", for notification source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs"); } TracerImpl tracer = this.tracers.get(tracerName); if (tracer.getParentTracerName() == null) { throw new InvalidArgumentException("Can not set root tracer level for source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs"); } tracer.setTraceLevel(lvl); } public void unsetTracerLevel(String tracerName) throws InvalidArgumentException { if (!isTracerDefined(tracerName)) { throw new InvalidArgumentException("No tracer definition with name: " + tracerName + ", for notification source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs"); } TracerImpl tracer = this.tracers.get(tracerName); if (tracer.getParentTracerName() == null) { throw new InvalidArgumentException("Can not unset root tracer level for source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs"); } tracer.unsetTraceLevel(); } public TraceLevel getTracerLevel(String tracerName) throws InvalidArgumentException { if (!isTracerDefined(tracerName)) { throw new InvalidArgumentException("No tracer definition with name: " + tracerName + ", for notification source: " + this.notificationSource + ". See section 13.3 of JSLEE 1.1 specs"); } TracerImpl tracer = this.tracers.get(tracerName); return tracer.getTraceLevel(); } /** * This method raturns tracer names of tracers that have been requested * directly from NotificationSource (like through SbbContext, RAContext, * etc) * * @return */ public String[] getRequestedTracerNames() { Set<String> names = new HashSet<String>(); for (TracerImpl t : this.tracers.values()) { if (t.isRequestedBySource()) names.add(t.getTracerName()); } if(names.size()==0) return new String[0]; return names.toArray(new String[names.size()]); } /** * This method returns tracer names that have been defined explicitly via * setTraceLevel from TraceMBean * * @return */ public String[] getDefinedTracerNames() { Set<String> names = new HashSet<String>(); for (TracerImpl t : this.tracers.values()) { if (t.isExplicitlySetTracerLevel()) names.add(t.getTracerName()); } if(names.size()==0) return new String[0]; return names.toArray(new String[names.size()]); } /** * This method can be called multiple times. * * @param tracerName * @param requestedBySource * @return * @throws IllegalArgumentException */ public Tracer createTracer(String tracerName, boolean requestedBySource) throws InvalidArgumentException { // FIXME: this is double check, in some cases. TracerImpl.checkTracerName(tracerName, this.notificationSource.getNotificationSource()); TracerImpl t = tracers.get(tracerName); if (t == null) { // FIXME do we really need to create parents? String[] split = tracerName.split("\\."); String parentName = null; String currentName = ""; for (String s : split) { if (parentName == null) { // first loop parentName = currentName; currentName = s; } else { parentName = currentName; currentName = currentName + "." + s; } // This could happen when we have org.mobicents tracers create, // and now request org.mobicents.Foo if (this.tracers.containsKey(currentName)) { continue; } t = new TracerImpl(currentName, parentName, this.notificationSource, this.traceFacility); TracerImpl u = this.tracers.putIfAbsent(t.getTracerName(), t); if (u != null) { t = u; } } } if (requestedBySource) t.setRequestedBySource(requestedBySource); return t; } public boolean isTracerDefined(String tracerName) { return tracers.containsKey(tracerName); } }