Source Code Cross Referenced for PersistenceAnnotationBeanPostProcessor.java in  » J2EE » spring-framework-2.0.6 » org » springframework » orm » jpa » support » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.0.6 » org.springframework.orm.jpa.support 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.orm.jpa.support;
018:
019:        import java.beans.PropertyDescriptor;
020:        import java.lang.reflect.AccessibleObject;
021:        import java.lang.reflect.AnnotatedElement;
022:        import java.lang.reflect.Field;
023:        import java.lang.reflect.InvocationTargetException;
024:        import java.lang.reflect.Member;
025:        import java.lang.reflect.Method;
026:        import java.lang.reflect.Modifier;
027:        import java.util.HashMap;
028:        import java.util.LinkedList;
029:        import java.util.List;
030:        import java.util.Map;
031:        import java.util.Properties;
032:
033:        import javax.naming.NamingException;
034:        import javax.persistence.EntityManager;
035:        import javax.persistence.EntityManagerFactory;
036:        import javax.persistence.PersistenceContext;
037:        import javax.persistence.PersistenceContextType;
038:        import javax.persistence.PersistenceProperty;
039:        import javax.persistence.PersistenceUnit;
040:
041:        import org.springframework.beans.BeansException;
042:        import org.springframework.beans.PropertyValues;
043:        import org.springframework.beans.factory.BeanFactory;
044:        import org.springframework.beans.factory.BeanFactoryAware;
045:        import org.springframework.beans.factory.BeanFactoryUtils;
046:        import org.springframework.beans.factory.ListableBeanFactory;
047:        import org.springframework.beans.factory.NoSuchBeanDefinitionException;
048:        import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
049:        import org.springframework.jndi.JndiLocatorSupport;
050:        import org.springframework.orm.jpa.EntityManagerFactoryInfo;
051:        import org.springframework.orm.jpa.EntityManagerFactoryUtils;
052:        import org.springframework.orm.jpa.ExtendedEntityManagerCreator;
053:        import org.springframework.orm.jpa.SharedEntityManagerCreator;
054:        import org.springframework.util.ObjectUtils;
055:        import org.springframework.util.ReflectionUtils;
056:
057:        /**
058:         * BeanPostProcessor that processes {@link javax.persistence.PersistenceUnit}
059:         * and {@link javax.persistence.PersistenceContext} annotations, for injection of
060:         * the corresponding JPA resources {@link javax.persistence.EntityManagerFactory}
061:         * and {@link javax.persistence.EntityManager}. Any such annotated fields or methods
062:         * in any Spring-managed object will automatically be injected.
063:         *
064:         * <p>This post-processor will inject sub-interfaces of <code>EntityManagerFactory</code>
065:         * and <code>EntityManager</code> if the annotated fields or methods are declared as such.
066:         * The actual type will be verified early, with the exception of a shared ("transactional")
067:         * <code>EntityManager</code> reference, where type mismatches might be detected as late
068:         * as on the first actual invocation.
069:         *
070:         * <p>Note: In the present implementation, PersistenceAnnotationBeanPostProcessor
071:         * only supports <code>@PersistenceUnit</code> and <code>@PersistenceContext</code>
072:         * with the "unitName" attribute, or no attribute at all (for the default unit).
073:         * If those annotations are present with the "name" attribute at the class level,
074:         * they will simply be ignored, since those only serve as deployment hint
075:         * (as per the Java EE 5 specification).
076:         *
077:         * <p>This post-processor can either obtain EntityManagerFactory beans defined
078:         * in the Spring application context (the default), or obtain EntityManagerFactory
079:         * references from JNDI ("persistence unit references"). In the bean case,
080:         * the persistence unit name will be matched against the actual deployed unit,
081:         * with the bean name used as fallback unit name if no deployed name found.
082:         * Typically, Spring's {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}
083:         * will be used for setting up such EntityManagerFactory beans. The post-processor
084:         * definition will then look as simple as this:
085:         *
086:         * <pre class="code">
087:         * &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/&gt;</pre>
088:         *
089:         * In the JNDI case, specify the corresponding JNDI names in this post-processor's
090:         * {@link #setPersistenceUnits "persistenceUnits" map}, typically with matching
091:         * <code>persistence-unit-ref</code> entries in the Java EE deployment descriptor.
092:         * By default, those names are considered as resource references (according to the
093:         * Java EE resource-ref convention), located underneath the "java:comp/env/" namespace.
094:         * For example:
095:         *
096:         * <pre class="code">
097:         * &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"&gt;
098:         *   &lt;property name="persistenceUnits"&gt;
099:         *     &lt;map/gt;
100:         *       &lt;entry key="unit1" value="persistence/unit1"/&gt;
101:         *       &lt;entry key="unit2" value="persistence/unit2"/&gt;
102:         *     &lt;/map/gt;
103:         *   &lt;/property&gt;
104:         * &lt;/bean&gt;</pre>
105:         *
106:         * In this case, the specified persistence units will always be resolved in JNDI
107:         * rather than as Spring-defined beans. The entire persistence unit deployment,
108:         * including the weaving of persistent classes, is then up to the Java EE server.
109:         * Persistence contexts (i.e. EntityManager references) will be built based on
110:         * those server-provided EntityManagerFactory references, using Spring's own
111:         * transaction synchronization facilities for transactional EntityManager handling
112:         * (typically with Spring's <code>@Transactional</code> annotation for demarcation
113:         * and {@link org.springframework.transaction.jta.JtaTransactionManager} as backend).
114:         *
115:         * <p>If you prefer the Java EE server's own EntityManager handling, specify entries
116:         * in this post-processor's {@link #setPersistenceContexts "persistenceContexts" map}
117:         * (or {@link #setExtendedPersistenceContexts "extendedPersistenceContexts" map},
118:         * typically with matching <code>persistence-context-ref</code> entries in the
119:         * Java EE deployment descriptor. For example:
120:         *
121:         * <pre class="code">
122:         * &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"&gt;
123:         *   &lt;property name="persistenceContexts"&gt;
124:         *     &lt;map/gt;
125:         *       &lt;entry key="unit1" value="persistence/context1"/&gt;
126:         *       &lt;entry key="unit2" value="persistence/context2"/&gt;
127:         *     &lt;/map/gt;
128:         *   &lt;/property&gt;
129:         * &lt;/bean&gt;</pre>
130:         *
131:         * If the application only obtains EntityManager references in the first place,
132:         * this is all you need to specify. If you need EntityManagerFactory references
133:         * as well, specify entries for both "persistenceUnits" and "persistenceContexts",
134:         * pointing to matching JNDI locations.
135:         *
136:         * <p><b>NOTE: In general, do not inject EXTENDED EntityManagers into STATELESS beans,
137:         * i.e. do not use <code>@PersistenceContext</code> with type <code>EXTENDED</code> in
138:         * Spring beans defined with scope 'singleton' (Spring's default scope).</b>
139:         * Extended EntityManagers are <i>not</i> thread-safe, hence they must not be used
140:         * in concurrently accessed beans (which Spring-managed singletons usually are).
141:         *
142:         * @author Rod Johnson
143:         * @author Juergen Hoeller
144:         * @since 2.0
145:         * @see javax.persistence.PersistenceUnit
146:         * @see javax.persistence.PersistenceContext
147:         */
148:        public class PersistenceAnnotationBeanPostProcessor extends
149:                JndiLocatorSupport implements 
150:                InstantiationAwareBeanPostProcessor, BeanFactoryAware {
151:
152:            private Map<String, String> persistenceUnits;
153:
154:            private Map<String, String> persistenceContexts;
155:
156:            private Map<String, String> extendedPersistenceContexts;
157:
158:            private String defaultPersistenceUnitName = "";
159:
160:            private ListableBeanFactory beanFactory;
161:
162:            private final Map<Class<?>, List<AnnotatedMember>> annotationMetadataCache = new HashMap<Class<?>, List<AnnotatedMember>>();
163:
164:            public PersistenceAnnotationBeanPostProcessor() {
165:                setResourceRef(true);
166:            }
167:
168:            /**
169:             * Specify the persistence units for EntityManagerFactory lookups,
170:             * as a Map from persistence unit name to persistence unit JNDI name
171:             * (which needs to resolve to an EntityManagerFactory instance).
172:             * <p>JNDI names specified here should refer to <code>persistence-unit-ref</code>
173:             * entries in the Java EE deployment descriptor, matching the target persistence unit.
174:             * <p>In case of no unit name specified in the annotation, the specified value
175:             * for the {@link #setDefaultPersistenceUnitName default persistence unit}
176:             * will be taken (by default, the value mapped to the empty String),
177:             * or simply the single persistence unit if there is only one.
178:             * <p>This is mainly intended for use in a Java EE 5 environment, with all
179:             * lookup driven by the standard JPA annotations, and all EntityManagerFactory
180:             * references obtained from JNDI. No separate EntityManagerFactory bean
181:             * definitions are necessary in such a scenario.
182:             * <p>If no corresponding "persistenceContexts"/"extendedPersistenceContexts"
183:             * are specified, <code>@PersistenceContext</code> will be resolved to
184:             * EntityManagers built on top of the EntityManagerFactory defined here.
185:             * Note that those will be Spring-managed EntityManagers, which implement
186:             * transaction synchronization based on Spring's facilities.
187:             * If you prefer the Java EE 5 server's own EntityManager handling,
188:             * specify corresponding "persistenceContexts"/"extendedPersistenceContexts".
189:             */
190:            public void setPersistenceUnits(Map<String, String> persistenceUnits) {
191:                this .persistenceUnits = persistenceUnits;
192:            }
193:
194:            /**
195:             * Specify the <i>transactional</i> persistence contexts for EntityManager lookups,
196:             * as a Map from persistence unit name to persistence context JNDI name
197:             * (which needs to resolve to an EntityManager instance).
198:             * <p>JNDI names specified here should refer to <code>persistence-context-ref</code>
199:             * entries in the Java EE deployment descriptors, matching the target persistence unit
200:             * and being set up with persistence context type <code>Transaction</code>.
201:             * <p>In case of no unit name specified in the annotation, the specified value
202:             * for the {@link #setDefaultPersistenceUnitName default persistence unit}
203:             * will be taken (by default, the value mapped to the empty String),
204:             * or simply the single persistence unit if there is only one.
205:             * <p>This is mainly intended for use in a Java EE 5 environment, with all
206:             * lookup driven by the standard JPA annotations, and all EntityManager
207:             * references obtained from JNDI. No separate EntityManagerFactory bean
208:             * definitions are necessary in such a scenario, and all EntityManager
209:             * handling is done by the Java EE 5 server itself.
210:             */
211:            public void setPersistenceContexts(
212:                    Map<String, String> persistenceContexts) {
213:                this .persistenceContexts = persistenceContexts;
214:            }
215:
216:            /**
217:             * Specify the <i>extended</i> persistence contexts for EntityManager lookups,
218:             * as a Map from persistence unit name to persistence context JNDI name
219:             * (which needs to resolve to an EntityManager instance).
220:             * <p>JNDI names specified here should refer to <code>persistence-context-ref</code>
221:             * entries in the Java EE deployment descriptors, matching the target persistence unit
222:             * and being set up with persistence context type <code>Extended</code>.
223:             * <p>In case of no unit name specified in the annotation, the specified value
224:             * for the {@link #setDefaultPersistenceUnitName default persistence unit}
225:             * will be taken (by default, the value mapped to the empty String),
226:             * or simply the single persistence unit if there is only one.
227:             * <p>This is mainly intended for use in a Java EE 5 environment, with all
228:             * lookup driven by the standard JPA annotations, and all EntityManager
229:             * references obtained from JNDI. No separate EntityManagerFactory bean
230:             * definitions are necessary in such a scenario, and all EntityManager
231:             * handling is done by the Java EE 5 server itself.
232:             */
233:            public void setExtendedPersistenceContexts(
234:                    Map<String, String> extendedPersistenceContexts) {
235:                this .extendedPersistenceContexts = extendedPersistenceContexts;
236:            }
237:
238:            /**
239:             * Specify the default persistence unit name, to be used in case
240:             * of no unit name specified in an <code>@PersistenceUnit</code> /
241:             * <code>@PersistenceContext</code> annotation.
242:             * <p>This is mainly intended for lookups in the application context,
243:             * indicating the target persistence unit name (typically matching
244:             * the bean name), but also applies to lookups in the
245:             * {@link #setPersistenceUnits "persistenceUnits"} /
246:             * {@link #setPersistenceContexts "persistenceContexts"} /
247:             * {@link #setExtendedPersistenceContexts "extendedPersistenceContexts"} map,
248:             * avoiding the need for duplicated mappings for the empty String there.
249:             * <p>Default is to check for a single EntityManagerFactory bean
250:             * in the Spring application context, if any. If there are multiple
251:             * such factories, either specify this default persistence unit name
252:             * or explicitly refer to named persistence units in your annotations.
253:             */
254:            public void setDefaultPersistenceUnitName(String unitName) {
255:                this .defaultPersistenceUnitName = (unitName != null ? unitName
256:                        : "");
257:            }
258:
259:            public void setBeanFactory(BeanFactory beanFactory) {
260:                if (beanFactory instanceof  ListableBeanFactory) {
261:                    this .beanFactory = (ListableBeanFactory) beanFactory;
262:                }
263:            }
264:
265:            public Object postProcessBeforeInstantiation(Class beanClass,
266:                    String beanName) throws BeansException {
267:                return null;
268:            }
269:
270:            public boolean postProcessAfterInstantiation(Object bean,
271:                    String beanName) throws BeansException {
272:                List<AnnotatedMember> metadata = findAnnotationMetadata(bean
273:                        .getClass());
274:                for (AnnotatedMember member : metadata) {
275:                    member.inject(bean);
276:                }
277:                return true;
278:            }
279:
280:            public PropertyValues postProcessPropertyValues(PropertyValues pvs,
281:                    PropertyDescriptor[] pds, Object bean, String beanName)
282:                    throws BeansException {
283:
284:                return pvs;
285:            }
286:
287:            public Object postProcessBeforeInitialization(Object bean,
288:                    String beanName) throws BeansException {
289:                return bean;
290:            }
291:
292:            public Object postProcessAfterInitialization(Object bean,
293:                    String beanName) throws BeansException {
294:                return bean;
295:            }
296:
297:            private List<AnnotatedMember> findAnnotationMetadata(Class clazz) {
298:                synchronized (this .annotationMetadataCache) {
299:                    List<AnnotatedMember> metadata = this .annotationMetadataCache
300:                            .get(clazz);
301:                    if (metadata == null) {
302:                        final List<AnnotatedMember> newMetadata = new LinkedList<AnnotatedMember>();
303:                        ReflectionUtils.doWithFields(clazz,
304:                                new ReflectionUtils.FieldCallback() {
305:                                    public void doWith(Field field) {
306:                                        addIfPresent(newMetadata, field);
307:                                    }
308:                                });
309:                        ReflectionUtils.doWithMethods(clazz,
310:                                new ReflectionUtils.MethodCallback() {
311:                                    public void doWith(Method method) {
312:                                        addIfPresent(newMetadata, method);
313:                                    }
314:                                });
315:                        metadata = newMetadata;
316:                        this .annotationMetadataCache.put(clazz, metadata);
317:                    }
318:                    return metadata;
319:                }
320:            }
321:
322:            private void addIfPresent(List<AnnotatedMember> metadata,
323:                    Member member) {
324:                AnnotatedElement ae = (AnnotatedElement) member;
325:                PersistenceContext pc = ae
326:                        .getAnnotation(PersistenceContext.class);
327:                PersistenceUnit pu = ae.getAnnotation(PersistenceUnit.class);
328:                if (pc != null) {
329:                    if (pu != null) {
330:                        throw new IllegalStateException(
331:                                "Method may only be annotated with either @PersistenceContext or @PersistenceUnit, not both");
332:                    }
333:                    if (member instanceof  Method
334:                            && ((Method) member).getParameterTypes().length != 1) {
335:                        throw new IllegalStateException(
336:                                "PersistenceContext annotation requires a single-arg method: "
337:                                        + member);
338:                    }
339:                    Properties properties = null;
340:                    PersistenceProperty[] pps = pc.properties();
341:                    if (!ObjectUtils.isEmpty(pps)) {
342:                        properties = new Properties();
343:                        for (int i = 0; i < pps.length; i++) {
344:                            PersistenceProperty pp = pps[i];
345:                            properties.setProperty(pp.name(), pp.value());
346:                        }
347:                    }
348:                    metadata.add(new AnnotatedMember(member, pc.unitName(), pc
349:                            .type(), properties));
350:                } else if (pu != null) {
351:                    if (member instanceof  Method
352:                            && ((Method) member).getParameterTypes().length != 1) {
353:                        throw new IllegalStateException(
354:                                "PersistenceUnit annotation requires a single-arg method: "
355:                                        + member);
356:                    }
357:                    metadata.add(new AnnotatedMember(member, pu.unitName()));
358:                }
359:            }
360:
361:            /**
362:             * Return a specified persistence unit for the given unit name,
363:             * as defined through the "persistenceUnits" map.
364:             * @param unitName the name of the persistence unit
365:             * @return the corresponding EntityManagerFactory,
366:             * or <code>null</code> if none found
367:             * @see #setPersistenceUnits
368:             */
369:            protected EntityManagerFactory getPersistenceUnit(String unitName) {
370:                if (this .persistenceUnits != null) {
371:                    String unitNameForLookup = (unitName != null ? unitName
372:                            : "");
373:                    if ("".equals(unitNameForLookup)) {
374:                        unitNameForLookup = this .defaultPersistenceUnitName;
375:                    }
376:                    String jndiName = this .persistenceUnits
377:                            .get(unitNameForLookup);
378:                    if (jndiName == null && "".equals(unitNameForLookup)
379:                            && this .persistenceUnits.size() == 1) {
380:                        jndiName = this .persistenceUnits.values().iterator()
381:                                .next();
382:                    }
383:                    if (jndiName != null) {
384:                        try {
385:                            return (EntityManagerFactory) lookup(jndiName,
386:                                    EntityManagerFactory.class);
387:                        } catch (NamingException ex) {
388:                            throw new IllegalStateException(
389:                                    "Could not obtain EntityManagerFactory ["
390:                                            + jndiName + "] from JNDI", ex);
391:                        }
392:                    }
393:                }
394:                return null;
395:            }
396:
397:            /**
398:             * Return a specified persistence context for the given unit name, as defined
399:             * through the "persistenceContexts" (or "extendedPersistenceContexts") map.
400:             * @param unitName the name of the persistence unit
401:             * @param extended whether to obtain an extended persistence context
402:             * @return the corresponding EntityManager, or <code>null</code> if none found
403:             * @see #setPersistenceContexts
404:             * @see #setExtendedPersistenceContexts
405:             */
406:            protected EntityManager getPersistenceContext(String unitName,
407:                    boolean extended) {
408:                Map<String, String> contexts = (extended ? this .extendedPersistenceContexts
409:                        : this .persistenceContexts);
410:                if (contexts != null) {
411:                    String unitNameForLookup = (unitName != null ? unitName
412:                            : "");
413:                    if ("".equals(unitNameForLookup)) {
414:                        unitNameForLookup = this .defaultPersistenceUnitName;
415:                    }
416:                    String jndiName = contexts.get(unitNameForLookup);
417:                    if (jndiName == null && "".equals(unitNameForLookup)
418:                            && contexts.size() == 1) {
419:                        jndiName = contexts.values().iterator().next();
420:                    }
421:                    if (jndiName != null) {
422:                        try {
423:                            return (EntityManager) lookup(jndiName,
424:                                    EntityManager.class);
425:                        } catch (NamingException ex) {
426:                            throw new IllegalStateException(
427:                                    "Could not obtain EntityManager ["
428:                                            + jndiName + "] from JNDI", ex);
429:                        }
430:                    }
431:                }
432:                return null;
433:            }
434:
435:            /**
436:             * Find an EntityManagerFactory with the given name in the current Spring
437:             * application context, falling back to a single default EntityManagerFactory
438:             * (if any) in case of no unit name specified.
439:             * @param unitName the name of the persistence unit (may be <code>null</code> or empty)
440:             * @return the EntityManagerFactory
441:             * @throws NoSuchBeanDefinitionException if there is no such EntityManagerFactory in the context
442:             */
443:            protected EntityManagerFactory findEntityManagerFactory(
444:                    String unitName) throws NoSuchBeanDefinitionException {
445:                if (this .beanFactory == null) {
446:                    throw new IllegalStateException(
447:                            "ListableBeanFactory required for EntityManagerFactory lookup");
448:                }
449:                String unitNameForLookup = (unitName != null ? unitName : "");
450:                if ("".equals(unitNameForLookup)) {
451:                    unitNameForLookup = this .defaultPersistenceUnitName;
452:                }
453:                if (!"".equals(unitNameForLookup)) {
454:                    return findNamedEntityManagerFactory(unitNameForLookup);
455:                } else {
456:                    return findDefaultEntityManagerFactory();
457:                }
458:            }
459:
460:            /**
461:             * Find an EntityManagerFactory with the given name in the current
462:             * Spring application context.
463:             * @param unitName the name of the persistence unit (never empty)
464:             * @return the EntityManagerFactory
465:             * @throws NoSuchBeanDefinitionException if there is no such EntityManagerFactory in the context
466:             */
467:            protected EntityManagerFactory findNamedEntityManagerFactory(
468:                    String unitName) throws NoSuchBeanDefinitionException {
469:
470:                return EntityManagerFactoryUtils.findEntityManagerFactory(
471:                        this .beanFactory, unitName);
472:            }
473:
474:            /**
475:             * Find a single default EntityManagerFactory in the Spring application context.
476:             * @return the default EntityManagerFactory
477:             * @throws NoSuchBeanDefinitionException if there is no single EntityManagerFactory in the context
478:             */
479:            protected EntityManagerFactory findDefaultEntityManagerFactory() {
480:                return (EntityManagerFactory) BeanFactoryUtils
481:                        .beanOfTypeIncludingAncestors(this .beanFactory,
482:                                EntityManagerFactory.class);
483:            }
484:
485:            /**
486:             * Class representing injection information about an annotated field
487:             * or setter method.
488:             */
489:            private class AnnotatedMember {
490:
491:                private final Member member;
492:
493:                private final String unitName;
494:
495:                private final PersistenceContextType type;
496:
497:                private final Properties properties;
498:
499:                public AnnotatedMember(Member member, String unitName) {
500:                    this (member, unitName, null, null);
501:                }
502:
503:                public AnnotatedMember(Member member, String unitName,
504:                        PersistenceContextType type, Properties properties) {
505:                    this .member = member;
506:                    this .unitName = unitName;
507:                    this .type = type;
508:                    this .properties = properties;
509:
510:                    // Validate member type
511:                    Class<?> memberType = getMemberType();
512:                    if (!(EntityManagerFactory.class
513:                            .isAssignableFrom(memberType) || EntityManager.class
514:                            .isAssignableFrom(memberType))) {
515:                        throw new IllegalArgumentException("Cannot inject "
516:                                + member + ": not a supported JPA type");
517:                    }
518:                }
519:
520:                public void inject(Object instance) {
521:                    Object value = resolve();
522:                    try {
523:                        if (!Modifier.isPublic(this .member.getModifiers())
524:                                || !Modifier.isPublic(this .member
525:                                        .getDeclaringClass().getModifiers())) {
526:                            ((AccessibleObject) this .member)
527:                                    .setAccessible(true);
528:                        }
529:                        if (this .member instanceof  Field) {
530:                            ((Field) this .member).set(instance, value);
531:                        } else if (this .member instanceof  Method) {
532:                            ((Method) this .member).invoke(instance, value);
533:                        } else {
534:                            throw new IllegalArgumentException(
535:                                    "Cannot inject unknown AccessibleObject type "
536:                                            + this .member);
537:                        }
538:                    } catch (IllegalAccessException ex) {
539:                        throw new IllegalArgumentException(
540:                                "Cannot inject member " + this .member, ex);
541:                    } catch (InvocationTargetException ex) {
542:                        // Method threw an exception
543:                        throw new IllegalArgumentException(
544:                                "Attempt to inject setter method "
545:                                        + this .member
546:                                        + " resulted in an exception", ex);
547:                    }
548:                }
549:
550:                /**
551:                 * Return the type of the member, whether it's a field or a method.
552:                 */
553:                public Class<?> getMemberType() {
554:                    if (this .member instanceof  Field) {
555:                        return ((Field) member).getType();
556:                    } else if (this .member instanceof  Method) {
557:                        Method setter = (Method) this .member;
558:                        if (setter.getParameterTypes().length != 1) {
559:                            throw new IllegalArgumentException(
560:                                    "Supposed setter [" + this .member
561:                                            + "] must have 1 argument, not "
562:                                            + setter.getParameterTypes().length);
563:                        }
564:                        return setter.getParameterTypes()[0];
565:                    } else {
566:                        throw new IllegalArgumentException(
567:                                "Unknown AccessibleObject type ["
568:                                        + this .member.getClass()
569:                                        + "]; can only inject setter methods and fields");
570:                    }
571:                }
572:
573:                /**
574:                 * Resolve the object against the application context.
575:                 */
576:                private Object resolve() {
577:                    // Resolves to EntityManagerFactory or EntityManager.
578:                    if (EntityManagerFactory.class
579:                            .isAssignableFrom(getMemberType())) {
580:                        EntityManagerFactory emf = resolveEntityManagerFactory();
581:                        if (!getMemberType().isInstance(emf)) {
582:                            throw new IllegalArgumentException(
583:                                    "Cannot inject [" + this .member
584:                                            + "] with EntityManagerFactory ["
585:                                            + emf + "]: type mismatch");
586:                        }
587:                        return emf;
588:                    } else {
589:                        // OK, so we need an EntityManager...
590:                        EntityManager em = (this .type == PersistenceContextType.EXTENDED ? resolveExtendedEntityManager()
591:                                : resolveEntityManager());
592:                        if (!getMemberType().isInstance(em)) {
593:                            throw new IllegalArgumentException(
594:                                    "Cannot inject [" + this .member
595:                                            + "] with EntityManager [" + em
596:                                            + "]: type mismatch");
597:                        }
598:                        return em;
599:                    }
600:                }
601:
602:                private EntityManagerFactory resolveEntityManagerFactory() {
603:                    // Obtain EntityManagerFactory from JNDI?
604:                    EntityManagerFactory emf = getPersistenceUnit(this .unitName);
605:                    if (emf == null) {
606:                        // Need to search for EntityManagerFactory beans.
607:                        emf = findEntityManagerFactory(this .unitName);
608:                    }
609:                    return emf;
610:                }
611:
612:                private EntityManager resolveEntityManager() {
613:                    // Obtain EntityManager reference from JNDI?
614:                    EntityManager em = getPersistenceContext(this .unitName,
615:                            false);
616:                    if (em == null) {
617:                        // No pre-built EntityManager found -> build one based on factory.
618:                        // Obtain EntityManagerFactory from JNDI?
619:                        EntityManagerFactory emf = getPersistenceUnit(this .unitName);
620:                        if (emf == null) {
621:                            // Need to search for EntityManagerFactory beans.
622:                            emf = findEntityManagerFactory(this .unitName);
623:                        }
624:                        // Inject a shared transactional EntityManager proxy.
625:                        if (emf instanceof  EntityManagerFactoryInfo
626:                                && !EntityManager.class
627:                                        .equals(((EntityManagerFactoryInfo) emf)
628:                                                .getEntityManagerInterface())) {
629:                            // Create EntityManager based on the info's vendor-specific type
630:                            // (which might be more specific than the field's type).
631:                            em = SharedEntityManagerCreator
632:                                    .createSharedEntityManager(emf,
633:                                            this .properties);
634:                        } else {
635:                            // Create EntityManager based on the field's type.
636:                            em = SharedEntityManagerCreator
637:                                    .createSharedEntityManager(emf,
638:                                            this .properties, getMemberType());
639:                        }
640:                    }
641:                    return em;
642:                }
643:
644:                private EntityManager resolveExtendedEntityManager() {
645:                    // Obtain EntityManager reference from JNDI?
646:                    EntityManager em = getPersistenceContext(this .unitName,
647:                            true);
648:                    if (em == null) {
649:                        // No pre-built EntityManager found -> build one based on factory.
650:                        // Obtain EntityManagerFactory from JNDI?
651:                        EntityManagerFactory emf = getPersistenceUnit(this .unitName);
652:                        if (emf == null) {
653:                            // Need to search for EntityManagerFactory beans.
654:                            emf = findEntityManagerFactory(this .unitName);
655:                        }
656:                        // Inject a container-managed extended EntityManager.
657:                        em = ExtendedEntityManagerCreator
658:                                .createContainerManagedEntityManager(emf,
659:                                        this.properties);
660:                    }
661:                    return em;
662:                }
663:            }
664:
665:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.