/* * 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.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"; protected static Set providers = new HashSet(); /** * 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; if (providers.isEmpty()) { try{ providers = findAllProviders(); } catch (IOException exc){}; } for (PersistenceProvider provider : providers) { emf = provider.createEntityManagerFactory(persistenceUnitName, properties); if (emf != null){ break; } } if (emf == null) { throw new PersistenceException("No Persistence provider can create EntityManager named " + persistenceUnitName); } return emf; } // Helper methods private static Set 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(serviceName + " not available in classpath"); Set names = new HashSet(); while (resources.hasMoreElements()) { URL url = resources.nextElement(); InputStream is = url.openStream(); try { names.addAll(providerNamesFromReader(new BufferedReader(new InputStreamReader(is)))); } finally { is.close(); } } Set providers = new HashSet(); Map errors = new TreeMap(); for (String s : names) { try{ providers.add((PersistenceProvider)loader.loadClass(s).newInstance()); } catch (Throwable t){ errors.put(s, t); } } if (providers.isEmpty()) { throw new PersistenceException(createErrorMessage(names.size() + " provider(s) is(are) configured but can not be loaded", errors)); } else if (!errors.isEmpty()) { System.err.println(createErrorMessage("WARNING: Following specified the persistence provider(s) can not be loaded.", 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 s:errors.keySet()) { errorMessage.append(s); errorMessage.append(": "); errors.get(s).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 * @throws IOException if no META-INF/services/javax.persistence.spi.PersistenceProvider * available relative to the current classpath. */ public static void main(String[] args) throws IOException { Set providers = findAllProviders(); System.out.println("List of " + providers.size() + " available persistence providers:"); for (PersistenceProvider provider:providers) System.out.println(provider.getClass().getName()); } }