Package org.apache.tuscany.sca.binding.sca.impl

Source Code of org.apache.tuscany.sca.binding.sca.impl.RuntimeSCAReferenceBindingProvider

/*
* 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.binding.sca.impl;

import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.tuscany.sca.assembly.OptimizableBinding;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.binding.sca.DistributedSCABinding;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.domain.SCADomainEventService;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
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.node.NodeFactory;
import org.apache.tuscany.sca.provider.BindingProviderFactory;
import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint;
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.osoa.sca.ServiceUnavailableException;

/**
* The sca reference binding provider mediates between the twin requirements of
* local sca bindings and remote sca bindings. In the local case is does
* very little. When the sca binding model is set as being remote (because a
* reference target can't be resolved in the current model) this binding will
* try and create a remote connection to it
*
* @version $Rev: 636903 $ $Date: 2008-03-13 15:21:31 -0700 (Thu, 13 Mar 2008) $
*/
public class RuntimeSCAReferenceBindingProvider implements ReferenceBindingProvider {

    private final static Logger logger = Logger.getLogger(RuntimeSCAReferenceBindingProvider.class.getName());

    private NodeFactory nodeFactory;
    private RuntimeComponent component;
    private RuntimeComponentReference reference;
    private SCABinding binding;
    private boolean started = false;

    private BindingProviderFactory<DistributedSCABinding> distributedProviderFactory = null;
    private ReferenceBindingProvider distributedProvider = null;

    public RuntimeSCAReferenceBindingProvider(ExtensionPointRegistry extensionPoints,
                                              NodeFactory nodeFactory,
                                              RuntimeComponent component,
                                              RuntimeComponentReference reference,
                                              SCABinding binding) {
        this.nodeFactory = nodeFactory;
        this.component = component;
        this.reference = reference;
        this.binding = binding;

        // look to see if a distributed SCA binding implementation has
        // been included on the classpath. This will be needed by the
        // provider itself to do it's thing
        ProviderFactoryExtensionPoint factoryExtensionPoint =
            extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class);
        distributedProviderFactory =
            (BindingProviderFactory<DistributedSCABinding>)factoryExtensionPoint
                .getProviderFactory(DistributedSCABinding.class);

