Package org.apache.tuscany.sca.node.impl

Source Code of org.apache.tuscany.sca.node.impl.SCANodeImpl

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

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;

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.Composite;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.assembly.SCABindingFactory;
import org.apache.tuscany.sca.assembly.xml.Constants;
import org.apache.tuscany.sca.contribution.Contribution;
import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
import org.apache.tuscany.sca.contribution.resolver.impl.ModelResolverImpl;
import org.apache.tuscany.sca.contribution.service.ContributionService;
import org.apache.tuscany.sca.core.assembly.ActivationException;
import org.apache.tuscany.sca.core.context.ServiceReferenceImpl;
import org.apache.tuscany.sca.node.ComponentManager;
import org.apache.tuscany.sca.node.ContributionManager;
import org.apache.tuscany.sca.node.SCANode;
import org.apache.tuscany.sca.node.NodeManagerInitService;
import org.apache.tuscany.sca.domain.SCADomain;
import org.apache.tuscany.sca.domain.DomainManagerService;
import org.apache.tuscany.sca.domain.SCADomainService;
import org.apache.tuscany.sca.host.embedded.impl.EmbeddedSCADomain;
import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeComponentContext;
import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
import org.osoa.sca.CallableReference;
import org.osoa.sca.ServiceReference;
import org.osoa.sca.ServiceRuntimeException;

/**
* A local representation of the sca domain running on a single node
*
* @version $Rev: 552343 $ $Date: 2007-09-09 23:54:46 +0100 (Sun, 09 Sep 2007) $
*/
public class SCANodeImpl extends SCADomain implements SCANode {
 
    private final static Logger logger = Logger.getLogger(SCANodeImpl.class.getName());
 
    public final static String LOCAL_DOMAIN_URI = "standalonedomain";
    public final static String LOCAL_NODE_URI = "standalonenode";
   
    private boolean isStandalone = false;
   
    // the domain used by the node to talk to the rest of the domain
    private EmbeddedSCADomain managementRuntime;
   
    // class loader used to get the runtime going
    private ClassLoader domainClassLoader;
   
    // class loader used to get application resources
    private ClassLoader applicationClassLoader;   
   
    // representation of the private state of the node that the domain is running on
    private String domainUri;
    private URL domainUrl;
    private String nodeUri;
    private URL nodeUrl;
    private ReallySmallRuntime nodeRuntime;
    private Composite nodeComposite;
   
    // the managers used to control the domain node
    private ComponentManagerServiceImpl componentManager;
    private ContributionManagerImpl contributionManager;
   
    // the proxies to the domain
    private SCADomainService scaDomain;
    private DomainManagerService domainManager;
    private NodeManagerInitService nodeManagerInit;
      
    // methods defined on the implementation only
   
    /**
     * Default constructor creates a standalone node with no connectivity to a wider
     * domain and no local web page.
     */
    public SCANodeImpl()
      throws ActivationException {
        this.domainUri = LOCAL_DOMAIN_URI ;
        this.nodeUri = LOCAL_NODE_URI;
        this.domainClassLoader = SCANodeImpl.class.getClassLoader();
        this.applicationClassLoader = Thread.currentThread().getContextClassLoader();               
        this.isStandalone = true;
        init();
    }
      
    /**
     * Creates a node connected to a wider domain.  To find its place in the domain
     * node and domain identifiers must be provided.
     *
     * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081
     * @param nodeUri - if this is a url it is assumed that this will be used as root url for management components, e.g. http://localhost:8082
     * @throws ActivationException
     */
    public SCANodeImpl(String domainUri, String nodeUri)
    throws ActivationException {
        this.domainUri = domainUri;
        this.nodeUri = nodeUri;
        this.domainClassLoader = SCANodeImpl.class.getClassLoader();
        this.applicationClassLoader = Thread.currentThread().getContextClassLoader();       
        this.isStandalone = LOCAL_DOMAIN_URI.equals(domainUri);
        init();
    }   
   
    /**
     * Creates a node connected to a wider domain and allows a classpath to be specified. 
     * To find its place in the domain node and domain identifiers must be provided.
     *
     * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081
     * @param nodeUri - if this is a url it is assumed that this will be used as root url for management components, e.g. http://localhost:8082
     * @param cl - the ClassLoader to use for loading system resources for the node
     * @throws ActivationException
     */
    public SCANodeImpl(String domainUri, String nodeUri, ClassLoader cl)
    throws ActivationException {
        this.domainUri = domainUri;
        this.nodeUri = nodeUri;
        this.domainClassLoader = cl;
        this.applicationClassLoader = Thread.currentThread().getContextClassLoader();
        this.isStandalone = LOCAL_DOMAIN_URI.equals(domainUri);
        init();
    }
   
