Index: logback-core/src/test/input/joran/define/noclass.xml
===================================================================
--- logback-core/src/test/input/joran/define/noclass.xml Thu Feb 04 20:11:13 GMT+04:00 2010
+++ logback-core/src/test/input/joran/define/noclass.xml Thu Feb 04 20:11:13 GMT+04:00 2010
@@ -0,0 +1,3 @@
+
+ Monster
+
\ No newline at end of file
Index: logback-core/src/test/input/joran/define/good.xml
===================================================================
--- logback-core/src/test/input/joran/define/good.xml Thu Feb 04 20:28:31 GMT+04:00 2010
+++ logback-core/src/test/input/joran/define/good.xml Thu Feb 04 20:28:31 GMT+04:00 2010
@@ -0,0 +1,3 @@
+
+ Monster
+
\ No newline at end of file
Index: logback-core/src/main/java/ch/qos/logback/core/spi/PropertyDefiner.java
===================================================================
--- logback-core/src/main/java/ch/qos/logback/core/spi/PropertyDefiner.java Fri Mar 26 12:12:13 GMT+04:00 2010
+++ logback-core/src/main/java/ch/qos/logback/core/spi/PropertyDefiner.java Fri Mar 26 12:12:13 GMT+04:00 2010
@@ -0,0 +1,10 @@
+package ch.qos.logback.core.spi;
+
+public interface PropertyDefiner extends ContextAware {
+
+ /**
+ * Get the property value, defined by this property definer
+ * @return defined property value
+ */
+ String getPropertyValue();
+}
Index: logback-core/src/test/input/joran/define/noname.xml
===================================================================
--- logback-core/src/test/input/joran/define/noname.xml Thu Feb 04 20:28:31 GMT+04:00 2010
+++ logback-core/src/test/input/joran/define/noname.xml Thu Feb 04 20:28:31 GMT+04:00 2010
@@ -0,0 +1,3 @@
+
+ Monster
+
\ No newline at end of file
Index: logback-core/src/main/java/ch/qos/logback/core/joran/action/DefinePropertyAction.java
===================================================================
--- logback-core/src/main/java/ch/qos/logback/core/joran/action/DefinePropertyAction.java Fri Mar 26 12:11:15 GMT+04:00 2010
+++ logback-core/src/main/java/ch/qos/logback/core/joran/action/DefinePropertyAction.java Fri Mar 26 12:11:15 GMT+04:00 2010
@@ -0,0 +1,86 @@
+package ch.qos.logback.core.joran.action;
+
+import ch.qos.logback.core.joran.spi.InterpretationContext;
+import ch.qos.logback.core.joran.spi.ActionException;
+import ch.qos.logback.core.util.OptionHelper;
+import ch.qos.logback.core.spi.PropertyDefiner;
+import org.xml.sax.Attributes;
+
+
+/**
+ * Instantiate class for define property value.
+ * Get future property name and property definer class from attributes.
+ * Some property definer properties could be used.
+ * After defining put new property to context.
+ *
+ * @author Aleksey Didik
+ */
+public class DefinePropertyAction extends Action {
+
+ String propertyName;
+ PropertyDefiner definer;
+ boolean inError;
+
+ public void begin(InterpretationContext ec,
+ String localName,
+ Attributes attributes) throws ActionException {
+ //reset variables
+ propertyName = null;
+ definer = null;
+ inError = false;
+
+ //read future property name
+ propertyName = attributes.getValue(NAME_ATTRIBUTE);
+ if (OptionHelper.isEmpty(propertyName)) {
+ addError("Missing property name for property definer. Near [" + localName
+ + "] line " + getLineNumber(ec));
+ inError = true;
+ return;
+ }
+
+ //read property definer class name
+ String className = attributes.getValue(CLASS_ATTRIBUTE);
+ if (OptionHelper.isEmpty(className)) {
+ addError("Missing class name for property definer. Near [" + localName
+ + "] line " + getLineNumber(ec));
+ inError = true;
+ return;
+ }
+
+ //try to instantiate property definer
+ try {
+ addInfo("About to instantiate property definer of type [" + className + "]");
+ definer = (PropertyDefiner) OptionHelper.instantiateByClassName(className,
+ PropertyDefiner.class, context);
+ definer.setContext(context);
+ ec.pushObject(definer);
+ } catch (Exception oops) {
+ inError = true;
+ addError("Could not create an PropertyDefiner of type [" + className + "].",
+ oops);
+ throw new ActionException(oops);
+ }
+ }
+
+ /**
+ * Now property definer is initialized by all properties and we can put property value to context
+ */
+ public void end(InterpretationContext ec, String name) {
+ if (inError) {
+ return;
+ }
+
+ Object o = ec.peekObject();
+
+ if (o != definer) {
+ addWarn("The object at the of the stack is not the property definer for property named ["
+ + propertyName + "] pushed earlier.");
+ } else {
+ addInfo("Popping property definer for property named [" + propertyName
+ + "] from the object stack");
+ ec.popObject();
+ //let's put defined property and value to context
+ context.putProperty(propertyName, definer.getPropertyValue());
+ }
+ }
+}
Index: logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java
===================================================================
--- logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java (revision 382f13d26b9718c7a5c3a467fcda487016dd3a17)
+++ logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java Fri Mar 26 12:12:13 GMT+04:00 2010
@@ -13,27 +13,16 @@
*/
package ch.qos.logback.core.joran;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import ch.qos.logback.core.joran.action.ActionConst;
-import ch.qos.logback.core.joran.action.AppenderAction;
-import ch.qos.logback.core.joran.action.AppenderRefAction;
-import ch.qos.logback.core.joran.action.ContextPropertyAction;
-import ch.qos.logback.core.joran.action.ConversionRuleAction;
-import ch.qos.logback.core.joran.action.NestedBasicPropertyIA;
-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.TimestampAction;
+import ch.qos.logback.core.joran.action.*;
import ch.qos.logback.core.joran.spi.InterpretationContext;
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 java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
// Based on 310985 revision 310985 as attested by http://tinyurl.com/8njps
// see also http://tinyurl.com/c2rp5
@@ -65,7 +54,10 @@
rs.addRule(new Pattern("configuration/timestamp"),
new TimestampAction());
-
+
+ rs.addRule(new Pattern("configuration/define"),
+ new DefinePropertyAction());
+
// the contextProperty pattern is deprecated. It is undocumented
// and will be dropped in future versions of logback
rs.addRule(new Pattern("configuration/contextProperty"),
Index: logback-core/src/test/java/ch/qos/logback/core/joran/action/DefinePropertyActionTest.java
===================================================================
--- logback-core/src/test/java/ch/qos/logback/core/joran/action/DefinePropertyActionTest.java Fri Mar 26 12:15:00 GMT+04:00 2010
+++ logback-core/src/test/java/ch/qos/logback/core/joran/action/DefinePropertyActionTest.java Fri Mar 26 12:15:00 GMT+04:00 2010
@@ -0,0 +1,113 @@
+package ch.qos.logback.core.joran.action;
+
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.ContextBase;
+import ch.qos.logback.core.joran.SimpleConfigurator;
+import ch.qos.logback.core.joran.spi.InterpretationContext;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.joran.spi.Pattern;
+import ch.qos.logback.core.status.ErrorStatus;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import org.junit.After;
+import static org.junit.Assert.assertTrue;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Test {@link DefinePropertyAction}.
+ *
+ * @author Aleksey Didik
+ */
+public class DefinePropertyActionTest {
+
+ private static final String DEFINE_XML_DIR = "src/test/input/joran/define/";
+ private static final String GOOD_XML = "good.xml";
+ private static final String NONAME_XML = "noname.xml";
+ private static final String NOCLASS_XML = "noclass.xml";
+ private static final String BADCLASS_XML = "badclass.xml";
+
+ SimpleConfigurator sc;
+ Context context;
+ DefinePropertyAction definerAction;
+ InterpretationContext ic;
+
+ @Before
+ public void setUp() throws Exception {
+ context = new ContextBase();
+ HashMap rulesMap = new HashMap();
+ rulesMap.put(new Pattern("define"), new DefinePropertyAction());
+ sc = new SimpleConfigurator(rulesMap);
+ sc.setContext(context);
+
+ }
+
+ @Test
+ public void testAllRight() throws JoranException {
+ sc.doConfigure(DEFINE_XML_DIR + GOOD_XML);
+ //get from context
+ String inContextFoo = context.getProperty("foo");
+ //get from real class
+ FooPropertyDefiner fooDefiner = new FooPropertyDefiner();
+ fooDefiner.setFooName("Monster");
+ String fromRealClassFoo = fooDefiner.getPropertyValue();
+ assertEquals(inContextFoo, fromRealClassFoo);
+ }
+
+
+ @Test
+ public void testNoName() throws JoranException {
+ sc.doConfigure(DEFINE_XML_DIR + NONAME_XML);
+ //get from context
+ String inContextFoo = context.getProperty("foo");
+ assertNull(inContextFoo);
+ //check context errors
+ assertTrue(checkError("Missing property name for property definer. Near [define] line 1"));
+ }
+
+ @Test
+ public void testNoClass() throws JoranException {
+ sc.doConfigure(DEFINE_XML_DIR + NOCLASS_XML);
+ //get from context
+ String inContextFoo = context.getProperty("foo");
+ assertNull(inContextFoo);
+ //check context errors
+ assertTrue(checkError("Missing class name for property definer. Near [define] line 1"));
+ }
+
+ @Test
+ public void testBadClass() throws JoranException {
+ sc.doConfigure(DEFINE_XML_DIR + BADCLASS_XML);
+ //get from context
+ String inContextFoo = context.getProperty("foo");
+ assertNull(inContextFoo);
+ //check context errors
+ assertTrue(checkBadClassError());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ context = null;
+ sc = null;
+ }
+
+
+ private boolean checkError(String waitedMsg) {
+ Iterator it = context.getStatusManager().getCopyOfStatusList().iterator();
+ ErrorStatus es1 = (ErrorStatus) it.next();
+ return waitedMsg.equals(es1.getMessage());
+ }
+
+ private boolean checkBadClassError() {
+ Iterator it = context.getStatusManager().getCopyOfStatusList().iterator();
+ //skip info about class instantiating
+ it.next();
+ //check error status
+ ErrorStatus es1 = (ErrorStatus) it.next();
+ return "Could not create an PropertyDefiner of type [a.b.c.Foo].".equals(es1.getMessage());
+ }
+
+}
Index: logback-core/src/test/java/ch/qos/logback/core/joran/action/FooPropertyDefiner.java
===================================================================
--- logback-core/src/test/java/ch/qos/logback/core/joran/action/FooPropertyDefiner.java Fri Mar 26 12:11:15 GMT+04:00 2010
+++ logback-core/src/test/java/ch/qos/logback/core/joran/action/FooPropertyDefiner.java Fri Mar 26 12:11:15 GMT+04:00 2010
@@ -0,0 +1,24 @@
+package ch.qos.logback.core.joran.action;
+
+import ch.qos.logback.core.PropertyDefinerBase;/*
+* Project: Maxifier
+* Author: Aleksey Didik
+* Created: 04.02.2010
+*
+* Copyright (c) 1999-2010 Magenta Corporation Ltd. All Rights Reserved.
+* Magenta Technology proprietary and confidential.
+* Use is subject to license terms.
+*/
+
+public class FooPropertyDefiner extends PropertyDefinerBase {
+
+ private String fooName;
+
+ public String getPropertyValue() {
+ return "Foo[" + fooName + "]";
+ }
+
+ public void setFooName(String fooName) {
+ this.fooName = fooName;
+ }
+}
Index: logback-core/src/main/java/ch/qos/logback/core/PropertyDefinerBase.java
===================================================================
--- logback-core/src/main/java/ch/qos/logback/core/PropertyDefinerBase.java Fri Mar 26 12:11:15 GMT+04:00 2010
+++ logback-core/src/main/java/ch/qos/logback/core/PropertyDefinerBase.java Fri Mar 26 12:11:15 GMT+04:00 2010
@@ -0,0 +1,13 @@
+package ch.qos.logback.core;
+
+import ch.qos.logback.core.spi.ContextAwareBase;
+import ch.qos.logback.core.spi.PropertyDefiner;
+
+/**
+ * Set a skeleton implementation for property definers
+ * just for have ContextAwareBase.
+ *
+ * @author Aleksey Didik
+ */
+public abstract class PropertyDefinerBase extends ContextAwareBase implements PropertyDefiner {
+}
Index: logback-core/src/test/input/joran/define/badclass.xml
===================================================================
--- logback-core/src/test/input/joran/define/badclass.xml Thu Feb 04 20:27:17 GMT+04:00 2010
+++ logback-core/src/test/input/joran/define/badclass.xml Thu Feb 04 20:27:17 GMT+04:00 2010
@@ -0,0 +1,1 @@
+