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.util.List;
021    import java.util.Properties;
022    import java.util.Map;
023    import java.util.ArrayList;
024    import java.net.URL;
025    
026    import javax.persistence.spi.PersistenceUnitInfo;
027    import javax.persistence.spi.PersistenceUnitTransactionType;
028    import javax.persistence.spi.ClassTransformer;
029    import javax.persistence.spi.PersistenceProvider;
030    import javax.persistence.EntityManagerFactory;
031    import javax.persistence.PersistenceException;
032    import javax.persistence.EntityManager;
033    import javax.sql.DataSource;
034    
035    import org.apache.geronimo.gbean.GBeanInfo;
036    import org.apache.geronimo.gbean.GBeanInfoBuilder;
037    import org.apache.geronimo.gbean.GBeanLifecycle;
038    import org.apache.geronimo.transaction.manager.TransactionManagerImpl;
039    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
040    import org.apache.geronimo.connector.outbound.ConnectionFactorySource;
041    import org.apache.geronimo.transformer.TransformerAgent;
042    import org.apache.geronimo.kernel.classloader.JarFileClassLoader;
043    
044    /**
045     * @version $Rev: 487175 $ $Date: 2006-12-14 03:10:31 -0800 (Thu, 14 Dec 2006) $
046     */
047    public class PersistenceUnitGBean implements GBeanLifecycle {
048    
049        private final PersistenceUnitInfoImpl persistenceUnitInfo;
050        private final EntityManagerFactory entityManagerFactory;
051        private final TransactionManagerImpl transactionManager;
052    
053    
054        public PersistenceUnitGBean() {
055            persistenceUnitInfo = null;
056            entityManagerFactory = null;
057            transactionManager = null;
058        }
059    
060        public PersistenceUnitGBean(String persistenceUnitName,
061                String persistenceProviderClassName,
062                String persistenceUnitTransactionTypeString,
063                ConnectionFactorySource jtaDataSourceWrapper,
064                ConnectionFactorySource nonJtaDataSourceWrapper,
065                List mappingFileNamesUntyped,
066                List jarFileUrlsUntyped,
067                URL persistenceUnitRootUrl,
068                List managedClassNamesUntyped,
069                boolean excludeUnlistedClassesValue,
070                Properties properties,
071                TransactionManagerImpl transactionManager,
072                ClassLoader classLoader) {
073            List<String> mappingFileNames = mappingFileNamesUntyped == null? new ArrayList<String>(): new ArrayList<String>(mappingFileNamesUntyped);
074            List<URL> jarFileUrls = jarFileUrlsUntyped == null? new ArrayList<URL>(): new ArrayList<URL>(jarFileUrlsUntyped);
075            List<String> managedClassNames = managedClassNamesUntyped == null? new ArrayList<String>(): new ArrayList<String>(managedClassNamesUntyped);
076            PersistenceUnitTransactionType persistenceUnitTransactionType = persistenceUnitTransactionTypeString == null? PersistenceUnitTransactionType.JTA: PersistenceUnitTransactionType.valueOf(persistenceUnitTransactionTypeString);
077    
078            persistenceUnitInfo = new PersistenceUnitInfoImpl(persistenceUnitName,
079                    persistenceProviderClassName,
080                    persistenceUnitTransactionType,
081                    jtaDataSourceWrapper == null? null: (DataSource)jtaDataSourceWrapper.$getResource(),
082                    nonJtaDataSourceWrapper == null? null: (DataSource)nonJtaDataSourceWrapper.$getResource(),
083                    mappingFileNames,
084                    jarFileUrls,
085                    persistenceUnitRootUrl,
086                    managedClassNames,
087                    excludeUnlistedClassesValue,
088                    properties,
089                    classLoader);
090            try {
091                Class clazz = classLoader.loadClass(persistenceProviderClassName);
092                PersistenceProvider persistenceProvider = (PersistenceProvider) clazz.newInstance();
093                entityManagerFactory = persistenceProvider.createContainerEntityManagerFactory(persistenceUnitInfo, properties);
094            } catch (ClassNotFoundException e) {
095                throw new PersistenceException("Could not locate PersistenceProvider class: " + persistenceProviderClassName + " in classloader " + classLoader, e);
096            } catch (InstantiationException e) {
097                throw new PersistenceException("Could not create PersistenceProvider instance: " + persistenceProviderClassName + " loaded from classloader " + classLoader, e);
098            } catch (IllegalAccessException e) {
099                throw new PersistenceException("Could not create PersistenceProvider instance: " + persistenceProviderClassName + " loaded from classloader " + classLoader, e);
100            }
101            this.transactionManager = transactionManager;
102        }
103    
104        public EntityManagerFactory getEntityManagerFactory() {
105            return entityManagerFactory;
106        }
107    
108        public EntityManager getEntityManager(boolean transactionScoped, Map properties) {
109            if (transactionScoped) {
110                return new CMPEntityManagerTxScoped(transactionManager, getPersistenceUnitName(), entityManagerFactory, properties);
111            } else {
112                return new CMPEntityManagerExtended(transactionManager, getPersistenceUnitName(), entityManagerFactory, properties);
113            }
114        }
115    
116        public String getPersistenceUnitName() {
117            return persistenceUnitInfo.getPersistenceUnitName();
118        }
119    
120        public String getPersistenceProviderClassName() {
121            return persistenceUnitInfo.getPersistenceProviderClassName();
122        }
123    
124        public PersistenceUnitTransactionType getTransactionType() {
125            return persistenceUnitInfo.getTransactionType();
126        }
127    
128        public DataSource getJtaDataSource() {
129            return persistenceUnitInfo.getJtaDataSource();
130        }
131    
132        public DataSource getNonJtaDataSource() {
133            return persistenceUnitInfo.getNonJtaDataSource();
134        }
135    
136        public List<String> getMappingFileNames() {
137            return persistenceUnitInfo.getMappingFileNames();
138        }
139    
140        public List<URL> getJarFileUrls() {
141            return persistenceUnitInfo.getJarFileUrls();
142        }
143    
144        public URL getPersistenceUnitRootUrl() {
145            return persistenceUnitInfo.getPersistenceUnitRootUrl();
146        }
147    
148        public List<String> getManagedClassNames() {
149            return persistenceUnitInfo.getManagedClassNames();
150        }
151    
152        public boolean excludeUnlistedClasses() {
153            return persistenceUnitInfo.excludeUnlistedClasses();
154        }
155    
156        public Properties getProperties() {
157            return persistenceUnitInfo.getProperties();
158        }
159    
160        public ClassLoader getClassLoader() {
161            return persistenceUnitInfo.getClassLoader();
162        }
163    
164        public void addTransformer(ClassTransformer classTransformer) {
165            persistenceUnitInfo.addTransformer(classTransformer);
166        }
167    
168        public ClassLoader getNewTempClassLoader() {
169            return persistenceUnitInfo.getNewTempClassLoader();
170        }
171    
172        public void doStart() throws Exception {
173        }
174    
175        public void doStop() throws Exception {
176            //TODO remove any classtransformers added
177            entityManagerFactory.close();
178        }
179    
180        public void doFail() {
181            entityManagerFactory.close();
182        }
183    
184        private static class PersistenceUnitInfoImpl implements PersistenceUnitInfo {
185            private final String persistenceUnitName;
186            private final String persistenceProviderClassName;
187            private final PersistenceUnitTransactionType persistenceUnitTransactionType;
188            private final DataSource jtaDataSource;
189            private final DataSource nonJtaDataSource;
190            private final List<String> mappingFileNames;
191            private final List<URL> jarFileUrls;
192            private final URL persistenceUnitRootUrl;
193            private final List<String> managedClassNames;
194            private final boolean excludeUnlistedClassesValue;
195            private final Properties properties;
196            private final ClassLoader classLoader;
197    
198    
199            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) {
200                this.persistenceUnitName = persistenceUnitName;
201                this.persistenceProviderClassName = persistenceProviderClassName;
202                this.persistenceUnitTransactionType = persistenceUnitTransactionType;
203                this.jtaDataSource = jtaDataSource;
204                this.nonJtaDataSource = nonJtaDataSource;
205                this.mappingFileNames = mappingFileNames;
206                this.jarFileUrls = jarFileUrls;
207                this.persistenceUnitRootUrl = persistenceUnitRootUrl;
208                this.managedClassNames = managedClassNames;
209                this.excludeUnlistedClassesValue = excludeUnlistedClassesValue;
210                this.properties = properties;
211                this.classLoader = classLoader;
212            }
213    
214            public String getPersistenceUnitName() {
215                return persistenceUnitName;
216            }
217    
218            public String getPersistenceProviderClassName() {
219                return persistenceProviderClassName;
220            }
221    
222            public PersistenceUnitTransactionType getTransactionType() {
223                return persistenceUnitTransactionType;
224            }
225    
226            public DataSource getJtaDataSource() {
227                return jtaDataSource;
228            }
229    
230            public DataSource getNonJtaDataSource() {
231                return nonJtaDataSource;
232            }
233    
234            public List<String> getMappingFileNames() {
235                return mappingFileNames;
236            }
237    
238            public List<URL> getJarFileUrls() {
239                return jarFileUrls;
240            }
241    
242            public URL getPersistenceUnitRootUrl() {
243                return persistenceUnitRootUrl;
244            }
245    
246            public List<String> getManagedClassNames() {
247                return managedClassNames;
248            }
249    
250            public boolean excludeUnlistedClasses() {
251                return excludeUnlistedClassesValue;
252            }
253    
254            public Properties getProperties() {
255                return properties;
256            }
257    
258            public ClassLoader getClassLoader() {
259                return classLoader;
260            }
261    
262            public void addTransformer(ClassTransformer classTransformer) {
263                TransformerAgent.addTransformer(new TransformerWrapper(classTransformer, classLoader));
264            }
265    
266            public ClassLoader getNewTempClassLoader() {
267                return JarFileClassLoader.copy(classLoader);
268            }
269    
270        }
271    
272        public static final GBeanInfo GBEAN_INFO;
273    
274        static {
275            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(PersistenceUnitGBean.class);
276            infoBuilder.setPriority(GBeanInfo.PRIORITY_CLASSLOADER);
277    
278            infoBuilder.addAttribute("persistenceUnitName", String.class, true, true);
279            infoBuilder.addAttribute("persistenceProviderClassName", String.class, true, true);
280            infoBuilder.addAttribute("persistenceUnitTransactionType", String.class, true, true);
281            infoBuilder.addAttribute("mappingFileNames", List.class, true, true);
282            infoBuilder.addAttribute("jarFileUrls", List.class, true, true);
283            infoBuilder.addAttribute("persistenceUnitRootUrl", URL.class, true, true);
284            infoBuilder.addAttribute("managedClassNames", List.class, true, true);
285            infoBuilder.addAttribute("excludeUnlistedClasses", boolean.class, true, true);
286            infoBuilder.addAttribute("properties", Properties.class, true, true);
287            infoBuilder.addReference("TransactionManager", TransactionManagerImpl.class, NameFactory.TRANSACTION_MANAGER);
288            infoBuilder.addReference("JtaDataSourceWrapper", ConnectionFactorySource.class, NameFactory.JCA_MANAGED_CONNECTION_FACTORY);
289            infoBuilder.addReference("NonJtaDataSourceWrapper", ConnectionFactorySource.class, NameFactory.JCA_MANAGED_CONNECTION_FACTORY);
290            infoBuilder.addOperation("getEntityManagerFactory");
291            infoBuilder.addOperation("getEntityManager", new Class[] {boolean.class, Map.class});
292    
293            infoBuilder.setConstructor(new String[] {
294                    "persistenceUnitName",
295                    "persistenceProviderClassName",
296                    "persistenceUnitTransactionType",
297                    "JtaDataSourceWrapper",
298                    "NonJtaDataSourceWrapper",
299                    "mappingFileNames",
300                    "jarFileUrls",
301                    "persistenceUnitRootUrl",
302                    "managedClassNames",
303                    "excludeUnlistedClasses",
304                    "properties",
305                    "TransactionManager",
306                    "classLoader"
307            });
308    
309            GBEAN_INFO = infoBuilder.getBeanInfo();
310    
311        }
312    
313        public static GBeanInfo getGBeanInfo() {
314            return GBEAN_INFO;
315        }
316    
317    }