[logback-dev] svn commit: r852 - in logback/trunk/logback-core/src: main/java/ch/qos/logback/core/joran/action main/java/ch/qos/logback/core/joran/spi main/java/ch/qos/logback/core/util test/input/joran test/java/ch/qos/logback/core test/java/ch/qos/logback/core/joran test/java/ch/qos/logback/core/joran/ia test/java/ch/qos/logback/core/joran/replay test/java/ch/qos/logback/core/joran/spi test/java/ch/qos/logback/core/rolling test/java/ch/qos/logback/core/util

noreply.ceki at qos.ch noreply.ceki at qos.ch
Thu Nov 2 19:11:55 CET 2006


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;



More information about the logback-dev mailing list