[logback-dev] svn commit: r683 - in logback/trunk: logback-classic/examples/src/chapter1 logback-classic/examples/src/chapter4 logback-classic/examples/src/chapter5 logback-classic/src/main/java/ch/qos/logback/classic/joran logback-classic/src/main/java/ch/qos/logback/classic/net 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/action logback-core/src/main/java/ch/qos/logback/core/joran/spi logback-core/src/main/java/ch/qos/logback/core/spi logback-core/src/test/input/joran logback-core/src/test/java/ch/qos/logback/core logback-core/src/test/java/ch/qos/logback/core/joran logback-core/src/test/java/ch/qos/logback/core/joran/action

noreply.ceki at qos.ch noreply.ceki at qos.ch
Sun Oct 15 19:44:15 CEST 2006


Author: ceki
Date: Sun Oct 15 19:44:14 2006
New Revision: 683

Added:
   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/spi/ContextAwareImpl.java
   logback/trunk/logback-core/src/test/input/joran/ampEvent.xml
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/EventRecorderTest.java
      - copied, changed from r678, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/EventInterpreterTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfigurator.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialcConfiguratorTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncAction.java
Removed:
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/EventInterpreterTest.java
Modified:
   logback/trunk/logback-classic/examples/src/chapter1/MyAppWithConfigFile.java
   logback/trunk/logback-classic/examples/src/chapter4/ConfigurationTester.java
   logback/trunk/logback-classic/examples/src/chapter5/CallerEvaluatorExample.java
   logback/trunk/logback-classic/examples/src/chapter5/ExceptionEvaluatorExample.java
   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/net/SimpleSocketServer.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketServer.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/BasicJoranTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.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/JoranConfiguratorBase.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComponentIA.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/BodyEvent.java
   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/SaxEvent.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEventRecorder.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/StartEvent.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java
   logback/trunk/logback-core/src/test/input/joran/event1.xml
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllTest.java

Log:

