/* * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the license at * https://glassfish.dev.java.net/public/CDDLv1.0.html or * glassfish/bootstrap/legal/CDDLv1.0.txt. * See the License for the specific language governing * permissions and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at glassfish/bootstrap/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * you own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. */ package javax.persistence; // J2SE imports import java.io.IOException; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.Map; import java.util.HashSet; import java.util.Enumeration; import java.util.TreeMap; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; // persistence imports import javax.persistence.spi.PersistenceProvider; /** * Bootstrap class that is used to obtain an {@link EntityManagerFactory}. * * @since Java Persistence 1.0 */ public class Persistence { public static String PERSISTENCE_PROVIDER = "javax.persistence.spi.PeristenceProvider"; // *** No longer used // This is retained to maintain signature compatibity. protected static final Set providers = null; /** * Create and return an EntityManagerFactory for the * named persistence unit. * * @param persistenceUnitName The name of the persistence unit * @return The factory that creates EntityManagers configured * according to the specified persistence unit */ public static EntityManagerFactory createEntityManagerFactory(String persistenceUnitName) { return createEntityManagerFactory(persistenceUnitName, null); } /** * Create and return an EntityManagerFactory for the * named persistence unit using the given properties. * * @param persistenceUnitName The name of the persistence unit * @param properties Additional properties to use when creating the * factory. The values of these properties override any values * that may have been configured elsewhere. * @return The factory that creates EntityManagers configured * according to the specified persistence unit. */ public static EntityManagerFactory createEntityManagerFactory( String persistenceUnitName, Map properties) { EntityManagerFactory emf = null; List providers = Collections.EMPTY_LIST; try{ providers = findAllProviders(); } catch (IOException exc){}; Map errors = new TreeMap(); for (PersistenceProvider provider : providers) { try { emf = provider.createEntityManagerFactory(persistenceUnitName, properties); if (emf != null){ break; } } catch (Throwable t) { errors.put(provider.getClass().getName(), t); // ignore : according to Spec the provider must return null from // createEntityManagerFactory(), if not the right provider. // But non-compliant provider may throw exception } } if (!errors.isEmpty()) { System.err.println(createErrorMessage("WARNING: One or more PersistenceProviders are not configured properly", errors)); } if (emf == null) { throw new PersistenceException("No Persistence provider can create EntityManager named " + persistenceUnitName); } return emf; } // Helper methods /** * Returns the set of PersistenceProviders. * Loads services file(s) as resources using context classloaders. * Loads each PersistenceProvider class specified in the services file(s). * * The order of */ private static List findAllProviders() throws IOException { ClassLoader loader = Thread.currentThread().getContextClassLoader(); String serviceName = "META-INF/services/" + PersistenceProvider.class.getName(); Enumeration resources = loader.getResources(serviceName); if (!resources.hasMoreElements()) throw new IOException(loader + " can not load any service descriptor as resource [" + serviceName + "]"); List names = new ArrayList(); while (resources.hasMoreElements()) { InputStream is = null; try { URL url = resources.nextElement(); is = url.openStream(); names.addAll(providerNamesFromReader(new BufferedReader(new InputStreamReader(is)))); } finally { if (is != null) is.close(); } } List providers = new ArrayList(); Map errors = new TreeMap(); for (String providerClassName : names) { try{ providers.add((PersistenceProvider)loader.loadClass(providerClassName).newInstance()); } catch (Throwable t){ errors.put(providerClassName, t); } } if (providers.isEmpty()) { throw new PersistenceException(createErrorMessage(names.size() + " provider(s) is(are) configured but " + loader + " can not load any one of them", errors)); } else if (!errors.isEmpty()) { System.err.println(createErrorMessage("WARNING: " + loader + " can not load following persistence provider(s).", errors)); } return providers; } private static final Pattern nonCommentPattern = Pattern.compile("^([^#]+)"); private static Set providerNamesFromReader(BufferedReader reader) throws IOException { Set names = new HashSet(); String line; while ((line = reader.readLine()) != null) { line = line.trim(); Matcher m = nonCommentPattern.matcher(line); if (m.find()) { names.add(m.group().trim()); } } return names; } private static String createErrorMessage(String header, Map errors) { StringWriter errorMessage = new StringWriter(); errorMessage.append(header).append("\r\n"); for (String providerClassName:errors.keySet()) { errorMessage.append(providerClassName); errorMessage.append(": "); errors.get(providerClassName).printStackTrace(new PrintWriter(errorMessage)); errorMessage.append("\r\n"); } return errorMessage.toString(); } /** * Prints informative message of available persistence providers in the * current classpath. * The list of persistence proviser class names are specified in one or more * META-INF/services/javax.persistence.spi.PersistenceProvider * files that are available relative to the current classpath. * Warns if any specified provider can not be loaded. * * @param args none */ public static void main(String[] args) { try { List providers = findAllProviders(); System.err.println("List of " + providers.size() + " available persistence providers:"); for (PersistenceProvider provider:providers) System.err.println(provider.getClass().getName()); } catch (Exception ex) { System.err.println(ex); } } }