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