- joran now registers sax events and perform configration by replaying them
- fixed bug related to element text (see bug #12). If the element body contained
  entities joran would not return the complete text part only parts of it.
- JoranConfigurator.doConfigure throws a JoranException. This changes has pros and 
  cons. On the plus side, it is a little for robust.



Modified: logback/trunk/logback-classic/examples/src/chapter1/MyAppWithConfigFile.java
==============================================================================
--- logback/trunk/logback-classic/examples/src/chapter1/MyAppWithConfigFile.java	(original)
+++ logback/trunk/logback-classic/examples/src/chapter1/MyAppWithConfigFile.java	Sun Oct 15 19:44:14 2006
@@ -6,23 +6,26 @@
 
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
 import ch.qos.logback.core.util.StatusPrinter;
 
 public class MyAppWithConfigFile {
-	
-	public static void main(String[] args) {
-		Logger logger = LoggerFactory.getLogger(MyAppWithConfigFile.class);
-		LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-		
-		JoranConfigurator configurator = new JoranConfigurator();
-		configurator.setContext(lc);
-		configurator.doConfigure(args[0]);
 
-		logger.info("Entering application.");
-		Bar bar = new Bar();
-		bar.doIt();
-		logger.info("Exiting application.");
-	
-		StatusPrinter.print(lc.getStatusManager());
-	}
+  public static void main(String[] args) {
+    Logger logger = LoggerFactory.getLogger(MyAppWithConfigFile.class);
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+    try {
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      configurator.doConfigure(args[0]);
+    } catch (JoranException je) {
+      StatusPrinter.print(lc.getStatusManager());
+    }
+    logger.info("Entering application.");
+    Bar bar = new Bar();
+    bar.doIt();
+    logger.info("Exiting application.");
+
+  }
 }

Modified: logback/trunk/logback-classic/examples/src/chapter4/ConfigurationTester.java
==============================================================================
--- logback/trunk/logback-classic/examples/src/chapter4/ConfigurationTester.java	(original)
+++ logback/trunk/logback-classic/examples/src/chapter4/ConfigurationTester.java	Sun Oct 15 19:44:14 2006
@@ -6,17 +6,21 @@
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.MDC;
 import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
 import ch.qos.logback.core.util.StatusPrinter;
 import chapter4.sub.sample.Bar;
+
 /**
  * 
  * This class can be used to check the result of a configuration file.
  * <p>
- * When all the logback-core, logback-classic and their dependencies have been added
- * to the ClassPath, one can launch this class using the following command:
+ * When all the logback-core, logback-classic and their dependencies have been
+ * added to the ClassPath, one can launch this class using the following
+ * command:
  * <p>
- * java chapter4.ConfigurationTester chapter4/conf/name_of_the_configuration_file.xml
- *
+ * java chapter4.ConfigurationTester
+ * chapter4/conf/name_of_the_configuration_file.xml
+ * 
  * @author S&eacute;bastien Pennec
  */
 public class ConfigurationTester {
@@ -25,10 +29,13 @@
     Logger logger = (Logger) LoggerFactory.getLogger(ConfigurationTester.class);
     LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
 
-    JoranConfigurator configurator = new JoranConfigurator();
-    configurator.setContext(lc);
-    configurator.doConfigure(args[0]);
-
+    try {
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      configurator.doConfigure(args[0]);
+    } catch (JoranException je) {
+      je.printStackTrace();
+    }
     logger.debug("**Hello {}", new Bar());
     MDC.put("testKey", "testValueFromMDC");
     MDC.put("testKey2", "value2");

Modified: logback/trunk/logback-classic/examples/src/chapter5/CallerEvaluatorExample.java
==============================================================================
--- logback/trunk/logback-classic/examples/src/chapter5/CallerEvaluatorExample.java	(original)
+++ logback/trunk/logback-classic/examples/src/chapter5/CallerEvaluatorExample.java	Sun Oct 15 19:44:14 2006
@@ -5,17 +5,24 @@
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
 
 public class CallerEvaluatorExample {
 
   public static void main(String[] args) throws InterruptedException {
-    Logger logger = (Logger) LoggerFactory.getLogger(CallerEvaluatorExample.class);
+    Logger logger = (Logger) LoggerFactory
+        .getLogger(CallerEvaluatorExample.class);
     LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
 
-    JoranConfigurator configurator = new JoranConfigurator();
-    configurator.setContext(lc);
-    configurator.doConfigure(args[0]);
-    
+    try {
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      configurator.doConfigure(args[0]);
+    } catch (JoranException je) {
+      StatusPrinter.print(lc);
+    }
+
     for (int i = 0; i < 5; i++) {
       if (i == 3) {
         logger.debug("stacktrace logging statement" + i);

Modified: logback/trunk/logback-classic/examples/src/chapter5/ExceptionEvaluatorExample.java
==============================================================================
--- logback/trunk/logback-classic/examples/src/chapter5/ExceptionEvaluatorExample.java	(original)
+++ logback/trunk/logback-classic/examples/src/chapter5/ExceptionEvaluatorExample.java	Sun Oct 15 19:44:14 2006
@@ -7,27 +7,33 @@
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
 import ch.qos.logback.core.util.StatusPrinter;
 
 public class ExceptionEvaluatorExample {
 
   public static void main(String[] args) throws InterruptedException {
-    Logger logger = (Logger) LoggerFactory.getLogger(ExceptionEvaluatorExample.class);
+    Logger logger = (Logger) LoggerFactory
+        .getLogger(ExceptionEvaluatorExample.class);
     LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
 
-    JoranConfigurator configurator = new JoranConfigurator();
-    configurator.setContext(lc);
-    configurator.doConfigure(args[0]);
-    
+    try {
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      configurator.doConfigure(args[0]);
+    } catch (JoranException je) {
+      StatusPrinter.print(lc);
+    }
     for (int i = 0; i < 5; i++) {
       if (i == 3) {
         Marker ignoreMarker = MarkerFactory.getMarker("IGNORE");
-        logger.debug(ignoreMarker, "logging statement" + i, new Exception("test"));
+        logger.debug(ignoreMarker, "logging statement" + i, new Exception(
+            "test"));
       } else {
         logger.debug("logging statement" + i, new Exception("test"));
       }
     }
-    
+
     StatusPrinter.print(lc);
   }
 }
\ No newline at end of file

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	Sun Oct 15 19:44:14 2006
@@ -32,7 +32,9 @@
   public JoranConfigurator() {
   }
 
+  @Override
   public void addInstanceRules(RuleStore rs) {
+    super.addInstanceRules(rs);
 
     rs.addRule(new Pattern("configuration"), new ConfigurationAction());
 

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java	Sun Oct 15 19:44:14 2006
@@ -17,22 +17,23 @@
 
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
 
 /**
  * A simple {@link SocketNode} based server.
  * 
  * <pre>
- *    &lt;b&gt;Usage:&lt;/b&gt; java ch.qos.logback.classic.net.SimpleSocketServer port configFile
- *   
- *    where
+ *     &lt;b&gt;Usage:&lt;/b&gt; java ch.qos.logback.classic.net.SimpleSocketServer port configFile
+ *    
+ *     where
  * <em>
  * port
  * </em>
- *    is a part number where the server listens and
+ *     is a part number where the server listens and
  * <em>
  * configFile
  * </em>
- *    is an xml configuration file fed to {@link JoranConfigurator}.
+ *     is an xml configuration file fed to {@link JoranConfigurator}.
  * </pre>
  * 
  * @author Ceki G&uuml;lc&uuml;
@@ -42,57 +43,57 @@
  */
 public class SimpleSocketServer {
 
-	static Logger logger = LoggerFactory.getLogger(SimpleSocketServer.class);
+  static Logger logger = LoggerFactory.getLogger(SimpleSocketServer.class);
 
-	static int port;
+  static int port;
 
-	public static void main(String argv[]) {
-		if (argv.length == 2) {
-			init(argv[0], argv[1]);
-		} else {
-			usage("Wrong number of arguments.");
-		}
-
-		runServer();
-	}
-
-	static void runServer() {
-		try {
-			logger.info("Listening on port " + port);
-			ServerSocket serverSocket = new ServerSocket(port);
-			while (true) {
-				logger.info("Waiting to accept a new client.");
-				Socket socket = serverSocket.accept();
-				logger.info("Connected to client at " + socket.getInetAddress());
-				logger.info("Starting new socket node.");
-				LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-				new Thread(new SocketNode(socket, lc)).start();
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	static void usage(String msg) {
-		System.err.println(msg);
-		System.err.println("Usage: java " + SimpleSocketServer.class.getName()
-				+ " port configFile");
-		System.exit(1);
-	}
-
-	static void init(String portStr, String configFile) {
-		try {
-			port = Integer.parseInt(portStr);
-		} catch (java.lang.NumberFormatException e) {
-			e.printStackTrace();
-			usage("Could not interpret port number [" + portStr + "].");
-		}
-
-		if (configFile.endsWith(".xml")) {
-			LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-			JoranConfigurator configurator = new JoranConfigurator();
-			configurator.setContext(lc);
-			configurator.doConfigure(configFile);
-		}
-	}
+  public static void main(String argv[]) throws Exception {
+    if (argv.length == 2) {
+      init(argv[0], argv[1]);
+    } else {
+      usage("Wrong number of arguments.");
+    }
+
+    runServer();
+  }
+
+  static void runServer() {
+    try {
+      logger.info("Listening on port " + port);
+      ServerSocket serverSocket = new ServerSocket(port);
+      while (true) {
+        logger.info("Waiting to accept a new client.");
+        Socket socket = serverSocket.accept();
+        logger.info("Connected to client at " + socket.getInetAddress());
+        logger.info("Starting new socket node.");
+        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+        new Thread(new SocketNode(socket, lc)).start();
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  static void usage(String msg) {
+    System.err.println(msg);
+    System.err.println("Usage: java " + SimpleSocketServer.class.getName()
+        + " port configFile");
+    System.exit(1);
+  }
+
+  static void init(String portStr, String configFile) throws JoranException {
+    try {
+      port = Integer.parseInt(portStr);
+    } catch (java.lang.NumberFormatException e) {
+      e.printStackTrace();
+      usage("Could not interpret port number [" + portStr + "].");
+    }
+
+    if (configFile.endsWith(".xml")) {
+      LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+      JoranConfigurator configurator = new JoranConfigurator();
+      configurator.setContext(lc);
+      configurator.doConfigure(configFile);
+    }
+  }
 }

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketServer.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketServer.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketServer.java	Sun Oct 15 19:44:14 2006
@@ -21,17 +21,19 @@
 
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
 
 /**
  * A {@link SocketNode} based server that uses a different hierarchy for each
  * client.
  * 
  * <pre>
- *    &lt;b&gt;Usage:&lt;/b&gt; java ch.qos.logback.classic.net.SocketServer port configFile configDir
- *   
- *    where &lt;b&gt;port&lt;/b&gt; is a part number where the server listens,
- *    &lt;b&gt;configFile&lt;/b&gt; is an xml configuration file fed to the {@link JoranConfigurator} and
- *    &lt;b&gt;configDir&lt;/b&gt; is a path to a directory containing configuration files, possibly one for each client host.
+ *        &lt;b&gt;Usage:&lt;/b&gt; java ch.qos.logback.classic.net.SocketServer port configFile configDir
+ *       
+ *        where &lt;b&gt;port&lt;/b&gt; is a part number where the server listens,
+ *        &lt;b&gt;configFile&lt;/b&gt; is an xml configuration file fed to the {@link JoranConfigurator} and
+ *        &lt;b&gt;configDir&lt;/b&gt; is a path to a directory containing configuration files, possibly one for each client host.
  * </pre>
  * 
  * <p>
@@ -72,132 +74,137 @@
  * 
  * 
  * @author Ceki G&uuml;lc&uuml;
- * 
- * @since 1.0
  */
 
 public class SocketServer {
 
-	static String GENERIC = "generic";
-	static String CONFIG_FILE_EXT = ".lcf";
+  static String GENERIC = "generic";
+  static String CONFIG_FILE_EXT = ".lcf";
 
-	static Logger logger = LoggerFactory.getLogger(SocketServer.class);
-	static SocketServer server;
-	static int port;
-
-	// key=inetAddress, value=hierarchy
-	Hashtable<InetAddress, LoggerContext> hierarchyMap;
-	LoggerContext genericHierarchy;
-	File dir;
-
-	public static void main(String argv[]) {
-		if (argv.length == 3) {
-			init(argv[0], argv[1], argv[2]);
-		} else {
-			usage("Wrong number of arguments.");
-		}
-
-		try {
-			logger.info("Listening on port " + port);
-			ServerSocket serverSocket = new ServerSocket(port);
-			while (true) {
-				logger.info("Waiting to accept a new client.");
-				Socket socket = serverSocket.accept();
-				InetAddress inetAddress = socket.getInetAddress();
-				logger.info("Connected to client at " + inetAddress);
-
-				LoggerContext h = (LoggerContext) server.hierarchyMap.get(inetAddress);
-				if (h == null) {
-					h = server.configureHierarchy(inetAddress);
-				}
-
-				logger.info("Starting new socket node.");
-				new Thread(new SocketNode(socket, h)).start();
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	static void usage(String msg) {
-		System.err.println(msg);
-		System.err.println("Usage: java " + SocketServer.class.getName()
-				+ " port configFile directory");
-		System.exit(1);
-	}
-
-	static void init(String portStr, String configFile, String dirStr) {
-		try {
-			port = Integer.parseInt(portStr);
-		} catch (java.lang.NumberFormatException e) {
-			e.printStackTrace();
-			usage("Could not interpret port number [" + portStr + "].");
-		}
-
-		LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-		JoranConfigurator configurator = new JoranConfigurator();
-		configurator.setContext(lc);
-		configurator.doConfigure(configFile);
-
-		File dir = new File(dirStr);
-		if (!dir.isDirectory()) {
-			usage("[" + dirStr + "] is not a directory.");
-		}
-		server = new SocketServer(dir);
-	}
-
-	public SocketServer(File directory) {
-		this.dir = directory;
-		hierarchyMap = new Hashtable<InetAddress, LoggerContext>(11);
-	}
-
-	// This method assumes that there is no hiearchy for inetAddress
-	// yet. It will configure one and return it.
-	LoggerContext configureHierarchy(InetAddress inetAddress) {
-		logger.info("Locating configuration file for " + inetAddress);
-		// We assume that the toSting method of InetAddress returns is in
-		// the format hostname/d1.d2.d3.d4 e.g. torino/192.168.1.1
-		String s = inetAddress.toString();
-		int i = s.indexOf("/");
-		if (i == -1) {
-			logger.warn("Could not parse the inetAddress [" + inetAddress
-					+ "]. Using default hierarchy.");
-			return genericHierarchy();
-		} else {
-			String key = s.substring(0, i);
-
-			File configFile = new File(dir, key + CONFIG_FILE_EXT);
-			if (configFile.exists()) {
-				LoggerContext lc = new LoggerContext();
-				hierarchyMap.put(inetAddress, lc);
-
-				JoranConfigurator configurator = new JoranConfigurator();
-				configurator.setContext(lc);
-				configurator.doConfigure(configFile);
-
-				return lc;
-			} else {
-				logger.warn("Could not find config file [" + configFile + "].");
-				return genericHierarchy();
-			}
-		}
-	}
-
-	LoggerContext genericHierarchy() {
-		if (genericHierarchy == null) {
-			File f = new File(dir, GENERIC + CONFIG_FILE_EXT);
-			if (f.exists()) {
-				genericHierarchy = new LoggerContext();
-				JoranConfigurator configurator = new JoranConfigurator();
-				configurator.setContext(genericHierarchy);
-				configurator.doConfigure(f.getAbsolutePath());
-
-			} else {
-				logger.warn("Could not find config file [" + f
-						+ "]. Will use the default hierarchy.");
-				genericHierarchy = new LoggerContext();
-			}
-		}
-		return genericHierarchy;
-	}
+  static Logger logger = LoggerFactory.getLogger(SocketServer.class);
+  static SocketServer server;
+  static int port;
+
+  // key=inetAddress, value=hierarchy
+  Hashtable<InetAddress, LoggerContext> hierarchyMap;
+  LoggerContext genericHierarchy;
+  File dir;
+
+  public static void main(String argv[]) throws Exception {
+    if (argv.length == 3) {
+      init(argv[0], argv[1], argv[2]);
+    } else {
+      usage("Wrong number of arguments.");
+    }
+
+    try {
+      logger.info("Listening on port " + port);
+      ServerSocket serverSocket = new ServerSocket(port);
+      while (true) {
+        logger.info("Waiting to accept a new client.");
+        Socket socket = serverSocket.accept();
+        InetAddress inetAddress = socket.getInetAddress();
+        logger.info("Connected to client at " + inetAddress);
+
+        LoggerContext h = (LoggerContext) server.hierarchyMap.get(inetAddress);
+        if (h == null) {
+          h = server.configureHierarchy(inetAddress);
+        }
+
+        logger.info("Starting new socket node.");
+        new Thread(new SocketNode(socket, h)).start();
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  static void usage(String msg) {
+    System.err.println(msg);
+    System.err.println("Usage: java " + SocketServer.class.getName()
+        + " port configFile directory");
+    System.exit(1);
+  }
+
+  static void init(String portStr, String configFile, String dirStr)
+      throws JoranException {
+    try {
+      port = Integer.parseInt(portStr);
+    } catch (java.lang.NumberFormatException e) {
+      e.printStackTrace();
+      usage("Could not interpret port number [" + portStr + "].");
+    }
+
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+    JoranConfigurator configurator = new JoranConfigurator();
+    configurator.setContext(lc);
+    configurator.doConfigure(configFile);
+
+    File dir = new File(dirStr);
+    if (!dir.isDirectory()) {
+      usage("[" + dirStr + "] is not a directory.");
+    }
+    server = new SocketServer(dir);
+  }
+
+  public SocketServer(File directory) {
+    this.dir = directory;
+    hierarchyMap = new Hashtable<InetAddress, LoggerContext>(11);
+  }
+
+  // This method assumes that there is no hiearchy for inetAddress
+  // yet. It will configure one and return it.
+  LoggerContext configureHierarchy(InetAddress inetAddress) {
+    logger.info("Locating configuration file for " + inetAddress);
+    // We assume that the toSting method of InetAddress returns is in
+    // the format hostname/d1.d2.d3.d4 e.g. torino/192.168.1.1
+    String s = inetAddress.toString();
+    int i = s.indexOf("/");
+    if (i == -1) {
+      logger.warn("Could not parse the inetAddress [" + inetAddress
+          + "]. Using default hierarchy.");
+      return genericHierarchy();
+    } else {
+      String key = s.substring(0, i);
+
+      File configFile = new File(dir, key + CONFIG_FILE_EXT);
+      if (configFile.exists()) {
+        LoggerContext lc = new LoggerContext();
+        hierarchyMap.put(inetAddress, lc);
+
+        try {
+          JoranConfigurator configurator = new JoranConfigurator();
+          configurator.setContext(lc);
+          configurator.doConfigure(configFile);
+        } catch (JoranException je) {
+          StatusPrinter.print(lc);
+        }
+        return lc;
+      } else {
+        logger.warn("Could not find config file [" + configFile + "].");
+        return genericHierarchy();
+      }
+    }
+  }
+
+  LoggerContext genericHierarchy() {
+    if (genericHierarchy == null) {
+      File f = new File(dir, GENERIC + CONFIG_FILE_EXT);
+      if (f.exists()) {
+        genericHierarchy = new LoggerContext();
+        try {
+          JoranConfigurator configurator = new JoranConfigurator();
+          configurator.setContext(genericHierarchy);
+          configurator.doConfigure(f.getAbsolutePath());
+        } catch (JoranException je) {
+          StatusPrinter.print(genericHierarchy);
+        }
+      } else {
+        logger.warn("Could not find config file [" + f
+            + "]. Will use the default hierarchy.");
+        genericHierarchy = new LoggerContext();
+      }
+    }
+    return genericHierarchy;
+  }
 }

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/BasicJoranTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/BasicJoranTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/BasicJoranTest.java	Sun Oct 15 19:44:14 2006
@@ -17,6 +17,7 @@
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.classic.util.Constants;
 import ch.qos.logback.core.appender.ListAppender;
+import ch.qos.logback.core.joran.spi.JoranException;
 import ch.qos.logback.core.util.StatusPrinter;
 
 public class BasicJoranTest extends TestCase {
@@ -25,7 +26,7 @@
     super(name);
   }
   
-  public void testSimpleList() {
+  public void testSimpleList() throws JoranException {
     JoranConfigurator jc = new JoranConfigurator();
     LoggerContext loggerContext = new LoggerContext();
     jc.setContext(loggerContext);
@@ -44,7 +45,7 @@
     assertEquals(msg, le.getMessage());
   }
   
-  public void testLevel() {
+  public void testLevel() throws JoranException {
     JoranConfigurator jc = new JoranConfigurator();
     LoggerContext loggerContext = new LoggerContext();
     jc.setContext(loggerContext);
@@ -63,7 +64,7 @@
     //assertEquals(msg, le.getMessage());
   }
   
-  public void testEval() {
+  public void testEval() throws JoranException {
     JoranConfigurator jc = new JoranConfigurator();
     LoggerContext loggerContext = new LoggerContext();
     jc.setContext(loggerContext);
@@ -78,6 +79,7 @@
   }
   
   
+  // COMMENTED_OUT_
   public static Test COMMENTED_OUT_suite() {
     TestSuite suite = new TestSuite();
     suite.addTest(new BasicJoranTest("testLevel"));

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/EvaluatorJoranTest.java	Sun Oct 15 19:44:14 2006
@@ -24,12 +24,13 @@
 import ch.qos.logback.classic.util.Constants;
 import ch.qos.logback.core.CoreGlobal;
 import ch.qos.logback.core.boolex.EvaluationException;
+import ch.qos.logback.core.joran.spi.JoranException;
 import ch.qos.logback.core.util.StatusPrinter;
 
 
 public class EvaluatorJoranTest extends TestCase {
 
-  public void xtest() throws NullPointerException, EvaluationException {
+  public void xtest() throws NullPointerException, EvaluationException, JoranException {
     JoranConfigurator jc = new JoranConfigurator();
     LoggerContext loggerContext = new LoggerContext();
     jc.setContext(loggerContext);
@@ -50,13 +51,13 @@
     //StatusPrinter.print(loggerContext.getStatusManager());
   }
   
-  public void testIgnoreMarker() throws NullPointerException, EvaluationException {
+  public void testIgnoreMarker() throws NullPointerException, EvaluationException, JoranException {
     JoranConfigurator jc = new JoranConfigurator();
     LoggerContext loggerContext = new LoggerContext();
     jc.setContext(loggerContext);
     jc.doConfigure(Constants.TEST_DIR_PREFIX + "input/joran/ignore.xml");
     
-    
+    StatusPrinter.print(loggerContext.getStatusManager());
     
     Map evalMap = (Map) loggerContext.getObject(CoreGlobal.EVALUATOR_MAP);
     assertNotNull(evalMap);

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	Sun Oct 15 19:44:14 2006
@@ -7,18 +7,23 @@
 import java.net.URL;
 import java.util.List;
 
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
 import org.xml.sax.InputSource;
 
+import ch.qos.logback.core.joran.spi.EventPlayer;
+import ch.qos.logback.core.joran.spi.ExecutionContext;
+import ch.qos.logback.core.joran.spi.Interpreter;
 import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.joran.spi.RuleStore;
 import ch.qos.logback.core.joran.spi.SaxEvent;
 import ch.qos.logback.core.joran.spi.SaxEventRecorder;
+import ch.qos.logback.core.joran.spi.SimpleRuleStore;
 import ch.qos.logback.core.spi.ContextAwareBase;
 
-public class GenericConfigurator extends ContextAwareBase {
+public abstract class GenericConfigurator extends ContextAwareBase {
 
+  List<SaxEvent> saxEventList;
+  Interpreter interpreter;
+  
   final public void doConfigure(URL url) throws JoranException {
     try {
       InputStream in = url.openStream();
@@ -61,42 +66,31 @@
     doConfigure(new InputSource(inputStream));
   }
 
-  List<SaxEvent> recordEvents(InputSource inputSource) throws JoranException {
-    SAXParser saxParser = null;
-    SaxEventRecorder saxEventRecorder = new SaxEventRecorder();
-    try {
-      SAXParserFactory spf = SAXParserFactory.newInstance();
-      spf.setValidating(false);
-      spf.setNamespaceAware(true);
-      saxParser = spf.newSAXParser();
-    } catch (Exception pce) {
-      String errMsg = "Parser configuration error occured";
-      addError(errMsg, pce);
-      throw new JoranException(errMsg, pce);
-    }
-
-    try {
-      saxParser.parse(inputSource, saxEventRecorder);
-      return saxEventRecorder.saxEventList;
-
-    } catch (IOException ie) {
-      String errMsg = "I/O error occurred while parsing xml file";
-      addError(errMsg, ie);
-      throw new JoranException(errMsg, ie);
-    } catch (Exception ex) {
-      String errMsg = "Problem parsing XML document. See previously reported errors. Abandoning all further processing.";
-      addError(errMsg, ex);
-      throw new JoranException(errMsg, ex);
-    }
-
+  abstract protected void addInstanceRules(RuleStore rs);
+  abstract protected void addImpliciutRules(Interpreter interpreter);
+  
+  protected void buildInterpreter() {
+    RuleStore rs = new SimpleRuleStore(context);
+    addInstanceRules(rs);
+    this.interpreter = new Interpreter(rs);
+    ExecutionContext ec = interpreter.getExecutionContext();
+    ec.setContext(context);
+    addImpliciutRules(interpreter);
+    
   }
-
+  
   final public void doConfigure(final InputSource inputSource)
       throws JoranException {
-    
-    List<SaxEvent> saxEventList;
-    saxEventList = recordEvents(inputSource);
-    
+    SaxEventRecorder recorder = new SaxEventRecorder();
+    recorder.setContext(context);
+    saxEventList = recorder.recordEvents(inputSource);
+    buildInterpreter();
+    EventPlayer player = new EventPlayer(interpreter);
+    player.play(recorder.saxEventList);
+  }
+
+  public List<SaxEvent> getSaxEventList() {
+    return saxEventList;
   }
 
 }

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	Sun Oct 15 19:44:14 2006
@@ -7,15 +7,10 @@
  * the terms of the GNU Lesser General Public License as published by the Free
  * Software Foundation.
  */
- 
-package ch.qos.logback.core.joran;
 
+package ch.qos.logback.core.joran;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -25,7 +20,6 @@
 
 import org.xml.sax.InputSource;
 
-import ch.qos.logback.core.Context;
 import ch.qos.logback.core.joran.action.ActionConst;
 import ch.qos.logback.core.joran.action.AppenderAction;
 import ch.qos.logback.core.joran.action.AppenderRefAction;
@@ -40,89 +34,46 @@
 import ch.qos.logback.core.joran.spi.Interpreter;
 import ch.qos.logback.core.joran.spi.Pattern;
 import ch.qos.logback.core.joran.spi.RuleStore;
-import ch.qos.logback.core.joran.spi.SimpleRuleStore;
-import ch.qos.logback.core.spi.ContextAwareBase;
-
 
-// Based on 310985 revision  310985 as attested by http://tinyurl.com/8njps
+// Based on 310985 revision 310985 as attested by http://tinyurl.com/8njps
 // see also http://tinyurl.com/c2rp5
 
 /**
- * A JoranConfiguratorBase lays most of the groundwork for concrete 
- * configurators derived from it. Concrete configurators only need to
- * implement the {@link #addInstanceRules} method.
+ * A JoranConfiguratorBase lays most of the groundwork for concrete
+ * configurators derived from it. Concrete configurators only need to implement
+ * the {@link #addInstanceRules} method.
  * <p>
  * A JoranConfiguratorBase instance should not be used more than once to
  * configure a Context.
- *
+ * 
  * @author Ceki G&uuml;lc&uuml;
  */
-abstract public class JoranConfiguratorBase extends ContextAwareBase {
-  Interpreter joranInterpreter;
- 
-  
-  final public void doConfigure(URL url) {
-    try {
-      InputStream in = url.openStream();
-      doConfigure(in);
-      in.close();
-    } catch (IOException ioe) {
-      String errMsg = "Could not open URL [" + url + "].";
-      addError(errMsg, ioe);
-    }
-  }
+abstract public class JoranConfiguratorBase extends GenericConfigurator {
   
-  final public void doConfigure(String filename) {
-    doConfigure(new File(filename));
-  }
 
-  final public void doConfigure(File file) {
-    FileInputStream fis = null;
-    try {
-      fis = new FileInputStream(file);
-      doConfigure(fis);
-    } catch (IOException ioe) {
-      String errMsg = "Could not open [" + file.getName() + "].";
-      addError(errMsg, ioe);
-    } finally {
-      if (fis != null) {
-        try {
-          fis.close();
-        } catch (java.io.IOException ioe) {
-          addError(
-            "Could not close [" + file.getName() + "].", ioe);
-        }
-      }
-    }
-  }
-
-  final public void doConfigure(InputStream inputStream) {
-    doConfigure(new InputSource(inputStream));
-  }
-
-  final public void doConfigure(final InputSource inputSource) {
-    // This line is needed here because there is logging from inside this method.
-    selfInitialize(this.context);
-    
-    ExecutionContext ec = joranInterpreter.getExecutionContext();
+  final public void xdoConfigure(final InputSource inputSource) {
+    // This line is needed here because there is logging from inside this
+    // method.
+    buildInterpreter();
 
+    ExecutionContext ec = interpreter.getExecutionContext();
 
     SAXParser saxParser = null;
     try {
-        SAXParserFactory spf = SAXParserFactory.newInstance();
-        spf.setValidating(false);
-        spf.setNamespaceAware(true);
-        saxParser = spf.newSAXParser();
+      SAXParserFactory spf = SAXParserFactory.newInstance();
+      spf.setValidating(false);
+      spf.setNamespaceAware(true);
+      saxParser = spf.newSAXParser();
     } catch (Exception pce) {
       String errMsg = "Parser configuration error occured";
       ec.addError(errMsg, pce);
       return;
     }
-    
+
     try {
       // attachListAppender(context);
-      saxParser.parse(inputSource, joranInterpreter);
-    } catch(IOException ie) {
+      saxParser.parse(inputSource, interpreter);
+    } catch (IOException ie) {
       final String errMsg = "I/O error occurred while parsing xml file";
       ec.addError(errMsg, ie);
     } catch (Exception ex) {
@@ -130,57 +81,51 @@
       addError(errMsg, ex);
       return;
     } finally {
-      //detachListAppender(repository);
-    }    
+      // detachListAppender(repository);
+    }
   }
 
   public List getErrorList() {
     return null;
   }
 
-  abstract public void addInstanceRules(RuleStore rs);
-  
-  protected void selfInitialize(Context context) {
-    RuleStore rs = new SimpleRuleStore(context);
-    addInstanceRules(rs);
-   
-    rs.addRule(
-      new Pattern("configuration/substitutionProperty"),
-      new SubstitutionPropertyAction());
-    rs.addRule(
-      new Pattern("configuration/repositoryProperty"),
-      new RepositoryPropertyAction());
-    rs.addRule(
-        new Pattern("configuration/conversionRule"),
+  @Override
+  protected void addInstanceRules(RuleStore rs) {
+    rs.addRule(new Pattern("configuration/substitutionProperty"),
+        new SubstitutionPropertyAction());
+    rs.addRule(new Pattern("configuration/repositoryProperty"),
+        new RepositoryPropertyAction());
+    rs.addRule(new Pattern("configuration/conversionRule"),
         new ConversionRuleAction());
-  
-    rs.addRule(
-      new Pattern("configuration/appender"), new AppenderAction());
-    rs.addRule(new Pattern("configuration/appender/appender-ref"), 
+
+    rs.addRule(new Pattern("configuration/appender"), new AppenderAction());
+    rs.addRule(new Pattern("configuration/appender/appender-ref"),
         new AppenderRefAction());
-    rs.addRule(
-      new Pattern("configuration/newRule"), new NewRuleAction());
+    rs.addRule(new Pattern("configuration/newRule"), new NewRuleAction());
     rs.addRule(new Pattern("*/param"), new ParamAction());
-    
-    joranInterpreter = new Interpreter(rs);
-    ExecutionContext ec = joranInterpreter.getExecutionContext();
-    ec.setContext(context);
-    
+  }
+
+  @Override
+  protected void addImpliciutRules(Interpreter interpreter) {
     // The following line adds the capability to parse nested components
     NestedComponentIA nestedIA = new NestedComponentIA();
     nestedIA.setContext(context);
-    joranInterpreter.addImplicitAction(nestedIA);
+    interpreter.addImplicitAction(nestedIA);
 
     NestedSimplePropertyIA nestedSimpleIA = new NestedSimplePropertyIA();
     nestedIA.setContext(context);
-    joranInterpreter.addImplicitAction(nestedSimpleIA);
+    interpreter.addImplicitAction(nestedSimpleIA);
+  }
 
-    Map<String, Object> omap = ec.getObjectMap();
+  @Override
+  protected void buildInterpreter() {
+    super.buildInterpreter();
+    Map<String, Object> omap = interpreter.getExecutionContext().getObjectMap();
     omap.put(ActionConst.APPENDER_BAG, new HashMap());
     omap.put(ActionConst.FILTER_CHAIN_BAG, new HashMap());
   }
 
   public ExecutionContext getExecutionContext() {
-    return joranInterpreter.getExecutionContext();
+    return interpreter.getExecutionContext();
   }
 }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java	Sun Oct 15 19:44:14 2006
@@ -39,7 +39,7 @@
     String className = attributes.getValue(CLASS_ATTRIBUTE);
     if(OptionHelper.isEmpty(className)) {
       className = defaultClassName();
-      addError("Assuming default evaluator class ["+className+"]");
+      addWarn("Assuming default evaluator class ["+className+"]");
     }
 
     if(OptionHelper.isEmpty(className)) {

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComponentIA.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComponentIA.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComponentIA.java	Sun Oct 15 19:44:14 2006
@@ -55,6 +55,7 @@
 
     switch (containmentType) {
     case PropertySetter.NOT_FOUND:
+    case PropertySetter.AS_PROPERTY:
       return false;
 
     // we only push action data if NestComponentIA is applicable

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/BodyEvent.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/BodyEvent.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/BodyEvent.java	Sun Oct 15 19:44:14 2006
@@ -3,9 +3,9 @@
 import org.xml.sax.Locator;
 
 public class BodyEvent extends SaxEvent {
-  
-  final String text;
-  
+
+  private String text;
+
   BodyEvent(String text, Locator locator) {
     super(null, null, null, locator);
     this.text = text;
@@ -14,10 +14,15 @@
   public String getText() {
     return text;
   }
-  
+
   @Override
   public String toString() {
-    return "BodyEvent("+getText()+")"+locator.getLineNumber()+","+locator.getColumnNumber();
+    return "BodyEvent(" + getText() + ")" + locator.getLineNumber() + ","
+        + locator.getColumnNumber();
+  }
+
+  public void append(String str) {
+    text += str;
   }
 
 }

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/EventPlayer.java	Sun Oct 15 19:44:14 2006
@@ -0,0 +1,26 @@
+package ch.qos.logback.core.joran.spi;
+
+import java.util.List;
+
+public class EventPlayer {
+
+  final Interpreter interpreter;
+  
+  public EventPlayer(Interpreter interpreter) {
+    this.interpreter = interpreter;
+  }
+  
+  public void play(List<SaxEvent> seList) {
+    for(SaxEvent se : seList) {
+      if(se instanceof StartEvent) {
+        interpreter.startElement((StartEvent) se);
+      }
+      if(se instanceof BodyEvent) {
+        interpreter.characters((BodyEvent) se);
+      }
+      if(se instanceof EndEvent) {
+        interpreter.endElement((EndEvent) se);
+      }
+    }
+  }
+}

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	Sun Oct 15 19:44:14 2006
@@ -66,10 +66,7 @@
   Pattern pattern;
   Locator locator;
 
-  public List<SaxEvent> saxEventList = new ArrayList<SaxEvent>();
-
-  
-  /**
+   /**
    * The <id>actionListStack</id> contains a list of actions that are executing
    * for the given XML element.
    * 
@@ -100,13 +97,17 @@
   public void startDocument() {
   }
 
+  public void startElement(StartEvent se) {
+    setDocumentLocator(se.getLocator());
+    startElement(se.namespaceURI, se.localName, se.qName, se.attributes);
+  }
+  
   public void startElement(String namespaceURI, String localName, String qName,
       Attributes atts) {
 
-	
-   String tagName = getTagName(localName, qName);
+    String tagName = getTagName(localName, qName);
 
-    //System.out.println("startElement [" + tagName + "]");
+    // System.out.println("startElement [" + tagName + "]");
 
     pattern.push(tagName);
 
@@ -124,23 +125,28 @@
     }
   }
 
-  public void characters(char[] ch, int start, int length) {
+  public void characters(BodyEvent be) {
+
+    setDocumentLocator(be.locator);
     
-    String body = new String(ch, start, length);    
+    String body = be.getText();
     List applicableActionList = (List) actionListStack.peek();
 
-    if(body != null) {
+    if (body != null) {
       body = body.trim();
     }
-    if(body.length() > 0) {
-      //System.out.println("calling body method with ["+body+ "]");
+    if (body.length() > 0) {
+      // System.out.println("calling body method with ["+body+ "]");
       callBodyAction(applicableActionList, body);
     }
   }
 
+  public void endElement(EndEvent endEvent) {
+    setDocumentLocator(endEvent.locator);
+    endElement(endEvent.namespaceURI, endEvent.localName, endEvent.qName);
+  }
+
   public void endElement(String namespaceURI, String localName, String qName) {
-    saxEventList.add(new EndEvent(namespaceURI, localName, qName, getLocator()));
-    
     List applicableActionList = (List) actionListStack.pop();
     // System.out.println("endElement ["+getTagName(localName, qName)+"]");
 
@@ -275,7 +281,8 @@
       try {
         action.body(ec, body);
       } catch (ActionException ae) {
-        ec.addError("Exception in end() methd for action [" + action+ "]", this, ae);
+        ec.addError("Exception in end() methd for action [" + action + "]",
+            this, ae);
       }
     }
   }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEvent.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEvent.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEvent.java	Sun Oct 15 19:44:14 2006
@@ -33,9 +33,4 @@
   public String getQName() {
     return qName;
   }
-
-  @Override
-  public String toString() {
-    return this.getClass().getName()+", "+locator.getLineNumber()+","+locator.getColumnNumber();
-  }
 }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEventRecorder.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEventRecorder.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/SaxEventRecorder.java	Sun Oct 15 19:44:14 2006
@@ -1,22 +1,68 @@
 package ch.qos.logback.core.joran.spi;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
 import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
 import org.xml.sax.Locator;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.helpers.DefaultHandler;
 
-public class SaxEventRecorder extends DefaultHandler {
-  
-  private ExecutionContext ec;
-  
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.spi.ContextAware;
+import ch.qos.logback.core.spi.ContextAwareImpl;
+import ch.qos.logback.core.status.Status;
+
+public class SaxEventRecorder extends DefaultHandler implements ContextAware {
+
+  ContextAwareImpl cai = new ContextAwareImpl();
+
   public List<SaxEvent> saxEventList = new ArrayList<SaxEvent>();
   Locator locator;
-  Pattern globalPattern;
-  
+  Pattern globalPattern = new Pattern();
+
+ 
+  final public void recordEvents(InputStream inputStream) throws JoranException {
+    recordEvents(new InputSource(inputStream));
+  }
+
+  public List<SaxEvent> recordEvents(InputSource inputSource)
+      throws JoranException {
+    SAXParser saxParser = null;
+    try {
+      SAXParserFactory spf = SAXParserFactory.newInstance();
+      spf.setValidating(false);
+      spf.setNamespaceAware(true);
+      saxParser = spf.newSAXParser();
+    } catch (Exception pce) {
+      String errMsg = "Parser configuration error occured";
+      addError(errMsg, pce);
+      throw new JoranException(errMsg, pce);
+    }
+
+    try {
+      saxParser.parse(inputSource, this);
+      return saxEventList;
+
+    } catch (IOException ie) {
+      String errMsg = "I/O error occurred while parsing xml file";
+      addError(errMsg, ie);
+      throw new JoranException(errMsg, ie);
+    } catch (Exception ex) {
+      String errMsg = "Problem parsing XML document. See previously reported errors. Abandoning all further processing.";
+      addError(errMsg, ex);
+      throw new JoranException(errMsg, ex);
+    }
+
+  }
+
   public void startDocument() {
   }
 
@@ -28,33 +74,55 @@
     locator = l;
   }
 
-  
   public void startElement(String namespaceURI, String localName, String qName,
       Attributes atts) {
 
     String tagName = getTagName(localName, qName);
     globalPattern.push(tagName);
     Pattern current = (Pattern) globalPattern.clone();
-    saxEventList.add(new StartEvent(current, namespaceURI, localName, qName, atts, getLocator()));
-   }
+    saxEventList.add(new StartEvent(current, namespaceURI, localName, qName,
+        atts, getLocator()));
+  }
 
   public void characters(char[] ch, int start, int length) {
-    String body = new String(ch, start, length);    
 
-    if(body != null) {
-      body = body.trim();
+    String body = new String(ch, start, length);
+    if (body == null) {
+      return;
+    }
+
+    // if the body string is null
+    if (body != null) {
+      String bodyTrimmed = body.trim();
+      if (bodyTrimmed.length() == 0) {
+        return;
+      }
     }
-    if(body.length() > 0) {
+
+    SaxEvent lastEvent = getLastEvent();
+    if (lastEvent instanceof BodyEvent) {
+      BodyEvent be = (BodyEvent) lastEvent;
+      be.append(body);
+    } else {
       saxEventList.add(new BodyEvent(body, getLocator()));
     }
+
+  }
+
+  SaxEvent getLastEvent() {
+    if (saxEventList.isEmpty()) {
+      return null;
+    }
+    int size = saxEventList.size();
+    return saxEventList.get(size - 1);
   }
-  
+
   public void endElement(String namespaceURI, String localName, String qName) {
-    saxEventList.add(new EndEvent(namespaceURI, localName, qName, getLocator()));
+    saxEventList
+        .add(new EndEvent(namespaceURI, localName, qName, getLocator()));
     globalPattern.pop();
   }
 
-  
   String getTagName(String localName, String qName) {
     String tagName = localName;
     if ((tagName == null) || (tagName.length() < 1)) {
@@ -62,22 +130,63 @@
     }
     return tagName;
   }
-  
+
   public void error(SAXParseException spe) throws SAXException {
-    ec.addError("Parsing error", this, spe);
-    ec.addError("Parsing problem on line " + spe.getLineNumber()
-        + " and column " + spe.getColumnNumber(), this, spe);
+    addError("Parsing error", spe);
+    addError("Parsing problem on line " + spe.getLineNumber() + " and column "
+        + spe.getColumnNumber(), spe);
   }
 
   public void fatalError(SAXParseException spe) throws SAXException {
-    ec.addError("Parsing fatal error", this, spe);
-    ec.addError("Parsing problem on line " + spe.getLineNumber()
-        + " and column " + spe.getColumnNumber(), this, spe);
+    addError("Parsing fatal error", spe);
+    addError("Parsing problem on line " + spe.getLineNumber() + " and column "
+        + spe.getColumnNumber(), spe);
   }
 
   public void warning(SAXParseException spe) throws SAXException {
-    ec.addWarn("Parsing warning", this, spe);
-    ec.addWarn("Parsing problem on line " + spe.getLineNumber()
-        + " and column " + spe.getColumnNumber(), this, spe);
+    addWarn("Parsing warning", spe);
+    addWarn("Parsing problem on line " + spe.getLineNumber() + " and column "
+        + spe.getColumnNumber(), spe);
   }
+
+  public void addError(String msg) {
+    cai.addError(msg);
+  }
+
+  public void addError(String msg, Throwable ex) {
+    cai.addError(msg, ex);
+  }
+
+  public void addInfo(String msg) {
+    cai.addInfo(msg);
+  }
+
+  public void addInfo(String msg, Throwable ex) {
+    cai.addInfo(msg, ex);
+  }
+
+  public void addStatus(Status status) {
+    cai.addStatus(status);
+  }
+
+  public void addWarn(String msg) {
+    cai.addWarn(msg);
+  }
+
+  public void addWarn(String msg, Throwable ex) {
+    addWarn(msg, ex);
+  }
+
+  public Context getContext() {
+    return cai.getContext();
+  }
+
+  public void setContext(Context context) {
+    cai.setContext(context);
+  }
+
+  public List<SaxEvent> getSaxEventList() {
+    return saxEventList;
+  }
+
 }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/StartEvent.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/StartEvent.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/StartEvent.java	Sun Oct 15 19:44:14 2006
@@ -2,6 +2,7 @@
 
 import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
+import org.xml.sax.helpers.AttributesImpl;
 
 public class StartEvent extends SaxEvent {
 
@@ -12,7 +13,7 @@
       Attributes attributes, Locator locator) {
     super(namespaceURI, localName, qName, locator);
     // locator impl is used to take a snapshot!
-    this.attributes = attributes;
+    this.attributes = new AttributesImpl(attributes);
     this.pattern = pattern;
   }
 

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java	Sun Oct 15 19:44:14 2006
@@ -9,12 +9,6 @@
  */
 package ch.qos.logback.core.spi;
 
-import ch.qos.logback.core.Context;
-import ch.qos.logback.core.status.ErrorStatus;
-import ch.qos.logback.core.status.InfoStatus;
-import ch.qos.logback.core.status.Status;
-import ch.qos.logback.core.status.StatusManager;
-import ch.qos.logback.core.status.WarnStatus;
 
 
 /**
@@ -23,65 +17,6 @@
  * 
  * @author Ceki G&uumllc&uuml;
  */
-public class ContextAwareBase implements ContextAware {
-
-  private int noContextWarning = 0;
-  protected Context context;
-
-  public void setContext(Context context) {
-    if (this.context == null) {
-      this.context = context;
-    } else if (this.context != context) {
-      throw new IllegalStateException("Context has been already set");
-    }
-  }
-
-  public Context getContext() {
-    return this.context;
-  }
-
-  public StatusManager getStatusManager() {
-    if (context == null) {
-      return null;
-    }
-    return context.getStatusManager();
-  }
-
-  public void addStatus(Status status) {
-    if (context == null) {
-      if (noContextWarning++ == 0) {
-        System.out.println("LOGBACK: No context given for " + this);
-      }
-      return;
-    }
-    StatusManager sm = context.getStatusManager();
-    if (sm != null) {
-      sm.add(status);
-    }
-  }
-
-  public void addInfo(String msg) {
-    addStatus(new InfoStatus(msg, this));
-  }
-
-  public void addInfo(String msg, Throwable ex) {
-    addStatus(new InfoStatus(msg, this, ex));
-  }
-
-  public void addWarn(String msg) {
-    addStatus(new WarnStatus(msg, this));
-  }
-
-  public void addWarn(String msg, Throwable ex) {
-    addStatus(new WarnStatus(msg, this, ex));
-  }
-
-  public void addError(String msg) {
-    addStatus(new ErrorStatus(msg, this));
-  }
-
-  public void addError(String msg, Throwable ex) {
-    addStatus(new ErrorStatus(msg, this, ex));
-  }
-
+public class ContextAwareBase extends ContextAwareImpl {
+  // to be removed
 }

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareImpl.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareImpl.java	Sun Oct 15 19:44:14 2006
@@ -0,0 +1,87 @@
+/**
+ * LOGBack: the reliable, fast and flexible logging library for Java.
+ *
+ * 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.spi;
+
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.status.ErrorStatus;
+import ch.qos.logback.core.status.InfoStatus;
+import ch.qos.logback.core.status.Status;
+import ch.qos.logback.core.status.StatusManager;
+import ch.qos.logback.core.status.WarnStatus;
+
+
+/**
+ * A helper class that implements ContextAware methods. This class can be either
+ * extended or alternatively included as a component.
+ * 
+ * @author Ceki G&uumllc&uuml;
+ */
+public class ContextAwareImpl implements ContextAware {
+
+  private int noContextWarning = 0;
+  protected Context context;
+
+  public void setContext(Context context) {
+    if (this.context == null) {
+      this.context = context;
+    } else if (this.context != context) {
+      throw new IllegalStateException("Context has been already set");
+    }
+  }
+
+  public Context getContext() {
+    return this.context;
+  }
+
+  public StatusManager getStatusManager() {
+    if (context == null) {
+      return null;
+    }
+    return context.getStatusManager();
+  }
+
+  public void addStatus(Status status) {
+    if (context == null) {
+      if (noContextWarning++ == 0) {
+        System.out.println("LOGBACK: No context given for " + this);
+      }
+      return;
+    }
+    StatusManager sm = context.getStatusManager();
+    if (sm != null) {
+      sm.add(status);
+    }
+  }
+
+  public void addInfo(String msg) {
+    addStatus(new InfoStatus(msg, this));
+  }
+
+  public void addInfo(String msg, Throwable ex) {
+    addStatus(new InfoStatus(msg, this, ex));
+  }
+
+  public void addWarn(String msg) {
+    addStatus(new WarnStatus(msg, this));
+  }
+
+  public void addWarn(String msg, Throwable ex) {
+    addStatus(new WarnStatus(msg, this, ex));
+  }
+
+  public void addError(String msg) {
+    addStatus(new ErrorStatus(msg, this));
+  }
+
+  public void addError(String msg, Throwable ex) {
+    addStatus(new ErrorStatus(msg, this, ex));
+  }
+
+}

Added: logback/trunk/logback-core/src/test/input/joran/ampEvent.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/input/joran/ampEvent.xml	Sun Oct 15 19:44:14 2006
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<test>xxx &amp; yyy</test>

Modified: logback/trunk/logback-core/src/test/input/joran/event1.xml
==============================================================================
--- logback/trunk/logback-core/src/test/input/joran/event1.xml	(original)
+++ logback/trunk/logback-core/src/test/input/joran/event1.xml	Sun Oct 15 19:44:14 2006
@@ -9,6 +9,6 @@
     <touch/>
   </badBegin>  
 
-  <hello name="John Doe">XXX</hello>
+  <hello name="John Doe">XXX&amp;</hello>
   
 </test>
\ No newline at end of file

Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllTest.java	Sun Oct 15 19:44:14 2006
@@ -15,7 +15,7 @@
     suite.addTest(ch.qos.logback.core.appender.PackageTest.suite());
     suite.addTest(ch.qos.logback.core.rolling.helper.PackageTest.suite());
     suite.addTest(ch.qos.logback.core.rolling.PackageTest.suite());
-    suite.addTest(ch.qos.logback.core.joran.spi.PackageTest.suite());
+    suite.addTest(ch.qos.logback.core.joran.PackageTest.suite());
     return suite;
   }
 }

Copied: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/EventRecorderTest.java (from r678, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/EventInterpreterTest.java)
==============================================================================
--- /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/EventInterpreterTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/EventRecorderTest.java	Sun Oct 15 19:44:14 2006
@@ -9,19 +9,23 @@
  */
 package ch.qos.logback.core.joran;
 
+import java.io.FileInputStream;
+import java.util.List;
+
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 
+import junit.framework.Test;
 import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import ch.qos.logback.core.Context;
 import ch.qos.logback.core.ContextBase;
-import ch.qos.logback.core.joran.spi.ExecutionContext;
-import ch.qos.logback.core.joran.spi.Interpreter;
-import ch.qos.logback.core.joran.spi.RuleStore;
+import ch.qos.logback.core.joran.spi.BodyEvent;
 import ch.qos.logback.core.joran.spi.SaxEvent;
-import ch.qos.logback.core.joran.spi.SimpleRuleStore;
+import ch.qos.logback.core.joran.spi.SaxEventRecorder;
+import ch.qos.logback.core.status.Status;
+import ch.qos.logback.core.status.StatusManager;
 import ch.qos.logback.core.util.Constants;
-import ch.qos.logback.core.util.StatusPrinter;
-
 
 /**
  * Test the way Interpreter skips elements in case of exceptions thrown by
@@ -29,9 +33,11 @@
  * 
  * @author Ceki Gulcu
  */
-public class EventInterpreterTest extends TestCase {
+public class EventRecorderTest extends TestCase {
+
+  Context context =  new ContextBase();
 
-  public EventInterpreterTest(String name) {
+  public EventRecorderTest(String name) {
     super(name);
   }
 
@@ -50,7 +56,23 @@
     SAXParserFactory spf = SAXParserFactory.newInstance();
     return spf.newSAXParser();
   }
-
+  
+  public List<SaxEvent> doTest(String filename) throws Exception {
+    SaxEventRecorder recorder = new SaxEventRecorder();
+    recorder.setContext(context);
+    FileInputStream fis = new FileInputStream(Constants.TEST_DIR_PREFIX
+        + "input/joran/"+ filename);
+    recorder.recordEvents(fis);
+    return  recorder.getSaxEventList();
+    
+ 
+  }
+ 
+  public void dump(List<SaxEvent> seList) {
+    for (SaxEvent se : seList) {
+      System.out.println(se);
+    }
+  }
   /**
    * Tests that whenever an action throws an exception, processing of child
    * elements is skipped.
@@ -58,28 +80,30 @@
    * @throws Exception
    */
   public void test1() throws Exception {
-    RuleStore rs = new SimpleRuleStore(new ContextBase());
-    
-    Interpreter jp = new Interpreter(rs);
-    ExecutionContext ec = jp.getExecutionContext();
-    ec.setContext(new ContextBase());
+    List<SaxEvent> seList = doTest("event1.xml");
+    StatusManager sm = context.getStatusManager();
+    assertTrue(sm.getLevel() == Status.INFO);
+    //dump(seList);  
+    assertEquals(11, seList.size());
     
-    SAXParser saxParser = createParser();
-    saxParser.parse("file:" + Constants.TEST_DIR_PREFIX + "input/joran/event1.xml", jp);
-   
-    StatusPrinter.print(ec.getStatusManager());
-    for(SaxEvent se : jp.saxEventList) {
-      System.out.println(se);
-    }
+  }
 
-   }
+  public void test2() throws Exception {
+    List<SaxEvent> seList = doTest("ampEvent.xml");
+    StatusManager sm = context.getStatusManager();
+    assertTrue(sm.getLevel() == Status.INFO);
+    dump(seList);  
+    assertEquals(3, seList.size());
+    
+    BodyEvent be = (BodyEvent) seList.get(1);
+    assertEquals("xxx & yyy", be.getText());
+  }
 
- 
-//  public static Test suite() {
-//    TestSuite suite = new TestSuite();
-//    //suite.addTest(new SkippingInInterpreterTest("testSkipSiblings2"));
-//    suite.addTestSuite(SkippingInInterpreterTest.class);
-//    return suite;
-//  }
+  public static Test XXXsuite() {
+    TestSuite suite = new TestSuite();
+    suite.addTest(new EventRecorderTest("test2"));
+    // suite.addTestSuite(SkippingInInterpreterTest.class);
+    return suite;
+  }
 
 }

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java	Sun Oct 15 19:44:14 2006
@@ -0,0 +1,17 @@
+package ch.qos.logback.core.joran;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class PackageTest extends TestCase {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    suite.addTestSuite(SkippingInInterpreterTest.class);
+    suite.addTestSuite(EventRecorderTest.class);
+    suite.addTestSuite(TrivialcConfiguratorTest.class);
+    suite.addTest(ch.qos.logback.core.joran.spi.PackageTest.suite());
+    return suite;
+  }
+}

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfigurator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfigurator.java	Sun Oct 15 19:44:14 2006
@@ -0,0 +1,20 @@
+package ch.qos.logback.core.joran;
+
+import ch.qos.logback.core.joran.action.IncAction;
+import ch.qos.logback.core.joran.spi.Interpreter;
+import ch.qos.logback.core.joran.spi.Pattern;
+import ch.qos.logback.core.joran.spi.RuleStore;
+
+public class TrivialConfigurator extends GenericConfigurator {
+
+  @Override
+  protected void addImpliciutRules(Interpreter interpreter) {
+  }
+
+  @Override
+  protected void addInstanceRules(RuleStore rs) {
+    rs.addRule(new Pattern("x/inc"), new IncAction());
+
+  }
+
+}

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialcConfiguratorTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialcConfiguratorTest.java	Sun Oct 15 19:44:14 2006
@@ -0,0 +1,42 @@
+package ch.qos.logback.core.joran;
+
+import junit.framework.TestCase;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.ContextBase;
+import ch.qos.logback.core.joran.action.IncAction;
+import ch.qos.logback.core.util.Constants;
+
+public class TrivialcConfiguratorTest extends TestCase {
+
+  Context context = new ContextBase();
+  
+  public TrivialcConfiguratorTest(String arg0) {
+    super(arg0);
+  }
+
+  protected void setUp() throws Exception {
+    super.setUp();
+  }
+
+  protected void tearDown() throws Exception {
+    super.tearDown();
+  }
+  
+  public void doTest(String filename) throws Exception {
+
+    TrivialConfigurator gc = new TrivialConfigurator();
+    gc.setContext(context);
+    gc.doConfigure(Constants.TEST_DIR_PREFIX
+        + "input/joran/"+ filename);
+  }
+  
+  public void test() throws Exception {
+    int oldBeginCount = IncAction.beginCount;
+    int oldEndCount = IncAction.endCount;
+    doTest("inc.xml");
+    assertEquals(oldBeginCount+1, IncAction.beginCount);
+    assertEquals(oldEndCount+1, IncAction.endCount);
+
+  }
+
+}

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncAction.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncAction.java	Sun Oct 15 19:44:14 2006
@@ -0,0 +1,41 @@
+/**
+ * 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.ExecutionContext;
+
+
+
+public class IncAction extends Action {
+
+  static public int  beginCount;
+  static public int  endCount;
+
+  /**
+   * Instantiates an layout of the given class and sets its name.
+   *
+   */
+  public void begin(ExecutionContext ec, String name, Attributes attributes) {
+    System.out.println("IncAction Begin called");
+    beginCount++;
+  }
+
+  /**
+   * Once the children elements are also parsed, now is the time to activate
+   * the appender options.
+   */
+  public void end(ExecutionContext ec, String name) {
+    endCount++;
+  }
+}



More information about the logback-dev mailing list