/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.communication.testutils;
import org.apache.commons.logging.LogFactory;
import de.rcenvironment.core.communication.api.CommunicationService;
import de.rcenvironment.core.communication.api.LiveNetworkIdResolutionService;
import de.rcenvironment.core.communication.api.NodeIdentifierService;
import de.rcenvironment.core.communication.api.PlatformService;
import de.rcenvironment.core.communication.channel.MessageChannelLifecycleListener;
import de.rcenvironment.core.communication.channel.MessageChannelService;
import de.rcenvironment.core.communication.configuration.NodeConfigurationService;
import de.rcenvironment.core.communication.connection.api.ConnectionSetupService;
import de.rcenvironment.core.communication.connection.impl.ConnectionSetupServiceImpl;
import de.rcenvironment.core.communication.connection.internal.MessageChannelServiceImpl;
import de.rcenvironment.core.communication.internal.CommunicationServiceImpl;
import de.rcenvironment.core.communication.internal.LiveNetworkIdResolutionServiceImpl;
import de.rcenvironment.core.communication.internal.PlatformServiceImpl;
import de.rcenvironment.core.communication.management.CommunicationManagementService;
import de.rcenvironment.core.communication.management.RemoteBenchmarkService;
import de.rcenvironment.core.communication.management.WorkflowHostService;
import de.rcenvironment.core.communication.management.internal.BenchmarkServiceImpl;
import de.rcenvironment.core.communication.management.internal.CommunicationManagementServiceImpl;
import de.rcenvironment.core.communication.management.internal.WorkflowHostServiceImpl;
import de.rcenvironment.core.communication.nodeproperties.NodePropertiesService;
import de.rcenvironment.core.communication.nodeproperties.internal.NodePropertiesServiceImpl;
import de.rcenvironment.core.communication.nodeproperties.spi.RawNodePropertiesChangeListener;
import de.rcenvironment.core.communication.routing.MessageRoutingService;
import de.rcenvironment.core.communication.routing.NetworkRoutingService;
import de.rcenvironment.core.communication.routing.internal.NetworkRoutingServiceImpl;
import de.rcenvironment.core.communication.routing.internal.v2.DistributedLinkStateManager;
import de.rcenvironment.core.communication.routing.internal.v2.LinkStateKnowledgeChangeListener;
import de.rcenvironment.core.communication.rpc.api.CallbackProxyService;
import de.rcenvironment.core.communication.rpc.api.CallbackService;
import de.rcenvironment.core.communication.rpc.api.RemoteServiceCallSenderService;
import de.rcenvironment.core.communication.rpc.internal.CallbackProxyServiceImpl;
import de.rcenvironment.core.communication.rpc.internal.RemoteServiceCallSenderServiceImpl;
import de.rcenvironment.core.communication.rpc.internal.ServiceCallHandlerServiceImpl;
import de.rcenvironment.core.communication.rpc.internal.ServiceProxyFactoryImpl;
import de.rcenvironment.core.communication.rpc.spi.LocalServiceResolver;
import de.rcenvironment.core.communication.rpc.spi.RemoteServiceCallHandlerService;
import de.rcenvironment.core.communication.rpc.spi.ServiceProxyFactory;
import de.rcenvironment.core.communication.spi.NetworkTopologyChangeListener;
import de.rcenvironment.core.communication.transport.spi.NetworkTransportProvider;
import de.rcenvironment.core.utils.common.service.MockAdditionalServicesRegistrationService;
/**
* A factory for {@link VirtualCommunicationBundle} instances intended for integration tests.
*
* @author Robert Mischke
*/
public final class VirtualCommunicationBundleFactory {
/**
* {@link VirtualCommunicationBundle} implementation.
*
* @author Robert Mischke
*/
private static final class VirtualCommunicationBundleImpl implements VirtualCommunicationBundle {
private MessageChannelServiceImpl messageChannelService;
private NetworkRoutingServiceImpl routingService;
private NodePropertiesServiceImpl nodePropertiesService;
private MockAdditionalServicesRegistrationService listenerRegistrationService;
private final VirtualServiceRegistry serviceRegistry;
private DistributedLinkStateManager distributedLinkStateManager;
private boolean autoStartNetworkOnActivation = true;
private CommunicationManagementServiceImpl communicationManagementService;
VirtualCommunicationBundleImpl(NodeConfigurationService nodeConfigurationService) {
serviceRegistry = new VirtualServiceRegistry();
listenerRegistrationService = new MockAdditionalServicesRegistrationService();
serviceRegistry.registerProvidedService(nodeConfigurationService, NodeConfigurationService.class);
serviceRegistry.registerProvidedService(nodeConfigurationService.getNodeIdentifierService(), NodeIdentifierService.class);
messageChannelService = new MessageChannelServiceImpl();
serviceRegistry.registerManagedService(messageChannelService, MessageChannelService.class);
ConnectionSetupServiceImpl connectionSetupService = new ConnectionSetupServiceImpl();
serviceRegistry.registerManagedService(connectionSetupService, false, ConnectionSetupService.class);
listenerRegistrationService.registerAdditionalServicesProvider(connectionSetupService);
nodePropertiesService = new NodePropertiesServiceImpl();
serviceRegistry.registerManagedService(nodePropertiesService, NodePropertiesService.class);
routingService = new NetworkRoutingServiceImpl();
// bind for both implemented interface
serviceRegistry.registerManagedService(routingService, NetworkRoutingService.class, MessageRoutingService.class);
listenerRegistrationService.registerAdditionalServicesProvider(routingService);
// keep reference to prevent automatic network startup before activation
communicationManagementService = new CommunicationManagementServiceImpl();
serviceRegistry.registerManagedService(communicationManagementService, CommunicationManagementService.class);
serviceRegistry.registerManagedService(new PlatformServiceImpl(), PlatformService.class);
serviceRegistry.registerManagedService(new LiveNetworkIdResolutionServiceImpl(), false, LiveNetworkIdResolutionService.class);
serviceRegistry.registerManagedService(new RemoteServiceCallSenderServiceImpl(), false, RemoteServiceCallSenderService.class);
// register stubs; replace when RPC callbacks should be made testable
serviceRegistry.registerProvidedService(new CallbackServiceDefaultStub(), CallbackService.class);
serviceRegistry.registerProvidedService(new CallbackProxyServiceImpl(), CallbackProxyService.class);
serviceRegistry.registerManagedService(new ServiceProxyFactoryImpl(), false, ServiceProxyFactory.class);
serviceRegistry.registerManagedService(new WorkflowHostServiceImpl(), WorkflowHostService.class);
CommunicationServiceImpl communicationService = new CommunicationServiceImpl();
serviceRegistry.registerManagedService(communicationService, CommunicationService.class);
listenerRegistrationService.registerAdditionalServicesProvider(communicationService);
distributedLinkStateManager = new DistributedLinkStateManager();
serviceRegistry.registerManagedService(distributedLinkStateManager, true, DistributedLinkStateManager.class);
listenerRegistrationService.registerAdditionalServicesProvider(distributedLinkStateManager);
// register a virtual LocalServiceResolver stub
serviceRegistry.registerProvidedService(new LocalServiceResolverStub(), LocalServiceResolver.class);
// register the standard RPC handler (which uses the resolver stub)
serviceRegistry.registerManagedService(new ServiceCallHandlerServiceImpl(), false, RemoteServiceCallHandlerService.class);
// add a simple remote service for RPC testing
serviceRegistry.registerProvidedService(new BenchmarkServiceImpl(), RemoteBenchmarkService.class);
}
@Override
public void registerNetworkTransportProvider(NetworkTransportProvider newProvider) {
messageChannelService.addNetworkTransportProvider(newProvider);
}
@Override
public void activate() {
// transfer autostart setting
communicationManagementService.setAutoStartNetworkOnActivation(autoStartNetworkOnActivation);
serviceRegistry.bindAndActivateServices();
// connect dynamic listeners
for (NetworkTopologyChangeListener listener : listenerRegistrationService.
getListeners(NetworkTopologyChangeListener.class)) {
routingService.addNetworkTopologyChangeListener(listener);
}
for (RawNodePropertiesChangeListener listener : listenerRegistrationService.
getListeners(RawNodePropertiesChangeListener.class)) {
nodePropertiesService.addRawNodePropertiesChangeListener(listener);
}
for (MessageChannelLifecycleListener listener : listenerRegistrationService.
getListeners(MessageChannelLifecycleListener.class)) {
messageChannelService.addChannelLifecycleListener(listener);
}
for (LinkStateKnowledgeChangeListener listener : listenerRegistrationService.
getListeners(LinkStateKnowledgeChangeListener.class)) {
distributedLinkStateManager.addLinkStateKnowledgeChangeListener(listener);
}
// TODO auto-detect unbound listeners?
}
@Override
public void setAutoStartNetworkOnActivation(boolean autoStartNetworkOnActivation) {
this.autoStartNetworkOnActivation = autoStartNetworkOnActivation;
}
@Override
public <T> T getService(Class<T> clazz) {
T implementation = serviceRegistry.getService(clazz);
if (implementation == null) {
throw new NullPointerException("No activated service provides the interface " + clazz.getName());
}
return implementation;
}
@Override
public <T> void injectService(Class<T> clazz, T implementation) {
// note: services are not implicitly activated
serviceRegistry.registerProvidedService(implementation, clazz);
}
/**
* A {@link LocalServiceResolver} implementation that accesses this instance's {@link VirtualServiceRegistry}.
*
* @author Robert Mischke
*/
private final class LocalServiceResolverStub implements LocalServiceResolver {
@Override
public Object getLocalService(String serviceName) {
try {
Object impl = serviceRegistry.getService(Class.forName(serviceName));
if (impl == null) {
LogFactory.getLog(getClass()).error("No such service available: " + serviceName);
return null;
}
return impl;
} catch (ClassNotFoundException e) {
LogFactory.getLog(getClass()).error("Failed to resolve service class " + serviceName, e);
return null;
}
}
}
}
private VirtualCommunicationBundleFactory() {}
/**
* Creates a {@link VirtualCommunicationBundle} from an existing {@link NodeConfigurationService}.
*
* @param nodeConfigurationService the {@link NodeConfigurationService} to pull configuration value from
* @return the new instance
*/
public static VirtualCommunicationBundle createFromNodeConfigurationService(NodeConfigurationService nodeConfigurationService) {
return new VirtualCommunicationBundleImpl(nodeConfigurationService);
}
}