package org.ow2.choreos.ee.context;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.apache.log4j.Logger;
import org.ow2.choreos.chors.datamodel.Choreography;
import org.ow2.choreos.chors.datamodel.LegacyService;
import org.ow2.choreos.chors.datamodel.LegacyServiceInstance;
import org.ow2.choreos.invoker.Invoker;
import org.ow2.choreos.invoker.InvokerException;
import org.ow2.choreos.invoker.InvokerFactory;
import org.ow2.choreos.services.datamodel.DeployableService;
import org.ow2.choreos.services.datamodel.Proxification;
import org.ow2.choreos.services.datamodel.Service;
import org.ow2.choreos.services.datamodel.ServiceDependency;
import org.ow2.choreos.services.datamodel.ServiceInstance;
import org.ow2.choreos.services.datamodel.ServiceType;
/**
* Cast choreography context to a single service.
*
* @author leonardo
*
*/
public class ServiceContextCaster {
private static final String TASK_NAME = "SET_INVOCATION_ADDRESS";
private static Logger logger = Logger.getLogger(ServiceContextCaster.class);
private final Choreography chor;
private final Service consumer;
private final String consumerName;
private Service provider;
private String providerName, providerRole;
public ServiceContextCaster(Choreography chor, Service consumer) {
this.chor = chor;
this.consumer = consumer;
this.consumerName = consumer.getSpec().getName();
}
public void cast() {
if (!isConsumerOK())
return;
Map<String, Service> deployedServicesMap = chor.getMapOfServicesBySpecNames();
for (ServiceDependency dep : consumer.getSpec().getDependencies()) {
providerName = dep.getServiceSpecName();
providerRole = dep.getServiceSpecRole();
provider = deployedServicesMap.get(providerName);
if (provider == null) {
logger.error("Service " + providerName + " not deployed. Not goint to pass this context to "
+ consumerName + " on chor " + chor.getId());
} else {
if (provider.getSpec().getRoles().contains(providerRole))
sendProviderContextToConsumer();
else
logger.error("Service " + providerName + " does not have role " + providerRole
+ "; not going to pass it to service " + consumerName + " on chor " + chor.getId());
}
}
}
private boolean isConsumerOK() {
List<ServiceDependency> dependencies = consumer.getSpec().getDependencies();
return dependencies != null && !dependencies.isEmpty();
}
public void sendProviderContextToConsumer() {
ServiceType consumerType = consumer.getSpec().getServiceType();
List<String> consumerUris = consumer.getUris();
List<String> providerUris = this.getUris(provider);
for (String consumerEndpoint : consumerUris) {
ContextSenderTask task = new ContextSenderTask(consumerType, consumerEndpoint, providerRole, providerName,
providerUris);
InvokerFactory<Void> factory = new InvokerFactory<Void>();
Invoker<Void> invoker = factory.geNewInvokerInstance(TASK_NAME, task);
try {
invoker.invoke();
} catch (InvokerException e) {
logger.error("Could not set " + providerName + " as " + providerRole + " to " + consumerName
+ " on chor " + chor.getId());
}
}
}
/**
* Get URIs from service that will be used in the setInvocationAddress.
*
* Implementation: if possible, uses the SOAP bus URI; if not use the
* nativeUri
*
* @param providerService
* @return
*/
private List<String> getUris(Service service) {
if (service instanceof DeployableService) {
return getUrisFromDeployable((DeployableService) service);
} else if (service instanceof LegacyService) {
return getUrisFromLegacy((LegacyService) service);
}
throw new IllegalArgumentException("Invalid service " + service);
}
private List<String> getUrisFromDeployable(DeployableService providerService) {
List<String> uris = new ArrayList<String>();
for (ServiceInstance instance : providerService.getInstances()) {
Proxification prox = instance.getProxification();
boolean isProxified = prox != null && prox.getBusUri(ServiceType.SOAP) != null;
if (isProxified) {
String proxifiedUri = prox.getBusUri(ServiceType.SOAP);
uris.add(proxifiedUri);
} else {
uris.add(instance.getNativeUri());
}
}
return uris;
}
// TODO: eliminate replication by building an abstract ServiceInstance
private List<String> getUrisFromLegacy(LegacyService providerService) {
List<String> uris = new ArrayList<String>();
for (LegacyServiceInstance instance : providerService.getLegacyServiceInstances()) {
Proxification prox = instance.getProxification();
boolean isProxified = prox != null && prox.getBusUri(ServiceType.SOAP) != null;
if (isProxified) {
String proxifiedUri = prox.getBusUri(ServiceType.SOAP);
uris.add(proxifiedUri);
} else {
uris.add(instance.getUri());
}
}
return uris;
}
private class ContextSenderTask implements Callable<Void> {
ServiceType consumerType;
String consumerEndpoint, providerRole, providerName;
List<String> providerEndpoints;
public ContextSenderTask(ServiceType consumerType, String consumerEndpoint, String providerRole,
String providerName, List<String> providerEndpoints) {
this.consumerType = consumerType;
this.consumerEndpoint = consumerEndpoint;
this.providerRole = providerRole;
this.providerName = providerName;
this.providerEndpoints = providerEndpoints;
}
@Override
public Void call() throws Exception {
ContextSender sender = ContextSenderFactory.getNewInstance(consumerType);
sender.sendContext(consumerEndpoint, providerRole, providerName, providerEndpoints);
return null;
}
}
}