blob: ad5cc139e2ada4b59e8171a4244908fd4dd527d6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tuscany.sca.core.assembly.impl;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.wsdl.xml.WSDLWriter;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.assembly.Component;
import org.apache.tuscany.sca.assembly.ComponentReference;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.CompositeReference;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.Contract;
import org.apache.tuscany.sca.assembly.Endpoint;
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
import org.apache.tuscany.sca.assembly.builder.BuilderContext;
import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
import org.apache.tuscany.sca.assembly.impl.EndpointImpl;
import org.apache.tuscany.sca.context.CompositeContext;
import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.ExtensionPointRegistryLocator;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory;
import org.apache.tuscany.sca.core.invocation.AsyncResponseService;
import org.apache.tuscany.sca.core.invocation.Constants;
import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor;
import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor;
import org.apache.tuscany.sca.core.invocation.RuntimeInvoker;
import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl;
import org.apache.tuscany.sca.core.invocation.impl.PhaseManager;
import org.apache.tuscany.sca.interfacedef.Compatibility;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract;
import org.apache.tuscany.sca.invocation.Interceptor;
import org.apache.tuscany.sca.invocation.InterceptorAsync;
import org.apache.tuscany.sca.invocation.InvocationChain;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
import org.apache.tuscany.sca.invocation.Message;
import org.apache.tuscany.sca.invocation.MessageFactory;
import org.apache.tuscany.sca.invocation.Phase;
import org.apache.tuscany.sca.provider.BindingProviderFactory;
import org.apache.tuscany.sca.provider.EndpointAsyncProvider;
import org.apache.tuscany.sca.provider.EndpointProvider;
import org.apache.tuscany.sca.provider.ImplementationAsyncProvider;
import org.apache.tuscany.sca.provider.ImplementationProvider;
import org.apache.tuscany.sca.provider.OptimisingBindingProvider;
import org.apache.tuscany.sca.provider.PolicyProvider;
import org.apache.tuscany.sca.provider.PolicyProviderFactory;
import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint;
import org.apache.tuscany.sca.provider.ServiceBindingProvider;
import org.apache.tuscany.sca.runtime.DomainRegistry;
import org.apache.tuscany.sca.runtime.DomainRegistryFactory;
import org.apache.tuscany.sca.runtime.EndpointSerializer;
import org.apache.tuscany.sca.runtime.ExtensibleDomainRegistryFactory;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeComponentService;
import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
import org.apache.tuscany.sca.runtime.RuntimeWireProcessor;
import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint;
import org.apache.tuscany.sca.work.WorkScheduler;
import org.oasisopen.sca.ServiceRuntimeException;
/**
* Runtime model for Endpoint that supports java serialization
*/
public class RuntimeEndpointImpl extends EndpointImpl implements RuntimeEndpoint, Externalizable {
private static final long serialVersionUID = 1L;
private transient CompositeContext compositeContext;
private transient RuntimeWireProcessor wireProcessor;
private transient ProviderFactoryExtensionPoint providerFactories;
private transient InterfaceContractMapper interfaceContractMapper;
private transient WorkScheduler workScheduler;
private transient PhaseManager phaseManager;
private transient MessageFactory messageFactory;
private transient RuntimeInvoker invoker;
private transient EndpointSerializer serializer;
private transient List<InvocationChain> chains;
private transient Map<Operation, InvocationChain> invocationChainMap =
new ConcurrentHashMap<Operation, InvocationChain>();
private transient InvocationChain bindingInvocationChain;
private transient ServiceBindingProvider bindingProvider;
private transient List<PolicyProvider> policyProviders;
private String xml;
private String wsdl;
protected InterfaceContract bindingInterfaceContract;
protected InterfaceContract serviceInterfaceContract;
private RuntimeEndpoint delegateEndpoint;
/**
* No-arg constructor for Java serialization
*/
public RuntimeEndpointImpl() {
super(null);
}
public RuntimeEndpointImpl(ExtensionPointRegistry registry) {
super(registry);
}
protected void copyFrom(RuntimeEndpointImpl copy) {
this.xml = copy.xml;
this.component = copy.component;
this.service = copy.service;
this.interfaceContract = copy.interfaceContract;
this.serviceInterfaceContract = copy.serviceInterfaceContract;
this.binding = copy.binding;
this.bindingInterfaceContract = copy.interfaceContract;
this.bindingInvocationChain = copy.bindingInvocationChain;
this.callbackEndpointReferences = copy.callbackEndpointReferences;
this.requiredIntents = copy.requiredIntents;
this.policySets = copy.policySets;
this.uri = copy.uri;
this.remote = copy.remote;
this.unresolved = copy.unresolved;
this.chains = copy.chains;
this.invocationChainMap = copy.invocationChainMap;
this.bindingProvider = copy.bindingProvider;
this.policyProviders = copy.policyProviders;
if (this.compositeContext == null && copy.compositeContext != null) {
bind(copy.compositeContext);
}
}
public void bind(CompositeContext compositeContext) {
this.compositeContext = compositeContext;
bind(compositeContext.getExtensionPointRegistry(), compositeContext.getEndpointRegistry());
}
public void bind(ExtensionPointRegistry registry, DomainRegistry domainRegistry) {
if (compositeContext == null) {
compositeContext = new CompositeContext(registry, domainRegistry);
}
// if interfaceContractMapper is already initialized then all the rest will be too
if (interfaceContractMapper != null) {
return;
}
this.registry = registry;
UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
this.workScheduler = utilities.getUtility(WorkScheduler.class);
this.wireProcessor =
new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class));
this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class);
this.invoker = new RuntimeInvoker(registry, this);
this.phaseManager = utilities.getUtility(PhaseManager.class);
this.serializer = utilities.getUtility(EndpointSerializer.class);
this.providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class);
this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
this.contractBuilder = builders.getContractBuilder();
}
public void unbind() {
compositeContext = null;
bindingInvocationChain = null;
chains = null;
bindingProvider = null;
policyProviders = null;
invocationChainMap.clear();
}
public synchronized List<InvocationChain> getInvocationChains() {
if (chains == null) {
initInvocationChains();
}
return chains;
}
public synchronized InvocationChain getBindingInvocationChain() {
if (bindingInvocationChain == null) {
bindingInvocationChain = new InvocationChainImpl(null, null, false, phaseManager, isAsyncInvocation());
initServiceBindingInvocationChains();
}
// Init the operation invocation chains now. We know they will
// be needed as well as the binding invocation chain and this
// makes the wire processors run
getInvocationChains();
return bindingInvocationChain;
}
/**
* A dummy invocation chain representing null as ConcurrentHashMap doesn't allow null values
*/
private static final InvocationChain NULL_CHAIN = new InvocationChainImpl(null, null, false, null, false);
public InvocationChain getInvocationChain(Operation operation) {
InvocationChain cached = invocationChainMap.get(operation);
if (cached == null) {
for (InvocationChain chain : getInvocationChains()) {
Operation op = chain.getTargetOperation();
// We used to check compatibility here but this is now validated when the
// chain is created. As the chain operations are the real interface types
// they may be incompatible just because they are described in different
// IDLs
if (operation.getInterface().isRemotable()) {
if (operation.getName().equals(op.getName())) {
invocationChainMap.put(operation, chain);
return chain;
}
if (interfaceContractMapper.isCompatible(operation, op, Compatibility.SUBSET)) {
invocationChainMap.put(operation, chain);
return chain;
}
} else {
// [rfeng] We need to run the compatibility check for local operations as they
// can be overloaded
if (interfaceContractMapper.isCompatible(operation, op, Compatibility.SUBSET)) {
invocationChainMap.put(operation, chain);
return chain;
}
}
}
// Cache it with the NULL_CHAIN to avoid NPE
invocationChainMap.put(operation, NULL_CHAIN);
return null;
} else {
if (cached == NULL_CHAIN) {
cached = null;
}
return cached;
}
}
public Message invoke(Message msg) {
// Deal with async callback
// Ensure invocation chains are built...
getInvocationChains();
// async callback handling
if( this.isAsyncInvocation() && !this.getCallbackEndpointReferences().isEmpty() ) {
RuntimeEndpointReference asyncEPR = (RuntimeEndpointReference) this.getCallbackEndpointReferences().get(0);
// Place a link to the callback EPR into the message headers...
msg.getHeaders().put(Constants.ASYNC_CALLBACK, asyncEPR );
}
// end of async callback handling
return invoker.invokeBinding(msg);
}
public Object invoke(Operation operation, Object[] args) throws InvocationTargetException {
return invoker.invoke(operation, args);
}
public Message invoke(Operation operation, Message msg) {
return invoker.invoke(operation, msg);
}
public void invokeAsync(Message msg){
invoker.invokeBindingAsync(msg);
} // end method invokeAsync(Message)
public void invokeAsync(Operation operation, Message msg){
msg.setOperation(operation);
invoker.invokeAsync(msg);
} // end method invokeAsync(Operation, Message)
public void invokeAsyncResponse(Message msg){
resolve();
invoker.invokeAsyncResponse(msg);
}
/**
* Navigate the component/componentType inheritance chain to find the leaf contract
* @param contract
* @return
*/
private Contract getLeafContract(Contract contract) {
Contract prev = null;
Contract current = contract;
while (current != null) {
prev = current;
if (current instanceof ComponentReference) {
current = ((ComponentReference)current).getReference();
} else if (current instanceof CompositeReference) {
current = ((CompositeReference)current).getPromotedReferences().get(0);
} else if (current instanceof ComponentService) {
current = ((ComponentService)current).getService();
} else if (current instanceof CompositeService) {
current = ((CompositeService)current).getPromotedService();
} else {
break;
}
if (current == null) {
return prev;
}
}
return current;
}
/**
* Initialize the invocation chains
*/
private void initInvocationChains() {
chains = new ArrayList<InvocationChain>();
InterfaceContract sourceContract = getBindingInterfaceContract();
// It's the service wire
RuntimeComponentService service = (RuntimeComponentService)getService();
RuntimeComponent serviceComponent = (RuntimeComponent)getComponent();
//InterfaceContract targetContract = getInterfaceContract();
// TODO - EPR - why is this looking at the component types. The endpoint should have the right interface contract by this time
InterfaceContract targetContract = getComponentTypeServiceInterfaceContract();
// setInterfaceContract(targetContract);
validateServiceInterfaceCompatibility();
for (Operation operation : sourceContract.getInterface().getOperations()) {
Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation);
if (targetOperation == null) {
throw new ServiceRuntimeException("No matching operation for " + operation.getName()
+ " is found in service "
+ serviceComponent.getURI()
+ "#"
+ service.getName());
}
InvocationChain chain = new InvocationChainImpl(operation, targetOperation, false, phaseManager, isAsyncInvocation());
if (operation.isNonBlocking()) {
addNonBlockingInterceptor(chain);
}
addServiceBindingInterceptor(chain, operation);
addImplementationInterceptor(serviceComponent, service, chain, targetOperation);
chains.add(chain);
// Handle cases where the operation is an async server
if( targetOperation.isAsyncServer() ) {
createAsyncServerCallback();
} // end if
}
wireProcessor.process(this);
// If we have to support async and there is no binding chain
// then set the response path to point directly to the
// binding provided async response handler
if (isAsyncInvocation() &&
bindingInvocationChain == null){
// fix up the operation chain response path to point back to the
// binding provided async response handler
ServiceBindingProvider serviceBindingProvider = getBindingProvider();
if (serviceBindingProvider instanceof EndpointAsyncProvider){
EndpointAsyncProvider asyncEndpointProvider = (EndpointAsyncProvider)serviceBindingProvider;
InvokerAsyncResponse asyncResponseInvoker = asyncEndpointProvider.createAsyncResponseInvoker();
for (InvocationChain chain : getInvocationChains()){
Invoker invoker = chain.getHeadInvoker();
if (invoker instanceof InterceptorAsync){
((InterceptorAsync)invoker).setPrevious(asyncResponseInvoker);
} else {
//TODO - throw error once the old async code is removed
} // end if
} // end for
} else {
// TODO - throw error once the old async code is removed
} // end if
} // end if
ServiceBindingProvider provider = getBindingProvider();
if ((provider != null) && (provider instanceof OptimisingBindingProvider)) {
//TODO - remove this comment once optimisation codepath is tested
((OptimisingBindingProvider)provider).optimiseBinding( this );
} // end if
} // end method initInvocationChains
/**
* Creates the async callback for this Endpoint, if it does not already exist
* and stores it into the Endpoint
*/
public void createAsyncServerCallback( ) {
// No need to create a callback if the Binding supports async natively...
if( hasNativeAsyncBinding(this) ) return;
// Check to see if the callback already exists
if( asyncCallbackExists( this ) ) return;
RuntimeEndpointReference asyncEPR = createAsyncEPR( this );
// Store the new callback EPR into the Endpoint
this.getCallbackEndpointReferences().add(asyncEPR);
// Also store the callback EPR into the DomainRegistry
DomainRegistry epReg = getEndpointRegistry( registry );
if( epReg != null ) epReg.addEndpointReference(asyncEPR);
} // end method createAsyncServerCallback
public RuntimeEndpointReference getAsyncServerCallback() {
return (RuntimeEndpointReference) this.getCallbackEndpointReferences().get(0);
} // end method getAsyncServerCallback
/**
* Indicates if a given endpoint has a Binding that supports native async invocation
* @param endpoint - the endpoint
* @return - true if the endpoint has a binding that supports native async, false otherwise
*/
private boolean hasNativeAsyncBinding(RuntimeEndpoint endpoint) {
ServiceBindingProvider provider = endpoint.getBindingProvider();
if( provider instanceof EndpointAsyncProvider ) {
EndpointAsyncProvider asyncProvider = (EndpointAsyncProvider) provider;
if( asyncProvider.supportsNativeAsync() ) return true;
} // end if
return false;
} // end method hasNativeAsyncBinding
/**
* Creates the Endpoint object for the async callback
* @param endpoint - the endpoint which has the async server operations
* @return the EndpointReference object representing the callback
*/
private RuntimeEndpointReference createAsyncEPR( RuntimeEndpoint endpoint ){
CompositeContext compositeContext = endpoint.getCompositeContext();
RuntimeAssemblyFactory assemblyFactory = getAssemblyFactory( compositeContext );
RuntimeEndpointReference epr = (RuntimeEndpointReference)assemblyFactory.createEndpointReference();
epr.bind( compositeContext );
// Create pseudo-component
epr.setComponent(component);
// Create pseudo-reference
ComponentReference reference = assemblyFactory.createComponentReference();
ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
JavaInterfaceFactory javaInterfaceFactory = (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class);
JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
try {
interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseService.class));
} catch (InvalidInterfaceException e1) {
// Nothing to do here - will not happen
} // end try
reference.setInterfaceContract(interfaceContract);
String referenceName = endpoint.getService().getName() + "_asyncCallback";
reference.setName(referenceName);
reference.setForCallback(true);
// Add in "implementation" reference (really a dummy, but with correct interface)
Reference implReference = assemblyFactory.createReference();
implReference.setInterfaceContract(interfaceContract);
implReference.setName(referenceName);
implReference.setForCallback(true);
reference.setReference(implReference);
// Set the created ComponentReference into the EPR
epr.setReference(reference);
// Create a binding
Binding binding = createMatchingBinding( endpoint.getBinding(), (RuntimeComponent)endpoint.getComponent(), reference, registry );
epr.setBinding(binding);
// Need to establish policies here (binding has some...)
epr.getRequiredIntents().addAll( endpoint.getRequiredIntents() );
epr.getPolicySets().addAll( endpoint.getPolicySets() );
// Attach a dummy endpoint to the epr
RuntimeEndpoint ep = (RuntimeEndpoint)assemblyFactory.createEndpoint();
ep.setUnresolved(false);
epr.setTargetEndpoint(ep);
//epr.setStatus(EndpointReference.Status.RESOLVED_BINDING);
epr.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED);
epr.setUnresolved(false);
// Set the URI for the EPR
String eprURI = endpoint.getComponent().getName() + "#reference-binding(" + referenceName + "/" + referenceName + ")";
epr.setURI(eprURI);
return epr;
} // end method RuntimeEndpointReference
private boolean asyncCallbackExists( RuntimeEndpoint endpoint ) {
if( endpoint.getCallbackEndpointReferences().isEmpty() ) return false;
return true;
} // end method asyncCallbackExists
/**
* Create a matching binding to a supplied binding
* - the matching binding has the same binding type, but is for the supplied component and service
* @param matchBinding - the binding to match
* @param component - the component
* @param service - the service
* @param registry - registry for extensions
* @return - the matching binding, or null if it could not be created
*/
@SuppressWarnings("unchecked")
private Binding createMatchingBinding( Binding matchBinding, RuntimeComponent component,
ComponentReference reference, ExtensionPointRegistry registry ) {
// Since there is no simple way to obtain a Factory for a binding where the type is not known ahead of
// time, the process followed here is to generate the <binding.xxx/> XML element from the binding type QName
// and then read the XML using the processor for that XML...
QName bindingName = matchBinding.getType();
String bindingXML = "<ns1:" + bindingName.getLocalPart() + " xmlns:ns1='" + bindingName.getNamespaceURI() + "'/>";
StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(bindingName);
FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
ValidatingXMLInputFactory inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class);
StreamSource source = new StreamSource( new StringReader(bindingXML) );
ProcessorContext context = new ProcessorContext();
try {
XMLStreamReader reader = inputFactory.createXMLStreamReader(source);
reader.next();
Binding newBinding = (Binding) processor.read(reader, context );
newBinding.setName(reference.getName());
// Create a URI address for the callback based on the Component_Name/Reference_Name pattern
//String callbackURI = "/" + component.getName() + "/" + reference.getName();
//newBinding.setURI(callbackURI);
BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
BindingBuilder builder = builders.getBindingBuilder(newBinding.getType());
if (builder != null) {
org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry);
builder.build(component, reference, newBinding, builderContext, true);
} // end if
return newBinding;
} catch (ContributionReadException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
return null;
} // end method createMatchingBinding
/**
* Gets a RuntimeAssemblyFactory from the CompositeContext
* @param compositeContext
* @return the RuntimeAssemblyFactory
*/
private RuntimeAssemblyFactory getAssemblyFactory( CompositeContext compositeContext ) {
ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
return (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
} // end method RuntimeAssemblyFactory
/**
* Check that endpoint has compatible interface at the component and binding ends.
* The user can specify the interfaces at both ends so there is a danger that they won't be compatible.
*/
public void validateServiceInterfaceCompatibility() {
InterfaceContract serviceContract = getComponentServiceInterfaceContract();
InterfaceContract bindingContract = getBindingInterfaceContract();
if ((serviceContract != bindingContract) &&
(serviceContract != null) && (bindingContract != null)) {
boolean bindingHasCallback = bindingContract.getCallbackInterface() != null;
try {
// Use the normalized contract if the interface types are different or if
// a normalized contract has been previously generate, for example, by virtue
// of finding a JAXWS annotation on a Java class that references a WSDL file
if (serviceContract.getClass() != bindingContract.getClass() ||
serviceContract.getNormalizedWSDLContract() != null ||
bindingContract.getNormalizedWSDLContract() != null) {
interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(serviceContract),
getGeneratedWSDLContract(bindingContract),
Compatibility.SUBSET,
!bindingHasCallback, // ignore callbacks if binding doesn't have one
false);
} else {
interfaceContractMapper.checkCompatibility(serviceContract,
bindingContract,
Compatibility.SUBSET,
!bindingHasCallback, // ignore callbacks if binding doesn't have one
false);
}
} catch (Exception ex){
throw new ServiceRuntimeException("Component " +
this.getComponent().getName() +
" Service " +
getService().getName() +
" interface is incompatible with the interface of the service binding - " +
getBinding().getName() +
" - " +
ex.getMessage() +
" - [" + this.toString() + "]");
}
}
}
private void initServiceBindingInvocationChains() {
// add the binding interceptors to the service binding wire
ServiceBindingProvider provider = getBindingProvider();
if ((provider != null) && (provider instanceof EndpointProvider)) {
((EndpointProvider)provider).configure();
}
// add the policy interceptors to the service binding wire
List<PolicyProvider> pps = getPolicyProviders();
if (pps != null) {
for (PolicyProvider p : pps) {
Interceptor interceptor = p.createBindingInterceptor();
if (interceptor != null) {
bindingInvocationChain.addInterceptor(interceptor);
} // end if
} // end for
} // end if
// This is strategically placed before the RuntimeInvoker is added to the end of the
// binding chain as the RuntimeInvoker doesn't need to take part in the response
// processing and doesn't implement InvokerAsyncResponse
ServiceBindingProvider serviceBindingProvider = getBindingProvider();
if (isAsyncInvocation() &&
serviceBindingProvider instanceof EndpointAsyncProvider &&
((EndpointAsyncProvider)serviceBindingProvider).supportsNativeAsync()){
// fix up the invocation chains to point back to the
// binding chain so that async response messages
// are processed correctly
for (InvocationChain chain : getInvocationChains()){
Invoker invoker = chain.getHeadInvoker();
((InterceptorAsync)invoker).setPrevious((InvokerAsyncResponse)bindingInvocationChain.getTailInvoker());
} // end for
// fix up the binding chain response path to point back to the
// binding provided async response handler
EndpointAsyncProvider asyncEndpointProvider = (EndpointAsyncProvider)serviceBindingProvider;
InvokerAsyncResponse asyncResponseInvoker = asyncEndpointProvider.createAsyncResponseInvoker();
((InterceptorAsync)bindingInvocationChain.getHeadInvoker()).setPrevious(asyncResponseInvoker);
} // end if
// Add the runtime invoker to the end of the binding chain.
// It mediates between the binding chain and selects the
// correct invocation chain based on the operation that's
// been selected
bindingInvocationChain.addInvoker(invoker);
} // end method initServiceBindingInvocationChains
/**
* Add the interceptor for a binding
*
* @param reference
* @param binding
* @param chain
* @param operation
*/
private void addServiceBindingInterceptor(InvocationChain chain, Operation operation) {
List<PolicyProvider> pps = getPolicyProviders();
if (pps != null) {
for (PolicyProvider p : pps) {
Interceptor interceptor = p.createInterceptor(operation);
if (interceptor != null) {
chain.addInterceptor(interceptor);
}
}
}
}
/**
* Add a non-blocking interceptor if the service binding needs it
*
* @param service
* @param binding
* @param chain
*/
private void addNonBlockingInterceptor(InvocationChain chain) {
ServiceBindingProvider provider = getBindingProvider();
if (provider != null) {
if (!provider.supportsOneWayInvocation()) {
chain.addInterceptor(Phase.SERVICE, new NonBlockingInterceptor(workScheduler));
}
}
}
/**
* Add the interceptor for a component implementation
*
* @param component
* @param service
* @param chain
* @param operation
*/
private void addImplementationInterceptor(Component component,
ComponentService service,
InvocationChain chain,
Operation operation) {
if (service.getService() instanceof CompositeService) {
CompositeService compositeService = (CompositeService)service.getService();
component = getPromotedComponent(compositeService);
service = getPromotedComponentService(compositeService);
}
ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider();
if (provider != null) {
Invoker invoker = null;
RuntimeComponentService runtimeService = (RuntimeComponentService)service;
if (runtimeService.getName().endsWith("_asyncCallback")){
if (provider instanceof ImplementationAsyncProvider){
invoker = (Invoker)((ImplementationAsyncProvider)provider).createAsyncResponseInvoker(operation);
} else {
// TODO - This should be an error but taking account of the
// existing non-native async support
invoker = provider.createInvoker((RuntimeComponentService)service, operation);
/*
throw new ServiceRuntimeException("Component " +
this.getComponent().getName() +
" Service " +
getService().getName() +
" implementation provider doesn't implement ImplementationAsyncProvider but the implementation uses a " +
"refrence interface with the asyncInvocation intent set" +
" - [" + this.toString() + "]");
*/
}
} else if (isAsyncInvocation() &&
provider instanceof ImplementationAsyncProvider){
invoker = (Invoker)((ImplementationAsyncProvider)provider).createAsyncInvoker((RuntimeComponentService)service, operation);
} else {
invoker = provider.createInvoker((RuntimeComponentService)service, operation);
}
chain.addInvoker(invoker);
}
List<PolicyProvider> pps = ((RuntimeComponent)component).getPolicyProviders();
if (pps != null) {
for (PolicyProvider p : pps) {
Interceptor interceptor = p.createInterceptor(operation);
if (interceptor != null) {
chain.addInterceptor(interceptor);
}
}
}
}
/**
* @see java.lang.Object#clone()
*/
@Override
public Object clone() throws CloneNotSupportedException {
RuntimeEndpointImpl copy = (RuntimeEndpointImpl)super.clone();
copy.invoker = new RuntimeInvoker(registry, copy);
return copy;
}
/**
* Follow a service promotion chain down to the inner most (non composite)
* component service.
*
* @param topCompositeService
* @return
*/
private ComponentService getPromotedComponentService(CompositeService compositeService) {
ComponentService componentService = compositeService.getPromotedService();
if (componentService != null) {
Service service = componentService.getService();
if (componentService.getName() != null && service instanceof CompositeService) {
// Continue to follow the service promotion chain
return getPromotedComponentService((CompositeService)service);
} else {
// Found a non-composite service
return componentService;
}
} else {
// No promoted service
return null;
}
}
/**
* Follow a service promotion chain down to the innermost (non-composite) component.
*
* @param compositeService
* @return
*/
private Component getPromotedComponent(CompositeService compositeService) {
ComponentService componentService = compositeService.getPromotedService();
if (componentService != null) {
Service service = componentService.getService();
if (componentService.getName() != null && service instanceof CompositeService) {
// Continue to follow the service promotion chain
return getPromotedComponent((CompositeService)service);
} else {
// Found a non-composite service
return compositeService.getPromotedComponent();
}
} else {
// No promoted service
return null;
}
}
public synchronized ServiceBindingProvider getBindingProvider() {
resolve();
if (bindingProvider == null) {
BindingProviderFactory factory =
(BindingProviderFactory)providerFactories.getProviderFactory(getBinding().getClass());
if (factory == null) {
throw new ServiceRuntimeException("No provider factory is registered for binding " + getBinding()
.getType());
}
this.bindingProvider = factory.createServiceBindingProvider(this);
}
return bindingProvider;
}
public synchronized List<PolicyProvider> getPolicyProviders() {
resolve();
if (policyProviders == null) {
policyProviders = new ArrayList<PolicyProvider>();
for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) {
PolicyProvider provider = factory.createServicePolicyProvider(this);
if (provider != null) {
policyProviders.add(provider);
}
}
}
return policyProviders;
}
public void setBindingProvider(ServiceBindingProvider provider) {
this.bindingProvider = provider;
}
public Contract getContract() {
return getService();
}
public CompositeContext getCompositeContext() {
return compositeContext;
}
@Override
protected void reset() {
super.reset();
this.xml = null;
}
@Override
protected synchronized void resolve() {
if (xml != null && component == null) {
if (compositeContext == null) {
compositeContext = CompositeContext.getCurrentCompositeContext();
if (compositeContext != null) {
bind(compositeContext);
}
} // end if
if (serializer != null) {
RuntimeEndpointImpl ep = (RuntimeEndpointImpl)serializer.readEndpoint(xml);
copyFrom(ep);
} else {
// In this case, we assume that we're running on a detached (non Tuscany) thread and
// as a result we need to connect back to the Tuscany environment...
ExtensionPointRegistry registry = ExtensionPointRegistryLocator.getExtensionPointRegistry();
if( registry != null ) {
this.registry = registry;
UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
this.serializer = utilities.getUtility(EndpointSerializer.class);
RuntimeEndpointImpl ep = (RuntimeEndpointImpl)serializer.readEndpoint(xml);
// Find the actual Endpoint in the DomainRegistry
ep = findActualEP( ep, registry );
if( ep != null ){
copyFrom( ep );
} // end if
} // end if
} // end if
setNormalizedWSDLContract();
} // end if
super.resolve();
} // end method resolve
/**
* Find the actual Endpoint in the DomainRegistry which corresponds to the configuration described
* in a deserialized Endpoint
* @param ep The deserialized endpoint
* @param registry - the main extension point Registry
* @return the corresponding Endpoint from the DomainRegistry, or null if no match can be found
*/
private RuntimeEndpointImpl findActualEP(RuntimeEndpointImpl ep,
ExtensionPointRegistry registry) {
DomainRegistry domainRegistry = getEndpointRegistry( registry );
if( domainRegistry == null ) return null;
for( Endpoint endpoint : domainRegistry.findEndpoint(ep.getURI()) ) {
// TODO: For the present, simply return the first matching endpoint
return (RuntimeEndpointImpl) endpoint;
} // end for
return null;
} // end method findActualEP
/**
* Get the DomainRegistry
* @param registry - the ExtensionPoint registry
* @return the DomainRegistry - will be null if the DomainRegistry cannot be found
*/
private DomainRegistry getEndpointRegistry( ExtensionPointRegistry registry) {
DomainRegistryFactory domainRegistryFactory = ExtensibleDomainRegistryFactory.getInstance(registry);
if( domainRegistryFactory == null ) return null;
// TODO: For the moment, just use the first (and only!) DomainRegistry...
DomainRegistry domainRegistry = (DomainRegistry) domainRegistryFactory.getEndpointRegistries().toArray()[0];
return domainRegistry;
} // end method
public InterfaceContract getBindingInterfaceContract() {
resolve();
if (bindingInterfaceContract != null) {
return bindingInterfaceContract;
}
bindingInterfaceContract = getBindingProvider().getBindingInterfaceContract();
if (bindingInterfaceContract == null) {
bindingInterfaceContract = getComponentServiceInterfaceContract();
}
if (bindingInterfaceContract == null) {
bindingInterfaceContract = getComponentTypeServiceInterfaceContract();
}
return bindingInterfaceContract;
}
public InterfaceContract getComponentTypeServiceInterfaceContract() {
resolve();
if (serviceInterfaceContract != null) {
return serviceInterfaceContract;
}
if (service == null) {
return getComponentServiceInterfaceContract();
}
serviceInterfaceContract = getLeafContract(service).getInterfaceContract();
if (serviceInterfaceContract == null) {
serviceInterfaceContract = getComponentServiceInterfaceContract();
}
return serviceInterfaceContract;
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.uri = in.readUTF();
this.xml = in.readUTF();
this.wsdl = in.readUTF();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(getURI());
if (serializer == null && xml != null) {
out.writeUTF(xml);
} else {
if (serializer != null) {
out.writeUTF(serializer.write(this));
} else {
throw new IllegalStateException("No serializer is configured");
}
}
if (wsdl == null) {
wsdl = getWsdl();
}
out.writeUTF(wsdl);
}
public String getAsXML() {
if (xml == null) {
this.xml = serializer.write(this);
}
return xml;
}
private String getWsdl() {
InterfaceContract ic = getComponentServiceInterfaceContract();
if (ic == null || ic.getInterface() == null || !!!ic.getInterface().isRemotable()) {
return "";
}
WSDLInterfaceContract wsdlIC = (WSDLInterfaceContract)getGeneratedWSDLContract(getComponentServiceInterfaceContract());
if (wsdlIC == null) {
return "";
}
WSDLInterface wsdl = (WSDLInterface)wsdlIC.getInterface();
WSDLDefinition d = wsdl.getWsdlDefinition();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
try {
WSDLWriter writer = javax.wsdl.factory.WSDLFactory.newInstance().newWSDLWriter();
writer.writeWSDL(d.getDefinition(), outStream);
} catch (Exception e){
throw new RuntimeException(e);
}
return outStream.toString();
}
private void setNormalizedWSDLContract() {
if (wsdl == null || wsdl.length() < 1) {
return;
}
InterfaceContract ic = getComponentServiceInterfaceContract();
if (ic != null) {
// ic.setNormalizedWSDLContract(WSDLHelper.createWSDLInterfaceContract(registry, wsdl));
}
}
public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) {
if ( interfaceContract.getNormalizedWSDLContract() == null){
if (getComponentServiceInterfaceContract() instanceof JavaInterfaceContract){
if (contractBuilder == null){
throw new ServiceRuntimeException("Contract builder not found while calculating WSDL contract for " + this.toString());
}
contractBuilder.build(interfaceContract, null);
}
}
return interfaceContract.getNormalizedWSDLContract();
}
@Override
public RuntimeEndpoint getDelegateEndpoint() {
return delegateEndpoint;
}
@Override
public void setDelegateEndpoint(RuntimeEndpoint delegateEndpoint) {
this.delegateEndpoint = delegateEndpoint;
}
}