logback-dev
Threads by month
- ----- 2025 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
July 2008
- 7 participants
- 41 discussions

svn commit: r1711 - in logback/trunk/logback-core/src/main/java/ch/qos/logback/core: . joran/spi
by noreply.ceki@qos.ch 18 Jul '08
by noreply.ceki@qos.ch 18 Jul '08
18 Jul '08
Author: ceki
Date: Fri Jul 18 15:47:05 2008
New Revision: 1711
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java
Log:
- added support for "valueOf" convention.
Joran now assumes that any class which has a static
valueOf method taking a String as an argument can
be built from a string.
Level, Duration and FileSize classes follow this convention.
This patch is indirectly related to LBCLASSIC-53
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java Fri Jul 18 15:47:05 2008
@@ -29,6 +29,15 @@
*/
static public final String EVALUATOR_MAP = "EVALUATOR_MAP";
+ /**
+ * By convention, we assume that the static method named "valueOf" taking
+ * a string argument can restore a given object from its string
+ * representation.
+ *
+ * <p>Classes participating in this convention must be declared
+ * as stringStorable in a (logback) context.
+ */
+ static public final String VALUE_OF = "valueOf";
/**
* An empty string.
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java Fri Jul 18 15:47:05 2008
@@ -23,12 +23,12 @@
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import ch.qos.logback.core.CoreGlobal;
import ch.qos.logback.core.joran.action.IADataForComplexProperty;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.util.AggregationType;
-import ch.qos.logback.core.util.Duration;
-import ch.qos.logback.core.util.FileSize;
import ch.qos.logback.core.util.PropertySetterException;
/**
@@ -207,7 +207,7 @@
Method adderMethod = getMethod("add" + name);
return adderMethod;
}
-
+
private Method findSetterMethod(String name) {
String dName = Introspector.decapitalize(name);
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName);
@@ -219,7 +219,7 @@
}
Class<?> getParameterClassForMethod(Method method) {
- if(method == null) {
+ if (method == null) {
return null;
}
Class[] classArray = method.getParameterTypes();
@@ -229,21 +229,20 @@
return classArray[0];
}
}
+
private AggregationType computeRawAggregationType(Method method) {
- Class<?> clazz = getParameterClassForMethod(method);
- if (clazz == null) {
+ Class<?> parameterClass = getParameterClassForMethod(method);
+ if (parameterClass == null) {
return AggregationType.NOT_FOUND;
} else {
- Package p = clazz.getPackage();
- if (clazz.isPrimitive()) {
+ Package p = parameterClass.getPackage();
+ if (parameterClass.isPrimitive()) {
return AggregationType.AS_BASIC_PROPERTY;
} else if (p != null && "java.lang".equals(p.getName())) {
return AggregationType.AS_BASIC_PROPERTY;
- } else if (Duration.class.isAssignableFrom(clazz)) {
- return AggregationType.AS_BASIC_PROPERTY;
- } else if (FileSize.class.isAssignableFrom(clazz)) {
+ } else if (isBuildableFromString(parameterClass)) {
return AggregationType.AS_BASIC_PROPERTY;
- } else if (clazz.isEnum()) {
+ } else if (parameterClass.isEnum()) {
return AggregationType.AS_BASIC_PROPERTY;
} else {
return AggregationType.AS_COMPLEX_PROPERTY;
@@ -257,9 +256,10 @@
AggregationType at = actionData.getAggregationType();
switch (at) {
case AS_COMPLEX_PROPERTY:
- Method setterMethod = findSetterMethod(actionData.getComplexPropertyName());
- clazz = getParameterClassForMethod(setterMethod);
- if(clazz != null && isUnequivocallyInstantiable(clazz)) {
+ Method setterMethod = findSetterMethod(actionData
+ .getComplexPropertyName());
+ clazz = getParameterClassForMethod(setterMethod);
+ if (clazz != null && isUnequivocallyInstantiable(clazz)) {
return clazz;
} else {
return null;
@@ -267,7 +267,7 @@
case AS_COMPLEX_PROPERTY_COLLECTION:
Method adderMethod = findAdderMethod(actionData.getComplexPropertyName());
clazz = getParameterClassForMethod(adderMethod);
- if(clazz != null && isUnequivocallyInstantiable(clazz)) {
+ if (clazz != null && isUnequivocallyInstantiable(clazz)) {
return clazz;
} else {
return null;
@@ -282,18 +282,22 @@
if (clazz.isInterface()) {
return false;
}
+ // checking for constructors would be slightly more elegant, but in
+ // classes
+ // without any declared constructors, Class.getConstructor() returns null.
+ Object o;
try {
- // checking for constructors would be slightly more elegant, but in classes
- // without any declared constructors, Class.getConstructor() returns null.
- Object o = clazz.newInstance();
- if(o != null) {
+ o = clazz.newInstance();
+ if (o != null) {
return true;
} else {
return false;
}
- } catch (Exception e) {
+ } catch (InstantiationException e) {
+ return false;
+ } catch (IllegalAccessException e) {
return false;
- }
+ }
}
public Class getObjClass() {
@@ -426,9 +430,7 @@
if (val == null) {
return null;
}
-
String v = val.trim();
-
if (String.class.isAssignableFrom(type)) {
return val;
} else if (Integer.TYPE.isAssignableFrom(type)) {
@@ -445,20 +447,47 @@
} else if ("false".equalsIgnoreCase(v)) {
return Boolean.FALSE;
}
- } else if (Duration.class.isAssignableFrom(type)) {
- return Duration.valueOf(val);
- } else if (FileSize.class.isAssignableFrom(type)) {
- return FileSize.valueOf(val);
} else if (type.isEnum()) {
return convertEnum(val, type);
+ } else if (isBuildableFromString(type)) {
+ return buildFromString(type, val);
}
return null;
}
+ boolean isBuildableFromString(Class<?> parameterClass) {
+ try {
+ Method valueOfMethod = parameterClass.getMethod(CoreGlobal.VALUE_OF,
+ STING_CLASS_PARAMETER);
+ int mod = valueOfMethod.getModifiers();
+ if (Modifier.isStatic(mod)) {
+ return true;
+ }
+ } catch (SecurityException e) {
+ // nop
+ } catch (NoSuchMethodException e) {
+ // nop
+ }
+ return false;
+ }
+
+ Object buildFromString(Class type, String val) {
+ try {
+ Method valueOfMethod = type.getMethod(CoreGlobal.VALUE_OF,
+ STING_CLASS_PARAMETER);
+ return valueOfMethod.invoke(null, val);
+ } catch (Exception e) {
+ addError("Failed to invoke " + CoreGlobal.VALUE_OF
+ + "{} method in class [" + type.getName() + "] with value [" + val
+ + "]");
+ return null;
+ }
+ }
+
protected Object convertEnum(String val, Class type) {
try {
- Method m = type.getMethod("valueOf", STING_CLASS_PARAMETER);
+ Method m = type.getMethod(CoreGlobal.VALUE_OF, STING_CLASS_PARAMETER);
return m.invoke(null, val);
} catch (Exception e) {
addError("Failed to convert value [" + val + "] to enum ["
@@ -467,7 +496,6 @@
return null;
}
-
protected Method getMethod(String methodName) {
if (methodDescriptors == null) {
introspect();
1
0
Author: ceki
Date: Thu Jul 17 22:37:35 2008
New Revision: 1710
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForBasicProperty.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java
- copied, changed from r1709, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java
- copied, changed from r1709, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedSimplePropertyIA.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java
- copied, changed from r1709, /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/PropertySetter.java
- copied, changed from r1709, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplex.xml
- copied unchanged from r1704, /logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComponent.xml
logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplexCollection.xml
- copied unchanged from r1704, /logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComponentCollection.xml
logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplexCollectionWithoutClassAtrribute.xml
logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplexWithoutClassAtrribute.xml
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java
- copied, changed from r1709, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java
Removed:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.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/action/NestedSimplePropertyIA.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComponent.xml
logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComponentCollection.xml
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.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/ParamAction.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java
Log:
- Refactoring of Joran, in particular of PropertySetter. The code should be
hopefully clearer.
- Joran now support complex types without the need to declare their class
in the XML element, if the complex type can be instantiated unequivocally.
This can make config files shorter.
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java Thu Jul 17 22:37:35 2008
@@ -19,8 +19,8 @@
import ch.qos.logback.core.joran.action.Action;
import ch.qos.logback.core.joran.spi.InterpretationContext;
+import ch.qos.logback.core.joran.spi.PropertySetter;
import ch.qos.logback.core.util.OptionHelper;
-import ch.qos.logback.core.util.PropertySetter;
/**
*
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 Thu Jul 17 22:37:35 2008
@@ -18,8 +18,8 @@
import ch.qos.logback.core.joran.action.AppenderAction;
import ch.qos.logback.core.joran.action.AppenderRefAction;
import ch.qos.logback.core.joran.action.ConversionRuleAction;
-import ch.qos.logback.core.joran.action.NestedComponentIA;
-import ch.qos.logback.core.joran.action.NestedSimplePropertyIA;
+import ch.qos.logback.core.joran.action.NestedComplexPropertyIA;
+import ch.qos.logback.core.joran.action.NestedBasicPropertyIA;
import ch.qos.logback.core.joran.action.NewRuleAction;
import ch.qos.logback.core.joran.action.ParamAction;
import ch.qos.logback.core.joran.action.ContextPropertyAction;
@@ -68,11 +68,11 @@
@Override
protected void addImplicitRules(Interpreter interpreter) {
// The following line adds the capability to parse nested components
- NestedComponentIA nestedIA = new NestedComponentIA();
+ NestedComplexPropertyIA nestedIA = new NestedComplexPropertyIA();
nestedIA.setContext(context);
interpreter.addImplicitAction(nestedIA);
- NestedSimplePropertyIA nestedSimpleIA = new NestedSimplePropertyIA();
+ NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA();
nestedIA.setContext(context);
interpreter.addImplicitAction(nestedSimpleIA);
}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForBasicProperty.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForBasicProperty.java Thu Jul 17 22:37:35 2008
@@ -0,0 +1,22 @@
+package ch.qos.logback.core.joran.action;
+
+import ch.qos.logback.core.joran.spi.PropertySetter;
+import ch.qos.logback.core.util.AggregationType;
+
+/**
+ * Lump together several fields for use by {@link NestedBasicPropertyIA}.
+ *
+ * @author Ceki Gulcu
+ */
+class IADataForBasicProperty {
+ final PropertySetter parentBean;
+ final AggregationType aggregationType;
+ final String propertyName;
+ boolean inError;
+
+ IADataForBasicProperty(PropertySetter parentBean, AggregationType aggregationType, String propertyName) {
+ this.parentBean = parentBean;
+ this.aggregationType = aggregationType;
+ this.propertyName = propertyName;
+ }
+}
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java (from r1709, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java Thu Jul 17 22:37:35 2008
@@ -1,23 +1,37 @@
package ch.qos.logback.core.joran.action;
+import ch.qos.logback.core.joran.spi.PropertySetter;
import ch.qos.logback.core.util.AggregationType;
-import ch.qos.logback.core.util.PropertySetter;
/**
- * ImplicitActionData is a data class aggregating several fields.
- *
+ * Lump together several fields for use by {@link NestedComplexPropertyIA}.
*
* @author Ceki
*/
-public class ImplicitActionData {
- PropertySetter parentBean;
- String propertyName;
- Object nestedComponent;
- AggregationType containmentType;
+public class IADataForComplexProperty {
+ final PropertySetter parentBean;
+ final AggregationType aggregationType;
+ final String complexPropertyName;
+ Object nestedComplexProperty;
boolean inError;
- ImplicitActionData(PropertySetter parentBean, AggregationType containmentType) {
+ public IADataForComplexProperty(PropertySetter parentBean, AggregationType aggregationType, String complexPropertyName) {
this.parentBean = parentBean;
- this.containmentType = containmentType;
+ this.aggregationType = aggregationType;
+ this.complexPropertyName = complexPropertyName;
+ }
+
+ public AggregationType getAggregationType() {
+ return aggregationType;
+ }
+
+ public Object getNestedComplexProperty() {
+ return nestedComplexProperty;
+ }
+
+ public String getComplexPropertyName() {
+ return complexPropertyName;
}
+
+
}
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java (from r1709, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedSimplePropertyIA.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedSimplePropertyIA.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java Thu Jul 17 22:37:35 2008
@@ -10,92 +10,91 @@
package ch.qos.logback.core.joran.action;
-
-
import java.util.Stack;
import org.xml.sax.Attributes;
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.joran.spi.Pattern;
+import ch.qos.logback.core.joran.spi.PropertySetter;
import ch.qos.logback.core.util.AggregationType;
-import ch.qos.logback.core.util.PropertySetter;
-
-
/**
- * This action is responsible for tying together a parent object with
- * one of its <em>simple</em> properties specified as an element but for
- * which there is no explicit rule.
+ * This action is responsible for tying together a parent object with one of its
+ * <em>simple</em> properties specified as an element but for which there is
+ * no explicit rule.
*
* @author Ceki Gülcü
*/
-public class NestedSimplePropertyIA extends ImplicitAction {
-
- // actionDataStack contains ActionData instances
- // We use a stack of ActionData objects in order to support nested
- // elements which are handled by the same NestedPropertyIA instance.
- // We push a ActionData instance in the isApplicable method (if the
+public class NestedBasicPropertyIA extends ImplicitAction {
+
+
+ // We use a stack of IADataForBasicProperty objects in order to
+ // support nested elements which are handled by the same NestedBasicPropertyIA instance.
+ // We push a IADataForBasicProperty instance in the isApplicable method (if the
// action is applicable) and pop it in the end() method.
// The XML well-formedness property will guarantee that a push will eventually
// be followed by the corresponding pop.
- Stack<ImplicitActionData> actionDataStack = new Stack<ImplicitActionData>();
+ Stack<IADataForBasicProperty> actionDataStack = new Stack<IADataForBasicProperty>();
- public boolean isApplicable(
- Pattern pattern, Attributes attributes, InterpretationContext ec) {
- //System.out.println("in NestedSimplePropertyIA.isApplicable [" + pattern + "]");
+ public boolean isApplicable(Pattern pattern, Attributes attributes,
+ InterpretationContext ec) {
+ // System.out.println("in NestedSimplePropertyIA.isApplicable [" + pattern +
+ // "]");
String nestedElementTagName = pattern.peekLast();
// no point in attempting if there is no parent object
- if(ec.isEmpty()) {
+ if (ec.isEmpty()) {
return false;
}
-
+
Object o = ec.peekObject();
PropertySetter parentBean = new PropertySetter(o);
parentBean.setContext(context);
-
- AggregationType containmentType = parentBean.canContainComponent(nestedElementTagName);
- switch (containmentType) {
+ AggregationType aggregationType = parentBean
+ .computeAggregationType(nestedElementTagName);
+
+ switch (aggregationType) {
case NOT_FOUND:
- case AS_SINGLE_COMPONENT:
- case AS_COMPONENT_COLLECTION:
+ case AS_COMPLEX_PROPERTY:
+ case AS_COMPLEX_PROPERTY_COLLECTION:
return false;
- case AS_SINGLE_PROPERTY:
- case AS_PROPERTY_COLLECTION:
- ImplicitActionData ad = new ImplicitActionData(parentBean, containmentType);
- ad.propertyName = nestedElementTagName;
+ case AS_BASIC_PROPERTY:
+ case AS_BASIC_PROPERTY_COLLECTION:
+ IADataForBasicProperty ad = new IADataForBasicProperty(parentBean,
+ aggregationType, nestedElementTagName);
actionDataStack.push(ad);
- //addInfo("NestedSimplePropertyIA deemed applicable [" + pattern + "]");
+ // addInfo("NestedSimplePropertyIA deemed applicable [" + pattern + "]");
return true;
default:
- addError("PropertySetter.canContainComponent returned " + containmentType);
+ addError("PropertySetter.canContainComponent returned " + aggregationType);
return false;
}
}
- public void begin(
- InterpretationContext ec, String localName, Attributes attributes) {
+ public void begin(InterpretationContext ec, String localName,
+ Attributes attributes) {
// NOP
}
public void body(InterpretationContext ec, String body) {
-
+
String finalBody = ec.subst(body);
- //System.out.println("body "+body+", finalBody="+finalBody);
+ // System.out.println("body "+body+", finalBody="+finalBody);
// get the action data object pushed in isApplicable() method call
- ImplicitActionData actionData = (ImplicitActionData) actionDataStack.peek();
- switch (actionData.containmentType) {
- case AS_SINGLE_PROPERTY:
+ IADataForBasicProperty actionData = (IADataForBasicProperty) actionDataStack.peek();
+ switch (actionData.aggregationType) {
+ case AS_BASIC_PROPERTY:
actionData.parentBean.setProperty(actionData.propertyName, finalBody);
break;
- case AS_PROPERTY_COLLECTION:
- actionData.parentBean.addProperty(actionData.propertyName, finalBody);
+ case AS_BASIC_PROPERTY_COLLECTION:
+ actionData.parentBean
+ .addBasicProperty(actionData.propertyName, finalBody);
}
}
-
+
public void end(InterpretationContext ec, String tagName) {
// pop the action data object pushed in isApplicable() method call
actionDataStack.pop();
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java (from r1709, /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/NestedComplexPropertyIA.java Thu Jul 17 22:37:35 2008
@@ -16,12 +16,12 @@
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.joran.spi.Pattern;
+import ch.qos.logback.core.joran.spi.PropertySetter;
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.LifeCycle;
import ch.qos.logback.core.util.AggregationType;
import ch.qos.logback.core.util.Loader;
import ch.qos.logback.core.util.OptionHelper;
-import ch.qos.logback.core.util.PropertySetter;
/**
* This action is responsible for tying together a parent object with a child
@@ -29,20 +29,21 @@
*
* @author Ceki Gülcü
*/
-public class NestedComponentIA extends ImplicitAction {
+public class NestedComplexPropertyIA extends ImplicitAction {
// actionDataStack contains ActionData instances
// We use a stack of ActionData objects in order to support nested
- // elements which are handled by the same NestComponentIA instance.
+ // elements which are handled by the same NestedComplexPropertyIA instance.
// We push a ActionData instance in the isApplicable method (if the
// action is applicable) and pop it in the end() method.
// The XML well-formedness property will guarantee that a push will eventually
- // be followed by the corresponding pop.
- Stack<ImplicitActionData> actionDataStack = new Stack<ImplicitActionData>();
+ // be followed by a corresponding pop.
+ Stack<IADataForComplexProperty> actionDataStack = new Stack<IADataForComplexProperty>();
public boolean isApplicable(Pattern pattern, Attributes attributes,
InterpretationContext ec) {
- // System.out.println("in NestComponentIA.isApplicable [" + pattern + "]");
+ // System.out.println("in NestedComplexPropertyIA.isApplicable [" + pattern
+ // + "]");
String nestedElementTagName = pattern.peekLast();
// calling ec.peekObject with an empty stack will throw an exception
@@ -54,26 +55,26 @@
PropertySetter parentBean = new PropertySetter(o);
parentBean.setContext(context);
- AggregationType containmentType = parentBean
- .canContainComponent(nestedElementTagName);
+ AggregationType aggregationType = parentBean
+ .computeAggregationType(nestedElementTagName);
- switch (containmentType) {
+ switch (aggregationType) {
case NOT_FOUND:
- case AS_SINGLE_PROPERTY:
- case AS_PROPERTY_COLLECTION:
+ case AS_BASIC_PROPERTY:
+ case AS_BASIC_PROPERTY_COLLECTION:
return false;
// we only push action data if NestComponentIA is applicable
- case AS_COMPONENT_COLLECTION:
- case AS_SINGLE_COMPONENT:
- //addInfo("was deemed applicable for " + pattern);
- ImplicitActionData ad = new ImplicitActionData(parentBean,
- containmentType);
+ case AS_COMPLEX_PROPERTY_COLLECTION:
+ case AS_COMPLEX_PROPERTY:
+ // addInfo("was deemed applicable for " + pattern);
+ IADataForComplexProperty ad = new IADataForComplexProperty(parentBean,
+ aggregationType, nestedElementTagName);
actionDataStack.push(ad);
return true;
default:
- addError("PropertySetter.canContainComponent returned " + containmentType);
+ addError("PropertySetter.canContainComponent returned " + aggregationType);
return false;
}
}
@@ -82,7 +83,8 @@
Attributes attributes) {
// LogLog.debug("in NestComponentIA begin method");
// get the action data object pushed in isApplicable() method call
- ImplicitActionData actionData = (ImplicitActionData) actionDataStack.peek();
+ IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack
+ .peek();
String className = attributes.getValue(CLASS_ATTRIBUTE);
@@ -90,11 +92,17 @@
className = ec.subst(className);
if (OptionHelper.isEmpty(className)) {
- actionData.inError = true;
- String errMsg = "No class name attribute in [" + localName + "]";
- addError(errMsg);
+ Class clazz = actionData.parentBean
+ .findUnequivocallyInstantiableClass(actionData);
+ if (clazz != null) {
+ className = clazz.getName();
+ } else {
+ actionData.inError = true;
+ String errMsg = "No class name attribute in [" + localName + "]";
+ addError(errMsg);
- return;
+ return;
+ }
}
try {
@@ -102,18 +110,18 @@
// "About to instantiate component [{}] of type [{}]", localName,
// className);
- // TODO: Loading classes should be governed by config file rules.
-
- actionData.nestedComponent = Loader.loadClass(className, context).newInstance();
+ actionData.nestedComplexProperty = Loader.loadClass(className, context)
+ .newInstance();
// pass along the repository
- if (actionData.nestedComponent instanceof ContextAware) {
- ((ContextAware) actionData.nestedComponent).setContext(this.context);
+ if (actionData.nestedComplexProperty instanceof ContextAware) {
+ ((ContextAware) actionData.nestedComplexProperty)
+ .setContext(this.context);
}
// getLogger().debug(
addInfo("Pushing component [" + localName
+ "] on top of the object stack.");
- ec.pushObject(actionData.nestedComponent);
+ ec.pushObject(actionData.nestedComplexProperty);
} catch (Exception oops) {
actionData.inError = true;
String msg = "Could not create component [" + localName + "] of type ["
@@ -126,44 +134,50 @@
// pop the action data object pushed in isApplicable() method call
// we assume that each this begin
- ImplicitActionData actionData = (ImplicitActionData) actionDataStack.pop();
+ IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack
+ .pop();
if (actionData.inError) {
return;
}
- PropertySetter nestedBean = new PropertySetter(actionData.nestedComponent);
+ PropertySetter nestedBean = new PropertySetter(
+ actionData.nestedComplexProperty);
nestedBean.setContext(context);
- if (nestedBean.canContainComponent("parent") == AggregationType.AS_SINGLE_COMPONENT) {
- nestedBean.setComponent("parent", actionData.parentBean.getObj());
- }
- if (actionData.nestedComponent instanceof LifeCycle) {
- ((LifeCycle) actionData.nestedComponent).start();
+ // have the nested element point to its parent if possible
+ if (nestedBean.computeAggregationType("parent") == AggregationType.AS_COMPLEX_PROPERTY) {
+ nestedBean.setComplexProperty("parent", actionData.parentBean.getObj());
+ }
+ // start the nested complex attribute if it implements LifeCycle
+ if (actionData.nestedComplexProperty instanceof LifeCycle) {
+ ((LifeCycle) actionData.nestedComplexProperty).start();
}
Object o = ec.peekObject();
- if (o != actionData.nestedComponent) {
+ if (o != actionData.nestedComplexProperty) {
addError("The object on the top the of the stack is not the component pushed earlier.");
} else {
// getLogger().debug("Removing component from the object stack");
ec.popObject();
// Now let us attach the component
- switch (actionData.containmentType) {
- case AS_SINGLE_COMPONENT:
+ switch (actionData.aggregationType) {
+ case AS_COMPLEX_PROPERTY:
// addInfo("Setting ["+tagName+"}] to parent of type
// ["+actionData.parentBean.getObjClass()+"]");
- actionData.parentBean.setComponent(tagName, actionData.nestedComponent);
+ actionData.parentBean.setComplexProperty(tagName,
+ actionData.nestedComplexProperty);
break;
- case AS_COMPONENT_COLLECTION:
+ case AS_COMPLEX_PROPERTY_COLLECTION:
// getLogger().debug(
// "Adding [{}] to parent of type [{}]", tagName,
// actionData.parentBean.getObjClass());
- actionData.parentBean.addComponent(tagName, actionData.nestedComponent);
+ actionData.parentBean.addComplexProperty(tagName,
+ actionData.nestedComplexProperty);
break;
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java Thu Jul 17 22:37:35 2008
@@ -14,7 +14,7 @@
import org.xml.sax.Attributes;
import ch.qos.logback.core.joran.spi.InterpretationContext;
-import ch.qos.logback.core.util.PropertySetter;
+import ch.qos.logback.core.joran.spi.PropertySetter;
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java (from r1709, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/PropertySetter.java Thu Jul 17 22:37:35 2008
@@ -15,18 +15,21 @@
*/
// Contributors: Georg Lundesgaard
-package ch.qos.logback.core.util;
+package ch.qos.logback.core.joran.spi;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
+import ch.qos.logback.core.joran.action.IADataForComplexProperty;
import ch.qos.logback.core.spi.ContextAwareBase;
-
+import ch.qos.logback.core.util.AggregationType;
+import ch.qos.logback.core.util.Duration;
+import ch.qos.logback.core.util.FileSize;
+import ch.qos.logback.core.util.PropertySetterException;
/**
* General purpose Object property setter. Clients repeatedly invokes
@@ -52,13 +55,8 @@
* @author Ceki Gulcu
*/
public class PropertySetter extends ContextAwareBase {
- private static final int X_NOT_FOUND = 0;
- private static final int X_AS_COMPONENT = 1;
- private static final int X_AS_PROPERTY = 2;
-
- private static final Class[] STING_CLASS_PARAMETER = new Class[] {String.class};
+ private static final Class[] STING_CLASS_PARAMETER = new Class[] { String.class };
-
protected Object obj;
protected Class objClass;
protected PropertyDescriptor[] propertyDescriptors;
@@ -69,7 +67,7 @@
* preparation for invoking {@link #setProperty} one or more times.
*
* @param obj
- * the object for which to set properties
+ * the object for which to set properties
*/
public PropertySetter(Object obj) {
this.obj = obj;
@@ -106,9 +104,9 @@
* Boolean(value).
*
* @param name
- * name of the property
+ * name of the property
* @param value
- * String value of the property
+ * String value of the property
*/
public void setProperty(String name, String value) {
if (value == null) {
@@ -135,12 +133,12 @@
* Set the named property given a {@link PropertyDescriptor}.
*
* @param prop
- * A PropertyDescriptor describing the characteristics of the
- * property to set.
+ * A PropertyDescriptor describing the characteristics of the
+ * property to set.
* @param name
- * The named of the property to set.
+ * The named of the property to set.
* @param value
- * The value of the property.
+ * The value of the property.
*/
public void setProperty(PropertyDescriptor prop, String name, String value)
throws PropertySetterException {
@@ -152,12 +150,11 @@
}
Class[] paramTypes = setter.getParameterTypes();
-
-
+
if (paramTypes.length != 1) {
throw new PropertySetterException("#params for setter != 1");
}
-
+
Object arg;
try {
@@ -171,141 +168,168 @@
throw new PropertySetterException("Conversion to type [" + paramTypes[0]
+ "] failed.");
}
-
- // getLogger().debug("Setting property [{}] to [{}].", name, arg);
-
try {
- setter.invoke(obj, new Object[] { arg });
+ setter.invoke(obj, arg);
} catch (Exception ex) {
throw new PropertySetterException(ex);
}
}
- public AggregationType canContainComponent(String name) {
+ public AggregationType computeAggregationType(String name) {
String cName = capitalizeFirstLetter(name);
Method addMethod = getMethod("add" + cName);
+ // if the
if (addMethod != null) {
- int type = computeContainmentTpye(addMethod);
+ AggregationType type = computeRawAggregationType(addMethod);
switch (type) {
- case X_NOT_FOUND:
+ case NOT_FOUND:
return AggregationType.NOT_FOUND;
- case X_AS_PROPERTY:
- return AggregationType.AS_PROPERTY_COLLECTION;
- case X_AS_COMPONENT:
- return AggregationType.AS_COMPONENT_COLLECTION;
+ case AS_BASIC_PROPERTY:
+ return AggregationType.AS_BASIC_PROPERTY_COLLECTION;
+ case AS_COMPLEX_PROPERTY:
+ return AggregationType.AS_COMPLEX_PROPERTY_COLLECTION;
}
}
- String dName = Introspector.decapitalize(name);
+ Method setterMethod = findSetterMethod(name);
+ if (setterMethod != null) {
+ return computeRawAggregationType(setterMethod);
+ } else {
+ // we have failed
+ return AggregationType.NOT_FOUND;
+ }
+ }
+ private Method findAdderMethod(String name) {
+ name = capitalizeFirstLetter(name);
+ Method adderMethod = getMethod("add" + name);
+ return adderMethod;
+ }
+
+ private Method findSetterMethod(String name) {
+ String dName = Introspector.decapitalize(name);
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName);
-
if (propertyDescriptor != null) {
- Method setterMethod = propertyDescriptor.getWriteMethod();
- if (setterMethod != null) {
- // getLogger().debug(
- // "Found setter method for property [{}] in class {}", name,
- // objClass.getName());
- int type = computeContainmentTpye(setterMethod);
- // getLogger().debug(
- // "Found add {} method in class {}", cName, objClass.getName());
- switch (type) {
- case X_NOT_FOUND:
- return AggregationType.NOT_FOUND;
- case X_AS_PROPERTY:
- return AggregationType.AS_SINGLE_PROPERTY;
- case X_AS_COMPONENT:
- return AggregationType.AS_SINGLE_COMPONENT;
- }
- }
+ return propertyDescriptor.getWriteMethod();
+ } else {
+ return null;
}
-
- // we have failed
- return AggregationType.NOT_FOUND;
}
- int computeContainmentTpye(Method setterMethod) {
- Class[] classArray = setterMethod.getParameterTypes();
+ Class<?> getParameterClassForMethod(Method method) {
+ if(method == null) {
+ return null;
+ }
+ Class[] classArray = method.getParameterTypes();
if (classArray.length != 1) {
- return X_NOT_FOUND;
+ return null;
+ } else {
+ return classArray[0];
+ }
+ }
+ private AggregationType computeRawAggregationType(Method method) {
+ Class<?> clazz = getParameterClassForMethod(method);
+ if (clazz == null) {
+ return AggregationType.NOT_FOUND;
} else {
- Class clazz = classArray[0];
Package p = clazz.getPackage();
if (clazz.isPrimitive()) {
- return X_AS_PROPERTY;
+ return AggregationType.AS_BASIC_PROPERTY;
} else if (p != null && "java.lang".equals(p.getName())) {
- return X_AS_PROPERTY;
+ return AggregationType.AS_BASIC_PROPERTY;
} else if (Duration.class.isAssignableFrom(clazz)) {
- return X_AS_PROPERTY;
+ return AggregationType.AS_BASIC_PROPERTY;
} else if (FileSize.class.isAssignableFrom(clazz)) {
- return X_AS_PROPERTY;
- } else if (clazz.isEnum()){
- return X_AS_PROPERTY;
+ return AggregationType.AS_BASIC_PROPERTY;
+ } else if (clazz.isEnum()) {
+ return AggregationType.AS_BASIC_PROPERTY;
} else {
- return X_AS_COMPONENT;
+ return AggregationType.AS_COMPLEX_PROPERTY;
}
}
}
-
- <T> boolean isUnequivocallyInstantiable(Class<T> clazz) {
- if(clazz.isInterface()) {
+
+ public Class findUnequivocallyInstantiableClass(
+ IADataForComplexProperty actionData) {
+ Class<?> clazz;
+ AggregationType at = actionData.getAggregationType();
+ switch (at) {
+ case AS_COMPLEX_PROPERTY:
+ Method setterMethod = findSetterMethod(actionData.getComplexPropertyName());
+ clazz = getParameterClassForMethod(setterMethod);
+ if(clazz != null && isUnequivocallyInstantiable(clazz)) {
+ return clazz;
+ } else {
+ return null;
+ }
+ case AS_COMPLEX_PROPERTY_COLLECTION:
+ Method adderMethod = findAdderMethod(actionData.getComplexPropertyName());
+ clazz = getParameterClassForMethod(adderMethod);
+ if(clazz != null && isUnequivocallyInstantiable(clazz)) {
+ return clazz;
+ } else {
+ return null;
+ }
+ default:
+ throw new IllegalArgumentException(at
+ + " is not valid type in this method");
+ }
+ }
+
+ boolean isUnequivocallyInstantiable(Class<?> clazz) {
+ if (clazz.isInterface()) {
return false;
}
try {
- Constructor<T> pubConstructor = clazz.getConstructor();
- return true;
- } catch (SecurityException e) {
- return false;
- } catch (NoSuchMethodException e) {
+ // checking for constructors would be slightly more elegant, but in classes
+ // without any declared constructors, Class.getConstructor() returns null.
+ Object o = clazz.newInstance();
+ if(o != null) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (Exception e) {
return false;
- }
+ }
}
public Class getObjClass() {
return objClass;
}
- @SuppressWarnings("unchecked")
- public void addComponent(String name, Object childComponent) {
- Class ccc = childComponent.getClass();
- name = capitalizeFirstLetter(name);
-
- Method method = getMethod("add" + name);
-
+ public void addComplexProperty(String name, Object complexProperty) {
+ Method adderMethod = findAdderMethod(name);
// first let us use the addXXX method
- if (method != null) {
- Class[] params = method.getParameterTypes();
-
- if (params.length == 1) {
- if (params[0].isAssignableFrom(childComponent.getClass())) {
- try {
- method.invoke(this.obj, new Object[] { childComponent });
- } catch (Exception e) {
- addError("Could not invoke method " + method.getName()
- + " in class " + obj.getClass().getName()
- + " with parameter of type " + ccc.getName(), e);
- }
- } else {
- addError("A \"" + ccc.getName()
- + "\" object is not assignable to a \"" + params[0].getName()
- + "\" variable.");
- addError("The class \"" + params[0].getName() + "\" was loaded by ");
- addError("[" + params[0].getClassLoader()
- + "] whereas object of type ");
- addError("\"" + ccc.getName() + "\" was loaded by ["
- + ccc.getClassLoader() + "].");
- }
+ if (adderMethod != null) {
+ Class[] paramTypes = adderMethod.getParameterTypes();
+ if (!isSanityCheckSuccessful(name, adderMethod, paramTypes,
+ complexProperty)) {
+ return;
}
+ invokeMethodWithSingleParameterOnThisObject(adderMethod, complexProperty);
} else {
addError("Could not find method [" + "add" + name + "] in class ["
+ objClass.getName() + "].");
}
}
+ void invokeMethodWithSingleParameterOnThisObject(Method method,
+ Object parameter) {
+ Class ccc = parameter.getClass();
+ try {
+ method.invoke(this.obj, parameter);
+ } catch (Exception e) {
+ addError("Could not invoke method " + method.getName() + " in class "
+ + obj.getClass().getName() + " with parameter of type "
+ + ccc.getName(), e);
+ }
+ }
+
@SuppressWarnings("unchecked")
- public void addProperty(String name, String strValue) {
+ public void addBasicProperty(String name, String strValue) {
if (strValue == null) {
return;
@@ -320,11 +344,8 @@
}
Class[] paramTypes = adderMethod.getParameterTypes();
- if (paramTypes.length != 1) {
- addError("#params for setter != 1");
- return;
+ isSanityCheckSuccessful(name, adderMethod, paramTypes, strValue);
- }
Object arg;
try {
arg = convertArg(strValue, paramTypes[0]);
@@ -332,20 +353,12 @@
addError("Conversion to type [" + paramTypes[0] + "] failed. ", t);
return;
}
-
- if (arg == null) {
- addError("Conversion to type [" + paramTypes[0] + "] failed.");
- } else {
- try {
- adderMethod.invoke(obj, arg);
- } catch (Exception ex) {
- addError("Failed to invoke adder for " + name, ex);
- }
+ if (arg != null) {
+ invokeMethodWithSingleParameterOnThisObject(adderMethod, strValue);
}
-
}
- public void setComponent(String name, Object childComponent) {
+ public void setComplexProperty(String name, Object complexProperty) {
String dName = Introspector.decapitalize(name);
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName);
@@ -367,24 +380,41 @@
Class[] paramTypes = setter.getParameterTypes();
- if (paramTypes.length != 1) {
- addError("Wrong number of parameters in setter method for property ["
- + name + "] in " + obj.getClass().getName());
-
+ if (!isSanityCheckSuccessful(name, setter, paramTypes, complexProperty)) {
return;
}
-
try {
- setter.invoke(obj, new Object[] { childComponent });
- // getLogger().debug(
- // "Set child component of type [{}] for [{}].", objClass.getName(),
- // childComponent.getClass().getName());
+ invokeMethodWithSingleParameterOnThisObject(setter, complexProperty);
+
} catch (Exception e) {
addError("Could not set component " + obj + " for parent component "
+ obj, e);
}
}
+ private boolean isSanityCheckSuccessful(String name, Method method,
+ Class<?>[] params, Object complexProperty) {
+ Class ccc = complexProperty.getClass();
+ if (params.length != 1) {
+ addError("Wrong number of parameters in setter method for property ["
+ + name + "] in " + obj.getClass().getName());
+
+ return false;
+ }
+
+ if (!params[0].isAssignableFrom(complexProperty.getClass())) {
+ addError("A \"" + ccc.getName() + "\" object is not assignable to a \""
+ + params[0].getName() + "\" variable.");
+ addError("The class \"" + params[0].getName() + "\" was loaded by ");
+ addError("[" + params[0].getClassLoader() + "] whereas object of type ");
+ addError("\"" + ccc.getName() + "\" was loaded by ["
+ + ccc.getClassLoader() + "].");
+ return false;
+ }
+
+ return true;
+ }
+
private String capitalizeFirstLetter(String name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
@@ -419,7 +449,7 @@
return Duration.valueOf(val);
} else if (FileSize.class.isAssignableFrom(type)) {
return FileSize.valueOf(val);
- } else if(type.isEnum()) {
+ } else if (type.isEnum()) {
return convertEnum(val, type);
}
@@ -431,10 +461,12 @@
Method m = type.getMethod("valueOf", STING_CLASS_PARAMETER);
return m.invoke(null, val);
} catch (Exception e) {
- addError("Failed to convert value ["+val+"] to enum ["+type.getName()+"]", e);
+ addError("Failed to convert value [" + val + "] to enum ["
+ + type.getName() + "]", e);
}
return null;
}
+
protected Method getMethod(String methodName) {
if (methodDescriptors == null) {
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java Thu Jul 17 22:37:35 2008
@@ -3,7 +3,6 @@
import java.util.ArrayList;
import java.util.List;
-import ch.qos.logback.core.CoreGlobal;
import ch.qos.logback.core.pattern.util.IEscapeUtil;
import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java Thu Jul 17 22:37:35 2008
@@ -1,9 +1,23 @@
package ch.qos.logback.core.util;
+/**
+ * AggregationType classifies how one object is contained within
+ * another object.
+ *
+ *
+ *
+ * See also http://en.wikipedia.org/wiki/Class_diagram
+ * and http://en.wikipedia.org/wiki/Object_composition
+ *
+ * @author Ceki Gulcu
+ */
public enum AggregationType {
NOT_FOUND,
- AS_SINGLE_COMPONENT,
- AS_SINGLE_PROPERTY,
- AS_PROPERTY_COLLECTION,
- AS_COMPONENT_COLLECTION;
+ AS_BASIC_PROPERTY, // Long, Integer, Double,..., java primitive, String,
+ // Duration or FileSize
+ AS_COMPLEX_PROPERTY, // a complex property, a.k.a. attribute, is any attribute
+ // not covered by basic attributes, i.e.
+ // object types defined by the user
+ AS_BASIC_PROPERTY_COLLECTION, // a collection of basic attributes
+ AS_COMPLEX_PROPERTY_COLLECTION; // a collection of complex attributes
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetterException.java Thu Jul 17 22:37:35 2008
@@ -7,6 +7,8 @@
package ch.qos.logback.core.util;
+import ch.qos.logback.core.joran.spi.PropertySetter;
+
/**
* Thrown when an error is encountered whilst attempting to set a property
* using the {@link PropertySetter} utility class.
Added: logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplexCollectionWithoutClassAtrribute.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplexCollectionWithoutClassAtrribute.xml Thu Jul 17 22:37:35 2008
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<context>
+ <fruit>
+ <name>blue</name>
+ <text>hello</text>
+ <text>world</text>
+ <cake>
+ <type>A</type>
+ <code>1</code>
+ </cake>
+ <cake>
+ <type>B</type>
+ <code>2</code>
+ </cake>
+ </fruit>
+</context>
\ No newline at end of file
Added: logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplexWithoutClassAtrribute.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/input/joran/implicitAction/nestedComplexWithoutClassAtrribute.xml Thu Jul 17 22:37:35 2008
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<context>
+ <fruit>
+ <name>blue</name>
+ <text>hello</text>
+ <text>world</text>
+ </fruit>
+</context>
\ No newline at end of file
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java Thu Jul 17 22:37:35 2008
@@ -13,8 +13,8 @@
import ch.qos.logback.core.joran.GenericConfigurator;
import ch.qos.logback.core.joran.action.Action;
-import ch.qos.logback.core.joran.action.NestedComponentIA;
-import ch.qos.logback.core.joran.action.NestedSimplePropertyIA;
+import ch.qos.logback.core.joran.action.NestedComplexPropertyIA;
+import ch.qos.logback.core.joran.action.NestedBasicPropertyIA;
import ch.qos.logback.core.joran.spi.Interpreter;
import ch.qos.logback.core.joran.spi.Pattern;
import ch.qos.logback.core.joran.spi.RuleStore;
@@ -29,11 +29,11 @@
@Override
protected void addImplicitRules(Interpreter interpreter) {
- NestedComponentIA nestedIA = new NestedComponentIA();
+ NestedComplexPropertyIA nestedIA = new NestedComplexPropertyIA();
nestedIA.setContext(context);
interpreter.addImplicitAction(nestedIA);
- NestedSimplePropertyIA nestedSimpleIA = new NestedSimplePropertyIA();
+ NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA();
nestedSimpleIA.setContext(context);
interpreter.addImplicitAction(nestedSimpleIA);
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/implicitAction/ImplicitActionTest.java Thu Jul 17 22:37:35 2008
@@ -17,11 +17,12 @@
public class ImplicitActionTest {
- static final String IMPLCIT_DIR = Constants.TEST_DIR_PREFIX +"input/joran/implicitAction/";
-
+ static final String IMPLCIT_DIR = Constants.TEST_DIR_PREFIX
+ + "input/joran/implicitAction/";
+
FruitContext fruitContext = new FruitContext();
SimpleConfigurator simpleConfigurator;
-
+
public ImplicitActionTest() {
}
@@ -34,49 +35,82 @@
simpleConfigurator.setContext(fruitContext);
}
+ void verifyFruit() {
+ List<Fruit> fList = fruitContext.getFruitList();
+ assertNotNull(fList);
+ assertEquals(1, fList.size());
+
+ Fruit f0 = fList.get(0);
+ assertEquals("blue", f0.getName());
+ assertEquals(2, f0.textList.size());
+ assertEquals("hello", f0.textList.get(0));
+ assertEquals("world", f0.textList.get(1));
+ }
+
+ @Test
+ public void nestedComplex() throws Exception {
+ try {
+ simpleConfigurator.doConfigure(IMPLCIT_DIR + "nestedComplex.xml");
+ verifyFruit();
+
+ } catch (Exception je) {
+ StatusPrinter.print(fruitContext);
+ throw je;
+ }
+ }
+
@Test
- public void nested() throws Exception {
- try {
- simpleConfigurator.doConfigure(IMPLCIT_DIR + "nestedComponent.xml");
-
- List<Fruit> fList = fruitContext.getFruitList();
- assertNotNull(fList);
- assertEquals(1, fList.size());
-
- Fruit f0 = fList.get(0);
- assertEquals("blue", f0.getName());
- assertEquals(2, f0.textList.size());
- assertEquals("hello", f0.textList.get(0));
- assertEquals("world", f0.textList.get(1));
-
+ public void nestedComplexWithoutClassAtrribute() throws Exception {
+ try {
+ simpleConfigurator.doConfigure(IMPLCIT_DIR
+ + "nestedComplexWithoutClassAtrribute.xml");
+
+ verifyFruit();
+
} catch (Exception je) {
StatusPrinter.print(fruitContext);
throw je;
}
}
+
+ void verifyFruitList() {
+ List<Fruit> fList = fruitContext.getFruitList();
+ assertNotNull(fList);
+ assertEquals(1, fList.size());
+
+ Fruit f0 = fList.get(0);
+ assertEquals(2, f0.cakeList.size());
+
+ Cake cakeA = f0.cakeList.get(0);
+ assertEquals("A", cakeA.getType());
+
+ Cake cakeB = f0.cakeList.get(1);
+ assertEquals("B", cakeB.getType());
+ }
@Test
- public void nestedCollection() throws Exception {
- try {
- simpleConfigurator.doConfigure(IMPLCIT_DIR + "nestedComponentCollection.xml");
-
- List<Fruit> fList = fruitContext.getFruitList();
- assertNotNull(fList);
- assertEquals(1, fList.size());
-
- Fruit f0 = fList.get(0);
- assertEquals(2, f0.cakeList.size());
-
- Cake cakeA = f0.cakeList.get(0);
- assertEquals("A", cakeA.getType());
-
- Cake cakeB = f0.cakeList.get(1);
- assertEquals("B", cakeB.getType());
-
+ public void nestedComplexCollection() throws Exception {
+ try {
+ simpleConfigurator.doConfigure(IMPLCIT_DIR
+ + "nestedComplexCollection.xml");
+ verifyFruitList();
} catch (Exception je) {
StatusPrinter.print(fruitContext);
throw je;
}
}
+
+ @Test
+ public void nestedComplexCollectionWithoutClassAtrribute() throws Exception {
+ try {
+ simpleConfigurator.doConfigure(IMPLCIT_DIR
+ + "nestedComplexCollectionWithoutClassAtrribute.xml");
+ verifyFruitList();
+ } catch (Exception je) {
+ StatusPrinter.print(fruitContext);
+ throw je;
+ }
+ }
+
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurator.java Thu Jul 17 22:37:35 2008
@@ -13,8 +13,8 @@
import ch.qos.logback.core.joran.GenericConfigurator;
import ch.qos.logback.core.joran.action.NOPAction;
-import ch.qos.logback.core.joran.action.NestedComponentIA;
-import ch.qos.logback.core.joran.action.NestedSimplePropertyIA;
+import ch.qos.logback.core.joran.action.NestedComplexPropertyIA;
+import ch.qos.logback.core.joran.action.NestedBasicPropertyIA;
import ch.qos.logback.core.joran.event.SaxEvent;
import ch.qos.logback.core.joran.spi.EventPlayer;
import ch.qos.logback.core.joran.spi.Interpreter;
@@ -40,11 +40,11 @@
@Override
protected void addImplicitRules(Interpreter interpreter) {
- NestedComponentIA nestedIA = new NestedComponentIA();
+ NestedComplexPropertyIA nestedIA = new NestedComplexPropertyIA();
nestedIA.setContext(context);
interpreter.addImplicitAction(nestedIA);
- NestedSimplePropertyIA nestedSimpleIA = new NestedSimplePropertyIA();
+ NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA();
nestedIA.setContext(context);
interpreter.addImplicitAction(nestedSimpleIA);
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java Thu Jul 17 22:37:35 2008
@@ -19,6 +19,7 @@
TestSuite suite = new TestSuite();
suite.addTestSuite(PatternTest.class);
suite.addTestSuite(SimpleStoreTest.class);
+ suite.addTestSuite(PropertySetterTest.class);
return suite;
}
}
Copied: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java (from r1709, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java)
==============================================================================
--- /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PropertySetterTest.java Thu Jul 17 22:37:35 2008
@@ -1,36 +1,42 @@
-package ch.qos.logback.core.util;
+package ch.qos.logback.core.joran.spi;
import java.util.ArrayList;
import java.util.List;
-import ch.qos.logback.core.spi.FilterReply;
-import ch.qos.logback.core.util.PropertySetter;
import junit.framework.TestCase;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.ContextBase;
+import ch.qos.logback.core.joran.action.IADataForComplexProperty;
+import ch.qos.logback.core.spi.FilterReply;
+import ch.qos.logback.core.util.AggregationType;
+import ch.qos.logback.core.util.Duration;
+import ch.qos.logback.core.util.FileSize;
+import ch.qos.logback.core.util.StatusPrinter;
public class PropertySetterTest extends TestCase {
- public void testCanContainComponent() {
+ public void testCanAggregateComponent() {
House house = new House();
PropertySetter setter = new PropertySetter(house);
- assertEquals(AggregationType.AS_SINGLE_COMPONENT, setter.canContainComponent("door"));
+ assertEquals(AggregationType.AS_COMPLEX_PROPERTY, setter.computeAggregationType("door"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("count"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Count"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("count"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("Count"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("name"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Name"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("name"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("Name"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Duration"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("fs"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("Duration"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("fs"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("open"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Open"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("open"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("Open"));
- assertEquals(AggregationType.AS_COMPONENT_COLLECTION, setter.canContainComponent("Window"));
- assertEquals(AggregationType.AS_PROPERTY_COLLECTION, setter.canContainComponent("adjective"));
+ assertEquals(AggregationType.AS_COMPLEX_PROPERTY_COLLECTION, setter.computeAggregationType("Window"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY_COLLECTION, setter.computeAggregationType("adjective"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("filterReply"));
- assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("houseColor"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("filterReply"));
+ assertEquals(AggregationType.AS_BASIC_PROPERTY, setter.computeAggregationType("houseColor"));
System.out.println();
}
@@ -72,25 +78,42 @@
assertEquals("gh", house.getCamelCase());
}
- public void testSetComponent() {
+ public void testSetComplexProperty() {
House house = new House();
Door door = new Door();
PropertySetter setter = new PropertySetter(house);
- setter.setComponent("door", door);
+ setter.setComplexProperty("door", door);
assertEquals(door, house.getDoor());
}
+ public void testSetComplexProperty2() {
+ House house = new House();
+ //Door door = new Door();
+ PropertySetter setter = new PropertySetter(house);
+
+ IADataForComplexProperty actionData = new IADataForComplexProperty(setter,
+ AggregationType.AS_COMPLEX_PROPERTY, "door");
+
+ Class clazz = setter.findUnequivocallyInstantiableClass(actionData);
+ assertNotNull(clazz);
+ assertEquals(Door.class.getName(), clazz.getName());
+ //setter.setComplexProperty("door", door);
+ //assertEquals(door, house.getDoor());
+ }
public void testPropertyCollection() {
House house = new House();
+ Context context = new ContextBase();
PropertySetter setter = new PropertySetter(house);
- setter.addProperty("adjective", "nice");
- setter.addProperty("adjective", "big");
+ setter.setContext(context);
+ setter.addBasicProperty("adjective", "nice");
+ setter.addBasicProperty("adjective", "big");
+ StatusPrinter.print(context);
assertEquals(2, house.adjectiveList.size());
assertEquals("nice", house.adjectiveList.get(0));
assertEquals("big", house.adjectiveList.get(1));
}
- public void testComponentCollection() {
+ public void testComplexCollection() {
House house = new House();
PropertySetter setter = new PropertySetter(house);
Window w1 = new Window();
@@ -98,21 +121,21 @@
Window w2 = new Window();
w2.handle=20;
- setter.addComponent("window", w1);
- setter.addComponent("window", w2);
+ setter.addComplexProperty("window", w1);
+ setter.addComplexProperty("window", w2);
assertEquals(2, house.windowList.size());
assertEquals(10, house.windowList.get(0).handle);
assertEquals(20, house.windowList.get(1).handle);
}
- public void testSetComponentWithCamelCaseName() {
+ public void testSetComplexWithCamelCaseName() {
House house = new House();
SwimmingPool pool = new SwimmingPool();
PropertySetter setter = new PropertySetter(house);
- setter.setComponent("swimmingPool", pool);
+ setter.setComplexProperty("swimmingPool", pool);
assertEquals(pool, house.getSwimmingPool());
}
-
+
public void testDuration() {
House house = new House();
PropertySetter setter = new PropertySetter(house);
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PackageTest.java Thu Jul 17 22:37:35 2008
@@ -21,7 +21,6 @@
suite.addTestSuite(DurationTest.class);
suite.addTestSuite(FileSizeTest.class);
suite.addTestSuite(OptionHelperTest.class);
- suite.addTestSuite(PropertySetterTest.class);
suite.addTestSuite(StatusPrinterTest.class);
suite.addTestSuite(TimeUtilTest.class);
return suite;
1
0

svn commit: r1709 - in logback/trunk/logback-core/src: main/java/ch/qos/logback/core/joran/action main/java/ch/qos/logback/core/util test/java/ch/qos/logback/core/util
by noreply.ceki@qos.ch 16 Jul '08
by noreply.ceki@qos.ch 16 Jul '08
16 Jul '08
Author: ceki
Date: Wed Jul 16 18:38:08 2008
New Revision: 1709
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java
- copied, changed from r1704, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/ContainmentType.java
Removed:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/ContainmentType.java
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.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/action/NestedSimplePropertyIA.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java
Log:
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ImplicitActionData.java Wed Jul 16 18:38:08 2008
@@ -1,16 +1,22 @@
package ch.qos.logback.core.joran.action;
-import ch.qos.logback.core.util.ContainmentType;
+import ch.qos.logback.core.util.AggregationType;
import ch.qos.logback.core.util.PropertySetter;
+/**
+ * ImplicitActionData is a data class aggregating several fields.
+ *
+ *
+ * @author Ceki
+ */
public class ImplicitActionData {
PropertySetter parentBean;
String propertyName;
Object nestedComponent;
- ContainmentType containmentType;
+ AggregationType containmentType;
boolean inError;
- ImplicitActionData(PropertySetter parentBean, ContainmentType containmentType) {
+ ImplicitActionData(PropertySetter parentBean, AggregationType containmentType) {
this.parentBean = parentBean;
this.containmentType = containmentType;
}
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 Wed Jul 16 18:38:08 2008
@@ -18,7 +18,7 @@
import ch.qos.logback.core.joran.spi.Pattern;
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.LifeCycle;
-import ch.qos.logback.core.util.ContainmentType;
+import ch.qos.logback.core.util.AggregationType;
import ch.qos.logback.core.util.Loader;
import ch.qos.logback.core.util.OptionHelper;
import ch.qos.logback.core.util.PropertySetter;
@@ -54,7 +54,7 @@
PropertySetter parentBean = new PropertySetter(o);
parentBean.setContext(context);
- ContainmentType containmentType = parentBean
+ AggregationType containmentType = parentBean
.canContainComponent(nestedElementTagName);
switch (containmentType) {
@@ -135,7 +135,7 @@
PropertySetter nestedBean = new PropertySetter(actionData.nestedComponent);
nestedBean.setContext(context);
- if (nestedBean.canContainComponent("parent") == ContainmentType.AS_SINGLE_COMPONENT) {
+ if (nestedBean.canContainComponent("parent") == AggregationType.AS_SINGLE_COMPONENT) {
nestedBean.setComponent("parent", actionData.parentBean.getObj());
}
if (actionData.nestedComponent instanceof LifeCycle) {
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedSimplePropertyIA.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedSimplePropertyIA.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedSimplePropertyIA.java Wed Jul 16 18:38:08 2008
@@ -18,7 +18,7 @@
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.joran.spi.Pattern;
-import ch.qos.logback.core.util.ContainmentType;
+import ch.qos.logback.core.util.AggregationType;
import ch.qos.logback.core.util.PropertySetter;
@@ -55,7 +55,7 @@
PropertySetter parentBean = new PropertySetter(o);
parentBean.setContext(context);
- ContainmentType containmentType = parentBean.canContainComponent(nestedElementTagName);
+ AggregationType containmentType = parentBean.canContainComponent(nestedElementTagName);
switch (containmentType) {
case NOT_FOUND:
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java (from r1704, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/ContainmentType.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/ContainmentType.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/AggregationType.java Wed Jul 16 18:38:08 2008
@@ -1,5 +1,9 @@
package ch.qos.logback.core.util;
-public enum ContainmentType {
- NOT_FOUND, AS_SINGLE_COMPONENT, AS_SINGLE_PROPERTY, AS_PROPERTY_COLLECTION, AS_COMPONENT_COLLECTION;
+public enum AggregationType {
+ NOT_FOUND,
+ AS_SINGLE_COMPONENT,
+ AS_SINGLE_PROPERTY,
+ AS_PROPERTY_COLLECTION,
+ AS_COMPONENT_COLLECTION;
}
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java Wed Jul 16 18:38:08 2008
@@ -181,7 +181,7 @@
}
}
- public ContainmentType canContainComponent(String name) {
+ public AggregationType canContainComponent(String name) {
String cName = capitalizeFirstLetter(name);
Method addMethod = getMethod("add" + cName);
@@ -190,11 +190,11 @@
int type = computeContainmentTpye(addMethod);
switch (type) {
case X_NOT_FOUND:
- return ContainmentType.NOT_FOUND;
+ return AggregationType.NOT_FOUND;
case X_AS_PROPERTY:
- return ContainmentType.AS_PROPERTY_COLLECTION;
+ return AggregationType.AS_PROPERTY_COLLECTION;
case X_AS_COMPONENT:
- return ContainmentType.AS_COMPONENT_COLLECTION;
+ return AggregationType.AS_COMPONENT_COLLECTION;
}
}
@@ -213,17 +213,17 @@
// "Found add {} method in class {}", cName, objClass.getName());
switch (type) {
case X_NOT_FOUND:
- return ContainmentType.NOT_FOUND;
+ return AggregationType.NOT_FOUND;
case X_AS_PROPERTY:
- return ContainmentType.AS_SINGLE_PROPERTY;
+ return AggregationType.AS_SINGLE_PROPERTY;
case X_AS_COMPONENT:
- return ContainmentType.AS_SINGLE_COMPONENT;
+ return AggregationType.AS_SINGLE_COMPONENT;
}
}
}
// we have failed
- return ContainmentType.NOT_FOUND;
+ return AggregationType.NOT_FOUND;
}
int computeContainmentTpye(Method setterMethod) {
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java Wed Jul 16 18:38:08 2008
@@ -12,25 +12,25 @@
public void testCanContainComponent() {
House house = new House();
PropertySetter setter = new PropertySetter(house);
- assertEquals(ContainmentType.AS_SINGLE_COMPONENT, setter.canContainComponent("door"));
+ assertEquals(AggregationType.AS_SINGLE_COMPONENT, setter.canContainComponent("door"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("count"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("Count"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("count"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Count"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("name"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("Name"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("name"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Name"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("Duration"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("fs"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Duration"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("fs"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("open"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("Open"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("open"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("Open"));
- assertEquals(ContainmentType.AS_COMPONENT_COLLECTION, setter.canContainComponent("Window"));
- assertEquals(ContainmentType.AS_PROPERTY_COLLECTION, setter.canContainComponent("adjective"));
+ assertEquals(AggregationType.AS_COMPONENT_COLLECTION, setter.canContainComponent("Window"));
+ assertEquals(AggregationType.AS_PROPERTY_COLLECTION, setter.canContainComponent("adjective"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("filterReply"));
- assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("houseColor"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("filterReply"));
+ assertEquals(AggregationType.AS_SINGLE_PROPERTY, setter.canContainComponent("houseColor"));
System.out.println();
}
2
1

[JIRA] Closed: (LBGENERAL-21) SVN link to trunk on web page gives error when used in Eclipse Subversion client
by Ceki Gulcu (JIRA) 15 Jul '08
by Ceki Gulcu (JIRA) 15 Jul '08
15 Jul '08
[ http://jira.qos.ch/browse/LBGENERAL-21?page=com.atlassian.jira.plugin.syste… ]
Ceki Gulcu closed LBGENERAL-21.
-------------------------------
Resolution: Won't Fix
Hi Thorbjørn,
Thank you for this bug report. As I don't know how to change the redirect message shown by viewvc, I can't correct this bug. Given that the bug is minor, and not directly related to logback software, I will mark this issue as "closed". However, if you have a solution or a proposal, I'd be happy to try it.
> SVN link to trunk on web page gives error when used in Eclipse Subversion client
> --------------------------------------------------------------------------------
>
> Key: LBGENERAL-21
> URL: http://jira.qos.ch/browse/LBGENERAL-21
> Project: logback-general
> Issue Type: Bug
> Environment: MyEclipse 6.0.1 (Eclipse 3.3.1 based) on XP
> Reporter: Thorbjørn Ravn Andersen
> Assignee: Logback dev list
>
> When trying to check out the source for logback, I get the following error
> svn: Repository moved permanently to '/viewvc/logback/trunk/'; please relocate
> This goes for any URL I try to use. Please advise.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

[JIRA] Commented: (LBCLASSIC-57) SyslogAppender fails sporadically
by Anton Tagunov (JIRA) 15 Jul '08
by Anton Tagunov (JIRA) 15 Jul '08
15 Jul '08
[ http://jira.qos.ch/browse/LBCLASSIC-57?page=com.atlassian.jira.plugin.syste… ]
Anton Tagunov commented on LBCLASSIC-57:
----------------------------------------
Suggested remedy would probably be to introduce a configurable length limit truncating all messages over threshold.
> SyslogAppender fails sporadically
> ---------------------------------
>
> Key: LBCLASSIC-57
> URL: http://jira.qos.ch/browse/LBCLASSIC-57
> Project: logback-classic
> Issue Type: Bug
> Environment: $ uname -a
> Linux ... 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux
> $ java -version
> java version "1.6.0_03"
> Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
> Java HotSpot(TM) Server VM (build 1.6.0_03-b05, mixed mode)
> multiprocessor PC box
> Reporter: Anton Tagunov
> Assignee: Logback dev list
>
> * several JVM-s per Linux box
> * 5 SyslogAppender-s logging to syslog-ng on 127.0.0.1
> Once in a while one of the SyslogAppender-s (the busiest one with longest messages) stops logging completely
> Other SyslogAppender-ss continue working fine.
> /usr/sbin/tcpdump has confirmed upd packets reach
> syslog-ng port via 'lo' network interface for remaining appends
> /usr/sbin/tcpdump has confirmed NO udp packets reach
> syslog-ng port via 'lo' network interface for the failing appender
> We have JMX enabled. JConsole does show StatusManager messages.
> There are no error messages there.
> Just the messages emitted during initial logback configuration
> from logback.xml on the classpath.
> We had invoked 'reload()' method via JMX.
> StatusMananger messages observed via JMX show that reload had happened.
> Full re-configuration had happened.
> All 5 SyslogAppenders had been apparently re-created.
> Yet NO udp messages had come from the SyslogAppender
> replacing those which had previously failed.
> Reloading did not help at all.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

[JIRA] Commented: (LBCLASSIC-51) Use of BasicStatusManager.iterator() without synchronization in ch.qos.logback.classic.jmx.Configurator
by Joern Huxhorn (JIRA) 15 Jul '08
by Joern Huxhorn (JIRA) 15 Jul '08
15 Jul '08
[ http://jira.qos.ch/browse/LBCLASSIC-51?page=com.atlassian.jira.plugin.syste… ]
Joern Huxhorn commented on LBCLASSIC-51:
----------------------------------------
Please consider fixing this problem before releasing the next logback version.
We had to remove the jmx configurator from our app and would really like to use it in production.
Thanks, Joern.
> Use of BasicStatusManager.iterator() without synchronization in ch.qos.logback.classic.jmx.Configurator
> -------------------------------------------------------------------------------------------------------
>
> Key: LBCLASSIC-51
> URL: http://jira.qos.ch/browse/LBCLASSIC-51
> Project: logback-classic
> Issue Type: Bug
> Components: Other
> Affects Versions: unspecified
> Environment: Operating System: Windows
> Platform: PC
> Reporter: Joern Huxhorn
> Assignee: Logback dev list
>
> We sometimes receive strange exceptions in our webapp:
> [21/Apr/2008:21:00:58] warning ( 1596): CORE3283: stderr: Exception in thread "Thread-6" java.lang.ArrayIndexOutOfBoundsException
> [21/Apr/2008:21:00:58] warning ( 1596): CORE3283: stderr: at java.lang.System.arraycopy(Native Method)
> [21/Apr/2008:21:00:58] warning ( 1596): CORE3283: stderr: at java.util.ArrayList.ensureCapacity(ArrayList.java:170)
> [21/Apr/2008:21:00:58] warning ( 1596): CORE3283: stderr: at java.util.ArrayList.add(ArrayList.java:351)
> [21/Apr/2008:21:00:58] warning ( 1596): CORE3283: stderr: at ch.qos.logback.core.BasicStatusManager.add(BasicStatusManager.java:38)
> [21/Apr/2008:21:00:58] warning ( 1596): CORE3283: stderr: at ch.qos.logback.core.spi.ContextAwareBase.addStatus(ContextAwareBase.java:59)
> [21/Apr/2008:21:00:58] warning ( 1596): CORE3283: stderr: at ch.qos.logback.core.spi.ContextAwareBase.addInfo(ContextAwareBase.java:64)
> I just tried to analyze the problem and found out that ch.qos.logback.classic.jmx.Configurator is simply using the iterator of the status manager without synchronizing, as it's documented in BasicStatusManager.
> So instead of
> public List<String> getStatuses() {
> List<String> list = new ArrayList<String>();
> Iterator<Status> it = context.getStatusManager().iterator();
> while(it.hasNext()) {
> list.add(it.next().toString());
> }
> return list;
> }
> it should probably be
> public List<String> getStatuses() {
> List<String> list = new ArrayList<String>();
> StatusManager sm = context.getStatusManager();
> Iterator<Status> it = sm.iterator();
> synchronized(sm) {
> while(it.hasNext()) {
> list.add(it.next().toString());
> }
> }
> return list;
> }
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0

[JIRA] Commented: (LBCLASSIC-57) SyslogAppender fails sporadically
by Anton Tagunov (JIRA) 14 Jul '08
by Anton Tagunov (JIRA) 14 Jul '08
14 Jul '08
[ http://jira.qos.ch/browse/LBCLASSIC-57?page=com.atlassian.jira.plugin.syste… ]
Anton Tagunov commented on LBCLASSIC-57:
----------------------------------------
We've traced this down to a very long log message "killing" our logging.
After we attempt to log a 1.85Mb message via SyslogAppender it stops working.
What is surprising is that even configuration reload which recreates DatagramSocket does not help.
It looks as if we messes up something in the data structures of libc on top of which jvm operates.
> SyslogAppender fails sporadically
> ---------------------------------
>
> Key: LBCLASSIC-57
> URL: http://jira.qos.ch/browse/LBCLASSIC-57
> Project: logback-classic
> Issue Type: Bug
> Environment: $ uname -a
> Linux ... 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux
> $ java -version
> java version "1.6.0_03"
> Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
> Java HotSpot(TM) Server VM (build 1.6.0_03-b05, mixed mode)
> multiprocessor PC box
> Reporter: Anton Tagunov
> Assignee: Logback dev list
>
> * several JVM-s per Linux box
> * 5 SyslogAppender-s logging to syslog-ng on 127.0.0.1
> Once in a while one of the SyslogAppender-s (the busiest one with longest messages) stops logging completely
> Other SyslogAppender-ss continue working fine.
> /usr/sbin/tcpdump has confirmed upd packets reach
> syslog-ng port via 'lo' network interface for remaining appends
> /usr/sbin/tcpdump has confirmed NO udp packets reach
> syslog-ng port via 'lo' network interface for the failing appender
> We have JMX enabled. JConsole does show StatusManager messages.
> There are no error messages there.
> Just the messages emitted during initial logback configuration
> from logback.xml on the classpath.
> We had invoked 'reload()' method via JMX.
> StatusMananger messages observed via JMX show that reload had happened.
> Full re-configuration had happened.
> All 5 SyslogAppenders had been apparently re-created.
> Yet NO udp messages had come from the SyslogAppender
> replacing those which had previously failed.
> Reloading did not help at all.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
0
Author: ceki
Date: Mon Jul 14 22:19:13 2008
New Revision: 1708
Modified:
logback/trunk/pom.xml
Log:
- latest SLF4J release is 1.5.2
Modified: logback/trunk/pom.xml
==============================================================================
--- logback/trunk/pom.xml (original)
+++ logback/trunk/pom.xml Mon Jul 14 22:19:13 2008
@@ -36,7 +36,7 @@
<properties>
<!-- slf4j.version property is used below and in setClasspath.cmd -->
- <slf4j.version>1.5.0</slf4j.version>
+ <slf4j.version>1.5.2</slf4j.version>
<consolePlugin.version>1.1.0</consolePlugin.version>
<retrotranslator.verify>false</retrotranslator.verify>
</properties>
1
0

14 Jul '08
Author: ceki
Date: Mon Jul 14 22:18:43 2008
New Revision: 1707
Modified:
logback/trunk/logback-site/src/site/pages/download.html
logback/trunk/logback-site/src/site/pages/news.html
Log:
- added blurb about LBCLASSIC-56
- added link to Lilith
Modified: logback/trunk/logback-site/src/site/pages/download.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/download.html (original)
+++ logback/trunk/logback-site/src/site/pages/download.html Mon Jul 14 22:18:43 2008
@@ -78,6 +78,16 @@
classic.</p>
</dd>
+
+ <dt>
+ <a href="http://lilith.huxhorn.de">Lilith</a> by Joern Huxhorn
+ </dt>
+
+ <dd>
+ <p>Lilith is a Logging- and AccessEvent viewer for LOGBack.
+ </p>
+ </dd>
+
</dl>
Modified: logback/trunk/logback-site/src/site/pages/news.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/news.html (original)
+++ logback/trunk/logback-site/src/site/pages/news.html Mon Jul 14 22:18:43 2008
@@ -43,6 +43,11 @@
prevents this. Documenation has been updated to reflect the change.
</p>
+ <p>Fixed <a href="http://jira.qos.ch/browse/LBCLASSIC-56">bug
+ LBCLASSIC-56c</a> originally reported by Michel Colette. Backslash
+ characters are now correctly interpreted in filename patterns.
+ </p>
+
<p>The TurboFilterChain in a LoggerContext is <a
href="http://svn.qos.ch/viewvc?view=rev&revision=1678">now
cleared</a> when the shutdownAndReset method is called. This problem
1
0
Author: ceki
Date: Mon Jul 14 21:31:59 2008
New Revision: 1706
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java
- copied, changed from r1704, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java
Removed:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java
Modified:
logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.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/pattern/parser/OptionTokenizer.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java
Log:
- fixes LBCLASSIC-56
Escaping is implemented selectively. Cerated a new interface called EscapeUtil.
In particular, FileNamePattern now uses AlmostAsIsEscapeUtil.
See also http://jira.qos.ch/browse/LBCLASSIC-56
Modified: logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java (original)
+++ logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java Mon Jul 14 21:31:59 2008
@@ -86,7 +86,10 @@
}
static ContextSelector dynamicalContextSelector(
- LoggerContext defaultLoggerContext, String contextSelectorStr) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
+ LoggerContext defaultLoggerContext, String contextSelectorStr)
+ throws ClassNotFoundException, SecurityException, NoSuchMethodException,
+ IllegalArgumentException, InstantiationException, IllegalAccessException,
+ InvocationTargetException {
Class contextSelectorClass = Loader.loadClass(contextSelectorStr);
Constructor cons = contextSelectorClass
.getConstructor(new Class[] { LoggerContext.class });
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/CoreGlobal.java Mon Jul 14 21:31:59 2008
@@ -44,5 +44,8 @@
* An empty Class array.
*/
public final static Class[] EMPTY_CLASS_ARRAY = new Class[] {};
- static public final String CAUSED_BY = "Caused by: ";
+ public final static String CAUSED_BY = "Caused by: ";
+
+
+ public final static char PERCENT_CHAR = '%';
}
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 Mon Jul 14 21:31:59 2008
@@ -12,7 +12,7 @@
import org.xml.sax.Attributes;
import ch.qos.logback.core.joran.spi.InterpretationContext;
-import ch.qos.logback.core.pattern.util.EscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
import ch.qos.logback.core.util.OptionHelper;
@@ -65,7 +65,7 @@
} else if (
!(OptionHelper.isEmpty(name) || OptionHelper.isEmpty(value))
&& OptionHelper.isEmpty(fileName)) {
- value = EscapeUtil.basicEscape(value);
+ value = RegularEscapeUtil.basicEscape(value);
// now remove both leading and trailing spaces
value = value.trim();
setProperty(ec, name, value);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java Mon Jul 14 21:31:59 2008
@@ -3,7 +3,9 @@
import java.util.ArrayList;
import java.util.List;
-import ch.qos.logback.core.pattern.util.EscapeUtil;
+import ch.qos.logback.core.CoreGlobal;
+import ch.qos.logback.core.pattern.util.IEscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
public class OptionTokenizer {
@@ -16,15 +18,26 @@
private static final char DOUBLE_QUOTE_CHAR = '"';
private static final char SINGLE_QUOTE_CHAR = '\'';
- String pattern;
- int patternLength;
+ final String pattern;
+ final int patternLength;
+ final IEscapeUtil escapeUtil;
+
char quoteChar;
int pointer = 0;
int state = EXPECTING_STATE;
+ /**
+ * This variant is used in tests
+ * @param pattern
+ */
OptionTokenizer(String pattern) {
+ this(pattern, new RegularEscapeUtil());
+ }
+
+ OptionTokenizer(String pattern, IEscapeUtil escapeUtil) {
this.pattern = pattern;
patternLength = pattern.length();
+ this.escapeUtil = escapeUtil;
}
List tokenize() throws ScanException {
@@ -96,7 +109,7 @@
void escape(String escapeChars, StringBuffer buf) {
if ((pointer < patternLength)) {
char next = pattern.charAt(pointer++);
- EscapeUtil.escape(escapeChars, buf, next, pointer);
+ escapeUtil.escape(escapeChars, buf, next, pointer);
}
}
}
\ No newline at end of file
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java Mon Jul 14 21:31:59 2008
@@ -5,6 +5,8 @@
import ch.qos.logback.core.pattern.Converter;
import ch.qos.logback.core.pattern.FormatInfo;
+import ch.qos.logback.core.pattern.util.IEscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
import ch.qos.logback.core.spi.ContextAwareBase;
@@ -12,14 +14,21 @@
final List tokenList;
int pointer = 0;
+ IEscapeUtil escapeUtil;
Parser(TokenStream ts) throws ScanException {
this.tokenList = ts.tokenize();
}
+ // this variant should be used for testing purposes only
public Parser(String pattern) throws ScanException {
+ this(pattern, new RegularEscapeUtil());
+ }
+
+ public Parser(String pattern, IEscapeUtil escapeUtil) throws ScanException {
+ this.escapeUtil = escapeUtil;
try {
- TokenStream ts = new TokenStream(pattern);
+ TokenStream ts = new TokenStream(pattern, escapeUtil);
this.tokenList = ts.tokenize();
} catch (NullPointerException npe) {
throw new ScanException("Failed to initialize Parser", npe);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java Mon Jul 14 21:31:59 2008
@@ -12,7 +12,11 @@
import java.util.List;
import java.util.ArrayList;
-import ch.qos.logback.core.pattern.util.EscapeUtil;
+import ch.qos.logback.core.CoreGlobal;
+import ch.qos.logback.core.pattern.util.IEscapeUtil;
+import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
+
+
/**
* <p>Return a steady stream of tokens. <p/>
@@ -29,7 +33,7 @@
class TokenStream {
private static final char ESCAPE_CHAR = '\\';
- private static final char PERCENT_CHAR = '%';
+ private static final char PERCENT_CHAR = CoreGlobal.PERCENT_CHAR;
private static final char LEFT_PARENTHESIS = '(';
private static final char RIGHT_PARENTHESIS = ')';
private static final char CURLY_LEFT = '{';
@@ -42,15 +46,23 @@
final String pattern;
final int patternLength;
+ final IEscapeUtil escapeUtil;
+
int state = LITERAL_STATE;
int pointer = 0;
+ // this variant should be used for testing purposes only
TokenStream(String pattern) {
+ this(pattern, new RegularEscapeUtil());
+ }
+
+ TokenStream(String pattern, IEscapeUtil escapeUtil) {
if(pattern == null) {
throw new NullPointerException("null pattern string not allowed");
}
this.pattern = pattern;
patternLength = pattern.length();
+ this.escapeUtil = escapeUtil;
}
List tokenize() throws ScanException {
@@ -133,7 +145,7 @@
} else if (c == ESCAPE_CHAR) {
if ((pointer < patternLength)) {
char next = pattern.charAt(pointer++);
- EscapeUtil.escape("%()", buf, next, pointer);
+ escapeUtil.escape("%()", buf, next, pointer);
}
} else {
buf.append(c);
@@ -167,7 +179,7 @@
void escape(String escapeChars, StringBuffer buf) {
if ((pointer < patternLength)) {
char next = pattern.charAt(pointer++);
- EscapeUtil.escape(escapeChars, buf, next, pointer);
+ escapeUtil.escape(escapeChars, buf, next, pointer);
}
}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java Mon Jul 14 21:31:59 2008
@@ -0,0 +1,40 @@
+package ch.qos.logback.core.pattern.util;
+
+import ch.qos.logback.core.CoreGlobal;
+import ch.qos.logback.core.rolling.helper.FileNamePattern;
+
+/**
+ * This implementation is intended for use in {@link FileNamePattern}.
+ *
+ * @author Ceki Gülcü
+ */
+public class AlmostAsIsEscapeUtil implements IEscapeUtil {
+
+ /**
+ * Do not perform any character escaping, except for '%'.
+ *
+ * <p>
+ * Here is the rationale. First, filename patterns do not include escape
+ * combinations such as \r or \n. Moreover, characters which have special
+ * meaning in logback parsers, such as '(', ')', '{', or '}' cannot be part of
+ * file names (so me thinks). Thus, the only character that needs escaping is
+ * '%'.
+ *
+ * <p>
+ * Note that this method assumes that it is called after the escape character
+ * has been consumed.
+ */
+ public void escape(String escapeChars, StringBuffer buf, char next,
+ int pointer) {
+
+ if (next == CoreGlobal.PERCENT_CHAR) {
+ buf.append(CoreGlobal.PERCENT_CHAR);
+ } else {
+ // restitute the escape char (because it was consumed
+ // before this method was called).
+ buf.append("\\");
+ // restitute the next character
+ buf.append(next);
+ }
+ }
+}
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/IEscapeUtil.java Mon Jul 14 21:31:59 2008
@@ -0,0 +1,6 @@
+package ch.qos.logback.core.pattern.util;
+
+public interface IEscapeUtil {
+
+ void escape(String additionalEscapeChars, StringBuffer buf, char next, int pointer);
+}
\ No newline at end of file
Copied: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java (from r1704, /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java)
==============================================================================
--- /logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/EscapeUtil.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java Mon Jul 14 21:31:59 2008
@@ -1,8 +1,13 @@
package ch.qos.logback.core.pattern.util;
-public class EscapeUtil {
+/**
+ * This implementation is intended for use in PatternLayout.
+ *
+ * @author Ceki Gülcü
+ */
+public class RegularEscapeUtil implements IEscapeUtil {
- public static void escape(String escapeChars, StringBuffer buf, char next,
+ public void escape(String escapeChars, StringBuffer buf, char next,
int pointer) {
if (escapeChars.indexOf(next) >= 0) {
buf.append(next);
@@ -24,16 +29,21 @@
buf.append('\n');
break;
default:
- String echars = "";
- for (int i = 0; i < escapeChars.length(); i++) {
- echars += ", \\" + escapeChars.charAt(i);
- }
+ String commaSeperatedEscapeChars = formatEscapeCharsForListing(escapeChars);
new IllegalArgumentException("Illegal char '" + next + " at column "
- + pointer + ". Only \\\\, \\_" + echars
+ + pointer + ". Only \\\\, \\_" + commaSeperatedEscapeChars
+ ", \\t, \\n, \\r combinations are allowed as escape characters.");
}
}
+ String formatEscapeCharsForListing(String escapeChars) {
+ String commaSeperatedEscapeChars = "";
+ for (int i = 0; i < escapeChars.length(); i++) {
+ commaSeperatedEscapeChars += ", \\" + escapeChars.charAt(i);
+ }
+ return commaSeperatedEscapeChars;
+ }
+
public static String basicEscape(String s) {
char c;
int len = s.length();
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java Mon Jul 14 21:31:59 2008
@@ -20,6 +20,7 @@
import ch.qos.logback.core.pattern.parser.Node;
import ch.qos.logback.core.pattern.parser.Parser;
import ch.qos.logback.core.pattern.parser.ScanException;
+import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil;
import ch.qos.logback.core.spi.ContextAwareBase;
@@ -52,7 +53,7 @@
void parse() {
try {
- Parser<Object> p = new Parser<Object>(pattern);
+ Parser<Object> p = new Parser<Object>(pattern, new AlmostAsIsEscapeUtil());
p.setContext(context);
Node t = p.parse();
this.headTokenConverter = p.compile(t, CONVERTER_MAP);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/PropertySetter.java Mon Jul 14 21:31:59 2008
@@ -22,6 +22,7 @@
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import ch.qos.logback.core.spi.ContextAwareBase;
@@ -247,6 +248,20 @@
}
}
}
+
+ <T> boolean isUnequivocallyInstantiable(Class<T> clazz) {
+ if(clazz.isInterface()) {
+ return false;
+ }
+ try {
+ Constructor<T> pubConstructor = clazz.getConstructor();
+ return true;
+ } catch (SecurityException e) {
+ return false;
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
public Class getObjClass() {
return objClass;
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java Mon Jul 14 21:31:59 2008
@@ -10,14 +10,12 @@
package ch.qos.logback.core.pattern.parser;
-import junit.framework.*;
-
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
-import ch.qos.logback.core.pattern.parser.ScanException;
-import ch.qos.logback.core.pattern.parser.Token;
-import ch.qos.logback.core.pattern.parser.TokenStream;
+import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil;
+
+import junit.framework.TestCase;
public class TokenStreamTest extends TestCase {
@@ -317,6 +315,18 @@
witness.add(new Token(Token.LITERAL, ")"));
assertEquals(witness, tl);
}
+ }
+ public void testWindowsLikeBackSlashes() throws ScanException {
+ {
+ List tl = new TokenStream("c:\\hello\\world.%i", new AlmostAsIsEscapeUtil())
+ .tokenize();
+
+ List<Token> witness = new ArrayList<Token>();
+ witness.add(new Token(Token.LITERAL, "c:\\hello\\world."));
+ witness.add(Token.PERCENT_TOKEN);
+ witness.add(new Token(Token.KEYWORD, "i"));
+ assertEquals(witness, tl);
+ }
}
}
\ No newline at end of file
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/FileNamePatternTest.java Mon Jul 14 21:31:59 2008
@@ -20,35 +20,33 @@
import ch.qos.logback.core.rolling.helper.FileNamePattern;
import ch.qos.logback.core.util.StatusPrinter;
-
-
/**
* @author Ceki
- *
+ *
*/
public class FileNamePatternTest extends TestCase {
-
+
Context context = new ContextBase();
-
+
public FileNamePatternTest(String arg) {
super(arg);
}
-
- public void test1() {
- //System.out.println("Testing [t]");
+
+
+ public void testSmoke() {
+ // System.out.println("Testing [t]");
FileNamePattern pp = new FileNamePattern("t", context);
assertEquals("t", pp.convertInt(3));
- //System.out.println("Testing [foo]");
+ // System.out.println("Testing [foo]");
pp = new FileNamePattern("foo", context);
assertEquals("foo", pp.convertInt(3));
- //System.out.println("Testing [foo%]");
- //pp = new FileNamePattern("foo%", context);
- //StatusPrinter.print(context.getStatusManager());
- //assertEquals("foo%", pp.convertInt(3));
-
-
+ // System.out.println("Testing [foo%]");
+ // pp = new FileNamePattern("foo%", context);
+ // StatusPrinter.print(context.getStatusManager());
+ // assertEquals("foo%", pp.convertInt(3));
+
pp = new FileNamePattern("%i foo", context);
StatusPrinter.print(context.getStatusManager());
assertEquals("3 foo", pp.convertInt(3));
@@ -62,7 +60,6 @@
pp = new FileNamePattern("foo.%i.log", context);
assertEquals("foo.3.log", pp.convertInt(3));
-
pp = new FileNamePattern("%i.foo\\%", context);
assertEquals("3.foo%", pp.convertInt(3));
@@ -70,15 +67,21 @@
assertEquals("%foo", pp.convertInt(3));
}
- public void test2() {
- //System.out.println("Testing [foo%ibar%i]");
-
- FileNamePattern pp = new FileNamePattern("foo%i\\_bar%i", context);
- assertEquals("foo3bar3", pp.convertInt(3));
-
+ // test ways for dealing with flowing i converter, as in "foo%ix"
+ public void testFlowingI() {
+ // System.out.println("Testing [foo%ibar%i]");
+
+ {
+ FileNamePattern pp = new FileNamePattern("foo%i{}bar%i", context);
+ assertEquals("foo3bar3", pp.convertInt(3));
+ }
+ {
+ FileNamePattern pp = new FileNamePattern("foo%i{}bar%i", context);
+ assertEquals("foo3bar3", pp.convertInt(3));
+ }
}
- public void test3() {
+ public void testDate() {
Calendar cal = Calendar.getInstance();
cal.set(2003, 4, 20, 17, 55);
@@ -90,15 +93,20 @@
assertEquals("foo2003.05.20 17:55", pp.convertDate(cal.getTime()));
pp = new FileNamePattern("%d{yyyy.MM.dd HH:mm} foo", context);
- assertEquals("2003.05.20 17:55 foo", pp.convertDate(cal.getTime()));
+ assertEquals("2003.05.20 17:55 foo", pp.convertDate(cal.getTime()));
}
+
+ public void testWithBackslash() {
+ FileNamePattern pp = new FileNamePattern("c:\\foo\\bar.%i", context);
+ assertEquals("c:\\foo\\bar.3", pp.convertInt(3));
+ }
public static Test xsuite() {
TestSuite suite = new TestSuite();
suite.addTest(new FileNamePatternTest("test1"));
suite.addTest(new FileNamePatternTest("test2"));
- //suite.addTest(new FileNamePatternTestCase("test3"));
+ // suite.addTest(new FileNamePatternTestCase("test3"));
return suite;
}
1
0