001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 // 021 // This source code implements specifications defined by the Java 022 // Community Process. In order to remain compliant with the specification 023 // DO NOT add / change / or delete method signatures! 024 // 025 package javax.persistence; 026 027 import java.io.BufferedReader; 028 import java.io.IOException; 029 import java.io.InputStreamReader; 030 import java.net.URL; 031 import java.util.Collections; 032 import java.util.Enumeration; 033 import java.util.Map; 034 import java.util.HashSet; 035 import java.util.Set; 036 037 import javax.persistence.spi.PersistenceProvider; 038 039 /** 040 * @version $Rev: 529834 $ $Date: 2007-04-18 04:32:23 +0200 (Mi, 18. Apr 2007) $ 041 */ 042 043 /** 044 * Bootstrap class that is used to obtain {@link javax.persistence.EntityManagerFactory} 045 * references. 046 */ 047 public class Persistence { 048 049 protected static final Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>(); 050 // Changed to the hard coded PERSISTENCE_PROVIDER value to pass signature tests. 051 // public static final java.lang.String PERSISTENCE_PROVIDER = PersistenceProvider.class.getName(); 052 public static final java.lang.String PERSISTENCE_PROVIDER = "javax.persistence.spi.PeristenceProvider"; 053 static final String PERSISTENCE_PROVIDER_PROPERTY = "javax.persistence.provider"; 054 static final String PERSISTENCE_PROVIDER_SERVICE = "META-INF/services/" 055 + PersistenceProvider.class.getName(); 056 057 /** 058 * Create and return an EntityManagerFactory for the named persistence unit. 059 * 060 * @param persistenceUnitName The name of the persistence unit 061 * @return The factory that creates EntityManagers configured according to the 062 * specified persistence unit 063 */ 064 public static EntityManagerFactory createEntityManagerFactory( 065 String persistenceUnitName) { 066 return createEntityManagerFactory(persistenceUnitName, Collections.EMPTY_MAP); 067 } 068 069 /** 070 * Create and return an EntityManagerFactory for the named persistence unit using the 071 * given properties. 072 * 073 * @param persistenceUnitName The name of the persistence unit 074 * @param properties Additional properties to use when creating the factory. The values of 075 * these properties override any values that may have been configured 076 * elsewhere. 077 * @return The factory that creates EntityManagers configured according to the 078 * specified persistence unit. 079 */ 080 public static EntityManagerFactory createEntityManagerFactory( 081 String persistenceUnitName, 082 Map properties) { 083 084 if (properties == null) { 085 properties = Collections.EMPTY_MAP; 086 } 087 088 // start by loading a provider explicitly specified in properties. The spec 089 // doesn't seem to forbid providers that are not deployed as a service 090 Object providerName = properties.get(PERSISTENCE_PROVIDER_PROPERTY); 091 if (providerName instanceof String) { 092 EntityManagerFactory factory = createFactory( 093 providerName.toString(), 094 persistenceUnitName, 095 properties); 096 if (factory != null) { 097 return factory; 098 } 099 } 100 101 // load correctly deployed providers 102 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 103 try { 104 Enumeration<URL> providers = loader 105 .getResources(PERSISTENCE_PROVIDER_SERVICE); 106 while (providers.hasMoreElements()) { 107 108 String name = getProviderName(providers.nextElement()); 109 110 if (name != null) { 111 112 EntityManagerFactory factory = createFactory( 113 name, 114 persistenceUnitName, 115 properties); 116 117 if (factory != null) { 118 return factory; 119 } 120 } 121 } 122 } 123 catch (IOException e) { 124 // spec doesn't mention any exceptions thrown by this method 125 } 126 127 return null; 128 } 129 130 static String getProviderName(URL url) throws IOException { 131 132 BufferedReader in = new BufferedReader(new InputStreamReader( 133 url.openStream(), 134 "UTF-8")); 135 136 String providerName; 137 138 try { 139 providerName = in.readLine(); 140 } 141 finally { 142 in.close(); 143 } 144 145 if (providerName != null) { 146 providerName = providerName.trim(); 147 } 148 149 return providerName; 150 } 151 152 static EntityManagerFactory createFactory( 153 String providerName, 154 String persistenceUnitName, 155 Map properties) 156 throws PersistenceException { 157 158 Class providerClass; 159 try { 160 providerClass = Class.forName(providerName, true, Thread 161 .currentThread().getContextClassLoader()); 162 } 163 catch (Exception e) { 164 throw new PersistenceException( 165 "Invalid or inaccessible provider class: " + providerName, 166 e); 167 } 168 169 try { 170 PersistenceProvider provider = (PersistenceProvider) providerClass 171 .newInstance(); 172 return provider.createEntityManagerFactory(persistenceUnitName, 173 properties); 174 } 175 catch (Exception e) { 176 throw new PersistenceException("Provider error. Provider: " 177 + providerName, e); 178 } 179 } 180 }