From 4ccc536c9926d29e41ada3001afe41e4f49d6400 Mon Sep 17 00:00:00 2001 From: Strong Liu Date: Mon, 15 Aug 2011 15:30:55 +0800 Subject: [PATCH] HHH-6573 change to use ClassLoaderService to locate service initiator --- .../internal/IntegratorServiceImpl.java | 7 +- .../integrator/internal/ServiceLoader.java | 195 ++++++++++++++++++ 2 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/integrator/internal/ServiceLoader.java diff --git a/hibernate-core/src/main/java/org/hibernate/integrator/internal/IntegratorServiceImpl.java b/hibernate-core/src/main/java/org/hibernate/integrator/internal/IntegratorServiceImpl.java index 1c0dc4164b..156c3355e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/integrator/internal/IntegratorServiceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/integrator/internal/IntegratorServiceImpl.java @@ -24,16 +24,14 @@ package org.hibernate.integrator.internal; import java.util.LinkedHashSet; -import java.util.ServiceLoader; - import org.jboss.logging.Logger; - import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator; import org.hibernate.integrator.spi.Integrator; import org.hibernate.integrator.spi.IntegratorService; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.service.spi.ServiceRegistryImplementor; + /** * @author Steve Ebersole */ @@ -60,8 +58,7 @@ public class IntegratorServiceImpl implements IntegratorService { public Iterable getIntegrators() { LinkedHashSet integrators = new LinkedHashSet(); integrators.addAll( this.integrators ); - - for ( Integrator integrator : ServiceLoader.load( Integrator.class ) ) { + for ( Integrator integrator : ServiceLoader.load( Integrator.class,serviceRegistry ) ) { LOG.debugf( "Adding Integrator [%s].", integrator.getClass().getName() ); integrators.add( integrator ); } diff --git a/hibernate-core/src/main/java/org/hibernate/integrator/internal/ServiceLoader.java b/hibernate-core/src/main/java/org/hibernate/integrator/internal/ServiceLoader.java new file mode 100644 index 0000000000..16c5051ee3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/integrator/internal/ServiceLoader.java @@ -0,0 +1,195 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program 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 distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.integrator.internal; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ServiceConfigurationError; + +import org.jboss.logging.Logger; + +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.classloading.spi.ClassLoaderService; + +/** + * @author Strong Liu + */ +final class ServiceLoader implements Iterable { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, ServiceLoader.class.getName() + ); + private static final String PREFIX = "META-INF/services/"; + private LinkedHashMap providers = new LinkedHashMap(); + + private ServiceLoader(Class svc, ServiceRegistry serviceRegistry) { + Class service = svc; + ClassLoaderService loader = serviceRegistry.getService( ClassLoaderService.class ); + String fullName = PREFIX + service.getName(); + service.getName(); + + List configs = locateResources( loader, fullName ); + for ( URL url : configs ) { + Iterator names = parse( service, url ); + while ( names.hasNext() ) { + String cn = names.next(); + try { + S p = service.cast( loader.classForName( cn ).newInstance() ); + providers.put( cn, p ); + } + catch ( Throwable x ) { + fail( service, "Provider " + cn + " could not be instantiated: " + x, x ); + } + } + + } + } + + private List locateResources(ClassLoaderService loader, String fullName) { + List urls = new ArrayList(); + urls.addAll( loader.locateResources( fullName ) ); + try { + Enumeration hibUrls = ServiceLoader.class.getClassLoader().getResources( fullName ); + while ( hibUrls.hasMoreElements() ) { + URL u = hibUrls.nextElement(); + if ( !urls.contains( u ) ) { + urls.add( u ); + } + + } + } + catch ( IOException e ) { + //ignore + } + return urls; + } + + private static void fail(Class service, String msg, Throwable cause) + throws ServiceConfigurationError { + throw new ServiceConfigurationError( + service.getName() + ": " + msg, + cause + ); + } + + private static void fail(Class service, String msg) + throws ServiceConfigurationError { + throw new ServiceConfigurationError( service.getName() + ": " + msg ); + } + + private static void fail(Class service, URL u, int line, String msg) + throws ServiceConfigurationError { + fail( service, u + ":" + line + ": " + msg ); + } + + // Parse a single line from the given configuration file, adding the name + // on the line to the names list. + // + private int parseLine(Class service, URL u, BufferedReader r, int lc, + List names) + throws IOException, ServiceConfigurationError { + String ln = r.readLine(); + if ( ln == null ) { + return -1; + } + int ci = ln.indexOf( '#' ); + if ( ci >= 0 ) { + ln = ln.substring( 0, ci ); + } + ln = ln.trim(); + int n = ln.length(); + if ( n != 0 ) { + if ( ( ln.indexOf( ' ' ) >= 0 ) || ( ln.indexOf( '\t' ) >= 0 ) ) { + fail( service, u, lc, "Illegal configuration-file syntax" ); + } + int cp = ln.codePointAt( 0 ); + if ( !Character.isJavaIdentifierStart( cp ) ) { + fail( service, u, lc, "Illegal provider-class name: " + ln ); + } + for ( int i = Character.charCount( cp ); i < n; i += Character.charCount( cp ) ) { + cp = ln.codePointAt( i ); + if ( !Character.isJavaIdentifierPart( cp ) && ( cp != '.' ) ) { + fail( service, u, lc, "Illegal provider-class name: " + ln ); + } + } + if ( !providers.containsKey( ln ) && !names.contains( ln ) ) { + names.add( ln ); + } + } + return lc + 1; + } + + private Iterator parse(Class service, URL u) + throws ServiceConfigurationError { + InputStream in = null; + BufferedReader r = null; + ArrayList names = new ArrayList(); + try { + in = u.openStream(); + r = new BufferedReader( new InputStreamReader( in, "utf-8" ) ); + int lc = 1; + while ( ( lc = parseLine( service, u, r, lc, names ) ) >= 0 ) { + ; + } + } + catch ( IOException x ) { + fail( service, "Error reading configuration file", x ); + } + finally { + try { + if ( r != null ) { + r.close(); + } + if ( in != null ) { + in.close(); + } + } + catch ( IOException y ) { + fail( service, "Error closing configuration file", y ); + } + } + return names.iterator(); + } + + public Iterator iterator() { + return providers.values().iterator(); + + } + + public static ServiceLoader load(Class service, + ServiceRegistry serviceRegistry) { + return new ServiceLoader( service, serviceRegistry ); + } + + +}