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