Commits

Anonymous committed a8cf58f

Comments (0)

Files changed (47)

src/java/com/opensymphony/xwork2/XWorkTestCase.java

 import junit.framework.TestCase;
 
 import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationException;
 import com.opensymphony.xwork2.config.ConfigurationManager;
 import com.opensymphony.xwork2.config.ConfigurationProvider;
 import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
 import com.opensymphony.xwork2.config.impl.MockConfiguration;
 import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
 import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
+import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
 import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.ContainerBuilder;
+import com.opensymphony.xwork2.inject.Context;
+import com.opensymphony.xwork2.inject.Factory;
+import com.opensymphony.xwork2.inject.Scope;
+import com.opensymphony.xwork2.mock.MockObjectTypeDeterminer;
+import com.opensymphony.xwork2.util.Cat;
 import com.opensymphony.xwork2.util.XWorkTestCaseHelper;
+import com.opensymphony.xwork2.util.location.LocatableProperties;
 
 
 /**
     
     protected void setUp() throws Exception {
         configurationManager = XWorkTestCaseHelper.setUp();
-        configuration = new MockConfiguration();
+        configuration = configurationManager.getConfiguration();
         container = configuration.getContainer();
         actionProxyFactory = container.getInstance(ActionProxyFactory.class);
     }
         actionProxyFactory = container.getInstance(ActionProxyFactory.class);
     }
     
-    protected void loadWithOverriding(ConfigurationProvider... providers) {
-        XWorkConfigurationProvider def = new XWorkConfigurationProvider();
-        ConfigurationProvider[] sum = new ConfigurationProvider[providers.length + 1];
-        System.arraycopy(providers, 0, sum, 0, providers.length);
-        sum[providers.length] = def;
-        
-        loadConfigurationProviders(sum);
+    protected void loadButAdd(final Class<?> type, final Object impl) {
+        loadConfigurationProviders(new StubConfigurationProvider() {
+            public void register(ContainerBuilder builder,
+                    LocatableProperties props) throws ConfigurationException {
+                builder.factory(type, new Factory() {
+                    public Object create(Context context) throws Exception {
+                        return impl;
+                    }
+                    
+                }, Scope.SINGLETON);
+            }
+        });
     }
     
-    
-    
-    
 }

src/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java

 import com.opensymphony.xwork2.config.providers.InterceptorBuilder;
 import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
 import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
+import com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter;
 import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.ContainerBuilder;
 import com.opensymphony.xwork2.inject.Context;
 import com.opensymphony.xwork2.inject.Factory;
+import com.opensymphony.xwork2.inject.Scope;
 import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
 import com.opensymphony.xwork2.ognl.OgnlUtil;
 import com.opensymphony.xwork2.ognl.OgnlValueStackFactory;
 
     protected Container createBootstrapContainer() {
         ContainerBuilder builder = new ContainerBuilder();
-        builder.factory(ObjectFactory.class);
-        builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class);
-        builder.factory(ValueStackFactory.class, OgnlValueStackFactory.class);
-        builder.factory(XWorkConverter.class);
-        builder.factory(TextProvider.class, DefaultTextProvider.class);
-        builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class);
-        builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class);
-        builder.factory(OgnlUtil.class);
+        builder.factory(ObjectFactory.class, Scope.SINGLETON);
+        builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON);
+        builder.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON);
+        builder.factory(XWorkConverter.class, Scope.SINGLETON);
+        builder.factory(XWorkBasicConverter.class, Scope.SINGLETON);
+        builder.factory(TextProvider.class, DefaultTextProvider.class, Scope.SINGLETON);
+        builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON);
+        builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON);
+        builder.factory(OgnlUtil.class, Scope.SINGLETON);
         builder.constant("devMode", "false");
         return builder.create(true);
     }

src/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java

 package com.opensymphony.xwork2.config.providers;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
                .factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON)
                .factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON)
                .factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAcccessor.class, Scope.SINGLETON)
+               
+               // silly workarounds for ognl since there is no way to flush its caches
                .factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
+               .factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
+               .factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
+               .factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
+               .factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
                .factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
+               
                .factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
-               .factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
                .factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON)
                .factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON)
                .factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON)

src/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java

                                     if (throwExceptionOnDuplicateBeans) {
                                         throw new ConfigurationException("Bean type " + ctype + " with the name " +
                                                 name + " has already been loaded by " + loc, child);
-                                    } else {
-                                        continue;
-                                    }
+                                    } 
                                 }
 
                                 // Force loading of class to detect no class def found exceptions

src/java/com/opensymphony/xwork2/conversion/impl/DefaultObjectTypeDeterminer.java

     private XWorkConverter xworkConverter;
     
     @Inject
-    public DefaultObjectTypeDeterminer(@Inject XWorkConverter conv, @Inject XWorkBasicConverter basicConv,
-                                       @Inject ReflectionProvider prov) {
+    public DefaultObjectTypeDeterminer(@Inject XWorkConverter conv, @Inject ReflectionProvider prov) {
         this.reflectionProvider = prov;
         this.xworkConverter = conv;
         
-        // HACK: this is to get around a dumb circular dependency
-        basicConv.setObjectTypeDeterminer(this);
-        this.xworkConverter.setDefaultTypeConverter(basicConv);
     }
     
     /**

src/java/com/opensymphony/xwork2/conversion/impl/GenericsObjectTypeDeterminer.java

 
     public GenericsObjectTypeDeterminer(XWorkConverter conv,
             XWorkBasicConverter basicConv, ReflectionProvider prov) {
-        super(conv, basicConv, prov);
+        super(conv, prov);
     }
 }

src/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverter.java

 import java.util.TreeSet;
 
 import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ObjectFactory;
 import com.opensymphony.xwork2.XWorkException;
 import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
 import com.opensymphony.xwork2.conversion.TypeConverter;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.util.TextUtils;
+import com.opensymphony.xwork2.util.XWorkList;
 
 
 /**
     private static String MILLISECOND_FORMAT = ".SSS";
     
     private ObjectTypeDeterminer objectTypeDeterminer;
+    private XWorkConverter xworkConverter;
+    private ObjectFactory objectFactory;
     
+    @Inject
     public void setObjectTypeDeterminer(ObjectTypeDeterminer det) {
         this.objectTypeDeterminer = det;
     }
+    
+    @Inject
+    public void setXWorkConverter(XWorkConverter conv) {
+        this.xworkConverter = conv;
+    }
+    
+    @Inject
+    public void setObjectFactory(ObjectFactory fac) {
+        this.objectFactory = fac;
+    }
 
     public Object convertValue(Map context, Object o, Member member, String s, Object value, Class toType) {
         Object result = null;
             result = new TreeSet();
         } else {
             if (size > 0) {
-                result = new ArrayList(size);
+                result = new XWorkList(objectFactory, xworkConverter, memberType, size);
             } else {
-                result = new ArrayList();
+                result = new XWorkList(objectFactory, xworkConverter, memberType);
             }
         }
 

src/java/com/opensymphony/xwork2/conversion/impl/XWorkConverter.java

         this.objectFactory = factory;
     }
     
-    // HACK: Will actually be set by default object type determiner to get around the circular dep
-    public void setDefaultTypeConverter(TypeConverter conv) {
+    @Inject
+    public void setDefaultTypeConverter(XWorkBasicConverter conv) {
         this.defaultTypeConverter = conv;
     }
     

src/java/com/opensymphony/xwork2/mock/MockObjectTypeDeterminer.java

  */
 package com.opensymphony.xwork2.mock;
 
