Package org.apache.tuscany.sca.core.assembly.impl

Source Code of org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl

/*
* 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.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Binding;
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.EndpointReference;
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.EndpointReferenceImpl;
import org.apache.tuscany.sca.context.CompositeContext;
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.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.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.EndpointReferenceProvider;
import org.apache.tuscany.sca.provider.ImplementationAsyncProvider;
import org.apache.tuscany.sca.provider.ImplementationProvider;
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.ReferenceBindingProvider;
import org.apache.tuscany.sca.runtime.DomainRegistryFactory;
import org.apache.tuscany.sca.runtime.EndpointReferenceBinder;
import org.apache.tuscany.sca.runtime.DomainRegistry;
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.RuntimeComponentReference;
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 RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implements RuntimeEndpointReference, Externalizable {
    private transient CompositeContext compositeContext;
    private transient RuntimeWireProcessor wireProcessor;
    private transient InterfaceContractMapper interfaceContractMapper;
    private transient WorkScheduler workScheduler;
    private transient PhaseManager phaseManager;
    private transient MessageFactory messageFactory;
    private transient RuntimeInvoker invoker;
    private transient DomainRegistry domainRegistry;

    private transient List<InvocationChain> chains;
    private transient Map<Operation, InvocationChain> invocationChainMap =
        new ConcurrentHashMap<Operation, InvocationChain>();
    private transient InvocationChain bindingInvocationChain;

    private transient EndpointReferenceBinder eprBinder;
    private transient ReferenceBindingProvider bindingProvider;
    private transient ProviderFactoryExtensionPoint providerFactories;
    private transient List<PolicyProvider> policyProviders;
    private transient EndpointSerializer serializer;

    protected InterfaceContract bindingInterfaceContract;
    protected InterfaceContract referenceInterfaceContract;
   
    //protected InterfaceContract generatedReferenceWSDLInterfaceContract;
   
    private String xml;

    private boolean started;
   
    private RuntimeEndpointReference delegateEndpointReference;
   
    /**
     * No-arg constructor for Java serilization
     */
    public RuntimeEndpointReferenceImpl() {
        super(null);
    }

    public RuntimeEndpointReferenceImpl(ExtensionPointRegistry registry) {
        super(registry);
    }

    protected void copyFrom(RuntimeEndpointReferenceImpl copy) {
        this.xml = copy.xml;

        this.component = copy.component;
        this.reference = copy.reference;
        this.interfaceContract = copy.interfaceContract;
        this.referenceInterfaceContract = copy.referenceInterfaceContract;
        this.callbackEndpoint = copy.callbackEndpoint;
        this.targetEndpoint = copy.targetEndpoint;

        this.binding = copy.binding;
        this.bindingInterfaceContract = copy.interfaceContract;
        this.bindingInvocationChain = copy.bindingInvocationChain;

        this.requiredIntents = copy.requiredIntents;
        this.policySets = copy.policySets;

        this.uri = copy.uri;
        this.unresolved = copy.unresolved;
        this.status = copy.status;

        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);
        }
        this.registry = registry;
        this.domainRegistry = domainRegistry;
        UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
        this.eprBinder = utilities.getUtility(EndpointReferenceBinder.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 synchronized List<InvocationChain> getInvocationChains() {
        if (chains == null) {
            initInvocationChains();
        }
        return chains;
    }

    public synchronized InvocationChain getBindingInvocationChain() {
        if (bindingInvocationChain == null) {
            bindingInvocationChain = new InvocationChainImpl(null, null, true, phaseManager, isAsyncInvocation());
            initReferenceBindingInvocationChains();
        }
        return bindingInvocationChain;
    }

    public InvocationChain getInvocationChain(Operation operation) {
        InvocationChain cached = invocationChainMap.get(operation);
        if (cached == null) {
            for (InvocationChain chain : getInvocationChains()) {
                Operation op = chain.getSourceOperation();
               
                // 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.getName().equals(op.getName())) {
                    invocationChainMap.put(operation, chain);
                    return chain;
                }
            }
            invocationChainMap.put(operation, null);
            return null;
        } else {
            return cached;
        }
    }

    public Message invoke(Message msg) {
        return invoker.invoke(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(Operation operation, Message msg){
        msg.setOperation(operation);
        invoker.invokeAsync(msg);
    }
   
    public void invokeAsync(Message msg){
        invoker.invokeAsync(msg);
    }
   
    public void invokeAsyncResponse(Message msg){
      // If there is a Binding Chain, invoke it first...
        InvocationChain chain = this.getBindingInvocationChain();
        if( chain != null ) {
          Invoker tailInvoker = chain.getTailInvoker();
          if (tailInvoker != null) {
            ((InvokerAsyncResponse)tailInvoker).invokeAsyncResponse(msg);
      } // end if
        } // end if
       
        chain = this.getInvocationChain(msg.getOperation());
        Invoker tailInvoker = chain.getTailInvoker();
        ((InvokerAsyncResponse)tailInvoker).invokeAsyncResponse(msg);  
    } // end method invokeAsyncResponse    

    /**
     * Navigate the component/componentType inheritence 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() {
        InterfaceContract sourceContract = getComponentTypeReferenceInterfaceContract();
        // TODO - EPR why is this looking at the component types. The endpoint reference should have the right interface contract by this time
        //InterfaceContract sourceContract = getLeafInterfaceContract(endpointReference);

        // It's the reference wire
        resolveEndpointReference();

        InterfaceContract targetContract = getBindingInterfaceContract();
        // TODO - EPR why is this looking at the component types. The endpoint should have the right interface contract by this time
        //InterfaceContract targetContract = getLeafInterfaceContract(endpoint);

        if (sourceContract == null && targetContract != null) {
            // TODO: until the web component introspection is brought up
            try {
                sourceContract = (InterfaceContract)targetContract.clone();
            } catch (CloneNotSupportedException e) {
                throw new IllegalStateException(e);
            }
        }
       
        validateReferenceInterfaceCompatibility();

        List<InvocationChain> chainList = new ArrayList<InvocationChain>();
        if(sourceContract != null && targetContract != null) {
            RuntimeComponentReference reference = (RuntimeComponentReference)getReference();
            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 reference "
                        + getComponent().getURI()
                        + "#"
                        + reference.getName());
                }
                InvocationChain chain = new InvocationChainImpl(operation, targetOperation, true, phaseManager, isAsyncInvocation());
                if (operation.isNonBlocking()) {
                    addNonBlockingInterceptor(chain);
                }
                chainList.add(chain);
                addReferenceBindingInterceptor(chain, operation);
            }           
        }

        // Set the chains until it's fully populated. If we initialize too early, any exception could
        // leave this endpoint reference in a wrong state with an empty chain.
        chains = chainList;
        wireProcessor.process(this);
       
        if (isAsyncInvocation()){
            // Fix up all of the operation chain response paths to point back to the implementation provided
            // async response handler
            //ImplementationProvider implementationProvider = ((RuntimeComponent)getComponent()).getImplementationProvider();
          RuntimeComponentReference theReference = (RuntimeComponentReference)this.getReference();
          RuntimeComponent theComponent = theReference.getComponent();
            ImplementationProvider implementationProvider = theComponent.getImplementationProvider();
            if (implementationProvider instanceof ImplementationAsyncProvider){
                for (InvocationChain chain : getInvocationChains()){
                    InvokerAsyncResponse asyncResponseInvoker = ((ImplementationAsyncProvider)implementationProvider).createAsyncResponseInvoker(chain.getSourceOperation());
                    if (chain.getHeadInvoker() instanceof InterceptorAsync){
                        ((InterceptorAsync)chain.getHeadInvoker()).setPrevious(asyncResponseInvoker);
                    } else {
                        //TODO - throw error once the old async code is removed
                    } // end if
                } // end for
            } // end if
        } // end if
    } // end method initInvocationChains
   
    /**
     * Check that endpoint reference 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.
     * There is checking in the activator but of course endpoint references may not have a binding assigned
     * until final resolution.
     */
    public void validateReferenceInterfaceCompatibility() {

        InterfaceContract referenceContract = getComponentReferenceInterfaceContract();
        InterfaceContract bindingContract =  getBindingInterfaceContract();
       
       if ((referenceContract != 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 (referenceContract.getClass() != bindingContract.getClass() ||
                   referenceContract.getNormalizedWSDLContract() != null ||
                   bindingContract.getNormalizedWSDLContract() != null) {
                   interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(referenceContract),
                                                              getGeneratedWSDLContract(bindingContract),
                                                              Compatibility.SUBSET,
                                                              !bindingHasCallback, // ignore callbacks if binding doesn't have one
                                                              false);
               } else {
                   interfaceContractMapper.checkCompatibility(referenceContract,
                                                              bindingContract,
                                                              Compatibility.SUBSET,
                                                              !bindingHasCallback, // ignore callbacks if binding doesn't have one
                                                              false);                  
              
           } catch (Exception ex){
               throw new ServiceRuntimeException("Component " +
                                                 this.getComponent().getName() +
                                                 " Reference " +
                                                 getReference().getName() +
                                                 " interface is incompatible with the interface of the reference binding " +
                                                 getBinding().getName() +
                                                 " - " +
                                                 ex.getMessage() +
                                                 " - [" + this.toString() + "]");
           }
        } 
    }    

    /**
     * This code used to be in the activator but has moved here as
     * the endpoint reference may not now be resolved until the wire
     * is first used
     */
    private void resolveEndpointReference() {
        resolve();

        eprBinder.bindRunTime(domainRegistry, this);

        // start the binding provider
        final ReferenceBindingProvider bindingProvider = getBindingProvider();

        if (bindingProvider != null) {
            // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy.
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    bindingProvider.start();
                    return null;
                }
            });
        }
        for (PolicyProvider policyProvider : getPolicyProviders()) {
            policyProvider.start();
        }

        started = true;
        // InterfaceContract bindingContract = getBindingInterfaceContract();
        // endpoint.setInterfaceContract(bindingContract);
    }

    private void initReferenceBindingInvocationChains() {

        // add the binding interceptors to the reference binding wire
        ReferenceBindingProvider provider = getBindingProvider();
        if ((provider != null) && (provider instanceof EndpointReferenceProvider)) {
            ((EndpointReferenceProvider)provider).configure();
        }

        // add the policy interceptors to the service binding wire
        // find out which policies are active
        for (PolicyProvider p : getPolicyProviders()) {
           Interceptor interceptor = p.createBindingInterceptor();
            if (interceptor != null) {
                bindingInvocationChain.addInterceptor(interceptor);
            }
        }
    }

    public void rebuild() {
        // TODO - can we use the idea of setTarget to rebuild the wire?
        //        used at the moment by binding.sca when it resets the
        //        source interface contract for local wires
        this.chains = null;

        if (getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED){
            setStatus(EndpointReference.Status.NOT_CONFIGURED);
        }

        // TODO - cheating here as I fixed the RuntimeComponentService code
        //        to call this when it resets the interface contract
        //endpointReference.setInterfaceContract(epr.getInterfaceContract());
    }

    /**
     * Add the interceptor for a reference binding
     *
     * @param reference
     * @param binding
     * @param chain
     * @param operation
     */
    private void addReferenceBindingInterceptor(InvocationChain chain, Operation operation) {
        ReferenceBindingProvider provider = getBindingProvider();
        if (provider != null) {
            Invoker invoker = provider.createInvoker(operation);
            if (invoker != null) {
                chain.addInvoker(invoker);
            }
        }
        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 reference binding needs it
     *
     * @param reference
     * @param binding
     * @param chain
     */
    private void addNonBlockingInterceptor(InvocationChain chain) {
        ReferenceBindingProvider provider = getBindingProvider();
        if (provider != null) {
            boolean supportsOneWayInvocation = provider.supportsOneWayInvocation();
            if (!supportsOneWayInvocation) {
                chain.addInterceptor(Phase.REFERENCE, new NonBlockingInterceptor(workScheduler));
            }
        }
    }

    /**
     * @see java.lang.Object#clone()
     */
    @Override
    public Object clone() throws CloneNotSupportedException {
        RuntimeEndpointReferenceImpl copy = (RuntimeEndpointReferenceImpl)super.clone();
        copy.invoker = new RuntimeInvoker(registry, copy);
        return copy;
    }

    public boolean isOutOfDate() {
        resolve();
        return eprBinder.isOutOfDate(domainRegistry, this);
    }

    public synchronized ReferenceBindingProvider getBindingProvider() {
        resolve();
        // For the case that binding.sca is implemented by another binding
        if (binding == null) {
            return null;
        }
        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.createReferenceBindingProvider(this);
        }
        return bindingProvider;
    }

    public void setBindingProvider(ReferenceBindingProvider bindingProvider) {
        this.bindingProvider = bindingProvider;
    }

    public synchronized List<PolicyProvider> getPolicyProviders() {
        resolve();
        if (policyProviders == null) {
            policyProviders = new ArrayList<PolicyProvider>();
            for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) {
                PolicyProvider provider = factory.createReferencePolicyProvider(this);
                if (provider != null) {
                    policyProviders.add(provider);
                }
            }
        }
        return policyProviders;
    }

    public void unbind() {
        bindingInvocationChain = null;
        chains = null;
        bindingProvider = null;
        policyProviders = null;
        invocationChainMap.clear();
    }

    public Contract getContract() {
        return getReference();
    }

    public CompositeContext getCompositeContext() {
        return compositeContext;
    }

    public InterfaceContract getBindingInterfaceContract() {
        resolve();
        if (bindingInterfaceContract != null) {
            return bindingInterfaceContract;
        }
        ReferenceBindingProvider provider = getBindingProvider();
        if (provider != null) {
            bindingInterfaceContract = provider.getBindingInterfaceContract();
        }
        if (bindingInterfaceContract == null) {
            bindingInterfaceContract = getComponentReferenceInterfaceContract();
        }
        if (bindingInterfaceContract == null) {
            bindingInterfaceContract = getComponentTypeReferenceInterfaceContract();
        }
        return bindingInterfaceContract;
    }

    public InterfaceContract getComponentTypeReferenceInterfaceContract() {
        resolve();
        if (referenceInterfaceContract != null) {
            return referenceInterfaceContract;
        }
        if (reference == null) {
            return getComponentReferenceInterfaceContract();
        }
        referenceInterfaceContract = getLeafContract(reference).getInterfaceContract();
        if (referenceInterfaceContract == null) {
            referenceInterfaceContract = getComponentReferenceInterfaceContract();
        }
        return referenceInterfaceContract;
    }

    @Override
    protected synchronized void resolve() {
        if (xml != null && component == null) {
            if (compositeContext == null) {
                compositeContext = CompositeContext.getCurrentCompositeContext();
                if (compositeContext != null) {
                    bind(compositeContext);
                }
            }
            if (serializer != null) {
                RuntimeEndpointReferenceImpl epr = (RuntimeEndpointReferenceImpl)serializer.readEndpointReference(xml);
                copyFrom(epr);
            } 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.serializer = utilities.getUtility(EndpointSerializer.class);
                    RuntimeEndpointReferenceImpl epr = (RuntimeEndpointReferenceImpl)serializer.readEndpointReference(xml);
                    // Find the actual Endpoint in the DomainRegistry
                    epr = findActualEPR( epr, registry );
                    if( epr != null ){
                        copyFrom( epr );
                    } // end if
                } // end if
            } // end if           
        }
        super.resolve();
    } // end method resolve
   
    /**
     * Find the actual EndpointReference in the DomainRegistry which corresponds to the configuration described
     * in a deserialized EndpointReference
     * @param ep The deserialized endpointReference
     * @param registry - the main extension point Registry
     * @return the corresponding EndpointReference from the DomainRegistry, or null if no match can be found
     */
    private RuntimeEndpointReferenceImpl findActualEPR(RuntimeEndpointReferenceImpl epr,
      ExtensionPointRegistry registry) {
    // Get the DomainRegistry
        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];
        if( domainRegistry == null ) return null;
       
        for( EndpointReference epReference : domainRegistry.getEndpointReferences() ) {
          // TODO: For the present, simply return the first matching endpointReference
          if( epReference.getURI().equals(epr.getURI()) ) {
              return (RuntimeEndpointReferenceImpl) epReference;
          } // end if
        } // end for
       
    return null;
  } // end method findActualEPR

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.uri = in.readUTF();
        this.xml = 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");
            }
        }
    }

    public boolean isStarted() {
        return started;
    }
   
    public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) {

        if ( interfaceContract.getNormalizedWSDLContract() == null){
            if (getComponentReferenceInterfaceContract() 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();     
    }  
   
    public void createAsyncCallbackEndpoint(){
        CompositeContext compositeContext = getCompositeContext();
        FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
        RuntimeAssemblyFactory assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
       
        RuntimeEndpoint endpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint();
        endpoint.bind(compositeContext);
        endpoint.setComponent(getComponent());

        // Create pseudo-service
        ComponentService service = assemblyFactory.createComponentService();
        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
       
        service.setInterfaceContract(interfaceContract);
       
        String serviceName = getReference().getName() + "_asyncCallback";
        service.setName(serviceName);
        service.getEndpoints().add(endpoint);
        service.setForCallback(true);
        endpoint.setService(service);
       
        // Set pseudo-service onto the component
        getComponent().getServices().add(service);
       
        // if the reference has a WSDL contract reset the response endpoint to be WSDL also
        InterfaceContract referenceInterfaceContract = getComponentTypeReferenceInterfaceContract();
        if (referenceInterfaceContract instanceof WSDLInterfaceContract){
            WSDLInterfaceContract wsdlInterfaceContract = (WSDLInterfaceContract)endpoint.getGeneratedWSDLContract(interfaceContract);
            service.setInterfaceContract(wsdlInterfaceContract);
        }        

        // Create a binding
        // Mike had to go via the XML but I don't remember why
        Binding binding = null;
        try {
            binding = (Binding)getBinding().clone();
        } catch (Exception ex){
            //
        }
        String callbackURI = "/" + component.getName() + "/" + service.getName();
        binding.setURI(callbackURI);
       
        BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
        BindingBuilder builder = builders.getBindingBuilder(binding.getType());
        if (builder != null) {
            org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry);
            builder.build(component, service, binding, builderContext, true);
        } // end if
       
        endpoint.setBinding(binding);

        // Need to establish policies here (binding has some...)
        endpoint.getRequiredIntents().addAll(getRequiredIntents());
        endpoint.getPolicySets().addAll(getPolicySets());
        String epURI = getComponent().getName() + "#service-binding(" + serviceName + "/" + serviceName + ")";
        endpoint.setURI(epURI);
        endpoint.setUnresolved(false);
       
        setCallbackEndpoint(endpoint);
    }
   
    @Override
    public RuntimeEndpointReference getDelegateEndpointReference() {
        return delegateEndpointReference;
    }
   
    @Override
    public void setDelegateEndpointReference(RuntimeEndpointReference delegateEndpointReference) {
        this.delegateEndpointReference = delegateEndpointReference;
    }
}
TOP

Related Classes of org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.