
javax.persistence.spi.PersistenceProviderResolverHolder Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2010 Bull S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.persistence.spi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.WeakHashMap;
import javax.persistence.PersistenceException;
/**
* Holds the global PersistenceProviderResolver instance. If no PersistenceProviderResolver is set by the environment, the default
* PersistenceProviderResolver is used. Implementations must be thread-safe.
* @see JPA 2.0 specification
* @author Florent Benoit
* @since JPA 2.0 version.
*/
public class PersistenceProviderResolverHolder {
/**
* The instance of the persistence provider resolver (which is initialized with a default resolver).
*/
private static PersistenceProviderResolver persistenceProviderResolver = new DefaultPersistenceProviderResolver();
/**
* Returns the current persistence provider resolver.
* @return persistence provider resolver in use
*/
public static PersistenceProviderResolver getPersistenceProviderResolver() {
return persistenceProviderResolver;
}
/**
* Defines the persistence provider resolver used.
* The implementation of PersistenceProviderResolver- Holder must be threadsafe, but no guarantee is made against multiple
* threads setting the resolver.
* @param resolver PersistenceProviderResolver to be used
*/
public static void setPersistenceProviderResolver(PersistenceProviderResolver resolver) {
// Reset previous one
persistenceProviderResolver.clearCachedProviders();
// Assign a new default one or the given resolver ?
if (resolver == null) {
persistenceProviderResolver = new DefaultPersistenceProviderResolver();
} else {
persistenceProviderResolver = resolver;
}
}
/**
* The name of this class should be kept as it is present in the RI implementation
*
*/
private static class DefaultPersistenceProviderResolver implements PersistenceProviderResolver {
/**
* Persistence Provider property.
*/
private static final String PERSISTENCE_PROVIDER = PersistenceProvider.class.getName();
/**
* The provider supplies the provider configuration file by creating a text file named
* javax.persistence.spi.PersistenceProvider and placing it in the META-INF/services directory of one of its JAR files.
* The contents of the file should be the name of the provider implementation class of the
* javax.persistence.spi.PersistenceProvider interface.
*/
private static final String PERSISTENCE_PROVIDER_JAR_PROPERTY = "META-INF/services/" + PERSISTENCE_PROVIDER;
/**
* UID for serialization.
*/
private static final long serialVersionUID = 5768927739496807544L;
/**
* Map of persistence providers between a given classloader and the list of persistence providers.
*/
private WeakHashMap> persistenceProviders = new WeakHashMap>();
/**
* Initialize the list of persistence providers. (it not done).
*/
private void findPersistenceProviders(ClassLoader classLoader) {
// Initialize the list of PersistenceProvider available to the given ClassLoader
persistenceProviders.put(classLoader, new ArrayList());
// List of PERSISTENCE_PROVIDER available in the given classloader.
Enumeration urls = null;
try {
urls = classLoader.getResources(PERSISTENCE_PROVIDER_JAR_PROPERTY);
} catch (IOException e) {
throw new PersistenceException("Cannot get resources named '" + PERSISTENCE_PROVIDER_JAR_PROPERTY
+ "' on the current classloader '" + classLoader + "'.", e);
}
// Analyze URLs
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
URLConnection urlConnection = null;
try {
urlConnection = url.openConnection();
} catch (IOException e) {
throw new PersistenceException("Cannot open connection on URL '" + url + "'.", e);
}
// avoid lock
urlConnection.setDefaultUseCaches(false);
InputStream is = null;
try {
is = urlConnection.getInputStream();
Reader reader = null;
BufferedReader bufferedReader = null;
try {
reader = new InputStreamReader(is);
bufferedReader = new BufferedReader(reader);
String line = bufferedReader.readLine();
if (line == null) {
throw new PersistenceException("No lines found in the file available at the URL '" + url + "'.");
}
// add The persistence provider found.
addPersistenceProvider(classLoader, line.trim());
} finally {
reader.close();
bufferedReader.close();
}
} catch (IOException e) {
throw new PersistenceException("Cannot get InputStream on URL '" + url + "'.", e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
throw new PersistenceException("Cannot close InputStream on URL '" + url + "'.", e);
}
}
}
}
}
/**
* Add to the set of persistence provider the given persistence provider (by using its name).
* @param persistenceProviderName name of the persistence provider.
*/
private void addPersistenceProvider(final ClassLoader classLoader, final String persistenceProviderName) {
// load the class
Class> persistenceProviderClass = null;
try {
persistenceProviderClass = classLoader.loadClass(persistenceProviderName);
} catch (ClassNotFoundException e) {
throw new PersistenceException("Cannot load the persistence provider class with the name '"
+ persistenceProviderName + "' in the ClassLoader '" + classLoader + "'.", e);
}
// build a new instance
Object object = null;
try {
object = persistenceProviderClass.newInstance();
} catch (InstantiationException e) {
throw new PersistenceException("Cannot build an instance of the persistence provider class with the name '"
+ persistenceProviderName + "' in the ClassLoader '" + classLoader + "'.", e);
} catch (IllegalAccessException e) {
throw new PersistenceException("Cannot build an instance of the persistence provider class with the name '"
+ persistenceProviderName + "' in the ClassLoader '" + classLoader + "'.", e);
}
if (!(object instanceof PersistenceProvider)) {
throw new PersistenceException("The instance of the object with the class name '" + persistenceProviderName
+ "' in the ClassLoader '" + classLoader + "' is not an instance of PersistenceProvider interface.");
}
// Get list
List existingPersistenceProviders = persistenceProviders.get(classLoader);
// Add it.
existingPersistenceProviders.add((PersistenceProvider) object);
}
/**
* Note that the PersistenceProviderResolver.getPersistenceProviders() method can potentially be called many times. It is
* therefore recommended that the implementation of this method make use of caching.
* This is why there is a cache mechanism
* @return current persistence providers associated to the current CL.
*/
public List getPersistenceProviders() {
// Get current classloader
ClassLoader currentCL = Thread.currentThread().getContextClassLoader();
// Get current list of providers for the given classloader
List availablePersistenceProviders = null;
synchronized (persistenceProviders) {
availablePersistenceProviders = persistenceProviders.get(currentCL);
if (availablePersistenceProviders == null) {
findPersistenceProviders(currentCL);
availablePersistenceProviders = persistenceProviders.get(currentCL);
}
}
return availablePersistenceProviders;
}
/**
* Clear the given hashmap
*/
public void clearCachedProviders() {
this.persistenceProviders.clear();
}
/**
* Class that is present in the RI but used by ourself.
* Here to be compliant to the .class file
*/
private class ProviderName {
public ProviderName(String name, URL source) {
}
public String getName() {
return null;
}
public URL getSource() {
return null;
}
public String toString() {
return super.toString();
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy