
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é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> - * <b>Usage:</b> java ch.qos.logback.classic.net.SimpleSocketServer port configFile - * - * where + * <b>Usage:</b> 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ülcü @@ -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> - * <b>Usage:</b> java ch.qos.logback.classic.net.SocketServer port configFile configDir - * - * where <b>port</b> is a part number where the server listens, - * <b>configFile</b> is an xml configuration file fed to the {@link JoranConfigurator} and - * <b>configDir</b> is a path to a directory containing configuration files, possibly one for each client host. + * <b>Usage:</b> java ch.qos.logback.classic.net.SocketServer port configFile configDir + * + * where <b>port</b> is a part number where the server listens, + * <b>configFile</b> is an xml configuration file fed to the {@link JoranConfigurator} and + * <b>configDir</b> is a path to a directory containing configuration files, possibly one for each client host. * </pre> * * <p> @@ -72,132 +74,137 @@ * * * @author Ceki Gülcü - * - * @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ülcü */ -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ülcü */ -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ülcü + */ +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 & 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&</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++; + } +}