geronimo-xbean-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d...@apache.org
Subject svn commit: r512030 - in /geronimo/xbean/trunk/xbean-reflect: ./ src/main/java/org/apache/xbean/ src/main/java/org/apache/xbean/propertyeditor/ src/main/java/org/apache/xbean/recipe/ src/test/java/org/apache/xbean/recipe/
Date Mon, 26 Feb 2007 22:01:26 GMT
Author: dain
Date: Mon Feb 26 14:01:25 2007
New Revision: 512030

URL: http://svn.apache.org/viewvc?view=rev&rev=512030
Log:
Add support for instance factory methods
Public field injection supported by default
Properties can now be plain old objects
Added unset properties recipe
Added recipe priority

Added:
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractSecretRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MissingFactoryMethodException.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/SecretRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/UnsetPropertiesRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/PersonFactory.java
    geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/UnsetPropertiesTest.java
Removed:
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/Classes.java
Modified:
    geronimo/xbean/trunk/xbean-reflect/pom.xml
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/AbstractConverter.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ArrayConverter.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ClassEditor.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/CollectionUtil.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/PropertyEditors.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/CollectionRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ConstructionException.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MapRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/Recipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/RecipeHelper.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/StaticRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ValueRecipe.java
    geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java
    geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/Person.java

Modified: geronimo/xbean/trunk/xbean-reflect/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/pom.xml?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/pom.xml (original)
+++ geronimo/xbean/trunk/xbean-reflect/pom.xml Mon Feb 26 14:01:25 2007
@@ -46,11 +46,11 @@
             <plugin>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <source>1.4</source>
-                    <target>1.4</target>
+                    <source>1.5</source>
+                    <target>1.5</target>
                 </configuration>
             </plugin>
         </plugins>
     </build>
 
-</project>
\ No newline at end of file
+</project>

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/AbstractConverter.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/AbstractConverter.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/AbstractConverter.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/AbstractConverter.java Mon Feb 26 14:01:25 2007
@@ -18,8 +18,6 @@
 
 import java.beans.PropertyEditorSupport;
 
-import org.apache.xbean.Classes;
-
 /**
  * A base class for converters.  This class handles all converter methods, and redirects all conversion requests to
  * toStringImpl and toObjectImpl.  These methods can assume that the supplied value or text is never null, and that
@@ -66,7 +64,7 @@
             super.setValue(null);
         }
         if (!type.isInstance(value)) {
-            throw new PropertyEditorException("Value is not an instance of " + Classes.getClassName(type));
+            throw new PropertyEditorException("Value is not an instance of " + type.getSimpleName());
         }
         super.setValue(value);
     }
@@ -76,7 +74,7 @@
             return null;
         }
         if (!type.isInstance(value)) {
-            throw new PropertyEditorException("Value is not an instance of " + Classes.getClassName(type) + ": " + value.getClass().getName());
+            throw new PropertyEditorException("Value is not an instance of " + type.getSimpleName() + ": " + value.getClass().getName());
         }
         return toStringImpl(value);
     }

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ArrayConverter.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ArrayConverter.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ArrayConverter.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ArrayConverter.java Mon Feb 26 14:01:25 2007
@@ -21,8 +21,6 @@
 import java.util.List;
 import java.util.ListIterator;
 
-import org.apache.xbean.Classes;
-
 /**
  * Adapter for editing array types.
  *
@@ -33,11 +31,11 @@
         super(type, editor);
 
         if (!type.isArray()) {
-            throw new IllegalArgumentException("type is not an array " + Classes.getClassName(type));
+            throw new IllegalArgumentException("type is not an array " + type.getSimpleName());
         }
 
         if (type.getComponentType().isArray()) {
-            throw new IllegalArgumentException("type is a multi-dimensional array " + Classes.getClassName(type, true));
+            throw new IllegalArgumentException("type is a multi-dimensional array " + type.getSimpleName());
         }
 
         if (editor == null) throw new NullPointerException("editor is null");

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ClassEditor.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ClassEditor.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ClassEditor.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/ClassEditor.java Mon Feb 26 14:01:25 2007
@@ -16,8 +16,6 @@
  */
 package org.apache.xbean.propertyeditor;
 
-import org.apache.xbean.Classes;
-
 /**
  * A property editor for converting class names into class object instances
  *
@@ -47,8 +45,8 @@
     }
 
     protected String toStringImpl(Object value) {
-        Class clazz = (Class) value;
-        String text = Classes.getClassName(clazz);
+        Class type = (Class) value;
+        String text = type.getSimpleName();
         return text;
     }
 }

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/CollectionUtil.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/CollectionUtil.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/CollectionUtil.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/CollectionUtil.java Mon Feb 26 14:01:25 2007
@@ -29,8 +29,6 @@
 import java.io.IOException;
 import java.io.ByteArrayOutputStream;
 
-import org.apache.xbean.Classes;
-
 /**
  * @version $Rev: 6680 $ $Date: 2005-12-24T04:38:27.427468Z $
  */
