Commits

Anonymous committed aaa5ba5

XW-534 (Updgrate Ognl dependency to 2.7 for XWork 1.2.3 release)
- fix a bug that result in compiled expression (added in ognl 2.7.x) doesn't work with primitive types
- added test cases for testing the new compiled expression feature (ognl 2.7.1)

git-svn-id: http://svn.opensymphony.com/svn/xwork/branches/xwork_1-2@1680e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (8)

src/java/com/opensymphony/xwork/util/CompoundRootAccessor.java

                 Integer.valueOf(beanName);
                 return ".cutStack("+name+")";
             }
-            catch(NumberFormatException e) { /* ignore, its not a number */ }
+            catch(NumberFormatException e) {
+                // ignore, its not a number
+            }
 
             if ("top".equals(name)) {
                 return ".get(0)";
                             }
 
                             Class type = OgnlRuntime.getCompiler().getSuperOrInterfaceClass(pd.getReadMethod(), tmp.getClass());
+
+
+                            if (pd.getPropertyType().isPrimitive()) {
+                                Class wrapClass = OgnlRuntime.getPrimitiveWrapperClass(pd.getPropertyType());
+
+                                ExpressionCompiler.addCastString(ognlcontext, "(ognl.OgnlOps.convertValue(((" + type.getName() + ")");
+                                                    
+                                ognlcontext.setCurrentType(type);
+                                ognlcontext.setCurrentAccessor(CompoundRoot.class);
+
+                                return ".get("+a+"))."+pd.getReadMethod().getName()+"(),"+wrapClass.getName()+".class, false))";
+                            }
+
                             ExpressionCompiler.addCastString(ognlcontext, "((" + type.getName() + ")");
 
                             ognlcontext.setCurrentType(type);
 
                             if (param.isPrimitive()) {
                                 Class wrapClass = OgnlRuntime.getPrimitiveWrapperClass(param);
+                                /*System.out.println("***"+"((" + wrapClass.getName() + ")ognl.OgnlOps#convertValue($3,"
+                                                                            + wrapClass.getName()+ ".class, true))." + OgnlTools.getPrimitiveValueGetter(wrapClass));*/
                                 conversion = OgnlRuntime.getCompiler().createLocalReference(ognlcontext,
                                                                             "((" + wrapClass.getName() + ")ognl.OgnlOps#convertValue($3,"
-                                                                            + wrapClass.getName()+ ".class, true))." + OgnlRuntime.getNumericValueGetter(wrapClass),
+                                                                            + wrapClass.getName()+ ".class, true))." + OgnlTools.getPrimitiveValueGetter(wrapClass),
                                                                             param);
 
                             } else if (param.isArray()) {
                                                                             param);
 
                             } else {
+                                /*System.out.println("(" + param.getName()+ ")ognl.OgnlOps#convertValue($3,"
+                                                                            + param.getName()
+                                                                            + ".class)");*/
                                 conversion = OgnlRuntime.getCompiler().createLocalReference(ognlcontext,
                                                                             "(" + param.getName()+ ")ognl.OgnlOps#convertValue($3,"
                                                                             + param.getName()
 
             if ((argTypes == null) || !invalidMethods.containsKey(mc)) {
                 try {
-                    Object value = OgnlRuntime.callMethod((OgnlContext) context, o, name, name, objects);
+                    Object value = OgnlRuntime.callMethod((OgnlContext) context, o, name, objects);
 
                     if (value != null) {
                         return value;

src/java/com/opensymphony/xwork/util/OgnlTools.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Utility class for features needed to compliment the enhancement added to Ognl 2.7.x
+ *
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class OgnlTools {
+
+    private static final Map PRIMITIVE_VALUE_GETTERS = new HashMap();
+
+    /**
+     * Constant strings for getting the primitive value of different
+     * native types on the generic {@link Number} object interface. (or the less
+     * generic BigDecimal/BigInteger types)
+     */
+    static {
+        PRIMITIVE_VALUE_GETTERS.put(Double.class, "doubleValue()");
+        PRIMITIVE_VALUE_GETTERS.put(Float.class, "floatValue()");
+        PRIMITIVE_VALUE_GETTERS.put(Integer.class, "intValue()");
+        PRIMITIVE_VALUE_GETTERS.put(Long.class, "longValue()");
+        PRIMITIVE_VALUE_GETTERS.put(Short.class, "shortValue()");
+        PRIMITIVE_VALUE_GETTERS.put(Byte.class, "byteValue()");
+        PRIMITIVE_VALUE_GETTERS.put(BigDecimal.class, "doubleValue()");
+        PRIMITIVE_VALUE_GETTERS.put(BigInteger.class, "doubleValue()");
+        PRIMITIVE_VALUE_GETTERS.put(Boolean.class, "booleanValue()");
+        PRIMITIVE_VALUE_GETTERS.put(Character.class, "charValue()");
+    }
+
+    public static String getPrimitiveValueGetter(Class primitiveWrapperClass) {
+        return (String) PRIMITIVE_VALUE_GETTERS.get(primitiveWrapperClass);
+    }
+}

src/test/com/opensymphony/xwork/util/Address.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class Address {
+    private String street;
+    private String pobox;
+    private MyPrimitiveArrayObject myArrayObject;
+
+    public String getStreet() {
+        return street;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+
+    public String getPobox() {
+        return pobox;
+    }
+
+    public void setPobox(String pobox) {
+        this.pobox = pobox;
+    }
+
+    public MyPrimitiveArrayObject getMyArrayObject() {
+        return myArrayObject;
+    }
+
+    public void setMyArrayObject(MyPrimitiveArrayObject myArrayObject) {
+        this.myArrayObject = myArrayObject;
+    }
+}

src/test/com/opensymphony/xwork/util/CompoundRootPropertyAccessorTest.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+import com.opensymphony.xwork.XWorkTestCase;
+import ognl.Node;
+import ognl.Ognl;
+import ognl.OgnlContext;
+import ognl.OgnlRuntime;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class CompoundRootPropertyAccessorTest extends XWorkTestCase {
+
+
+    public void testBasic() throws Exception {
+        
+        MyPrimitivesObject o = new MyPrimitivesObject();
+        o.setMyShort((short)9);
+        o.setMyShortObject(new Short((short)10));
+        o.setMyByte((byte)111);
+        o.setMyByteObject(new Byte((byte)112));
+        o.setMyCharacter('a');
+        o.setMyCharacterObject(new Character('b'));
+        o.setMyDouble(1.1d);
+        o.setMyDoubleObject(new Double(1.2d));
+        o.setMyFloat(2.1f);
+        o.setMyFloatObject(new Float(2.2));
+        o.setMyLong(1);
+        o.setMyLongObject(new Long(2));
+        o.setMyInteger(3);
+        o.setMyIntegerObject(new Integer(4));
+        o.setMyString("hello tmjee");
+        o.setMyBoolean(true);
+        o.setMyBooleanObject(Boolean.TRUE);
+
+
+        CompoundRootAccessor accessor = new CompoundRootAccessor();
+
+        CompoundRoot root = new CompoundRoot();
+        root.add(o);
+
+        OgnlRuntime.setPropertyAccessor(CompoundRoot.class, accessor);
+
+        OgnlContext ognlContext = (OgnlContext) Ognl.createDefaultContext(root, accessor);
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myInteger");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Integer(3));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myIntegerObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Integer(4));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myByte");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Byte((byte)111));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myByteObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Byte((byte)112));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myCharacter");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Character('a'));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myCharacterObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Character('b'));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myDouble");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Double(1.1d));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myDoubleObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Double(1.2d));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myFloat");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(2.1f));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myFloatObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(2.2f));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myLong");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Long(1));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myLongObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Long(2));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myString");
+            assertEquals(node.getAccessor().get(ognlContext, root), "hello tmjee");
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myShort");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Short((short)9));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myShortObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Short((short)10));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myBoolean");
+            assertEquals(node.getAccessor().get(ognlContext, root), Boolean.TRUE);
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myBooleanObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), Boolean.TRUE);
+        }
+    }
+
+
+    public void testArray() throws Exception {
+        CompoundRootAccessor accessor = new CompoundRootAccessor();
+
+        MyPrimitiveArrayObject o = new MyPrimitiveArrayObject();
+        o.setMyByte(new byte[] { (byte)110, (byte)111, (byte)112 });
+        o.setMyByteObject(new Byte[] { new Byte((byte)98), new Byte((byte)99), new Byte((byte)100) });
+        o.setMyShort(new short[] { (short)1, (short)2, (short)3 });
+        o.setMyShortObject(new Short[] { new Short((short)4), new Short((short)5), new Short((short)6) });
+        o.setMyCharacter(new char[] { 'a', 'b', 'c' });
+        o.setMyCharacterObject(new Character[] { new Character('d'), new Character('e'), new Character('f') } );
+        o.setMyString(new String[] { "one", "two", "three" });
+        o.setMyInteger(new int[] { 1, 2, 3 });
+        o.setMyIntegerObject(new Integer[] { new Integer(4), new Integer(5), new Integer(6) });
+        o.setMyLong(new long[] { 1l, 2l, 3l });
+        o.setMyLongObject(new Long[] { new Long(4l), new Long(5l), new Long(6l) });
+        o.setMyFloat(new float[] { 1.1f, 2.2f, 3.3f });
+        o.setMyFloatObject(new Float[] { new Float(4.4f), new Float(5.5f), new Float(6.6f) });
+        o.setMyDouble(new double[] { 1.1d, 2.2d, 3.3d });
+        o.setMyDoubleObject(new Double[] { new Double(4.4d), new Double(5.5d), new Double(6.6d)  });
+        o.setMyBoolean(new boolean[] { true, false });
+        o.setMyBooleanObject(new Boolean[] { Boolean.TRUE, Boolean.FALSE });
+
+
+        CompoundRoot root = new CompoundRoot();
+        root.add(o);
+
+        OgnlContext ognlContext = (OgnlContext) Ognl.createDefaultContext(root, accessor);
+
+        {   // byte[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myByte");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyByte());
+            assertEquals(((byte[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((byte[])node.getAccessor().get(ognlContext, root))[0], (byte)110);
+            assertEquals(((byte[])node.getAccessor().get(ognlContext, root))[1], (byte)111);
+            assertEquals(((byte[])node.getAccessor().get(ognlContext, root))[2], (byte)112);
+        }
+
+        {   // Byte[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myByteObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyByteObject());
+            assertEquals(((Byte[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((Byte[])node.getAccessor().get(ognlContext, root))[0], new Byte((byte)98));
+            assertEquals(((Byte[])node.getAccessor().get(ognlContext, root))[1], new Byte((byte)99));
+            assertEquals(((Byte[])node.getAccessor().get(ognlContext, root))[2], new Byte((byte)100));
+        }
+
+
+        {   // short[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myShort");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyShort());
+            assertEquals(((short[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((short[])node.getAccessor().get(ognlContext, root))[0], (short)1);
+            assertEquals(((short[])node.getAccessor().get(ognlContext, root))[1], (short)2);
+            assertEquals(((short[])node.getAccessor().get(ognlContext, root))[2], (short)3);
+        }
+
+        {   // Short[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myShortObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyShortObject());
+            assertEquals(((Short[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((Short[])node.getAccessor().get(ognlContext, root))[0], new Short((short)4));
+            assertEquals(((Short[])node.getAccessor().get(ognlContext, root))[1], new Short((short)5));
+            assertEquals(((Short[])node.getAccessor().get(ognlContext, root))[2], new Short((short)6));
+        }
+
+        {   // char[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myCharacter");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyCharacter());
+            assertEquals(((char[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((char[])node.getAccessor().get(ognlContext, root))[0], 'a');
+            assertEquals(((char[])node.getAccessor().get(ognlContext, root))[1], 'b');
+            assertEquals(((char[])node.getAccessor().get(ognlContext, root))[2], 'c');
+        }
+
+        {   // Character[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myCharacterObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(((Character[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((Character[])node.getAccessor().get(ognlContext, root))[0], new Character('d'));
+            assertEquals(((Character[])node.getAccessor().get(ognlContext, root))[1], new Character('e'));
+            assertEquals(((Character[])node.getAccessor().get(ognlContext, root))[2], new Character('f'));
+        }
+
+        {   // String[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myString");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyString());
+            assertEquals(((String[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((String[])node.getAccessor().get(ognlContext, root))[0], "one");
+            assertEquals(((String[])node.getAccessor().get(ognlContext, root))[1], "two");
+            assertEquals(((String[])node.getAccessor().get(ognlContext, root))[2], "three");
+        }
+
+        {   // int[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myInteger");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyInteger());
+            assertEquals(((int[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((int[])node.getAccessor().get(ognlContext, root))[0], 1);
+            assertEquals(((int[])node.getAccessor().get(ognlContext, root))[1], 2);
+            assertEquals(((int[])node.getAccessor().get(ognlContext, root))[2], 3);
+        }
+
+        {   // Integer[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myIntegerObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(((Integer[])node.getAccessor().get(ognlContext, root)).length, 3);
+            assertEquals(((Integer[])node.getAccessor().get(ognlContext, root))[0], new Integer(4));
+            assertEquals(((Integer[])node.getAccessor().get(ognlContext, root))[1], new Integer(5));
+            assertEquals(((Integer[])node.getAccessor().get(ognlContext, root))[2], new Integer(6));
+        }
+
+        {   // long[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myLong");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyLong());
+            assertEquals(((long[])node.getAccessor().get(ognlContext, root))[0], 1l);
+            assertEquals(((long[])node.getAccessor().get(ognlContext, root))[1], 2l);
+            assertEquals(((long[])node.getAccessor().get(ognlContext, root))[2], 3l);
+        }
+
+        {   // Long[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myLongObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyLongObject());
+            assertEquals(((Long[])node.getAccessor().get(ognlContext, root))[0], new Long(4l));
+            assertEquals(((Long[])node.getAccessor().get(ognlContext, root))[1], new Long(5l));
+            assertEquals(((Long[])node.getAccessor().get(ognlContext, root))[2], new Long(6l));
+        }
+
+        {   // float[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myFloat");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyFloat());
+            assertEquals(((float[])node.getAccessor().get(ognlContext, root))[0], 1.1f, 2f);
+            assertEquals(((float[])node.getAccessor().get(ognlContext, root))[1], 2.2f, 2f);
+            assertEquals(((float[])node.getAccessor().get(ognlContext, root))[2], 3.3f, 2f);
+        }
+
+        {   // Float[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myFloatObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyFloatObject());
+            assertEquals(((Float[])node.getAccessor().get(ognlContext, root))[0], new Float(4.4f));
+            assertEquals(((Float[])node.getAccessor().get(ognlContext, root))[1], new Float(5.5f));
+            assertEquals(((Float[])node.getAccessor().get(ognlContext, root))[2], new Float(6.6f));
+        }
+
+        {   // double[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myDouble");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyDouble());
+            assertEquals(((double[])node.getAccessor().get(ognlContext, root))[0], 1.1d, 2d);
+            assertEquals(((double[])node.getAccessor().get(ognlContext, root))[1], 2.2d, 2d);
+            assertEquals(((double[])node.getAccessor().get(ognlContext, root))[2], 3.3d, 2d);
+        }
+
+        {   // Double[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myDoubleObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyDoubleObject());
+            assertEquals(((Double[])node.getAccessor().get(ognlContext, root))[0], new Double(4.4d));
+            assertEquals(((Double[])node.getAccessor().get(ognlContext, root))[1], new Double(5.5d));
+            assertEquals(((Double[])node.getAccessor().get(ognlContext, root))[2], new Double(6.6d));
+        }
+
+        {   // boolean[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myBoolean");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyBoolean());
+            assertEquals(((boolean[])node.getAccessor().get(ognlContext, root))[0], true);
+            assertEquals(((boolean[])node.getAccessor().get(ognlContext, root))[1], false);
+        }
+
+        {   // Boolean[]
+            Node node = Ognl.compileExpression(ognlContext, root, "myBooleanObject");
+            assertTrue(node.getAccessor().get(ognlContext, root).getClass().isArray());
+            assertEquals(node.getAccessor().get(ognlContext, root), o.getMyBooleanObject());
+            assertEquals(((Boolean[])node.getAccessor().get(ognlContext, root))[0], Boolean.TRUE);
+            assertEquals(((Boolean[])node.getAccessor().get(ognlContext, root))[1], Boolean.FALSE);
+        }
+    }
+
+
+    public void testObjects() throws Exception {
+        
+        MyPrimitivesObject myPrimitiveObject = new MyPrimitivesObject();
+        myPrimitiveObject.setMyLong(2l);
+        myPrimitiveObject.setMyLongObject(new Long(3l));
+
+        MyPrimitiveArrayObject myPrimitiveArrayObject = new MyPrimitiveArrayObject();
+        myPrimitiveArrayObject.setMyFloat(new float[] { 1.1f, 2.2f, 3.3f });
+        myPrimitiveArrayObject.setMyFloatObject(new Float[] { new Float(4.4f), new Float(5.5f), new Float(6.6f) });
+
+        Address a = new Address();
+        a.setStreet("High Street");
+        a.setPobox("hd1 5pr");
+        a.setMyArrayObject(myPrimitiveArrayObject);
+
+        Person p = new Person();
+        p.setName("tmjee");
+        p.setAge(new Integer(28));
+        p.setMyPrimitiveObject(myPrimitiveObject);
+        p.setAddress(a);
+
+        CompoundRoot root = new CompoundRoot();
+        root.add(p);
+
+        CompoundRootAccessor accessor = new CompoundRootAccessor();
+
+        OgnlRuntime.setPropertyAccessor(CompoundRoot.class, accessor);
+
+        OgnlContext ognlContext = (OgnlContext) Ognl.createDefaultContext(root);
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "name");
+            assertEquals(node.getAccessor().get(ognlContext, root), "tmjee");
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myPrimitiveObject.myLong");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Long(2l));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "myPrimitiveObject.myLongObject");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Long(3l));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "address.street");
+            assertEquals(node.getAccessor().get(ognlContext, root), "High Street");
+        }
+
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "address.myArrayObject.myFloat[0]");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(1.1f));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "address.myArrayObject.myFloat[1]");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(2.2f));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "address.myArrayObject.myFloat[2]");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(3.3f));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "address.myArrayObject.myFloatObject[0]");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(4.4f));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "address.myArrayObject.myFloatObject[1]");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(5.5f));
+        }
+
+        {
+            Node node = Ognl.compileExpression(ognlContext, root, "address.myArrayObject.myFloatObject[2]");
+            assertEquals(node.getAccessor().get(ognlContext, root), new Float(6.6f));
+        }
+    }
+
+}

src/test/com/opensymphony/xwork/util/MyObject.java

+package com.opensymphony.xwork.util;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class MyObject {
+
+    private short myShort;
+    private Short myShortObject;
+    private String myString;
+    private char myCharacter;
+    private Character myCharacterObject;
+    private byte myByte;
+    private Byte myByteObject;
+    private int myInteger;
+    private Integer myIntegerObject;
+    private long myLong;
+    private Long myLongObject;
+    private float myFloat;
+    private Float myFloatObject;
+    private double myDouble;
+
+
+    public short getMyShort() {
+        return myShort;
+    }
+
+    public void setMyShort(short myShort) {
+        this.myShort = myShort;
+    }
+
+    public Short getMyShortObject() {
+        return myShortObject;
+    }
+
+    public void setMyShortObject(Short myShortObject) {
+        this.myShortObject = myShortObject;
+    }
+
+    public String getMyString() {
+        return myString;
+    }
+
+    public void setMyString(String myString) {
+        this.myString = myString;
+    }
+
+    public char getMyCharacter() {
+        return myCharacter;
+    }
+
+    public void setMyCharacter(char myCharacter) {
+        this.myCharacter = myCharacter;
+    }
+
+    public Character getMyCharacterObject() {
+        return myCharacterObject;
+    }
+
+    public void setMyCharacterObject(Character myCharacterObject) {
+        this.myCharacterObject = myCharacterObject;
+    }
+
+    public byte getMyByte() {
+        return myByte;
+    }
+
+    public void setMyByte(byte myByte) {
+        this.myByte = myByte;
+    }
+
+    public Byte getMyByteObject() {
+        return myByteObject;
+    }
+
+    public void setMyByteObject(Byte myByteObject) {
+        this.myByteObject = myByteObject;
+    }
+
+    public int getMyInteger() {
+        return myInteger;
+    }
+
+    public void setMyInteger(int myInteger) {
+        this.myInteger = myInteger;
+    }
+
+    public Integer getMyIntegerObject() {
+        return myIntegerObject;
+    }
+
+    public void setMyIntegerObject(Integer myIntegerObject) {
+        this.myIntegerObject = myIntegerObject;
+    }
+
+    public long getMyLong() {
+        return myLong;
+    }
+
+    public void setMyLong(long myLong) {
+        this.myLong = myLong;
+    }
+
+    public Long getMyLongObject() {
+        return myLongObject;
+    }
+
+    public void setMyLongObject(Long myLongObject) {
+        this.myLongObject = myLongObject;
+    }
+
+    public float getMyFloat() {
+        return myFloat;
+    }
+
+    public void setMyFloat(float myFloat) {
+        this.myFloat = myFloat;
+    }
+
+    public Float getMyFloatObject() {
+        return myFloatObject;
+    }
+
+    public void setMyFloatObject(Float myFloatObject) {
+        this.myFloatObject = myFloatObject;
+    }
+
+    public double getMyDouble() {
+        return myDouble;
+    }
+
+    public void setMyDouble(double myDouble) {
+        this.myDouble = myDouble;
+    }
+
+    public Double getMyDoubleObject() {
+        return myDoubleObject;
+    }
+
+    public void setMyDoubleObject(Double myDoubleObject) {
+        this.myDoubleObject = myDoubleObject;
+    }
+
+    private Double myDoubleObject;
+
+
+}

src/test/com/opensymphony/xwork/util/MyPrimitiveArrayObject.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class MyPrimitiveArrayObject {
+
+    private byte[] myByte;
+    private Byte[] myByteObject;
+    private char[] myCharacter;
+    private Character[] myCharacters;
+    private short[] myShort;
+    private Short[] myShortObject;
+    private int[] myInteger;
+    private Integer[] myIntegerObject;
+    private long[] myLong;
+    private Long[] myLongObject;
+    private float[] myFloat;
+    private Float[] myFloatObject;
+    private double[] myDouble;
+    private Double[] myDoubleObject;
+    private String[] myString;
+    private boolean[] myBoolean;
+    private Boolean[] myBooleanObject;
+
+
+    public boolean[] getMyBoolean() {
+        return myBoolean;
+    }
+
+    public void setMyBoolean(boolean[] myBoolean) {
+        this.myBoolean = myBoolean;
+    }
+
+    public Boolean[] getMyBooleanObject() {
+        return myBooleanObject;
+    }
+
+    public void setMyBooleanObject(Boolean[] myBooleanObject) {
+        this.myBooleanObject = myBooleanObject;
+    }
+
+    public String[] getMyString() {
+        return myString;
+    }
+
+    public void setMyString(String[] myString) {
+        this.myString = myString;
+    }
+
+    public byte[] getMyByte() {
+        return myByte;
+    }
+
+    public void setMyByte(byte[] myByte) {
+        this.myByte = myByte;
+    }
+
+    public Byte[] getMyByteObject() {
+        return myByteObject;
+    }
+
+    public void setMyByteObject(Byte[] myByteObject) {
+        this.myByteObject = myByteObject;
+    }
+
+    public char[] getMyCharacter() {
+        return myCharacter;
+    }
+
+    public void setMyCharacter(char[] myCharacter) {
+        this.myCharacter = myCharacter;
+    }
+
+    public Character[] getMyCharacterObject() {
+        return myCharacters;
+    }
+
+    public void setMyCharacterObject(Character[] myCharacters) {
+        this.myCharacters = myCharacters;
+    }
+
+    public short[] getMyShort() {
+        return myShort;
+    }
+
+    public void setMyShort(short[] myShort) {
+        this.myShort = myShort;
+    }
+
+    public Short[] getMyShortObject() {
+        return myShortObject;
+    }
+
+    public void setMyShortObject(Short[] myShortObject) {
+        this.myShortObject = myShortObject;
+    }
+
+    public int[] getMyInteger() {
+        return myInteger;
+    }
+
+    public void setMyInteger(int[] myInteger) {
+        this.myInteger = myInteger;
+    }
+
+    public Integer[] getMyIntegerObject() {
+        return myIntegerObject;
+    }
+
+    public void setMyIntegerObject(Integer[] myIntegerObject) {
+        this.myIntegerObject = myIntegerObject;
+    }
+
+    public long[] getMyLong() {
+        return myLong;
+    }
+
+    public void setMyLong(long[] myLong) {
+        this.myLong = myLong;
+    }
+
+    public Long[] getMyLongObject() {
+        return myLongObject;
+    }
+
+    public void setMyLongObject(Long[] myLongObject) {
+        this.myLongObject = myLongObject;
+    }
+
+    public float[] getMyFloat() {
+        return myFloat;
+    }
+
+    public void setMyFloat(float[] myFloat) {
+        this.myFloat = myFloat;
+    }
+
+    public Float[] getMyFloatObject() {
+        return myFloatObject;
+    }
+
+    public void setMyFloatObject(Float[] myFloatObject) {
+        this.myFloatObject = myFloatObject;
+    }
+
+    public double[] getMyDouble() {
+        return myDouble;
+    }
+
+    public void setMyDouble(double[] myDouble) {
+        this.myDouble = myDouble;
+    }
+
+    public Double[] getMyDoubleObject() {
+        return myDoubleObject;
+    }
+
+    public void setMyDoubleObject(Double[] myDoubleObject) {
+        this.myDoubleObject = myDoubleObject;
+    }
+}

src/test/com/opensymphony/xwork/util/MyPrimitivesObject.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class MyPrimitivesObject {
+
+    private boolean myBoolean;
+    private Boolean myBooleanObject;
+    private short myShort;
+    private Short myShortObject;
+    private String myString;
+    private char myCharacter;
+    private Character myCharacterObject;
+    private byte myByte;
+    private Byte myByteObject;
+    private int myInteger;
+    private Integer myIntegerObject;
+    private long myLong;
+    private Long myLongObject;
+    private float myFloat;
+    private Float myFloatObject;
+    private double myDouble;
+
+
+    public boolean isMyBoolean() {
+        return myBoolean;
+    }
+
+    public void setMyBoolean(boolean myBoolean) {
+        this.myBoolean = myBoolean;
+    }
+
+    public Boolean getMyBooleanObject() {
+        return myBooleanObject;
+    }
+
+    public void setMyBooleanObject(Boolean myBooleanObject) {
+        this.myBooleanObject = myBooleanObject;
+    }
+
+    public short getMyShort() {
+        return myShort;
+    }
+
+    public void setMyShort(short myShort) {
+        this.myShort = myShort;
+    }
+
+    public Short getMyShortObject() {
+        return myShortObject;
+    }
+
+    public void setMyShortObject(Short myShortObject) {
+        this.myShortObject = myShortObject;
+    }
+
+    public String getMyString() {
+        return myString;
+    }
+
+    public void setMyString(String myString) {
+        this.myString = myString;
+    }
+
+    public char getMyCharacter() {
+        return myCharacter;
+    }
+
+    public void setMyCharacter(char myCharacter) {
+        this.myCharacter = myCharacter;
+    }
+
+    public Character getMyCharacterObject() {
+        return myCharacterObject;
+    }
+
+    public void setMyCharacterObject(Character myCharacterObject) {
+        this.myCharacterObject = myCharacterObject;
+    }
+
+    public byte getMyByte() {
+        return myByte;
+    }
+
+    public void setMyByte(byte myByte) {
+        this.myByte = myByte;
+    }
+
+    public Byte getMyByteObject() {
+        return myByteObject;
+    }
+
+    public void setMyByteObject(Byte myByteObject) {
+        this.myByteObject = myByteObject;
+    }
+
+    public int getMyInteger() {
+        return myInteger;
+    }
+
+    public void setMyInteger(int myInteger) {
+        this.myInteger = myInteger;
+    }
+
+    public Integer getMyIntegerObject() {
+        return myIntegerObject;
+    }
+
+    public void setMyIntegerObject(Integer myIntegerObject) {
+        this.myIntegerObject = myIntegerObject;
+    }
+
+    public long getMyLong() {
+        return myLong;
+    }
+
+    public void setMyLong(long myLong) {
+        this.myLong = myLong;
+    }
+
+    public Long getMyLongObject() {
+        return myLongObject;
+    }
+
+    public void setMyLongObject(Long myLongObject) {
+        this.myLongObject = myLongObject;
+    }
+
+    public float getMyFloat() {
+        return myFloat;
+    }
+
+    public void setMyFloat(float myFloat) {
+        this.myFloat = myFloat;
+    }
+
+    public Float getMyFloatObject() {
+        return myFloatObject;
+    }
+
+    public void setMyFloatObject(Float myFloatObject) {
+        this.myFloatObject = myFloatObject;
+    }
+
+    public double getMyDouble() {
+        return myDouble;
+    }
+
+    public void setMyDouble(double myDouble) {
+        this.myDouble = myDouble;
+    }
+
+    public Double getMyDoubleObject() {
+        return myDoubleObject;
+    }
+
+    public void setMyDoubleObject(Double myDoubleObject) {
+        this.myDoubleObject = myDoubleObject;
+    }
+
+    private Double myDoubleObject;
+
+
+}

src/test/com/opensymphony/xwork/util/Person.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class Person {
+
+    private String name;
+    private Integer age;
+    private Address address;
+    private MyPrimitivesObject myPrimitiveObject;
+
+
+    public Address getAddress() {
+        return address;
+    }
+
+    public void setAddress(Address address) {
+        this.address = address;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public MyPrimitivesObject getMyPrimitiveObject() {
+        return myPrimitiveObject;
+    }
+
+    public void setMyPrimitiveObject(MyPrimitivesObject myPrimitiveObject) {
+        this.myPrimitiveObject = myPrimitiveObject;
+    }
+}