Index: src/java/javax/jdo/JDOHelper.java =================================================================== --- src/java/javax/jdo/JDOHelper.java (revision 632419) +++ src/java/javax/jdo/JDOHelper.java (working copy) @@ -58,6 +58,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.ArrayList; +import java.util.List; import java.util.Properties; import java.util.Enumeration; import java.io.IOException; @@ -760,19 +761,8 @@ String pmfClassName = (String) props.get ( PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS); - if (pmfClassName == null) { - // no PMF class name property -- try to find via services lookup + if (!isNullOrBlank(pmfClassName)) { try { - pmfClassName = getPMFClassNameViaServiceLookup(pmfClassLoader); - } - catch (IOException e) { - throw new JDOFatalInternalException(msg.msg( - "EXC_IOExceptionDuringServiceLookup"), e); // NOI18N - } - } - - if (pmfClassName != null) { - try { Class pmfClass = forName(pmfClassName, true, pmfClassLoader); Method pmfMethod = getMethod(pmfClass, "getPersistenceManagerFactory", //NOI18N @@ -804,14 +794,24 @@ throw new JDOFatalInternalException (msg.msg( "EXC_GetPMFUnexpectedException"), e); //NOI18N } + } else { + // PMF class name property is null or blank -- try to find via services + List pmfClassNames = getPMFClassNamesViaServiceLookup(pmfClassLoader); + try { + pmfClassName = getPMFClassNameViaServiceLookup(pmfClassLoader); + } + catch (IOException e) { + throw new JDOFatalInternalException(msg.msg( + "EXC_IOExceptionDuringServiceLookup"), e); // NOI18N + } } - - // else no PMF class name given; check PU name + + // else no PMF class name given; try services lookup String puName = (String) props.get(PROPERTY_PERSISTENCE_UNIT_NAME); - if (puName != null && !"".equals(puName.trim())) { + if (!isNullOrBlank(puName)) { PersistenceManagerFactory pmf = - getPMFFromEMF(puName, props, pmfClassLoader); + getPMFFromPersistenceUnitName(puName, props, pmfClassLoader); if (pmf != null) { return pmf; @@ -848,16 +848,63 @@ protected static String getPMFClassNameViaServiceLookup(ClassLoader cl) throws IOException { - /* - Note: not using sun.misc.Service because it's not a standard part of - the JDK (yet). - */ InputStream is = getResourceAsStream(cl, SERVICE_LOOKUP_PMF_RESOURCE_NAME); if (is == null) { return null; } + return getClassNameFromServicesInputStream(is); + } + + /** + * 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 a list of resource names found in the resource files; should be + * PMF implementation class names; null and blank names are removed + */ + protected static List/**/ getPMFClassNamesViaServiceLookup(ClassLoader cl) + { + List resourceNames = new ArrayList(); + Enumeration resources; + try { + resources = getResources(cl, SERVICE_LOOKUP_PMF_RESOURCE_NAME); + + } catch (IOException iOException) { + // no resources + return resourceNames; + } + + while (resources.hasMoreElements()) { + URL resource = (URL)resources.nextElement(); + try { + InputStream is = resource.openStream(); + String name = getClassNameFromServicesInputStream(is); + if (!isNullOrBlank(name)) { + resourceNames.add(name); + } + } catch (IOException iOException) { + // never mind; try the next resource + } + } + return resourceNames; + } + + /** Get a class name from a stream in resources format. + * + */ + protected static String getClassNameFromServicesInputStream + (InputStream is) throws IOException + { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line = null; try { @@ -1073,34 +1120,20 @@ "EXC_GetPMFNoPMFClassNamePropertyOrPUNameProperty")); } - try { - return invokeGetPersistenceManagerFactoryOnImplementation( + return invokeGetPersistenceManagerFactoryOnImplementation( pmfClassName, overrides, properties, pmfLoader); - } catch (ClassNotFoundException e) { - throw new JDOFatalUserException(msg.msg( - "EXC_GetPMFClassNotFound", pmfClassName), e); - } catch (NoSuchMethodException e) { - throw new JDOFatalUserException(msg.msg( - "EXC_GetPMFNoSuchMethod2", pmfClassName), e); - } catch (IllegalAccessException e) { - throw new JDOFatalUserException(msg.msg( - "EXC_GetPMFIllegalAccess", pmfClassName), e); - } catch (InvocationTargetException e) { - throw new JDOFatalUserException(msg.msg( - "EXC_GetPMFInvocationTargetException", pmfClassName), e); - } } - // else no properties found; next, assume name is a JPA PU name + // else no properties found; see if name is a JPA PU name if (!ANONYMOUS_PERSISTENCE_MANAGER_FACTORY_NAME.equals(name)) { PersistenceManagerFactory pmf = - getPMFFromEMF(name, overrides, pmfLoader); + getPMFFromPersistenceUnitName(name, overrides, pmfLoader); if (pmf != null) { return pmf; } } - // else no PMF found + // no PMF found throw new JDOFatalUserException (msg.msg ( "EXC_NoPMFConfigurableViaPropertiesOrXML", name)); //NOI18N @@ -1109,19 +1142,28 @@ protected static PersistenceManagerFactory invokeGetPersistenceManagerFactoryOnImplementation( String pmfClassName, Map overrides, Map properties, ClassLoader cl) - throws - ClassNotFoundException, - NoSuchMethodException, - IllegalAccessException, - InvocationTargetException { - Class implClass = forName(pmfClassName, true, cl); - Method m = getMethod(implClass, - "getPersistenceManagerFactory", - new Class[] { Map.class, Map.class }); + try { + Class implClass = forName(pmfClassName, true, cl); + Method m = getMethod(implClass, + "getPersistenceManagerFactory", + new Class[]{Map.class, Map.class}); + return (PersistenceManagerFactory) invoke(m, + null, new Object[]{overrides, properties}); - return (PersistenceManagerFactory) invoke(m, - null, new Object[] {overrides, properties}); + } catch (ClassNotFoundException e) { + throw new JDOFatalUserException(msg.msg( + "EXC_GetPMFClassNotFound", pmfClassName), e); + } catch (NoSuchMethodException e) { + throw new JDOFatalUserException(msg.msg( + "EXC_GetPMFNoSuchMethod2", pmfClassName), e); + } catch (IllegalAccessException e) { + throw new JDOFatalUserException(msg.msg( + "EXC_GetPMFIllegalAccess", pmfClassName), e); + } catch (InvocationTargetException e) { + throw new JDOFatalUserException(msg.msg( + "EXC_GetPMFInvocationTargetException", pmfClassName), e); + } } @@ -1178,8 +1220,8 @@ */ protected static Map getNamedPMFProperties( String name, - ClassLoader resourceLoader - ) { + ClassLoader resourceLoader) + { return getNamedPMFProperties( name, resourceLoader, JDOCONFIG_RESOURCE_NAME); } @@ -1209,8 +1251,8 @@ protected static Map getNamedPMFProperties( String name, ClassLoader resourceLoader, - String jdoconfigResourceName - ) { + String jdoconfigResourceName) + { // key is PU name, value is Map of PU properties Map/**/ propertiesByNameInAllConfigs = new HashMap/**/(); @@ -1326,6 +1368,29 @@ } /** + * Attempts to load a PersistenceManagerFactory by using the name as a + * javax.jdo.PersistenceUnitName. This is done by constructing a + * properties instance with the name set as the value of + * javax.jdo.PersistenceUnitName and then invoking the + * PersistenceManagerFactory service on all implementations. + */ + protected static PersistenceManagerFactory getPMFFromPersistenceUnitName( + String name, Map overrides, ClassLoader loader) + { + Properties props = new Properties(); + props.put(PROPERTY_PERSISTENCE_UNIT_NAME, name); + List pmfNames = getPMFClassNamesViaServiceLookup(loader); + PersistenceManagerFactory pmf = null; + for (Iterator it = pmfNames.iterator(); it.hasNext();) { + String pmfName = (String)it.next(); + pmf = invokeGetPersistenceManagerFactoryOnImplementation( + pmfName, props, overrides, loader); + if (pmf != null) break; + } + return pmf; + } + + /** * Attempts to locate a javax.persistence.EntityManagerFactory * via the javax.persistence.Persistence method * createEntityManagerFactory(String) @@ -1496,9 +1561,9 @@ pmfPropertiesFromElements.getProperty(PROPERTY_NAME); String pmfName = null; - if (nullOrBlank(pmfNameFromAtts)) { + if (isNullOrBlank(pmfNameFromAtts)) { // no PMF name attribute given - if (!nullOrBlank(pmfNameFromElem)) { + if (!isNullOrBlank(pmfNameFromElem)) { // PMF name element was given pmfName = pmfNameFromElem; } @@ -1509,7 +1574,7 @@ } else { // PMF name given in an attribute - if (!nullOrBlank(pmfNameFromElem)) { + if (!isNullOrBlank(pmfNameFromElem)) { // exception -- PMF name given as both att & elem throw new JDOFatalUserException( msg.msg( @@ -1726,7 +1791,7 @@ return p; } - protected static boolean nullOrBlank(String s) { + protected static boolean isNullOrBlank(String s) { return s == null || "".equals(s.trim()); }