    /**
     * Creates a node connected to a wider domain and allows a classpath to be specified. 
     * To find its place in the domain node and domain identifiers must be provided.
     *
     * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081
     * @param nodeUri - if this is a url it is assumed that this will be used as root url for management components, e.g. http://localhost:8082
     * @param cl - the ClassLoader to use for loading system resources for the node
     * @param applicationCl - the ClassLoader to use for loading application resources for the node
     * @throws ActivationException
     */
    public SCANodeImpl(String domainUri, String nodeUri, ClassLoader cl, ClassLoader applicationCl, String contributionPath, String[] composites)
    throws ActivationException {
        this.domainUri = domainUri;
        this.nodeUri = nodeUri;
        this.domainClassLoader = cl;
        this.applicationClassLoader = applicationCl;       
        this.isStandalone = LOCAL_DOMAIN_URI.equals(domainUri);
        init();
        start();       
       
        try {
            URL contributionURL = SCANodeUtil.findContributionURLFromCompositeNameOrPath(applicationClassLoader, contributionPath, composites);
           
            contributionManager.addContribution(contributionURL);
           
            if (composites.length > 0 ){
                for(int i = 0; i < composites.length; i++) {
                    contributionManager.addComposite(composites[i]);
                    contributionManager.startComposite(composites[i]);
                }
            } else {
                contributionManager.addAllComposites(contributionURL);
                contributionManager.startAllComposites(contributionURL);
            }
            
        } catch(Exception ex) {
            throw new ActivationException(ex);
        }
       
    }   
   
    /**
     * Work out if we are representing a domain in memory or can go out to the network to
     * get domain information. This all depends on whether there is a management
     * composite on the classpath
     */
    private void init()
      throws ActivationException {
        try {
           
            // create a node runtime for the domain contributions to run on
            nodeRuntime = new ReallySmallRuntime(domainClassLoader);
         
            // Check if node has been given a domain name to connect to
            if (isStandalone) {
              logger.log(Level.INFO, "Domain node will be started stand-alone as node and domain URIs are not provided");
              managementRuntime = null;
              scaDomain = null;
            } else {
                // check where domain and node uris are urls, they will be used to configure various
                // endpoints if they are
                URI tmpURI;
                try {
                    tmpURI = new URI(domainUri);
                    if (tmpURI.isAbsolute()){
                        domainUrl = tmpURI.toURL();
                    }
                } catch(Exception ex) {
                    throw new ActivationException("domain uri " +
                                                  domainUri +
                                                  "must be a valid url");
                }
               
                try {
                    tmpURI = new URI(nodeUri);
                    if (tmpURI.isAbsolute()){
                        nodeUrl = tmpURI.toURL();
                    }
                } catch(Exception ex) {
                    nodeUrl = null;
                }

                createManagementNode();
            }
        } catch(ActivationException ex) {
            throw ex;                       
        } catch(Exception ex) {
            throw new ActivationException(ex);
        }
    }
   
