I'm trying to back-port to J1.8 an application written for J9 (Update4j); it uses ServiceLoader.Provider class and its methods. The original code is:
public static <T extends Service> T loadService(ModuleLayer layer, ClassLoader classLoader, Class<T> type,
String classname) {
if (classname != null && !StringUtils.isClassName(classname)) {
throw new IllegalArgumentException(classname + " is not a valid Java class name.");
}
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
ServiceLoader<T> loader;
List<Provider<T>> providers = new ArrayList<>();
if (layer != null) {
loader = ServiceLoader.load(layer, type);
providers.addAll(loader.stream().collect(Collectors.toList()));
}
loader = ServiceLoader.load(type, classLoader);
providers.addAll(loader.stream().collect(Collectors.toList()));
if (classname != null) {
// an explicit class name is used
// first lets look at providers, to locate in closed modules
for (Provider<T> p : providers) {
if (p.type().getName().equals(classname))
return p.get();
}
// nothing found, lets load with reflection
try {
Class<?> clazz = classLoader.loadClass(classname);
if (type.isAssignableFrom(clazz)) {
// What do you mean?? look 1 line above
@SuppressWarnings("unchecked")
T value = (T) clazz.getConstructor().newInstance();
return value;
} else {
// wrong type
throw new IllegalArgumentException(classname + " is not of type " + type.getCanonicalName());
}
} catch (RuntimeException e) {
throw e; // avoid unnecessary wrapping
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
if (providers.isEmpty()) {
throw new IllegalStateException("No provider found for " + type.getCanonicalName());
}
List<T> values = providers.stream().map(Provider::get).collect(Collectors.toList());
long maxVersion = Long.MIN_VALUE;
T maxValue = null;
for (T t : values) {
long version = t.version();
if (maxVersion <= version) {
maxVersion = version;
maxValue = t;
}
}
return maxValue;
}
}
How can you achieve the same result in J1.8? Is there a best-practice? Unfortunately J1.8 does not have ServiceLoader.Provider and its utility methods. Should I iterate and select? Is there a reference I can study? Thanks