/* * Copyright (c) 2013 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.common.core.service; import java.util.Collection; import java.util.Collections; import java.util.List; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ListMultimap; import de.fhg.igd.slf4jplus.ALogger; import de.fhg.igd.slf4jplus.ALoggerFactory; import eu.esdihumboldt.hale.common.core.service.internal.ServiceFactoryDefinition; import eu.esdihumboldt.hale.common.core.service.internal.ServiceFactoryExtension; /** * Manages HALE service instances. * * @author Simon Templer */ public class ServiceManager implements ServiceProvider, ServiceConstants { private static final ALogger log = ALoggerFactory.getLogger(ServiceManager.class); private final String serviceScope; /** * Service factories. */ private final ListMultimap<Class<?>, ServiceFactory> factories = ArrayListMultimap.create(); /** * Instantiated services. */ private final ListMultimap<Class<?>, Object> services = ArrayListMultimap.create(); /** * Create a service manager for the given scope. * * @param serviceScope the service scope, <code>null</code> for all service * scopes */ public ServiceManager(String serviceScope) { super(); this.serviceScope = serviceScope; // get all relevant services of the given scope for (ServiceFactoryDefinition sf : ServiceFactoryExtension.getInstance().getElements()) { if (serviceScope == null || serviceScope.equals(sf.getScope())) { // only use service factories of the correct scope for (Class<?> iface : sf.getServiceInterfaces()) { factories.put(iface, sf); } } } } @Override public <T> T getService(Class<T> serviceInterface) { Collection<T> services = getServices(serviceInterface); if (!services.isEmpty()) { return services.iterator().next(); } else { return null; } } /** * Get service instances providing the given interface. * * @param serviceInterface the service interface * @return the service instances available */ @SuppressWarnings("unchecked") public <T> Collection<T> getServices(Class<T> serviceInterface) { synchronized (services) { List<T> instances = (List<T>) services.get(serviceInterface); if (instances.isEmpty()) { List<ServiceFactory> serviceFactories = factories.get(serviceInterface); for (ServiceFactory factory : serviceFactories) { try { T service = factory.createService(serviceInterface, this); if (service != null) { services.put(serviceInterface, service); } } catch (Exception e) { log.error("Error creating " + getServiceScope() + " service instance for interface " + serviceInterface.getName(), e); } } if (instances.isEmpty()) { // add null to mark that we tried to create the services // already instances.add(null); } } if (instances.size() == 1 && instances.get(0) == null) { // no services available return Collections.emptyList(); } else { return ImmutableList.copyOf(instances); } } } /** * Get the scope of services provided by the manager. * * @return the service scope name or <code>null</code> representing all * scopes */ public String getServiceScope() { return serviceScope; } /** * Remove all service instances. */ public void clear() { synchronized (services) { services.clear(); } } }