summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-1.0/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'branches/sca-java-1.0/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java')
-rw-r--r--branches/sca-java-1.0/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java551
1 files changed, 551 insertions, 0 deletions
diff --git a/branches/sca-java-1.0/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java b/branches/sca-java-1.0/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java
new file mode 100644
index 0000000000..30ab7e3ad2
--- /dev/null
+++ b/branches/sca-java-1.0/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java
@@ -0,0 +1,551 @@
+ /*
+ * 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);
+ }
+ }
+ }
+
+}