package org.infinispan.hibernate.search.impl; import java.io.IOException; import java.io.InputStream; import org.hibernate.search.engine.service.classloading.spi.ClassLoaderService; import org.hibernate.search.engine.service.spi.ServiceManager; import org.infinispan.commons.util.Util; import org.infinispan.configuration.parsing.ConfigurationBuilderHolder; import org.infinispan.configuration.parsing.ParserRegistry; /** * The Infinispan configuration is ClassLoader sensitive, this wrapper around the standard Parser is used to allow it to * find resources in a modular classloading environment. * * @author Sanne Grinovero * @since 4.3 */ public class InfinispanConfigurationParser { private final ParserRegistry configurationParser; private final ClassLoader ispnClassLoadr; public InfinispanConfigurationParser() { //This class instance will have visibility on the components we need ispnClassLoadr = InfinispanConfigurationParser.class.getClassLoader(); configurationParser = new ParserRegistry(ispnClassLoadr); } /** * Resolves an Infinispan configuration file but using the Hibernate Search classloader. The returned Infinispan * configuration template also overrides Infinispan's runtime classloader to the one of Hibernate Search. * * @param filename Infinispan configuration resource name * @param transportOverrideResource An alternative JGroups configuration file to be injected * @param serviceManager the ServiceManager to load resources * @return * @throws IOException */ public ConfigurationBuilderHolder parseFile(String filename, String transportOverrideResource, ServiceManager serviceManager) throws IOException { ClassLoaderService classLoaderService = serviceManager.requestService(ClassLoaderService.class); try { return parseFile(classLoaderService, filename, transportOverrideResource); } finally { serviceManager.releaseService(ClassLoaderService.class); } } private ConfigurationBuilderHolder parseFile(ClassLoaderService classLoaderService, String filename, String transportOverrideResource) { InputStream is = classLoaderService.locateResourceStream(filename); try { //Infinispan requires the context ClassLoader to have full visibility on all //its components and eventual extension points even *during* configuration parsing. final Thread currentThread = Thread.currentThread(); final ClassLoader originalContextClassLoader = currentThread.getContextClassLoader(); try { currentThread.setContextClassLoader(ispnClassLoadr); ConfigurationBuilderHolder builderHolder = configurationParser.parse(is); //Workaround Infinispan's ClassLoader strategies to bend to our will: fixClassLoaders(builderHolder); patchTransportConfiguration(builderHolder, transportOverrideResource); return builderHolder; } finally { currentThread.setContextClassLoader(originalContextClassLoader); } } finally { Util.close(is); } } private void fixClassLoaders(ConfigurationBuilderHolder builderHolder) { //Global section: builderHolder.getGlobalConfigurationBuilder().classLoader(ispnClassLoadr); } /** * After having parsed the Infinispan configuration file, we might want to override the specified JGroups * configuration file. * * @param builderHolder * @param transportOverrideResource The alternative JGroups configuration file to be used, or null */ private void patchTransportConfiguration(ConfigurationBuilderHolder builderHolder, String transportOverrideResource) { if (transportOverrideResource != null) { builderHolder.getGlobalConfigurationBuilder().transport().addProperty("configurationFile", transportOverrideResource); } } }