Package: DefaultPersistenceProviderResolver
DefaultPersistenceProviderResolver
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DefaultPersistenceProviderResolver() |
|
|
|
|
|
||||||||||||||||||||
clearCachedProviders() |
|
|
|
|
|
||||||||||||||||||||
getPersistenceProviderClass(String) |
|
|
|
|
|
||||||||||||||||||||
getPersistenceProviders() |
|
|
|
|
|
||||||||||||||||||||
initProviders() |
|
|
|
|
|
||||||||||||||||||||
registerPersistenceProviderClass(Class) |
|
|
|
|
|
||||||||||||||||||||
resolveProvider(URL) |
|
|
|
|
|
||||||||||||||||||||
resolveProviders() |
|
|
|
|
|
||||||||||||||||||||
static {...} |
|
|
|
|
|
Coverage
1: /**
2: * Copyright (C) 2020 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jopa.model;
16:
17: import org.slf4j.Logger;
18: import org.slf4j.LoggerFactory;
19:
20: import java.io.BufferedReader;
21: import java.io.IOException;
22: import java.io.InputStreamReader;
23: import java.net.URL;
24: import java.util.*;
25: import java.util.regex.Matcher;
26: import java.util.regex.Pattern;
27:
28: /**
29: * Default implementation of the {@link PersistenceProviderResolver}, threadsafe.
30: * <p>
31: * It gets persistence providers by scanning the classpath, looking for {@link #PROVIDER_FILE} containing fully
32: * qualified name of a {@link PersistenceProvider} implementation.
33: */
34: public class DefaultPersistenceProviderResolver implements PersistenceProviderResolver {
35:
36: private static final Logger LOG = LoggerFactory.getLogger(DefaultPersistenceProviderResolver.class);
37:
38: /**
39: * Configuration file of the persistence provider implementations.
40: */
41: public static final String PROVIDER_FILE = "META-INF/services/" + PersistenceProperties.JPA_PERSISTENCE_PROVIDER;
42: private static final Pattern nonCommentPattern = Pattern.compile("^([^#]+)");
43:
44: private static final Set<Class<? extends PersistenceProvider>> PROVIDER_TYPES = new LinkedHashSet<>(4);
45:
46: private List<PersistenceProvider> providers = null;
47:
48: @Override
49: public synchronized List<PersistenceProvider> getPersistenceProviders() {
50:• if (providers == null) {
51: this.providers = initProviders();
52: }
53: return Collections.unmodifiableList(providers);
54: }
55:
56: private static List<PersistenceProvider> initProviders() {
57: final List<Class<? extends PersistenceProvider>> providerTypes = new ArrayList<>(PROVIDER_TYPES);
58: providerTypes.addAll(resolveProviders());
59: final List<PersistenceProvider> providerList = new ArrayList<>(providerTypes.size());
60:• for (Class<? extends PersistenceProvider> cls : providerTypes) {
61: try {
62: providerList.add(cls.newInstance());
63: } catch (InstantiationException | IllegalAccessException e) {
64: LOG.error("Unable to instantiate PersistenceProvider {}.", cls, e);
65: }
66: }
67:• if (providerList.isEmpty()) {
68: LOG.warn("No persistence provider implementations found on classpath.");
69: }
70: return providerList;
71: }
72:
73: @Override
74: public synchronized void clearCachedProviders() {
75: this.providers = null;
76: }
77:
78: /**
79: * Registers the specified class so that {@link PersistenceProvider} instances can be created by this resolver.
80: * <p>
81: * This allows to programmatically specify additional persistence providers. Providers registered via this method
82: * are instantiated first by the resolver instance.
83: *
84: * @param cls The class to register
85: */
86: public static synchronized void registerPersistenceProviderClass(Class<? extends PersistenceProvider> cls) {
87: PROVIDER_TYPES.add(cls);
88: }
89:
90: private static List<Class<? extends PersistenceProvider>> resolveProviders() {
91: final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
92: final List<Class<? extends PersistenceProvider>> providerTypes = new ArrayList<>();
93: try {
94: final Enumeration<URL> configs = classLoader.getResources(PROVIDER_FILE);
95:
96:• while (configs.hasMoreElements()) {
97: final URL config = configs.nextElement();
98: resolveProvider(config).ifPresent(providerTypes::add);
99: }
100: } catch (IOException e) {
101: LOG.error("Unable to read persistence provider configuration files from classpath.", e);
102: }
103: return providerTypes;
104: }
105:
106: private static Optional<Class<? extends PersistenceProvider>> resolveProvider(URL file) {
107: try (final BufferedReader in = new BufferedReader(new InputStreamReader(file.openStream()))) {
108: String line;
109:• while ((line = in.readLine()) != null) {
110: line = line.trim();
111: Matcher m = nonCommentPattern.matcher(line);
112:• if (m.find()) {
113: final String providerClass = m.group().trim();
114: return getPersistenceProviderClass(providerClass);
115: }
116: }
117: return Optional.empty();
118: } catch (IOException e) {
119: LOG.error("Unable to read persistence provider implementation from file {}.", file, e);
120: }
121: return Optional.empty();
122: }
123:
124: private static Optional<Class<? extends PersistenceProvider>> getPersistenceProviderClass(String className) {
125: try {
126: final Class<?> cls = Class.forName(className);
127:• if (!PersistenceProvider.class.isAssignableFrom(cls)) {
128: LOG.error("The registered type {} is not a PersistenceProvider implementation.", className);
129: return Optional.empty();
130: }
131: return Optional.of((Class<? extends PersistenceProvider>) cls);
132: } catch (ClassNotFoundException e) {
133: LOG.error("Persistence provider type {} not found.", className, e);
134: return Optional.empty();
135: }
136: }
137: }