001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.persistence; 019 020 import java.io.File; 021 import java.net.MalformedURLException; 022 import java.net.URI; 023 import java.net.URISyntaxException; 024 import java.net.URL; 025 import java.util.ArrayList; 026 import java.util.Collection; 027 import java.util.List; 028 import java.util.Map; 029 import java.util.Properties; 030 031 import javax.persistence.EntityManager; 032 import javax.persistence.EntityManagerFactory; 033 import javax.persistence.PersistenceException; 034 import javax.persistence.spi.ClassTransformer; 035 import javax.persistence.spi.PersistenceProvider; 036 import javax.persistence.spi.PersistenceUnitInfo; 037 import javax.persistence.spi.PersistenceUnitTransactionType; 038 import javax.sql.DataSource; 039 import javax.resource.ResourceException; 040 041 import org.apache.geronimo.connector.outbound.ConnectionFactorySource; 042 import org.apache.geronimo.gbean.GBeanInfo; 043 import org.apache.geronimo.gbean.GBeanInfoBuilder; 044 import org.apache.geronimo.gbean.GBeanLifecycle; 045 import org.apache.geronimo.gbean.SingleElementCollection; 046 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 047 import org.apache.geronimo.kernel.classloader.TemporaryClassLoader; 048 import org.apache.geronimo.transaction.manager.TransactionManagerImpl; 049 import org.apache.geronimo.transformer.TransformerAgent; 050 051 /** 052 * @version $Rev: 545396 $ $Date: 2007-06-07 23:49:40 -0400 (Thu, 07 Jun 2007) $ 053 */ 054 public class PersistenceUnitGBean implements GBeanLifecycle { 055 private final String persistenceUnitRoot; 056 private final PersistenceUnitInfoImpl persistenceUnitInfo; 057 private final EntityManagerFactory entityManagerFactory; 058 private final TransactionManagerImpl transactionManager; 059 private final SingleElementCollection<ExtendedEntityManagerRegistry> entityManagerRegistry; 060 061 062 public PersistenceUnitGBean() { 063 persistenceUnitRoot = null; 064 persistenceUnitInfo = null; 065 entityManagerFactory = null; 066 transactionManager = null; 067 entityManagerRegistry = null; 068 } 069 070 public PersistenceUnitGBean(String persistenceUnitName, 071 String persistenceProviderClassName, 072 String persistenceUnitTransactionTypeString, 073 ConnectionFactorySource jtaDataSourceWrapper, 074 ConnectionFactorySource nonJtaDataSourceWrapper, 075 List<String> mappingFileNamesUntyped, 076 List<String> jarFileUrlsUntyped, 077 String persistenceUnitRoot, 078 List<String> managedClassNames, 079 boolean excludeUnlistedClassesValue, 080 Properties properties, 081 TransactionManagerImpl transactionManager, 082 Collection<ExtendedEntityManagerRegistry > entityManagerRegistry, 083 URL configurationBaseURL, 084 ClassLoader classLoader) throws URISyntaxException, MalformedURLException, ResourceException { 085 List<String> mappingFileNames = mappingFileNamesUntyped == null? new ArrayList<String>(): new ArrayList<String>(mappingFileNamesUntyped); 086 this.persistenceUnitRoot = persistenceUnitRoot; 087 URI configurationBaseURI = new File(configurationBaseURL.getFile()).toURI(); 088 URL rootURL = null; 089 List<URL> jarFileUrls = null; 090 if (!excludeUnlistedClassesValue) { 091 rootURL = configurationBaseURI.resolve(persistenceUnitRoot).normalize().toURL(); 092 jarFileUrls = new ArrayList<URL>(); 093 for (String urlString: jarFileUrlsUntyped) { 094 URL url = configurationBaseURI.resolve(urlString).normalize().toURL(); 095 jarFileUrls.add(url); 096 } 097 } 098 PersistenceUnitTransactionType persistenceUnitTransactionType = persistenceUnitTransactionTypeString == null? PersistenceUnitTransactionType.JTA: PersistenceUnitTransactionType.valueOf(persistenceUnitTransactionTypeString); 099 100 if (persistenceProviderClassName == null) persistenceProviderClassName = "org.apache.openjpa.persistence.PersistenceProviderImpl"; 101 102 persistenceUnitInfo = new PersistenceUnitInfoImpl(persistenceUnitName, 103 persistenceProviderClassName, 104 persistenceUnitTransactionType, 105 jtaDataSourceWrapper == null? null: (DataSource)jtaDataSourceWrapper.$getResource(), 106 nonJtaDataSourceWrapper == null? null: (DataSource)nonJtaDataSourceWrapper.$getResource(), 107 mappingFileNames, 108 jarFileUrls, 109 rootURL, 110 managedClassNames, 111 excludeUnlistedClassesValue, 112 properties, 113 classLoader); 114 try { 115 Class clazz = classLoader.loadClass(persistenceProviderClassName); 116 PersistenceProvider persistenceProvider = (PersistenceProvider) clazz.newInstance(); 117 entityManagerFactory = persistenceProvider.createContainerEntityManagerFactory(persistenceUnitInfo, properties); 118 } catch (ClassNotFoundException e) { 119 persistenceUnitInfo.destroy(); 120 throw new PersistenceException("Could not locate PersistenceProvider class: " + persistenceProviderClassName + " in classloader " + classLoader, e); 121 } catch (InstantiationException e) { 122 persistenceUnitInfo.destroy(); 123 throw new PersistenceException("Could not create PersistenceProvider instance: " + persistenceProviderClassName + " loaded from classloader " + classLoader, e); 124 } catch (IllegalAccessException e) { 125 persistenceUnitInfo.destroy(); 126 throw new PersistenceException("Could not create PersistenceProvider instance: " + persistenceProviderClassName + " loaded from classloader " + classLoader, e); 127 } 128 this.transactionManager = transactionManager; 129 this.entityManagerRegistry = new SingleElementCollection<ExtendedEntityManagerRegistry>(entityManagerRegistry); 130 } 131 132 public EntityManagerFactory getEntityManagerFactory() { 133 return entityManagerFactory; 134 } 135 136 public EntityManager getEntityManager(boolean transactionScoped, Map properties) { 137 if (transactionScoped) { 138 return new CMPEntityManagerTxScoped(transactionManager, getPersistenceUnitName(), entityManagerFactory, properties); 139 } else if (entityManagerRegistry.getElement() != null) { 140 return new CMPEntityManagerExtended(entityManagerRegistry.getElement(), entityManagerFactory, properties); 141 } else { 142 throw new NullPointerException("No ExtendedEntityManagerRegistry supplied, you cannot use extended persistence contexts"); 143 } 144 } 145 146 public String getPersistenceUnitName() { 147 return persistenceUnitInfo.getPersistenceUnitName(); 148 } 149 150 151 public String getPersistenceUnitRoot() { 152 return persistenceUnitRoot; 153 } 154 155 public String getPersistenceProviderClassName() { 156 return persistenceUnitInfo.getPersistenceProviderClassName(); 157 } 158 159 public PersistenceUnitTransactionType getTransactionType() { 160 return persistenceUnitInfo.getTransactionType(); 161 } 162 163 public DataSource getJtaDataSource() { 164 return persistenceUnitInfo.getJtaDataSource(); 165 } 166 167 public DataSource getNonJtaDataSource() { 168 return persistenceUnitInfo.getNonJtaDataSource(); 169 } 170 171 public List<String> getMappingFileNames() { 172 return persistenceUnitInfo.getMappingFileNames(); 173 } 174 175 public List<URL> getJarFileUrls() { 176 return persistenceUnitInfo.getJarFileUrls(); 177 } 178 179 public URL getPersistenceUnitRootUrl() { 180 return persistenceUnitInfo.getPersistenceUnitRootUrl(); 181 } 182 183 public List<String> getManagedClassNames() { 184 return persistenceUnitInfo.getManagedClassNames(); 185 } 186 187 public boolean excludeUnlistedClasses() { 188 return persistenceUnitInfo.excludeUnlistedClasses(); 189 } 190 191 public Properties getProperties() { 192 return persistenceUnitInfo.getProperties(); 193 } 194 195 public ClassLoader getClassLoader() { 196 return persistenceUnitInfo.getClassLoader(); 197 } 198 199 public void addTransformer(ClassTransformer classTransformer) { 200 persistenceUnitInfo.addTransformer(classTransformer); 201 } 202 203 public ClassLoader getNewTempClassLoader() { 204 return persistenceUnitInfo.getNewTempClassLoader(); 205 } 206 207 public void doStart() throws Exception { 208 } 209 210 public void doStop() throws Exception { 211 //TODO remove any classtransformers added 212 entityManagerFactory.close(); 213 persistenceUnitInfo.destroy(); 214 } 215 216 public void doFail() { 217 entityManagerFactory.close(); 218 persistenceUnitInfo.destroy(); 219 } 220 221 private static class PersistenceUnitInfoImpl implements PersistenceUnitInfo { 222 private final String persistenceUnitName; 223 private final String persistenceProviderClassName; 224 private final PersistenceUnitTransactionType persistenceUnitTransactionType; 225 private final DataSource jtaDataSource; 226 private final DataSource nonJtaDataSource; 227 private final List<String> mappingFileNames; 228 private final List<URL> jarFileUrls; 229 private final URL persistenceUnitRootUrl; 230 private final List<String> managedClassNames; 231 private final boolean excludeUnlistedClassesValue; 232 private final Properties properties; 233 private final ClassLoader classLoader; 234 private final TemporaryClassLoader tempClassLoader; 235 private final List<TransformerWrapper> transformers; 236 237 238 public PersistenceUnitInfoImpl(String persistenceUnitName, String persistenceProviderClassName, PersistenceUnitTransactionType persistenceUnitTransactionType, DataSource jtaDataSource, DataSource nonJtaDataSource, List<String> mappingFileNames, List<URL> jarFileUrls, URL persistenceUnitRootUrl, List<String> managedClassNames, boolean excludeUnlistedClassesValue, Properties properties, ClassLoader classLoader) { 239 this.persistenceUnitName = persistenceUnitName; 240 this.persistenceProviderClassName = persistenceProviderClassName; 241 this.persistenceUnitTransactionType = persistenceUnitTransactionType; 242 this.jtaDataSource = jtaDataSource; 243 this.nonJtaDataSource = nonJtaDataSource; 244 this.mappingFileNames = mappingFileNames; 245 this.jarFileUrls = jarFileUrls; 246 this.persistenceUnitRootUrl = persistenceUnitRootUrl; 247 this.managedClassNames = managedClassNames; 248 this.excludeUnlistedClassesValue = excludeUnlistedClassesValue; 249 this.properties = properties; 250 this.classLoader = classLoader; 251 this.transformers = new ArrayList<TransformerWrapper>(); 252 253 // This classloader can only be used during PersistenceProvider.createContainerEntityManagerFactory() calls 254 // Possible that it could be cleaned up sooner, but for now it's destroyed when the PUGBean is stopped 255 this.tempClassLoader = new TemporaryClassLoader(classLoader); 256 } 257 258 public String getPersistenceUnitName() { 259 return persistenceUnitName; 260 } 261 262 public String getPersistenceProviderClassName() { 263 return persistenceProviderClassName; 264 } 265 266 public PersistenceUnitTransactionType getTransactionType() { 267 return persistenceUnitTransactionType; 268 } 269 270 public DataSource getJtaDataSource() { 271 return jtaDataSource; 272 } 273 274 public DataSource getNonJtaDataSource() { 275 return nonJtaDataSource; 276 } 277 278 public List<String> getMappingFileNames() { 279 return mappingFileNames; 280 } 281 282 public List<URL> getJarFileUrls() { 283 return jarFileUrls; 284 } 285 286 public URL getPersistenceUnitRootUrl() { 287 return persistenceUnitRootUrl; 288 } 289 290 public List<String> getManagedClassNames() { 291 return managedClassNames; 292 } 293 294 public boolean excludeUnlistedClasses() { 295 return excludeUnlistedClassesValue; 296 } 297 298 public Properties getProperties() { 299 return properties; 300 } 301 302 public ClassLoader getClassLoader() { 303 return classLoader; 304 } 305 306 public void addTransformer(ClassTransformer classTransformer) { 307 TransformerWrapper transformer = new TransformerWrapper(classTransformer, classLoader); 308 transformers.add(transformer); 309 TransformerAgent.addTransformer(transformer); 310 } 311 312 public ClassLoader getNewTempClassLoader() { 313 return tempClassLoader; 314 } 315 316 private void destroy() { 317 for (TransformerWrapper t : transformers) { 318 TransformerAgent.removeTransformer(t); 319 } 320 } 321 322 } 323 324 public static final GBeanInfo GBEAN_INFO; 325 326 static { 327 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(PersistenceUnitGBean.class, NameFactory.PERSISTENCE_UNIT); 328 infoBuilder.setPriority(GBeanInfo.PRIORITY_CLASSLOADER); 329 330 infoBuilder.addAttribute("persistenceUnitName", String.class, true, true); 331 infoBuilder.addAttribute("persistenceProviderClassName", String.class, true, true); 332 infoBuilder.addAttribute("persistenceUnitTransactionType", String.class, true, true); 333 infoBuilder.addAttribute("mappingFileNames", List.class, true, true); 334 infoBuilder.addAttribute("jarFileUrls", List.class, true, true); 335 infoBuilder.addAttribute("persistenceUnitRoot", String.class, true, true); 336 infoBuilder.addAttribute("managedClassNames", List.class, true, true); 337 infoBuilder.addAttribute("excludeUnlistedClasses", boolean.class, true, true); 338 infoBuilder.addAttribute("properties", Properties.class, true, true); 339 infoBuilder.addAttribute("configurationBaseUrl", URL.class, true); 340 341 infoBuilder.addReference("TransactionManager", TransactionManagerImpl.class, NameFactory.TRANSACTION_MANAGER); 342 infoBuilder.addReference("JtaDataSourceWrapper", ConnectionFactorySource.class, NameFactory.JCA_MANAGED_CONNECTION_FACTORY); 343 infoBuilder.addReference("NonJtaDataSourceWrapper", ConnectionFactorySource.class, NameFactory.JCA_MANAGED_CONNECTION_FACTORY); 344 infoBuilder.addReference("EntityManagerRegistry", ExtendedEntityManagerRegistry.class, NameFactory.GERONIMO_SERVICE); 345 346 infoBuilder.setConstructor(new String[] { 347 "persistenceUnitName", 348 "persistenceProviderClassName", 349 "persistenceUnitTransactionType", 350 "JtaDataSourceWrapper", 351 "NonJtaDataSourceWrapper", 352 "mappingFileNames", 353 "jarFileUrls", 354 "persistenceUnitRoot", 355 "managedClassNames", 356 "excludeUnlistedClasses", 357 "properties", 358 "TransactionManager", 359 "EntityManagerRegistry", 360 "configurationBaseUrl", 361 "classLoader" 362 }); 363 364 GBEAN_INFO = infoBuilder.getBeanInfo(); 365 366 } 367 368 public static GBeanInfo getGBeanInfo() { 369 return GBEAN_INFO; 370 } 371 372 }