    private void createManagementNode()
      throws ActivationException {
        try {
            // create a runtime for components to run on that will be used for talking to the
            // rest of the domain. The components are defined in the node.composite file
            String nodeCompositeName = "node.composite";
            URL contributionURL = SCANodeUtil.findContributionURLFromCompositeNameOrPath(domainClassLoader, null, new String[]{nodeCompositeName} );
           
            if ( contributionURL != null ){
                logger.log(Level.INFO, "Node management configured from " + contributionURL);
               
                // start a local domain in order to talk to the logical domain
                managementRuntime = new EmbeddedSCADomain(domainClassLoader, "node");  
                managementRuntime.start();
           
                // add node composite to the management domain
                ContributionService contributionService = managementRuntime.getContributionService();
                Contribution contribution = null;

              contribution = contributionService.contribute(nodeUri,
                                                            contributionURL,
                                                            false);
               
                if (contribution.getDeployables().size() != 0) {
                    Composite composite = contribution.getDeployables().get(0);
               
                    managementRuntime.getDomainComposite().getIncludes().add(composite);
                    managementRuntime.getCompositeBuilder().build(composite);
                   
                    // deal with the special case of registering the node manager service
                    // in service discovery. It's not on an SCA binding.
                    // TODO - really want to be able to hand out service references but they
                    //        don't serialize out over web services yet.
                    SCANodeUtil.fixUpNodeServiceUrls(managementRuntime.getDomainComposite().getIncludes().get(0).getComponents(), nodeUrl);
                    SCANodeUtil.fixUpNodeReferenceUrls(managementRuntime.getDomainComposite().getIncludes().get(0).getComponents(), domainUrl)
                 
                    managementRuntime.getCompositeActivator().activate(composite);
                    managementRuntime.getCompositeActivator().start(composite);
               
                    // get the management components out of the domain so that they
                    // can be configured/used.
                    scaDomain =  managementRuntime.getService(SCADomainService.class, "SCADomainComponent");
                    domainManager = managementRuntime.getService(DomainManagerService.class, "DomainManagerComponent");
                    nodeManagerInit = managementRuntime.getService(NodeManagerInitService.class, "NodeManagerComponent/NodeManagerInitService");
                   
                    // Now get the uri back out of the component now it has been built and started
                    // TODO - this doesn't pick up the url from external hosting environments
                    String nodeManagerUrl = SCANodeUtil.getNodeManagerServiceUrl(managementRuntime.getDomainComposite().getIncludes().get(0).getComponents());
                   
                    if (nodeManagerUrl != null) {
                        if (isStandalone == false){
                            try {
                               
                                scaDomain.registerServiceEndpoint(domainUri,
                                                                  nodeUri,
                                                                  nodeUri + "NodeManagerService",
                                                                  "",
                                                                  nodeManagerUrl);
                               
                            } catch(Exception ex) {
                                logger.log(Level.SEVERE, 
                                           "Can't connect to domain manager at: " +
                                           domainUrl);
                                throw new ActivationException(ex);
                            }
                        }                       
                    }
                       
                } else {
                    throw new ActivationException("Node management contribution " +
                                                  contributionURL +
                                                  " found but could not be loaded");
                }
            } else {
                throw new ActivationException("Node management contribution " +
                                              nodeCompositeName +
                                              " not found on the classpath");
            }
        } catch(ActivationException ex) {
            throw ex;                       
        } catch(Exception ex) {
            throw new ActivationException(ex);
        }
    }  
   
       
    // methods that implement interfaces
   
    public void start() throws ActivationException {
        // Start the runtime
        nodeRuntime.start();
       
        // Create an in-memory domain level composite
        AssemblyFactory assemblyFactory = nodeRuntime.getAssemblyFactory();
        nodeComposite = assemblyFactory.createComposite();
        nodeComposite.setName(new QName(Constants.SCA10_NS, "domain"));
        nodeComposite.setURI(domainUri);
       
        // add the top level composite into the composite activator
        nodeRuntime.getCompositeActivator().setDomainComposite(nodeComposite)
       
        // make the domain available to the model.
        // TODO - No sure how this should be done properly. As a nod to this though
        //        I have a domain factory which always returns the same domain
        //        object. I.e. this node
        ModelFactoryExtensionPoint factories = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
        NodeFactoryImpl domainFactory = new NodeFactoryImpl(this);
        factories.addFactory(domainFactory);
       
        // create the domain node managers
        componentManager = new ComponentManagerServiceImpl(domainUri, nodeUri, nodeComposite, nodeRuntime);
        contributionManager = new ContributionManagerImpl(domainUri, nodeUri, nodeComposite, nodeRuntime, applicationClassLoader, null);
       
        if (isStandalone == false){
            // pass this object into the node manager
            nodeManagerInit.setNode((SCANode)this);
           
            try {
                // go out and add this node to the wider domain
                domainManager.registerNode(domainUri, nodeUri);
            } catch(Exception ex) {
                logger.log(Level.SEVERE, 
                           "Can't connect to domain manager at: " +
                           domainUrl);
                throw new ActivationException(ex);
            }
        }
    }
   
    @Override
    public void close() {
        try {
            stop();
        } catch (Exception ex) {
            throw new ServiceRuntimeException(ex);
        }
    }

