Index: test/schema/jdoconfig.xml/Positive3/META-INF/jdoconfig.xml =================================================================== --- test/schema/jdoconfig.xml/Positive3/META-INF/jdoconfig.xml (revision 0) +++ test/schema/jdoconfig.xml/Positive3/META-INF/jdoconfig.xml (working copy) @@ -8,10 +8,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig"> - + - - - Index: test/schema/jdoconfig.xml/Positive3/META-INF/services/javax.jdo.PersistenceManagerFactory =================================================================== --- test/schema/jdoconfig.xml/Positive3/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) +++ test/schema/jdoconfig.xml/Positive3/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) @@ -0,0 +1 @@ +class.positive3.pmf0 \ No newline at end of file Index: test/schema/jdoconfig.xml/Positive4/META-INF/jdoconfig.xml =================================================================== --- test/schema/jdoconfig.xml/Positive4/META-INF/jdoconfig.xml (revision 0) +++ test/schema/jdoconfig.xml/Positive4/META-INF/jdoconfig.xml (revision 0) @@ -0,0 +1,13 @@ + + + + + + + Index: test/schema/jdoconfig.xml/Positive4/META-INF/services/javax.jdo.PersistenceManagerFactory =================================================================== --- test/schema/jdoconfig.xml/Positive4/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) +++ test/schema/jdoconfig.xml/Positive4/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) @@ -0,0 +1,3 @@ + +#this is a comment +class.positive4.pmf0 # this is another comment \ No newline at end of file Index: test/schema/jdoconfig.xml/Positive5/META-INF/jdoconfig.xml =================================================================== --- test/schema/jdoconfig.xml/Positive5/META-INF/jdoconfig.xml (revision 0) +++ test/schema/jdoconfig.xml/Positive5/META-INF/jdoconfig.xml (revision 0) @@ -0,0 +1,13 @@ + + + + + + + Index: test/schema/jdoconfig.xml/Positive5/META-INF/services/javax.jdo.PersistenceManagerFactory =================================================================== --- test/schema/jdoconfig.xml/Positive5/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) +++ test/schema/jdoconfig.xml/Positive5/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) @@ -0,0 +1 @@ +class.positive5.pmf0# this is a comment without whitespace separating it from the uncommented text \ No newline at end of file Index: test/schema/jdoconfig.xml/Negative7/META-INF/services/javax.jdo.PersistenceManagerFactory =================================================================== Index: test/schema/jdoconfig.xml/Negative8/META-INF/services/javax.jdo.PersistenceManagerFactory =================================================================== --- test/schema/jdoconfig.xml/Negative8/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) +++ test/schema/jdoconfig.xml/Negative8/META-INF/services/javax.jdo.PersistenceManagerFactory (revision 0) @@ -0,0 +1,3 @@ +# there are +# only comments +# in this file \ No newline at end of file Index: test/java/javax/jdo/JDOConfigTestClassLoader.java =================================================================== --- test/java/javax/jdo/JDOConfigTestClassLoader.java (revision 0) +++ test/java/javax/jdo/JDOConfigTestClassLoader.java (revision 0) @@ -0,0 +1,34 @@ +package javax.jdo; + +import java.net.URL; +import java.net.URLClassLoader; + +/** + * A class loader used to ensure that classpath URLs added in JUnit tests + * aren't included in subsequent JUnit tests. + */ +public class JDOConfigTestClassLoader extends URLClassLoader { + + public JDOConfigTestClassLoader(String partialPathToIgnore, URLClassLoader unparent) { + this(new String[]{partialPathToIgnore}, unparent); + } + + public JDOConfigTestClassLoader(String[] partialPathsToIgnore, URLClassLoader unparent) { + super(new URL[]{}, null); + addNonTestURLs(partialPathsToIgnore == null ? new String[]{} : partialPathsToIgnore, unparent); + } + + // HACK: need to identify a better way of controlling test classpath + protected void addNonTestURLs(String[] partialPathsToIgnore, URLClassLoader unparent) { + URL[] urls = unparent.getURLs(); + for (int i = 0; i < urls.length; i++) { + URL url = urls[i]; + String urlString = url.toString(); + for (int j = 0; j < partialPathsToIgnore.length; j++) { + if (urlString.indexOf(partialPathsToIgnore[j]) == -1) { + addURL(url); + } + } + } + } +} Index: test/java/javax/jdo/JDOHelperConfigTest.java =================================================================== --- test/java/javax/jdo/JDOHelperConfigTest.java (revision 541701) +++ test/java/javax/jdo/JDOHelperConfigTest.java (working copy) @@ -21,12 +21,13 @@ import javax.jdo.util.AbstractTest; import javax.jdo.util.BatchTestRunner; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; -import java.util.Iterator; import java.util.Random; -import java.io.InputStream; -import java.io.IOException; +import java.net.URLClassLoader; /** * Tests class javax.jdo.JDOHelper for META-INF/jdoconfig.xml compliance. @@ -51,12 +52,13 @@ * Positive0-jdoconfig.xml and PU name * "persistence-unit-name.positive0.pmf0" */ - public void testGetNamedPMFProperties_positive0_pmf0() throws IOException { + public void testPositive00_PMF0_GetNamedPMFProperties() throws IOException { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0", loader); - ClassLoader loader = getClass().getClassLoader(); - Map expected = prepareInitialExpectedMap("positive0.pmf0", 2); String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME); @@ -71,11 +73,12 @@ * Positive0-jdoconfig.xml and PU name * "persistence-unit-name.positive0.pmf1" */ - public void testGetNamedPMFProperties_positive0_pmf1() throws IOException { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0"); + public void testPositive00_PMF1_GetNamedPMFProperties() throws IOException { + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0", loader); - ClassLoader loader = getClass().getClassLoader(); - Map expected = prepareInitialExpectedMap("positive0.pmf1", 2); String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME); @@ -90,11 +93,12 @@ * Positive0-jdoconfig.xml and PU name * "persistence-unit-name.positive0.pmf2" */ - public void testGetNamedPMFProperties_positive0_pmf2() throws IOException { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0"); + public void testPositive00_PMF2_GetNamedPMFProperties() throws IOException { + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0", loader); - ClassLoader loader = getClass().getClassLoader(); - Map expected = prepareInitialExpectedMap("positive0.pmf2", 2); String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME); @@ -109,11 +113,12 @@ * Positive0-jdoconfig.xml and PU name * "persistence-unit-name.positive0.pmf3" */ - public void testGetNamedPMFProperties_positive0_pmf3() throws IOException { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0"); + public void testPositive00_PMF3_GetNamedPMFProperties() throws IOException { + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0", loader); - ClassLoader loader = getClass().getClassLoader(); - Map expected = prepareInitialExpectedMap("positive0.pmf3", 2, 2); String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME); @@ -128,11 +133,12 @@ * Positive0-jdoconfig.xml and PU name * "persistence-unit-name.positive0.pmf4" */ - public void testGetNamedPMFProperties_positive0_pmf4() throws IOException { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0"); + public void testPositive00_PMF4_GetNamedPMFProperties() throws IOException { + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive0", loader); - ClassLoader loader = getClass().getClassLoader(); - Map expected = prepareInitialExpectedMap("positive0.pmf4", 0, 2); String name = (String) expected.get(PROPERTY_PERSISTENCE_UNIT_NAME); @@ -251,18 +257,70 @@ * Positive0-jdoconfig.xml and PU name * "persistence-unit-name.positive0.pmf0" */ - public void testDuplicatePUsInDifferentConfigFilesButNotRequested_positive1() throws IOException { + public void testPostiive01_DuplicatePUsInDifferentConfigFilesButNotRequested() throws IOException { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive1/1a"); - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive1/1b"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive1/1a", loader); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive1/1b", loader); - ClassLoader loader = getClass().getClassLoader(); - - Map props = JDOHelper.getPersistenceUnitProperties(null); + Map props = JDOHelper.getPersistenceUnitProperties(null, loader); assertNotNull(props); } - public void testNegative_NoResourcesFound() { + /** + * Tests JDOHelper.getPMFClassNameViaServiceLookup + */ + public void testPositive03_PMF0_PMFClassNameViaServicesLookup() throws IOException { + + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive3", loader); + + String expected = "class.positive3.pmf0"; + String actual = JDOHelper.getPMFClassNameViaServiceLookup(loader); + + assertNotNull("No PMF name found via services lookup", actual); + assertEquals(expected, actual); + } + + /** + * Tests JDOHelper.getPMFClassNameViaServiceLookup + */ + public void testPositive04_PMF0_PMFClassNameViaServicesLookup() throws IOException { + + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive4", loader); + + String expected = "class.positive4.pmf0"; + String actual = JDOHelper.getPMFClassNameViaServiceLookup(loader); + + assertNotNull("No PMF name found via services lookup", actual); + assertEquals(expected, actual); + } + + /** + * Tests JDOHelper.getPMFClassNameViaServiceLookup + */ + public void testPositive05_PMF0_PMFClassNameViaServicesLookup() throws IOException { + + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Positive5", loader); + + String expected = "class.positive5.pmf0"; + String actual = JDOHelper.getPMFClassNameViaServiceLookup(loader); + + assertNotNull("No PMF name found via services lookup", actual); + assertEquals(expected, actual); + } + + public void testNegative08_NoResourcesFound() { String resource = "" + RANDOM.nextLong(); InputStream in = @@ -279,11 +337,14 @@ } } - public void testNegative0_EmptyJDOConfigXML() throws IOException { + public void testNegative00_EmptyJDOConfigXML() throws IOException { try { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative0"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative0", loader); - JDOHelper.getPersistenceManagerFactory(); + JDOHelper.getPersistenceManagerFactory(loader); fail("JDOHelper failed to throw JDOFatalUserException"); } catch (JDOFatalUserException x) { @@ -291,11 +352,14 @@ } } - public void testNegative1_NoPersistenceUnitsDefined() throws IOException { + public void testNegative01_NoPersistenceUnitsDefined() throws IOException { try { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative1"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative1", loader); - JDOHelper.getPersistenceManagerFactory(); + JDOHelper.getPersistenceManagerFactory(loader); fail("JDOHelper failed to throw JDOFatalUserException"); } catch (JDOFatalUserException x) { @@ -303,13 +367,16 @@ } } - public void testNegative2_DuplicateAnonymousPersistenceUnitsInSameConfig() + public void testNegative02_DuplicateAnonymousPersistenceUnitsInSameConfig() throws IOException { try { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative2"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative2", loader); - JDOHelper.getPersistenceManagerFactory(); + JDOHelper.getPersistenceManagerFactory(loader); fail("JDOHelper failed to throw JDOFatalUserException"); } catch (JDOFatalUserException x) { @@ -317,14 +384,18 @@ } } - public void testNegative3_DuplicateNamedPersistenceUnitsInSameConfig() + public void testNegative03_DuplicateNamedPersistenceUnitsInSameConfig() throws IOException { try { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative3"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative3", loader); JDOHelper.getPersistenceManagerFactory( - "persistence-unit-name.negative3"); + "persistence-unit-name.negative3", + loader); fail("JDOHelper failed to throw JDOFatalUserException"); } @@ -333,14 +404,18 @@ } } - public void testNegative4_DuplicatePUNamePropertyInAttributeAndElement() + public void testNegative04_DuplicatePUNamePropertyInAttributeAndElement() throws IOException { try { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative4"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative4", loader); JDOHelper.getPersistenceManagerFactory( - "persistence-unit-name.negative4.value0"); + "persistence-unit-name.negative4.value0", + loader); fail("JDOHelper failed to throw JDOFatalUserException"); } @@ -349,13 +424,16 @@ } } - public void testNegative5_DuplicatePropertyInAttributeAndElement() + public void testNegative05_DuplicatePropertyInAttributeAndElement() throws IOException { try { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative5"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative5", loader); - JDOHelper.getPersistenceManagerFactory(); + JDOHelper.getPersistenceManagerFactory(loader); fail("JDOHelper failed to throw JDOFatalUserException"); } @@ -364,14 +442,19 @@ } } - public void testNegative6_DuplicatePUInDifferentConfigFiles() + public void testNegative06_DuplicatePUInDifferentConfigFiles() throws IOException { try { - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative6/6a"); - ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative6/6b"); + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + (URLClassLoader) getClass().getClassLoader()); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative6/6a", loader); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative6/6b", loader); - JDOHelper.getPersistenceManagerFactory("persistence-unit-name.negative6"); + JDOHelper.getPersistenceManagerFactory( + "persistence-unit-name.negative6", + loader); fail("JDOHelper failed to throw JDOFatalUserException"); } @@ -379,5 +462,24 @@ // happy path } } + + public void testNegative07_EmptyServicesFile() + throws IOException + { + URLClassLoader loader = (URLClassLoader) getClass().getClassLoader(); + JDOConfigTestClassLoader testLoader = new JDOConfigTestClassLoader(new String[] {JDOCONFIG_CLASSPATH_PREFIX}, loader); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative7", testLoader); + String shouldBeNull = JDOHelper.getPMFClassNameViaServiceLookup(testLoader); + assertNull(shouldBeNull); + } + + public void testNegative08_ServicesFileWithOnlyComments() + throws IOException + { + URLClassLoader loader = (URLClassLoader) getClass().getClassLoader(); + JDOConfigTestClassLoader testLoader = new JDOConfigTestClassLoader(new String[] {JDOCONFIG_CLASSPATH_PREFIX}, loader); + ClasspathHelper.addFile(JDOCONFIG_CLASSPATH_PREFIX + "/Negative8", testLoader); + String shouldBeNull = JDOHelper.getPMFClassNameViaServiceLookup(testLoader); + assertNull(shouldBeNull); + } } - Index: src/java/javax/jdo/JDOHelper.java =================================================================== --- src/java/javax/jdo/JDOHelper.java (revision 541701) +++ src/java/javax/jdo/JDOHelper.java (working copy) @@ -22,55 +22,31 @@ package javax.jdo; +import org.w3c.dom.*; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; -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; -import java.io.InputStream; -import java.io.IOException; - -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.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.HashMap; -import java.util.Enumeration; -import java.util.Collections; - import javax.jdo.spi.I18NHelper; import javax.jdo.spi.JDOImplHelper; import javax.jdo.spi.JDOImplHelper.StateInterrogationBooleanReturn; import javax.jdo.spi.JDOImplHelper.StateInterrogationObjectReturn; import javax.jdo.spi.PersistenceCapable; import javax.jdo.spi.StateInterrogation; - import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; - import javax.rmi.PortableRemoteObject; - +import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.FactoryConfigurationError; +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.*; /** @@ -607,6 +583,36 @@ return getPersistenceManagerFactory ((String)null, cl); } + /** Get the anonymous PersistenceManagerFactory configured via the standard + * configuration file resource "META-INF/jdoconfig.xml", using the given class loader + * to locate the configuration file resource(s). + * @return the anonymous PersistenceManagerFactory. + * @param cl the ClassLoader used to load resources and classes + * @since 2.1 + * @see #getPersistenceManagerFactory(String,ClassLoader) + */ + public static PersistenceManagerFactory getPersistenceManagerFactory( + ClassLoader cl + ) { + return getPersistenceManagerFactory((String)null, cl, cl); + } + + /** Get the anonymous PersistenceManagerFactory configured via the standard + * configuration file resource "META-INF/jdoconfig.xml", using the given resource class loader & class loader + * to locate the configuration file resource(s). + * @return the anonymous PersistenceManagerFactory. + * @param resourceLoader the class loader to use to load resources + * @param pmfLoader the class loader to use to load the classes + * @since 2.1 + * @see #getPersistenceManagerFactory(String,ClassLoader) + */ + public static PersistenceManagerFactory getPersistenceManagerFactory( + ClassLoader resourceLoader, + ClassLoader pmfLoader + ) { + return getPersistenceManagerFactory((String)null, resourceLoader, pmfLoader); + } + /** Get a PersistenceManagerFactory based on a Properties * instance, using the current thread's context class loader to locate the * PersistenceManagerFactory class. @@ -678,8 +684,17 @@ String pmfClassName = (String) props.get ( PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); //NOI18N if (pmfClassName == null) { - throw new JDOFatalUserException(msg.msg( - "EXC_GetPMFNoClassNameProperty")); // NOI18N + try { + pmfClassName = getPMFClassNameViaServiceLookup(cl); + } + catch (IOException e) { + throw new JDOFatalInternalException(msg.msg( + "EXC_IOExceptionDuringServiceLookup"), e); // NOI18N + } + if (pmfClassName == null) { + throw new JDOFatalUserException(msg.msg( + "EXC_GetPMFNoClassNameProperty")); // NOI18N + } } try { Class pmfClass = cl.loadClass (pmfClassName); @@ -699,7 +714,7 @@ "EXC_GetPMFNoSuchMethod"), nsme); //NOI18N } catch (InvocationTargetException ite) { Throwable nested = ite.getTargetException(); - if (nested instanceof JDOException) { + if (nested instanceof JDOException) { throw (JDOException)nested; } else throw new JDOFatalInternalException (msg.msg( "EXC_GetPMFUnexpectedException"), ite); //NOI18N @@ -714,8 +729,53 @@ "EXC_GetPMFUnexpectedException"), e); //NOI18N } } - + /** + * Looks up a (@link PersistenceManagerFactory} implementation class name from the resource + * META-INF/services/javax.jdo.PersistenceManagerFactory, which should be a text file whose + * only contents are the fully qualified name of a class that implements (@link PersistenceManagerFactory}. + * Note that the method {@link java.lang.ClassLoader#getResourceAsStream(String)} is used to find the resource. + * Only the first implementation class name found in the resource is used. + * @param cl The ClassLoader used to find the resource. + * @return The first non-blank, trimmed line found in the file; should be a PMF implementation class name, or null + * if no content was found. + * @throws IOException + */ + protected static String getPMFClassNameViaServiceLookup(ClassLoader cl) throws IOException { + InputStream is = cl.getResourceAsStream(SERVICE_LOOKUP_PMF_RESOURCE_NAME); + if (is == null) { + return null; + } + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line = null; + try { + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.length() == 0 || line.startsWith("#")) { + continue; + } + // else assume first line of text is the PMF class name + String[] tokens = line.split("\\s"); + String pmfClassName = tokens[0]; + int indexOfComment = pmfClassName.indexOf("#"); + if (indexOfComment == -1) { + return pmfClassName; + } + // else pmfClassName has a comment at the end of it -- remove + return pmfClassName.substring(0, indexOfComment); + } + return null; + } finally { + try { + reader.close(); + } + catch (IOException x) { + // gulp + } + } + } + + /** * 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 Index: src/java/javax/jdo/Constants.java =================================================================== --- src/java/javax/jdo/Constants.java (revision 541701) +++ src/java/javax/jdo/Constants.java (working copy) @@ -25,6 +25,16 @@ public interface Constants { /** + * The name of the standard service configuration resource text file containing + * the name of an implementation of {@link PersistenceManagerFactory}. + * Constant value is META-INF/services/javax.jdo.PersistenceManagerFactory. + * + * @since 2.1 + */ + static String SERVICE_LOOKUP_PMF_RESOURCE_NAME + = "META-INF/services/javax.jdo.PersistenceManagerFactory"; + + /** * The name of the standard JDO configuration resource file(s). * Constant value is META-INF/jdoconfig.xml. * Index: src/java/javax/jdo/Bundle.properties =================================================================== --- src/java/javax/jdo/Bundle.properties (revision 541701) +++ src/java/javax/jdo/Bundle.properties (working copy) @@ -26,6 +26,8 @@ EXC_GetPMFClassNotFound=Class {0} was not found. EXC_GetPMFIllegalAccess=Illegal Access for class {0}. EXC_GetPMFNoClassNameProperty=A property named javax.jdo.PersistenceManagerFactoryClass must be specified. +EXC_IOExceptionDuringServiceLookup=IO error while attempting to lookup PMF name \ +via META-INF/services/javax.jdo.PersistenceManagerFactory MSG_FailedObject=FailedObject: MSG_NestedThrowables=NestedThrowables: MSG_NestedThrowablesStackTrace=NestedThrowablesStackTrace: