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

Source Code of org.apache.tuscany.sca.core.assembly.RuntimeWireImpl

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

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

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.Contract;
import org.apache.tuscany.sca.core.conversation.ConversationManager;
import org.apache.tuscany.sca.core.invocation.InvocationChainImpl;
import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor;
import org.apache.tuscany.sca.core.invocation.RuntimeWireInvoker;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.invocation.InvocationChain;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;
import org.apache.tuscany.sca.invocation.MessageFactory;
import org.apache.tuscany.sca.provider.ImplementationProvider;
import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
import org.apache.tuscany.sca.runtime.EndpointReference;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
import org.apache.tuscany.sca.runtime.RuntimeComponentService;
import org.apache.tuscany.sca.runtime.RuntimeWire;
import org.apache.tuscany.sca.runtime.RuntimeWireProcessor;
import org.apache.tuscany.sca.work.WorkScheduler;
import org.osoa.sca.ServiceRuntimeException;

/**
* @version $Rev: 608822 $ $Date: 2008-01-04 12:59:56 +0000 (Fri, 04 Jan 2008) $
*/
public class RuntimeWireImpl implements RuntimeWire {
    private EndpointReference wireSource;
    private EndpointReference wireTarget;

    private transient RuntimeWireProcessor wireProcessor;
    private transient InterfaceContractMapper interfaceContractMapper;
    private transient WorkScheduler workScheduler;
    private transient MessageFactory messageFactory;
    private transient ConversationManager conversationManager;
    private transient RuntimeWireInvoker invoker;

    private List<InvocationChain> chains;

    /**
     * @param source
     * @param target
     * @param interfaceContractMapper
     * @param workScheduler
     * @param wireProcessor
     * @param messageFactory
     * @param conversationManager
     */
    public RuntimeWireImpl(EndpointReference source,
                           EndpointReference target,
                           InterfaceContractMapper interfaceContractMapper,
                           WorkScheduler workScheduler,
                           RuntimeWireProcessor wireProcessor,
                           MessageFactory messageFactory, ConversationManager conversationManager) {
        super();
        this.wireSource = source;
        this.wireTarget = target;
        this.interfaceContractMapper = interfaceContractMapper;
        this.workScheduler = workScheduler;
        this.wireProcessor = wireProcessor;
        this.messageFactory = messageFactory;
        this.conversationManager = conversationManager;
        this.invoker = new RuntimeWireInvoker(this.messageFactory, this.conversationManager, this);
    }

    public synchronized List<InvocationChain> getInvocationChains() {
        if (chains == null) {
            initInvocationChains();
        }
        return chains;
    }

    public InvocationChain getInvocationChain(Operation operation) {
        for (InvocationChain chain : getInvocationChains()) {
            Operation op = null;
            if (wireSource.getContract() != null) {
                // Reference chain
                op = chain.getSourceOperation();
            } else {
                // Service chain
                op = chain.getTargetOperation();
            }
            if (interfaceContractMapper.isCompatible(operation, op, op.getInterface().isRemotable())) {
                return chain;
            }
        }
        return null;
    }

    public Object invoke(Operation operation, Object[] args) throws InvocationTargetException {
        Message msg = messageFactory.createMessage();
        msg.setBody(args);
        return invoker.invoke(operation, msg);
    }

    public Object invoke(Operation operation, Message msg) throws InvocationTargetException {
        return invoker.invoke(operation, msg);
    }

    /**
     * Initialize the invocation chains
     */
    private void initInvocationChains() {
        chains = new ArrayList<InvocationChain>();
        InterfaceContract sourceContract = wireSource.getInterfaceContract();
        InterfaceContract targetContract = wireTarget.getInterfaceContract();

        Contract source = wireSource.getContract();
        if (source instanceof RuntimeComponentReference) {
            // It's the reference wire
            RuntimeComponentReference reference = (RuntimeComponentReference)wireSource.getContract();
            Binding refBinding = wireSource.getBinding();
            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 "
                        + wireSource.getComponent().getURI()
                        + "#"
                        + reference.getName());
                }
                InvocationChain chain = new InvocationChainImpl(operation, targetOperation);
                if (operation.isNonBlocking()) {
                    addNonBlockingInterceptor(reference, refBinding, chain);
                }
                addBindingInterceptor(reference, refBinding, chain, operation);
                chains.add(chain);
            }
        } else {
            // It's the service wire
            RuntimeComponentService service = (RuntimeComponentService)wireTarget.getContract();
            RuntimeComponent serviceComponent = wireTarget.getComponent();
            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);
                addImplementationInterceptor(serviceComponent, service, chain, targetOperation);
                chains.add(chain);
            }
        }
        wireProcessor.process(this);
    }

    public EndpointReference getSource() {
        return wireSource;
    }

    public EndpointReference getTarget() {
        return wireTarget;
    }

    public void setTarget(EndpointReference target) {
        if (this.wireTarget != target) {
            rebuild();
        }
        this.wireTarget = target;
    }

    public void rebuild() {
        this.chains = null;
    }

    /**
     * Add the interceptor for a binding
     *
     * @param reference
     * @param binding
     * @param chain
     * @param operation
     */
    private void addBindingInterceptor(ComponentReference reference,
                                       Binding binding,
                                       InvocationChain chain,
                                       Operation operation) {
        try {
            ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding);
            if (provider != null) {
                Invoker invoker = provider.createInvoker(operation);
                if (invoker != null) {
                    chain.addInvoker(invoker);
                }
            }
        } catch (RuntimeException e) {
            throw e;
        }
    }

    /**
     * Add a non-blocking interceptor if the reference binding needs it
     *
     * @param reference
     * @param binding
     * @param chain
     */
    private void addNonBlockingInterceptor(ComponentReference reference, Binding binding, InvocationChain chain) {
        ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding);
        if (provider != null) {
            boolean supportsOneWayInvocation = provider.supportsOneWayInvocation();
            if (!supportsOneWayInvocation) {
                chain.addInterceptor(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) {
        ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider();
        if (provider != null) {
            Invoker invoker = null;
            invoker = provider.createInvoker((RuntimeComponentService)service, operation);
            chain.addInvoker(invoker);
        }
    }

    /**
     * @see java.lang.Object#clone()
     */
    @Override
    public Object clone() throws CloneNotSupportedException {
        RuntimeWireImpl copy = (RuntimeWireImpl)super.clone();
        copy.wireSource = (EndpointReference)wireSource.clone();
        copy.wireTarget = (EndpointReference)wireTarget.clone();
        copy.invoker = new RuntimeWireInvoker(copy.messageFactory, copy.conversationManager, copy);
        return copy;
    }

    /**
     * @return the conversationManager
     */
    public ConversationManager getConversationManager() {
        return conversationManager;
    }
}
TOP

Related Classes of org.apache.tuscany.sca.core.assembly.RuntimeWireImpl

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.