ceki 2005/01/13 08:12:26 Modified: src/java/org/apache/log4j/joran/spi Interpreter.java src/java/org/apache/log4j/joran/action AppenderAction.java Action.java tests/src/java/org/apache/log4j/joran InterpreterTest.java tests build.xml tests/src/java/org/apache/log4j/joran/action TouchAction.java Added: src/java/org/apache/log4j/joran/spi ActionException.java tests/src/java/org/apache/log4j/joran SkippingInInterpreterTest.java tests/input/joran badEnd1.xml badEnd2.xml Removed: tests/input/joran exception2.xml Log: - By thowing an ActionExcetion an Action can now signal the joran Interpreter to skip processing children or following siblings. - Added corresponding test cases Revision Changes Path 1.3 +41 -10 logging-log4j/src/java/org/apache/log4j/joran/spi/Interpreter.java Index: Interpreter.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/joran/spi/Interpreter.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- Interpreter.java 12 Jan 2005 18:04:36 -0000 1.2 +++ Interpreter.java 13 Jan 2005 16:12:25 -0000 1.3 @@ -17,7 +17,6 @@ package org.apache.log4j.joran.spi; import org.apache.log4j.LogManager; -import org.apache.log4j.helpers.LogLog; import org.apache.log4j.joran.action.Action; import org.apache.log4j.joran.action.ImplicitAction; import org.apache.log4j.spi.Component; @@ -124,11 +123,6 @@ //LogLog.debug("in startElement <" + tagName + ">"); pattern.push(tagName); - - if(skip != null) { - System.out.println("Skipping nested <"+tagName+"> element."); - } - List applicableActionList = getApplicableActionList(pattern, atts); @@ -149,9 +143,14 @@ public void endElement(String namespaceURI, String localName, String qName) { List applicableActionList = (List) actionListStack.pop(); - if(skip != null && skip.equals(pattern)) { - System.out.println("Setting skipping to null"); - skip = null; + if(skip != null) { + //System.err.println("In End, pattern is "+pattern+", skip pattern "+skip); + if(skip.equals(pattern)) { + getLogger().info("Skipping discontinued. Normall processing will continue with the following element."); + skip = null; + } else { + getLogger().info("Skipping invoking end() method for <{}>.", localName); + } } else if (applicableActionList != EMPTY_LIST) { callEndAction(applicableActionList, getTagName(localName, qName)); } @@ -224,6 +223,11 @@ return; } + if(skip != null) { + getLogger().debug("Skipping invoking end() method for <{}>.", pattern); + return; + } + Iterator i = applicableActionList.iterator(); while (i.hasNext()) { @@ -233,9 +237,22 @@ // exceptions try { action.begin(ec, tagName, atts); + } catch( ActionException ae) { + switch(ae.getSkipCode()) { + case ActionException.SKIP_CHILDREN: + skip = (Pattern) pattern.clone(); + break; + case ActionException.SKIP_SIBLINGS: + skip = (Pattern) pattern.clone(); + // pretend the exception came from one level up. This will cause + // all children and following siblings elements to be skipped + skip.pop(); + break; + } + getLogger().info("Skip pattern set to: "+skip); } catch (Exception e) { skip = (Pattern) pattern.clone(); - System.out.println("Skip pattern set to "+skip); + getLogger().info("Skip pattern set to: "+skip); ec.addError(new ErrorItem("Exception in Action for tag <"+tagName+">", e)); } } @@ -255,8 +272,22 @@ // any eventual exceptions try { action.end(ec, tagName); + } catch( ActionException ae) { + switch(ae.getSkipCode()) { + case ActionException.SKIP_CHILDREN: + // after end() is called there can't be any children + break; + case ActionException.SKIP_SIBLINGS: + skip = (Pattern) pattern.clone(); + skip.pop(); + break; + } + getLogger().info("Skip pattern set to: "+skip); } catch(Exception e) { ec.addError(new ErrorItem("Exception in Action for tag <"+tagName+">", e)); + skip = (Pattern) pattern.clone(); + skip.pop(); // induce the siblings to be skipped + getLogger().info("Skip pattern set to <{}>.", skip); } } } 1.1 logging-log4j/src/java/org/apache/log4j/joran/spi/ActionException.java Index: ActionException.java =================================================================== /* * Copyright 1999,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.log4j.joran.spi; /** * By throwing an exception an action can signal the Interpreter to skip * processing, all the nested elements nested within the element throwing the * exception or skip all following sibling elements in the document. * * @author <a href="http://www.qos.ch/log4j/">Ceki Gulcu</a> */ public class ActionException extends Exception { /** * SKIP_CHILDREN signals the [EMAIL PROTECTED] Interpreter} to skip processing all the * nested elements contained within the element causing this ActionException. */ public static final int SKIP_CHILDREN = 1; /** * SKIP_SIBLINGS signals the [EMAIL PROTECTED] Interpreter} to skip processing all the * children of this element as well as all the siblings of this elements, * including any children they may have. */ public static final int SKIP_SIBLINGS = 2; final Throwable rootCause; final int skipCode; public ActionException(final int skipCode) { this(skipCode, null); } public ActionException(final int skipCode, final Throwable rootCause) { this.skipCode = skipCode; this.rootCause = rootCause; } public Throwable getCause() { return rootCause; } public int getSkipCode() { return skipCode; } } 1.20 +8 -2 logging-log4j/src/java/org/apache/log4j/joran/action/AppenderAction.java Index: AppenderAction.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/joran/action/AppenderAction.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- AppenderAction.java 12 Jan 2005 18:04:37 -0000 1.19 +++ AppenderAction.java 13 Jan 2005 16:12:26 -0000 1.20 @@ -20,6 +20,7 @@ import org.apache.log4j.Appender; import org.apache.log4j.helpers.Option; import org.apache.log4j.helpers.OptionConverter; +import org.apache.log4j.joran.spi.ActionException; import org.apache.log4j.joran.spi.ExecutionContext; import org.apache.log4j.spi.ErrorItem; import org.apache.log4j.spi.LoggerRepository; @@ -40,9 +41,13 @@ * The appender thus generated is placed in the ExecutionContext appender bag. */ public void begin( - ExecutionContext ec, String localName, Attributes attributes) { + ExecutionContext ec, String localName, Attributes attributes) throws ActionException { String className = attributes.getValue(CLASS_ATTRIBUTE); + // We are just beginning, reset variables + appender = null; + inError = false; + try { getLogger().debug("About to instantiate appender of type [{}]", className); @@ -72,12 +77,13 @@ getLogger().debug("Pushing appender on to the object stack."); ec.pushObject(appender); - } catch (Throwable oops) { + } catch (Exception oops) { inError = true; getLogger().error( "Could not create an Appender. Reported error follows.", oops); ec.addError( new ErrorItem("Could not create appender of type " + className + "].")); + throw new ActionException(ActionException.SKIP_CHILDREN, oops); } } 1.2 +3 -2 logging-log4j/src/java/org/apache/log4j/joran/action/Action.java Index: Action.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/joran/action/Action.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Action.java 12 Jan 2005 15:04:18 -0000 1.1 +++ Action.java 13 Jan 2005 16:12:26 -0000 1.2 @@ -16,6 +16,7 @@ package org.apache.log4j.joran.action; +import org.apache.log4j.joran.spi.ActionException; import org.apache.log4j.joran.spi.ExecutionContext; import org.apache.log4j.joran.spi.Interpreter; import org.apache.log4j.spi.ComponentBase; @@ -53,9 +54,9 @@ * the returned value is 'false', then child elements are ignored. */ public abstract void begin( - ExecutionContext ec, String name, Attributes attributes); + ExecutionContext ec, String name, Attributes attributes) throws ActionException ; - public abstract void end(ExecutionContext ec, String name); + public abstract void end(ExecutionContext ec, String name) throws ActionException; public String toString() { return this.getClass().getName(); 1.2 +2 -52 logging-log4j/tests/src/java/org/apache/log4j/joran/InterpreterTest.java Index: InterpreterTest.java =================================================================== RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/joran/InterpreterTest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- InterpreterTest.java 12 Jan 2005 18:04:35 -0000 1.1 +++ InterpreterTest.java 13 Jan 2005 16:12:26 -0000 1.2 @@ -38,10 +38,7 @@ import org.apache.log4j.joran.action.ActionConst; import org.apache.log4j.joran.action.AppenderAction; import org.apache.log4j.joran.action.AppenderRefAction; -import org.apache.log4j.joran.action.BadBeginAction; -import org.apache.log4j.joran.action.BadEndAction; import org.apache.log4j.joran.action.ConversionRuleAction; -import org.apache.log4j.joran.action.HelloAction; import org.apache.log4j.joran.action.LayoutAction; import org.apache.log4j.joran.action.LevelAction; import org.apache.log4j.joran.action.LoggerAction; @@ -49,7 +46,6 @@ import org.apache.log4j.joran.action.ParamAction; import org.apache.log4j.joran.action.RootLoggerAction; import org.apache.log4j.joran.action.StackCounterAction; -import org.apache.log4j.joran.action.TouchAction; import org.apache.log4j.joran.spi.ExecutionContext; import org.apache.log4j.joran.spi.Interpreter; import org.apache.log4j.joran.spi.Pattern; @@ -63,7 +59,6 @@ import org.xml.sax.SAXParseException; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Stack; @@ -389,52 +384,7 @@ assertEquals("Hello John Doe.", str); } - public void testException1() throws Exception { - logger.debug("Starting testException1"); - - RuleStore rs = new SimpleRuleStore(); - rs.addRule(new Pattern("test"), new NOPAction()); - rs.addRule(new Pattern("test/badBegin"), new BadBeginAction()); - rs.addRule(new Pattern("test/badBegin/touch"), new TouchAction()); - rs.addRule(new Pattern("test/hello"), new HelloAction()); - - Interpreter jp = new Interpreter(rs); - ExecutionContext ec = jp.getExecutionContext(); - Map omap = ec.getObjectMap(); - - SAXParser saxParser = createParser(); - saxParser.parse("file:input/joran/exception1.xml", jp); - List el = jp.getExecutionContext().getErrorList(); - for(int i = 0; i < el.size(); i++) { - ((ErrorItem) el.get(i)).dump(); - } - String str = (String) ec.getObjectMap().get("hello"); - assertEquals("Hello John Doe.", str); - } - - public void testException2() throws Exception { - logger.debug("Starting testException2"); - - RuleStore rs = new SimpleRuleStore(); - rs.addRule(new Pattern("test"), new NOPAction()); - rs.addRule(new Pattern("test/badEnd"), new BadEndAction()); - rs.addRule(new Pattern("test/hello"), new HelloAction()); - - Interpreter jp = new Interpreter(rs); - ExecutionContext ec = jp.getExecutionContext(); - Map omap = ec.getObjectMap(); - - SAXParser saxParser = createParser(); - saxParser.parse("file:input/joran/exception2.xml", jp); - List el = jp.getExecutionContext().getErrorList(); - for(int i = 0; i < el.size(); i++) { - ((ErrorItem) el.get(i)).dump(); - } - String str = (String) ec.getObjectMap().get("hello"); - assertEquals("Hello John Doe.", str); - } - - public static Test suite() { + public static Test RUNALLsuite() { TestSuite suite = new TestSuite(); //suite.addTest(new InterpreterTest("testIllFormedXML")); //suite.addTest(new InterpreterTest("testBasicLoop")); @@ -442,7 +392,7 @@ //suite.addTest(new InterpreterTest("testParsing2")); //suite.addTest(new InterpreterTest("testParsing3")) suite.addTest(new InterpreterTest("testException1")); - //suite.addTest(new InterpreterTest("testException2")); + suite.addTest(new InterpreterTest("testException2")); return suite; } 1.1 logging-log4j/tests/src/java/org/apache/log4j/joran/SkippingInInterpreterTest.java Index: SkippingInInterpreterTest.java =================================================================== /* * Copyright 1999,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.log4j.joran; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.joran.action.BadBeginAction; import org.apache.log4j.joran.action.BadEndAction; import org.apache.log4j.joran.action.HelloAction; import org.apache.log4j.joran.action.TouchAction; import org.apache.log4j.joran.spi.ExecutionContext; import org.apache.log4j.joran.spi.Interpreter; import org.apache.log4j.joran.spi.Pattern; import org.apache.log4j.joran.spi.RuleStore; import org.apache.log4j.joran.spi.SimpleRuleStore; import org.apache.log4j.spi.ErrorItem; import java.util.List; import java.util.Map; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; /** * Test the way Interpreter skips elements in case of exceptions thrown by * Actions. * * @author Ceki Gulcu */ public class SkippingInInterpreterTest extends TestCase { static final Logger logger = Logger.getLogger(SkippingInInterpreterTest.class); public SkippingInInterpreterTest(String name) { super(name); } /* * @see TestCase#setUp() */ protected void setUp() throws Exception { super.setUp(); Logger root = Logger.getRootLogger(); root.addAppender( new ConsoleAppender(new PatternLayout("%r %5p [%t] %c - %m%n"))); } /* * @see TestCase#tearDown() */ protected void tearDown() throws Exception { super.tearDown(); LogManager.shutdown(); } SAXParser createParser() throws Exception { SAXParserFactory spf = SAXParserFactory.newInstance(); return spf.newSAXParser(); } public void testChildrenSkipping() throws Exception { logger.debug("Starting testException1"); RuleStore rs = new SimpleRuleStore(); rs.addRule(new Pattern("test"), new NOPAction()); rs.addRule(new Pattern("test/badBegin"), new BadBeginAction()); rs.addRule(new Pattern("test/badBegin/touch"), new TouchAction()); rs.addRule(new Pattern("test/hello"), new HelloAction()); Interpreter jp = new Interpreter(rs); ExecutionContext ec = jp.getExecutionContext(); Map omap = ec.getObjectMap(); SAXParser saxParser = createParser(); saxParser.parse("file:input/joran/exception1.xml", jp); List el = jp.getExecutionContext().getErrorList(); for(int i = 0; i < el.size(); i++) { ((ErrorItem) el.get(i)).dump(); } String str = (String) ec.getObjectMap().get("hello"); assertEquals("Hello John Doe.", str); Integer i = (Integer) ec.getObjectMap().get(TouchAction.KEY); assertNull(i); } public void testSkipSiblings() throws Exception { logger.debug("Starting testException2"); RuleStore rs = new SimpleRuleStore(); rs.addRule(new Pattern("test"), new NOPAction()); rs.addRule(new Pattern("test/badEnd"), new BadEndAction()); rs.addRule(new Pattern("test/badEnd/touch"), new TouchAction()); rs.addRule(new Pattern("test/hello"), new HelloAction()); Interpreter jp = new Interpreter(rs); ExecutionContext ec = jp.getExecutionContext(); Map omap = ec.getObjectMap(); SAXParser saxParser = createParser(); saxParser.parse("file:input/joran/badEnd1.xml", jp); String str = (String) ec.getObjectMap().get("hello"); assertNull(str); Integer i = (Integer) ec.getObjectMap().get(TouchAction.KEY); assertEquals(2, i.intValue()); } public void testSkipSiblings2() throws Exception { logger.debug("Starting testException2"); RuleStore rs = new SimpleRuleStore(); rs.addRule(new Pattern("test"), new NOPAction()); rs.addRule(new Pattern("test/badEnd"), new BadEndAction()); rs.addRule(new Pattern("test/badEnd/touch"), new TouchAction()); rs.addRule(new Pattern("test/hello"), new HelloAction()); Interpreter jp = new Interpreter(rs); ExecutionContext ec = jp.getExecutionContext(); Map omap = ec.getObjectMap(); SAXParser saxParser = createParser(); saxParser.parse("file:input/joran/badEnd2.xml", jp); String str = (String) ec.getObjectMap().get("hello"); assertEquals("Hello John Doe.", str); Integer i = (Integer) ec.getObjectMap().get(TouchAction.KEY); assertNull(i); } public static Test RUNALLsuite() { TestSuite suite = new TestSuite(); suite.addTest(new SkippingInInterpreterTest("testChildrenSkipping")); suite.addTest(new SkippingInInterpreterTest("testNoSkipping")); return suite; } } 1.1 logging-log4j/tests/input/joran/badEnd1.xml Index: badEnd1.xml =================================================================== <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE test> <test> <!-- this action throws an exception in the Action.end method --> <badEnd> <touch/> <touch/> </badEnd> <hello name="John Doe"></hello> </test> 1.1 logging-log4j/tests/input/joran/badEnd2.xml Index: badEnd2.xml =================================================================== <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE test> <test> <isolate> <!-- badEnd throws an exception in the Action.end method --> <badEnd> <touch/> <touch/> </badEnd> </isolate> <hello name="John Doe"></hello> </test> 1.93 +13 -2 logging-log4j/tests/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/logging-log4j/tests/build.xml,v retrieving revision 1.92 retrieving revision 1.93 diff -u -r1.92 -r1.93 --- build.xml 12 Jan 2005 18:04:41 -0000 1.92 +++ build.xml 13 Jan 2005 16:12:26 -0000 1.93 @@ -215,7 +215,10 @@ <!-- ================================================================= --> <!-- Joran unit tests --> <!-- ================================================================= --> - <target name="Joran" depends="Pattern, SimpleStore, Interpreter, + <target name="Joran" depends="Pattern, + SimpleStore, + Interpreter, + SkipInInterpreter, JoranConfigurator"/> @@ -580,7 +583,15 @@ <test name="org.apache.log4j.joran.InterpreterTest" /> </junit> </target> - + + <target name="SkipInInterpreter" depends="check, build, cleanOutputDir"> + <junit printsummary="yes" fork="yes" haltonfailure="yes"> + <classpath refid="tests.classpath"/> + <formatter type="plain" usefile="false" /> + <test name="org.apache.log4j.joran.SkippingInInterpreterTest" /> + </junit> + </target> + <target name="JoranConfigurator" depends="check, build, cleanOutputDir"> <junit printsummary="yes" fork="yes" haltonfailure="yes"> <classpath refid="tests.classpath"/> 1.2 +9 -2 logging-log4j/tests/src/java/org/apache/log4j/joran/action/TouchAction.java Index: TouchAction.java =================================================================== RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/joran/action/TouchAction.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TouchAction.java 12 Jan 2005 18:04:36 -0000 1.1 +++ TouchAction.java 13 Jan 2005 16:12:26 -0000 1.2 @@ -24,7 +24,8 @@ public class TouchAction extends Action { - + public static String KEY = "touched"; + public TouchAction() { } /** @@ -32,7 +33,13 @@ * */ public void begin(ExecutionContext ec, String name, Attributes attributes) { - ec.getObjectMap().put("touch", "x"); + + Integer i = (Integer) ec.getObjectMap().get(KEY); + if(i == null) { + ec.getObjectMap().put(KEY, new Integer(1)); + } else { + ec.getObjectMap().put(KEY, new Integer(i.intValue()+1)); + } } /**
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]