svn commit: r1891 - in logback/trunk: logback-core/src/main/java/ch/qos/logback/core 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/spi logback-core/src/test/java/ch/qos/logback/core/joran/action logback-core/src/test/resources/asResource logback-core/src/test/resources/asResource/joran logback-core/src/test/resources/input logback-examples/src/main/java/chapter3 logback-examples/sr

Author: ceki Date: Tue Oct 28 15:46:33 2008 New Revision: 1891 Added: logback/trunk/logback-core/src/test/resources/asResource/ - copied from r1859, /logback/trunk/logback-core/src/test/resources/input/ logback/trunk/logback-core/src/test/resources/asResource/joran/propertyActionTest.properties logback/trunk/logback-examples/src/main/resources/resource1.properties Removed: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/SubstitutionPropertyAction.java logback/trunk/logback-core/src/test/resources/input/ Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/FileAppender.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/ContextPropertyAction.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java logback/trunk/logback-examples/src/main/java/chapter3/MyApp2.java logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml Log: Fixed LBCORE-43 Properties can be read from a resource as well as file or "key/value" pairs. Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/FileAppender.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/FileAppender.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/FileAppender.java Tue Oct 28 15:46:33 2008 @@ -87,6 +87,8 @@ public void start() { int errors = 0; if (fileName != null) { + addInfo("filename set to ["+fileName+"]"); + // In case both bufferedIO and immediateFlush are set, the former // takes priority because 'immediateFlush' is set to true by default. // If the user explicitly set bufferedIO, then we should follow her 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 Tue Oct 28 15:46:33 2008 @@ -23,8 +23,8 @@ import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; import ch.qos.logback.core.joran.action.NewRuleAction; import ch.qos.logback.core.joran.action.ParamAction; +import ch.qos.logback.core.joran.action.PropertyAction; import ch.qos.logback.core.joran.action.StatusListenerAction; -import ch.qos.logback.core.joran.action.SubstitutionPropertyAction; import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.joran.spi.Interpreter; import ch.qos.logback.core.joran.spi.Pattern; @@ -52,10 +52,18 @@ @Override protected void addInstanceRules(RuleStore rs) { + + rs.addRule(new Pattern("configuration/property"), + new PropertyAction()); + rs.addRule(new Pattern("configuration/substitutionProperty"), - new SubstitutionPropertyAction()); + new PropertyAction()); + + // the contextProperty pattern is deprecated. It is undocumented + // and will be dropped in future versions of logback rs.addRule(new Pattern("configuration/contextProperty"), new ContextPropertyAction()); + rs.addRule(new Pattern("configuration/conversionRule"), new ConversionRuleAction()); Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ContextPropertyAction.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ContextPropertyAction.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ContextPropertyAction.java Tue Oct 28 15:46:33 2008 @@ -1,28 +1,23 @@ - package ch.qos.logback.core.joran.action; -import java.util.Properties; +import org.xml.sax.Attributes; +import ch.qos.logback.core.joran.spi.ActionException; import ch.qos.logback.core.joran.spi.InterpretationContext; - /** * @author Ceki Gulcu */ -public class ContextPropertyAction extends PropertyAction { - - /** - * Add all the properties found in the argument named 'props' to an InterpretationContext. - */ - public void setProperties(InterpretationContext ec, Properties props) { - // TODO : test this method - for(Object o: props.keySet()) { - String key = (String) o; - this.context.putProperty(key, props.getProperty(key)); - } +public class ContextPropertyAction extends Action { + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + addError("The [contextProperty] element has been removed. Please use [substitutionProperty] element instead"); } - - public void setProperty(InterpretationContext ec, String key, String value) { - this.context.putProperty(key, value); + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { } + } Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/PropertyAction.java Tue Oct 28 15:46:33 2008 @@ -1,7 +1,7 @@ /** - * LOGBack: the generic, reliable, fast and flexible logging framework. + * Logback: the generic, reliable, fast and flexible logging framework. * - * Copyright (C) 1999-2006, QOS.ch + * Copyright (C) 2000-2008, 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 @@ -13,68 +13,135 @@ import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.pattern.util.RegularEscapeUtil; +import ch.qos.logback.core.util.Loader; import ch.qos.logback.core.util.OptionHelper; - import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.net.URL; import java.util.Properties; /** - * This class serves as a base for other actions, which similar to the ANT + * This class serves as a base for other actions, which similar to the ANT * <property> task which add/set properties of a given object. * + * This action sets new substitution properties in the logging context by name, + * value pair, or adds all the properties passed in "file" or "resource" + * attribute. + * * @author Ceki Gülcü */ -abstract public class PropertyAction extends Action { - static String INVALID_ATTRIBUTES = - "In <property> element, either the \"file\" attribute or both the \"name\" and \"value\" attributes must be set."; - - - abstract void setProperties(InterpretationContext ec, Properties props); - abstract void setProperty(InterpretationContext ec, String key, String value); - +public class PropertyAction extends Action { + + static final String RESOURCE_ATTRIBUTE = "resource"; + + static String INVALID_ATTRIBUTES = "In <substitutionProperty> element, either the \"file\" attribute alone, or " + + "the \"resource\" element alone, or both the \"name\" and \"value\" attributes must be set."; + + /** + * Add all the properties found in the argument named 'props' to an + * InterpretationContext. + */ + public void setProperties(InterpretationContext ec, Properties props) { + ec.addSubstitutionProperties(props); + } + + public void setProperty(InterpretationContext ec, String key, String value) { + ec.addSubstitutionProperty(key, value); + } + /** * Set a new property for the execution context by name, value pair, or adds * all the properties found in the given file. - * + * */ - public void begin( - InterpretationContext ec, String localName, Attributes attributes) { + public void begin(InterpretationContext ec, String localName, + Attributes attributes) { + + if ("substitutionProperty".equals(localName)) { + addWarn("[substitutionProperty] element has been deprecated. Plase use the [property] element instead."); + } + String name = attributes.getValue(NAME_ATTRIBUTE); String value = attributes.getValue(VALUE_ATTRIBUTE); - String fileName = attributes.getValue(FILE_ATTRIBUTE); - - if ( - !OptionHelper.isEmpty(fileName) - && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value))) { - Properties props = new Properties(); + if (checkFileAttributeSanity(attributes)) { + String file = attributes.getValue(FILE_ATTRIBUTE); + file = ec.subst(file); try { - FileInputStream istream = new FileInputStream(fileName); - props.load(istream); - istream.close(); - setProperties(ec, props); + FileInputStream istream = new FileInputStream(file); + loadAndSetProperties(ec, istream); } catch (IOException e) { - String errMsg = "Could not read properties file [" + fileName + "]."; - addError(errMsg, e); - addError("Ignoring configuration file [" + fileName + "]."); - + addError("Could not read properties file [" + file + "].", e); } - } else if ( - !(OptionHelper.isEmpty(name) || OptionHelper.isEmpty(value)) - && OptionHelper.isEmpty(fileName)) { + } else if (checkResourceAttributeSanity(attributes)) { + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + resource = ec.subst(resource); + URL resourceURL = Loader.getResourceBySelfClassLoader(resource); + if (resourceURL == null) { + addError("Could not find resource [" + resource + "]."); + } else { + try { + InputStream istream = resourceURL.openStream(); + loadAndSetProperties(ec, istream); + } catch (IOException e) { + addError("Could not read resource file [" + resource + "].", e); + } + } + } else if (checkValueNameAttributesSanity(attributes)) { value = RegularEscapeUtil.basicEscape(value); // now remove both leading and trailing spaces value = value.trim(); + value = ec.subst(value); setProperty(ec, name, value); + } else { - addError(INVALID_ATTRIBUTES); } } + void loadAndSetProperties(InterpretationContext ec, InputStream istream) + throws IOException { + Properties props = new Properties(); + props.load(istream); + istream.close(); + setProperties(ec, props); + } + + boolean checkFileAttributeSanity(Attributes attributes) { + String file = attributes.getValue(FILE_ATTRIBUTE); + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + + return !(OptionHelper.isEmpty(file)) + && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper + .isEmpty(resource)); + } + + boolean checkResourceAttributeSanity(Attributes attributes) { + String file = attributes.getValue(FILE_ATTRIBUTE); + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + + return !(OptionHelper.isEmpty(resource)) + && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper + .isEmpty(file)); + } + + boolean checkValueNameAttributesSanity(Attributes attributes) { + String file = attributes.getValue(FILE_ATTRIBUTE); + String name = attributes.getValue(NAME_ATTRIBUTE); + String value = attributes.getValue(VALUE_ATTRIBUTE); + String resource = attributes.getValue(RESOURCE_ATTRIBUTE); + + return (!(OptionHelper.isEmpty(name) || OptionHelper.isEmpty(value)) && (OptionHelper + .isEmpty(file) && OptionHelper.isEmpty(resource))); + } + public void end(InterpretationContext ec, String name) { } Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/spi/AppenderAttachableImpl.java Tue Oct 28 15:46:33 2008 @@ -43,7 +43,6 @@ appenderList.add(newAppender); } w.unlock(); - } /** Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/IncludeActionTest.java Tue Oct 28 15:46:33 2008 @@ -53,7 +53,7 @@ static final String INVALID = INCLUSION_DIR_PREFIX + "invalid.xml"; - static final String INCLUDED_AS_RESOURCE = "input/joran/inclusion/includedAsResource.xml"; + static final String INCLUDED_AS_RESOURCE = "asResource/joran/inclusion/includedAsResource.xml"; public IncludeActionTest() { HashMap<Pattern, Action> rulesMap = new HashMap<Pattern, Action>(); Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PackageTest.java Tue Oct 28 15:46:33 2008 @@ -18,7 +18,7 @@ public static Test suite() { TestSuite suite = new TestSuite(); - suite.addTestSuite(PropertyActionTest.class); + suite.addTest(new JUnit4TestAdapter(PropertyActionTest.class)); suite.addTest(new JUnit4TestAdapter(IncludeActionTest.class)); return suite; Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java Tue Oct 28 15:46:33 2008 @@ -1,38 +1,43 @@ package ch.qos.logback.core.joran.action; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.util.Iterator; -import junit.framework.TestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + import ch.qos.logback.core.Context; import ch.qos.logback.core.ContextBase; import ch.qos.logback.core.joran.spi.InterpretationContext; import ch.qos.logback.core.status.ErrorStatus; import ch.qos.logback.core.util.Constants; -public class PropertyActionTest extends TestCase { +public class PropertyActionTest { Context context; InterpretationContext ec; - SubstitutionPropertyAction spAction; + PropertyAction spAction; DummyAttributes atts = new DummyAttributes(); - @Override - protected void setUp() throws Exception { + @Before + public void setUp() throws Exception { context = new ContextBase(); ec = new InterpretationContext(context, null); - spAction = new SubstitutionPropertyAction(); + spAction = new PropertyAction(); spAction.setContext(context); - super.setUp(); } - @Override - protected void tearDown() throws Exception { + @After + public void tearDown() throws Exception { context = null; spAction = null; atts = null; - super.tearDown(); } + @Test public void testBegin() { atts.setValue("name", "v1"); atts.setValue("value", "work"); @@ -40,6 +45,7 @@ assertEquals("work", ec.getSubstitutionProperty("v1")); } + @Test public void testBeginNoValue() { atts.setValue("name", "v1"); spAction.begin(ec, null, atts); @@ -47,6 +53,7 @@ assertTrue(checkError()); } + @Test public void testBeginNoName() { atts.setValue("value", "v1"); spAction.begin(ec, null, atts); @@ -54,12 +61,14 @@ assertTrue(checkError()); } + @Test public void testBeginNothing() { spAction.begin(ec, null, atts); assertEquals(1, context.getStatusManager().getCount()); assertTrue(checkError()); } + @Test public void testFileNotLoaded() { atts.setValue("file", "toto"); atts.setValue("value", "work"); @@ -68,17 +77,45 @@ assertTrue(checkError()); } + @Test + public void testLoadFileWithPrerequisiteSubsitution() { + context.putProperty("STEM", Constants.TEST_DIR_PREFIX + "input/joran"); + atts.setValue("file", "${STEM}/propertyActionTest.properties"); + spAction.begin(ec, null, atts); + assertEquals("tata", ec.getSubstitutionProperty("v1")); + assertEquals("toto", ec.getSubstitutionProperty("v2")); + } + + @Test public void testLoadFile() { atts.setValue("file", Constants.TEST_DIR_PREFIX + "input/joran/propertyActionTest.properties"); spAction.begin(ec, null, atts); assertEquals("tata", ec.getSubstitutionProperty("v1")); assertEquals("toto", ec.getSubstitutionProperty("v2")); } + + @Test + public void testLoadResource() { + atts.setValue("resource", "asResource/joran/propertyActionTest.properties"); + spAction.begin(ec, null, atts); + assertEquals("tata", ec.getSubstitutionProperty("r1")); + assertEquals("toto", ec.getSubstitutionProperty("r2")); + } + @Test + public void testLoadResourceWithPrerequisiteSubsitution() { + context.putProperty("STEM", "asResource/joran"); + atts.setValue("resource", "${STEM}/propertyActionTest.properties"); + spAction.begin(ec, null, atts); + assertEquals("tata", ec.getSubstitutionProperty("r1")); + assertEquals("toto", ec.getSubstitutionProperty("r2")); + } + + @Test public void testLoadNotPossible() { atts.setValue("file", "toto"); spAction.begin(ec, null, atts); - assertEquals(2, context.getStatusManager().getCount()); + assertEquals(1, context.getStatusManager().getCount()); assertTrue(checkFileErrors()); } @@ -91,9 +128,6 @@ private boolean checkFileErrors() { Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); ErrorStatus es1 = (ErrorStatus)it.next(); - boolean result1 = "Could not read properties file [toto].".equals(es1.getMessage()); - ErrorStatus es2 = (ErrorStatus)it.next(); - boolean result2 = "Ignoring configuration file [toto].".equals(es2.getMessage()); - return result1 && result2; + return "Could not read properties file [toto].".equals(es1.getMessage()); } } Added: logback/trunk/logback-core/src/test/resources/asResource/joran/propertyActionTest.properties ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/test/resources/asResource/joran/propertyActionTest.properties Tue Oct 28 15:46:33 2008 @@ -0,0 +1,2 @@ +r1=tata +r2=toto \ No newline at end of file Modified: logback/trunk/logback-examples/src/main/java/chapter3/MyApp2.java ============================================================================== --- logback/trunk/logback-examples/src/main/java/chapter3/MyApp2.java (original) +++ logback/trunk/logback-examples/src/main/java/chapter3/MyApp2.java Tue Oct 28 15:46:33 2008 @@ -1,7 +1,7 @@ /** - * Logback: the reliable, generic, fast and flexible logging framework. + * Logback: the generic, reliable, fast and flexible logging framework. * - * Copyright (C) 1999-2006, QOS.ch + * Copyright (C) 2000-2008, 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 Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml ============================================================================== --- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml (original) +++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml Tue Oct 28 15:46:33 2008 @@ -1,6 +1,6 @@ <configuration> - <substitutionProperty name="USER_HOME" value="/home/sebastien" /> + <property name="USER_HOME" value="/home/sebastien" /> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_HOME}/myApp.log</file> @@ -9,8 +9,7 @@ </layout> </appender> - <root> - <level value="debug" /> + <root level="debug"> <appender-ref ref="FILE" /> </root> </configuration> \ No newline at end of file Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml ============================================================================== --- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml (original) +++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml Tue Oct 28 15:46:33 2008 @@ -7,8 +7,7 @@ </layout> </appender> - <root> - <level value="debug" /> + <root level="debug"> <appender-ref ref="FILE" /> </root> </configuration> \ No newline at end of file Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml ============================================================================== --- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml (original) +++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml Tue Oct 28 15:46:33 2008 @@ -1,6 +1,6 @@ <configuration> - <substitutionProperty file="variables1.properties" /> + <property file="src/main/java/chapter3/variables1.properties" /> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_HOME}/myApp.log</file> @@ -9,8 +9,7 @@ </layout> </appender> - <root> - <level value="debug" /> + <root level="debug"> <appender-ref ref="FILE" /> </root> </configuration> \ No newline at end of file Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml ============================================================================== --- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml (original) +++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml Tue Oct 28 15:46:33 2008 @@ -1,6 +1,6 @@ <configuration> - <substitutionProperty file="variables2.properties" /> + <property file="src/main/java/chapter3/variables2.properties" /> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${destination}/myApp.log</file> @@ -9,8 +9,7 @@ </layout> </appender> - <root> - <level value="debug" /> + <root level="debug"> <appender-ref ref="FILE" /> </root> </configuration> \ No newline at end of file Added: logback/trunk/logback-examples/src/main/resources/resource1.properties ============================================================================== --- (empty file) +++ logback/trunk/logback-examples/src/main/resources/resource1.properties Tue Oct 28 15:46:33 2008 @@ -0,0 +1 @@ +USER_HOME=/home/sebastien \ No newline at end of file
participants (1)
-
noreply.ceki@qos.ch