    public void stop() throws ActivationException {
        // stop the components
       
        // remove contributions
       
        // Stop the node
      nodeRuntime.stop();
       
        // Cleanup the top level composite
        nodeComposite = null;
       
        // remove the manager objects
       
        // go out and remove this node from the wider domain
        if (isStandalone == false){
            try {
                domainManager.removeNode(domainUri, nodeUri);
            } catch(Exception ex) {
                logger.log(Level.SEVERE, 
                        "Can't connect to domain manager at: " +
                        domainUrl);
                throw new ActivationException(ex);
            }
        }
    }   
    public String getURI(){
        return domainUri;
    }
   
    public String getDomainURI(){
        return domainUri;
    }
   
    public String getNodeURI(){
        return nodeUri;
   
   
    public URL getDomainURL(){
        return domainUrl;
    }
   
    public URL getNodeURL(){
        return nodeUrl;
    }    
   
    public ComponentManager getComponentManager() {
        return componentManager;
    }
   
    public ContributionManager getContributionManager() {     
        return contributionManager;
    }    
     
   
    /**
     * Return an interface for registering local services and for
     * finding remote services
     *
     * @return The service discovery interface
     */   
    public SCADomainService getDomainService(){
        return scaDomain;
    }
      
    public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
        return (R)nodeRuntime.getProxyFactory().cast(target);
    }

    public <B> B getService(Class<B> businessInterface, String serviceName) {
        ServiceReference<B> serviceReference = getServiceReference(businessInterface, serviceName);
        if (serviceReference == null) {
            throw new ServiceRuntimeException("Service not found: " + serviceName);
        }
        return serviceReference.getService();
    }

    private <B> ServiceReference<B> createServiceReference(Class<B> businessInterface, String targetURI) {
        try {
            AssemblyFactory assemblyFactory = nodeRuntime.getAssemblyFactory();
            Composite composite = assemblyFactory.createComposite();
            composite.setName(new QName(Constants.SCA10_TUSCANY_NS, "default"));
            RuntimeComponent component = (RuntimeComponent)assemblyFactory.createComponent();
            component.setName("default");
            component.setURI("default");
            nodeRuntime.getCompositeActivator().configureComponentContext(component);
            composite.getComponents().add(component);
            RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference();
            reference.setName("default");
            ModelFactoryExtensionPoint factories =
              nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
            JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);
            InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
            interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface));
            reference.setInterfaceContract(interfaceContract);
            component.getReferences().add(reference);
            reference.setComponent(component);
            SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class);
            SCABinding binding = scaBindingFactory.createSCABinding();
            binding.setURI(targetURI);
            reference.getBindings().add(binding);      
            return new ServiceReferenceImpl<B>(businessInterface, component, reference, binding, nodeRuntime
                .getProxyFactory(), nodeRuntime.getCompositeActivator());
        } catch (Exception e) {
            throw new ServiceRuntimeException(e);
        }
    }

    public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) {

        // Extract the component name
        String componentName;
        String serviceName;
        int i = name.indexOf('/');
        if (i != -1) {
            componentName = name.substring(0, i);
            serviceName = name.substring(i + 1);

        } else {
            componentName = name;
            serviceName = null;
        }

        // Lookup the component in the domain
        Component component = componentManager.getComponent(componentName);
        if (component == null) {
            // The component is not local in the partition, try to create a remote service ref
            return createServiceReference(businessInterface, name);
        }
        RuntimeComponentContext componentContext = null;

        // If the component is a composite, then we need to find the
        // non-composite component that provides the requested service
        if (component.getImplementation() instanceof Composite) {
            for (ComponentService componentService : component.getServices()) {
                if (serviceName == null || serviceName.equals(componentService.getName())) {
                    CompositeService compositeService = (CompositeService)componentService.getService();
                    if (compositeService != null) {
                        if (serviceName != null) {
                            serviceName = "$promoted$." + serviceName;
                        }
                        componentContext =
                            ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext();
                        return componentContext.createSelfReference(businessInterface, compositeService
                            .getPromotedService());
                    }
                    break;
                }
            }
            // No matching service is found
            throw new ServiceRuntimeException("Composite service not found: " + name);
        } else {
            componentContext = ((RuntimeComponent)component).getComponentContext();
            if (serviceName != null) {
                return componentContext.createSelfReference(businessInterface, serviceName);
            } else {
                return componentContext.createSelfReference(businessInterface);
            }
        }
    }

}
TOP

Related Classes of org.apache.tuscany.sca.node.impl.SCANodeImpl

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.