You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by cl...@apache.org on 2005/07/04 01:44:57 UTC

svn commit: r209003 - in /incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck: JDO_Test.java lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java

Author: clr
Date: Sun Jul  3 16:44:55 2005
New Revision: 209003

URL: http://svn.apache.org/viewcvs?rev=209003&view=rev
Log:
JDO-77 fixed illegally trying to modify a final field via reflection

Modified:
    incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/JDO_Test.java
    incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java

Modified: incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/JDO_Test.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/JDO_Test.java?rev=209003&r1=209002&r2=209003&view=diff
==============================================================================
--- incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/JDO_Test.java (original)
+++ incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/JDO_Test.java Sun Jul  3 16:44:55 2005
@@ -20,10 +20,18 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+
 import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Properties;
 import java.util.Vector;
 
@@ -749,53 +757,74 @@
         return NUM_STATES;
     }
 
-    /** This method mangles an object by changing all its public fields
+    /** This method mangles an object by changing all its non-static, 
+     *  non-final fields.
+     *  It returns true if the object was mangled, and false if there
+     *  are no fields to mangle.
      */
-    protected void mangleObject (Object oid) 
+    protected boolean mangleObject (Object oid) 
         throws Exception {
-        Class oidClass = oid.getClass();
-        Field[] fields = oidClass.getFields();
+        Field[] fields = getModifiableFields(oid);
+        if (fields.length == 0) return false;
         for (int i = 0; i < fields.length; ++i) {
             Field field = fields[i];
-            field.setAccessible(true);
-            if (debug) 
-                logger.debug("field" + i + " has name: " + field.getName() +
-                             " type: " + field.getType());
             Class fieldType = field.getType();
             if (fieldType == long.class) {
-                field.setLong(oid, 10000L);
-            }
-            if (fieldType == int.class) {
-                field.setInt(oid, 10000);
-            }
-            if (fieldType == short.class) {
-                field.setShort(oid, (short)10000);
-            }
-            if (fieldType == byte.class) {
-                field.setByte(oid, (byte)100);
-            }
-            if (fieldType == char.class) {
-                field.setChar(oid, '0');
-            }
-            if (fieldType == String.class) {
-                field.set(oid, "This is certainly a challenge");
-            }
-            if (fieldType == Integer.class) {
-                field.set(oid, new Integer(10000));
-            }
-            if (fieldType == Long.class) {
-                field.set(oid, new Long(10000L));
-            }
-            if (fieldType == Short.class) {
-                field.set(oid, new Short((short)10000));
-            }
-            if (fieldType == Byte.class) {
-                field.set(oid, new Byte((byte)100));
-            }
-            if (fieldType == Character.class) {
-                field.set(oid, new Character('0'));
+                field.setLong(oid, 10000L + field.getLong(oid));
+            } else if (fieldType == int.class) {
+                field.setInt(oid, 10000 + field.getInt(oid));
+            } else if (fieldType == short.class) {
+                field.setShort(oid, (short)(10000 + field.getShort(oid)));
+            } else if (fieldType == byte.class) {
+                field.setByte(oid, (byte)(100 + field.getByte(oid)));
+            } else if (fieldType == char.class) {
+                field.setChar(oid, (char)(10 + field.getChar(oid)));
+            } else if (fieldType == String.class) {
+                field.set(oid, "This is certainly a challenge" + (String)field.get(oid));
+            } else if (fieldType == Integer.class) {
+                field.set(oid, new Integer(10000 + ((Integer)field.get(oid)).intValue()));
+            } else if (fieldType == Long.class) {
+                field.set(oid, new Long(10000L + ((Long)field.get(oid)).longValue()));
+            } else if (fieldType == Short.class) {
+                field.set(oid, new Short((short)(10000 + ((Short)field.get(oid)).shortValue())));
+            } else if (fieldType == Byte.class) {
+                field.set(oid, new Byte((byte)(100 + ((Byte)field.get(oid)).byteValue())));
+            } else if (fieldType == Character.class) {
+                field.set(oid, new Character((char)(10 + ((Character)(field.get(oid))).charValue())));
+            }
+        }
+        return true;
+    }
+    
+    /** Returns modifiable Fields of the class of the parameter. 
+     * Fields are considered modifiable if they are not static or final.
+     * This method requires several permissions in order to run with
+     * a SecurityManager, hence the doPrivileged block:
+     * <ul>
+     * <li>ReflectPermission("suppressAccessChecks")</li>
+     * <li>RuntimePermission("accessDeclaredMembers")</li>
+     * </ul>
+     */
+    protected Field[] getModifiableFields(final Object obj) {
+        return (Field[])AccessController.doPrivileged(
+            new PrivilegedAction () {
+                public Object run () {
+                    Class cls = obj.getClass();
+                    List result = new ArrayList();
+                    Field[] fields = cls.getFields();
+                    for (int i = 0; i < fields.length; ++i) {
+                        Field field = fields[i];
+                        int modifiers = field.getModifiers();
+                        if (Modifier.isFinal(modifiers) ||
+                                Modifier.isStatic(modifiers))
+                            continue;
+                        field.setAccessible(true);
+                        result.add(field);
+                    }
+                    return result.toArray(new Field[result.size()]);
+                }
             }
-        }
+        );
     }
 
     /**

Modified: incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java?rev=209003&r1=209002&r2=209003&view=diff
==============================================================================
--- incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java (original)
+++ incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java Sun Jul  3 16:44:55 2005
@@ -16,7 +16,9 @@
  
 package org.apache.jdo.tck.lifecycle;
 
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
 import javax.jdo.Extent;
 import javax.jdo.Transaction;
@@ -76,16 +78,45 @@
     				 "Extent for StateTransitionObj should not be empty");
     		}
     		extent.close(iter);
-    
-    		for (int i=0; i<NUM_OBJECTS; i++)
-    		{
-    			Object objId=pm.getObjectId(obj[i]);
-    			mangleObject(objId);
-    			Object objId2 = pm.getObjectId(obj[i]); // get another ObjectId copy
-    			if (objId.equals(objId2))
-    				fail(ASSERTION_FAILED,
-    					 "object Id has been changed");
+            int failures = 0;
+            StringBuffer report = new StringBuffer("Failures comparing oids.\n");
+    		for (int i=0; i<NUM_OBJECTS; i++) {
+    			Object objId1=pm.getObjectId(obj[i]);
+                String before=objId1.toString();
+                int objId1HashCode = objId1.hashCode();
+                Object objId2=pm.getObjectId(obj[i]);
+    			if (!mangleObject(objId2)) {
+                    /* The object id class is immutable, so the test succeeds. */
+                    break;
+                }
+                int objId2HashCode = objId2.hashCode();
+    			Object objId3 = pm.getObjectId(obj[i]); // get another ObjectId copy
+    			if (!(objId1.equals(objId3) && objId1HashCode != objId2HashCode)) {
+                    /* The object id obtained after mangling the second object id
+                     * must equal the original object id, and the mangling must
+                     * have changed the mangled id.
+                     */
+                    report.append("Index= ");
+                    report.append(i);
+                    report.append("\n");
+                    report.append(" before= ");
+                    report.append(before);
+                    report.append("\n");
+                    report.append("mangled= ");
+                    report.append(objId2.toString());
+                    report.append("\n");
+                    report.append("  after= ");
+                    report.append(objId3.toString());
+                    report.append("\n");
+                    ++failures;
+                }
     		}
+            if (failures != 0) {
+                if (debug) {
+                    logger.debug(report.toString());
+                }
+                fail(ASSERTION_FAILED, "Failed to compare " + failures + " object ids.");
+            }
             pm.currentTransaction().commit();
         } finally {
             if (pm!=null && pm.currentTransaction().isActive()) {