/* * JBoss, Home of Professional Open Source. * Copyright 2011, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.jpa.persistenceprovider; import static org.jboss.as.jpa.messages.JpaLogger.ROOT_LOGGER; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceProviderResolver; import org.jboss.as.jpa.messages.JpaLogger; import org.jboss.modules.ModuleClassLoader; import org.wildfly.security.manager.WildFlySecurityManager; /** * Implementation of PersistenceProviderResolver * * @author Scott Marlow */ public class PersistenceProviderResolverImpl implements PersistenceProviderResolver { private Map<ClassLoader, List<Class<? extends PersistenceProvider>>> persistenceProviderPerClassLoader = new HashMap<>(); private List<Class<? extends PersistenceProvider>> providers = new CopyOnWriteArrayList<>(); private static final PersistenceProviderResolverImpl INSTANCE = new PersistenceProviderResolverImpl(); public static PersistenceProviderResolverImpl getInstance() { return INSTANCE; } public PersistenceProviderResolverImpl() { } /** * Return a new instance of each persistence provider class * * @return */ @Override public List<PersistenceProvider> getPersistenceProviders() { List<PersistenceProvider> providersCopy = new ArrayList<>(providers.size()); /** * Add the application specified providers first so they are found before the global providers */ synchronized(persistenceProviderPerClassLoader) { if (persistenceProviderPerClassLoader.size() > 0) { // get the deployment or subdeployment classloader ClassLoader deploymentClassLoader = findParentModuleCl(WildFlySecurityManager.getCurrentContextClassLoaderPrivileged()); ROOT_LOGGER.tracef("get application level Persistence Provider for classloader %s" , deploymentClassLoader); // collect persistence providers associated with deployment/each sub-deployment List<Class<? extends PersistenceProvider>> deploymentSpecificPersistenceProviders = persistenceProviderPerClassLoader.get(deploymentClassLoader); ROOT_LOGGER.tracef("got application level Persistence Provider list %s" , deploymentSpecificPersistenceProviders); if (deploymentSpecificPersistenceProviders != null) { for (Class<? extends PersistenceProvider> providerClass : deploymentSpecificPersistenceProviders) { try { ROOT_LOGGER.tracef("application has its own Persistence Provider %s", providerClass.getName()); providersCopy.add(providerClass.newInstance()); } catch (InstantiationException e) { throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName()); } catch (IllegalAccessException e) { throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName()); } } } } } // add global persistence providers last (so application packaged providers have priority) for (Class<?> providerClass : providers) { try { providersCopy.add((PersistenceProvider) providerClass.newInstance()); ROOT_LOGGER.tracef("returning global (module) Persistence Provider %s", providerClass.getName()); } catch (InstantiationException e) { throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName()); } catch (IllegalAccessException e) { throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName()); } } return providersCopy; } @Override public void clearCachedProviders() { providers.clear(); } /** * Cleared at application undeployment time to remove any persistence providers that were deployed with the application * * @param deploymentClassLoaders */ public void clearCachedDeploymentSpecificProviders(Set<ClassLoader> deploymentClassLoaders) { synchronized(persistenceProviderPerClassLoader) { for (ClassLoader deploymentClassLoader: deploymentClassLoaders) { persistenceProviderPerClassLoader.remove(deploymentClassLoader); } } } /** * Set at application deployment time to the persistence providers packaged in the application * * @param persistenceProvider * @param deploymentClassLoaders */ public void addDeploymentSpecificPersistenceProvider(PersistenceProvider persistenceProvider, Set<ClassLoader> deploymentClassLoaders) { synchronized(persistenceProviderPerClassLoader) { for (ClassLoader deploymentClassLoader: deploymentClassLoaders) { List<Class<? extends PersistenceProvider>> list = persistenceProviderPerClassLoader.get(deploymentClassLoader); ROOT_LOGGER.tracef("getting persistence provider list (%s) for deployment (%s)", list, deploymentClassLoader ); if (list == null) { list = new ArrayList<>(); persistenceProviderPerClassLoader.put(deploymentClassLoader, list); ROOT_LOGGER.tracef("saving new persistence provider list (%s) for deployment (%s)", list, deploymentClassLoader ); } list.add(persistenceProvider.getClass()); ROOT_LOGGER.tracef("added new persistence provider (%s) to provider list (%s)", persistenceProvider.getClass().getName(), list); } } } /** * If a custom CL is in use we want to get the module CL it delegates to * @param classLoader The current CL * @returnThe corresponding module CL */ private ClassLoader findParentModuleCl(ClassLoader classLoader) { ClassLoader c = classLoader; while (c != null && !(c instanceof ModuleClassLoader)) { c = c.getParent(); } return c; } public void addPersistenceProvider(PersistenceProvider persistenceProvider) { providers.add(persistenceProvider.getClass()); } }