        // determine if the target is remote. If we can tell now then this will
        // do some initialization before we get to run time
        //isTargetRemote();
    }

    public boolean isTargetRemote() {
        boolean targetIsRemote = false;

        // first look at the target service and see if this has been resolved
        OptimizableBinding optimizableBinding = (OptimizableBinding)binding;

        // The descision is based primary on the results of the wiring process in the assembly model
        // however there are two notable situations when this process doesn't give the right answer
        // 1. When a callback is in operation. A callback reference bindings sometimes has to
        //    act as though there is a local wire and sometimes as if there is a remote wire
        // 2. When a reference is retrieved from the domain. In this case the reference
        //    will not have been part of the original wiring process and will only have
        //    a target set if the target is local
        if (optimizableBinding.getTargetComponentService() != null) {
            if (optimizableBinding.getTargetComponentService().isUnresolved() == true) {
                targetIsRemote = true;
            } else {
                targetIsRemote = false;
            }
        } else {
            // deal with the case where the wire is completely dynamic (e.g. callbacks) and
            // look at the provided URI to decide whether is a local or remote case
            try {
                URI uri = new URI(binding.getURI());
                if (uri.isAbsolute()) {
                    targetIsRemote = true;
                } else {
                    // look in the domain to see if this referenced service is available on this node
                    // or on some other node
                    String serviceNode = null;

                    SCADomainEventService domainProxy = (SCADomainEventService)nodeFactory.getNode().getDomain();

                    try {
                        serviceNode =
                            domainProxy.findServiceNode(nodeFactory.getNode().getDomain().getURI(),
                                                        binding.getURI(),
                                                        binding.getClass().getName());
                    } catch (Exception ex) {
                        logger.log(Level.WARNING,
                                   "Unable to contact domain to find service node. Service: " + nodeFactory.getNode()
                                       .getDomain().getURI()
                                       + " "
                                       + nodeFactory.getNode().getURI()
                                       + " "
                                       + binding.getURI()
                                       + " "
                                       + SCABinding.class.getName());

                    }

                    if (serviceNode.equals(domainProxy.SERVICE_NOT_KNOWN)) {
                        throw new IllegalStateException("Can't resolve : " + component.getName()
                            + " and reference: "
                            + reference.getName()
                            + " as the service "
                            + binding.getURI()
                            + " has not been contributed to the domain");
                    } else if ((serviceNode.equals(domainProxy.SERVICE_NOT_REGISTERED)) || (!serviceNode
                        .equals(nodeFactory.getNode().getURI()))) {
                        targetIsRemote = true;
                    } else {
                        targetIsRemote = false;
                    }
                }
            } catch (Exception ex) {
                targetIsRemote = false;
            }
        }
        return targetIsRemote;
    }

    private ReferenceBindingProvider getDistributedProvider() {

        if (isTargetRemote()) {
            // initialize the remote provider if it hasn't been done already
            if (distributedProvider == null) {
                if (!reference.getInterfaceContract().getInterface().isRemotable()) {
                    throw new IllegalStateException("Reference interface not remoteable for component: " + component
                        .getName()
                        + " and reference: "
                        + reference.getName());
                }

                if (distributedProviderFactory == null) {
                    throw new IllegalStateException("No distributed SCA binding available for component: " + component
                        .getName()
                        + " and reference: "
                        + reference.getName());
                }

                if ((nodeFactory != null) && (nodeFactory.getNode() == null)) {
                    throw new IllegalStateException("No distributed domain available for component: " + component
                        .getName()
                        + " and reference: "
                        + reference.getName());
                }

                // create the remote provider
                DistributedSCABinding distributedBinding = new DistributedSCABindingImpl();
                distributedBinding.setSCABinging(binding);

                distributedProvider =
                    distributedProviderFactory.createReferenceBindingProvider(component, reference, distributedBinding);
            }

        }

        return distributedProvider;
    }

    public InterfaceContract getBindingInterfaceContract() {
        if (isTargetRemote()) {
            return getDistributedProvider().getBindingInterfaceContract();
        } else {
            if (reference.getReference() != null) {
                return reference.getReference().getInterfaceContract();
            } else {
                return reference.getInterfaceContract();
            }
        }
    }

    public boolean supportsOneWayInvocation() {
        if (isTargetRemote()) {
            return getDistributedProvider().supportsOneWayInvocation();
        } else {
            return false;
        }
    }

    /**
     * @param wire
     */
    private Invoker getInvoker(RuntimeWire wire, Operation operation) {
        EndpointReference target = wire.getTarget();
        if (target != null) {
            RuntimeComponentService service = (RuntimeComponentService)target.getContract();
            if (service != null) { // not a callback wire
                SCABinding scaBinding = service.getBinding(SCABinding.class);
                InvocationChain chain =
                    service.getInvocationChain(scaBinding, wire.getSource().getInterfaceContract(), operation);
                return chain == null ? null : new SCABindingInvoker(chain);
            }
        }
        return null;
    }

    public Invoker createInvoker(Operation operation) {
        if (isTargetRemote()) {
            return getDistributedProvider().createInvoker(operation);
        } else {
            RuntimeWire wire = reference.getRuntimeWire(binding);
            Invoker invoker = getInvoker(wire, operation);
            if (invoker == null) {
                throw new ServiceUnavailableException("Service not found for component " + component.getName()
                    + " reference "
                    + reference.getName()
                    + " (bindingURI="
                    + binding.getURI()
                    + " operation="
                    + operation.getName()
                    + "). Ensure that the composite containing the service is loaded and "
                    + "started somewhere in the SCA domain and that if running in a "
                    + "remote node that the interface of the target service marked as @Remotable");
            }
            return invoker;
        }
    }

    public void start() {
        if (started) {
            return;
        } else {
            started = true;
        }

        if (getDistributedProvider() != null) {
            distributedProvider.start();
        }
    }

    public void stop() {
        if (!started) {
            return;
        } else {
            started = false;
        }

        if (getDistributedProvider() != null) {
            distributedProvider.stop();
        }
    }

}
TOP

Related Classes of org.apache.tuscany.sca.binding.sca.impl.RuntimeSCAReferenceBindingProvider

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.