/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.toolkit.core.internal; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.picocontainer.DefaultPicoContainer; import org.picocontainer.behaviors.Caching; import de.rcenvironment.toolkit.core.api.ImmutableServiceRegistry; import de.rcenvironment.toolkit.core.api.ToolkitException; /** * An {@link AbstractObjectGraph} implementation based on the PicoContainer library. * * @author Robert Mischke */ public class PicoContainerObjectGraph extends AbstractObjectGraph { private DefaultPicoContainer container; private Map<Class<?>, Object> services = new HashMap<>(); public PicoContainerObjectGraph() { container = new DefaultPicoContainer(new Caching()); // container with object caching behavior } @Override protected void registerObject(Object object, Collection<Class<?>> privateInterfaces) { container.addComponent(object); } @Override protected void registerServiceClass(Object implementationClass, Collection<Class<?>> publicInterfaces, Collection<Class<?>> privateInterfaces) { // optimistically let PicoContainer handle the internal interface mapping selection for now, ie no explicit filtering; // adjust as necessary container.addComponent(implementationClass); // logDebug("Registering service implementation class " + implementationClass); for (Class<?> i : publicInterfaces) { // TODO verify uniqueness, fail on overlap // logDebug("Registering interface to publish: " + i); services.put(i, null); } } @Override public boolean isMissingService(Class<?> serviceInterface) { return !services.containsKey(serviceInterface); } @Override protected ImmutableServiceRegistry instantiateServices(Collection<Class<?>> serviceInterfaces) throws ToolkitException { try { for (Class<?> i : services.keySet()) { Object impl = container.getComponent(i); services.put(i, impl); logDebug("Publishing service " + i.getName() + " implemented by " + impl); } return new ImmutableServiceRegistryImpl(services); } catch (RuntimeException e) { if (e.getClass().getName().contains("UnsatisfiableDependenciesException")) { // compress known stacktrace; this also keeps PicoContainer classes hidden from user throw new ToolkitException("Error constructing the service object graph: " + e.getMessage()); } else { throw new ToolkitException("Error constructing the service object graph", e); } } } }