/*
* Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi)
*
* Licensed under the EUPL, Version 1.1 or – as soon they
* will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
*
* You may not use this work except in compliance with the Licence.
*
* You may obtain a copy of the Licence at:
*
* https://joinup.ec.europa.eu/community/eupl/og_page/eupl
*
* Unless required by applicable law or agreed to in
* writing, software distributed under the Licence is
* distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the Licence for the specific language governing
* permissions and limitations under the Licence.
*/
package no.difi.oxalis.commons.guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import no.difi.oxalis.api.lang.OxalisPluginException;
import no.difi.oxalis.commons.util.ClassUtils;
import java.io.*;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* This class works by the same principles as {@link java.util.ServiceLoader}, however this implementation loads each
* detected class using the Guice injector.
*
* @author erlend
*/
public class GuiceServiceLoader {
private static final String PREFIX = "META-INF/services/";
private final Injector injector;
@Inject
public GuiceServiceLoader(Injector injector) {
this.injector = injector;
}
public <T> List<T> load(Class<T> cls, ClassLoader classLoader) {
try {
// Find all instances of files in class loader.
return Collections.list(classLoader.getResources(PREFIX + cls.getName())).stream()
// Fetch all lines in all detected files.
.map(this::getLines)
// Convert stream of lists to stream.
.flatMap(Collection::stream)
// Load classes referenced in detected files.
.map(s -> (Class<T>) ClassUtils.load(s, classLoader))
// Load each class using Guice magic.
.map(injector::getInstance)
// Collect all instances to a list.
.collect(Collectors.toList());
} catch (IOException e) {
throw new OxalisPluginException("Unable to load resources.", e);
}
}
/**
* Extracts all lines in the provided target.
*/
private List<String> getLines(URL url) {
try (InputStream inputStream = url.openStream();
Reader reader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(reader)) {
// Read all lines.
return bufferedReader.lines()
// Trim all lines.
.map(String::trim)
// Collect all lines.
.collect(Collectors.toList());
} catch (IOException e) {
throw new OxalisPluginException("Unable to read.", e);
}
}
/**
* Loads a class from the given class loader.
*/
private Class<?> getClass(String className, ClassLoader classLoader) {
try {
return Class.forName(className, false, classLoader);
} catch (ClassNotFoundException e) {
throw new OxalisPluginException("Unable to get class definition.", e);
}
}
}