| /* |
| * 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.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.util.Collections; |
| import java.util.HashMap; |
| 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; |
| |
| /** |
| * Bootstrap class to obtain {@link javax.persistence.EntityManagerFactory} |
| * references. |
| * |
| * Contains Geronimo implemented code as required by the JPA spec. |
| * |
| * @version $Rev$ $Date$ |
| */ |
| public class Persistence { |
| |
| // The following variable is only here for TCK backward compatibility |
| @Deprecated |
| protected static final Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>(); |
| |
| // The following string is only here for TCK backward compatibility |
| @Deprecated |
| public static final 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(); |
| |
| |
| public static EntityManagerFactory createEntityManagerFactory( |
| String persistenceUnitName) { |
| return createEntityManagerFactory(persistenceUnitName, Collections.EMPTY_MAP); |
| } |
| |
| /** |
| * Geronimo implementation specific code |
| */ |
| 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 |
| List<PersistenceProvider> providers = getProviders(); |
| |
| /* |
| * Now, the default JPA2 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 that if we have more than one |
| * provider, then the other providers have a chance to return an EMF. |
| * Now, we will return any exceptions wrapped in a |
| * PersistenceException to match 1.0 behavior and provide more |
| * diagnostics to the end user. |
| */ |
| |
| // capture any provider returned exceptions |
| Map<String, Throwable> exceptions = new HashMap<String, Throwable>(); |
| // capture the provider names to use in the exception text if needed |
| StringBuffer foundProviders = null; |
| |
| for (PersistenceProvider provider : providers) { |
| String providerName = provider.getClass().getName(); |
| try { |
| factory = provider.createEntityManagerFactory(persistenceUnitName, props); |
| } catch (Exception e) { |
| // capture the exception details and give other providers a chance |
| exceptions.put(providerName, e); |
| } |
| if (factory != null) { |
| // we're done |
| return factory; |
| } else { |
| // update the list of providers we have tried |
| if (foundProviders == null) { |
| foundProviders = new StringBuffer(providerName); |
| } else { |
| foundProviders.append(", "); |
| foundProviders.append(providerName); |
| } |
| } |
| } |
| |
| // make sure our providers list is initialized for the exceptions below |
| if (foundProviders == null) { |
| foundProviders = new StringBuffer("NONE"); |
| } |
| |
| /* |
| * 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. |
| */ |
| if (exceptions.isEmpty()) { |
| // throw an exception with the PU name and providers we tried |
| throw new PersistenceException("No persistence providers available for \"" + persistenceUnitName + |
| "\" after trying the following discovered implementations: " + foundProviders); |
| } else { |
| // we encountered one or more exceptions, so format and throw as a single exception |
| throw createPersistenceException( |
| "Explicit persistence provider error(s) occurred for \"" + persistenceUnitName + |
| "\" after trying the following discovered implementations: " + foundProviders, |
| exceptions); |
| } |
| } |
| |
| /** |
| * Geronimo/OpenJPA private helper code for creating a PersistenceException |
| * @param msg String to use as the exception message |
| * @param failures Persistence provider exceptions to add to the exception message |
| * @return PersistenceException |
| */ |
| private static PersistenceException createPersistenceException(String msg, Map<String, Throwable> failures) { |
| String newline = System.getProperty("line.separator"); |
| StringWriter strWriter = new StringWriter(); |
| strWriter.append(msg); |
| if (failures.size() <= 1) { |
| // we caught an exception, so include it as the cause |
| Throwable t = null; |
| for (String providerName : failures.keySet()) { |
| t = failures.get(providerName); |
| strWriter.append(" from provider: "); |
| strWriter.append(providerName); |
| break; |
| } |
| return new PersistenceException(strWriter.toString(), t); |
| } else { |
| // we caught multiple exceptions, so format them into the message string and don't set a cause |
| strWriter.append(" with the following failures:"); |
| strWriter.append(newline); |
| for (String providerName : failures.keySet()) { |
| strWriter.append(providerName); |
| strWriter.append(" returned: "); |
| failures.get(providerName).printStackTrace(new PrintWriter(strWriter)); |
| } |
| strWriter.append(newline); |
| return new PersistenceException(strWriter.toString()); |
| } |
| } |
| |
| public static PersistenceUtil getPersistenceUtil() { |
| return new PersistenceUtilImpl(); |
| } |
| |
| public static void generateSchema(String persistenceUnitName, Map properties) { |
| final List<PersistenceProvider> providers = getProviders(); |
| for (final PersistenceProvider provider : providers) { |
| if (provider.generateSchema( persistenceUnitName, properties)) { |
| return; |
| } |
| } |
| throw new PersistenceException("No provider for schema generation of unit '" + persistenceUnitName + "'"); |
| } |
| |
| private static List<PersistenceProvider> getProviders() { |
| // get the discovered set of providers |
| PersistenceProviderResolver resolver = |
| PersistenceProviderResolverHolder.getPersistenceProviderResolver(); |
| // following will throw PersistenceExceptions for invalid services |
| return resolver.getPersistenceProviders(); |
| } |
| |
| /** |
| * 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) { |
| // Get the list of persistence providers from the resolver |
| List<PersistenceProvider> pps = getProviders(); |
| |
| // 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 |
| List<PersistenceProvider> pps = getProviders(); |
| |
| // 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; |
| } |
| } |
| |
| } |
| |