/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.internal.util.privilegedactions;
import org.hibernate.validator.internal.util.logging.Log;
import org.hibernate.validator.internal.util.logging.LoggerFactory;
import java.lang.invoke.MethodHandles;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
Author: Guillaume Smet
/**
* @author Guillaume Smet
*/
public class GetInstancesFromServiceLoader<T> implements PrivilegedAction<List<T>> {
private final ClassLoader primaryClassLoader;
private final Class<T> clazz;
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
private GetInstancesFromServiceLoader(ClassLoader primaryClassLoader, Class<T> clazz) {
this.primaryClassLoader = primaryClassLoader;
this.clazz = clazz;
}
public static <T> GetInstancesFromServiceLoader<T> action(ClassLoader primaryClassLoader, Class<T> serviceClass) {
return new GetInstancesFromServiceLoader<T>( primaryClassLoader, serviceClass );
}
@Override
public List<T> run() {
// Option #1: try the primary class loader first (either the thread context class loader or the external class
// loader that has been defined)
List<T> instances = loadInstances( primaryClassLoader );
// Option #2: if we cannot find any service files within the primary class loader, use the current class loader
if ( instances.isEmpty() && GetInstancesFromServiceLoader.class.getClassLoader() != primaryClassLoader ) {
instances = loadInstances( GetInstancesFromServiceLoader.class.getClassLoader() );
}
return instances;
}
private List<T> loadInstances(ClassLoader classloader) {
ServiceLoader<T> loader = ServiceLoader.load( clazz, classloader );
Iterator<T> iterator = loader.iterator();
List<T> instances = new ArrayList<T>();
while ( iterator.hasNext() ) {
try {
instances.add( iterator.next() );
}
catch (ServiceConfigurationError e) {
// ignore, because it can happen when multiple
// services are present and some of them are not class loader
// compatible with our API.
// log an error still as it can hide a legitimate issue (see HV-1689)
LOG.unableToLoadInstanceOfService( loader.getClass().getName(), e );
}
}
return instances;
}
}