All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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