You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ce...@apache.org on 2004/03/31 21:02:15 UTC
cvs commit: logging-log4j/tests/input/joran parser2.xml
ceki 2004/03/31 11:02:14
Modified: src/java/org/apache/joran ExecutionContext.java
src/java/org/apache/joran/action NestComponentIA.java
Action.java
tests build.xml
tests/input/joran parser2.xml
Added: src/java/org/apache/joran Interpreter.java
tests/src/java/org/apache/joran InterpreterTest.java
Removed: src/java/org/apache/joran JoranParser.java
tests/src/java/org/apache/joran JoranParserTest.java
Log:
- Renamed JoranParser to Interpreter.
- Implicit actions now work for SAX based element handling.
Revision Changes Path
1.4 +3 -3 logging-log4j/src/java/org/apache/joran/ExecutionContext.java
Index: ExecutionContext.java
===================================================================
RCS file: /home/cvs/logging-log4j/src/java/org/apache/joran/ExecutionContext.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ExecutionContext.java 27 Feb 2004 16:47:28 -0000 1.3
+++ ExecutionContext.java 31 Mar 2004 19:02:14 -0000 1.4
@@ -40,9 +40,9 @@
Vector errorList;
Properties substProperties;
- JoranParser joranParser;
+ Interpreter joranParser;
- public ExecutionContext(JoranParser joranParser) {
+ public ExecutionContext(Interpreter joranParser) {
this.joranParser = joranParser;
objectStack = new Stack();
objectMap = new HashMap(5);
@@ -57,7 +57,7 @@
return errorList;
}
- public JoranParser getJoranParser() {
+ public Interpreter getJoranParser() {
return joranParser;
}
1.1 logging-log4j/src/java/org/apache/joran/Interpreter.java
Index: Interpreter.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.joran;
import org.apache.joran.action.*;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
public class Interpreter extends DefaultHandler {
static final Logger logger = Logger.getLogger(Interpreter.class);
private static List EMPTY_LIST = new Vector(0);
private RuleStore ruleStore;
private ExecutionContext ec;
private ArrayList implicitActions;
Pattern pattern;
Locator locator;
/**
* The <code>actionListStack</code> contains a list of actions that are
* executing for the given XML element.
*
* A list of actions is pushed by the {link #startElement} and popped by
* {@link #endElement}.
*
*/
Stack actionListStack;
Interpreter(RuleStore rs) {
ruleStore = rs;
ec = new ExecutionContext(this);
implicitActions = new ArrayList(3);
pattern = new Pattern();
actionListStack = new Stack();
}
public ExecutionContext getExecutionContext() {
return ec;
}
public void startDocument() {
System.out.println(" in JP startDocument");
}
public void startElement(
String namespaceURI, String localName, String qName, Attributes atts) {
String x = null;
String tagName = getTagName(localName, qName);
logger.debug("in startElement <" + tagName + ">");
pattern.push(tagName);
List applicableActionList = getapplicableActionList(pattern);
if (applicableActionList != null) {
actionListStack.add(applicableActionList);
callBeginAction(applicableActionList, tagName, atts);
} else {
actionListStack.add(EMPTY_LIST);
logger.debug("no applicable action for <"+tagName+">.");
}
}
public void endElement(String namespaceURI, String localName, String qName) {
List applicableActionList = (List) actionListStack.pop();
if (applicableActionList != EMPTY_LIST) {
callEndAction(applicableActionList, getTagName(localName, qName));
}
// given that we always push, we must also pop the pattern
pattern.pop();
}
public Locator getDocumentLocator() {
return locator;
}
public void setDocumentLocator(Locator l) {
locator = l;
}
String getTagName(String localName, String qName) {
String tagName = localName;
if ((tagName == null) || (tagName.length() < 1)) {
tagName = qName;
}
return tagName;
}
public void addImplcitAction(ImplicitAction ia) {
implicitActions.add(ia);
}
/**
* Check if any implicit actions are applicable. As soon as an applicable
* action is found, it is returned. Thus, the returned list will have at most
* one element.
*/
List lookupImplicitAction(ExecutionContext ec, Pattern pattern) {
int len = implicitActions.size();
for (int i = 0; i < len; i++) {
ImplicitAction ia = (ImplicitAction) implicitActions.get(i);
if (ia.isApplicable(ec, pattern.peekLast())) {
List actionList = new ArrayList(1);
actionList.add(ia);
return actionList;
}
}
return null;
}
/**
* Return the list of applicable patterns for this
*/
List getapplicableActionList(Pattern pattern) {
List applicableActionList = ruleStore.matchActions(pattern);
//logger.debug("set of applicable patterns: " + applicableActionList);
if (applicableActionList == null) {
applicableActionList = lookupImplicitAction(ec, pattern);
}
return applicableActionList;
}
void callBeginAction(
List applicableActionList, String tagName, Attributes atts) {
if (applicableActionList == null) {
return;
}
Iterator i = applicableActionList.iterator();
while (i.hasNext()) {
Action action = (Action) i.next();
action.begin(ec, tagName, atts);
}
}
void callEndAction(List applicableActionList, String tagName) {
if (applicableActionList == null) {
return;
}
//logger.debug("About to call end actions on node: <" + localName + ">");
Iterator i = applicableActionList.iterator();
while (i.hasNext()) {
Action action = (Action) i.next();
action.end(ec, tagName);
}
}
public RuleStore getRuleStore() {
return ruleStore;
}
public void setRuleStore(RuleStore ruleStore) {
this.ruleStore = ruleStore;
}
}
1.1 logging-log4j/tests/src/java/org/apache/joran/InterpreterTest.java
Index: InterpreterTest.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.
*/
/*
* Created on Aug 24, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package org.apache.joran;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.joran.action.NestComponentIA;
import org.apache.joran.action.NewRuleAction;
import org.apache.joran.action.ParamAction;
import org.apache.joran.action.StackCounterAction;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
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.ConversionRuleAction;
import org.apache.log4j.joran.action.LayoutAction;
import org.apache.log4j.joran.action.LevelAction;
import org.apache.log4j.joran.action.LoggerAction;
import org.apache.log4j.joran.action.RootLoggerAction;
import java.util.HashMap;
import java.util.Stack;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/**
* @author ceki
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class InterpreterTest extends TestCase {
static final Logger logger = Logger.getLogger(InterpreterTest.class);
/**
* Constructor for JoranParserTestCase.
* @param name
*/
public InterpreterTest(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();
}
/**
* Tests the basic looping contruct in Interpreter.
*
* The parser is set up to push 2 string objects for each element encountered.
* The results are compared with a witness stack.
*/
public void testBasicLoop() throws Exception {
RuleStore rs = new SimpleRuleStore();
rs.addRule(
new Pattern("log4j:configuration"), new StackCounterAction());
rs.addRule(
new Pattern("log4j:configuration/root"), new StackCounterAction());
rs.addRule(
new Pattern("log4j:configuration/root/level"), new StackCounterAction());
Interpreter jp = new Interpreter(rs);
ExecutionContext ec = jp.getExecutionContext();
SAXParser saxParser = createParser();
saxParser.parse("file:input/joran/basicLoop.xml", jp);
Stack witness = new Stack();
witness.push("log4j:configuration-begin");
witness.push("root-begin");
witness.push("level-begin");
witness.push("level-end");
witness.push("root-end");
witness.push("log4j:configuration-end");
assertEquals(witness, ec.getObjectStack());
}
/**
* This test verifies that <logger>, <root> and embedded <level> elements
* are handled correctly.
*/
public void testParsing1() throws Exception {
logger.debug("Starting testLoop");
RuleStore rs = new SimpleRuleStore();
logger.debug("pattern: " + new Pattern("log4j:configuration/logger"));
rs.addRule(new Pattern("log4j:configuration/logger"), new LoggerAction());
rs.addRule(
new Pattern("log4j:configuration/logger/level"), new LevelAction());
rs.addRule(
new Pattern("log4j:configuration/root"), new RootLoggerAction());
rs.addRule(
new Pattern("log4j:configuration/root/level"), new LevelAction());
Interpreter jp = new Interpreter(rs);
ExecutionContext ec = jp.getExecutionContext();
HashMap omap = ec.getObjectMap();
omap.put(ActionConst.APPENDER_BAG, new HashMap());
ec.pushObject(LogManager.getLoggerRepository());
SAXParser saxParser = createParser();
saxParser.parse("file:input/joran/parser1.xml", jp);
Logger rootLogger = LogManager.getLoggerRepository().getRootLogger();
assertSame(Level.WARN, rootLogger.getLevel());
Logger asdLogger = LogManager.getLoggerRepository().getLogger("asd");
assertSame(Level.DEBUG, asdLogger.getLevel());
assertEquals(2, ec.getErrorList().size());
String e0 = (String) ec.getErrorList().get(0);
if(!e0.startsWith("No 'name' attribute in element")) {
fail("Expected error string [No 'name' attribute in element]");
}
String e1 = (String) ec.getErrorList().get(1);
if(!e1.startsWith("For element <level>")) {
fail("Expected error string [For element <level>]");
}
}
/**
* This tests verifies the handling of logger, logger/level, root, root/level
* logger/appender-ref, root/appender-ref, appender, appender/layout,
* and param actions.
*
* These cover a fairly significant part of log4j configuration directives.
*
* */
public void testParsing2() throws Exception {
logger.debug("Starting testLoop2");
RuleStore rs = new SimpleRuleStore();
rs.addRule(new Pattern("log4j:configuration/logger"), new LoggerAction());
rs.addRule(
new Pattern("log4j:configuration/logger/level"), new LevelAction());
rs.addRule(
new Pattern("log4j:configuration/root"), new RootLoggerAction());
rs.addRule(
new Pattern("log4j:configuration/root/level"), new LevelAction());
rs.addRule(
new Pattern("log4j:configuration/logger/appender-ref"),
new AppenderRefAction());
rs.addRule(
new Pattern("log4j:configuration/root/appender-ref"),
new AppenderRefAction());
rs.addRule(
new Pattern("log4j:configuration/appender"), new AppenderAction());
rs.addRule(
new Pattern("log4j:configuration/appender/layout"), new LayoutAction());
rs.addRule(new Pattern("*/param"), new ParamAction());
Interpreter jp = new Interpreter(rs);
ExecutionContext ec = jp.getExecutionContext();
HashMap omap = ec.getObjectMap();
omap.put(ActionConst.APPENDER_BAG, new HashMap());
ec.pushObject(LogManager.getLoggerRepository());
SAXParser saxParser = createParser();
saxParser.parse("file:input/joran/parser2.xml", jp);
// the following assertions depend on the contensts of parser2.xml
Logger rootLogger = LogManager.getLoggerRepository().getRootLogger();
assertSame(Level.DEBUG, rootLogger.getLevel());
Logger asdLogger = LogManager.getLoggerRepository().getLogger("asd");
assertSame(Level.INFO, asdLogger.getLevel());
FileAppender a1Back = (FileAppender) asdLogger.getAppender("A1");
assertFalse("a1.append should be false", a1Back.getAppend());
assertEquals("output/temp.A1", a1Back.getFile());
PatternLayout plBack = (PatternLayout) a1Back.getLayout();
assertEquals("%-5p %c{2} - %m%n", plBack.getConversionPattern());
a1Back = (FileAppender) rootLogger.getAppender("A1");
assertEquals(3, ec.getErrorList().size());
String e0 = (String) ec.getErrorList().get(0);
if(!e0.startsWith("No 'name' attribute in element")) {
fail("Expected error string [No 'name' attribute in element]");
}
String e1 = (String) ec.getErrorList().get(1);
if(!e1.startsWith("For element <level>")) {
fail("Expected error string [For element <level>]");
}
String e2 = (String) ec.getErrorList().get(2);
if(!e2.startsWith("Could not find an AppenderAttachable at the top of execution stack. Near")) {
fail("Expected error string [Could not find an AppenderAttachable at the top of execution stack. Near]");
}
}
public void testParsing3() throws Exception {
logger.debug("Starting testLoop3");
RuleStore rs = new SimpleRuleStore();
rs.addRule(new Pattern("log4j:configuration/logger"), new LoggerAction());
rs.addRule(
new Pattern("log4j:configuration/logger/level"), new LevelAction());
rs.addRule(
new Pattern("log4j:configuration/root"), new RootLoggerAction());
//rs.addRule(
//new Pattern("log4j:configuration/root/level"), new LevelAction());
rs.addRule(
new Pattern("log4j:configuration/logger/appender-ref"),
new AppenderRefAction());
rs.addRule(
new Pattern("log4j:configuration/root/appender-ref"),
new AppenderRefAction());
rs.addRule(
new Pattern("log4j:configuration/appender"), new AppenderAction());
rs.addRule(
new Pattern("log4j:configuration/appender/layout"), new LayoutAction());
rs.addRule(new Pattern("*/param"), new ParamAction());
Interpreter jp = new Interpreter(rs);
jp.addImplcitAction(new NestComponentIA());
ExecutionContext ec = jp.getExecutionContext();
HashMap omap = ec.getObjectMap();
omap.put(ActionConst.APPENDER_BAG, new HashMap());
ec.pushObject(LogManager.getLoggerRepository());
logger.debug("About to parse doc");
SAXParser saxParser = createParser();
saxParser.parse("file:input/joran/parser3.xml", jp);
// the following assertions depend on the contensts of parser3.xml
}
public void testNewConversionWord() throws Exception {
logger.debug("Starting testNewConversionWord");
RuleStore rs = new SimpleRuleStore();
rs.addRule(
new Pattern("log4j:configuration/appender"), new AppenderAction());
rs.addRule(
new Pattern("log4j:configuration/appender/layout"), new LayoutAction());
rs.addRule(
new Pattern("log4j:configuration/appender/layout/conversionRule"),
new ConversionRuleAction());
rs.addRule(new Pattern("*/param"), new ParamAction());
Interpreter jp = new Interpreter(rs);
jp.addImplcitAction(new NestComponentIA());
ExecutionContext ec = jp.getExecutionContext();
HashMap omap = ec.getObjectMap();
omap.put(ActionConst.APPENDER_BAG, new HashMap());
ec.pushObject(LogManager.getLoggerRepository());
SAXParser saxParser = createParser();
saxParser.parse("file:input/joran/conversionRule.xml", jp);
HashMap appenderBag =
(HashMap) ec.getObjectMap().get(ActionConst.APPENDER_BAG);
Appender appender = (Appender) appenderBag.get("A1");
PatternLayout pl = (PatternLayout) appender.getLayout();
assertEquals("org.apache.log4j.toto", pl.getRuleRegistry().get("toto"));
}
public void testNewRule1() throws Exception {
logger.debug("Starting testNewConversionWord");
RuleStore rs = new SimpleRuleStore();
rs.addRule(
new Pattern("log4j:configuration/newRule"),
new NewRuleAction());
Interpreter jp = new Interpreter(rs);
ExecutionContext ec = jp.getExecutionContext();
HashMap omap = ec.getObjectMap();
omap.put(ActionConst.APPENDER_BAG, new HashMap());
ec.pushObject(LogManager.getLoggerRepository());
SAXParser saxParser = createParser();
saxParser.parse("file:input/joran/newRule1.xml", jp);
String str = (String) ec.getObjectMap().get("hello");
assertEquals("Hello John Doe.", str);
}
public static Test suite() {
TestSuite suite = new TestSuite();
//suite.addTest(new InterpreterTest("testBasicLoop"));
//suite.addTest(new InterpreterTest("testParsing1"));
//suite.addTest(new InterpreterTest("testParsing2"));
suite.addTest(new InterpreterTest("testParsing3"));
return suite;
}
}
1.7 +2 -0 logging-log4j/src/java/org/apache/joran/action/NestComponentIA.java
Index: NestComponentIA.java
===================================================================
RCS file: /home/cvs/logging-log4j/src/java/org/apache/joran/action/NestComponentIA.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- NestComponentIA.java 31 Mar 2004 13:13:15 -0000 1.6
+++ NestComponentIA.java 31 Mar 2004 19:02:14 -0000 1.7
@@ -92,6 +92,8 @@
}
public void end(ExecutionContext ec, String tagName) {
+
+ logger.debug("entering end method");
if (inError) {
return;
}
1.9 +3 -3 logging-log4j/src/java/org/apache/joran/action/Action.java
Index: Action.java
===================================================================
RCS file: /home/cvs/logging-log4j/src/java/org/apache/joran/action/Action.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- Action.java 31 Mar 2004 13:13:15 -0000 1.8
+++ Action.java 31 Mar 2004 19:02:14 -0000 1.9
@@ -17,7 +17,7 @@
package org.apache.joran.action;
import org.apache.joran.ExecutionContext;
-import org.apache.joran.JoranParser;
+import org.apache.joran.Interpreter;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
@@ -66,7 +66,7 @@
}
protected int getColumnNumber(ExecutionContext ec) {
- JoranParser jp = ec.getJoranParser();
+ Interpreter jp = ec.getJoranParser();
Locator locator = jp.getDocumentLocator();
if(locator != null) {
return locator.getColumnNumber();
@@ -75,7 +75,7 @@
}
protected int getLineNumber(ExecutionContext ec) {
- JoranParser jp = ec.getJoranParser();
+ Interpreter jp = ec.getJoranParser();
Locator locator = jp.getDocumentLocator();
if(locator != null) {
return locator.getLineNumber();
1.48 +3 -3 logging-log4j/tests/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/logging-log4j/tests/build.xml,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -r1.47 -r1.48
--- build.xml 27 Mar 2004 06:46:27 -0000 1.47
+++ build.xml 31 Mar 2004 19:02:14 -0000 1.48
@@ -133,7 +133,7 @@
<!-- ================================================================= -->
<!-- Joran unit tests -->
<!-- ================================================================= -->
- <target name="Joran" depends="Pattern, SimpleStore, JoranParser"/>
+ <target name="Joran" depends="Pattern, SimpleStore, Interpreter"/>
<!-- ================================================================= -->
@@ -453,11 +453,11 @@
</target>
- <target name="JoranParser" depends="build, cleanOutputDir">
+ <target name="Interpreter" depends="build, cleanOutputDir">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<classpath refid="tests.classpath"/>
<formatter type="plain" usefile="false" />
- <test name="org.apache.joran.JoranParserTest" />
+ <test name="org.apache.joran.InterpreterTest" />
</junit>
</target>
1.3 +1 -1 logging-log4j/tests/input/joran/parser2.xml
Index: parser2.xml
===================================================================
RCS file: /home/cvs/logging-log4j/tests/input/joran/parser2.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- parser2.xml 31 Mar 2004 14:04:08 -0000 1.2
+++ parser2.xml 31 Mar 2004 19:02:14 -0000 1.3
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration>
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+<log4j:configuration>
<appender name="A1" class="org.apache.log4j.FileAppender">
asdfasdf
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org