svn commit: r1427 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic/joran logback-classic/src/main/java/ch/qos/logback/classic/joran/action logback-classic/src/test/input/joran logback-classic/src/test/java/ch/qos/logback/classic/joran logback-core/src/main/java/ch/qos/logback/core/joran logback-core/src/main/java/ch/qos/logback/core/joran/spi

Author: seb Date: Wed Mar 14 20:44:42 2007 New Revision: 1427 Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoadConfigurationFileAction.java logback/trunk/logback-classic/src/test/input/joran/invalidConfig.xml logback/trunk/logback-classic/src/test/input/joran/invalidRedirect.xml logback/trunk/logback-classic/src/test/input/joran/redirectConfig.xml logback/trunk/logback-classic/src/test/input/joran/redirectToInvalid.xml logback/trunk/logback-classic/src/test/input/joran/redirectWithSubst.xml logback/trunk/logback-classic/src/test/input/joran/simpleConfig.xml logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/LoadConfigurationFileTest.java Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java Log: Added include functionality to Joran. The <include> pattern used in a <configuration> pattern can have a "path" attribute with the path to a file that will be parsed and executed to configure logback. This attribute can be set with a property. Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java Wed Mar 14 20:44:42 2007 @@ -15,6 +15,7 @@ import ch.qos.logback.classic.joran.action.JMXConfiguratorAction; import ch.qos.logback.classic.joran.action.LayoutAction; import ch.qos.logback.classic.joran.action.LevelAction; +import ch.qos.logback.classic.joran.action.LoadConfigurationFileAction; import ch.qos.logback.classic.joran.action.LoggerAction; import ch.qos.logback.classic.joran.action.RootLoggerAction; import ch.qos.logback.core.joran.JoranConfiguratorBase; @@ -58,6 +59,7 @@ new LayoutAction()); rs.addRule(new Pattern("configuration/jmxConfigurator"), new JMXConfiguratorAction()); + rs.addRule(new Pattern("configuration/include"), new LoadConfigurationFileAction()); } } Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoadConfigurationFileAction.java ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoadConfigurationFileAction.java Wed Mar 14 20:44:42 2007 @@ -0,0 +1,88 @@ +/** + * Logback: the reliable, generic, 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.classic.joran.action; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.SaxEventRecorder; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.JoranException; + +public class LoadConfigurationFileAction extends Action { + + private static final String INCLUDED_TAG = "included"; + private static final String PATH_ATTR = "path"; + private SaxEventRecorder recorder; + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + + String attribute = attributes.getValue(PATH_ATTR); + if (attribute == null) { + addError("Path to configuration file to include is not set."); + return; + } + + String pathToFile; + + if (attribute.startsWith("$")) { + pathToFile = ec.subst(attribute); + } else { + pathToFile = attribute; + } + + try { + InputStream in = new FileInputStream(pathToFile); + parseAndRecord(in); + in.close(); + } catch (IOException ioe) { + String errMsg = "File [" + pathToFile + "] does not exist."; + addError(errMsg, ioe); + } catch (JoranException e) { + addError("Error while parsing file " + pathToFile + e); + } + + if (recorder.saxEventList.size() == 0) { + return; + } + + SaxEvent first = recorder.saxEventList.get(0); + if (first != null && first.qName.equalsIgnoreCase(INCLUDED_TAG)) { + recorder.saxEventList.remove(0); + } + + SaxEvent last = recorder.saxEventList.get(recorder.saxEventList.size()-1); + if (last != null && last.qName.equalsIgnoreCase(INCLUDED_TAG)) { + recorder.saxEventList.remove(recorder.saxEventList.size()-1); + } + + ec.getJoranInterpreter().addEvents(recorder.saxEventList); + } + + private void parseAndRecord(InputStream inputSource) throws JoranException { + recorder = new SaxEventRecorder(); + recorder.setContext(context); + recorder.recordEvents(inputSource); + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + // do nothing + } + +} Added: logback/trunk/logback-classic/src/test/input/joran/invalidConfig.xml ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/input/joran/invalidConfig.xml Wed Mar 14 20:44:42 2007 @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE included> + +<included> + <!-- This file is invalid on purpose. Do not correct it. --> + + <appender name="redirectConsole" + class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.classic.PatternLayout"> + <param name="Pattern" value="%d - %m%n" /> + </layout> + + + <root> + <level value="DEBUG" /> + <appender-ref ref="redirectConsole" /> + </root> + +</included> \ No newline at end of file Added: logback/trunk/logback-classic/src/test/input/joran/invalidRedirect.xml ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/input/joran/invalidRedirect.xml Wed Mar 14 20:44:42 2007 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE configuration> + +<configuration> + + <include path="toto" /> + +</configuration> Added: logback/trunk/logback-classic/src/test/input/joran/redirectConfig.xml ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/input/joran/redirectConfig.xml Wed Mar 14 20:44:42 2007 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE configuration> + +<configuration> + + <include path="src/test/input/joran/simpleConfig.xml" /> + +</configuration> Added: logback/trunk/logback-classic/src/test/input/joran/redirectToInvalid.xml ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/input/joran/redirectToInvalid.xml Wed Mar 14 20:44:42 2007 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE configuration> + +<configuration> + + <include path="src/test/input/joran/invalidConfig.xml" /> + +</configuration> Added: logback/trunk/logback-classic/src/test/input/joran/redirectWithSubst.xml ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/input/joran/redirectWithSubst.xml Wed Mar 14 20:44:42 2007 @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE configuration> + +<configuration> + <substitutionProperty name="path.to.file" + value="src/test/input/joran/simpleConfig.xml" /> + + <include path="${path.to.file}" /> + +</configuration> Added: logback/trunk/logback-classic/src/test/input/joran/simpleConfig.xml ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/input/joran/simpleConfig.xml Wed Mar 14 20:44:42 2007 @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE included> + +<included> + + <appender name="redirectConsole" + class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.classic.PatternLayout"> + <param name="Pattern" value="%d - %m%n" /> + </layout> + </appender> + + <root> + <level value="DEBUG" /> + <appender-ref ref="redirectConsole" /> + </root> + +</included> \ No newline at end of file Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/LoadConfigurationFileTest.java ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/LoadConfigurationFileTest.java Wed Mar 14 20:44:42 2007 @@ -0,0 +1,85 @@ +package ch.qos.logback.classic.joran; + +import junit.framework.TestCase; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.joran.action.LoadConfigurationFileAction; +import ch.qos.logback.classic.util.Constants; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.ConsoleAppender; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.Status; + +public class LoadConfigurationFileTest extends TestCase { + + LoggerContext context; + LoadConfigurationFileAction action; + + String filePath = Constants.TEST_DIR_PREFIX + + "input/joran/redirectConfig.xml"; + String invalidRedirect = Constants.TEST_DIR_PREFIX + + "input/joran/invalidRedirect.xml"; + String filePathWithSubst = Constants.TEST_DIR_PREFIX + + "input/joran/redirectWithSubst.xml"; + String redirectToInvalid = Constants.TEST_DIR_PREFIX + + "input/joran/redirectToInvalid.xml"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + context = new LoggerContext(); + action = new LoadConfigurationFileAction(); + action.setContext(context); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + action = null; + context = null; + } + + public void testLoadFileOK() throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + jc.doConfigure(filePath); + + verifyConfig(); + } + + public void testNoFileFound() throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + jc.doConfigure(invalidRedirect); + + assertEquals(3, context.getStatusManager().getCount()); + assertEquals(Status.ERROR, context.getStatusManager().getLevel()); + } + + public void testWithCorruptFile() throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + jc.doConfigure(redirectToInvalid); + + assertEquals(10, context.getStatusManager().getCount()); + assertEquals(Status.ERROR, context.getStatusManager().getLevel()); + } + + public void testWithSubst() throws JoranException { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + jc.doConfigure(filePathWithSubst); + + verifyConfig(); + } + + private void verifyConfig() { + Logger logger = context.getLogger(LoggerContext.ROOT_NAME); + Appender appender = (ConsoleAppender) logger.getAppender("redirectConsole"); + assertNotNull(appender); + PatternLayout layout = (PatternLayout) appender.getLayout(); + assertNotNull(layout); + assertEquals("%d - %m%n", layout.getPattern()); + } +} Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java ============================================================================== --- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java (original) +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/PackageTest.java Wed Mar 14 20:44:42 2007 @@ -17,7 +17,7 @@ TestSuite suite = new TestSuite(); suite.addTestSuite(BasicJoranTest.class); suite.addTestSuite(EvaluatorJoranTest.class); - + suite.addTestSuite(LoadConfigurationFileTest.class); return suite; } } \ No newline at end of file Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java Wed Mar 14 20:44:42 2007 @@ -85,7 +85,6 @@ InterpretationContext ec = interpreter.getExecutionContext(); ec.setContext(context); addImplicitRules(interpreter); - } final public void doConfigure(final InputSource inputSource) @@ -94,8 +93,7 @@ recorder.setContext(context); recorder.recordEvents(inputSource); buildInterpreter(); - EventPlayer player = new EventPlayer(interpreter); - player.play(recorder.saxEventList); + interpreter.play(recorder.saxEventList); } public void doConfigure(final List<SaxEvent> eventList) Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java Wed Mar 14 20:44:42 2007 @@ -19,14 +19,19 @@ public class EventPlayer { final Interpreter interpreter; - + List<SaxEvent> eventList; + int currentIndex; + public EventPlayer(Interpreter interpreter) { - this.interpreter = interpreter; + this.interpreter = interpreter; } public void play(List<SaxEvent> seList) { - - for(SaxEvent se : seList) { + eventList = seList; + SaxEvent se; + for(currentIndex = 0; currentIndex < eventList.size(); currentIndex++) { + se = eventList.get(currentIndex); + if(se instanceof StartEvent) { interpreter.startElement((StartEvent) se); // invoke fireInPlay after startElement processing @@ -45,4 +50,8 @@ } } + + public void addEvents(List<SaxEvent> eventList) { + this.eventList.addAll(currentIndex+2, eventList); + } } Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Interpreter.java Wed Mar 14 20:44:42 2007 @@ -23,6 +23,7 @@ import ch.qos.logback.core.joran.action.ImplicitAction; import ch.qos.logback.core.joran.event.BodyEvent; import ch.qos.logback.core.joran.event.EndEvent; +import ch.qos.logback.core.joran.event.SaxEvent; import ch.qos.logback.core.joran.event.StartEvent; import ch.qos.logback.core.spi.ContextAwareImpl; @@ -68,6 +69,7 @@ final private ContextAwareImpl cai; Pattern pattern; Locator locator; + EventPlayer player; /** * The <id>actionListStack</id> contains a list of actions that are executing @@ -93,6 +95,7 @@ implicitActions = new ArrayList<ImplicitAction>(3); pattern = new Pattern(); actionListStack = new Stack<List>(); + player = new EventPlayer(this); } public InterpretationContext getExecutionContext() { @@ -328,4 +331,14 @@ public RuleStore getRuleStore() { return ruleStore; } + + public void play(List<SaxEvent> eventList) { + player.play(eventList); + } + + public void addEvents(List<SaxEvent> eventList) { + if (player != null) { + player.addEvents(eventList); + } + } }
participants (1)
-
noreply.seb@qos.ch