+import java.util.Map;
+
+import ognl.OgnlException;
+import ognl.OgnlRuntime;
+
 import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
 
 /**
 
     public boolean shouldCreateIfNew(Class parentClass, String property,
                                      Object target, String keyProperty, boolean isIndexAccessed) {
+        try {
+            System.out.println("ognl:"+OgnlRuntime.getPropertyAccessor(Map.class)+" this:"+this);
+        } catch (OgnlException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
         return isShouldCreateIfNew();
     }
 

src/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java

 import ognl.Ognl;
 import ognl.OgnlContext;
 import ognl.OgnlException;
+import ognl.PropertyAccessor;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.TextProvider;
 import com.opensymphony.xwork2.XWorkException;
 import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
 import com.opensymphony.xwork2.util.CompoundRoot;
 	
     private static Log LOG = LogFactory.getLog(OgnlValueStack.class);
     private boolean devMode;
-    private boolean allowStaticMethodAccess = true;
-
-    /**
-     * @depreated Since 2.1
-     */
-    public static void reset() {
-        // create a new OgnlValueStackFactory instead
-    }
 
     public static void link(Map context, Class clazz, String name) {
         context.put("__link", new Object[]{clazz, name});
     transient Map context;
     Class defaultType;
     Map overrides;
-    OgnlUtil ognlUtil;
+    transient OgnlUtil ognlUtil;
     
-    protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov) {
-        setRoot(xworkConverter, accessor, new CompoundRoot());
+    protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticAccess) {
+        setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticAccess);
         push(prov);
     }
 
 
-    protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor) {
-        setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()));
+    protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticAccess) {
+        setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticAccess);
     }
     
     @Inject
     public void setOgnlUtil(OgnlUtil ognlUtil) {
         this.ognlUtil = ognlUtil;
     }
-
+    
     protected void setRoot(XWorkConverter xworkConverter,
-            CompoundRootAccessor accessor, CompoundRoot compoundRoot) {
+            CompoundRootAccessor accessor, CompoundRoot compoundRoot, boolean allowStaticMethodAccess) {
         this.root = compoundRoot;
         this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter),
                 new StaticMemberAccess(allowStaticMethodAccess));
         devMode = "true".equalsIgnoreCase(mode);
     }
 
-    @Inject(value="allowStaticMethodAccess", required=false)
-    public void setAllowStaticMethodAccess(String allowStaticMethodAccess) {
-        this.allowStaticMethodAccess = "true".equalsIgnoreCase(allowStaticMethodAccess);
-    }
-
     /* (non-Javadoc)
      * @see com.opensymphony.xwork2.util.ValueStack#getContext()
      */
     public int size() {
         return root.size();
     }
+    
+    private Object readResolve() {
+        // TODO: this should be done better
+        ActionContext ac = ActionContext.getContext();
+        Container cont = ac.getContainer();
+        XWorkConverter xworkConverter = cont.getInstance(XWorkConverter.class);
+        CompoundRootAccessor accessor = (CompoundRootAccessor) cont.getInstance(PropertyAccessor.class, CompoundRoot.class.getName());
+        TextProvider prov = cont.getInstance(TextProvider.class);
+        boolean allow = "true".equals(cont.getInstance(String.class, "allowStaticMethodAccess"));
+        OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allow);
+        aStack.setOgnlUtil(cont.getInstance(OgnlUtil.class));
+        aStack.setRoot(xworkConverter, accessor, this.root, allow);
+
+        return aStack;
+    }
+
  
 }

src/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java

     private CompoundRootAccessor compoundRootAccessor;
     private TextProvider textProvider;
     private Container container;
