[logback-dev] 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

noreply.seb at qos.ch noreply.seb at qos.ch
Wed Mar 14 20:44:42 CET 2007


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);
+    }
+  }
 }



More information about the logback-dev mailing list