/*
 * 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;
    }
}
