HHH-6573 change to use ClassLoaderService to locate service initiator

This commit is contained in:
Strong Liu 2011-08-15 15:30:55 +08:00
parent 71adfabca8
commit 4ccc536c99
2 changed files with 197 additions and 5 deletions

View File

@ -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<Integrator> getIntegrators() {
LinkedHashSet<Integrator> integrators = new LinkedHashSet<Integrator>();
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 );
}

View File

@ -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<S> implements Iterable<S> {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class, ServiceLoader.class.getName()
);
private static final String PREFIX = "META-INF/services/";
private LinkedHashMap<String, S> providers = new LinkedHashMap<String, S>();
private ServiceLoader(Class<S> svc, ServiceRegistry serviceRegistry) {
Class<S> service = svc;
ClassLoaderService loader = serviceRegistry.getService( ClassLoaderService.class );
String fullName = PREFIX + service.getName();
service.getName();
List<URL> configs = locateResources( loader, fullName );
for ( URL url : configs ) {
Iterator<String> 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<URL> locateResources(ClassLoaderService loader, String fullName) {
List<URL> urls = new ArrayList<URL>();
urls.addAll( loader.locateResources( fullName ) );
try {
Enumeration<URL> 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<String> 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<String> parse(Class service, URL u)
throws ServiceConfigurationError {
InputStream in = null;
BufferedReader r = null;
ArrayList<String> names = new ArrayList<String>();
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<S> iterator() {
return providers.values().iterator();
}
public static <S> ServiceLoader<S> load(Class<S> service,
ServiceRegistry serviceRegistry) {
return new ServiceLoader<S>( service, serviceRegistry );
}
}