|
|
|
@ -10,9 +10,28 @@ import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Properties;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The main container that loads a specific properties file
|
|
|
|
|
* and creates instances of defined services
|
|
|
|
|
* <p>
|
|
|
|
|
* Services are given arbitrary names and can be defined as singletons:
|
|
|
|
|
* <code><pre>
|
|
|
|
|
* service.servicename: tld.vendor.project.ServiceClass
|
|
|
|
|
* service.servicename.singleton: true
|
|
|
|
|
* </pre></code>
|
|
|
|
|
* Service names must match the regular expression <code>^service\.[^.]+$</code>
|
|
|
|
|
* <p>
|
|
|
|
|
* Services declare their dependencies via their constructor. Only one
|
|
|
|
|
* constructor per class is allowed.
|
|
|
|
|
* All dependencies must be declared in the same container as the declaring
|
|
|
|
|
* service.
|
|
|
|
|
* <p>
|
|
|
|
|
* After loading the properties file, an {@link IntegrityCheck} will be performed.
|
|
|
|
|
*/
|
|
|
|
|
public class SdiContainer implements SdiContainerInterface {
|
|
|
|
|
|
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(SdiContainer.class);
|
|
|
|
@ -25,11 +44,22 @@ public class SdiContainer implements SdiContainerInterface {
|
|
|
|
|
this.singletons = new HashMap<>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a Container using the file <code>sdic.properties</code> from the classpath.
|
|
|
|
|
*
|
|
|
|
|
* @return the loaded and integrity checked container
|
|
|
|
|
*/
|
|
|
|
|
@SuppressWarnings("unused")
|
|
|
|
|
public static SdiContainer load() {
|
|
|
|
|
return load("sdic.properties");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a Container using the properties file at the designated location
|
|
|
|
|
*
|
|
|
|
|
* @param filename the filename that shall be loaded
|
|
|
|
|
* @return the loaded and integrity checked container
|
|
|
|
|
*/
|
|
|
|
|
@SuppressWarnings("WeakerAccess")
|
|
|
|
|
public static SdiContainer load(String filename) {
|
|
|
|
|
Properties props = new Properties();
|
|
|
|
@ -57,6 +87,16 @@ public class SdiContainer implements SdiContainerInterface {
|
|
|
|
|
.orElse(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates and returns a service instance of the given class
|
|
|
|
|
* <p>
|
|
|
|
|
* Dependency services are automatically created. Services marked
|
|
|
|
|
* as singletons will be only created once, either as transient
|
|
|
|
|
* or direct dependency.
|
|
|
|
|
*
|
|
|
|
|
* @param clz the type which shall be created
|
|
|
|
|
* @return the created type with declared dependencies fulfilled
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public <T> T getInstance(Class<T> clz) {
|
|
|
|
|
LOG.trace("instance ordered: ", clz);
|
|
|
|
@ -80,6 +120,22 @@ public class SdiContainer implements SdiContainerInterface {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* returns all registered services that implement or extend the given class
|
|
|
|
|
*
|
|
|
|
|
* @param clz parent class or interface
|
|
|
|
|
* @return the list with instances, or an empty list if nothing is found
|
|
|
|
|
*/
|
|
|
|
|
@SuppressWarnings("WeakerAccess")
|
|
|
|
|
public <T> List<T> getInstancesThatImplement(Class<T> clz) {
|
|
|
|
|
LOG.trace("instances of interface {} ordered", clz);
|
|
|
|
|
return definitions.stream()
|
|
|
|
|
.filter(d -> clz.isAssignableFrom(d.getClz()))
|
|
|
|
|
.map(ServiceDefinition::getClz)
|
|
|
|
|
.map(c -> clz.cast(getInstance(c)))
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private <T> void handleSingleton(ServiceDefinition definition, T instance) {
|
|
|
|
|
if (definition.isSingleton()) {
|
|
|
|
|
singletons.put(definition, instance);
|
|
|
|
|