| /* |
| * 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. |
| */ |
| |
| // |
| // This source code implements specifications defined by the Java |
| // Community Process. In order to remain compliant with the specification |
| // DO NOT add / change / or delete method signatures! |
| // |
| package javax.persistence; |
| |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.persistence.spi.LoadState; |
| import javax.persistence.spi.PersistenceProvider; |
| import javax.persistence.spi.PersistenceProviderResolver; |
| import javax.persistence.spi.PersistenceProviderResolverHolder; |
| import javax.persistence.spi.ProviderUtil; |
| |
| /** |
| * @version $Rev$ $Date$ |
| */ |
| |
| /** |
| * Bootstrap class that is used to obtain {@link javax.persistence.EntityManagerFactory} |
| * references. |
| * |
| * Contains Geronimo implemented code as required by the JPA spec. |
| */ |
| public class Persistence { |
| |
| protected static final Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>(); |
| // Changed to the hard coded PERSISTENCE_PROVIDER value to pass signature tests. |
| // public static final java.lang.String PERSISTENCE_PROVIDER = PersistenceProvider.class.getName(); |
| public static final java.lang.String PERSISTENCE_PROVIDER = "javax.persistence.spi.PeristenceProvider"; |
| static final String PERSISTENCE_PROVIDER_PROPERTY = "javax.persistence.provider"; |
| static final String PERSISTENCE_PROVIDER_SERVICE = "META-INF/services/" |
| + PersistenceProvider.class.getName(); |
| |
| /** |
| * Create and return an EntityManagerFactory for the named persistence unit. |
| * |
| * @param persistenceUnitName Name of the persistence unit |
| * @return The factory for the specified persistence unit or null if none |
| * are applicable. |
| */ |
| public static EntityManagerFactory createEntityManagerFactory( |
| String persistenceUnitName) { |
| return createEntityManagerFactory(persistenceUnitName, Collections.EMPTY_MAP); |
| } |
| |
| /** |
| * Create and return an EntityManagerFactory for the named persistence unit |
| * using the given properties. |
| * |
| * @param persistenceUnitName Name of the persistence unit |
| * @param properties Additional properties to use when creating the |
| * persistence unit factory. These properties override any |
| * values that have been configured elsewhere. |
| * @return The factory for the specified persistence unit or null if none |
| * are applicable. |
| */ |
| public static EntityManagerFactory createEntityManagerFactory( |
| String persistenceUnitName, Map properties) { |
| |
| EntityManagerFactory factory = null; |
| Map props = properties; |
| if (props == null) { |
| props = Collections.EMPTY_MAP; |
| } |
| |
| // get the discovered set of providers |
| PersistenceProviderResolver resolver = |
| PersistenceProviderResolverHolder.getPersistenceProviderResolver(); |
| // following will throw PersistenceExceptions for invalid services |
| List<PersistenceProvider> providers = resolver.getPersistenceProviders(); |
| |
| /* |
| * Geronimo/OpenJPA 1.0 unique behavior - Start by loading a provider |
| * explicitly specified in the properties and return any exceptions. |
| * The spec doesn't forbid providers that aren't a service - it only |
| * states that they "should" be implemented as services in Sect. 9.2. |
| * |
| * For 2.0 - We only perform the above behavior if the specified |
| * provider is not in the discovered list. |
| * |
| * Note: This special non-spec defined case will rethrow any encountered |
| * Exceptions as a PersistenceException. |
| */ |
| Object providerName = props.get(PERSISTENCE_PROVIDER_PROPERTY); |
| if ((providerName != null) && (providerName instanceof String)) { |
| boolean isLoaded = false; |
| // search the discovered providers for this explicit provider |
| for (PersistenceProvider provider : providers) { |
| if (provider.getClass().getName().compareTo(providerName.toString()) == 0) { |
| isLoaded = true; |
| break; |
| } |
| } |
| /* |
| * Only try to explicitly create this provider if we didn't |
| * find it as a service, while rethrowing any exceptions to |
| * match the old 1.0 behavior |
| */ |
| if (!isLoaded) { |
| factory = createFactory( |
| providerName.toString(), |
| persistenceUnitName, |
| props); |
| if (factory != null) { |
| return factory; |
| } |
| } |
| } |
| |
| /* |
| * Now, the default behavior of loading a provider from our resolver |
| * Note: Change in behavior from 1.0, which always returned exceptions: |
| * Spec states that a provider "must" return null if it |
| * cannot fulfill an EMF request, so ignore any exceptions |
| * that are thrown if we have more than one provider, |
| * so the other providers have a chance to return an EMF. |
| * Otherwise, return any exceptions and rethrow/wrapper as a |
| * PersistenceException if needed to match 1.0 behavior. |
| */ |
| if (providers.size() == 1) { |
| // allow any exceptions to pass thru to caller |
| return providers.get(0).createEntityManagerFactory( |
| persistenceUnitName, props); |
| } else { |
| for (PersistenceProvider provider : providers) { |
| try { |
| factory = provider.createEntityManagerFactory( |
| persistenceUnitName, props); |
| } catch (Exception e) { |
| // ignore and give other providers a chance |
| } |
| if (factory != null) { |
| return factory; |
| } |
| } |
| } |
| |
| /* |
| * Spec doesn't mention any exceptions thrown by this method if no emf |
| * returned, but old 1.0 behavior always generated an EMF or exception. |
| */ |
| throw new PersistenceException("No Persistence providers found for PU=" |
| + persistenceUnitName); |
| } |
| |
| /* |
| * Geronimo/OpenJPA private helper code for PERSISTENCE_PROVIDER_PROPERTY |
| * @return EntityManagerFactory or null |
| * @throws PersistenceException |
| */ |
| private static EntityManagerFactory createFactory(String providerName, |
| String persistenceUnitName, Map properties) |
| throws PersistenceException { |
| |
| Class<?> providerClass; |
| ClassLoader cl = Thread.currentThread().getContextClassLoader(); |
| if (cl == null) |
| cl = Persistence.class.getClassLoader(); |
| try { |
| providerClass = Class.forName(providerName, true, cl); |
| } catch (Exception e) { |
| throw new PersistenceException("Invalid or inaccessible explicit provider class: " + |
| providerName, e); |
| } |
| try { |
| PersistenceProvider provider = (PersistenceProvider) providerClass.newInstance(); |
| return provider.createEntityManagerFactory(persistenceUnitName, properties); |
| } catch (Exception e) { |
| throw new PersistenceException("Explicit error returned from provider: " + |
| providerName, e); |
| } |
| } |
| |
| /* |
| * @return PersistenceUtil instance |
| * @since 2.0 |
| */ |
| public static PersistenceUtil getPersistenceUtil() { |
| return new PersistenceUtilImpl(); |
| } |
| |
| /* |
| * Geronimo implementation specific code |
| */ |
| private static class PersistenceUtilImpl implements PersistenceUtil { |
| |
| /* |
| * Determines the load state of the attribute of an entity |
| * @see javax.persistence.PersistenceUtil#isLoaded(java.lang.Object, java.lang.String) |
| */ |
| public boolean isLoaded(Object entity, String attributeName) { |
| boolean isLoaded = true; |
| |
| // Get the list of persistence providers from the resolver |
| PersistenceProviderResolver ppr = |
| PersistenceProviderResolverHolder.getPersistenceProviderResolver(); |
| List<PersistenceProvider> pps = ppr.getPersistenceProviders(); |
| |
| // Iterate through the list using ProviderUtil.isLoadedWithoutReference() |
| for (PersistenceProvider pp : pps) { |
| try { |
| ProviderUtil pu = pp.getProviderUtil(); |
| LoadState ls = pu.isLoadedWithoutReference(entity, attributeName); |
| if (ls == LoadState.LOADED) |
| return true; |
| if (ls == LoadState.NOT_LOADED) |
| return false; |
| } |
| catch (Throwable t) { |
| // JPA 1.0 providers will not implement the getProviderUtil |
| // method. Eat the exception and try the next provider. |
| } |
| } |
| // Iterate through the list a second time using ProviderUtil.isLoadedWithReference() |
| for (PersistenceProvider pp : pps) { |
| try { |
| ProviderUtil pu = pp.getProviderUtil(); |
| LoadState ls = pu.isLoadedWithReference(entity, attributeName); |
| if (ls == LoadState.LOADED) |
| return true; |
| if (ls == LoadState.NOT_LOADED) |
| return false; |
| } |
| catch (Throwable t) { |
| // JPA 1.0 providers will not implement the getProviderUtil |
| // method. Eat the exception and try the next provider. |
| } |
| } |
| |
| // All providers returned a load state of unknown. Return true. |
| return true; |
| } |
| |
| public boolean isLoaded(Object entity) { |
| // Get the list of persistence providers from the resolver |
| PersistenceProviderResolver ppr = |
| PersistenceProviderResolverHolder.getPersistenceProviderResolver(); |
| List<PersistenceProvider> pps = ppr.getPersistenceProviders(); |
| |
| // Iterate through the list of providers, using ProviderUtil to |
| // determine the load state |
| for (PersistenceProvider pp : pps) { |
| try { |
| ProviderUtil pu = pp.getProviderUtil(); |
| LoadState ls = pu.isLoaded(entity); |
| if (ls == LoadState.LOADED) |
| return true; |
| if (ls == LoadState.NOT_LOADED) |
| return false; |
| // Otherwise, load state is unknown. Query the next provider. |
| } |
| catch (Throwable t) { |
| // JPA 1.0 providers will not implement the getProviderUtil |
| // method. Eat the exception and try the next provider. |
| } |
| } |
| |
| // All providers returned a load state of unknown. Return true. |
| return true; |
| } |
| } |
| |
| } |