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: */package org.apache.geronimo.persistence;
017:
018: import java.io.File;
019: import java.net.MalformedURLException;
020: import java.net.URI;
021: import java.net.URISyntaxException;
022: import java.net.URL;
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.Properties;
028: import java.util.Collections;
029:
030: import javax.persistence.EntityManager;
031: import javax.persistence.EntityManagerFactory;
032: import javax.persistence.PersistenceException;
033: import javax.persistence.spi.ClassTransformer;
034: import javax.persistence.spi.PersistenceProvider;
035: import javax.persistence.spi.PersistenceUnitInfo;
036: import javax.persistence.spi.PersistenceUnitTransactionType;
037: import javax.resource.ResourceException;
038: import javax.sql.DataSource;
039:
040: import org.apache.geronimo.gbean.GBeanInfo;
041: import org.apache.geronimo.gbean.GBeanInfoBuilder;
042: import org.apache.geronimo.gbean.GBeanLifecycle;
043: import org.apache.geronimo.gbean.SingleElementCollection;
044: import org.apache.geronimo.naming.ResourceSource;
045: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
046: import org.apache.geronimo.kernel.classloader.TemporaryClassLoader;
047: import org.apache.geronimo.transaction.manager.TransactionManagerImpl;
048: import org.apache.geronimo.transformer.TransformerAgent;
049:
050: /**
051: * @version $Rev: 633225 $ $Date: 2008-03-03 10:21:31 -0800 (Mon, 03 Mar 2008) $
052: */
053: public class PersistenceUnitGBean implements GBeanLifecycle {
054: private static final List<URL> NO_URLS = Collections.emptyList();
055: private static final List<String> NO_STRINGS = Collections
056: .emptyList();
057: private final String persistenceUnitRoot;
058: private final PersistenceUnitInfoImpl persistenceUnitInfo;
059: private final EntityManagerFactory entityManagerFactory;
060: private final TransactionManagerImpl transactionManager;
061: private final SingleElementCollection<ExtendedEntityManagerRegistry> entityManagerRegistry;
062:
063: public PersistenceUnitGBean() {
064: persistenceUnitRoot = null;
065: persistenceUnitInfo = null;
066: entityManagerFactory = null;
067: transactionManager = null;
068: entityManagerRegistry = null;
069: }
070:
071: public PersistenceUnitGBean(
072: String persistenceUnitName,
073: String persistenceProviderClassName,
074: String persistenceUnitTransactionTypeString,
075: ResourceSource<ResourceException> jtaDataSourceWrapper,
076: ResourceSource<ResourceException> nonJtaDataSourceWrapper,
077: List<String> mappingFileNamesUntyped,
078: List<String> jarFileUrlsUntyped,
079: String persistenceUnitRoot,
080: List<String> managedClassNames,
081: boolean excludeUnlistedClassesValue,
082: Properties properties,
083: TransactionManagerImpl transactionManager,
084: Collection<ExtendedEntityManagerRegistry> entityManagerRegistry,
085: URL configurationBaseURL, ClassLoader classLoader)
086: throws URISyntaxException, MalformedURLException,
087: ResourceException {
088: List<String> mappingFileNames = mappingFileNamesUntyped == null ? NO_STRINGS
089: : new ArrayList<String>(mappingFileNamesUntyped);
090: this .persistenceUnitRoot = persistenceUnitRoot;
091: URI configurationBaseURI = new File(configurationBaseURL
092: .getFile()).toURI();
093: URL rootURL = configurationBaseURI.resolve(persistenceUnitRoot)
094: .normalize().toURL();
095: List<URL> jarFileUrls = NO_URLS;
096: if (!excludeUnlistedClassesValue) {
097: jarFileUrls = new ArrayList<URL>();
098: for (String urlString : jarFileUrlsUntyped) {
099: URL url = configurationBaseURI.resolve(urlString)
100: .normalize().toURL();
101: jarFileUrls.add(url);
102: }
103: }
104: if (managedClassNames == null) {
105: managedClassNames = NO_STRINGS;
106: }
107: if (properties == null) {
108: properties = new Properties();
109: }
110: PersistenceUnitTransactionType persistenceUnitTransactionType = persistenceUnitTransactionTypeString == null ? PersistenceUnitTransactionType.JTA
111: : PersistenceUnitTransactionType
112: .valueOf(persistenceUnitTransactionTypeString);
113:
114: if (persistenceProviderClassName == null)
115: persistenceProviderClassName = "org.apache.openjpa.persistence.PersistenceProviderImpl";
116:
117: persistenceUnitInfo = new PersistenceUnitInfoImpl(
118: persistenceUnitName, persistenceProviderClassName,
119: persistenceUnitTransactionType,
120: jtaDataSourceWrapper == null ? null
121: : (DataSource) jtaDataSourceWrapper
122: .$getResource(),
123: nonJtaDataSourceWrapper == null ? null
124: : (DataSource) nonJtaDataSourceWrapper
125: .$getResource(), mappingFileNames,
126: jarFileUrls, rootURL, managedClassNames,
127: excludeUnlistedClassesValue, properties, classLoader);
128: try {
129: Class clazz = classLoader
130: .loadClass(persistenceProviderClassName);
131: PersistenceProvider persistenceProvider = (PersistenceProvider) clazz
132: .newInstance();
133: entityManagerFactory = persistenceProvider
134: .createContainerEntityManagerFactory(
135: persistenceUnitInfo, properties);
136: } catch (ClassNotFoundException e) {
137: persistenceUnitInfo.destroy();
138: throw new PersistenceException(
139: "Could not locate PersistenceProvider class: "
140: + persistenceProviderClassName
141: + " in classloader " + classLoader, e);
142: } catch (InstantiationException e) {
143: persistenceUnitInfo.destroy();
144: throw new PersistenceException(
145: "Could not create PersistenceProvider instance: "
146: + persistenceProviderClassName
147: + " loaded from classloader " + classLoader,
148: e);
149: } catch (IllegalAccessException e) {
150: persistenceUnitInfo.destroy();
151: throw new PersistenceException(
152: "Could not create PersistenceProvider instance: "
153: + persistenceProviderClassName
154: + " loaded from classloader " + classLoader,
155: e);
156: }
157: this .transactionManager = transactionManager;
158: this .entityManagerRegistry = new SingleElementCollection<ExtendedEntityManagerRegistry>(
159: entityManagerRegistry);
160: }
161:
162: public EntityManagerFactory getEntityManagerFactory() {
163: return entityManagerFactory;
164: }
165:
166: public EntityManager getEntityManager(boolean transactionScoped,
167: Map properties) {
168: if (transactionScoped) {
169: return new CMPEntityManagerTxScoped(transactionManager,
170: getPersistenceUnitName(), entityManagerFactory,
171: properties);
172: } else if (entityManagerRegistry.getElement() != null) {
173: return new CMPEntityManagerExtended(entityManagerRegistry
174: .getElement(), entityManagerFactory, properties);
175: } else {
176: throw new NullPointerException(
177: "No ExtendedEntityManagerRegistry supplied, you cannot use extended persistence contexts");
178: }
179: }
180:
181: public String getPersistenceUnitName() {
182: return persistenceUnitInfo.getPersistenceUnitName();
183: }
184:
185: public String getPersistenceUnitRoot() {
186: return persistenceUnitRoot;
187: }
188:
189: public String getPersistenceProviderClassName() {
190: return persistenceUnitInfo.getPersistenceProviderClassName();
191: }
192:
193: public PersistenceUnitTransactionType getTransactionType() {
194: return persistenceUnitInfo.getTransactionType();
195: }
196:
197: public DataSource getJtaDataSource() {
198: return persistenceUnitInfo.getJtaDataSource();
199: }
200:
201: public DataSource getNonJtaDataSource() {
202: return persistenceUnitInfo.getNonJtaDataSource();
203: }
204:
205: public List<String> getMappingFileNames() {
206: return persistenceUnitInfo.getMappingFileNames();
207: }
208:
209: public List<URL> getJarFileUrls() {
210: return persistenceUnitInfo.getJarFileUrls();
211: }
212:
213: public URL getPersistenceUnitRootUrl() {
214: return persistenceUnitInfo.getPersistenceUnitRootUrl();
215: }
216:
217: public List<String> getManagedClassNames() {
218: return persistenceUnitInfo.getManagedClassNames();
219: }
220:
221: public boolean excludeUnlistedClasses() {
222: return persistenceUnitInfo.excludeUnlistedClasses();
223: }
224:
225: public Properties getProperties() {
226: return persistenceUnitInfo.getProperties();
227: }
228:
229: public ClassLoader getClassLoader() {
230: return persistenceUnitInfo.getClassLoader();
231: }
232:
233: public void addTransformer(ClassTransformer classTransformer) {
234: persistenceUnitInfo.addTransformer(classTransformer);
235: }
236:
237: public ClassLoader getNewTempClassLoader() {
238: return persistenceUnitInfo.getNewTempClassLoader();
239: }
240:
241: public void doStart() throws Exception {
242: }
243:
244: public void doStop() throws Exception {
245: //TODO remove any classtransformers added
246: entityManagerFactory.close();
247: persistenceUnitInfo.destroy();
248: }
249:
250: public void doFail() {
251: entityManagerFactory.close();
252: persistenceUnitInfo.destroy();
253: }
254:
255: private static class PersistenceUnitInfoImpl implements
256: PersistenceUnitInfo {
257: private final String persistenceUnitName;
258: private final String persistenceProviderClassName;
259: private final PersistenceUnitTransactionType persistenceUnitTransactionType;
260: private final DataSource jtaDataSource;
261: private final DataSource nonJtaDataSource;
262: private final List<String> mappingFileNames;
263: private final List<URL> jarFileUrls;
264: private final URL persistenceUnitRootUrl;
265: private final List<String> managedClassNames;
266: private final boolean excludeUnlistedClassesValue;
267: private final Properties properties;
268: private final ClassLoader classLoader;
269: private final TemporaryClassLoader tempClassLoader;
270: private final List<TransformerWrapper> transformers;
271:
272: public PersistenceUnitInfoImpl(
273: String persistenceUnitName,
274: String persistenceProviderClassName,
275: PersistenceUnitTransactionType persistenceUnitTransactionType,
276: DataSource jtaDataSource, DataSource nonJtaDataSource,
277: List<String> mappingFileNames, List<URL> jarFileUrls,
278: URL persistenceUnitRootUrl,
279: List<String> managedClassNames,
280: boolean excludeUnlistedClassesValue,
281: Properties properties, ClassLoader classLoader) {
282: this .persistenceUnitName = persistenceUnitName;
283: this .persistenceProviderClassName = persistenceProviderClassName;
284: this .persistenceUnitTransactionType = persistenceUnitTransactionType;
285: this .jtaDataSource = jtaDataSource;
286: this .nonJtaDataSource = nonJtaDataSource;
287: this .mappingFileNames = mappingFileNames;
288: this .jarFileUrls = jarFileUrls;
289: this .persistenceUnitRootUrl = persistenceUnitRootUrl;
290: this .managedClassNames = managedClassNames;
291: this .excludeUnlistedClassesValue = excludeUnlistedClassesValue;
292: this .properties = properties;
293: this .classLoader = classLoader;
294: this .transformers = new ArrayList<TransformerWrapper>();
295:
296: // This classloader can only be used during PersistenceProvider.createContainerEntityManagerFactory() calls
297: // Possible that it could be cleaned up sooner, but for now it's destroyed when the PUGBean is stopped
298: this .tempClassLoader = new TemporaryClassLoader(classLoader);
299: }
300:
301: public String getPersistenceUnitName() {
302: return persistenceUnitName;
303: }
304:
305: public String getPersistenceProviderClassName() {
306: return persistenceProviderClassName;
307: }
308:
309: public PersistenceUnitTransactionType getTransactionType() {
310: return persistenceUnitTransactionType;
311: }
312:
313: public DataSource getJtaDataSource() {
314: return jtaDataSource;
315: }
316:
317: public DataSource getNonJtaDataSource() {
318: return nonJtaDataSource;
319: }
320:
321: public List<String> getMappingFileNames() {
322: return mappingFileNames;
323: }
324:
325: public List<URL> getJarFileUrls() {
326: return jarFileUrls;
327: }
328:
329: public URL getPersistenceUnitRootUrl() {
330: return persistenceUnitRootUrl;
331: }
332:
333: public List<String> getManagedClassNames() {
334: return managedClassNames;
335: }
336:
337: public boolean excludeUnlistedClasses() {
338: return excludeUnlistedClassesValue;
339: }
340:
341: public Properties getProperties() {
342: return properties;
343: }
344:
345: public ClassLoader getClassLoader() {
346: return classLoader;
347: }
348:
349: public void addTransformer(ClassTransformer classTransformer) {
350: TransformerWrapper transformer = new TransformerWrapper(
351: classTransformer, classLoader);
352: transformers.add(transformer);
353: TransformerAgent.addTransformer(transformer);
354: }
355:
356: public ClassLoader getNewTempClassLoader() {
357: return tempClassLoader;
358: }
359:
360: private void destroy() {
361: for (TransformerWrapper t : transformers) {
362: TransformerAgent.removeTransformer(t);
363: }
364: }
365:
366: }
367:
368: public static final GBeanInfo GBEAN_INFO;
369:
370: static {
371: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(
372: PersistenceUnitGBean.class,
373: NameFactory.PERSISTENCE_UNIT);
374: infoBuilder.setPriority(GBeanInfo.PRIORITY_CLASSLOADER);
375:
376: infoBuilder.addAttribute("persistenceUnitName", String.class,
377: true, true);
378: infoBuilder.addAttribute("persistenceProviderClassName",
379: String.class, true, true);
380: infoBuilder.addAttribute("persistenceUnitTransactionType",
381: String.class, true, true);
382: infoBuilder.addAttribute("mappingFileNames", List.class, true,
383: true);
384: infoBuilder.addAttribute("jarFileUrls", List.class, true, true);
385: infoBuilder.addAttribute("persistenceUnitRoot", String.class,
386: true, true);
387: infoBuilder.addAttribute("managedClassNames", List.class, true,
388: true);
389: infoBuilder.addAttribute("excludeUnlistedClasses",
390: boolean.class, true, true);
391: infoBuilder.addAttribute("properties", Properties.class, true,
392: true);
393: infoBuilder.addAttribute("configurationBaseUrl", URL.class,
394: true);
395:
396: infoBuilder.addReference("TransactionManager",
397: TransactionManagerImpl.class, NameFactory.JTA_RESOURCE);
398: infoBuilder.addReference("JtaDataSourceWrapper",
399: ResourceSource.class,
400: NameFactory.JCA_MANAGED_CONNECTION_FACTORY);
401: infoBuilder.addReference("NonJtaDataSourceWrapper",
402: ResourceSource.class,
403: NameFactory.JCA_MANAGED_CONNECTION_FACTORY);
404: infoBuilder.addReference("EntityManagerRegistry",
405: ExtendedEntityManagerRegistry.class,
406: NameFactory.GERONIMO_SERVICE);
407:
408: infoBuilder.setConstructor(new String[] {
409: "persistenceUnitName", "persistenceProviderClassName",
410: "persistenceUnitTransactionType",
411: "JtaDataSourceWrapper", "NonJtaDataSourceWrapper",
412: "mappingFileNames", "jarFileUrls",
413: "persistenceUnitRoot", "managedClassNames",
414: "excludeUnlistedClasses", "properties",
415: "TransactionManager", "EntityManagerRegistry",
416: "configurationBaseUrl", "classLoader" });
417:
418: GBEAN_INFO = infoBuilder.getBeanInfo();
419:
420: }
421:
422: public static GBeanInfo getGBeanInfo() {
423: return GBEAN_INFO;
424: }
425:
426: }
|