Index: api2/src/java/javax/jdo/JDOHelper.java =================================================================== --- api2/src/java/javax/jdo/JDOHelper.java (revision 693935) +++ api2/src/java/javax/jdo/JDOHelper.java (working copy) @@ -773,47 +773,85 @@ * PersistenceManagerFactory. * @param pmfClassLoader the class loader to use to load the * PersistenceManagerFactory class + * @throws JDOFatalUserException If either the pmfClassLoader passed is + * invalid or a valid class name cannot be obtained from + * either props or system resources. * @since 2.1 */ protected static PersistenceManagerFactory getPersistenceManagerFactory - (Map overrides, Map props, ClassLoader pmfClassLoader) { + (Map overrides, Map props, ClassLoader pmfClassLoader) throws JDOFatalUserException { List exceptions = new ArrayList(); if (pmfClassLoader == null) throw new JDOFatalUserException (msg.msg ( "EXC_GetPMFNullLoader")); //NOI18N + // try and get the class name from the properties object. String pmfClassName = (String) props.get ( PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); + // test to be sure all the throwables are in the nested exceptions + // array. There are multiple jar files where the class loader can + // exist in - and this code will find all of them. + // positive test: a bad implementation of a class: + // META-INF is missing a class or the class is bad. + // test 1: check that all bad classes are skipped + // test 2: check that when all classes are bad, that all exceptions are + // caught. + // use JDOHelperConfigTest and JDOConfigTestClassLoader + // have multiple jar files in classpath if (!isNullOrBlank(pmfClassName)) { + // a valid name was returned from the properties. return invokeGetPersistenceManagerFactoryOnImplementation( pmfClassName, overrides, props, pmfClassLoader); } else { - // PMF class name null or blank -- try services - // for each file META-INF/services/javax.jdo.PersistenceManagerFactory - // try to invoke the getPersistenceManagerFactory method of the - // implementation class + /* + * If you have a .jar file that provides services, a file name for + * each service goes into the jar file + * META-INF/services/javax.naming.initialContext. + * The contents of the file is a string that is the PMF class name, + * null or blank. For each file + * META-INF/services/javax.jdo.PersistenceManagerFactory + * try to invoke the getPersistenceManagerFactory method of the + * implementation class. Return the factory if a valid class name is + * extracted from resources. Otherwise add the exception thrown to + * an exception list. + */ + Enumeration urls = null; try { - Enumeration urls = getResources(pmfClassLoader, - SERVICE_LOOKUP_PMF_RESOURCE_NAME); + urls = getResources(pmfClassLoader, + SERVICE_LOOKUP_PMF_RESOURCE_NAME); + } catch (Throwable ex) { + exceptions.add(ex); + } + + if (urls != null){ while (urls.hasMoreElements()) { - pmfClassName = getClassNameFromURL((URL)urls.nextElement()); + + try { + pmfClassName = getClassNameFromURL( + (URL) urls.nextElement()); + + // return the first class name that is valid. return invokeGetPersistenceManagerFactoryOnImplementation( - pmfClassName, overrides, props, pmfClassLoader); + pmfClassName, overrides, props, pmfClassLoader); + + } catch (Throwable ex) { + + // remember exceptions from failed pmf invocations + exceptions.add(ex); + + } } - } catch (Throwable ex) { - // remember exceptions from failed pmf invocations - exceptions.add(ex); } + } - // no PMF class name and no services + // no PMF class name and no services. throw new JDOFatalUserException(msg.msg( "EXC_GetPMFNoPMFClassNamePropertyOrPUNameProperty"), - (Throwable[]) - exceptions.toArray(new Throwable[exceptions.size()])); + (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()])); } /** Get a class name from a URL. The URL is from getResources with Index: api2/test/java/javax/jdo/JDOHelperConfigTest.java =================================================================== --- api2/test/java/javax/jdo/JDOHelperConfigTest.java (revision 693934) +++ api2/test/java/javax/jdo/JDOHelperConfigTest.java (working copy) @@ -527,6 +527,7 @@ } } + public void testNegative07_EmptyServicesFile() throws IOException { JDOConfigTestClassLoader testLoader = new JDOConfigTestClassLoader( @@ -556,6 +557,31 @@ } } + public void testNegative09_MultipleInvalidClassesInDifferentConfigFiles() + throws IOException { + + // failure ensured with a bad class name in Negative09/jdoconfig.xml + try { + URLClassLoader loader = new JDOConfigTestClassLoader( + JDOCONFIG_CLASSPATH_PREFIX, + getClass().getClassLoader()); + ClasspathHelper.addFile( + JDOCONFIG_CLASSPATH_PREFIX + "/Negative09", loader); + + JDOHelper.getPersistenceManagerFactory(loader); + + fail("JDOHelper failed to throw JDOFatalUserException"); + } + catch (JDOFatalUserException x) { + + // if nested exceptions are returned, we're on the happy farm ... + if (x.getNestedExceptions() == null){ + fail("JDOHelper failed to include any nested exceptions"); + } + + } + } + public void testNegative08_ServicesFileWithOnlyComments() throws IOException { JDOConfigTestClassLoader testLoader = new JDOConfigTestClassLoader( Index: api2/test/schema/jdoconfig/Negative09/META-INF/jdoconfig.xml =================================================================== --- api2/test/schema/jdoconfig/Negative09/META-INF/jdoconfig.xml (revision 693934) +++ api2/test/schema/jdoconfig/Negative09/META-INF/jdoconfig.xml (working copy) @@ -8,9 +8,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig"> - - + + + + \ No newline at end of file