1
2
3
4
5 package mockit.internal.injection.full;
6
7 import edu.umd.cs.findbugs.annotations.NonNull;
8 import edu.umd.cs.findbugs.annotations.Nullable;
9
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.lang.annotation.Annotation;
13
14 import javax.persistence.EntityManager;
15 import javax.persistence.EntityManagerFactory;
16 import javax.persistence.Persistence;
17 import javax.persistence.PersistenceContext;
18 import javax.persistence.PersistenceUnit;
19 import javax.xml.parsers.ParserConfigurationException;
20 import javax.xml.parsers.SAXParser;
21 import javax.xml.parsers.SAXParserFactory;
22
23 import mockit.internal.injection.InjectionPoint;
24 import mockit.internal.injection.InjectionProvider;
25 import mockit.internal.injection.InjectionState;
26
27 import org.xml.sax.Attributes;
28 import org.xml.sax.SAXException;
29 import org.xml.sax.helpers.DefaultHandler;
30
31
32
33
34
35 final class JPADependencies {
36 static boolean isApplicable(@NonNull Class<?> dependencyType) {
37 return dependencyType == EntityManager.class || dependencyType == EntityManagerFactory.class;
38 }
39
40 @NonNull
41 private final InjectionState injectionState;
42 @Nullable
43 private String defaultPersistenceUnitName;
44
45 JPADependencies(@NonNull InjectionState injectionState) {
46 this.injectionState = injectionState;
47 }
48
49 @Nullable
50 InjectionPoint getInjectionPointIfAvailable(@NonNull Annotation jpaAnnotation) {
51 Class<? extends Annotation> annotationType = jpaAnnotation.annotationType();
52 Class<?> jpaClass;
53 String unitName;
54
55 if (annotationType == PersistenceUnit.class) {
56 jpaClass = EntityManagerFactory.class;
57 unitName = ((PersistenceUnit) jpaAnnotation).unitName();
58 } else if (annotationType == PersistenceContext.class) {
59 jpaClass = EntityManager.class;
60 unitName = ((PersistenceContext) jpaAnnotation).unitName();
61 } else {
62 return null;
63 }
64
65 if (unitName.isEmpty()) {
66 unitName = discoverNameOfDefaultPersistenceUnit();
67 }
68
69 return new InjectionPoint(jpaClass, unitName, true);
70 }
71
72 @NonNull
73 private String discoverNameOfDefaultPersistenceUnit() {
74 if (defaultPersistenceUnitName != null) {
75 return defaultPersistenceUnitName;
76 }
77
78 defaultPersistenceUnitName = "<unknown>";
79 InputStream xmlFile = getClass().getResourceAsStream("/META-INF/persistence.xml");
80
81 if (xmlFile != null) {
82 try {
83 SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
84 parser.parse(xmlFile, new DefaultHandler() {
85 @Override
86 public void startElement(String uri, String localName, String qName, Attributes attributes) {
87 if ("persistence-unit".equals(qName)) {
88 defaultPersistenceUnitName = attributes.getValue("name");
89 }
90 }
91 });
92 xmlFile.close();
93 } catch (ParserConfigurationException | SAXException | IOException ignore) {
94 }
95 }
96
97 return defaultPersistenceUnitName;
98 }
99
100 @Nullable
101 Object createAndRegisterDependency(@NonNull Class<?> dependencyType, @NonNull InjectionPoint dependencyKey,
102 @Nullable InjectionProvider injectionProvider) {
103 if (injectionProvider != null) {
104 if (dependencyType == EntityManagerFactory.class
105 && injectionProvider.hasAnnotation(PersistenceUnit.class)) {
106 InjectionPoint injectionPoint = createFactoryInjectionPoint(dependencyKey);
107 return createAndRegisterEntityManagerFactory(injectionPoint);
108 }
109
110 if (dependencyType == EntityManager.class && injectionProvider.hasAnnotation(PersistenceContext.class)) {
111 return createAndRegisterEntityManager(dependencyKey);
112 }
113 }
114
115 return null;
116 }
117
118 @NonNull
119 private InjectionPoint createFactoryInjectionPoint(@NonNull InjectionPoint injectionPoint) {
120 String persistenceUnitName = getNameOfPersistentUnit(injectionPoint.name);
121 return new InjectionPoint(EntityManagerFactory.class, persistenceUnitName, injectionPoint.qualified);
122 }
123
124 @NonNull
125 private String getNameOfPersistentUnit(@Nullable String injectionPointName) {
126 return injectionPointName != null && !injectionPointName.isEmpty() ? injectionPointName
127 : discoverNameOfDefaultPersistenceUnit();
128 }
129
130 @NonNull
131 private static EntityManagerFactory createAndRegisterEntityManagerFactory(@NonNull InjectionPoint injectionPoint) {
132 String persistenceUnitName = injectionPoint.name;
133 EntityManagerFactory emFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
134 InjectionState.saveGlobalDependency(injectionPoint, emFactory);
135 return emFactory;
136 }
137
138 @NonNull
139 private EntityManager createAndRegisterEntityManager(@NonNull InjectionPoint injectionPoint) {
140 InjectionPoint emFactoryKey = createFactoryInjectionPoint(injectionPoint);
141 EntityManagerFactory emFactory = InjectionState.getGlobalDependency(emFactoryKey);
142
143 if (emFactory == null) {
144 emFactory = createAndRegisterEntityManagerFactory(emFactoryKey);
145 }
146
147 EntityManager entityManager = emFactory.createEntityManager();
148 injectionState.saveInstantiatedDependency(injectionPoint, entityManager);
149 return entityManager;
150 }
151 }