+    private boolean allowStaticMethodAccess;
 
     @Inject
     public void setXWorkConverter(XWorkConverter conv) {
     public void setTextProvider(TextProvider textProvider) {
         this.textProvider = textProvider;
     }
+    
+    @Inject(value="allowStaticMethodAccess", required=false)
+    public void setAllowStaticMethodAccess(String allowStaticMethodAccess) {
+        this.allowStaticMethodAccess = "true".equalsIgnoreCase(allowStaticMethodAccess);
+    }
 
     public ValueStack createValueStack() {
-        ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider);
+        ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, allowStaticMethodAccess);
         container.inject(stack);
         return stack;
     }
 
     public ValueStack createValueStack(ValueStack stack) {
-        ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor);
+        ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor, allowStaticMethodAccess);
         container.inject(result);
         return result;
     }
             for (String name : names) {
                 Class cls = Class.forName(name);
                 if (cls != null) {
+                    if (Map.class.isAssignableFrom(cls)) {
+                        PropertyAccessor acc = container.getInstance(PropertyAccessor.class, name);
+                    }
                     OgnlRuntime.setPropertyAccessor(cls, container.getInstance(PropertyAccessor.class, name));
                     if (compoundRootAccessor == null && CompoundRoot.class.isAssignableFrom(cls)) {
                         compoundRootAccessor = (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, name);

src/java/com/opensymphony/xwork2/ognl/accessor/XWorkListPropertyAccessor.java

 
 import ognl.ListPropertyAccessor;
 import ognl.OgnlException;
+import ognl.PropertyAccessor;
 
 import java.util.Collection;
 import java.util.List;
     private ObjectTypeDeterminer objectTypeDeterminer;
     private OgnlUtil ognlUtil;
     
+    @Inject("java.util.Collection")
+    public void setXWorkCollectionPropertyAccessor(PropertyAccessor acc) {
+        this._sAcc = (XWorkCollectionPropertyAccessor) acc;
+    }
+    
     @Inject
     public void setXWorkConverter(XWorkConverter conv) {
         this.xworkConverter = conv;

src/java/com/opensymphony/xwork2/util/XWorkList.java

+/*
+ * Copyright (c) 2002-2006 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2.util;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.XWorkException;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+
+/**
+ * A simple list that guarantees that inserting and retrieving objects will always work regardless
+ * of the current size of the list.  Upon insertion, type conversion is also performed if necessary.
+ * Empty beans will be created to fill the gap between the current list size and the requested index
+ * using ObjectFactory's {@link ObjectFactory#buildBean(Class,java.util.Map) buildBean} method.
+ *
+ * @author Patrick Lightbody
+ */
+public class XWorkList extends ArrayList {
+    private static final Log LOG = LogFactory.getLog(XWorkConverter.class);
+
+    private Class clazz;
+    private XWorkConverter conv;
+
+    private ObjectFactory objectFactory;
+
+    public XWorkList(ObjectFactory fac, XWorkConverter conv, Class clazz) {
+        this.conv = conv;
+        this.clazz = clazz;
+        this.objectFactory = fac;
+    }
+
+    public XWorkList(ObjectFactory fac, XWorkConverter conv, Class clazz, int initialCapacity) {
+        super(initialCapacity);
+        this.clazz = clazz;
+        this.conv = conv;
+        this.objectFactory = fac;
+    }
+
+    /**
+     * Inserts the specified element at the specified position in this list. Shifts the element
+     * currently at that position (if any) and any subsequent elements to the right (adds one to
+     * their indices).
+     * <p/>
+     * This method is guaranteed to work since it will create empty beans to fill the gap between
+     * the current list size and the requested index to enable the element to be set.  This method
+     * also performs any necessary type conversion.
+     *
+     * @param index   index at which the specified element is to be inserted.
+     * @param element element to be inserted.
+     */
+    public void add(int index, Object element) {
+        if (index >= this.size()) {
+            get(index);
+        }
+
+        element = convert(element);
+
+        super.add(index, element);
+    }
+
+    /**
+     * Appends the specified element to the end of this list.
+     * <p/>
+     * This method performs any necessary type conversion.
+     *
+     * @param element element to be appended to this list.
+     * @return <tt>true</tt> (as per the general contract of Collection.add).
+     */
+    public boolean add(Object element) {
+        element = convert(element);
+
+        return super.add(element);
+    }
+
+    /**
+     * Appends all of the elements in the specified Collection to the end of this list, in the order
+     * that they are returned by the specified Collection's Iterator.  The behavior of this
+     * operation is undefined if the specified Collection is modified while the operation is in
+     * progress.  (This implies that the behavior of this call is undefined if the specified
+     * Collection is this list, and this list is nonempty.)
+     * <p/>
+     * This method performs any necessary type conversion.
+     *
+     * @param c the elements to be inserted into this list.
+     * @return <tt>true</tt> if this list changed as a result of the call.
+     * @throws NullPointerException if the specified collection is null.
+     */
+    public boolean addAll(Collection c) {
+        if (c == null) {
+            throw new NullPointerException("Collection to add is null");
+        }
+
+        Iterator it = c.iterator();
+
+        while (it.hasNext()) {
+            add(it.next());
+        }
+
+        return true;
+    }
+
+    /**
+     * Inserts all of the elements in the specified Collection into this list, starting at the
+     * specified position.  Shifts the element currently at that position (if any) and any
+     * subsequent elements to the right (increases their indices).  The new elements will appear in
+     * the list in the order that they are returned by the specified Collection's iterator.
+     * <p/>
+     * This method is guaranteed to work since it will create empty beans to fill the gap between
+     * the current list size and the requested index to enable the element to be set.  This method
+     * also performs any necessary type conversion.
+     *
+     * @param index index at which to insert first element from the specified collection.
+     * @param c     elements to be inserted into this list.
+     * @return <tt>true</tt> if this list changed as a result of the call.
+     */
+    public boolean addAll(int index, Collection c) {
+        if (c == null) {
+            throw new NullPointerException("Collection to add is null");
+        }
+
+        boolean trim = false;
+
+        if (index >= this.size()) {
+            trim = true;
+        }
+
+        for (Iterator it = c.iterator(); it.hasNext(); index++) {
+            add(index, it.next());
+        }
+
+        if (trim) {
+            remove(this.size() - 1);
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns the element at the specified position in this list.
+     * <p/>
+     * An object is guaranteed to be returned since it will create empty beans to fill the gap
+     * between the current list size and the requested index.
+     *
+     * @param index index of element to return.
+     * @return the element at the specified position in this list.
+     */
+    public synchronized Object get(int index) {
+        while (index >= this.size()) {
+            try {
+                //todo
+                this.add(objectFactory.buildBean(clazz, null)); //ActionContext.getContext().getContextMap()));
+            } catch (Exception e) {
+                throw new XWorkException(e);
+            }
+        }
+
+        return super.get(index);
+    }
+
+    /**
+     * Replaces the element at the specified position in this list with the specified element.
+     * <p/>
+     * This method is guaranteed to work since it will create empty beans to fill the gap between
+     * the current list size and the requested index to enable the element to be set.  This method
+     * also performs any necessary type conversion.
+     *
+     * @param index   index of element to replace.
+     * @param element element to be stored at the specified position.
+     * @return the element previously at the specified position.
+     */
+    public Object set(int index, Object element) {
+        if (index >= this.size()) {
+            get(index);
+        }
+
+        element = convert(element);
+
+        return super.set(index, element);
+    }
+
+    private Object convert(Object element) {
+        if ((element != null) && !clazz.isAssignableFrom(element.getClass())) {
+            // convert to correct type
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Converting from " + element.getClass().getName() + " to " + clazz.getName());
+            }
+
+            Map context = ActionContext.getContext().getContextMap();
+            element = conv.convertValue(context, null, null, null, element, clazz);
+        }
+
+        return element;
+    }
+
+    public boolean contains(Object element) {
+        element = convert(element);
+
+        return super.contains(element);
+    }
+}

src/java/com/opensymphony/xwork2/util/XWorkTestCaseHelper.java

 
     public static ConfigurationManager loadConfigurationProviders(ConfigurationManager configurationManager,
             ConfigurationProvider... providers) {
-        if (configurationManager != null) {
-            configurationManager.clearConfigurationProviders();
-        } else {
-            configurationManager = new ConfigurationManager();
+        try {
+            tearDown(configurationManager);
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot clean old configuration", e);
         }
-        configurationManager.clearConfigurationProviders();
+        configurationManager = new ConfigurationManager();
         configurationManager.addConfigurationProvider(new ConfigurationProvider() {
             public void destroy() {}
             public void init(Configuration configuration) throws ConfigurationException {}
             }
             configurationManager.addConfigurationProvider(prov);
         }
-        configurationManager.getConfiguration().reload(
-                configurationManager.getConfigurationProviders());
         Container container = configurationManager.getConfiguration().getContainer();
         
         // Reset the value stack

src/java/com/opensymphony/xwork2/util/reflection/ReflectionContextState.java

 
 
     public static void clear(Map context) {
-        context.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED,null);
-        context.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED,null);
-
-        context.put(CURRENT_PROPERTY_PATH,null);
-        context.put(FULL_PROPERTY_PATH,null);
+        if (context != null) {
+            context.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED,null);
+            context.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED,null);
+    
+            context.put(CURRENT_PROPERTY_PATH,null);
+            context.put(FULL_PROPERTY_PATH,null);
+        }
 
     }
 

src/java/com/opensymphony/xwork2/validator/ValidationInterceptor.java

     
     private ActionValidatorManager actionValidatorManager;
     
-    @Inject
-    public void setActionValidatorManager(ActionValidatorManager mgr) {
-        this.actionValidatorManager = mgr;
-    }
-
     private static final Log _log = LogFactory.getLog(DefaultWorkflowInterceptor.class);
     
     private final static String VALIDATE_PREFIX = "validate";
     private boolean programmatic = true;
     private boolean declarative = true;
 
+    @Inject
+    public void setActionValidatorManager(ActionValidatorManager mgr) {
+        this.actionValidatorManager = mgr;
+    }
+    
     /**
      * Determines if {@link Validateable}'s <code>validate()</code> should be called,
      * as well as methods whose name that start with "validate". Defaults to "true".

src/test/com/opensymphony/xwork2/config/providers/MockConfigurationProvider.java

 import com.opensymphony.xwork2.config.ConfigurationException;
 import com.opensymphony.xwork2.config.ConfigurationProvider;
 import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
 import com.opensymphony.xwork2.config.entities.PackageConfig;
 import com.opensymphony.xwork2.config.entities.ResultConfig;
 import com.opensymphony.xwork2.config.entities.InterceptorMapping;
 import com.opensymphony.xwork2.inject.ContainerBuilder;
+import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor;
 import com.opensymphony.xwork2.interceptor.ParametersInterceptor;
 import com.opensymphony.xwork2.interceptor.StaticParametersInterceptor;
     public static final String VALIDATION_SUBPROPERTY_NAME = "subproperty";
     private Configuration configuration;
     private Map<String,String> params;
+    private ObjectFactory objectFactory;
 
     public MockConfigurationProvider() {}
     public MockConfigurationProvider(Map<String,String> params) {
     public void init(Configuration config) {
         this.configuration = config;
     }
+    
+    @Inject
+    public void setObjectFactory(ObjectFactory fac) {
+        this.objectFactory = fac;
+    }
 
     public void loadPackages() {
         
         defaultPackageContext.addActionConfig(PARAM_INTERCEPTOR_ACTION_NAME, paramInterceptorActionConfig);
 
         interceptors = new ArrayList();
-        interceptors.add(new InterceptorMapping("model", new ModelDrivenInterceptor()));
-        interceptors.add(new InterceptorMapping("params", new ParametersInterceptor()));
+        interceptors.add(new InterceptorMapping("model", 
+                objectFactory.buildInterceptor(new InterceptorConfig("model", ModelDrivenInterceptor.class.getName(), null), new HashMap())));
+        interceptors.add(new InterceptorMapping("params",
+                objectFactory.buildInterceptor(new InterceptorConfig("model", ParametersInterceptor.class.getName(), null), new HashMap())));
 
         ActionConfig modelParamActionConfig = new ActionConfig(null, ModelDrivenAction.class, null, null, interceptors);
         modelParamActionConfig.addResultConfig(new ResultConfig(Action.SUCCESS, MockResult.class.getName()));
         results.put("success", new ResultConfig("success", ActionChainResult.class.getName(), successParams));
 
         interceptors = new ArrayList();
-        interceptors.add(new InterceptorMapping("static-params", new StaticParametersInterceptor()));
-        interceptors.add(new InterceptorMapping("model", new ModelDrivenInterceptor()));
-        interceptors.add(new InterceptorMapping("params", new ParametersInterceptor()));
-        interceptors.add(new InterceptorMapping("validation", new ValidationInterceptor()));
+        interceptors.add(new InterceptorMapping("static-params", 
+                objectFactory.buildInterceptor(new InterceptorConfig("model", StaticParametersInterceptor.class.getName(), null), new HashMap())));
+        interceptors.add(new InterceptorMapping("model", 
+                objectFactory.buildInterceptor(new InterceptorConfig("model", ModelDrivenInterceptor.class.getName(), null), new HashMap())));
+        interceptors.add(new InterceptorMapping("params", 
+                objectFactory.buildInterceptor(new InterceptorConfig("model", ParametersInterceptor.class.getName(), null), new HashMap())));
+        interceptors.add(new InterceptorMapping("validation", 
+                objectFactory.buildInterceptor(new InterceptorConfig("model", ValidationInterceptor.class.getName(), null), new HashMap())));
 
         //Explicitly set an out-of-range date for DateRangeValidatorTest
         params = new HashMap();

src/test/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor2Test.java

  */
 package com.opensymphony.xwork2.interceptor;
 
+import java.util.HashMap;
+
 import junit.framework.TestCase;
 
 import org.easymock.MockControl;
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.ActionProxy;
 import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
 import com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor;
 import com.opensymphony.xwork2.validator.ValidationInterceptor;
 
  * @author tm_jee
  * @version $Date$ $Id$
  */
-public class DefaultWorkflowInterceptor2Test extends TestCase {
+public class DefaultWorkflowInterceptor2Test extends XWorkTestCase {
 	
 	public void testDefaultResultNameIsReturnedWithBadValidation() throws Exception {
 		ValidationFailedAction action = new ValidationFailedAction();
 		actionInvocationControl.replay();
 		actionProxyControl.replay();
 		
-		ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+		ValidationInterceptor validationInterceptor = create();
 		DefaultWorkflowInterceptor interceptor = new DefaultWorkflowInterceptor();
 		try {
 		        validationInterceptor.intercept(actionInvocation);
 		actionInvocationControl.replay();
 		actionProxyControl.replay();
 		
-		ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+		ValidationInterceptor validationInterceptor = create();
 		DefaultWorkflowInterceptor interceptor = new DefaultWorkflowInterceptor();
 		try {
 		        validationInterceptor.intercept(actionInvocation);
 		actionProxyControl.verify();
 	}
 	
+	protected ValidationInterceptor create() {
+        ObjectFactory objectFactory = container.getInstance(ObjectFactory.class);
+        return (ValidationInterceptor) objectFactory.buildInterceptor(new InterceptorConfig("model", ValidationInterceptor.class.getName(), null), new HashMap());
+    }
+	
 	
 	public class ValidationFailedAction extends ActionSupport {
 		

src/test/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptorTest.java

  */
 package com.opensymphony.xwork2.interceptor;
 
+import java.util.HashMap;
+
 import com.mockobjects.dynamic.Mock;
 import com.opensymphony.xwork2.*;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
 import com.opensymphony.xwork2.mock.MockActionProxy;
 import com.opensymphony.xwork2.validator.ValidationInterceptor;
 
  *
  * @author Jason Carreira
  */
-public class DefaultWorkflowInterceptorTest extends TestCase {
+public class DefaultWorkflowInterceptorTest extends XWorkTestCase {
 
     DefaultWorkflowInterceptor interceptor;
     private ActionInvocation invocation;
         invocationMock.expectAndReturn("invoke", result);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.intercept(invocation);
         assertEquals(result, interceptor.intercept(invocation));
     }
         invocationMock.expectAndReturn("invoke", Action.INPUT);
         invocationMock.expectAndReturn("invoke", Action.INPUT);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.intercept(invocation);
         assertEquals(Action.INPUT, interceptor.intercept(invocation));
     }
         proxyMock.expectAndReturn("getMethod", "execute");        
         invocationMock.expectAndReturn("invoke", result);
                 
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setExcludeMethods("execute");
         interceptor.setExcludeMethods("execute");
         validationInterceptor.intercept(invocation);
         invocationMock.expectAndReturn("invoke", result);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.intercept(invocation);
         validationInterceptor.setExcludeMethods("*");
         assertEquals(result, interceptor.intercept(invocation));
         actionMock.expectAndReturn("hasErrors", false);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setIncludeMethods("*");
         validationInterceptor.intercept(invocation);
         
         actionMock.expectAndReturn("hasErrors", false);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setIncludeMethods("execute");
         validationInterceptor.intercept(invocation);
         
         actionMock.expectAndReturn("hasErrors", false);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setExcludeMethods("execute,input,validate");
         validationInterceptor.setIncludeMethods("execute");
         validationInterceptor.intercept(invocation);
         actionMock.expectAndReturn("hasErrors", false);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setExcludeMethods("*");
         validationInterceptor.setIncludeMethods("*");
         validationInterceptor.intercept(invocation);
         actionMock.expectAndReturn("hasErrors", false);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setExcludeMethods("*");
         validationInterceptor.setIncludeMethods("execute");
         validationInterceptor.intercept(invocation);
         proxyMock.expectAndReturn("getMethod", "execute");
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setExcludeMethods("execute,input,validate");
         validationInterceptor.setIncludeMethods("*");
         validationInterceptor.intercept(invocation);
         actionMock.expectAndReturn("hasErrors", false);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setExcludeMethods("input,validate");
         validationInterceptor.setIncludeMethods("*");
         validationInterceptor.intercept(invocation);
         invocationMock.expectAndReturn("invoke", result);
         invocationMock.expectAndReturn("invoke", result);
         
-        ValidationInterceptor validationInterceptor = new ValidationInterceptor();
+        ValidationInterceptor validationInterceptor = create();
         validationInterceptor.setExcludeMethods("execute,input,validate");
         validationInterceptor.setIncludeMethods("execute");
         validationInterceptor.intercept(invocation);
         actionMock.verify();
         invocationMock.verify();
     }
+    
+    protected ValidationInterceptor create() {
+        ObjectFactory objectFactory = container.getInstance(ObjectFactory.class);
+        return (ValidationInterceptor) objectFactory.buildInterceptor(new InterceptorConfig("model", ValidationInterceptor.class.getName(), null), new HashMap());
+    }
 
     
     

src/test/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java

         ValueStack stack = new OgnlValueStack(
                 container.getInstance(XWorkConverter.class),
                 (CompoundRootAccessor)container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
-                container.getInstance(TextProvider.class)) {
+                container.getInstance(TextProvider.class), true) {
             public void setValue(String expr, Object value) {
                 actual.put(expr, value);
             }

src/test/com/opensymphony/xwork2/interceptor/ValidationInterceptorPrefixMethodInvocationTest.java

  */
 package com.opensymphony.xwork2.interceptor;
 
+import java.util.HashMap;
+
 import org.easymock.MockControl;
 
 import com.opensymphony.xwork2.Action;
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.ObjectFactory;
 import com.opensymphony.xwork2.Validateable;
 import com.opensymphony.xwork2.ValidationAware;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
 import com.opensymphony.xwork2.validator.ValidationInterceptor;
 
 import junit.framework.TestCase;
  * @author tm_jee
  * @version $Date$ $Id$
  */
-public class ValidationInterceptorPrefixMethodInvocationTest extends TestCase {
+public class ValidationInterceptorPrefixMethodInvocationTest extends XWorkTestCase {
 
 	public void testPrefixMethodInvocation1() throws Exception {
 		
 		controlActionProxy.replay();
 		controlActionInvocation.replay();
 		
-		ValidationInterceptor interceptor = new ValidationInterceptor();
+		ValidationInterceptor interceptor = create();
 		String result = interceptor.intercept(mockActionInvocation);
 		
 		assertEquals(Action.INPUT, result);
 		controlActionProxy.replay();
 		controlActionInvocation.replay();
 		
-		ValidationInterceptor interceptor = new ValidationInterceptor();
+		ValidationInterceptor interceptor = create();
 		String result = interceptor.intercept(mockActionInvocation);
 		
 		assertEquals("okok", result);
 		controlActionInvocation.verify();
 	}
 	
+	protected ValidationInterceptor create() {
+	    ObjectFactory objectFactory = container.getInstance(ObjectFactory.class);
+	    return (ValidationInterceptor) objectFactory.buildInterceptor(new InterceptorConfig("model", ValidationInterceptor.class.getName(), null), new HashMap());
+	}
+	
 	private interface ValidateAction extends Action, Validateable, ValidationAware {
 		void validateDoSave();
 		void validateSubmit();

src/test/com/opensymphony/xwork2/ognl/OgnlValueStackTest.java

     }
     
     private OgnlValueStack createValueStack() {
+        return createValueStack(true);
+    }
+    private OgnlValueStack createValueStack(boolean allowStaticMethodAccess) {
         OgnlValueStack stack = new OgnlValueStack(
                 container.getInstance(XWorkConverter.class),
                 (CompoundRootAccessor)container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
-                container.getInstance(TextProvider.class));
+                container.getInstance(TextProvider.class), allowStaticMethodAccess);
         container.inject(stack);
         return stack;
     }
     }
     
     public void testStaticMethodDisallow() {
-        OgnlValueStack vs = createValueStack();
-        vs.setAllowStaticMethodAccess("false");
+        OgnlValueStack vs = createValueStack(false);
 
         Dog dog = new Dog();
         dog.setDeity("fido");
         
         OgnlValueStack stack2 = new OgnlValueStack(stack,
                 container.getInstance(XWorkConverter.class),
-                (CompoundRootAccessor)container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()));
+                (CompoundRootAccessor)container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), true);
         container.inject(stack2);
 
         assertEquals(stack.getRoot(), stack2.getRoot());

src/test/com/opensymphony/xwork2/ognl/SetPropertiesTest.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+/*
+ * Created on 6/10/2003
+ *
+ */
+package com.opensymphony.xwork2.ognl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import ognl.Ognl;
+import ognl.OgnlException;
+import ognl.OgnlRuntime;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.StubConfigurationProvider;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
+import com.opensymphony.xwork2.conversion.impl.FooBarConverter;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.inject.ContainerBuilder;
+import com.opensymphony.xwork2.inject.Context;
+import com.opensymphony.xwork2.inject.Factory;
+import com.opensymphony.xwork2.inject.Scope;
+import com.opensymphony.xwork2.mock.MockObjectTypeDeterminer;
+import com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor;
+import com.opensymphony.xwork2.util.Bar;
+import com.opensymphony.xwork2.util.Cat;
+import com.opensymphony.xwork2.util.Foo;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.location.LocatableProperties;
+import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
+
+
+/**
+ * @author CameronBraid and Gabe
+ * @author tm_jee
+ */
+public class SetPropertiesTest extends XWorkTestCase {
+    
+    private OgnlUtil ognlUtil;
+    
+    public void setUp() throws Exception {
+        super.setUp();
+        ognlUtil = container.getInstance(OgnlUtil.class);
+        ((OgnlValueStack)ActionContext.getContext().getValueStack()).setDevMode("true");
+    }
+    public void testOgnlUtilEmptyStringAsLong() {
+        Bar bar = new Bar();
+        Map context = Ognl.createDefaultContext(bar);
+        context.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+        bar.setId(null);
+
+        HashMap props = new HashMap();
+        props.put("id", "");
+
+        ognlUtil.setProperties(props, bar, context);
+        assertNull(bar.getId());
+        assertEquals(0, bar.getFieldErrors().size());
+
+        props.put("id", new String[]{""});
+
+        bar.setId(null);
+        ognlUtil.setProperties(props, bar, context);
+        assertNull(bar.getId());
+        assertEquals(0, bar.getFieldErrors().size());
+    }
+
+    public void testSetCollectionByConverterFromArray() {
+        Foo foo = new Foo();
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+
+        XWorkConverter c = (XWorkConverter)((OgnlTypeConverterWrapper) Ognl.getTypeConverter(vs.getContext())).getTarget();
+        c.registerConverter(Cat.class.getName(), new FooBarConverter());
+        vs.push(foo);
+
+        vs.setValue("cats", new String[]{"1", "2"});
+        assertNotNull(foo.getCats());
+        assertEquals(2, foo.getCats().size());
+        assertEquals(Cat.class, foo.getCats().get(0).getClass());
+        assertEquals(Cat.class, foo.getCats().get(1).getClass());
+    }
+
+    public void testSetCollectionByConverterFromCollection() {
+        Foo foo = new Foo();
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+
+        XWorkConverter c = (XWorkConverter)((OgnlTypeConverterWrapper) Ognl.getTypeConverter(vs.getContext())).getTarget();
+        c.registerConverter(Cat.class.getName(), new FooBarConverter());
+        vs.push(foo);
+
+        HashSet s = new HashSet();
+        s.add("1");
+        s.add("2");
+        vs.setValue("cats", s);
+        assertNotNull(foo.getCats());
+        assertEquals(2, foo.getCats().size());
+        assertEquals(Cat.class, foo.getCats().get(0).getClass());
+        assertEquals(Cat.class, foo.getCats().get(1).getClass());
+    }
+    
+    public void testValueStackSetValueEmptyStringAsLong() {
+        Bar bar = new Bar();
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+        vs.push(bar);
+
+        vs.setValue("id", "");
+        assertNull(bar.getId());
+        assertEquals(0, bar.getFieldErrors().size());
+
+        bar.setId(null);
+
+        vs.setValue("id", new String[]{""});
+        assertNull(bar.getId());
+        assertEquals(0, bar.getFieldErrors().size());
+    }
+    public void testAddingToListsWithObjectsTrue() {
+        doTestAddingToListsWithObjects(true);
+    }
+    public void testAddingToListsWithObjectsFalse() {
+        doTestAddingToListsWithObjects(false);
+
+    }
+    public void doTestAddingToListsWithObjects(final boolean allowAdditions) {
+
+        loadConfigurationProviders(new StubConfigurationProvider() {
+            public void register(ContainerBuilder builder,
+                    LocatableProperties props) throws ConfigurationException {
+                builder.factory(ObjectTypeDeterminer.class, new Factory() {
+                    public Object create(Context context) throws Exception {
+                        return new MockObjectTypeDeterminer(null,Cat.class,null,allowAdditions);
+                    }
+                    
+                });
+            }
+        });
+
+        Foo foo = new Foo();
+        foo.setMoreCats(new ArrayList());
+        String spielname = "Spielen";
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+        vs.getContext().put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.TRUE);
+        vs.push(foo);
+        try {
+            vs.setValue("moreCats[2].name", spielname);
+        } catch (IndexOutOfBoundsException e) {
+            if (allowAdditions) {
+                throw e;
+            }
+        }
+        Object setCat = null;
+        if (allowAdditions) {
+             setCat = foo.getMoreCats().get(2);
+
+
+            assertNotNull(setCat);
+            assertTrue(setCat instanceof Cat);
+            assertTrue(((Cat) setCat).getName().equals(spielname));
+        }	else {
+            assertTrue(foo.getMoreCats()==null || foo.getMoreCats().size()==0);
+        }
+
+        //now try to set a lower number
+        //to test setting after a higher one
+        //has been created
+        if (allowAdditions) {
+            spielname = "paws";
+            vs.setValue("moreCats[0].name", spielname);
+            setCat = foo.getMoreCats().get(0);
+            assertNotNull(setCat);
+            assertTrue(setCat instanceof Cat);
+            assertTrue(((Cat) setCat).getName().equals(spielname));
+        }
+
+    }
+
+    
+    public void testAddingToMapsWithObjectsTrue() throws Exception {
+        doTestAddingToMapsWithObjects(true);
+    }
+    
+    public void testAddingToMapsWithObjectsFalse() throws Exception {
+        doTestAddingToMapsWithObjects(false);
+
+    }
+
+    public void doTestAddingToMapsWithObjects(boolean allowAdditions) throws Exception {
+
+        loadButAdd(ObjectTypeDeterminer.class, new MockObjectTypeDeterminer(Long.class,Cat.class,null,allowAdditions));
+
+        Foo foo = new Foo();
+        foo.setAnotherCatMap(new HashMap());
+        String spielname = "Spielen";
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+        vs.getContext().put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.TRUE);
+        vs.push(foo);
+        vs.getContext().put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+        vs.setValue("anotherCatMap[\"3\"].name", spielname);
+        Object setCat = foo.getAnotherCatMap().get(new Long(3));
+        if (allowAdditions) {
+            assertNotNull(setCat);
+            assertTrue(setCat instanceof Cat);
+            assertTrue(((Cat) setCat).getName().equals(spielname));
+        }	else {
+            assertNull(setCat);
+        }
+
+
+    }
+    
+    
+    public void testAddingAndModifyingCollectionWithObjectsSet() {
+        doTestAddingAndModifyingCollectionWithObjects(new HashSet());
+    }
+    public void testAddingAndModifyingCollectionWithObjectsList() {
+        doTestAddingAndModifyingCollectionWithObjects(new ArrayList());
+
+    }
+    public void doTestAddingAndModifyingCollectionWithObjects(Collection barColl) {
+
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        Foo foo = new Foo();
+
+        foo.setBarCollection(barColl);
+        Bar bar1 = new Bar();
+        bar1.setId(new Long(11));
+        barColl.add(bar1);
+        Bar bar2 = new Bar();
+        bar2.setId(new Long(22));
+        barColl.add(bar2);
+        //try modifying bar1 and bar2
+        //check the logs here to make sure
+        //the Map is being created
+        ReflectionContextState.setCreatingNullObjects(vs.getContext(), true);
+        ReflectionContextState.setReportingConversionErrors(vs.getContext(), true);
+        vs.push(foo);
+        String bar1Title = "The Phantom Menace";
+        String bar2Title = "The Clone Wars";
+        vs.setValue("barCollection(22).title", bar2Title);
+        vs.setValue("barCollection(11).title", bar1Title);
+        Iterator barSetIter = barColl.iterator();
+        while (barSetIter.hasNext()) {
+            Bar next = (Bar) barSetIter.next();
+            if (next.getId().intValue() == 22) {
+                assertEquals(bar2Title, next.getTitle());
+            } else {
+                assertEquals(bar1Title, next.getTitle());
+            }
+        }
+        //now test adding to a collection
+        String bar3Title = "Revenge of the Sith";
+        String bar4Title = "A New Hope";
+        vs.setValue("barCollection.makeNew[4].title", bar4Title, true);
+        vs.setValue("barCollection.makeNew[0].title", bar3Title, true);
+
+        assertEquals(4, barColl.size());
+        barSetIter = barColl.iterator();
+
+        while (barSetIter.hasNext()) {
+            Bar next = (Bar) barSetIter.next();
+            if (next.getId() == null) {
+                assertNotNull(next.getTitle());
+                assertTrue(next.getTitle().equals(bar4Title)
+                        || next.getTitle().equals(bar3Title));
+            }
+        }
+
+    }
+    public void testAddingToCollectionBasedOnPermission() {
+        final MockObjectTypeDeterminer determiner = new MockObjectTypeDeterminer(Long.class,Bar.class,"id",true);
+        loadConfigurationProviders(new StubConfigurationProvider() {
+            public void register(ContainerBuilder builder,
+                    LocatableProperties props) throws ConfigurationException {
+                builder.factory(ObjectTypeDeterminer.class, new Factory() {
+                    public Object create(Context context) throws Exception {
+                        return determiner;
+                    }
+                    
+                }, Scope.SINGLETON);
+            }
+        });
+
+        Collection barColl=new HashSet();
+
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        ReflectionContextState.setCreatingNullObjects(vs.getContext(), true);
+        ReflectionContextState.setReportingConversionErrors(vs.getContext(), true);
+        Foo foo = new Foo();
+
+        foo.setBarCollection(barColl);
+
+        vs.push(foo);
+
+        String bar1Title="title";
+        vs.setValue("barCollection(11).title", bar1Title);
+
+        assertEquals(1, barColl.size());
+        Object bar=barColl.iterator().next();
+        assertTrue(bar instanceof Bar);
+        assertEquals(((Bar)bar).getTitle(), bar1Title);
+        assertEquals(((Bar)bar).getId(), new Long(11));
+
+        //now test where there is no permission
+        determiner.setShouldCreateIfNew(false);
+
+        String bar2Title="another title";
+        vs.setValue("barCollection(22).title", bar1Title);
+
+        assertEquals(1, barColl.size());
+        bar=barColl.iterator().next();
+        assertTrue(bar instanceof Bar);
+        assertEquals(((Bar)bar).getTitle(), bar1Title);
+        assertEquals(((Bar)bar).getId(), new Long(11));
+
+
+    }
+
+}

src/test/com/opensymphony/xwork2/ognl/accessor/XWorkListPropertyAccessorTest.java

  */
 package com.opensymphony.xwork2.ognl.accessor;
 
+import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.XWorkTestCase;
 import com.opensymphony.xwork2.util.ListHolder;
 import com.opensymphony.xwork2.util.ValueStack;
 public class XWorkListPropertyAccessorTest extends XWorkTestCase {
 
     public void testContains() {
-        ValueStack vs = ValueStackFactory.getFactory().createValueStack();
+        ValueStack vs = ActionContext.getContext().getValueStack();
         ListHolder listHolder = new ListHolder();
         vs.push(listHolder);
 
     }
 
     public void testCanAccessListSizeProperty() {
-        ValueStack vs = ValueStackFactory.getFactory().createValueStack();
+        ValueStack vs = ActionContext.getContext().getValueStack();
         List myList = new ArrayList();
         myList.add("a");
         myList.add("b");

src/test/com/opensymphony/xwork2/spring/ActionsFromSpringTest.java

 public class ActionsFromSpringTest extends XWorkTestCase {
     private ApplicationContext appContext;
 
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         super.setUp();
 
-        XmlConfigurationProvider defaults = new XmlConfigurationProvider("xwork-default.xml");
-        defaults.setThrowExceptionOnDuplicateBeans(false);
         // Set up XWork
-        loadConfigurationProviders(new XmlConfigurationProvider("com/opensymphony/xwork2/spring/actionContext-xwork.xml"),
-                defaults);
+        loadConfigurationProviders(new XmlConfigurationProvider("com/opensymphony/xwork2/spring/actionContext-xwork.xml"));
         appContext = ((SpringObjectFactory)container.getInstance(ObjectFactory.class)).appContext;
     }
 

src/test/com/opensymphony/xwork2/spring/InjectSpringObjectFactoryTest.java

-/*
- * Created on Jun 29, 2004
- */
-package com.opensymphony.xwork2.spring;
-
-import com.opensymphony.xwork2.ObjectFactory;
-import com.opensymphony.xwork2.XWorkTestCase;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-/**
- * Test that Spring correctly calls the "init" method of the
- * {@link com.opensymphony.xwork2.spring.SpringObjectFactory}
- * 
- * @author Simon Stewart
- */
-public class InjectSpringObjectFactoryTest extends XWorkTestCase {
-
-    public void testSpringShouldCallInitMethod() {
-        ApplicationContext appContext = new ClassPathXmlApplicationContext(
-                "com/opensymphony/xwork2/spring/autowireContext.xml");
-
-        ObjectFactory factory = ObjectFactory.getObjectFactory();
-
-        assertTrue(
-                "ObjectFactory should be an instance of SpringObjectFactory",
-                factory instanceof SpringObjectFactory);
-    }
-}

src/test/com/opensymphony/xwork2/spring/SpringObjectFactoryTest.java

  */
 
 import com.opensymphony.xwork2.*;
+import com.opensymphony.xwork2.config.ConfigurationException;
 import com.opensymphony.xwork2.config.entities.ActionConfig;
 import com.opensymphony.xwork2.config.entities.InterceptorConfig;
 import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.inject.ContainerBuilder;
 import com.opensymphony.xwork2.interceptor.Interceptor;
 import com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor;
 import com.opensymphony.xwork2.interceptor.TimerInterceptor;
 import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
+import com.opensymphony.xwork2.util.location.LocatableProperties;
 import com.opensymphony.xwork2.validator.Validator;
 import com.opensymphony.xwork2.validator.validators.ExpressionValidator;
 import com.opensymphony.xwork2.validator.validators.RequiredStringValidator;
 public class SpringObjectFactoryTest extends XWorkTestCase {
 
     StaticApplicationContext sac;
+    SpringObjectFactory objectFactory;
 
 
     public void setUp() throws Exception {
         super.setUp();
 
         sac = new StaticApplicationContext();
-
-        SpringObjectFactory objFactory = new SpringObjectFactory();
-        objFactory.setApplicationContext(sac);
-        objFactory.setReflectionProvider(new OgnlReflectionProvider());
-        ObjectFactory.setObjectFactory(objFactory);
+        loadConfigurationProviders(new StubConfigurationProvider() {
+
+            @Override
+            public void register(ContainerBuilder builder,
+                    LocatableProperties props) throws ConfigurationException {
+                builder.factory(ObjectFactory.class, SpringObjectFactory.class);
+            }
+            
+        });
+
+        objectFactory = (SpringObjectFactory) container.getInstance(ObjectFactory.class);
+        objectFactory.setApplicationContext(sac);
     }
 
     public void testFallsBackToDefaultObjectFactoryActionSearching() throws Exception {
         ActionConfig actionConfig = new ActionConfig(null, ModelDrivenAction.class.getName(), new HashMap(), new HashMap(), null);
 
-        Object action = ObjectFactory.getObjectFactory().buildBean(actionConfig.getClassName(), null);
+        Object action = objectFactory.buildBean(actionConfig.getClassName(), null);
 
         assertEquals(ModelDrivenAction.class, action.getClass());
     }
     public void testFallsBackToDefaultObjectFactoryInterceptorBuilding() throws Exception {
         InterceptorConfig iConfig = new InterceptorConfig("timer", ModelDrivenInterceptor.class.getName(), new HashMap());
 
-        Interceptor interceptor = ObjectFactory.getObjectFactory().buildInterceptor(iConfig, new HashMap());
+        Interceptor interceptor = objectFactory.buildInterceptor(iConfig, new HashMap());
 
         assertEquals(ModelDrivenInterceptor.class, interceptor.getClass());
     }
 
     public void testFallsBackToDefaultObjectFactoryResultBuilding() throws Exception {
         ResultConfig rConfig = new ResultConfig(Action.SUCCESS, ActionChainResult.class.getName(), null);
-        Result result = ObjectFactory.getObjectFactory().buildResult(rConfig, ActionContext.getContext().getContextMap());
+        Result result = objectFactory.buildResult(rConfig, ActionContext.getContext().getContextMap());
 
         assertEquals(ActionChainResult.class, result.getClass());
     }
 
     public void testFallsBackToDefaultObjectFactoryValidatorBuilding() throws Exception {
-        Validator validator = ObjectFactory.getObjectFactory().buildValidator(RequiredStringValidator.class.getName(), new HashMap(), null);
+        Validator validator = objectFactory.buildValidator(RequiredStringValidator.class.getName(), new HashMap(), null);
 
         assertEquals(RequiredStringValidator.class, validator.getClass());
     }
         sac.registerPrototype("simple-action", SimpleAction.class, new MutablePropertyValues());
 
         ActionConfig actionConfig = new ActionConfig(null, "simple-action", new HashMap(), new HashMap(), null);
-        Object action = ObjectFactory.getObjectFactory().buildBean(actionConfig.getClassName(), null);
+        Object action = objectFactory.buildBean(actionConfig.getClassName(), null);
 
         assertEquals(SimpleAction.class, action.getClass());
     }
         sac.registerSingleton("timer-interceptor", TimerInterceptor.class, new MutablePropertyValues());
 
         InterceptorConfig iConfig = new InterceptorConfig("timer", "timer-interceptor", new HashMap());
-        Interceptor interceptor = ObjectFactory.getObjectFactory().buildInterceptor(iConfig, new HashMap());
+        Interceptor interceptor = objectFactory.buildInterceptor(iConfig, new HashMap());
 
         assertEquals(TimerInterceptor.class, interceptor.getClass());
     }
         sac.registerPrototype("chaining-result", ActionChainResult.class, new MutablePropertyValues());
 
         ResultConfig rConfig = new ResultConfig(Action.SUCCESS, "chaining-result", null);
-        Result result = ObjectFactory.getObjectFactory().buildResult(rConfig, ActionContext.getContext().getContextMap());
+        Result result = objectFactory.buildResult(rConfig, ActionContext.getContext().getContextMap());
 
         assertEquals(ActionChainResult.class, result.getClass());
     }
     public void testObtainValidatorBySpringName() throws Exception {
         sac.registerPrototype("expression-validator", ExpressionValidator.class, new MutablePropertyValues());
 
-        Validator validator = ObjectFactory.getObjectFactory().buildValidator("expression-validator", new HashMap(), null);
+        Validator validator = objectFactory.buildValidator("expression-validator", new HashMap(), null);
 
         assertEquals(ExpressionValidator.class, validator.getClass());
     }
         sac.getBeanFactory().registerSingleton("bean", new TestBean());
         TestBean bean = (TestBean) sac.getBean("bean");
 
-        SimpleAction action = (SimpleAction) ObjectFactory.getObjectFactory().buildBean(SimpleAction.class.getName(), null);
+        SimpleAction action = (SimpleAction) objectFactory.buildBean(SimpleAction.class.getName(), null);
 
         assertEquals(bean, action.getBean());
     }
 
     public void testShouldGiveReferenceToAppContextIfBeanIsApplicationContextAwareAndNotInstantiatedViaSpring() throws Exception {
-        Foo foo = (Foo) ObjectFactory.getObjectFactory().buildBean(Foo.class.getName(), null);
+        Foo foo = (Foo) objectFactory.buildBean(Foo.class.getName(), null);
 
         assertTrue("Expected app context to have been set", foo.isApplicationContextSet());
     }
         sac.getBeanFactory().registerSingleton("bean", new TestBean());
         TestBean bean = (TestBean) sac.getBean("bean");
 
-        SimpleAction action = (SimpleAction) ObjectFactory.getObjectFactory().buildBean(SimpleAction.class, null);
+        SimpleAction action = (SimpleAction) objectFactory.buildBean(SimpleAction.class, null);
 
         assertEquals(bean, action.getBean());
     }
 
     public void testShouldGiveReferenceToAppContextIfBeanIsLoadedByClassApplicationContextAwareAndNotInstantiatedViaSpring() throws Exception {
-        Foo foo = (Foo) ObjectFactory.getObjectFactory().buildBean(Foo.class, null);
+        Foo foo = (Foo) objectFactory.buildBean(Foo.class, null);
 
         assertTrue("Expected app context to have been set", foo.isApplicationContextSet());
     }
     public void testLookingUpAClassInstanceDelegatesToSpring() throws Exception {
         sac.registerPrototype("simple-action", SimpleAction.class, new MutablePropertyValues());
 
-        Class clazz = ObjectFactory.getObjectFactory().getClassInstance("simple-action");
+        Class clazz = objectFactory.getClassInstance("simple-action");
 
         assertNotNull("Nothing returned", clazz);
         assertEquals("Expected to have instance of SimpleAction returned", SimpleAction.class, clazz);
     }
 
     public void testLookingUpAClassInstanceFallsBackToTheDefaultObjectFactoryIfSpringBeanNotFound() throws Exception {
-        Class clazz = ObjectFactory.getObjectFactory().getClassInstance(SimpleAction.class.getName());
+        Class clazz = objectFactory.getClassInstance(SimpleAction.class.getName());
 
         assertNotNull("Nothing returned", clazz);
         assertEquals("Expected to have instance of SimpleAction returned", SimpleAction.class, clazz);
     }
 
     public void testSetAutowireStrategy() throws Exception {
-        SpringObjectFactory objectFactory = (SpringObjectFactory) ObjectFactory.getObjectFactory();
         assertEquals(objectFactory.getAutowireStrategy(), AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
 
         objectFactory.setAutowireStrategy(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);
     }
 
     public void testShouldUseConstructorBasedInjectionWhenCreatingABeanFromAClassName() throws Exception {
-        SpringObjectFactory factory = (SpringObjectFactory) ObjectFactory.getObjectFactory();
+        SpringObjectFactory factory = (SpringObjectFactory) objectFactory;
         sac.registerSingleton("actionBean", SimpleAction.class, new MutablePropertyValues());
 
         ConstructorBean bean = (ConstructorBean) factory.buildBean(ConstructorBean.class, null);
     }
 
     public void testFallBackToDefaultObjectFactoryWhenTheCConstructorDIIsAmbiguous() throws Exception {
-        SpringObjectFactory factory = (SpringObjectFactory) ObjectFactory.getObjectFactory();
+        SpringObjectFactory factory = (SpringObjectFactory) objectFactory;
         sac.registerSingleton("firstActionBean", SimpleAction.class, new MutablePropertyValues());
         sac.registerSingleton("secondActionBean", SimpleAction.class, new MutablePropertyValues());
 
         ActionConfig actionConfig = new ActionConfig();
         actionConfig.setClassName(ConstructorAction.class.getName());
 
-        ConstructorAction action = (ConstructorAction) ObjectFactory.getObjectFactory().buildBean(actionConfig.getClassName(), null);
+        ConstructorAction action = (ConstructorAction) objectFactory.buildBean(actionConfig.getClassName(), null);
 
         assertNotNull("Bean should not be null", action);
         assertNotNull("Action should have been added via DI", action.getAction());
 
         ActionConfig actionConfig = new ActionConfig();
         actionConfig.setClassName(SimpleAction.class.getName());
-        Action action = (Action) ObjectFactory.getObjectFactory().buildBean(actionConfig.getClassName(), null);
+        Action action = (Action) objectFactory.buildBean(actionConfig.getClassName(), null);
 
         assertNotNull("Bean should not be null", action);
         System.out.println("Action class is: " + action.getClass().getName());