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!
=