
Author: ceki Date: Wed Aug 6 22:14:52 2008 New Revision: 1736 Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/StatusListenerAction.java Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java Log: Relates to LBCLASSIC-59 LBCLASSIC-58 ongoing work on StatusListner support Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/BasicStatusManager.java Wed Aug 6 22:14:52 2008 @@ -27,13 +27,13 @@ // reading SynchronizedCollection the mutex is the returned // synchronized list, we make use of this fact in getCopyOfStatusList - List<Status> statusList = Collections + final List<Status> statusList = Collections .synchronizedList(new ArrayList<Status>()); int level = Status.INFO; // reading SynchronizedCollection the mutex is the returned // synchronized list, we make use of this fact in getCopyOfStatusListnerList - List<StatusListener> statusListenerList = Collections + final List<StatusListener> statusListenerList = Collections .synchronizedList(new ArrayList<StatusListener>()); /** @@ -52,6 +52,15 @@ level = newStatus.getLevel(); } statusList.add(newStatus); + fireStatusAddEvent(newStatus); + } + + private void fireStatusAddEvent(Status status) { + synchronized (statusListenerList) { + for(StatusListener sl : statusListenerList) { + sl.addStatusEvent(status); + } + } } public synchronized List<Status> getCopyOfStatusList() { @@ -73,7 +82,7 @@ } public void remove(StatusListener listener) { - statusListenerList.add(listener); + statusListenerList.remove(listener); } public List<StatusListener> getCopyOfStatusListenerList() { Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java Wed Aug 6 22:14:52 2008 @@ -17,12 +17,13 @@ import ch.qos.logback.core.joran.action.ActionConst; import ch.qos.logback.core.joran.action.AppenderAction; import ch.qos.logback.core.joran.action.AppenderRefAction; +import ch.qos.logback.core.joran.action.ContextPropertyAction; import ch.qos.logback.core.joran.action.ConversionRuleAction; -import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; +import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; import ch.qos.logback.core.joran.action.NewRuleAction; import ch.qos.logback.core.joran.action.ParamAction; -import ch.qos.logback.core.joran.action.ContextPropertyAction; +import ch.qos.logback.core.joran.action.StatusListenerAction; import ch.qos.logback.core.joran.action.SubstitutionPropertyAction; import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.joran.spi.Interpreter; @@ -58,6 +59,9 @@ rs.addRule(new Pattern("configuration/conversionRule"), new ConversionRuleAction()); + rs.addRule(new Pattern("configuration/statusListener"), + new StatusListenerAction()); + rs.addRule(new Pattern("configuration/appender"), new AppenderAction()); rs.addRule(new Pattern("configuration/appender/appender-ref"), new AppenderRefAction()); Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AppenderAction.java Wed Aug 6 22:14:52 2008 @@ -34,12 +34,20 @@ @SuppressWarnings("unchecked") public void begin( InterpretationContext ec, String localName, Attributes attributes) throws ActionException { - String className = attributes.getValue(CLASS_ATTRIBUTE); - // We are just beginning, reset variables appender = null; inError = false; + String className = attributes.getValue(CLASS_ATTRIBUTE); + if(OptionHelper.isEmpty(className)) { + addError( + "Missing class name for appender. Near [" + + localName + "] line " + getLineNumber(ec)); + inError = true; + return; + } + + try { addInfo("About to instantiate appender of type ["+className+"]"); @@ -66,7 +74,6 @@ // add the appender just created to the appender bag. appenderBag.put(appenderName, appender); - //getLogger().debug("Pushing appender on to the object stack."); ec.pushObject(appender); } catch (Exception oops) { inError = true; Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/StatusListenerAction.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/StatusListenerAction.java Wed Aug 6 22:14:52 2008 @@ -0,0 +1,72 @@ +/** + * LOGBack: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 1999-2006, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ + +package ch.qos.logback.core.joran.action; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.util.OptionHelper; + + +public class StatusListenerAction extends Action { + + + boolean inError = false; + StatusListener statusListener = null; + + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { + inError = false; + String className = attributes.getValue(CLASS_ATTRIBUTE); + if(OptionHelper.isEmpty(className)) { + addError( + "Missing class name for statusListener. Near [" + + name + "] line " + getLineNumber(ec)); + inError = true; + return; + } + + try { + statusListener = (StatusListener) OptionHelper.instantiateByClassName( + className, StatusListener.class, context); + ec.getContext().getStatusManager().add(statusListener); + ec.pushObject(statusListener); + } catch (Exception e) { + inError = true; + addError( + "Could not create an StatusListener of type ["+className+"].", e); + throw new ActionException(ActionException.SKIP_CHILDREN, e); + } + + } + + public void finish(InterpretationContext ec) { + } + + public void end(InterpretationContext ec, String e) { + if (inError) { + return; + } + if (statusListener instanceof LifeCycle) { + ((LifeCycle) statusListener).start(); + } + Object o = ec.peekObject(); + if (o != statusListener) { + addWarn( + "The object at the of the stack is not the statusListener pushed earlier."); + } else { + ec.popObject(); + } + } +}