Hi, Final review. Thanks for your review of the first draft. Please take a look at these changes for API 20. They are needed to implement the latest changes to the JDO specification. Thanks, Craig |
Index: test/java/javax/jdo/identity/StringIdentityTest.java =================================================================== --- test/java/javax/jdo/identity/StringIdentityTest.java (revision 202295) +++ test/java/javax/jdo/identity/StringIdentityTest.java (working copy) @@ -70,4 +70,10 @@ assertFalse ("Not equal StringIdentity instances compare equal.", sc1.equals(sc3)); assertFalse ("Not equal StringIdentity instances compare equal.", sc3.equals(sc1)); } + + public void testGetKeyAsObject() { + StringIdentity c1 = new StringIdentity(Object.class, "1"); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), "1"); + } + } Index: test/java/javax/jdo/identity/IntIdentityTest.java =================================================================== --- test/java/javax/jdo/identity/IntIdentityTest.java (revision 202295) +++ test/java/javax/jdo/identity/IntIdentityTest.java (working copy) @@ -95,4 +95,14 @@ assertFalse ("Not equal IntIdentity instances compare equal.", sc1.equals(sc3)); assertFalse ("Not equal IntIdentity instances compare equal.", sc3.equals(sc1)); } + public void testGetKeyAsObjectPrimitive() { + IntIdentity c1 = new IntIdentity(Object.class, 1); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1)); + } + + public void testGetKeyAsObject() { + IntIdentity c1 = new IntIdentity(Object.class, new Integer(1)); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Integer(1)); + } + } Index: test/java/javax/jdo/identity/CharIdentityTest.java =================================================================== --- test/java/javax/jdo/identity/CharIdentityTest.java (revision 202295) +++ test/java/javax/jdo/identity/CharIdentityTest.java (working copy) @@ -105,4 +105,14 @@ assertFalse ("Not equal CharIdentity instances compare equal.", sc1.equals(sc3)); assertFalse ("Not equal CharIdentity instances compare equal.", sc3.equals(sc1)); } + public void testGetKeyAsObjectPrimitive() { + CharIdentity c1 = new CharIdentity(Object.class, '1'); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1')); + } + + public void testGetKeyAsObject() { + CharIdentity c1 = new CharIdentity(Object.class, new Character('1')); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Character('1')); + } + } Index: test/java/javax/jdo/identity/ShortIdentityTest.java =================================================================== --- test/java/javax/jdo/identity/ShortIdentityTest.java (revision 202295) +++ test/java/javax/jdo/identity/ShortIdentityTest.java (working copy) @@ -95,4 +95,14 @@ assertFalse ("Not equal ShortIdentity instances compare equal.", sc1.equals(sc3)); assertFalse ("Not equal ShortIdentity instances compare equal.", sc3.equals(sc1)); } + public void testGetKeyAsObjectPrimitive() { + ShortIdentity c1 = new ShortIdentity(Object.class, (short)1); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1)); + } + + public void testGetKeyAsObject() { + ShortIdentity c1 = new ShortIdentity(Object.class, new Short((short)1)); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Short((short)1)); + } + } Index: test/java/javax/jdo/identity/LongIdentityTest.java =================================================================== --- test/java/javax/jdo/identity/LongIdentityTest.java (revision 202295) +++ test/java/javax/jdo/identity/LongIdentityTest.java (working copy) @@ -95,4 +95,15 @@ assertFalse ("Not equal LongIdentity instances compare equal.", sc1.equals(sc3)); assertFalse ("Not equal LongIdentity instances compare equal.", sc3.equals(sc1)); } + + public void testGetKeyAsObjectPrimitive() { + LongIdentity c1 = new LongIdentity(Object.class, 1L); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L)); + } + + public void testGetKeyAsObject() { + LongIdentity c1 = new LongIdentity(Object.class, new Long(1L)); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Long(1L)); + } + } Index: test/java/javax/jdo/identity/ByteIdentityTest.java =================================================================== --- test/java/javax/jdo/identity/ByteIdentityTest.java (revision 202295) +++ test/java/javax/jdo/identity/ByteIdentityTest.java (working copy) @@ -95,4 +95,15 @@ assertFalse ("Not equal ByteIdentity instances compare equal.", sc1.equals(sc3)); assertFalse ("Not equal ByteIdentity instances compare equal.", sc3.equals(sc1)); } + + public void testGetKeyAsObjectPrimitive() { + ByteIdentity c1 = new ByteIdentity(Object.class, (byte)1); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1)); + } + + public void testGetKeyAsObject() { + ByteIdentity c1 = new ByteIdentity(Object.class, new Byte((byte)1)); + assertEquals("keyAsObject doesn't match.", c1.getKeyAsObject(), new Byte((byte)1)); + } + } Index: src/java/javax/jdo/identity/SingleFieldIdentity.java =================================================================== --- src/java/javax/jdo/identity/SingleFieldIdentity.java (revision 202295) +++ src/java/javax/jdo/identity/SingleFieldIdentity.java (working copy) @@ -26,6 +26,10 @@ import java.io.ObjectInput; import java.io.ObjectOutput; +import javax.jdo.JDOFatalInternalException; + +import javax.jdo.spi.I18NHelper; + /** This class is the abstract base class for all single field identity * classes. A common case of application identity uses exactly one * persistent field in the class to represent identity. In this case, @@ -36,6 +40,10 @@ public abstract class SingleFieldIdentity implements Externalizable { + /** The Internationalization message helper. + */ + protected static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N + /** The class of the target object. */ transient private Class targetClass; @@ -47,6 +55,10 @@ /** The hashCode. */ protected int hashCode; + + /** The key as an Object. + */ + protected Object keyAsObject; /** Constructor with target class. * @param pcClass the class of the target @@ -80,6 +92,27 @@ return targetClassName; } + /** Return the key as an Object. The method is synchronized to avoid + * race conditions in multi-threaded environments. + * @return the key as an Object. + * @since 2.0 + */ + public synchronized Object getKeyAsObject() { + if (keyAsObject == null) { + keyAsObject = createKeyAsObject(); + } + return keyAsObject; + } + + /** Create the key as an Object. + * @return the key as an Object; + * @since 2.0 + */ + protected Object createKeyAsObject() { + throw new JDOFatalInternalException + (msg.msg("EXC_CreateKeyAsObjectMustNotBeCalled")); + } + /** Check the class and class name and object type. If restored * from serialization, class will be null so compare class name. * @param obj the other object Index: src/java/javax/jdo/identity/StringIdentity.java =================================================================== --- src/java/javax/jdo/identity/StringIdentity.java (revision 202295) +++ src/java/javax/jdo/identity/StringIdentity.java (working copy) @@ -30,11 +30,9 @@ */ public class StringIdentity extends SingleFieldIdentity { - /** The key. + /** The key is stored in the superclass field keyAsObject. */ - private String key; - - + /** Constructor with class and key. * @param pcClass the class * @param key the key @@ -43,8 +41,8 @@ super (pcClass); if (key == null) throw new NullPointerException (); - this.key = key; - hashCode = hashClassName() ^ key.hashCode(); + this.keyAsObject = key; + hashCode = hashClassName() ^ keyAsObject.hashCode(); } /** Constructor only for Externalizable. @@ -56,14 +54,14 @@ * @return the key */ public String getKey () { - return key; + return (String)keyAsObject; } /** Return the String form of the key. * @return the String form of the key */ public String toString () { - return key; + return (String)keyAsObject; } /** Determine if the other object represents the same object id. @@ -77,7 +75,7 @@ return false; } else { StringIdentity other = (StringIdentity) obj; - return key.equals(other.key); + return keyAsObject.equals(other.keyAsObject); } } @@ -86,7 +84,7 @@ */ public void writeExternal(ObjectOutput out) throws IOException { super.writeExternal (out); - out.writeObject(key); + out.writeObject(keyAsObject); } /** Read this object. Read the superclass first. @@ -95,7 +93,6 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal (in); - key = (String)in.readObject(); - hashCode = hashClassName() ^ key.hashCode(); + keyAsObject = (String)in.readObject(); } } Index: src/java/javax/jdo/identity/IntIdentity.java =================================================================== --- src/java/javax/jdo/identity/IntIdentity.java (revision 202295) +++ src/java/javax/jdo/identity/IntIdentity.java (working copy) @@ -47,6 +47,7 @@ */ public IntIdentity (Class pcClass, Integer key) { this (pcClass, key.intValue ()); + keyAsObject = key; } @@ -92,6 +93,14 @@ } } + /** Create the key as an Object. + * @return the key as an Object + * @since 2.0 + */ + protected Object createKeyAsObject() { + return new Integer(key); + } + /** Write this object. Write the superclass first. * @param out the output */ @@ -107,6 +116,5 @@ throws IOException, ClassNotFoundException { super.readExternal (in); key = in.readInt(); - hashCode = hashClassName() ^ key; } } Index: src/java/javax/jdo/identity/CharIdentity.java =================================================================== --- src/java/javax/jdo/identity/CharIdentity.java (revision 202295) +++ src/java/javax/jdo/identity/CharIdentity.java (working copy) @@ -56,6 +56,7 @@ */ public CharIdentity (Class pcClass, Character key) { this (pcClass, key.charValue ()); + keyAsObject = key; } /** Constructor with class and key. The String must have exactly one @@ -106,6 +107,14 @@ } } + /** Create the key as an Object. + * @return the key as an Object + * @since 2.0 + */ + protected Object createKeyAsObject() { + return new Character(key); + } + /** Write this object. Write the superclass first. * @param out the output */ Index: src/java/javax/jdo/identity/ShortIdentity.java =================================================================== --- src/java/javax/jdo/identity/ShortIdentity.java (revision 202295) +++ src/java/javax/jdo/identity/ShortIdentity.java (working copy) @@ -50,6 +50,7 @@ */ public ShortIdentity (Class pcClass, Short key) { this (pcClass, key.shortValue ()); + keyAsObject = key; } /** Constructor with class and key. @@ -94,6 +95,14 @@ } } + /** Create the key as an Object. + * @return the key as an Object + * @since 2.0 + */ + protected Object createKeyAsObject() { + return new Short(key); + } + /** Write this object. Write the superclass first. * @param out the output */ @@ -109,6 +118,5 @@ throws IOException, ClassNotFoundException { super.readExternal (in); key = in.readShort(); - hashCode = hashClassName() ^ key; } } Index: src/java/javax/jdo/identity/LongIdentity.java =================================================================== --- src/java/javax/jdo/identity/LongIdentity.java (revision 202295) +++ src/java/javax/jdo/identity/LongIdentity.java (working copy) @@ -50,6 +50,7 @@ */ public LongIdentity (Class pcClass, Long key) { this (pcClass, key.longValue ()); + keyAsObject = key; } /** Constructor with class and key. @@ -94,6 +95,14 @@ } } + /** Create the key as an Object. + * @return the key as an Object + * @since 2.0 + */ + protected Object createKeyAsObject() { + return new Long(key); + } + /** Write this object. Write the superclass first. * @param out the output */ @@ -109,6 +118,6 @@ throws IOException, ClassNotFoundException { super.readExternal (in); key = in.readLong(); - hashCode = hashClassName() ^ (int)key; } + } Index: src/java/javax/jdo/identity/ByteIdentity.java =================================================================== --- src/java/javax/jdo/identity/ByteIdentity.java (revision 202295) +++ src/java/javax/jdo/identity/ByteIdentity.java (working copy) @@ -50,6 +50,7 @@ */ public ByteIdentity(Class pcClass, Byte key) { this (pcClass, key.byteValue()); + keyAsObject = key; } /** Constructor with class and key. @@ -94,6 +95,14 @@ } } + /** Create the key as an Object. + * @return the key as an Object + * @since 2.0 + */ + protected Object createKeyAsObject() { + return new Byte(key); + } + /** Write this object. Write the superclass first. * @param out the output */ @@ -109,6 +118,5 @@ throws IOException, ClassNotFoundException { super.readExternal (in); key = in.readByte (); - hashCode = super.hashCode() ^ key; } } Index: src/java/javax/jdo/spi/JDOImplHelper.java =================================================================== --- src/java/javax/jdo/spi/JDOImplHelper.java (revision 202295) +++ src/java/javax/jdo/spi/JDOImplHelper.java (working copy) @@ -182,6 +182,18 @@ } /** Create a new instance of the ObjectId class of this <code>PersistenceCapable</code> + * class, using the <code>Object</code> form of the constructor. + * @return the new ObjectId instance, or <code>null</code> if the class is not registered. + * @param str the <code>Object</code> form of the object id + * @param pcClass the <code>PersistenceCapable</code> class. + */ + public Object newObjectIdInstance (Class pcClass, Object obj) { + Meta meta = getMeta (pcClass); + PersistenceCapable pcInstance = meta.getPC(); + return pcInstance == null?null:pcInstance.jdoNewObjectIdInstance(obj); + } + + /** Create a new instance of the ObjectId class of this <code>PersistenceCapable</code> * class, using the <code>String</code> form of the constructor. * @return the new ObjectId instance, or <code>null</code> if the class is not registered. * @param str the <code>String</code> form of the object id Index: src/java/javax/jdo/JDOHelper.java =================================================================== --- src/java/javax/jdo/JDOHelper.java (revision 202295) +++ src/java/javax/jdo/JDOHelper.java (working copy) @@ -30,6 +30,7 @@ import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; +import java.util.Map; import java.util.Properties; import javax.jdo.spi.I18NHelper; @@ -249,7 +250,7 @@ * @see #getPersistenceManagerFactory(Properties,ClassLoader) */ public static PersistenceManagerFactory getPersistenceManagerFactory - (Properties props) { + (Map props) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); return getPersistenceManagerFactory (props, cl); } @@ -287,15 +288,49 @@ * @param cl a class loader to use to load the <code>PersistenceManagerFactory</code> class. */ public static PersistenceManagerFactory getPersistenceManagerFactory - (Properties props, ClassLoader cl) { + (Map props, ClassLoader cl) { String pmfClassName = (String) props.get ("javax.jdo.PersistenceManagerFactoryClass"); //NOI18N if (pmfClassName == null) { throw new JDOFatalUserException (msg.msg("EXC_NoClassNameProperty")); // NOI18N } + Method propsMethod = null; + Exception propsGetMethodException = null; + Method mapMethod = null; + Exception mapGetMethodException = null; + Method pmfMethod = null; try { Class pmfClass = cl.loadClass (pmfClassName); - Method pmfMethod = pmfClass.getMethod ("getPersistenceManagerFactory", //NOI18N - new Class[] {Properties.class}); + try { + propsMethod = pmfClass.getMethod("getPersistenceManagerFactory", //NOI18N + new Class[] {Properties.class}); + } catch (NoSuchMethodException nsme) { + propsGetMethodException = nsme; + } + try { + mapMethod = pmfClass.getMethod("getPersistenceManagerFactory", //NOI18N + new Class[] {Map.class}); + } catch (NoSuchMethodException nsme) { + mapGetMethodException = nsme; + } + /* If the parameter is not a Properties, + * we need a mapMethod or else throw an exception. + */ + if (!(props instanceof Properties)) { + if (mapMethod != null) { + pmfMethod = mapMethod; + } else { + throw mapGetMethodException; + } + } else { // the parameter is a Properties; use either method. + if (mapMethod != null) { + pmfMethod = mapMethod; + } else if (propsMethod != null) { + pmfMethod = propsMethod; + } else { + throw mapGetMethodException; + } + } + return (PersistenceManagerFactory) pmfMethod.invoke (null, new Object[] {props}); } catch (ClassNotFoundException cnfe) { throw new JDOFatalUserException (msg.msg("EXC_ClassNotFound", pmfClassName), cnfe); //NOI18N @@ -307,12 +342,12 @@ Throwable nested = ite.getTargetException(); if (nested instanceof JDOException) { throw (JDOException)nested; - } else throw new JDOFatalUserException (msg.msg("EXC_getPersistenceManagerFactory"), ite); //NOI18N + } else throw new JDOFatalInternalException (msg.msg("EXC_getPersistenceManagerFactory"), ite); //NOI18N } catch (Exception e) { throw new JDOFatalInternalException (msg.msg("ERR_UnexpectedException"), e); //NOI18N } } - + /** * Returns a [EMAIL PROTECTED] PersistenceManagerFactory} configured based * on the properties stored in the resource at Index: src/java/javax/jdo/Bundle.properties =================================================================== --- src/java/javax/jdo/Bundle.properties (revision 202295) +++ src/java/javax/jdo/Bundle.properties (working copy) @@ -46,3 +46,13 @@ PersistenceManagerFactory at "{0}" from JNDI. EXC_StringWrongLength: There must be exactly one character in the id in the input String for CharIdentity. EXC_IllegalEventType:The event type is outside the range of valid event types. +EXC_ObjectIdentityStringConstruction: The instance could not be constructed from \ +the parameter String "{0}". \nThe exception thrown was: "{1}". \n\ +Parsing the class name as "{2}" and key as "{3}". +EXC_ObjectIdentityStringConstructionNoDelimiter: Missing delimiter ":". +EXC_ObjectIdentityStringConstructionTooShort: Parameter is too short. +EXC_ObjectIdentityStringConstructionUsage: The instance could not be constructed \ +from the parameter String "{0}". \ +\nThe parameter String is of the form "<className>:<keyString>". +EXC_CreateKeyAsObjectMustNotBeCalled: The method createKeyAsObject must not be called \ +because the keyAsObject field must never be null for this class.
Craig Russell Architect, Sun Java Enterprise System http://java.sun.com/products/jdo 408 276-5638 mailto:[EMAIL PROTECTED] P.S. A good JDO? O, Gasp! Craig Russell Architect, Sun Java Enterprise System http://java.sun.com/products/jdo 408 276-5638 mailto:[EMAIL PROTECTED] P.S. A good JDO? O, Gasp! |
smime.p7s
Description: S/MIME cryptographic signature