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()) {