@@ -140,7 +138,7 @@
             Converter converter = (Converter) componentEditor;
             Class type = converter.getType();
             if (!type.isInstance(value)) {
-                throw new PropertyEditorException("Value is not an instance of " + Classes.getClassName(type) + ": " + value.getClass().getName());
+                throw new PropertyEditorException("Value is not an instance of " + type.getSimpleName() + ": " + value.getClass().getName());
             }
             return converter.toString(value);
         } else {

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/PropertyEditors.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/PropertyEditors.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/PropertyEditors.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/PropertyEditors.java Mon Feb 26 14:01:25 2007
@@ -22,8 +22,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.xbean.Classes;
-
 /**
  * The property editor manager.  This orchestrates Geronimo usage of
  * property editors, allowing additional search paths to be added and
@@ -166,7 +164,7 @@
         // fall back to a property editor
         PropertyEditor editor = findEditor(type);
         if (editor == null) {
-            throw new PropertyEditorException("Unable to find PropertyEditor for " + Classes.getClassName(type, true));
+            throw new PropertyEditorException("Unable to find PropertyEditor for " + type.getSimpleName());
         }
 
         // create the string value
@@ -175,8 +173,8 @@
         try {
             textValue = editor.getAsText();
         } catch (Exception e) {
-            throw new PropertyEditorException("Error while converting a \"" + Classes.getClassName(type, true) + "\" to text " +
-                    " using the property editor " + Classes.getClassName(editor.getClass(), true), e);
+            throw new PropertyEditorException("Error while converting a \"" + type.getSimpleName() + "\" to text " +
+                    " using the property editor " + editor.getClass().getSimpleName(), e);
         }
         return textValue;
     }
@@ -211,7 +209,7 @@
         // fall back to a property editor
         PropertyEditor editor = findEditor(type);
         if (editor == null) {
-            throw new PropertyEditorException("Unable to find PropertyEditor for " + Classes.getClassName(type, true));
+            throw new PropertyEditorException("Unable to find PropertyEditor for " + type.getSimpleName());
         }
 
         // create the object value
@@ -220,8 +218,8 @@
         try {
             objectValue = editor.getValue();
         } catch (Exception e) {
-            throw new PropertyEditorException("Error while converting \"" + value + "\" to a " + Classes.getClassName(type, true) +
-                    " using the property editor " + Classes.getClassName(editor.getClass(), true), e);
+            throw new PropertyEditorException("Error while converting \"" + value + "\" to a " + type.getSimpleName() +
+                    " using the property editor " + editor.getClass().getSimpleName(), e);
         }
         return objectValue;
     }

Added: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractRecipe.java?view=auto&rev=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractRecipe.java (added)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractRecipe.java Mon Feb 26 14:01:25 2007
@@ -0,0 +1,30 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.recipe;
+
+public abstract class AbstractRecipe implements Recipe {
+    public float getPriority() {
+        return 0;
+    }
+
+    public Object create() throws ConstructionException {
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        if (classLoader == null) classLoader = getClass().getClassLoader();
+        return create(classLoader);
+    }
+}

Added: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractSecretRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractSecretRecipe.java?view=auto&rev=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractSecretRecipe.java (added)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/AbstractSecretRecipe.java Mon Feb 26 14:01:25 2007
@@ -0,0 +1,24 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.recipe;
+
+public abstract class AbstractSecretRecipe extends AbstractRecipe implements SecretRecipe {
+    public Object create(ClassLoader classLoader) throws ConstructionException {
+        return create(null, classLoader);
+    }
+}

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/CollectionRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/CollectionRecipe.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/CollectionRecipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/CollectionRecipe.java Mon Feb 26 14:01:25 2007
@@ -28,31 +28,31 @@
 /**
  * @version $Rev: 6685 $ $Date: 2005-12-28T00:29:37.967210Z $
  */
-public class CollectionRecipe implements Recipe {
-    private final List list;
+public class CollectionRecipe extends AbstractRecipe {
+    private final List<Object> list;
     private final String type;
 
     public CollectionRecipe() {
-        list = new ArrayList();
+        list = new ArrayList<Object>();
         type = ArrayList.class.getName();
     }
 
     public CollectionRecipe(String type) {
-        list = new ArrayList();
+        list = new ArrayList<Object>();
         this.type = type;
     }
 
     public CollectionRecipe(Class type) {
         if (type == null) throw new NullPointerException("type is null");
         if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
-        this.list = new ArrayList();
+        this.list = new ArrayList<Object>();
         this.type = type.getName();
     }
 
     public CollectionRecipe(Collection collection) {
         if (collection == null) throw new NullPointerException("collection is null");
 
-        this.list = new ArrayList(collection.size());
+        this.list = new ArrayList<Object>(collection.size());
 
         // If the specified set has a default constructor we will recreate the set, otherwise we use a the default
         if (RecipeHelper.hasDefaultConstructor(collection.getClass())) {
@@ -70,7 +70,7 @@
     public CollectionRecipe(String type, Collection collection) {
         if (type == null) throw new NullPointerException("type is null");
         if (collection == null) throw new NullPointerException("collection is null");
-        this.list = new ArrayList(collection.size());
+        this.list = new ArrayList<Object>(collection.size());
         this.type = type;
         addAll(collection);
     }
@@ -79,7 +79,7 @@
         if (type == null) throw new NullPointerException("type is null");
         if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
         if (collection == null) throw new NullPointerException("collection is null");
-        this.list = new ArrayList(collection.size());
+        this.list = new ArrayList<Object>(collection.size());
         this.type = type.getName();
         addAll(collection);
     }
@@ -87,16 +87,16 @@
     public CollectionRecipe(CollectionRecipe collectionRecipe) {
         if (collectionRecipe == null) throw new NullPointerException("setRecipe is null");
         this.type = collectionRecipe.type;
-        list = new ArrayList(collectionRecipe.list);
+        list = new ArrayList<Object>(collectionRecipe.list);
     }
 
-    public Object create(ClassLoader classLoader) {
-        Class setType = null;
-        try {
-            setType = Class.forName(type, true, classLoader);
-        } catch (ClassNotFoundException e) {
-            throw new ConstructionException("Type class could not be found: " + type);
-        }
+    public boolean canCreate(Class type, ClassLoader classLoader) {
+        Class myType = getType(classLoader);
+        return type.isAssignableFrom(myType);
+    }
+
+    public Collection create(ClassLoader classLoader) {
+        Class setType = getType(classLoader);
 
         if (!RecipeHelper.hasDefaultConstructor(setType)) {
             throw new ConstructionException("Type does not have a default constructor " + type);
@@ -126,10 +126,21 @@
                     throw e;
                 }
             }
+            //noinspection unchecked
             instance.add(value);
             i++;
         }
         return instance;
+    }
+
+    private Class getType(ClassLoader classLoader) {
+        Class setType = null;
+        try {
+            setType = Class.forName(type, true, classLoader);
+        } catch (ClassNotFoundException e) {
+            throw new ConstructionException("Type class could not be found: " + type);
+        }
+        return setType;
     }
 
     public void add(Boolean value) {

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ConstructionException.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ConstructionException.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ConstructionException.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ConstructionException.java Mon Feb 26 14:01:25 2007
@@ -21,7 +21,7 @@
  */
 public class ConstructionException extends RuntimeException {
 
-    private String beanName;
+    private String className;
     private String attributeName;
 
     public ConstructionException() {
@@ -39,12 +39,12 @@
         super(cause);
     }
 
-    public String getBeanName() {
-        return beanName;
+    public String getClassName() {
+        return className;
     }
 
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
+    public void setClassName(String className) {
+        this.className = className;
     }
 
     public String getAttributeName() {
@@ -56,11 +56,17 @@
     }
 
     public void setPrependAttributeName(String attributeName) {
-        this.attributeName += attributeName;
     }
 
     public String getMessage() {
-        return "Unable to create bean " + beanName + " attribute " + attributeName + ": "  + super.getMessage();
+        if (className == null) {
+            return super.getMessage();
+        }
+
+        if (attributeName == null) {
+            return "Unable to create bean of type " + className + ": "  + super.getMessage();
+        }
 
+        return "Unable to create bean of type " + className + " for attribute " + attributeName + ": "  + super.getMessage();
     }
 }

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MapRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MapRecipe.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MapRecipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MapRecipe.java Mon Feb 26 14:01:25 2007
@@ -27,30 +27,30 @@
 /**
  * @version $Rev: 6687 $ $Date: 2005-12-28T21:08:56.733437Z $
  */
-public class MapRecipe implements Recipe {
-    private final List entries;
+public class MapRecipe extends AbstractRecipe {
+    private final List<Object[]> entries;
     private final String type;
 
     public MapRecipe() {
         type = LinkedHashMap.class.getName();
-        entries = new ArrayList();
+        entries = new ArrayList<Object[]>();
     }
 
     public MapRecipe(String type) {
         this.type = type;
-        entries = new ArrayList();
+        entries = new ArrayList<Object[]>();
     }
 
     public MapRecipe(Class type) {
         this.type = type.getName();
         if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
-        entries = new ArrayList();
+        entries = new ArrayList<Object[]>();
     }
 
     public MapRecipe(Map map) {
         if (map == null) throw new NullPointerException("map is null");
 
-        entries = new ArrayList(map.size());
+        entries = new ArrayList<Object[]>(map.size());
 
         // If the specified set has a default constructor we will recreate the set, otherwise we use a LinkedHashMap or TreeMap
         if (RecipeHelper.hasDefaultConstructor(map.getClass())) {
@@ -66,7 +66,7 @@
     public MapRecipe(String type, Map map) {
         if (map == null) throw new NullPointerException("map is null");
         this.type = type;
-        entries = new ArrayList(map.size());
+        entries = new ArrayList<Object[]>(map.size());
         putAll(map);
     }
 
@@ -74,23 +74,23 @@
         if (map == null) throw new NullPointerException("map is null");
         if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
         this.type = type.getName();
-        entries = new ArrayList(map.size());
+        entries = new ArrayList<Object[]>(map.size());
         putAll(map);
     }
 
     public MapRecipe(MapRecipe mapRecipe) {
         if (mapRecipe == null) throw new NullPointerException("mapRecipe is null");
         this.type = mapRecipe.type;
-        entries = new ArrayList(mapRecipe.entries);
+        entries = new ArrayList<Object[]>(mapRecipe.entries);
     }
 
-    public Object create(ClassLoader classLoader) {
-        Class mapType = null;
-        try {
-            mapType = Class.forName(type, true, classLoader);
-        } catch (ClassNotFoundException e) {
-            throw new ConstructionException("Type class could not be found: " + type);
-        }
+    public boolean canCreate(Class type, ClassLoader classLoader) {
+        Class myType = getType(classLoader);
+        return type.isAssignableFrom(myType);
+    }
+
+    public Map create(ClassLoader classLoader) {
+        Class mapType = getType(classLoader);
 
         if (!RecipeHelper.hasDefaultConstructor(mapType)) {
             throw new ConstructionException("Type does not have a default constructor " + type);
@@ -108,9 +108,7 @@
         }
 
         Map instance = (Map) o;
-        for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
-            Object[] entry = (Object[]) iterator.next();
-
+        for (Object[] entry : entries) {
             Object key = entry[0];
             if (key instanceof Recipe) {
                 Recipe recipe = (Recipe) key;
@@ -133,9 +131,20 @@
                 }
             }
 
+            //noinspection unchecked
             instance.put(key, value);
         }
         return instance;
+    }
+
+    private Class getType(ClassLoader classLoader) {
+        Class mapType = null;
+        try {
+            mapType = Class.forName(type, true, classLoader);
+        } catch (ClassNotFoundException e) {
+            throw new ConstructionException("Type class could not be found: " + type);
+        }
+        return mapType;
     }
 
     public void put(Object key, Object value) {

Added: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MissingFactoryMethodException.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MissingFactoryMethodException.java?view=auto&rev=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MissingFactoryMethodException.java (added)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/MissingFactoryMethodException.java Mon Feb 26 14:01:25 2007
@@ -0,0 +1,27 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.recipe;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class MissingFactoryMethodException extends ConstructionException {
+    public MissingFactoryMethodException(String message) {
+        super(message);
+    }
+}

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java Mon Feb 26 14:01:25 2007
@@ -16,7 +16,6 @@
  */
 package org.apache.xbean.recipe;
 
-import org.apache.xbean.Classes;
 import org.apache.xbean.propertyeditor.PropertyEditors;
 
 import java.lang.reflect.Constructor;
@@ -26,24 +25,25 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Iterator;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
 /**
  * @version $Rev: 6688 $ $Date: 2005-12-29T02:08:29.200064Z $
  */
-public class ObjectRecipe implements Recipe {
+public class ObjectRecipe extends AbstractRecipe {
     private final String type;
     private final String factoryMethod;
     private final String[] constructorArgNames;
     private final Class[] constructorArgTypes;
-    private final LinkedHashMap properties;
-    private final List options = new ArrayList();
-    private final Map unsetProperties = new LinkedHashMap();
+    private final LinkedHashMap<Property,Object> properties;
+    private final List<Option> options = new ArrayList<Option>();
+    private final Map<String,Object> unsetProperties = new LinkedHashMap<String,Object>();
+
     public ObjectRecipe(Class type) {
         this(type.getName());
     }
@@ -52,7 +52,7 @@
         this(type.getName(), factoryMethod);
     }
 
-    public ObjectRecipe(Class type, Map properties) {
+    public ObjectRecipe(Class type, Map<String,Object> properties) {
         this(type.getName(), properties);
     }
 
@@ -72,7 +72,7 @@
         this(typeName, factoryMethod, null, null, null);
     }
 
-    public ObjectRecipe(String typeName, Map properties) {
+    public ObjectRecipe(String typeName, Map<String,Object> properties) {
         this(typeName, null, null, null, properties);
     }
 
@@ -84,7 +84,9 @@
         this(typeName, factoryMethod, constructorArgNames, constructorArgTypes, null);
     }
 
-    public ObjectRecipe(String type, String factoryMethod, String[] constructorArgNames, Class[] constructorArgTypes, Map properties) {
+    public ObjectRecipe(String type, String factoryMethod, String[] constructorArgNames, Class[] constructorArgTypes, Map<String,Object> properties) {
+        options.add(Option.FIELD_INJECTION);
+        
         this.type = type;
         this.factoryMethod = factoryMethod;
         if (constructorArgNames != null) {
@@ -98,10 +100,10 @@
             this.constructorArgTypes = new Class[0];
         }
         if (properties != null) {
-            this.properties = new LinkedHashMap(properties);
+            this.properties = new LinkedHashMap<Property,Object>();
             setAllProperties(properties);
         } else {
-            this.properties = new LinkedHashMap();
+            this.properties = new LinkedHashMap<Property,Object>();
         }
     }
 
@@ -132,8 +134,8 @@
     }
 
     private void setProperty(Property key, Object value) {
-        if (!RecipeHelper.isSimpleType(value)) {
-            value = new ValueRecipe(value);
+        if (value instanceof UnsetPropertiesRecipe) {
+            allow(Option.IGNORE_MISSING_PROPERTIES);
         }
         properties.put(key, value);
     }
@@ -149,89 +151,65 @@
         }
     }
 
-    public Object create() throws ConstructionException {
-        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
-        return create(contextClassLoader);
+    public Map<String,Object> getUnsetProperties() {
+        return unsetProperties;
+    }
+
+    public boolean canCreate(Class type, ClassLoader classLoader) {
+        Class myType = getType(classLoader);
+        return type.isAssignableFrom(myType);
     }
 
     public Object create(ClassLoader classLoader) throws ConstructionException {
         unsetProperties.clear();
         // load the type class
-        Class typeClass = null;
-        try {
-            typeClass = Class.forName(type, true, classLoader);
-        } catch (ClassNotFoundException e) {
-            throw new ConstructionException("Type class could not be found: " + type);
-        }
+        Class typeClass = getType(classLoader);
 
         // verify that it is a class we can construct
         if (!Modifier.isPublic(typeClass.getModifiers())) {
-            throw new ConstructionException("Class is not public: " + Classes.getClassName(typeClass, true));
+            throw new ConstructionException("Class is not public: " + typeClass.getName());
         }
         if (Modifier.isInterface(typeClass.getModifiers())) {
-            throw new ConstructionException("Class is an interface: " + Classes.getClassName(typeClass, true));
+            throw new ConstructionException("Class is an interface: " + typeClass.getName());
         }
         if (Modifier.isAbstract(typeClass.getModifiers())) {
-            throw new ConstructionException("Class is abstract: " + Classes.getClassName(typeClass, true));
+            throw new ConstructionException("Class is abstract: " + typeClass.getName());
         }
 
-        // get object values for all recipe properties
-        Map propertyValues = new LinkedHashMap(properties);
-        for (Iterator iterator = propertyValues.entrySet().iterator(); iterator.hasNext();) {
-            Map.Entry entry = (Map.Entry) iterator.next();
-            Object value = entry.getValue();
-            if (value instanceof Recipe) {
-                Recipe recipe = ((Recipe) value);
-                value = recipe.create(classLoader);
-                entry.setValue(value);
-            }
+        // clone the properties so they can be used again
+        Map<Property,Object> propertyValues = new LinkedHashMap<Property,Object>(properties);
+
+        // find the factory method is one is declared
+        Method factoryMethod = null;
+        if (this.factoryMethod != null) {
+            factoryMethod = findFactoryMethod(typeClass, this.factoryMethod);
         }
 
         // create the instance
-        Object instance = createInstance(typeClass, propertyValues);
+        Object result;
+        if (factoryMethod != null && Modifier.isStatic(factoryMethod.getModifiers())) {
+            result = createInstance(factoryMethod, propertyValues, classLoader);
+        } else {
+            Constructor constructor = selectConstructor(typeClass);
+            result = createInstance(constructor, propertyValues, classLoader);
+        }
+        Object instance = result;
 
         boolean allowPrivate = options.contains(Option.PRIVATE_PROPERTIES);
         boolean ignoreMissingProperties = options.contains(Option.IGNORE_MISSING_PROPERTIES);
 
         // set remaining properties
-        for (Iterator iterator = propertyValues.entrySet().iterator(); iterator.hasNext();) {
-            Map.Entry entry = (Map.Entry) iterator.next();
-            Property propertyName = (Property) entry.getKey();
+        for (Map.Entry<Property, Object> entry : RecipeHelper.prioritizeProperties(propertyValues)) {
+            Property propertyName = entry.getKey();
             Object propertyValue = entry.getValue();
 
-            Member member;
-            try {
-                if (propertyName instanceof SetterProperty){
-                    member = new MethodMember(findSetter(typeClass, propertyName.name, propertyValue, allowPrivate));
-                } else if (propertyName instanceof FieldProperty){
-                    member = new FieldMember(findField(typeClass, propertyName.name, propertyValue, allowPrivate));
-                } else {
-                    try {
-                        member = new MethodMember(findSetter(typeClass, propertyName.name, propertyValue, allowPrivate));
-                    } catch (MissingAccessorException noSetter) {
-                        if (!options.contains(Option.FIELD_INJECTION)) {
-                            throw noSetter;
-                        }
-
-                        try {
-                            member = new FieldMember(findField(typeClass, propertyName.name, propertyValue, allowPrivate));
-                        } catch (MissingAccessorException noField) {
-                            throw (noField.getMatchLevel() > noSetter.getMatchLevel())? noField: noSetter;
-                        }
-                    }
-                }
-            } catch (MissingAccessorException e) {
-                if (ignoreMissingProperties){
-                    unsetProperties.put(propertyName.name, propertyValue);
-                    continue;
-                } else {
-                    throw e;
-                }
-            }
+            setProperty(instance, propertyName, propertyValue, allowPrivate, ignoreMissingProperties, classLoader);
+        }
 
+        // call instance factory method
+        if (factoryMethod != null && !Modifier.isStatic(factoryMethod.getModifiers())) {
             try {
-                propertyValue = convert(member.getType(), propertyValue);
-                member.setValue(instance, propertyValue);
+                instance = factoryMethod.invoke(instance);
             } catch (Exception e) {
                 Throwable t = e;
                 if (e instanceof InvocationTargetException) {
@@ -240,17 +218,70 @@
                         t = invocationTargetException.getCause();
                     }
                 }
-                throw new ConstructionException("Error setting property: " + member, t);
+                throw new ConstructionException("Error calling factory method: " + factoryMethod, t);
             }
         }
+
         return instance;
     }
 
-    public Map getUnsetProperties() {
-        return new LinkedHashMap(unsetProperties);
+    private Class getType(ClassLoader classLoader) {
+        Class typeClass = null;
+        try {
+            typeClass = Class.forName(type, true, classLoader);
+        } catch (ClassNotFoundException e) {
+            throw new ConstructionException("Type class could not be found: " + type);
+        }
+        return typeClass;
+    }
+
+    private void setProperty(Object instance, Property propertyName, Object propertyValue, boolean allowPrivate, boolean ignoreMissingProperties, ClassLoader classLoader) {
+        Member member;
+        try {
+            if (propertyName instanceof SetterProperty){
+                member = new MethodMember(findSetter(instance.getClass(), propertyName.name, propertyValue, allowPrivate, classLoader));
+            } else if (propertyName instanceof FieldProperty){
+                member = new FieldMember(findField(instance.getClass(), propertyName.name, propertyValue, allowPrivate, classLoader));
+            } else {
+                try {
+                    member = new MethodMember(findSetter(instance.getClass(), propertyName.name, propertyValue, allowPrivate, classLoader));
+                } catch (MissingAccessorException noSetter) {
+                    if (!options.contains(Option.FIELD_INJECTION)) {
+                        throw noSetter;
+                    }
+
+                    try {
+                        member = new FieldMember(findField(instance.getClass(), propertyName.name, propertyValue, allowPrivate, classLoader));
+                    } catch (MissingAccessorException noField) {
+                        throw (noField.getMatchLevel() > noSetter.getMatchLevel())? noField: noSetter;
+                    }
+                }
+            }
+        } catch (MissingAccessorException e) {
+            if (ignoreMissingProperties){
+                unsetProperties.put(propertyName.name, propertyValue);
+                return;
+            } else {
+                throw e;
+            }
+        }
+
+        try {
+            propertyValue = convert(member.getType(), propertyValue, classLoader);
+            member.setValue(instance, propertyValue);
+        } catch (Exception e) {
+            Throwable t = e;
+            if (e instanceof InvocationTargetException) {
+                InvocationTargetException invocationTargetException = (InvocationTargetException) e;
+                if (invocationTargetException.getCause() != null) {
+                    t = invocationTargetException.getCause();
+                }
+            }
+            throw new ConstructionException("Error setting property: " + member, t);
+        }
     }
 
-    private Object[] extractConstructorArgs(Map propertyValues, Class[] constructorArgTypes) {
+    private Object[] extractConstructorArgs(Map propertyValues, Class[] constructorArgTypes, ClassLoader classLoader) {
         Object[] parameters = new Object[constructorArgNames.length];
         for (int i = 0; i < constructorArgNames.length; i++) {
             Property name = new Property(constructorArgNames[i]);
@@ -259,14 +290,14 @@
             Object value;
             if (propertyValues.containsKey(name)) {
                 value = propertyValues.remove(name);
-                if (!isInstance(type, value) && !isConvertable(type, value)) {
+                if (!isInstance(type, value) && !isConvertable(type, value, classLoader)) {
                     throw new ConstructionException("Invalid and non-convertable constructor parameter type: " +
                             "name=" + name + ", " +
                             "index=" + i + ", " +
-                            "expected=" + Classes.getClassName(type, true) + ", " +
-                            "actual=" + Classes.getClassName(value, true));
+                            "expected=" + type.getName() + ", " +
+                            "actual=" + getClassName(value));
                 }
-                value = convert(type, value);
+                value = convert(type, value, classLoader);
             } else {
                 value = getDefaultValue(type);
             }
@@ -277,7 +308,23 @@
         return parameters;
     }
 
-    private static Object convert(Class type, Object value) {
+    private static String getClassName(Object value) {
+        if (value == null) return "null";
+
+        return value.getClass().getName();
+    }
+
+    private Object convert(Class type, Object value, ClassLoader classLoader) {
+        if (value instanceof Recipe) {
+            if (value instanceof SecretRecipe) {
+                SecretRecipe recipe = (SecretRecipe) value;
+                value = recipe.create(this, classLoader);
+            } else {
+                Recipe recipe = (Recipe) value;
+                value = recipe.create(classLoader);
+            }
+        }
+
         if (value instanceof String && (type != Object.class)) {
             String stringValue = (String) value;
             value = PropertyEditors.getValue(type, stringValue);
@@ -306,129 +353,50 @@
         return null;
     }
 
-    private Object createInstance(Class typeClass, Map propertyValues) {
-        if (factoryMethod != null) {
-            Method method = selectFactory(typeClass);
-            // get the constructor parameters
-            Object[] parameters = extractConstructorArgs(propertyValues, method.getParameterTypes());
+    private Object createInstance(Constructor constructor, Map propertyValues, ClassLoader classLoader) {
+        // get the constructor parameters
+        Object[] parameters = extractConstructorArgs(propertyValues, constructor.getParameterTypes(), classLoader);
 
-            try {
-                Object object = method.invoke(null, parameters);
-                return object;
-            } catch (Exception e) {
-                Throwable t = e;
-                if (e instanceof InvocationTargetException) {
-                    InvocationTargetException invocationTargetException = (InvocationTargetException) e;
-                    if (invocationTargetException.getCause() != null) {
-                        t = invocationTargetException.getCause();
-                    }
-                }
-                throw new ConstructionException("Error invoking factory method: " + method, t);
-            }
-        } else {
-            Constructor constructor = selectConstructor(typeClass);
-            // get the constructor parameters
-            Object[] parameters = extractConstructorArgs(propertyValues, constructor.getParameterTypes());
-
-            try {
-                Object object = constructor.newInstance(parameters);
-                return object;
-            } catch (Exception e) {
-                Throwable t = e;
-                if (e instanceof InvocationTargetException) {
-                    InvocationTargetException invocationTargetException = (InvocationTargetException) e;
-                    if (invocationTargetException.getCause() != null) {
-                        t = invocationTargetException.getCause();
-                    }
+        try {
+            Object object = constructor.newInstance(parameters);
+            return object;
+        } catch (Exception e) {
+            Throwable t = e;
+            if (e instanceof InvocationTargetException) {
+                InvocationTargetException invocationTargetException = (InvocationTargetException) e;
+                if (invocationTargetException.getCause() != null) {
+                    t = invocationTargetException.getCause();
                 }
-                throw new ConstructionException("Error invoking constructor: " + constructor, t);
             }
+            throw new ConstructionException("Error invoking constructor: " + constructor, t);
         }
     }
 
-    private Method selectFactory(Class typeClass) {
-        if (constructorArgNames.length > 0 && constructorArgTypes.length == 0) {
-            ArrayList matches = new ArrayList();
-
-            Method[] methods = typeClass.getMethods();
-            for (int i = 0; i < methods.length; i++) {
-                Method method = methods[i];
-                if (method.getName().equals(factoryMethod) && method.getParameterTypes().length == constructorArgNames.length) {
-                    try {
-                        checkFactory(method);
-                        matches.add(method);
-                    } catch (Exception dontCare) {
-                    }
-                }
-            }
-
-            if (matches.size() < 1) {
-                StringBuffer buffer = new StringBuffer("No parameter types supplied; unable to find a potentially valid factory method: ");
-                buffer.append("public static Object ").append(factoryMethod);
-                buffer.append(toArgumentList(constructorArgNames));
-                throw new ConstructionException(buffer.toString());
-            } else if (matches.size() > 1) {
-                StringBuffer buffer = new StringBuffer("No parameter types supplied; found too many potentially valid factory methods: ");
-                buffer.append("public static Object ").append(factoryMethod);
-                buffer.append(toArgumentList(constructorArgNames));
-                throw new ConstructionException(buffer.toString());
-            }
-
-            return (Method) matches.get(0);
-        }
+    private Object createInstance(Method method, Map propertyValues, ClassLoader classLoader) {
+        // get the constructor parameters
+        Object[] parameters = extractConstructorArgs(propertyValues, method.getParameterTypes(), classLoader);
 
         try {
-            Method method = typeClass.getMethod(factoryMethod, constructorArgTypes);
-
-            checkFactory(method);
-
-            return method;
-        } catch (NoSuchMethodException e) {
-            // try to find a matching private method
-            Method[] methods = typeClass.getDeclaredMethods();
-            for (int i = 0; i < methods.length; i++) {
-                Method method = methods[i];
-                if (method.getName().equals(factoryMethod) && isAssignableFrom(constructorArgTypes, method.getParameterTypes())) {
-                    if (!Modifier.isPublic(method.getModifiers())) {
-                        throw new ConstructionException("Factory method is not public: " + method);
-                    }
+            Object object = method.invoke(null, parameters);
+            return object;
+        } catch (Exception e) {
+            Throwable t = e;
+            if (e instanceof InvocationTargetException) {
+                InvocationTargetException invocationTargetException = (InvocationTargetException) e;
+                if (invocationTargetException.getCause() != null) {
+                    t = invocationTargetException.getCause();
                 }
             }
-
-            StringBuffer buffer = new StringBuffer("Unable to find a valid factory method: ");
-            buffer.append("public static Object ").append(Classes.getClassName(typeClass, true)).append(".");
-            buffer.append(factoryMethod).append(toParameterList(constructorArgTypes));
-            throw new ConstructionException(buffer.toString());
-        }
-    }
-
-    private void checkFactory(Method method) {
-        if (!Modifier.isPublic(method.getModifiers())) {
-            // this will never occur since private methods are not returned from
-            // getMethod, but leave this here anyway, just to be safe
-            throw new ConstructionException("Factory method is not public: " + method);
-        }
-
-        if (!Modifier.isStatic(method.getModifiers())) {
-            throw new ConstructionException("Factory method is not static: " + method);
-        }
-
-        if (method.getReturnType().equals(Void.TYPE)) {
-            throw new ConstructionException("Factory method does not return anything: " + method);
-        }
-
-        if (method.getReturnType().isPrimitive()) {
-            throw new ConstructionException("Factory method returns a primitive type: " + method);
+            throw new ConstructionException("Error invoking factory method: " + method, t);
         }
     }
 
     private Constructor selectConstructor(Class typeClass) {
         if (constructorArgNames.length > 0 && constructorArgTypes.length == 0) {
-            ArrayList matches = new ArrayList();
+            ArrayList<Constructor> matches = new ArrayList<Constructor>();
 
             Constructor[] constructors = typeClass.getConstructors();
-            for (int i = 0; i < constructors.length; i++) {
-                Constructor constructor = constructors[i];
+            for (Constructor constructor : constructors) {
                 if (constructor.getParameterTypes().length == constructorArgNames.length) {
                     matches.add(constructor);
                 }
@@ -436,17 +404,17 @@
 
             if (matches.size() < 1) {
                 StringBuffer buffer = new StringBuffer("No parameter types supplied; unable to find a potentially valid constructor: ");
-                buffer.append("constructor= public ").append(Classes.getClassName(typeClass, true));
+                buffer.append("constructor= public ").append(typeClass.getName());
                 buffer.append(toArgumentList(constructorArgNames));
                 throw new ConstructionException(buffer.toString());
             } else if (matches.size() > 1) {
                 StringBuffer buffer = new StringBuffer("No parameter types supplied; found too many potentially valid constructors: ");
-                buffer.append("constructor= public ").append(Classes.getClassName(typeClass, true));
+                buffer.append("constructor= public ").append(typeClass.getName());
                 buffer.append(toArgumentList(constructorArgNames));
                 throw new ConstructionException(buffer.toString());
             }
 
-            return (Constructor) matches.get(0);
+            return matches.get(0);
         }
 
         try {
@@ -462,8 +430,7 @@
         } catch (NoSuchMethodException e) {
             // try to find a matching private method
             Constructor[] constructors = typeClass.getDeclaredConstructors();
-            for (int i = 0; i < constructors.length; i++) {
-                Constructor constructor = constructors[i];
+            for (Constructor constructor : constructors) {
                 if (isAssignableFrom(constructorArgTypes, constructor.getParameterTypes())) {
                     if (!Modifier.isPublic(constructor.getModifiers())) {
                         throw new ConstructionException("Constructor is not public: " + constructor);
@@ -472,7 +439,7 @@
             }
 
             StringBuffer buffer = new StringBuffer("Unable to find a valid constructor: ");
-            buffer.append("constructor= public ").append(Classes.getClassName(typeClass, true));
+            buffer.append("constructor= public ").append(typeClass.getName());
             buffer.append(toParameterList(constructorArgTypes));
             throw new ConstructionException(buffer.toString());
         }
@@ -484,7 +451,7 @@
         for (int i = 0; i < parameterTypes.length; i++) {
             Class type = parameterTypes[i];
             if (i > 0) buffer.append(", ");
-            buffer.append(Classes.getClassName(type, true));
+            buffer.append(type.getName());
         }
         buffer.append(")");
         return buffer.toString();
@@ -502,7 +469,86 @@
         return buffer.toString();
     }
 
-    public static Method findSetter(Class typeClass, String propertyName, Object propertyValue, boolean allowPrivate) {
+    public Method findFactoryMethod(Class typeClass, String factoryMethod) {
+        if (factoryMethod == null) throw new NullPointerException("name is null");
+        if (factoryMethod.length() == 0) throw new IllegalArgumentException("name is an empty string");
+
+        int matchLevel = 0;
+        MissingFactoryMethodException missException = null;
+
+        List<Method> methods = new ArrayList<Method>(Arrays.asList(typeClass.getMethods()));
+        methods.addAll(Arrays.asList(typeClass.getDeclaredMethods()));
+        for (Method method : methods) {
+            if (method.getName().equals(factoryMethod)) {
+                if (Modifier.isStatic(method.getModifiers())) {
+                    if (method.getParameterTypes().length != constructorArgNames.length) {
+                        if (matchLevel < 1) {
+                            matchLevel = 1;
+                            missException = new MissingFactoryMethodException("Static factory method has " + method.getParameterTypes().length + " arugments " +
+                                    "but expected " + constructorArgNames.length + " arguments: " + method);
+                        }
+                        continue;
+                    }
+
+                    if (constructorArgTypes.length > 0 && !isAssignableFrom(constructorArgTypes, method.getParameterTypes())) {
+                        if (matchLevel < 2) {
+                            matchLevel = 2;
+                            missException = new MissingFactoryMethodException("Static factory method has signature " +
+                                    "public static " + typeClass.getName() + "." + factoryMethod + toParameterList(method.getParameterTypes()) +
+                                    " but expected signature " +
+                                    "public static " + typeClass.getName() + "." + factoryMethod + toParameterList(constructorArgTypes));
+                        }
+                        continue;
+                    }
+                } else {
+                    if (method.getParameterTypes().length != 0) {
+                        if (matchLevel < 1) {
+                            matchLevel = 1;
+                            missException = new MissingFactoryMethodException("Instance factory method has parameters: " + method);
+                        }
+                        continue;
+                    }
+                }
+
+                if (method.getReturnType() == Void.TYPE) {
+                    if (matchLevel < 3) {
+                        matchLevel = 3;
+                        missException = new MissingFactoryMethodException("Factory method does not return a value: " + method);
+                    }
+                    continue;
+                }
+
+                if (Modifier.isAbstract(method.getModifiers())) {
+                    if (matchLevel < 4) {
+                        matchLevel = 4;
+                        missException = new MissingFactoryMethodException("Factory method is abstract: " + method);
+                    }
+                    continue;
+                }
+
+                if (!Modifier.isPublic(method.getModifiers())) {
+                    if (matchLevel < 5) {
+                        matchLevel = 5;
+                        missException = new MissingFactoryMethodException("Factory method is not public: " + method);
+                    }
+                    continue;
+                }
+
+                return method;
+            }
+        }
+
+        if (missException != null) {
+            throw missException;
+        } else {
+            StringBuffer buffer = new StringBuffer("Unable to find a valid factory method: ");
+            buffer.append("public void ").append(typeClass.getName()).append(".");
+            buffer.append(factoryMethod).append("()");
+            throw new MissingFactoryMethodException(buffer.toString());
+        }
+    }
+
+    public static Method findSetter(Class typeClass, String propertyName, Object propertyValue, boolean allowPrivate, ClassLoader classLoader) {
         if (propertyName == null) throw new NullPointerException("name is null");
         if (propertyName.length() == 0) throw new IllegalArgumentException("name is an empty string");
 
@@ -515,10 +561,9 @@
         int matchLevel = 0;
         MissingAccessorException missException = null;
 
-        List methods = new ArrayList(Arrays.asList(typeClass.getMethods()));
+        List<Method> methods = new ArrayList<Method>(Arrays.asList(typeClass.getMethods()));
         methods.addAll(Arrays.asList(typeClass.getDeclaredMethods()));
-        for (Iterator iterator = methods.iterator(); iterator.hasNext();) {
-            Method method = (Method) iterator.next();
+        for (Method method : methods) {
             if (method.getName().equals(setterName)) {
                 if (method.getParameterTypes().length == 0) {
                     if (matchLevel < 1) {
@@ -573,17 +618,17 @@
                     if (matchLevel < 6) {
                         matchLevel = 6;
                         missException = new MissingAccessorException("Null can not be assigned to " +
-                                Classes.getClassName(methodParameterType, true) + ": " + method, matchLevel);
+                                methodParameterType.getName() + ": " + method, matchLevel);
                     }
                     continue;
                 }
 
 
-                if (!isInstance(methodParameterType, propertyValue) && !isConvertable(methodParameterType, propertyValue)) {
+                if (!isInstance(methodParameterType, propertyValue) && !isConvertable(methodParameterType, propertyValue, classLoader)) {
                     if (matchLevel < 5) {
                         matchLevel = 5;
-                        missException = new MissingAccessorException(Classes.getClassName(propertyValue, true) + " can not be assigned or converted to " +
-                                Classes.getClassName(methodParameterType, true) + ": " + method, matchLevel);
+                        missException = new MissingAccessorException(getClassName(propertyValue) + " can not be assigned or converted to " +
+                                methodParameterType.getName() + ": " + method, matchLevel);
                     }
                     continue;
                 }
@@ -601,28 +646,27 @@
             throw missException;
         } else {
             StringBuffer buffer = new StringBuffer("Unable to find a valid setter method: ");
-            buffer.append("public void ").append(Classes.getClassName(typeClass, true)).append(".");
-            buffer.append(setterName).append("(").append(Classes.getClassName(propertyValue, true)).append(")");
+            buffer.append("public void ").append(typeClass.getName()).append(".");
+            buffer.append(setterName).append("(").append(getClassName(propertyValue)).append(")");
             throw new MissingAccessorException(buffer.toString(), -1);
         }
     }
 
-    public static Field findField(Class typeClass, String propertyName, Object propertyValue, boolean allowPrivate) {
+    public static Field findField(Class typeClass, String propertyName, Object propertyValue, boolean allowPrivate, ClassLoader classLoader) {
         if (propertyName == null) throw new NullPointerException("name is null");
         if (propertyName.length() == 0) throw new IllegalArgumentException("name is an empty string");
 
         int matchLevel = 0;
         MissingAccessorException missException = null;
 
-        List fields = new ArrayList(Arrays.asList(typeClass.getDeclaredFields()));
+        List<Field> fields = new ArrayList<Field>(Arrays.asList(typeClass.getDeclaredFields()));
         Class parent = typeClass.getSuperclass();
         while (parent != null){
             fields.addAll(Arrays.asList(parent.getDeclaredFields()));
             parent = parent.getSuperclass();
         }
 
-        for (Iterator iterator = fields.iterator(); iterator.hasNext();) {
-            Field field = (Field) iterator.next();
+        for (Field field : fields) {
             if (field.getName().equals(propertyName)) {
 
                 if (!allowPrivate && !Modifier.isPublic(field.getModifiers())) {
@@ -646,17 +690,17 @@
                     if (matchLevel < 6) {
                         matchLevel = 6;
                         missException = new MissingAccessorException("Null can not be assigned to " +
-                                Classes.getClassName(fieldType, true) + ": " + field, matchLevel);
+                                fieldType.getName() + ": " + field, matchLevel);
                     }
                     continue;
                 }
 
 
-                if (!isInstance(fieldType, propertyValue) && !isConvertable(fieldType, propertyValue)) {
+                if (!isInstance(fieldType, propertyValue) && !isConvertable(fieldType, propertyValue, classLoader)) {
                     if (matchLevel < 5) {
                         matchLevel = 5;
-                        missException = new MissingAccessorException(Classes.getClassName(propertyValue, true) + " can not be assigned or converted to " +
-                                Classes.getClassName(fieldType, true) + ": " + field, matchLevel);
+                        missException = new MissingAccessorException(getClassName(propertyValue) + " can not be assigned or converted to " +
+                                fieldType.getName() + ": " + field, matchLevel);
                     }
                     continue;
                 }
@@ -674,14 +718,18 @@
             throw missException;
         } else {
             StringBuffer buffer = new StringBuffer("Unable to find a valid field: ");
-            buffer.append("public ").append(" ").append(Classes.getClassName(propertyValue, true));
+            buffer.append("public ").append(" ").append(getClassName(propertyValue));
             buffer.append(" ").append(propertyName).append(";");
             throw new MissingAccessorException(buffer.toString(), -1);
         }
     }
 
-    public static boolean isConvertable(Class methodParameterType, Object propertyValue) {
-        return (propertyValue instanceof String && PropertyEditors.canConvert(methodParameterType));
+    public static boolean isConvertable(Class type, Object propertyValue, ClassLoader classLoader) {
+        if (propertyValue instanceof Recipe) {
+            Recipe recipe = (Recipe) propertyValue;
+            return recipe.canCreate(type, classLoader);
+        }
+        return (propertyValue instanceof String && PropertyEditors.canConvert(type));
     }
 
     public static boolean isInstance(Class type, Object instance) {
@@ -750,7 +798,7 @@
         for (int i = 0; i < expectedTypes.length; i++) {
             Class expectedType = expectedTypes[i];
             Class actualType = actualTypes[i];
-            if (!isAssignableFrom(expectedType, actualType)) {
+            if (expectedType != actualType && !isAssignableFrom(expectedType, actualType)) {
                 return false;
             }
         }
@@ -758,7 +806,7 @@
     }
 
     private static void setAccessible(final Method method) {
-        AccessController.doPrivileged(new PrivilegedAction() {
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
             public Object run() {
                 method.setAccessible(true);
                 return null;
@@ -767,7 +815,7 @@
     }
 
     private static void setAccessible(final Field field) {
-        AccessController.doPrivileged(new PrivilegedAction() {
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
             public Object run() {
                 field.setAccessible(true);
                 return null;
@@ -792,7 +840,7 @@
         }
 
         public void setValue(Object instance, Object value) throws Exception {
-            setter.invoke(instance, new Object[]{value});
+            setter.invoke(instance, value);
         }
 
         public String toString() {

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/Recipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/Recipe.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/Recipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/Recipe.java Mon Feb 26 14:01:25 2007
@@ -22,5 +22,10 @@
  * @version $Rev: 6680 $ $Date: 2005-12-24T04:38:27.427468Z $
  */
 public interface Recipe extends Serializable {
+    float getPriority();
+
+    boolean canCreate(Class type, ClassLoader classLoader);
+
+    Object create() throws ConstructionException;
     Object create(ClassLoader classLoader) throws ConstructionException;
 }

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/RecipeHelper.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/RecipeHelper.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/RecipeHelper.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/RecipeHelper.java Mon Feb 26 14:01:25 2007
@@ -18,6 +18,11 @@
 
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Constructor;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.List;
+import java.util.Collections;
+import java.util.ArrayList;
 
 /**
  * @version $Rev: 6687 $ $Date: 2005-12-28T21:08:56.733437Z $
@@ -54,5 +59,26 @@
                 o instanceof String ||
                 o instanceof Recipe;
 
+    }
+
+    public static <K,V> List<Map.Entry<K,V>> prioritizeProperties(Map<K,V> properties) {
+        ArrayList<Map.Entry<K,V>> entries = new ArrayList<Map.Entry<K,V>>(properties.entrySet());
+        Collections.sort(entries, new RecipeComparator());
+        return entries;
+    }
+
+    public static class RecipeComparator implements Comparator<Object> {
+        public int compare(Object left, Object right) {
+            if (!(left instanceof Recipe) && !(right instanceof Recipe)) return 0;
+            if (left instanceof Recipe && !(right instanceof Recipe)) return 1;
+            if (!(left instanceof Recipe) && right instanceof Recipe) return -1;
+
+            float leftPriority = ((Recipe) left).getPriority();
+            float rightPriority = ((Recipe) right).getPriority();
+
+            if (leftPriority > rightPriority) return 1;
+            if (leftPriority < rightPriority) return -1;
+            return 0;
+        }
     }
 }

Added: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/SecretRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/SecretRecipe.java?view=auto&rev=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/SecretRecipe.java (added)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/SecretRecipe.java Mon Feb 26 14:01:25 2007
@@ -0,0 +1,22 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.recipe;
+
+public interface SecretRecipe extends Recipe {
+    Object create(Recipe outerRecipe, ClassLoader classLoader) throws ConstructionException;
+}

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/StaticRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/StaticRecipe.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/StaticRecipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/StaticRecipe.java Mon Feb 26 14:01:25 2007
@@ -19,12 +19,15 @@
 /**
  * @version $Rev$ $Date$
  */
-public class StaticRecipe implements Recipe {
-
+public class StaticRecipe extends AbstractRecipe {
     private final Object object;
 
     public StaticRecipe(Object object) {
         this.object = object;
+    }
+
+    public boolean canCreate(Class type, ClassLoader classLoader) {
+        return object == null || type.isAssignableFrom(object.getClass());
     }
 
     public Object create(ClassLoader classLoader) throws ConstructionException {

Added: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/UnsetPropertiesRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/UnsetPropertiesRecipe.java?view=auto&rev=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/UnsetPropertiesRecipe.java (added)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/UnsetPropertiesRecipe.java Mon Feb 26 14:01:25 2007
@@ -0,0 +1,46 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.recipe;
+
+import java.util.Map;
+import java.util.Properties;
+
+public class UnsetPropertiesRecipe extends AbstractSecretRecipe {
+    public float getPriority() {
+        return 100;
+    }
+
+    public boolean canCreate(Class type, ClassLoader classLoader) {
+        return type.isAssignableFrom(Properties.class);
+    }
+
+    public Object create(Recipe outerRecipe, ClassLoader classLoader) throws ConstructionException {
+        if (!(outerRecipe instanceof ObjectRecipe)) {
+            throw new ConstructionException("UnsetPropertiesRecipe can only be nested in an ObjectRecipe: outerRecipe=" + outerRecipe);
+        }
+        ObjectRecipe objectRecipe = (ObjectRecipe) outerRecipe;
+        Map<String,Object> unsetProperties = objectRecipe.getUnsetProperties();
+
+        // copy to a properties object
+        Properties properties = new Properties();
+        for (Map.Entry<String, Object> entry : unsetProperties.entrySet()) {
+            properties.put(entry.getKey(), entry.getValue());
+        }
+        return properties;
+    }
+}

Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ValueRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ValueRecipe.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ValueRecipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ValueRecipe.java Mon Feb 26 14:01:25 2007
@@ -18,20 +18,19 @@
 
 import org.apache.xbean.propertyeditor.PropertyEditors;
 import org.apache.xbean.propertyeditor.PropertyEditorException;
-import org.apache.xbean.Classes;
 
 
 /**
  * @version $Rev: 6689 $ $Date: 2006-01-02T06:48:49.815187Z $
  */
-public class ValueRecipe implements Recipe {
+public class ValueRecipe extends AbstractRecipe {
     private final String type;
     private final String value;
 
     public ValueRecipe(Class type, String value) {
         if (type == null) throw new NullPointerException("type is null");
         if (!PropertyEditors.canConvert(type)) {
-            throw new IllegalArgumentException("No converter available for " + Classes.getClassName(type));
+            throw new IllegalArgumentException("No converter available for " + type.getSimpleName());
         }
         this.type = type.getName();
         this.value = value;
@@ -53,6 +52,15 @@
         if (valueRecipe == null) throw new NullPointerException("valueRecipe is null");
         this.type = valueRecipe.type;
         this.value = valueRecipe.value;
+    }
+
+    public boolean canCreate(Class type, ClassLoader classLoader) {
+        try {
+            Class myType = Class.forName(this.type, true, classLoader);
+            return type.isAssignableFrom(myType);
+        } catch (ClassNotFoundException e) {
+            throw new ConstructionException("Type class could not be found: " + type);
+        }
     }
 
     public String getType() {

Modified: geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/ObjectRecipeTest.java Mon Feb 26 14:01:25 2007
@@ -49,21 +49,39 @@
         doTest(objectRecipe);
     }
 
-    public void testFactoryMethodAndSetters() throws Exception {
+    public void testStaticFactoryMethodAndSetters() throws Exception {
 
         ObjectRecipe objectRecipe = new ObjectRecipe(Person.class, "newInstance");
         doTest(objectRecipe);
     }
 
-    public void testFactoryMethodWithParams() throws Exception {
+    public void testStaticFactoryMethodWithParams() throws Exception {
 
         ObjectRecipe objectRecipe = new ObjectRecipe(Person.class, "newInstance", new String[]{"name", "age", "homePage"}, new Class[]{String.class, Integer.TYPE, URL.class});
         doTest(objectRecipe);
     }
 
-    public void testFactoryMethodWithImpliedTypes() throws Exception {
+    public void testStaticFactoryMethodWithImpliedTypes() throws Exception {
 
         ObjectRecipe objectRecipe = new ObjectRecipe(Person.class, "newInstance", new String[]{"name", "age", "homePage"}, null);
+        doTest(objectRecipe);
+    }
+
+    public void testInstanceFactorySetters() throws Exception {
+
+        ObjectRecipe objectRecipe = new ObjectRecipe(PersonFactory.class, "create");
+        doTest(objectRecipe);
+    }
+
+    public void testInstanceFactoryConstructor() throws Exception {
+
+        ObjectRecipe objectRecipe = new ObjectRecipe(PersonFactory.class, "create", new String[]{"name", "age", "homePage"}, new Class[]{String.class, Integer.TYPE, URL.class});
+        doTest(objectRecipe);
+    }
+
+    public void testInstanceFactoryConstructorWithImpliedTypes() throws Exception {
+
+        ObjectRecipe objectRecipe = new ObjectRecipe(PersonFactory.class, "create", new String[]{"name", "age", "homePage"}, null);
         doTest(objectRecipe);
     }
 

Modified: geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/Person.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/Person.java?view=diff&rev=512030&r1=512029&r2=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/Person.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/Person.java Mon Feb 26 14:01:25 2007
@@ -17,15 +17,19 @@
 package org.apache.xbean.recipe;
 
 import java.net.URL;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Properties;
 
 /**
  * @version $Rev$ $Date$
  */
 public class Person {
-
     private String name;
     private int age;
     private URL homePage;
+    private Map<String,Object> unsetMap;
+    private Properties unsetProperties;
 
     public Person() {
     }
@@ -68,15 +72,48 @@
         this.homePage = homePage;
     }
 
+    public Map<String, Object> getUnsetMap() {
+        return unsetMap;
+    }
+
+    public void setUnsetMap(Map<String, Object> unsetMap) {
+        this.unsetMap = new HashMap<String, Object>(unsetMap);
+    }
+
+    public Properties getUnsetProperties() {
+        return unsetProperties;
+    }
+
+    public void setUnsetProperties(Properties unsetProperties) {
+        this.unsetProperties = unsetProperties;
+    }
+
     public String toString() {
         return super.toString() + " (name=\"" + name + "\", age=\"" + age + "\", homePage=\"" + homePage + "\")";
     }
 
-    public boolean equals(Object obj) {
-        if (obj instanceof Person) {
-            Person that = (Person) obj;
-            return this.name.equals(that.name) && this.age == that.age && this.homePage.equals(that.homePage);
-        }
-        return false;
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Person person = (Person) o;
+
+        if (age != person.age) return false;
+        if (homePage != null ? !homePage.equals(person.homePage) : person.homePage != null) return false;
+        if (name != null ? !name.equals(person.name) : person.name != null) return false;
+        if (unsetMap != null ? !unsetMap.equals(person.unsetMap) : person.unsetMap != null) return false;
+        if (unsetProperties != null ? !unsetProperties.equals(person.unsetProperties) : person.unsetProperties != null) return false;
+
+        return true;
+    }
+
+    public int hashCode() {
+        int result;
+        result = (name != null ? name.hashCode() : 0);
+        result = 31 * result + age;
+        result = 31 * result + (homePage != null ? homePage.hashCode() : 0);
+        result = 31 * result + (unsetMap != null ? unsetMap.hashCode() : 0);
+        result = 31 * result + (unsetProperties != null ? unsetProperties.hashCode() : 0);
+        return result;
     }
 }

Added: geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/PersonFactory.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/PersonFactory.java?view=auto&rev=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/PersonFactory.java (added)
+++ geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/PersonFactory.java Mon Feb 26 14:01:25 2007
@@ -0,0 +1,63 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.recipe;
+
+import java.net.URL;
+
+public class PersonFactory {
+    private String name;
+    private int age;
+    private URL homePage;
+
+    public PersonFactory() {
+    }
+
+    public PersonFactory(String name, int age, URL homePage) {
+        this.name = name;
+        this.age = age;
+        this.homePage = homePage;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    public URL getHomePage() {
+        return homePage;
+    }
+
+    public void setHomePage(URL homePage) {
+        this.homePage = homePage;
+    }
+
+    public Person create() {
+        return new Person(name, age, homePage);
+    }
+}

Added: geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/UnsetPropertiesTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/UnsetPropertiesTest.java?view=auto&rev=512030
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/UnsetPropertiesTest.java (added)
+++ geronimo/xbean/trunk/xbean-reflect/src/test/java/org/apache/xbean/recipe/UnsetPropertiesTest.java Mon Feb 26 14:01:25 2007
@@ -0,0 +1,49 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.recipe;
+
+import junit.framework.TestCase;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.Properties;
+
+public class UnsetPropertiesTest extends TestCase {
+    public void testSetters() throws Exception {
+        ObjectRecipe objectRecipe = new ObjectRecipe(Person.class);
+        doTest(objectRecipe);
+    }
+
+    private void doTest(ObjectRecipe objectRecipe) throws Exception {
+        Person expected = new Person("Joe", 21, new URL("http://www.acme.org"));
+        expected.setUnsetMap(Collections.<String,Object>singletonMap("Fake Property", "Fake Value"));
+        Properties properties = new Properties();
+        properties.setProperty("Fake Property", "Fake Value");
+        expected.setUnsetProperties(properties);
+
+        objectRecipe.setProperty("name", "Joe");
+        objectRecipe.setProperty("age", "21");
+        objectRecipe.setProperty("homePage", "http://www.acme.org");
+        objectRecipe.setProperty("Fake Property", "Fake Value");
+        objectRecipe.setProperty("unsetMap", new UnsetPropertiesRecipe());
+        objectRecipe.setProperty("unsetProperties", new UnsetPropertiesRecipe());
+
+        Person actual = (Person) objectRecipe.create(Person.class.getClassLoader());
+        assertEquals("person", expected, actual);
+    }
+}



Mime
View raw message