Index: test/schema/jdoconfig.xml/Negative0/META-INF/jdoconfig.xml
===================================================================
Index: test/schema/jdoconfig.xml/Positive0/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Positive0/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Positive0/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,245 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: test/schema/jdoconfig.xml/Negative1/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Negative1/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Negative1/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,7 @@
+
+
+
+
+
Index: test/schema/jdoconfig.xml/Negative2/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Negative2/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Negative2/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
Index: test/schema/jdoconfig.xml/Negative3/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Negative3/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Negative3/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
Index: test/schema/jdoconfig.xml/Negative4/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Negative4/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Negative4/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
Index: test/schema/jdoconfig.xml/Negative5/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Negative5/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Negative5/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
Index: test/schema/jdoconfig.xml/Negative6/6a/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Negative6/6a/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Negative6/6a/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
Index: test/schema/jdoconfig.xml/Negative6/6b/META-INF/jdoconfig.xml
===================================================================
--- test/schema/jdoconfig.xml/Negative6/6b/META-INF/jdoconfig.xml (revision 0)
+++ test/schema/jdoconfig.xml/Negative6/6b/META-INF/jdoconfig.xml (revision 0)
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
Index: test/java/javax/jdo/ClasspathHelper.java
===================================================================
--- test/java/javax/jdo/ClasspathHelper.java (revision 0)
+++ test/java/javax/jdo/ClasspathHelper.java (revision 0)
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.jdo;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class ClasspathHelper {
+
+ private static URLClassLoader SYSTEM_CLASSLOADER = (URLClassLoader) ClassLoader.getSystemClassLoader();
+ private static Method METHOD;
+ static {
+ try {
+ METHOD = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
+ METHOD.setAccessible(true);
+ }
+ catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ public static void addFile(String s) throws IOException {
+ addFile(s, null);
+ }
+
+ public static void addFile(File f) throws IOException {
+ addFile(f, null);
+ }
+
+ public static void addURL(URL u) throws IOException {
+ addURL(u, null);
+ }
+
+ public static void addFile(String s, URLClassLoader loader) throws IOException {
+ addFile(new File(s), loader);
+ }
+
+ public static void addFile(File f, URLClassLoader loader) throws IOException {
+ addURL(f.toURL(), loader);
+ }
+
+ public static void addURL(URL u, URLClassLoader loader) throws IOException {
+ if (loader == null) {
+ loader = SYSTEM_CLASSLOADER;
+ }
+ try {
+ METHOD.invoke(loader, new Object[] { u });
+ }
+ catch (Throwable t) {
+ throw new IOException("Could not add URL to system classloader: " + t.getMessage());
+ }
+ }
+}
+
Index: test/java/javax/jdo/JDOHelperConfigTest.java
===================================================================
--- test/java/javax/jdo/JDOHelperConfigTest.java (revision 0)
+++ test/java/javax/jdo/JDOHelperConfigTest.java (revision 0)
@@ -0,0 +1,379 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.jdo;
+
+import junit.framework.TestSuite;
+
+import javax.jdo.util.AbstractTest;
+import javax.jdo.util.BatchTestRunner;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Random;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * Tests class javax.jdo.JDOHelper for META-INF/jdoconfig.xml compliance.
+ */
+public class JDOHelperConfigTest extends AbstractTest implements Constants {
+
+ public static void main(String args[]) {
+ BatchTestRunner.run(JDOHelperConfigTest.class);
+ }
+
+ public static TestSuite suite() {
+ return new TestSuite(JDOHelperConfigTest.class);
+ }
+
+ protected static String JDOCONFIG_CLASSPATH_PREFIX
+ = "test/schema/jdoconfig.xml";
+
+ protected static Random RANDOM = new Random(System.currentTimeMillis());
+
+ /**
+ * Tests JDOHelper.getPersistenceUnitProperties using file
+ * Positive0-jdoconfig.xml and PU name
+ * "persistence-unit-name.positive0.pmf0"
+ */
+ public void testGetNamedPMFProperties_positive0_pmf0() throws IOException {
+
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0");
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ Map expected = prepareInitialExpectedMap("positive0.pmf0", 2);
+ String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME);
+
+ Map actual = JDOHelper.getPersistenceUnitProperties(name, loader);
+
+ assertNotNull("No properties found", actual);
+ assertEqualProperties(expected, actual);
+ }
+
+ /**
+ * Tests JDOHelper.getPersistenceUnitProperties using file
+ * Positive0-jdoconfig.xml and PU name
+ * "persistence-unit-name.positive0.pmf1"
+ */
+ public void testGetNamedPMFProperties_positive0_pmf1() throws IOException {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0");
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ Map expected = prepareInitialExpectedMap("positive0.pmf1", 2);
+ String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME);
+
+ Map actual = JDOHelper.getPersistenceUnitProperties(name, loader);
+
+ assertNotNull("No properties found", actual);
+ assertEqualProperties(expected, actual);
+ }
+
+ /**
+ * Tests JDOHelper.getPersistenceUnitProperties using file
+ * Positive0-jdoconfig.xml and PU name
+ * "persistence-unit-name.positive0.pmf2"
+ */
+ public void testGetNamedPMFProperties_positive0_pmf2() throws IOException {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0");
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ Map expected = prepareInitialExpectedMap("positive0.pmf2", 2);
+ String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME);
+
+ Map actual = JDOHelper.getPersistenceUnitProperties(name, loader);
+
+ assertNotNull("No properties found", actual);
+ assertEqualProperties(expected, actual);
+ }
+
+ /**
+ * Tests JDOHelper.getPersistenceUnitProperties using file
+ * Positive0-jdoconfig.xml and PU name
+ * "persistence-unit-name.positive0.pmf3"
+ */
+ public void testGetNamedPMFProperties_positive0_pmf3() throws IOException {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0");
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ Map expected = prepareInitialExpectedMap("positive0.pmf3", 2, 2);
+ String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME);
+
+ Map actual = JDOHelper.getPersistenceUnitProperties(name, loader);
+
+ assertNotNull("No properties found", actual);
+ assertEqualProperties(expected, actual);
+ }
+
+ /**
+ * Tests JDOHelper.getPersistenceUnitProperties using file
+ * Positive0-jdoconfig.xml and PU name
+ * "persistence-unit-name.positive0.pmf4"
+ */
+ public void testGetNamedPMFProperties_positive0_pmf4() throws IOException {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0");
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ Map expected = prepareInitialExpectedMap("positive0.pmf4", 0, 2);
+ String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME);
+
+ Map actual = JDOHelper.getPersistenceUnitProperties(name, loader);
+
+ assertNotNull("No properties found", actual);
+ assertEqualProperties(expected, actual);
+ }
+
+ public Map prepareInitialExpectedMap(String testVariant) {
+ return prepareInitialExpectedMap(testVariant, 0, 0);
+ }
+ public Map prepareInitialExpectedMap(String testVariant, int numListeners) {
+ return prepareInitialExpectedMap(testVariant, numListeners, 0);
+ }
+ public Map prepareInitialExpectedMap(
+ String testVariant,
+ int numListeners,
+ int numProperties
+ ) {
+ Map expected = new HashMap();
+
+ expected.put(PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS,
+ "class." + testVariant);
+ expected.put(
+ PROPERTY_CONNECTION_DRIVER_NAME,
+ "connection-driver-name." + testVariant);
+ expected.put(
+ PROPERTY_CONNECTION_FACTORY_NAME,
+ "connection-factory-name." + testVariant);
+ expected.put(
+ PROPERTY_CONNECTION_FACTORY2_NAME,
+ "connection-factory2-name." + testVariant);
+ expected.put(
+ PROPERTY_CONNECTION_PASSWORD,
+ "connection-password." + testVariant);
+ expected.put(
+ PROPERTY_CONNECTION_URL,
+ "connection-url." + testVariant);
+ expected.put(
+ PROPERTY_CONNECTION_USER_NAME,
+ "connection-user-name." + testVariant);
+ expected.put(
+ PROPERTY_IGNORE_CACHE,
+ "ignore-cache." + testVariant);
+ expected.put(
+ PROPERTY_MAPPING,
+ "mapping." + testVariant);
+ expected.put(
+ PROPERTY_MULTITHREADED,
+ "multithreaded." + testVariant);
+ expected.put(
+ PROPERTY_NONTRANSACTIONAL_READ,
+ "nontransactional-read." + testVariant);
+ expected.put(
+ PROPERTY_NONTRANSACTIONAL_WRITE,
+ "nontransactional-write." + testVariant);
+ expected.put(
+ PROPERTY_OPTIMISTIC,
+ "optimistic." + testVariant);
+ expected.put(
+ PROPERTY_PERSISTENCE_UNIT_NAME,
+ "persistence-unit-name." + testVariant);
+ expected.put(
+ PROPERTY_RESTORE_VALUES,
+ "restore-values." + testVariant);
+ expected.put(
+ PROPERTY_RETAIN_VALUES,
+ "retain-values." + testVariant);
+ expected.put(
+ PROPERTY_DETACH_ALL_ON_COMMIT,
+ "detach-all-on-commit." + testVariant);
+
+ // listeners
+ for (int i = 0; i < numListeners; i++) {
+ expected.put(
+ PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER +
+ "listener." + testVariant + ".listener" + i,
+ "classes." + testVariant + ".classes" + i
+ );
+ }
+
+ // properties
+ for (int i = 0; i < numProperties; i++) {
+ expected.put(
+ "property." + testVariant + ".name" + i,
+ "property." + testVariant + ".value" + i
+ );
+ }
+
+ return expected;
+ }
+
+ static void assertEqualProperties(Map expected, Map actual) {
+ Iterator i = expected.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry entry = (Map.Entry) i.next();
+ String key = (String) entry.getKey();
+ String expectedValue = (String) entry.getValue();
+ String actualValue = (String) actual.get(key);
+
+ assertEquals(
+ "Actual property at key [" + key + "] with value [" +
+ actualValue + "] not equal to expected value [" +
+ expectedValue + "]",
+ expectedValue,
+ actualValue);
+ }
+ }
+
+ /**
+ * Tests JDOHelper.getPersistenceUnitProperties using file
+ * Positive0-jdoconfig.xml and PU name
+ * "persistence-unit-name.positive0.pmf0"
+ */
+ public void testDuplicatePUsInDifferentConfigFilesButNotRequested_positive1() throws IOException {
+
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive1/1a");
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive1/1b");
+
+ ClassLoader loader = getClass().getClassLoader();
+
+ Map props = JDOHelper.getPersistenceUnitProperties(null);
+ assertNotNull(props);
+ }
+
+ public void testNegative_NoResourcesFound() {
+ String resource = "" + RANDOM.nextLong();
+
+ InputStream in =
+ getClass().getClassLoader().getResourceAsStream(resource);
+ assertNull(in);
+
+ // resource pretty much guaranteed not to exist
+ try {
+ JDOHelper.getPersistenceManagerFactory(resource);
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+
+ public void testNegative0_EmptyJDOConfigXML() throws IOException {
+ try {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative0");
+
+ JDOHelper.getPersistenceManagerFactory();
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+
+ public void testNegative1_NoPersistenceUnitsDefined() throws IOException {
+ try {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative1");
+
+ JDOHelper.getPersistenceManagerFactory();
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+
+ public void testNegative2_DuplicateAnonymousPersistenceUnitsInSameConfig()
+ throws IOException
+ {
+ try {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative2");
+
+ JDOHelper.getPersistenceManagerFactory();
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+
+ public void testNegative3_DuplicateNamedPersistenceUnitsInSameConfig()
+ throws IOException
+ {
+ try {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative3");
+
+ JDOHelper.getPersistenceManagerFactory(
+ "persistence-unit-name.negative3");
+
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+
+ public void testNegative4_DuplicatePUNamePropertyInAttributeAndElement()
+ throws IOException
+ {
+ try {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative4");
+
+ JDOHelper.getPersistenceManagerFactory(
+ "persistence-unit-name.negative4.value0");
+
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+
+ public void testNegative5_DuplicatePropertyInAttributeAndElement()
+ throws IOException
+ {
+ try {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative5");
+
+ JDOHelper.getPersistenceManagerFactory();
+
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+
+ public void testNegative6_DuplicatePUInDifferentConfigFiles()
+ throws IOException
+ {
+ try {
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative6/6a");
+ ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative6/6b");
+
+ JDOHelper.getPersistenceManagerFactory("persistence-unit-name.negative6");
+
+ fail("JDOHelper failed to throw JDOFatalUserException");
+ }
+ catch (JDOFatalUserException x) {
+ // happy path
+ }
+ }
+}
Index: src/schema/javax/jdo/jdoconfig_2_1.xsd
===================================================================
--- src/schema/javax/jdo/jdoconfig_2_1.xsd (revision 0)
+++ src/schema/javax/jdo/jdoconfig_2_1.xsd (revision 0)
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+ This is the XML Schema for the JDO configuration file.
+
+
+
+
+
+
+
+ The root configuration element for JDO.
+
+
+
+
+
+
+
+ Standard JDO PersistenceManagerFactory
+ configuration properties.
+ Vendor-specific properties are set using
+ additional vendor-specific attributes and/or
+ property elements.
+
+
+
+
+
+
+
+ Vendor-specific properties.
+
+
+
+
+
+
+
+
+
+ javax.jdo.listener.InstanceLifecycleListener
+ instance configuration.
+ There is one
+ instance-lifecycle-listener element
+ per listener instance.
+ Only one instance of the listener
+ class is supported in this
+ configuration file.
+ If multiple instances of the same
+ listener class is required, then the
+ API
+ PersistenceManagerFactory.addInstanceLifecycleListener(...)
+ must be used.
+
+ If attribute "classes" is missing,
+ all persistence-capable instances
+ are observed,
+ otherwise it is a comma- or
+ whitespace-delimited list of
+ persistence-capable
+ classes whose instances' will be
+ observed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ These are attributes corresponding to the standard properties
+ defined in JDO 2.1.
+ Any other attributes present, if unrecognized by a JDO
+ implementation, may be silently ignored.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: src/schema/javax/jdo/jdoconfig_2_1.dtd
===================================================================
--- src/schema/javax/jdo/jdoconfig_2_1.dtd (revision 0)
+++ src/schema/javax/jdo/jdoconfig_2_1.dtd (revision 0)
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: src/java/javax/jdo/PersistenceManagerFactory.java
===================================================================
--- src/java/javax/jdo/PersistenceManagerFactory.java (revision 513879)
+++ src/java/javax/jdo/PersistenceManagerFactory.java (working copy)
@@ -25,6 +25,8 @@
import java.util.Properties;
import java.util.Collection;
+import java.io.Serializable;
+
import javax.jdo.datastore.DataStoreCache;
import javax.jdo.listener.InstanceLifecycleListener;
@@ -54,21 +56,8 @@
* @version 2.1
*/
-public interface PersistenceManagerFactory extends java.io.Serializable {
+public interface PersistenceManagerFactory extends Serializable {
- /**
- * The value for TransactionType to specify that transactions
- * are managed by the Java Transactions API, as documented in
- * JSR-220.
- */
- public static final String JTA = "JTA";
-
- /**
- * The value for TransactionType to specify that transactions
- * are managed by the javax.jdo.Transaction instance, similar
- * to the usage as documented in JSR-220.
- */
- public static final String RESOURCE_LOCAL = "RESOURCE_LOCAL";
/** Close this PersistenceManagerFactory. Check for
* JDOPermission("closePersistenceManagerFactory") and if not authorized,
@@ -425,8 +414,8 @@
* This has the same semantics as the same-named property in
* JSR-220 EntityManagerFactory.
* @see #getTransactionType()
- * @see #JTA
- * @see #RESOURCE_LOCAL
+ * @see Constants#JTA
+ * @see Constants#RESOURCE_LOCAL
* @since 2.1
* @param name the TransactionType
* @throws JDOUserException if the parameter is not a permitted value
Index: src/java/javax/jdo/JDOHelper.java
===================================================================
--- src/java/javax/jdo/JDOHelper.java (revision 513879)
+++ src/java/javax/jdo/JDOHelper.java (working copy)
@@ -22,6 +22,14 @@
package javax.jdo;
+import org.xml.sax.SAXException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -31,16 +39,20 @@
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.net.URL;
+
+import java.util.Collection;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
+import java.util.HashMap;
+import java.util.Enumeration;
+import java.util.Collections;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
import javax.jdo.spi.I18NHelper;
import javax.jdo.spi.JDOImplHelper;
import javax.jdo.spi.JDOImplHelper.StateInterrogationBooleanReturn;
@@ -54,7 +66,12 @@
import javax.rmi.PortableRemoteObject;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.FactoryConfigurationError;
+
/**
* This class can be used by a JDO-aware application to call the JDO behavior
* of PersistenceCapable instances without declaring them to be
@@ -69,13 +86,103 @@
*
* @version 2.1
*/
-public class JDOHelper extends Object {
-
+public class JDOHelper extends Object implements Constants {
+
+ /**
+ * A mapping from jdoconfig.xsd element attributes to PMF properties.
+ */
+ static final Map ATTRIBUTE_PROPERTY_XREF
+ = createAttributePropertyXref();
+
+ /**
+ * The standard XML schema type.
+ */
+ protected static final String XSD_TYPE
+ = "http://www.w3.org/2001/XMLSchema";
+
+ /**
+ * The JAXP schema language property.
+ */
+ protected static final String SCHEMA_LANGUAGE_PROP
+ = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
+
+ /**
+ * External schema location property.
+ */
+ protected static final String SCHEMA_LOCATION_PROP
+ = "http://apache.org/xml/properties/schema/external-schemaLocation";
+
/** The Internationalization message helper.
*/
private final static I18NHelper msg =
I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
+ /**
+ * Creates a map from jdoconfig.xsd element attributes to PMF properties.
+ * @return An unmodifiable Map of jdoconfig.xsd element attributes to PMF
+ * properties.
+ */
+ static Map createAttributePropertyXref() {
+ Map xref = new HashMap();
+
+ xref.put(
+ PMF_ATTRIBUTE_CLASS,
+ PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS);
+ xref.put(
+ PMF_ATTRIBUTE_CONNECTION_DRIVER_NAME,
+ PROPERTY_CONNECTION_DRIVER_NAME);
+ xref.put(
+ PMF_ATTRIBUTE_CONNECTION_FACTORY_NAME,
+ PROPERTY_CONNECTION_FACTORY_NAME);
+ xref.put(
+ PMF_ATTRIBUTE_CONNECTION_FACTORY2_NAME,
+ PROPERTY_CONNECTION_FACTORY2_NAME);
+ xref.put(
+ PMF_ATTRIBUTE_CONNECTION_PASSWORD,
+ PROPERTY_CONNECTION_PASSWORD);
+ xref.put(
+ PMF_ATTRIBUTE_CONNECTION_URL,
+ PROPERTY_CONNECTION_URL);
+ xref.put(
+ PMF_ATTRIBUTE_CONNECTION_USER_NAME,
+ PROPERTY_CONNECTION_USER_NAME);
+ xref.put(
+ PMF_ATTRIBUTE_IGNORE_CACHE,
+ PROPERTY_IGNORE_CACHE);
+ xref.put(
+ PMF_ATTRIBUTE_MAPPING,
+ PROPERTY_MAPPING);
+ xref.put(
+ PMF_ATTRIBUTE_MULTITHREADED,
+ PROPERTY_MULTITHREADED);
+ xref.put(
+ PMF_ATTRIBUTE_NONTRANSACTIONAL_READ,
+ PROPERTY_NONTRANSACTIONAL_READ);
+ xref.put(
+ PMF_ATTRIBUTE_NONTRANSACTIONAL_WRITE,
+ PROPERTY_NONTRANSACTIONAL_WRITE);
+ xref.put(
+ PMF_ATTRIBUTE_OPTIMISTIC,
+ PROPERTY_OPTIMISTIC);
+ xref.put(
+ PMF_ATTRIBUTE_PERSISTENCE_UNIT_NAME,
+ PROPERTY_PERSISTENCE_UNIT_NAME);
+ xref.put(
+ PMF_ATTRIBUTE_RESTORE_VALUES,
+ PROPERTY_RESTORE_VALUES);
+ xref.put(
+ PMF_ATTRIBUTE_RETAIN_VALUES,
+ PROPERTY_RETAIN_VALUES);
+ xref.put(
+ PMF_ATTRIBUTE_DETACH_ALL_ON_COMMIT,
+ PROPERTY_DETACH_ALL_ON_COMMIT);
+ xref.put(
+ PMF_ATTRIBUTE_SERVERTIMEZONEID,
+ PROPERTY_SERVER_TIMEZONE_ID);
+
+ return Collections.unmodifiableMap(xref);
+ }
+
/** The JDOImplHelper instance used for handling non-binary-compatible
* implementations.
*/
@@ -487,23 +594,35 @@
}
}
- /** Get a PersistenceManagerFactory based on a Properties
+ /** Get the anonymous PersistenceManagerFactory configured via the standard
+ * configuration file resource "META-INF/jdoconfig.xml", using the current thread's context class loader
+ * to locate the configuration file resource(s).
+ * @return the anonymous PersistenceManagerFactory.
+ * @since 2.1
+ * @see #getPersistenceManagerFactory(String,ClassLoader)
+ */
+ public static PersistenceManagerFactory getPersistenceManagerFactory() {
+ ClassLoader cl = getContextClassLoader();
+ return getPersistenceManagerFactory ((String)null, cl);
+ }
+
+ /** Get a PersistenceManagerFactory based on a Properties
* instance, using the current thread's context class loader to locate the
* PersistenceManagerFactory class.
* @return the PersistenceManagerFactory.
- * @param props a Properties instance with properties of the
+ * @param props a Properties instance with properties of the
* PersistenceManagerFactory.
- * @see #getPersistenceManagerFactory(Map,ClassLoader)
+ * @see #getPersistenceManagerFactory(java.util.Map,ClassLoader)
*/
public static PersistenceManagerFactory getPersistenceManagerFactory
(Map props) {
ClassLoader cl = getContextClassLoader();
return getPersistenceManagerFactory (props, cl);
}
-
+
/**
* Get a PersistenceManagerFactory based on a
- * Properties instance and a class loader.
+ * Map instance and a class loader.
* The following are standard key values:
*
"javax.jdo.PersistenceManagerFactoryClass"
*
"javax.jdo.option.Optimistic",
@@ -520,8 +639,20 @@
*
"javax.jdo.option.ConnectionFactory2Name",
*
"javax.jdo.option.Mapping",
*
"javax.jdo.mapping.Catalog",
- *
"javax.jdo.mapping.Schema".
- *
JDO implementations
+ *
"javax.jdo.mapping.Schema",
+ *
"javax.jdo.option.PersistenceUnitName".
+ *
+ * and properties of the form
+ *
javax.jdo.option.InstanceLifecycleListener.{listenerClass}={pcClasses}
+ * where {listenerClass} is the fully qualified name of a
+ * class that implements
+ * {@link javax.jdo.listener.InstanceLifecycleListener}, and
+ * {pcClasses} is an optional comma- or whitespace-delimited
+ * list of persistence-capable classes to be observed; the absence of a
+ * value for a property of this form means that instances of all
+ * persistence-capable classes will be observed by an instance of the given
+ * listener class.
+ *
JDO implementations
* are permitted to define key values of their own. Any key values not
* recognized by the implementation must be ignored. Key values that are
* recognized but not supported by an implementation must result in a
@@ -544,9 +675,9 @@
public static PersistenceManagerFactory getPersistenceManagerFactory
(Map props, ClassLoader cl) {
String pmfClassName = (String) props.get (
- "javax.jdo.PersistenceManagerFactoryClass"); //NOI18N
+ PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); //NOI18N
if (pmfClassName == null) {
- throw new JDOFatalUserException (msg.msg(
+ throw new JDOFatalUserException(msg.msg(
"EXC_GetPMFNoClassNameProperty")); // NOI18N
}
try {
@@ -584,93 +715,680 @@
}
/**
- * Returns a {@link PersistenceManagerFactory} configured based
+ * Returns a named {@link PersistenceManagerFactory} with the given persistence unit name or,
+ * if not found, a {@link PersistenceManagerFactory} configured based
* on the properties stored in the resource at
- * propsResource. This method is equivalent to
+ * name. This method is equivalent to
* invoking {@link
* #getPersistenceManagerFactory(String,ClassLoader)} with
* Thread.currentThread().getContextClassLoader() as
* the loader argument.
+ * If multiple persistence units with the name given are found, a {@link JDOFatalUserException} is thrown.
* @since 2.0
- * @param propsResource the resource containing the Properties
+ * @param name the persistence unit name or resource containing the Properties
* @return the PersistenceManagerFactory
*/
public static PersistenceManagerFactory getPersistenceManagerFactory
- (String propsResource) {
- return getPersistenceManagerFactory (propsResource,
+ (String name) {
+ return getPersistenceManagerFactory (name,
getContextClassLoader());
}
/**
- * Returns a {@link PersistenceManagerFactory} configured based
+ * Returns a named {@link PersistenceManagerFactory} with the given persistence unit name or,
+ * if not found, a {@link PersistenceManagerFactory} configured based
* on the properties stored in the resource at
- * propsResource. Loads the resource via
+ * name. Loads the resource via
* loader, and creates a {@link
* PersistenceManagerFactory} with loader. Any
* IOExceptions thrown during resource loading will
* be wrapped in a {@link JDOFatalUserException}.
+ * If multiple persistence units with the name given are found, a {@link JDOFatalUserException} is thrown.
* @since 2.0
- * @param propsResource the resource containing the Properties
- * @param loader the class loader to use to load both the propsResource and
+ * @param name the persistence unit name or resource containing the Properties
+ * @param loader the class loader to use to load both the name and
* the PersistenceManagerFactory class
* @return the PersistenceManagerFactory
*/
public static PersistenceManagerFactory getPersistenceManagerFactory
- (String propsResource, ClassLoader loader) {
- return getPersistenceManagerFactory(propsResource, loader, loader);
+ (String name, ClassLoader loader) {
+ return getPersistenceManagerFactory(name, loader, loader);
}
/**
- * Returns a {@link PersistenceManagerFactory} configured based
+ * Returns a named {@link PersistenceManagerFactory} with the given
+ * persistence unit name or,
+ * if not found, a {@link PersistenceManagerFactory} configured based
* on the properties stored in the resource at
- * propsResource. Loads the Properties via
- * propsLoader, and creates a {@link
+ * name. Loads the Properties via
+ * resourceLoader, and creates a {@link
* PersistenceManagerFactory} with pmfLoader. Any
- * IOExceptions thrown during resource loading will
+ * exceptions thrown during resource loading will
* be wrapped in a {@link JDOFatalUserException}.
+ * If multiple persistence units with the requested name are found, a
+ * {@link JDOFatalUserException} is thrown.
* @since 2.0
- * @param propsResource the resource containing the Properties
- * @param propsLoader the class loader to use to load the propsResource
+ * @param name the persistence unit name or resource containing the Properties
+ * @param resourceLoader the class loader to use to load the name
* @param pmfLoader the class loader to use to load the
* PersistenceManagerFactory class
* @return the PersistenceManagerFactory
*/
public static PersistenceManagerFactory getPersistenceManagerFactory
- (String propsResource, ClassLoader propsLoader, ClassLoader pmfLoader) {
-
- if (propsResource == null)
+ (String name, ClassLoader resourceLoader, ClassLoader pmfLoader) {
+
+ if (resourceLoader == null)
throw new JDOFatalUserException (msg.msg (
- "EXC_GetPMFNullResource")); //NOI18N
- if (propsLoader == null)
- throw new JDOFatalUserException (msg.msg (
"EXC_GetPMFNullPropsLoader")); //NOI18N
if (pmfLoader == null)
throw new JDOFatalUserException (msg.msg (
"EXC_GetPMFNullPMFLoader")); //NOI18N
- Properties props = new Properties ();
InputStream in = null;
+ if (name != null) { // then try to load resources from properties file
+ Properties props = new Properties ();
+ try {
+ in = resourceLoader.getResourceAsStream (name);
+ if (in != null) {
+ // then some kind of resource was found by the given name;
+ // assume that it's a properties file and proceed as usual
+ props.load (in);
+ return getPersistenceManagerFactory (props, pmfLoader);
+ }
+ }
+ catch (IOException ioe) {
+ throw new JDOFatalUserException (msg.msg (
+ "EXC_GetPMFIOExceptionRsrc", name), ioe); //NOI18N
+ }
+ finally {
+ if (in != null)
+ try {
+ in.close ();
+ } catch (IOException ioe) { }
+ }
+ }
+ // JDO 2.1: else name was null or no resource found by given name;
+ // assume name represents name of PU
+
+ PersistenceManagerFactory pmf = getPersistenceUnit(
+ name == null ? "" : name.trim(),
+ resourceLoader,
+ pmfLoader
+ );
+ if (pmf != null) {
+ return pmf;
+ }
+
+ // else no PU found
+ throw new JDOFatalUserException (msg.msg (
+ "EXC_NoPMFConfigurableViaPropertiesOrXML",
+ name,
+ resourceLoader)); //NOI18N
+ }
+
+ /** Find and return
+ * - a {@link PersistenceManagerFactory} with the given name,
+ * - a JPA
EntityManagerFactory cast to a
+ * {@link PersistenceManagerFactory}, or -
+ *
- null if not found.
+ * If name is null
+ * or blank, this method attempts to return the anonymous
+ * {@link PersistenceManagerFactory}. If multiple persistence units with
+ * the given name are found (including the anonymous persistence unit),
+ * this method will throw {@link JDOFatalUserException}.
+ *
+ * @param name The persistence unit name, or null, the empty string or a
+ * string only containing whitespace characters for the anonymous
+ * persistence unit.
+ * @param resourceLoader The ClassLoader used to load the standard JDO
+ * configuration file(s) given in the constant
+ * {@link Constants#JDOCONFIG_RESOURCE_NAME}.
+ * @param pmfLoader The loader used to load the
+ * {@link PersistenceManagerFactory} implementation class.
+ * @return A {@link PersistenceManagerFactory} corresponding to the
+ * persistence unit name if found, or null if not found.
+ * @throws JDOFatalUserException if multiple persistence units are found
+ * with the given name, or any other is encountered.
+ * @since 2.1
+ */
+ public static PersistenceManagerFactory getPersistenceUnit(
+ String name,
+ ClassLoader resourceLoader,
+ ClassLoader pmfLoader
+ ) {
+ Map properties = getPersistenceUnitProperties(
+ name, resourceLoader, JDOCONFIG_RESOURCE_NAME);
+
+ if (properties != null) { // found requested JDO persistence unit props
+ return getPersistenceManagerFactory(properties, pmfLoader);
+ }
+
+ // else try to return PMF from JPA EMF
+ if ("".equals(name)) { // no such thing as an anonymous JPA EMF
+ return null;
+ }
+
+ // else try to return PMF from named JPA EMF
+ return getPMFFromEMF(name, pmfLoader);
+ }
+
+ protected static Map getPersistenceUnitProperties(
+ String name
+ ) {
+ return getPersistenceUnitProperties(
+ name, getContextClassLoader(), JDOCONFIG_RESOURCE_NAME);
+ }
+
+ protected static Map getPersistenceUnitProperties(
+ String name,
+ ClassLoader resourceLoader
+ ) {
+ return getPersistenceUnitProperties(
+ name, resourceLoader, JDOCONFIG_RESOURCE_NAME);
+ }
+
+ /**
+ * Find and return the named {@link PersistenceManagerFactory}, or null if
+ * not found. If name is null, return the anonymous
+ * {@link PersistenceManagerFactory}. If multiple persistence units with
+ * the given name are found (including anonymous), throw
+ * {@link JDOFatalUserException}.
+ * This method is here only to facilitate testing; the parameter
+ * "jdoconfigResourceName" in public usage should always have the value
+ * given in the constant JDOCONFIG_RESOURCE_NAME.
+ *
+ * @param name The persistence unit name, or null or blank for the
+ * anonymous persistence unit.
+ * @param resourceLoader The ClassLoader used to load the standard JDO
+ * configuration file.
+ * @param jdoconfigResourceName The name of the configuration file to read.
+ * In public usage, this should always be the value of
+ * {@link Constants#JDOCONFIG_RESOURCE_NAME}.
+ * @return The named PersistenceManagerFactory properties if found, null if
+ * not.
+ * @since 2.1
+ * @throws JDOFatalUserException if multiple persistence units are found
+ * with the given name, or any other exception is encountered.
+ */
+ protected static Map getPersistenceUnitProperties(
+ String name,
+ ClassLoader resourceLoader,
+ String jdoconfigResourceName
+ ) {
+ /* JDO 2.1:
+ Attempt to find & return named persistence unit here.
+ If name == null or name == "", then we're looking for the default PMF.
+
+ If we can't find it, this method returns null.
+ */
+ name = name == null ? "" : name.trim(); // for use as key in Maps
+
+ // key is PU name, value is Map of PU properties
+ Map/**/ propertiesByNameInAllConfigs
+ = new HashMap/**/();
try {
- in = propsLoader.getResourceAsStream (propsResource);
- if (in == null)
- throw new JDOFatalUserException (msg.msg (
- "EXC_GetPMFNoResource", propsResource, propsLoader)); //NOI18N
- props.load (in);
- } catch (IOException ioe) {
+ URL firstFoundConfigURL = null;
+
+ // get all JDO configurations
+ Enumeration resources =
+ resourceLoader.getResources(jdoconfigResourceName);
+
+ if (resources.hasMoreElements()) {
+
+ // get ready to parse XML
+ DocumentBuilderFactory factory = null;
+ // TODO: ensure DBF is initialized properly
+ factory = DocumentBuilderFactory.newInstance();
+ factory.setIgnoringComments(true);
+ factory.setNamespaceAware(true);
+ factory.setValidating(false);
+ factory.setIgnoringElementContentWhitespace(true);
+ factory.setExpandEntityReferences(true);
+
+ do {
+ URL currentConfigURL = (URL) resources.nextElement();
+ Map/**/ propertiesByNameInCurrentConfig =
+ readPersistenceUnitProperties(
+ currentConfigURL, name, factory);
+
+ // try to detect duplicate requested PU
+ if (propertiesByNameInCurrentConfig.containsKey(name)) {
+ // possible dup -- check for it
+ if (firstFoundConfigURL == null) {
+ firstFoundConfigURL = currentConfigURL;
+ }
+
+ if (propertiesByNameInAllConfigs.containsKey(name))
+ throw new JDOFatalUserException (msg.msg(
+ "EXC_DuplicateRequestedPUFoundInDifferentConfigs",
+ "".equals(name)
+ ? "(anonymous)"
+ : name,
+ firstFoundConfigURL.toExternalForm(),
+ currentConfigURL.toExternalForm())); //NOI18N
+ }
+ // no dups -- add found PUs to all PUs and keep going
+ propertiesByNameInAllConfigs
+ .putAll(propertiesByNameInCurrentConfig);
+ } while (resources.hasMoreElements());
+ }
+ }
+ catch (FactoryConfigurationError e) {
+ throw new JDOFatalUserException(
+ msg.msg("ERR_NoDocumentBuilderFactory"), e);
+ }
+ catch (IOException ioe) {
throw new JDOFatalUserException (msg.msg (
- "EXC_GetPMFIOExceptionRsrc", propsResource), ioe); //NOI18N
+ "EXC_GetPMFIOExceptionRsrc", name), ioe); //NOI18N
}
+
+ // done with reading all config resources;
+ // return what we found, which may very well be null
+ return (Map) propertiesByNameInAllConfigs.get(name);
+ }
+
+
+ /**
+ * Convenience method for retrieving the JPA persistence unit by the given
+ * name. This method is equivalent to
+ * calling {@link #getPMFFromEMF(String,ClassLoader)} with the context ClassLoader.
+ * @see {@link #getPMFFromEMF(String,ClassLoader)}
+ */
+ protected static PersistenceManagerFactory getPMFFromEMF(String name) {
+ return getPMFFromEMF(name, getContextClassLoader());
+ }
+
+ /**
+ * Attempts to locate a javax.persistence.EntityManagerFactory
+ * via the javax.persistence.Persistence method
+ * createEntityManagerFactory(String)
+ * and casts it to a {@link PersistenceManagerFactory}. It is a user error
+ * if his chosen JPA vendor's EntityManagerFactory
+ * implementation class does not also implement
+ * {@link PersistenceManagerFactory}.
+ * @param name The persistence unit name.
+ * @param loader The classloader used to attempt loading of the class
+ * javax.persistence.Persistence
+ * and javax.persistence.PersistenceException.
+ * @return The EntityManagerFactory, cast as a
+ * PersistenceManagerFactory for the given
+ * persistence unit name, or null if any of the following
+ * conditions are true.
+ *
+ * - The attempt to load
javax.persistence.Persistence or
+ * javax.persistence.Persistence fails for any
+ * reason.
+ * - The named JPA persistence unit is not found.
+ *
+ * @throws JDOFatalUserException This method will throw
+ * a {@link JDOFatalUserException}
+ * with the exception that caused the error
+ * if any of the following conditions are true.
+ *
+ * - The
javax.persistence.Persistence method
+ * createEntityManagerFactory(String)
+ * cannot be invoked.
+ * - The
javax.persistence.EntityManagerFactory cannot be
+ * cast to a
+ * {@link PersistenceManagerFactory}.
+ *
+ */
+ protected static PersistenceManagerFactory getPMFFromEMF(
+ String name, ClassLoader loader
+ ) {
+ /*
+ This implementation uses reflection to try to get an EMF so that
+ javax.jdo, a Java SE API, does not introduce an unnecessary
+ dependency on a Java EE API, namely the
+ javax.persistence.Persistence class, while still
+ being compatible with JPA.
+ */
+
+ // First, get required classes & methods
+ Class persistenceClass = null;
+ Class persistenceExceptionClass = null;
+ Method createEntityManagerFactoryMethod = null;
+ try {
+ persistenceClass = Class.forName(
+ "javax.persistence.Persistence",
+ true,
+ loader);
+
+ createEntityManagerFactoryMethod = persistenceClass.getMethod(
+ "createEntityManagerFactory",
+ new Class[] { String.class });
+
+ persistenceExceptionClass =
+ Class.forName(
+ "javax.persistence.PersistenceException",
+ true,
+ loader);
+ }
+ catch (Exception x) {
+ // may happen -- if it does, javax.persistence.Persistence or
+ // requisites not available
+ return null;
+ }
+
+ // Now, try to invoke createEntityManagerFactory method
+ Object entityManagerFactory = null;
+ Throwable t = null;
+ try {
+ entityManagerFactory =
+ createEntityManagerFactoryMethod.invoke(
+ persistenceClass, new Object[] { name });
+ }
+ catch (RuntimeException x) {
+ if (persistenceExceptionClass.isAssignableFrom(x.getClass())) {
+ // named persistence unit not found
+ return null;
+ }
+ // else something else went wrong
+ t = x;
+ }
+ catch (Exception x) {
+ t = x;
+ }
+ if (t != null) { // something went wrong -- throw
+ throw new JDOFatalUserException(
+ msg.msg("EXC_UnableToInvokeCreateEMFMethod"), t);
+ }
+
+ // Last, try to cast to PMF & return
+ try {
+ return (PersistenceManagerFactory) entityManagerFactory;
+ }
+ catch (ClassCastException x) { // EMF impl doesn't also implement PMF
+ throw new JDOFatalUserException(
+ msg.msg(
+ "EXC_UnableToCastEMFToPMF",
+ entityManagerFactory.getClass().getName()),
+ x);
+ }
+ }
+
+ /** Reads JDO configuration file, creates a Map for each
+ * persistence-manager-factory, then returns the map.
+ * @param url URL of a JDO configuration file compliant with
+ * javax/jdo/jdoconfig.xsd.
+ * @param requestedPersistenceUnitName The name of the requested
+ * persistence unit (allows for fail-fast).
+ * @param factory The DocumentBuilderFactory to use for XML
+ * parsing.
+ * @return a Map holding persistence unit configurations; for
+ * the anonymous persistence unit, the
+ * value of the String key is the empty string, "".
+ */
+ protected static Map/**/ readPersistenceUnitProperties(
+ URL url,
+ String requestedPersistenceUnitName,
+ DocumentBuilderFactory factory
+ ) {
+ requestedPersistenceUnitName = requestedPersistenceUnitName == null
+ ? ""
+ : requestedPersistenceUnitName.trim();
+
+ Map propertiesByName = new HashMap();
+ InputStream in = null;
+ try {
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ in = url.openStream();
+ Document doc = builder.parse(in);
+
+ Element root = doc.getDocumentElement();
+ if (root == null) {
+ throw new JDOFatalUserException(
+ msg.msg("EXC_InvalidJDOConfigNoRoot", url.toExternalForm())
+ );
+ }
+
+ // TODO: consider namespace?!?!
+ NodeList pmfs = root.getElementsByTagName(
+ ELEMENT_PERSISTENCE_MANAGER_FACTORY);
+
+ for(int i = 0; i < pmfs.getLength(); i++) {
+ Node pmfElement = pmfs.item(i);
+
+ Properties pmfPropertiesFromAttributes
+ = readPropertiesFromPMFElementAttributes(pmfElement);
+
+ Properties pmfPropertiesFromElements
+ = readPropertiesFromPMFSubelements(pmfElement, url);
+
+ // for informative error handling, get PU name (or names) now
+ String puNameFromAtts =
+ pmfPropertiesFromAttributes.getProperty(
+ PROPERTY_PERSISTENCE_UNIT_NAME);
+ String puNameFromElem =
+ pmfPropertiesFromElements.getProperty(
+ PROPERTY_PERSISTENCE_UNIT_NAME);
+
+ String puName = null;
+ if (nullOrBlank(puNameFromAtts)) {
+ // no PU name attribute given
+ if (!nullOrBlank(puNameFromElem)) {
+ // PU name element was given
+ puName = puNameFromElem;
+ }
+ else {
+ // PU name not given at all, means the "anonymous" PU
+ puName = "";
+ }
+ }
+ else {
+ // PU name given in an attribute
+ if (!nullOrBlank(puNameFromElem)) {
+ // exception -- PU name given as both att & elem
+ throw new JDOFatalUserException(
+ msg.msg(
+ "EXC_DuplicatePersistenceUnitNamePropertyFoundWithinUnitConfig",
+ puNameFromAtts,
+ puNameFromElem,
+ url.toExternalForm()));
+ }
+ puName = puNameFromAtts;
+ }
+ puName = puName == null ? "" : puName.trim();
+
+ // check for duplicate properties among atts & elems
+ if (requestedPersistenceUnitName.equals(puName)) {
+ Iterator it =
+ pmfPropertiesFromAttributes.keySet().iterator();
+ while (it.hasNext()) {
+ String property = (String) it.next();
+ if (pmfPropertiesFromElements.contains(property)) {
+ throw new JDOFatalUserException(
+ msg.msg(
+ "EXC_DuplicatePropertyFound",
+ property,
+ puName,
+ url.toExternalForm()));
+ }
+ }
+ }
+
+ // at this point, we're guaranteed not to have duplicate
+ // properties -- merge them
+ Properties pmfProps = new Properties();
+ pmfProps.putAll(pmfPropertiesFromAttributes);
+ pmfProps.putAll(pmfPropertiesFromElements);
+
+ // check for duplicate requested PU name
+ if (puName.equals(requestedPersistenceUnitName)
+ && propertiesByName.containsKey(puName)) {
+
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_DuplicateRequestedPersistenceUnitFoundInSameConfig",
+ puName,
+ url.toExternalForm()));
+ }
+ propertiesByName.put(puName, pmfProps);
+ }
+ return propertiesByName;
+ }
+ catch (IOException ioe) {
+ throw new JDOFatalUserException(
+ msg.msg("EXC_GetPMFIOExceptionRsrc", url.toString()),
+ ioe); //NOI18N
+ }
+ catch (ParserConfigurationException e) {
+ throw new JDOFatalUserException(
+ msg.msg("EXC_ParserConfigException"),
+ e);
+ }
+ catch (SAXException e) {
+ throw new JDOFatalUserException(
+ msg.msg("EXC_ParsingException", url.toExternalForm()),
+ e);
+ }
+ catch (JDOException e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ throw new JDOFatalUserException(
+ msg.msg("EXC_ParsingException", url.toExternalForm()),
+ e);
+ }
finally {
- if (in != null)
+ if (in != null) {
try {
- in.close ();
- } catch (IOException ioe) { }
+ in.close();
+ }
+ catch (IOException ioe) { /* gulp */ }
+ }
}
+ }
- return getPersistenceManagerFactory (props, pmfLoader);
+ protected static Properties readPropertiesFromPMFElementAttributes(
+ Node pmfElement
+ ) {
+ Properties p = new Properties();
+ NamedNodeMap attributes = pmfElement.getAttributes();
+ if (attributes == null) {
+ return p;
+ }
+
+ for(int i = 0; i < attributes.getLength(); i++) {
+ Node att = attributes.item(i);
+ String attName = att.getNodeName();
+ String attValue = att.getNodeValue().trim();
+
+ String jdoPropertyName =
+ (String) ATTRIBUTE_PROPERTY_XREF.get(attName);
+
+ p.put(
+ jdoPropertyName != null
+ ? jdoPropertyName
+ : attName,
+ attValue);
+ }
+
+ return p;
}
+ protected static Properties readPropertiesFromPMFSubelements(
+ Node pmfElement, URL url)
+ {
+ Properties p = new Properties();
+ NodeList elements = pmfElement.getChildNodes();
+ if (elements == null) {
+ return p;
+ }
+ for(int i = 0; i < elements.getLength(); i++) {
+ Node element = elements.item(i);
+ if (element.getNodeType() != Node.ELEMENT_NODE) {
+ continue;
+ }
+
+ String elementName = element.getNodeName();
+ NamedNodeMap attributes = element.getAttributes();
+ if (ELEMENT_PROPERTY.equalsIgnoreCase(elementName)) {
+ //
+ // get the "name" attribute's value (required)
+ Node nameAtt = attributes.getNamedItem(PROPERTY_ATTRIBUTE_NAME);
+ if (nameAtt == null) {
+ throw new JDOFatalUserException(
+ msg.msg("EXC_PropertyElementHasNoNameAttribute", url));
+ }
+ String name = nameAtt.getNodeValue().trim();
+ if ("".equals(name)) {
+ throw new JDOFatalUserException(
+ msg.msg(
+ "EXC_PropertyElementNameAttributeHasNoValue",
+ name,
+ url));
+ }
+ // The next call allows users to use either the
+ // attribute names or the
+ // "javax.jdo" property names in element "name"
+ // attributes. Handy-dandy.
+ String jdoPropertyName =
+ (String) ATTRIBUTE_PROPERTY_XREF.get(name);
+
+ String propertyName = jdoPropertyName != null
+ ? jdoPropertyName
+ : name;
+
+ if (p.containsKey(propertyName)) {
+ throw new JDOFatalUserException(
+ msg.msg(
+ "EXC_DuplicatePropertyNameGivenInPropertyElement",
+ propertyName,
+ url));
+ }
+
+ // get the "value" attribute's value (optional)
+ Node valueAtt = attributes.getNamedItem(
+ PROPERTY_ATTRIBUTE_VALUE);
+ String value = valueAtt == null
+ ? null
+ : valueAtt.getNodeValue().trim();
+
+ p.put(propertyName, value);
+ }
+ else if (ELEMENT_INSTANCE_LIFECYCLE_LISTENER.equals(elementName)) {
+ //
+
+ // get the "listener" attribute's value
+ Node listenerAtt = attributes.getNamedItem(
+ INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_LISTENER);
+ if (listenerAtt == null) {
+ throw new JDOFatalUserException(
+ msg.msg(
+ "EXC_MissingListenerAttribute",
+ url));
+ }
+ String listener = listenerAtt.getNodeValue().trim();
+ if ("".equals(listener)) {
+ throw new JDOFatalUserException(
+ msg.msg(
+ "EXC_MissingListenerAttributeValue",
+ url));
+ }
+
+ // listener properties are of the form
+ // "javax.jdo.option.InstanceLifecycleListener." + listener
+ listener =
+ PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER + listener;
+
+ // get the "classes" attribute's value (optional)
+ Node classesAtt = attributes.getNamedItem(
+ INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_CLASSES);
+ String value = classesAtt == null
+ ? null
+ : classesAtt.getNodeValue().trim();
+
+ p.put(listener, value);
+ }
+ }
+ return p;
+ }
+
+ protected static boolean nullOrBlank(String s) {
+ return s == null || "".equals(s.trim());
+ }
+
/**
* Returns a {@link PersistenceManagerFactory} configured based
* on the properties stored in the file at
Index: src/java/javax/jdo/Constants.java
===================================================================
--- src/java/javax/jdo/Constants.java (revision 0)
+++ src/java/javax/jdo/Constants.java (revision 0)
@@ -0,0 +1,667 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package javax.jdo;
+
+/**
+ * Constant values used in JDO.
+ * @since 2.1
+ */
+public interface Constants {
+
+ /**
+ * The name of the standard JDO configuration resource file(s).
+ * @since 2.1
+ */
+ static String JDOCONFIG_RESOURCE_NAME =
+ "META-INF/jdoconfig.xml";
+
+ /**
+ * The standard JDO configuration schema namespace.
+ * @since 2.1
+ */
+ static String JDOCONFIG_XSD_NS =
+ "http://java.sun.com/xml/ns/jdo/jdoconfig";
+
+ /**
+ * The name of the persitence manager factory element in the JDO
+ * configuration file.
+ * @since 2.1
+ */
+ static String ELEMENT_PERSISTENCE_MANAGER_FACTORY
+ = "persistence-manager-factory";
+
+ /**
+ * The name of the persitence manager factory element's "class" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_CLASS
+ = "class";
+ /**
+ * The name of the persitence manager factory element's
+ * "persistence-unit-name" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_PERSISTENCE_UNIT_NAME
+ = "persistence-unit-name";
+ /**
+ * The name of the persitence manager factory element's "optimistic"
+ * attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_OPTIMISTIC
+ = "optimistic";
+ /**
+ * The name of the persitence manager factory element's "retain-values"
+ * attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_RETAIN_VALUES
+ = "retain-values";
+ /**
+ * The name of the persitence manager factory element's "restore-values"
+ * attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_RESTORE_VALUES
+ = "restore-values";
+ /**
+ * The name of the persitence manager factory element's "ignore-cache"
+ * attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_IGNORE_CACHE
+ = "ignore-cache";
+ /**
+ * The name of the persitence manager factory element's
+ * "nontransactional-read" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_NONTRANSACTIONAL_READ
+ = "nontransactional-read";
+ /**
+ * The name of the persitence manager factory element's
+ * "nontransactional-write" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_NONTRANSACTIONAL_WRITE
+ = "nontransactional-write";
+ /**
+ * The name of the persitence manager factory element's "multithreaded"
+ * attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_MULTITHREADED
+ = "multithreaded";
+ /**
+ * The name of the persitence manager factory element's
+ * "connection-driver-name" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_CONNECTION_DRIVER_NAME
+ = "connection-driver-name";
+ /**
+ * The name of the persitence manager factory element's
+ * "connection-user-name" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_CONNECTION_USER_NAME
+ = "connection-user-name";
+ /**
+ * The name of the persitence manager factory element's
+ * "connection-password" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_CONNECTION_PASSWORD
+ = "connection-password";
+ /**
+ * The name of the persitence manager factory element's "connection-url"
+ * attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_CONNECTION_URL
+ = "connection-url";
+ /**
+ * The name of the persitence manager factory element's "connection-factory-name" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_CONNECTION_FACTORY_NAME
+ = "connection-factory-name";
+ /**
+ * The name of the persitence manager factory element's "connection-factory2-name" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_CONNECTION_FACTORY2_NAME
+ = "connection-factory2-name";
+ /**
+ * The name of the persitence manager factory element's "detach-all-on-commit" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_DETACH_ALL_ON_COMMIT
+ = "detach-all-on-commit";
+ /**
+ * The name of the persitence manager factory element's "mapping" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_MAPPING
+ = "mapping";
+ /**
+ * The name of the persitence manager factory element's "mapping" attribute.
+ * @since 2.1
+ */
+ static String PMF_ATTRIBUTE_SERVERTIMEZONEID
+ = "server-timezone-id";
+
+ /**
+ * The name of the persitence manager factory property elements in the JDO
+ * configuration file.
+ */
+ static String ELEMENT_PROPERTY
+ = "property";
+ /**
+ * The name of the persitence manager factory property element's "name"
+ * attribute.
+ */
+ static String PROPERTY_ATTRIBUTE_NAME
+ = "name";
+ /**
+ * The name of the persitence manager factory property element's "value"
+ * attribute.
+ */
+ static String PROPERTY_ATTRIBUTE_VALUE
+ = "value";
+
+ /**
+ * The name of the instance lifecycle listener element in the JDO
+ * configuration file.
+ */
+ static String ELEMENT_INSTANCE_LIFECYCLE_LISTENER
+ = "instance-lifecycle-listener";
+
+ /**
+ * The name of the instance lifecycle listener element's "listener"
+ * attribute.
+ */
+ static String INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_LISTENER
+ = "listener";
+ /**
+ * The name of the instance lifecycle listener element's "classes"
+ * attribute.
+ */
+ static String INSTANCE_LIFECYCLE_LISTENER_ATTRIBUTE_CLASSES
+ = "classes";
+
+ /**
+ * "javax.jdo.option.TransientTransactional"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_TRANSACTIONAL_TRANSIENT
+ = "javax.jdo.option.TransientTransactional";
+ /**
+ * "javax.jdo.option.NontransactionalRead"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_NONTRANSACTIONAL_READ
+ = "javax.jdo.option.NontransactionalRead";
+ /**
+ * "javax.jdo.option.NontransactionalWrite"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_NONTRANSACTIONAL_WRITE
+ = "javax.jdo.option.NontransactionalWrite";
+ /**
+ * "javax.jdo.option.RetainValues"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_RETAIN_VALUES
+ = "javax.jdo.option.RetainValues";
+ /**
+ * "javax.jdo.option.Optimistic"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_OPTIMISTIC
+ = "javax.jdo.option.Optimistic";
+ /**
+ * "javax.jdo.option.ApplicationIdentity"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_APPLICATION_IDENTITY
+ = "javax.jdo.option.ApplicationIdentity";
+ /**
+ * "javax.jdo.option.DatastoreIdentity"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_DATASTORE_IDENTITY
+ = "javax.jdo.option.DatastoreIdentity";
+ /**
+ * "javax.jdo.option.NonDurableIdentity"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_NONDURABLE_IDENTITY
+ = "javax.jdo.option.NonDurableIdentity";
+ /**
+ * "javax.jdo.option.ArrayList"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_ARRAYLIST
+ = "javax.jdo.option.ArrayList";
+ /**
+ * "javax.jdo.option.LinkedList"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_LINKEDLIST
+ = "javax.jdo.option.LinkedList";
+ /**
+ * "javax.jdo.option.TreeMap"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_TREEMAP
+ = "javax.jdo.option.TreeMap";
+ /**
+ * "javax.jdo.option.TreeSet"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_TREESET
+ = "javax.jdo.option.TreeSet";
+ /**
+ * "javax.jdo.option.Vector"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_VECTOR
+ = "javax.jdo.option.Vector";
+ /**
+ * "javax.jdo.option.Array"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_ARRAY
+ = "javax.jdo.option.Array";
+ /**
+ * "javax.jdo.option.NullCollection"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_NULL_COLLECTION
+ = "javax.jdo.option.NullCollection";
+ /**
+ * "javax.jdo.option.ChangeApplicationIdentity"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_CHANGE_APPLICATION_IDENTITY
+ = "javax.jdo.option.ChangeApplicationIdentity";
+ /**
+ * "javax.jdo.option.BinaryCompatibility"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_BINARY_COMPATIBILITY
+ = "javax.jdo.option.BinaryCompatibility";
+ /**
+ * "javax.jdo.option.GetDataStoreConnection"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_GET_DATASTORE_CONNECTION
+ = "javax.jdo.option.GetDataStoreConnection";
+ /**
+ * "javax.jdo.option.GetJDBCConnection"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_GET_JDBC_CONNECTION
+ = "javax.jdo.option.GetJDBCConnection";
+ /**
+ * "javax.jdo.query.SQL"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_QUERY_SQL
+ = "javax.jdo.query.SQL";
+ /**
+ * "javax.jdo.option.UnconstrainedQueryVariables"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_UNCONSTRAINED_QUERY_VARIABLES
+ = "javax.jdo.option.UnconstrainedQueryVariables";
+ /**
+ * "javax.jdo.option.version.DateTime"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_VERSION_DATETIME
+ = "javax.jdo.option.version.DateTime";
+ /**
+ * "javax.jdo.option.version.StateImage"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_VERSION_STATE_IMAGE
+ = "javax.jdo.option.version.StateImage";
+ /**
+ * "javax.jdo.option.PreDirtyEvent"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_PREDIRTY_EVENT
+ = "javax.jdo.option.PreDirtyEvent";
+ /**
+ * "javax.jdo.option.mapping.HeterogeneousObjectType"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_MAPPING_HETEROGENEOUS_OBJECT_TYPE
+ = "javax.jdo.option.mapping.HeterogeneousObjectType";
+ /**
+ * "javax.jdo.option.mapping.HeterogeneousInterfaceType"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_MAPPING_HETEROGENEOUS_INTERFACE_TYPE
+ = "javax.jdo.option.mapping.HeterogeneousInterfaceType";
+ /**
+ * "javax.jdo.option.mapping.JoinedTablePerClass"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_MAPPING_JOINED_TABLE_PER_CLASS
+ = "javax.jdo.option.mapping.JoinedTablePerClass";
+ /**
+ * "javax.jdo.option.mapping.JoinedTablePerConcreteClass"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_MAPPING_JOINED_TABLE_PER_CONCRETE_CLASS
+ = "javax.jdo.option.mapping.JoinedTablePerConcreteClass";
+ /**
+ * "javax.jdo.option.mapping.NonJoinedTablePerConcreteClass"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_MAPPING_NON_JOINED_TABLE_PER_CONCRETE_CLASS
+ = "javax.jdo.option.mapping.NonJoinedTablePerConcreteClass";
+ /**
+ * "javax.jdo.option.mapping.RelationSubclassTable"
+ * @see {@link PersistenceManagerFactory#supportedOptions()}
+ * @since 2.1
+ */
+ static String OPTION_MAPPING_RELATION_SUBCLASS_TABLE
+ = "javax.jdo.option.mapping.RelationSubclassTable";
+
+ /**
+ * "javax.jdo.PersistenceManagerFactoryClass"
+ * @see {@link JDOHelper#getPersistenceManagerFactory(java.util.Map)}
+ * @since 2.1
+ */
+ static String PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS
+ = "javax.jdo.PersistenceManagerFactoryClass";
+
+ /**
+ * "javax.jdo.option.Optimistic"
+ * @see {@link PersistenceManagerFactory#getOptimistic()}
+ * @since 2.1
+ */
+ static String PROPERTY_OPTIMISTIC
+ = "javax.jdo.option.Optimistic";
+ /**
+ * "javax.jdo.option.RetainValues"
+ * @see {@link PersistenceManagerFactory#getRetainValues()}
+ * @since 2.1
+ */
+ static String PROPERTY_RETAIN_VALUES
+ = "javax.jdo.option.RetainValues";
+ /**
+ * "javax.jdo.option.RestoreValues"
+ * @see {@link PersistenceManagerFactory#getRestoreValues()}
+ * @since 2.1
+ */
+ static String PROPERTY_RESTORE_VALUES
+ = "javax.jdo.option.RestoreValues";
+ /**
+ * "javax.jdo.option.IgnoreCache"
+ * @see {@link PersistenceManagerFactory#getIgnoreCache()}
+ * @since 2.1
+ */
+ static String PROPERTY_IGNORE_CACHE
+ = "javax.jdo.option.IgnoreCache";
+ /**
+ * "javax.jdo.option.NontransactionalRead"
+ * @see {@link PersistenceManagerFactory#getNontransactionalRead()}
+ * @since 2.1
+ */
+ static String PROPERTY_NONTRANSACTIONAL_READ
+ = "javax.jdo.option.NontransactionalRead";
+ /**
+ * "javax.jdo.option.NontransactionalWrite"
+ * @see {@link PersistenceManagerFactory#getNontransactionalWrite()}
+ * @since 2.1
+ */
+ static String PROPERTY_NONTRANSACTIONAL_WRITE
+ = "javax.jdo.option.NontransactionalWrite";
+ /**
+ * "javax.jdo.option.Multithreaded"
+ * @see {@link PersistenceManagerFactory#getMultithreaded()}
+ * @since 2.1
+ */
+ static String PROPERTY_MULTITHREADED
+ = "javax.jdo.option.Multithreaded";
+ /**
+ * "javax.jdo.option.DetachAllOnCommit"
+ * @see {@link PersistenceManagerFactory#getDetachAllOnCommit()}
+ * @since 2.1
+ */
+ static String PROPERTY_DETACH_ALL_ON_COMMIT
+ = "javax.jdo.option.DetachAllOnCommit";
+ /**
+ * "javax.jdo.option.ConnectionDriverName"
+ * @see {@link PersistenceManagerFactory#getConnectionDriverName()}
+ * @since 2.1
+ */
+ static String PROPERTY_CONNECTION_DRIVER_NAME
+ = "javax.jdo.option.ConnectionDriverName";
+ /**
+ * "javax.jdo.option.ConnectionUserName"
+ * @see {@link PersistenceManagerFactory#getConnectionUserName()}
+ * @since 2.1
+ */
+ static String PROPERTY_CONNECTION_USER_NAME
+ = "javax.jdo.option.ConnectionUserName";
+ /**
+ * "javax.jdo.option.Password"
+ * @since 2.1
+ */
+ static String PROPERTY_CONNECTION_PASSWORD
+ = "javax.jdo.option.ConnectionPassword";
+ /**
+ * "javax.jdo.option.ConnectionURL"
+ * @see {@link PersistenceManagerFactory#getConnectionURL()}
+ * @since 2.1
+ */
+ static String PROPERTY_CONNECTION_URL
+ = "javax.jdo.option.ConnectionURL";
+ /**
+ * "javax.jdo.option.ConnectionFactoryName"
+ * @see {@link PersistenceManagerFactory#getConnectionFactoryName()}
+ * @since 2.1
+ */
+ static String PROPERTY_CONNECTION_FACTORY_NAME
+ = "javax.jdo.option.ConnectionFactoryName";
+ /**
+ * "javax.jdo.option.ConnectionFactory2Name"
+ * @see {@link PersistenceManagerFactory#getConnectionFactory2Name()}
+ * @since 2.1
+ */
+ static String PROPERTY_CONNECTION_FACTORY2_NAME
+ = "javax.jdo.option.ConnectionFactory2Name";
+ /**
+ * "javax.jdo.option.Mapping"
+ * @see {@link PersistenceManagerFactory#getMapping()}
+ * @since 2.1
+ */
+ static String PROPERTY_MAPPING
+ = "javax.jdo.option.Mapping";
+ /**
+ * "javax.jdo.option.PersistenceUnitName"
+ * @see {@link PersistenceManagerFactory#getPersistenceUnitName()}
+ * @since 2.1
+ */
+ static String PROPERTY_PERSISTENCE_UNIT_NAME
+ = "javax.jdo.option.PersistenceUnitName";
+
+ /**
+ * Prefix used to configure
+ * {@link javax.jdo.listener.InstanceLifecycleListener} instances
+ * externally.
+ * To configure an InstanceLifecycleListener via properties,
+ * create a property name with the prefix of
+ * this constant and append the fully qualified listener class name, then
+ * set its value to the comma- or whitespace-delimited list
+ * of persistence-capable classes whose instances are to be observed.
+ * Use no value to indicate that instances of
+ * all persistence-capable classes are to be observed.
+ * For example,
+ * javax.jdo.option.InstanceLifecycleListener.com.example.MyListener=com.example.Foo,com.example.Bar
+ * is equivalent to calling
+ * pmf.addInstanceLifecycleListener(new com.example.MyListener(), new Class[] {com.example.Foo.class, com.example.Bar.class});
+ * where pmf is an instance of type
+ * PersistenceManagerFactory.
+ * @see {@link javax.jdo.PersistenceManagerFactory#addInstanceLifecycleListener(javax.jdo.listener.InstanceLifecycleListener,Class[])}
+ * @since 2.1
+ */
+ static String PROPERTY_PREFIX_INSTANCE_LIFECYCLE_LISTENER
+ = "javax.jdo.option.InstanceLifecycleListener.";
+
+ /**
+ * Mapping "javax.jdo.mapping.Catalog"
+ * @since 2.1
+ */
+ static String PROPERTY_MAPPING_CATALOG
+ = "javax.jdo.mapping.Catalog";
+ /**
+ * Mapping "javax.jdo.mapping.Schema"
+ * @since 2.1
+ */
+ static String PROPERTY_MAPPING_SCHEMA
+ = "javax.jdo.mapping.Schema";
+
+ /**
+ * Mapping "javax.jdo.option.ServerTimeZoneID"
+ * @since 2.1
+ */
+ static String PROPERTY_SERVER_TIMEZONE_ID
+ = "javax.jdo.option.ServerTimeZoneID";
+
+ /**
+ * Nonconfigurable property constanct "VendorName"
+ * @see {@link PersistenceManagerFactory#getProperties()}
+ * @since 2.1
+ */
+ static String NONCONFIGURABLE_PROPERTY_VENDOR_NAME
+ = "VendorName";
+ /**
+ * Nonconfigurable property constanct "VersionNumber"
+ * @see {@link PersistenceManagerFactory#getProperties()}
+ * @since 2.1
+ */
+ static String NONCONFIGURABLE_PROPERTY_VERSION_NUMBER
+ = "VersionNumber";
+
+ /**
+ * The value for TransactionType to specify that transactions
+ * are managed by the Java Transactions API, as documented in
+ * JSR-220.
+ * @since 2.1
+ */
+ static String JTA = "JTA";
+
+ /**
+ * The value for TransactionType to specify that transactions
+ * are managed by the javax.jdo.Transaction instance, similar
+ * to the usage as documented in JSR-220.
+ * @since 2.1
+ */
+ static String RESOURCE_LOCAL = "RESOURCE_LOCAL";
+
+ /**
+ * The name of the resource for the DTD of the standard JDO configuration
+ * file.
+ * @since 2.1
+ */
+ static String JDOCONFIG_DTD_RESOURCE = "javax/jdo/jdoconfig_2_1.dtd";
+
+ /**
+ * The name of the resource for the XML schema of the standard JDO
+ * configuration file.
+ * @since 2.1
+ */
+ static String JDOCONFIG_XSD_RESOURCE = "javax/jdo/jdoconfig_2_1.xsd";
+
+ /**
+ * The name of the resource for the DTD of the standard JDO metadata file.
+ * @since 2.1
+ */
+ static String JDO_DTD_RESOURCE = "javax/jdo/jdo_2_0.dtd";
+
+ /**
+ * The name of the resource for the XML schema of the standard JDO
+ * metadata file.
+ * @since 2.1
+ */
+ static String JDO_XSD_RESOURCE = "javax/jdo/jdo_2_0.xsd";
+
+ /**
+ * The name of the resource for the DTD of the standard JDO
+ * object-relational mapping metadata file.
+ * @since 2.1
+ */
+ static String ORM_DTD_RESOURCE = "javax/jdo/orm_2_0.dtd";
+
+ /**
+ * The name of the resource for the XML schema of the standard JDO
+ * object-relational mapping metadata file.
+ * @since 2.1
+ */
+ static String ORM_XSD_RESOURCE = "javax/jdo/orm_2_0.xsd";
+
+ /**
+ * The name of the resource for the DTD of the standard JDO query
+ * metadata file.
+ * @since 2.1
+ */
+ static String JDOQUERY_DTD_RESOURCE = "javax/jdo/jdoquery_2_0.dtd";
+
+ /**
+ * The name of the resource for the XML schema of the standard JDO query
+ * metadata file.
+ * @since 2.1
+ */
+ static String JDOQUERY_XSD_RESOURCE = "javax/jdo/jdoquery_2_0.xsd";
+}
Index: src/java/javax/jdo/Bundle.properties
===================================================================
--- src/java/javax/jdo/Bundle.properties (revision 513879)
+++ src/java/javax/jdo/Bundle.properties (working copy)
@@ -77,3 +77,34 @@
EXC_DateStringConstructor: Error parsing Date string "{0}" at position {1} \
using date format "{2}".
MSG_unknown: unknown
+EXC_DuplicateRequestedPUFoundInDifferentConfigs: Duplicate persistence unit \
+name "{0}" found in {1} and {2}.
+EXC_DuplicateRequestedPersistenceUnitFoundInSameConfig: Duplicate persistence \
+unit name "{0}" found in {1}.
+EXC_UnableToInvokeCreateEMFMethod: Unable to invoke \
+javax.persistence.Persistence.createEntityManagerFactory(String)
+EXC_UnableToCastEMFToPMF: Unable to cast EntityManagerFactory class {0} \
+to javax.jdo.PersistenceManagerFactory
+ERR_NoDocumentBuilderFactory: Unable to instantiate \
+javax.xml.parsers.DocumentBuilderFactory
+EXC_ParserConfigException: Encountered parser configuration exception while \
+getting javax.xml.parsers.DocumentBuilder
+EXC_ParsingException: Exception parsing configuration {0}
+EXC_DuplicatePropertyFound: Duplicate property name "{0}" found in persistence \
+unit name "{1}" found in {2}.
+EXC_DuplicatePersistenceUnitNamePropertyFoundWithinUnitConfig: Duplicate \
+persistence unit name found in {2}: attribute is "{0}", element is "{1}"
+EXC_PropertyElementHasNoNameAttribute: Found element with no \
+"name" attribute in {0}
+EXC_PropertyElementNameAttributeHasNoValue: Found element name \
+attribute "{0}" with no value in {1}
+EXC_DuplicatePropertyNameGivenInPropertyElement: Duplicate property name given \
+in property element: name {0} in {1}
+EXC_MissingListenerAttribute: Required \
+attribute "listener" missing in {0}
+EXC_MissingListenerAttributeValue: attribute \
+"listener" missing value in {0}
+EXC_InvalidJDOConfigNoRoot: No root element found in {0}
+EXC_NoPMFConfigurableViaPropertiesOrXML: No PersistenceManagerFactory \
+configurable via properties resource "{0}" or no persistence unit named "{0}" \
+found using resource loader {1}