
Author: ceki Date: Thu Nov 2 19:11:54 2006 New Revision: 852 Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/ContainmentType.java logback/trunk/logback-core/src/test/input/joran/simplePropertyIA1.xml logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java - copied, changed from r829, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/SimpleConfigurator.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/Fruit.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/FruitContext.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/FruitContextAction.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/PackageTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/SimplePropertyIATest.java Removed: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/SimpleConfigurator.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/joran/spi/Pattern.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/AllTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java logback/trunk/logback-core/src/test/java/ch/qos/logback/core/util/PropertySetterTest.java Log: - added capability of setting collections of simple properties in PropertySetter and Joran - small bug fix in Pattern class (a trailing / in the pattern string would cause the addition of an extra component with an empty string) 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 Thu Nov 2 19:11:54 2006 @@ -1,15 +1,16 @@ package ch.qos.logback.core.joran.action; +import ch.qos.logback.core.util.ContainmentType; import ch.qos.logback.core.util.PropertySetter; public class ImplicitActionData { PropertySetter parentBean; String propertyName; Object nestedComponent; - int containmentType; + ContainmentType containmentType; boolean inError; - ImplicitActionData(PropertySetter parentBean, int containmentType) { + ImplicitActionData(PropertySetter parentBean, ContainmentType 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 Thu Nov 2 19:11:54 2006 @@ -10,30 +10,27 @@ package ch.qos.logback.core.joran.action; - - 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.spi.ContextAware; import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.ContainmentType; import ch.qos.logback.core.util.Loader; import ch.qos.logback.core.util.OptionHelper; import ch.qos.logback.core.util.PropertySetter; - import java.util.Stack; - /** - * This action is responsible for tying together a parent object with - * a child element for which there is no explicit rule. + * This action is responsible for tying together a parent object with a child + * element for which there is no explicit rule. * * @author Ceki Gülcü */ public class NestedComponentIA 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. @@ -43,32 +40,35 @@ // be followed by the corresponding pop. Stack<ImplicitActionData> actionDataStack = new Stack<ImplicitActionData>(); - public boolean isApplicable( - Pattern pattern, Attributes attributes, InterpretationContext ec) { - //System.out.println("in NestComponentIA.isApplicable <" + pattern + ">"); + public boolean isApplicable(Pattern pattern, Attributes attributes, + InterpretationContext ec) { + // System.out.println("in NestComponentIA.isApplicable <" + pattern + ">"); String nestedElementTagName = pattern.peekLast(); // calling ec.peekObject with an empty stack will throw an exception - if(ec.isEmpty()) { + if (ec.isEmpty()) { return false; } - + Object o = ec.peekObject(); PropertySetter parentBean = new PropertySetter(o); parentBean.setContext(context); - - int containmentType = parentBean.canContainComponent(nestedElementTagName); + + ContainmentType containmentType = parentBean + .canContainComponent(nestedElementTagName); switch (containmentType) { - case PropertySetter.NOT_FOUND: - case PropertySetter.AS_PROPERTY: + case NOT_FOUND: + case AS_SINGLE_PROPERTY: + case AS_PROPERTY_COLLECTION: return false; - // we only push action data if NestComponentIA is applicable - case PropertySetter.AS_COLLECTION: - case PropertySetter.AS_COMPONENT: - addInfo("is dmmed applicable for "+pattern); - ImplicitActionData ad = new ImplicitActionData(parentBean, containmentType); + // 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); actionDataStack.push(ad); return true; @@ -78,9 +78,9 @@ } } - public void begin( - InterpretationContext ec, String localName, Attributes attributes) { - //LogLog.debug("in NestComponentIA begin method"); + public void begin(InterpretationContext ec, String localName, + Attributes attributes) { + // LogLog.debug("in NestComponentIA begin method"); // get the action data object pushed in isApplicable() method call ImplicitActionData actionData = (ImplicitActionData) actionDataStack.peek(); @@ -98,29 +98,31 @@ } try { - //getLogger().debug( - // "About to instantiate component <{}> of type [{}]", localName, - // className); + // getLogger().debug( + // "About to instantiate component <{}> of type [{}]", localName, + // className); - // FIXME: Loading classes should be governed by config file rules. + // FIXME: Loading classes should be governed by config file rules. actionData.nestedComponent = Loader.loadClass(className).newInstance(); - + // pass along the repository - if(actionData.nestedComponent instanceof ContextAware) { + if (actionData.nestedComponent instanceof ContextAware) { ((ContextAware) actionData.nestedComponent).setContext(this.context); } - //getLogger().debug( - addInfo("Pushing component <"+localName+"> on top of the object stack."); + // getLogger().debug( + addInfo("Pushing component <" + localName + + "> on top of the object stack."); ec.pushObject(actionData.nestedComponent); } catch (Exception oops) { actionData.inError = true; - String msg = "Could not create component <" + localName + "> of type ["+className+"]"; + String msg = "Could not create component <" + localName + "> of type [" + + className + "]"; addError(msg, oops); } } public void end(InterpretationContext ec, String tagName) { - + // pop the action data object pushed in isApplicable() method call // we assume that each this begin ImplicitActionData actionData = (ImplicitActionData) actionDataStack.pop(); @@ -130,47 +132,41 @@ } PropertySetter nestedBean = new PropertySetter(actionData.nestedComponent); - -// FIXME set parent - nestedBean.setComponent( - "parent", actionData.parentBean.getObj()); - + nestedBean.setContext(context); + + if (nestedBean.canContainComponent("parent") == ContainmentType.AS_SINGLE_COMPONENT) { + nestedBean.setComponent("parent", actionData.parentBean.getObj()); + } if (actionData.nestedComponent instanceof LifeCycle) { ((LifeCycle) actionData.nestedComponent).start(); } - - Object o = ec.peekObject(); if (o != actionData.nestedComponent) { - addError( - "The object on the top the of the stack is not the component pushed earlier."); + 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"); + // getLogger().debug("Removing component from the object stack"); ec.popObject(); // Now let us attach the component switch (actionData.containmentType) { - case PropertySetter.AS_COMPONENT: - //addInfo("Setting ["+tagName+"}] to parent of type ["+actionData.parentBean.getObjClass()+"]"); - - actionData.parentBean.setComponent( - tagName, actionData.nestedComponent); + case AS_SINGLE_COMPONENT: + // addInfo("Setting ["+tagName+"}] to parent of type + // ["+actionData.parentBean.getObjClass()+"]"); + + actionData.parentBean.setComponent(tagName, actionData.nestedComponent); break; - case PropertySetter.AS_COLLECTION: - //getLogger().debug( - //"Adding [{}] to parent of type [{}]", tagName, - //actionData.parentBean.getObjClass()); - actionData.parentBean.addComponent( - tagName, actionData.nestedComponent); + case AS_COMPONENT_COLLECTION: + // getLogger().debug( + // "Adding [{}] to parent of type [{}]", tagName, + // actionData.parentBean.getObjClass()); + actionData.parentBean.addComponent(tagName, actionData.nestedComponent); break; } } } - } - 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 Thu Nov 2 19:11:54 2006 @@ -18,6 +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.PropertySetter; @@ -54,15 +55,18 @@ PropertySetter parentBean = new PropertySetter(o); parentBean.setContext(context); - int containmentType = parentBean.canContainComponent(nestedElementTagName); + ContainmentType containmentType = parentBean.canContainComponent(nestedElementTagName); + System.out.println("==="+containmentType); + switch (containmentType) { - case PropertySetter.NOT_FOUND: - case PropertySetter.AS_COMPONENT: - case PropertySetter.AS_COLLECTION: + case NOT_FOUND: + case AS_SINGLE_COMPONENT: + case AS_COMPONENT_COLLECTION: return false; - case PropertySetter.AS_PROPERTY: + case AS_SINGLE_PROPERTY: + case AS_PROPERTY_COLLECTION: ImplicitActionData ad = new ImplicitActionData(parentBean, containmentType); ad.propertyName = nestedElementTagName; actionDataStack.push(ad); @@ -85,8 +89,14 @@ //System.out.println("body "+body+", finalBody="+finalBody); // get the action data object pushed in isApplicable() method call ImplicitActionData actionData = (ImplicitActionData) actionDataStack.peek(); - actionData.parentBean.setProperty(actionData.propertyName, finalBody); + switch (actionData.containmentType) { + case AS_SINGLE_COMPONENT: + actionData.parentBean.setProperty(actionData.propertyName, finalBody); + break; + case AS_PROPERTY_COLLECTION: + actionData.parentBean.addProperty(actionData.propertyName, finalBody); + } } public void end(InterpretationContext ec, String tagName) { Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java ============================================================================== --- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java (original) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java Thu Nov 2 19:11:54 2006 @@ -43,14 +43,16 @@ int lastIndex = 0; - //System.out.println("p is "+ p); + // System.out.println("p is "+ p); while (true) { int k = p.indexOf('/', lastIndex); - //System.out.println("k is "+ k); + // System.out.println("k is "+ k); if (k == -1) { - components.add(p.substring(lastIndex)); - + String lastPart = p.substring(lastIndex); + if(lastPart != null && lastPart.length() > 0) { + components.add(p.substring(lastIndex)); + } break; } else { String c = p.substring(lastIndex, k); @@ -213,7 +215,7 @@ int size = components.size(); String result = ""; for(int i = 0; i < size; i++) { - result += "/" + components.get(i); + result += "[" + components.get(i) + "]"; } return result; } Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/ContainmentType.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/ContainmentType.java Thu Nov 2 19:11:54 2006 @@ -0,0 +1,5 @@ +package ch.qos.logback.core.util; + +public enum ContainmentType { + 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 Thu Nov 2 19:11:54 2006 @@ -50,10 +50,9 @@ * @author Ceki Gulcu */ public class PropertySetter extends ContextAwareBase { - public static final int NOT_FOUND = 0; - public static final int AS_COMPONENT = 1; - public static final int AS_PROPERTY = 2; - public static final int AS_COLLECTION = 3; + private static final int X_NOT_FOUND = 0; + private static final int X_AS_COMPONENT = 1; + private static final int X_AS_PROPERTY = 2; protected Object obj; protected Class objClass; @@ -89,37 +88,6 @@ } /** - * Set the properties for the object that match the <code>prefix</code> - * passed as parameter. - */ - // public void setProperties(Properties properties, String prefix) { - // int len = prefix.length(); - // - // for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { - // String key = (String) e.nextElement(); - // - // // handle only properties that start with the desired frefix. - // if (key.startsWith(prefix)) { - // // ignore key if it contains dots after the prefix - // if (key.indexOf('.', len + 1) > 0) { - // // System.err.println("----------Ignoring---["+key - // // +"], prefix=["+prefix+"]."); - // continue; - // } - // - // String value = OptionHelper.findAndSubst(key, properties); - // - // key = key.substring(len); - // - // if ("layout".equals(key) && obj instanceof Appender) { - // continue; - // } - // - // setProperty(key, value); - // } - // } - // } - /** * Set a property on this PropertySetter's Object. If successful, this method * will invoke a setter method on the underlying Object. The setter is the one * for the specified property name and the value is determined partly from the @@ -208,16 +176,21 @@ } } - public int canContainComponent(String name) { + public ContainmentType canContainComponent(String name) { String cName = capitalizeFirstLetter(name); - Method method = getMethod("add" + cName); - - if (method != null) { - // getLogger().debug( - // "Found add {} method in class {}", cName, objClass.getName()); + Method addMethod = getMethod("add" + cName); - return AS_COLLECTION; + if (addMethod != null) { + int type = computeContainmentTpye(addMethod); + switch (type) { + case X_NOT_FOUND: + return ContainmentType.NOT_FOUND; + case X_AS_PROPERTY: + return ContainmentType.AS_PROPERTY_COLLECTION; + case X_AS_COMPONENT: + return ContainmentType.AS_COMPONENT_COLLECTION; + } } String dName = Introspector.decapitalize(name); @@ -230,25 +203,39 @@ // getLogger().debug( // "Found setter method for property [{}] in class {}", name, // objClass.getName()); - Class[] classArray = setterMethod.getParameterTypes(); - if (classArray.length != 1) { - return NOT_FOUND; - } else { - Class clazz = classArray[0]; - Package p = clazz.getPackage(); - if (clazz.isPrimitive()) { - return AS_PROPERTY; - } else if ("java.lang".equals(p.getName())) { - return AS_PROPERTY; - } else { - return AS_COMPONENT; - } + int type = computeContainmentTpye(setterMethod); + // getLogger().debug( + // "Found add {} method in class {}", cName, objClass.getName()); + switch (type) { + case X_NOT_FOUND: + return ContainmentType.NOT_FOUND; + case X_AS_PROPERTY: + return ContainmentType.AS_SINGLE_PROPERTY; + case X_AS_COMPONENT: + return ContainmentType.AS_SINGLE_COMPONENT; } } } // we have failed - return NOT_FOUND; + return ContainmentType.NOT_FOUND; + } + + int computeContainmentTpye(Method setterMethod) { + Class[] classArray = setterMethod.getParameterTypes(); + if (classArray.length != 1) { + return X_NOT_FOUND; + } else { + Class clazz = classArray[0]; + Package p = clazz.getPackage(); + if (clazz.isPrimitive()) { + return X_AS_PROPERTY; + } else if ("java.lang".equals(p.getName())) { + return X_AS_PROPERTY; + } else { + return X_AS_COMPONENT; + } + } } public Class getObjClass() { @@ -292,6 +279,48 @@ } } + @SuppressWarnings("unchecked") + public void addProperty(String name, String strValue) { + + if (strValue == null) { + return; + } + + name = capitalizeFirstLetter(name); + + Method adderMethod = getMethod("add" + name); + if (adderMethod == null) { + addError("No adder for property [" + name + "]."); + return; + } + + Class[] paramTypes = adderMethod.getParameterTypes(); + if (paramTypes.length != 1) { + addError("#params for setter != 1"); + return; + + } + Object arg; + try { + arg = convertArg(strValue, paramTypes[0]); + } catch (Throwable t) { + addError("Conversion to type [" + paramTypes[0] + "] failed. ", t); + return; + } + + if (arg == null) { + addError("Conversion to type [" + paramTypes[0] + "] failed."); + } else { + + try { + adderMethod.invoke(obj, new Object[] { arg }); + } catch (Exception ex) { + addError("Failed to invoke adder for " + name, ex); + } + } + + } + public void setComponent(String name, Object childComponent) { String dName = Introspector.decapitalize(name); PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName); @@ -387,10 +416,10 @@ } for (int i = 0; i < propertyDescriptors.length; i++) { - //System.out.println("Comparing " + name + " against " - // + propertyDescriptors[i].getName()); + // System.out.println("Comparing " + name + " against " + // + propertyDescriptors[i].getName()); if (name.equals(propertyDescriptors[i].getName())) { - //System.out.println("matched"); + // System.out.println("matched"); return propertyDescriptors[i]; } } Added: logback/trunk/logback-core/src/test/input/joran/simplePropertyIA1.xml ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/test/input/joran/simplePropertyIA1.xml Thu Nov 2 19:11:54 2006 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<context> + <fruit class="ch.qos.logback.core.joran.ia.Fruit"> + <name>blue</name> + <text>hello</text> + </fruit> +</context> \ No newline at end of file Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllTest.java Thu Nov 2 19:11:54 2006 @@ -21,7 +21,6 @@ suite.addTest(ch.qos.logback.core.pattern.PackageTest.suite()); suite.addTest(ch.qos.logback.core.joran.PackageTest.suite()); suite.addTest(ch.qos.logback.core.appender.PackageTest.suite()); - suite.addTest(ch.qos.logback.core.rolling.helper.PackageTest.suite()); suite.addTest(ch.qos.logback.core.rolling.PackageTest.suite()); return suite; } Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/PackageTest.java Thu Nov 2 19:11:54 2006 @@ -22,6 +22,7 @@ suite.addTest(ch.qos.logback.core.joran.event.PackageTest.suite()); suite.addTest(ch.qos.logback.core.joran.spi.PackageTest.suite()); suite.addTest(ch.qos.logback.core.joran.replay.PackageTest.suite()); + suite.addTest(ch.qos.logback.core.joran.ia.PackageTest.suite()); return suite; } } Copied: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java (from r829, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/SimpleConfigurator.java) ============================================================================== --- /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/SimpleConfigurator.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/SimpleConfigurator.java Thu Nov 2 19:11:54 2006 @@ -7,7 +7,7 @@ * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation. */ -package ch.qos.logback.core.joran.replay; +package ch.qos.logback.core.joran; import java.util.HashMap; @@ -42,6 +42,7 @@ protected void addInstanceRules(RuleStore rs) { for(Pattern pattern : rulesMap.keySet()) { Action action = rulesMap.get(pattern); + System.out.println("Adding "+pattern +" "+action); rs.addRule(pattern, action); } } Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/Fruit.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/Fruit.java Thu Nov 2 19:11:54 2006 @@ -0,0 +1,27 @@ +package ch.qos.logback.core.joran.ia; + +import java.util.ArrayList; +import java.util.List; + +public class Fruit { + + String name; + List<String> textList = new ArrayList<String>(); + + public Fruit() { + System.out.println("Fruit constructor called"); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void addText(String s) { + textList.add(s); + } + +} Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/FruitContext.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/FruitContext.java Thu Nov 2 19:11:54 2006 @@ -0,0 +1,23 @@ +package ch.qos.logback.core.joran.ia; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.core.ContextBase; + +public class FruitContext extends ContextBase { + + List<Fruit> fruitList = new ArrayList<Fruit>(); + + public void addFruit(Fruit fs) { + fruitList.add(fs); + } + + public List<Fruit> getFruitList() { + return fruitList; + } + + public void setFruitShellList(List<Fruit> fruitList) { + this.fruitList = fruitList; + } +} Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/FruitContextAction.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/FruitContextAction.java Thu Nov 2 19:11:54 2006 @@ -0,0 +1,62 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework for Java. + * + * Copyright (C) 2000-2006, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ + +package ch.qos.logback.core.joran.ia; + +import org.xml.sax.Attributes; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; + +public class FruitContextAction extends Action { + + private boolean inError = false; + + + @Override + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException { + + + inError = false; + + try { + ec.pushObject(context); + } catch (Exception oops) { + inError = true; + addError( + "Could not push context", oops); + throw new ActionException(ActionException.SKIP_CHILDREN, oops); + } + } + + @Override + public void end(InterpretationContext ec, String name) throws ActionException { + if (inError) { + return; + } + + Object o = ec.peekObject(); + + if (o != context) { + addWarn( + "The object at the of the stack is not the context named [" + + context.getName() + "] pushed earlier."); + } else { + addInfo( + "Popping context named [" + context.getName() + + "] from the object stack"); + ec.popObject(); + } + } + + +} Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/PackageTest.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/PackageTest.java Thu Nov 2 19:11:54 2006 @@ -0,0 +1,23 @@ +/** + * Logback: the generic, reliable, fast and flexible logging framework. + * + * Copyright (C) 1999-2006, QOS.ch + * + * This library is free software, you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation. + */ +package ch.qos.logback.core.joran.ia; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class PackageTest extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTestSuite(SimplePropertyIATest.class); + return suite; + } +} Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/SimplePropertyIATest.java ============================================================================== --- (empty file) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/ia/SimplePropertyIATest.java Thu Nov 2 19:11:54 2006 @@ -0,0 +1,55 @@ +package ch.qos.logback.core.joran.ia; + +import java.util.HashMap; +import java.util.List; + +import junit.framework.TestCase; +import ch.qos.logback.core.joran.SimpleConfigurator; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.Pattern; +import ch.qos.logback.core.util.Constants; +import ch.qos.logback.core.util.StatusPrinter; + +public class SimplePropertyIATest extends TestCase { + + FruitContext fruitContext = new FruitContext(); + + public SimplePropertyIATest(String arg0) { + super(arg0); + } + + protected void setUp() throws Exception { + super.setUp(); + fruitContext.setName("fruits"); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void test() throws Exception { + try { + HashMap<Pattern, Action> rulesMap = new HashMap<Pattern, Action>(); + rulesMap.put(new Pattern("/context/"), new FruitContextAction()); + SimpleConfigurator simpleConfigurator = new SimpleConfigurator(rulesMap); + + simpleConfigurator.setContext(fruitContext); + + simpleConfigurator.doConfigure(Constants.TEST_DIR_PREFIX + "input/joran/" + + "simplePropertyIA1.xml"); + StatusPrinter.print(fruitContext); + List<Fruit> fList = fruitContext.getFruitList(); + assertNotNull(fList); + assertEquals(1, fList.size()); + + Fruit f0 = fList.get(0); + assertEquals("blue", f0.getName()); + assertEquals(1, f0.textList.size()); + } catch (Exception je) { + StatusPrinter.print(fruitContext); + throw je; + } + } + + +} Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/Fruit.java Thu Nov 2 19:11:54 2006 @@ -1,9 +1,13 @@ package ch.qos.logback.core.joran.replay; +import java.util.ArrayList; +import java.util.List; + public class Fruit { String name; - + List<String> textList = new ArrayList<String>(); + public Fruit() { System.out.println("Fruit constructor called"); } @@ -25,4 +29,9 @@ return retValue.toString(); } + + public void addText(String s) { + textList.add(s); + } + } Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/replay/FruitConfigurationTest.java Thu Nov 2 19:11:54 2006 @@ -6,6 +6,7 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; +import ch.qos.logback.core.joran.SimpleConfigurator; import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.action.NOPAction; import ch.qos.logback.core.joran.spi.Pattern; Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java Thu Nov 2 19:11:54 2006 @@ -49,6 +49,13 @@ assertEquals("a", p.get(0)); } + public void testSuffix() { + Pattern p = new Pattern("a/"); + assertEquals(1, p.size()); + assertEquals("a", p.peekLast()); + assertEquals("a", p.get(0)); + } + public void test2() { Pattern p = new Pattern("a/b"); assertEquals(2, p.size()); Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java Thu Nov 2 19:11:54 2006 @@ -69,9 +69,23 @@ fail("Wrong type"); } - // jp.parse(doc); } + public void testSlashSuffix() throws Exception { + SimpleRuleStore srs = new SimpleRuleStore(new ContextBase()); + Pattern pa = new Pattern("a/"); + srs.addRule(pa, new XAction()); + + List r = srs.matchActions(new Pattern("a")); + assertNotNull(r); + assertEquals(1, r.size()); + + if (!(r.get(0) instanceof XAction)) { + fail("Wrong type"); + } + + + } public void testTail1() throws Exception { SimpleRuleStore srs = new SimpleRuleStore(new ContextBase()); srs.addRule(new Pattern("*/b"), new XAction()); Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java ============================================================================== --- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java (original) +++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java Thu Nov 2 19:11:54 2006 @@ -11,6 +11,7 @@ suite.addTestSuite(RenamingTest.class); suite.addTestSuite(SizeBasedRollingTest.class); suite.addTestSuite(TimeBasedRollingTest.class); + suite.addTest(ch.qos.logback.core.rolling.helper.PackageTest.suite()); return suite; } } 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 Thu Nov 2 19:11:54 2006 @@ -1,5 +1,8 @@ package ch.qos.logback.core.util; +import java.util.ArrayList; +import java.util.List; + import ch.qos.logback.core.util.PropertySetter; import junit.framework.TestCase; @@ -8,16 +11,20 @@ public void testCanContainComponent() { House house = new House(); PropertySetter setter = new PropertySetter(house); - assertEquals(PropertySetter.AS_COMPONENT, setter.canContainComponent("door")); + assertEquals(ContainmentType.AS_SINGLE_COMPONENT, setter.canContainComponent("door")); + + assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("count")); + assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("Count")); - assertEquals(PropertySetter.AS_PROPERTY, setter.canContainComponent("count")); - assertEquals(PropertySetter.AS_PROPERTY, setter.canContainComponent("Count")); + assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("name")); + assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("Name")); - assertEquals(PropertySetter.AS_PROPERTY, setter.canContainComponent("name")); - assertEquals(PropertySetter.AS_PROPERTY, setter.canContainComponent("Name")); + assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("open")); + assertEquals(ContainmentType.AS_SINGLE_PROPERTY, setter.canContainComponent("Open")); + + assertEquals(ContainmentType.AS_COMPONENT_COLLECTION, setter.canContainComponent("Window")); + assertEquals(ContainmentType.AS_PROPERTY_COLLECTION, setter.canContainComponent("adjective")); - assertEquals(PropertySetter.AS_PROPERTY, setter.canContainComponent("open")); - assertEquals(PropertySetter.AS_PROPERTY, setter.canContainComponent("Open")); } public void testSetProperty() { @@ -55,10 +62,6 @@ setter.setProperty("camelCase", "gh"); assertEquals("gh", house.getCamelCase()); - - setter.setProperty("OnMatch", "raven"); - assertEquals("raven", house.getOnMatch()); - } public void testSetComponent() { @@ -68,6 +71,31 @@ setter.setComponent("door", door); assertEquals(door, house.getDoor()); } + + public void testPropertyCollection() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + setter.addProperty("adjective", "nice"); + setter.addProperty("adjective", "big"); + assertEquals(2, house.adjectiveList.size()); + assertEquals("nice", house.adjectiveList.get(0)); + assertEquals("big", house.adjectiveList.get(1)); + } + + public void testComponentCollection() { + House house = new House(); + PropertySetter setter = new PropertySetter(house); + Window w1 = new Window(); + w1.handle=10; + Window w2 = new Window(); + w2.handle=20; + + setter.addComponent("window", w1); + setter.addComponent("window", w2); + assertEquals(2, house.windowList.size()); + assertEquals(10, house.windowList.get(0).handle); + assertEquals(20, house.windowList.get(1).handle); + } public void testSetComponentWithCamelCaseName() { House house = new House(); @@ -80,22 +108,16 @@ } class House { - Door door; + Door mainDoor; int count; boolean open; String name; String camelCase; - String onMatch; SwimmingPool pool; - public String getOnMatch() { - return onMatch; - } - - public void setOnMatch(String onMatch) { - this.onMatch = onMatch; - } - + List<String> adjectiveList = new ArrayList<String>(); + List<Window> windowList = new ArrayList<Window>(); + public String getCamelCase() { return camelCase; } @@ -113,11 +135,11 @@ } public Door getDoor() { - return door; + return mainDoor; } public void setDoor(Door door) { - this.door = door; + this.mainDoor = door; } public String getName() { @@ -143,12 +165,25 @@ public SwimmingPool getSwimmingPool() { return pool; } + + public void addWindow(Window w) { + windowList.add(w); + } + + + public void addAdjective(String s) { + adjectiveList.add(s); + } } class Door { int handle; } +class Window { + int handle; +} + class SwimmingPool { int length; int width;