summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-1.0.1/modules/node-impl/src
diff options
context:
space:
mode:
Diffstat (limited to 'branches/sca-java-1.0.1/modules/node-impl/src')
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java47
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java111
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/DomainManagerServiceImpl.java166
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeManagerServiceImpl.java148
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java67
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainImpl.java445
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java71
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java378
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java332
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/resources/node.composite64
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/index.html87
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/node.pngbin0 -> 296 bytes
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/style.css176
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddService.java31
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddServiceImpl.java31
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorService.java38
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java74
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideService.java28
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java30
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyService.java28
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java30
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractService.java31
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java31
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCase.java124
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCase.java126
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/Calculator.composite44
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml24
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeB/META-INF/sca-deployables/Calculator.composite45
-rw-r--r--branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeC/Calculator.composite32
29 files changed, 2839 insertions, 0 deletions
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java
new file mode 100644
index 0000000000..5e38c6bb81
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java
@@ -0,0 +1,47 @@
+/*
+ * 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.Serializable;
+
+import org.apache.tuscany.sca.node.ComponentInfo;
+
+public class ComponentInfoImpl implements ComponentInfo, Serializable {
+
+ private String name;
+ private boolean started;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public void setStarted(boolean started) {
+ this.started = started;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java
new file mode 100644
index 0000000000..3e135c7ebf
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java
@@ -0,0 +1,111 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.core.assembly.ActivationException;
+import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl;
+import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime;
+import org.apache.tuscany.sca.node.ComponentListener;
+import org.apache.tuscany.sca.node.ComponentManager;
+
+public class ComponentManagerServiceImpl implements ComponentManager {
+
+ protected List<ComponentListener> listeners = new CopyOnWriteArrayList<ComponentListener>();
+ protected String domainURI;
+ protected String nodeName;
+ protected Composite nodeComposite;
+ protected ReallySmallRuntime nodeRuntime;
+
+ public ComponentManagerServiceImpl(String domainURI, String nodeName, Composite nodeComposite, ReallySmallRuntime nodeRuntime) {
+ this.domainURI = domainURI;
+ this.nodeName = nodeName;
+ this.nodeComposite = nodeComposite;
+ this.nodeRuntime = nodeRuntime;
+ }
+
+ public void addComponentListener(ComponentListener listener) {
+ this.listeners.add(listener);
+ }
+
+ public void removeComponentListener(ComponentListener listener) {
+ this.listeners.remove(listener);
+ }
+
+ public Component getComponent(String componentName) {
+ for (Composite composite: nodeComposite.getIncludes()) {
+ for (Component component: composite.getComponents()) {
+ if (component.getName().equals(componentName)) {
+ return component;
+ }
+ }
+ }
+ return null;
+ }
+
+ public List<Component> getComponents() {
+ List<Component> components = new ArrayList<Component>();
+ for (Composite composite: nodeComposite.getIncludes()) {
+ components.addAll(composite.getComponents());
+ }
+ return components;
+ }
+
+ public void startComponent(Component component) throws ActivationException {
+ nodeRuntime.getCompositeActivator().start(component);
+ notifyComponentStarted(component);
+ }
+
+ public void stopComponent(Component component) throws ActivationException {
+ nodeRuntime.getCompositeActivator().stop(component);
+ notifyComponentStopped(component);
+ }
+
+ public void notifyComponentStarted(Component component) {
+ for (ComponentListener listener : listeners) {
+ try {
+ listener.componentStarted(component);
+ } catch (Exception e) {
+ e.printStackTrace(); // TODO: log
+ }
+ }
+ }
+
+ public void notifyComponentStopped(Component component) {
+ for (ComponentListener listener : listeners) {
+ try {
+ listener.componentStopped(component);
+ } catch (Exception e) {
+ e.printStackTrace(); // TODO: log
+ }
+ }
+ }
+
+ public boolean isComponentStarted(Component component) {
+ RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)component;
+ return runtimeComponent.isStarted();
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/DomainManagerServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/DomainManagerServiceImpl.java
new file mode 100644
index 0000000000..1363af724f
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/DomainManagerServiceImpl.java
@@ -0,0 +1,166 @@
+/*
+ * 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.lang.reflect.UndeclaredThrowableException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.domain.DomainManagerNodeEventService;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Scope;
+
+
+/**
+ * Stores details of services exposed and retrieves details of remote services
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+@Scope("COMPOSITE")
+public class DomainManagerServiceImpl implements DomainManagerNodeEventService{
+
+ private final static Logger logger = Logger.getLogger(DomainManagerServiceImpl.class.getName());
+
+ @Property
+ protected int retryCount = 100;
+
+ @Property
+ protected int retryInterval = 5000; //ms
+
+ @Reference
+ protected DomainManagerNodeEventService domainManager;
+
+ public String registerNode(String nodeURI, String nodeURL) {
+
+ String returnValue = null;
+
+ for (int i =0; i < retryCount; i++){
+ try {
+ returnValue = domainManager.registerNode(nodeURI, nodeURL);
+ break;
+ } catch(UndeclaredThrowableException ex) {
+ logger.log(Level.INFO, "Trying to regsiter node " +
+ nodeURI +
+ " at endpoint " +
+ nodeURL);
+
+ }
+
+ try {
+ Thread.sleep(retryInterval);
+ } catch(InterruptedException ex) {
+ }
+ }
+
+ return returnValue;
+ }
+
+ public String removeNode(String nodeURI) {
+ return domainManager.removeNode(nodeURI);
+ }
+
+ public void registerContribution(String nodeURI, String contributionURI, String contributionURL){
+ domainManager.registerContribution(nodeURI, contributionURI, contributionURL);
+ }
+
+ public void unregisterContribution(String contributionURI){
+ domainManager.unregisterContribution(contributionURI);
+ }
+
+
+ public String registerServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName, String URL){
+
+ String dummy = null;
+
+ for (int i =0; i < retryCount; i++){
+ try {
+ dummy = domainManager.registerServiceEndpoint(domainUri, nodeUri, serviceName, bindingName, URL);
+ break;
+ } catch(UndeclaredThrowableException ex) {
+ logger.log(Level.INFO, "Trying to connect to domain " +
+ domainUri +
+ " to register service " +
+ serviceName);
+
+ }
+
+ try {
+ Thread.sleep(retryInterval);
+ } catch(InterruptedException ex) {
+ }
+ }
+
+ return dummy;
+ }
+
+ public String removeServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName){
+
+ String dummy = null;
+
+ for (int i =0; i < retryCount; i++){
+ try {
+ dummy = domainManager.removeServiceEndpoint(domainUri, nodeUri, serviceName, bindingName);
+ break;
+ } catch(UndeclaredThrowableException ex) {
+ logger.log(Level.INFO, "Trying to connect to domain " +
+ domainUri +
+ " to remove service " +
+ serviceName);
+
+ }
+
+ try {
+ Thread.sleep(retryInterval);
+ } catch(InterruptedException ex) {
+ }
+ }
+
+ return dummy;
+ }
+
+ public String findServiceEndpoint(String domainUri, String serviceName, String bindingName){
+
+
+ String url = null;
+
+ for (int i =0; i < retryCount; i++){
+ try {
+ url = domainManager.findServiceEndpoint(domainUri, serviceName, bindingName);
+ break;
+ } catch(UndeclaredThrowableException ex) {
+ logger.log(Level.INFO, "Trying to connect to domain " +
+ domainUri +
+ " to find service " +
+ serviceName);
+
+ }
+
+ try {
+ Thread.sleep(retryInterval);
+ } catch(InterruptedException ex) {
+ }
+ }
+
+ return url;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeManagerServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeManagerServiceImpl.java
new file mode 100644
index 0000000000..64b58da5d7
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeManagerServiceImpl.java
@@ -0,0 +1,148 @@
+/*
+ * 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.net.URL;
+import java.util.ArrayList;
+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.Component;
+import org.apache.tuscany.sca.core.assembly.ActivationException;
+import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl;
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.node.ComponentInfo;
+import org.apache.tuscany.sca.node.ComponentManagerService;
+import org.apache.tuscany.sca.node.NodeManagerInitService;
+import org.apache.tuscany.sca.node.NodeManagerService;
+import org.apache.tuscany.sca.node.SCANode;
+import org.osoa.sca.annotations.Scope;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * Manages a node implementation
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-11 18:45:36 +0100 (Tue, 11 Sep 2007) $
+ */
+@Scope("COMPOSITE")
+@Service(interfaces = {NodeManagerService.class, NodeManagerInitService.class, ComponentManagerService.class})
+public class NodeManagerServiceImpl implements NodeManagerService, NodeManagerInitService, ComponentManagerService {
+
+ private final static Logger logger = Logger.getLogger(NodeManagerServiceImpl.class.getName());
+
+ private SCANodeImpl node;
+
+
+ // NodeManagerInitService
+
+ public void setNode(SCANode node) {
+ this.node = (SCANodeImpl)node;
+ }
+
+ // NodeManagerSerivice
+
+ /**
+ * Returns the URI of the SCA node. That URI is the endpoint of the
+ * SCA node administration service.
+ *
+ * @return the URI of the SCA node
+ */
+ public String getURI(){
+ return node.getURI();
+ }
+
+ /**
+ * Add an SCA contribution into the node.
+ *
+ * @param uri the URI of the contribution
+ * @param url the URL of the contribution
+ */
+ public void addContribution(String contributionURI, String contributionURL){
+ try {
+ node.addContribution(contributionURI, new URL(contributionURL));
+ } catch (Exception ex){
+ // TODO - sort out exceptions passing across binding.sca
+ logger.log(Level.SEVERE, ex.toString());
+ }
+ }
+
+ /**
+ * deploy deployable composite on the node.
+ *
+ * @param composite
+ */
+ public void deployComposite(String compositeName) {
+ try {
+ node.deployComposite(QName.valueOf(compositeName));
+ } catch (Exception ex){
+ // TODO - sort out exceptions passing across binding.sca
+ logger.log(Level.SEVERE, ex.toString());
+ }
+ }
+
+ /**
+ * Start the SCA node service.
+ */
+ public void start(){
+ try {
+ node.start();
+ } catch (Exception ex){
+ // TODO - sort out exceptions passing across binding.sca
+ logger.log(Level.SEVERE, ex.toString());
+ }
+ }
+
+ /**
+ * Stop the SCA node service.
+ */
+ public void stop(){
+ try {
+ node.stop();
+ } catch (Exception ex){
+ // TODO - sort out exceptions passing across binding.sca
+ logger.log(Level.SEVERE, ex.toString());
+ }
+ }
+
+ // ComponentManagerService
+
+ public List<ComponentInfo> getComponentInfos() {
+ List<ComponentInfo> componentInfos = new ArrayList<ComponentInfo>();
+ for (Component component : node.getComponents()) {
+ ComponentInfo componentInfo = new ComponentInfoImpl();
+ componentInfo.setName(component.getName());
+ componentInfo.setStarted(((RuntimeComponentImpl)component).isStarted());
+ componentInfos.add(componentInfo);
+ }
+ return componentInfos;
+ }
+
+ public ComponentInfo getComponentInfo(String componentName) {
+ Component component = node.getComponent(componentName);
+ ComponentInfo componentInfo = new ComponentInfoImpl();
+ componentInfo.setName(component.getName());
+ componentInfo.setStarted(((RuntimeComponentImpl)component).isStarted());
+ return componentInfo;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java
new file mode 100644
index 0000000000..c8842100a0
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.util.HashMap;
+
+import org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.SCADomainFinder;
+
+/**
+ * A finder for SCA domains.
+ *
+ * @version $Rev: 580520 $ $Date: 2007-09-29 00:50:25 +0100 (Sat, 29 Sep 2007) $
+ */
+public class SCADomainFinderImpl extends SCADomainFinder {
+
+ private static HashMap<String, SCADomain> domains = new HashMap<String, SCADomain>();
+
+ /**
+ * Returns a new SCA domain finder instance.
+ *
+ * @return a new SCA domain finder
+ */
+ public SCADomainFinderImpl() {
+
+ }
+
+ /**
+ * Finds an existing SCA domain.
+ *
+ * @param domainURI the URI of the domain, this is the endpoint
+ * URI of the domain administration service
+ * @return the SCA domain
+ */
+ public SCADomain getSCADomain(String domainURI) throws DomainException {
+ SCADomain scaDomain = domains.get(domainURI);
+
+ if (scaDomain == null) {
+ scaDomain = new SCADomainImpl(domainURI);
+ //domains.put(domainURI, scaDomain);
+ // TODO - not caching local domains as currently the local domain can
+ // - only handle one node
+ // - provides the management endpoint for that node
+ }
+ return scaDomain;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainImpl.java
new file mode 100644
index 0000000000..5e9a8c0407
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainImpl.java
@@ -0,0 +1,445 @@
+ /*
+ * 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.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.Component;
+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.DeployedArtifact;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+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.domain.DomainException;
+import org.apache.tuscany.sca.domain.DomainManagerNodeEventService;
+import org.apache.tuscany.sca.domain.model.Domain;
+import org.apache.tuscany.sca.host.embedded.impl.EmbeddedSCADomain;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.node.NodeManagerInitService;
+import org.apache.tuscany.sca.node.SCADomainProxySPI;
+import org.apache.tuscany.sca.node.SCANode;
+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 SCADomainImpl implements SCADomainProxySPI {
+
+ private final static Logger logger = Logger.getLogger(SCADomainImpl.class.getName());
+
+ // the domain used to talk to the rest of the domain
+ private EmbeddedSCADomain domainManagementRuntime;
+
+ // class loader used to get the runtime going
+ private ClassLoader domainClassLoader;
+
+ // representation of the private state of the node that the domain is running on
+ private String domainURI;
+ private URL domainURL;
+
+ // proxy to the domain
+ private DomainManagerNodeEventService domainManager;
+
+ // proxy to the node manager
+ private NodeManagerInitService nodeManagerInit;
+ private String nodeManagerUrl;
+
+ // the local node implementation
+ private SCANodeImpl nodeImpl;
+
+ // methods defined on the implementation only
+
+ /**
+ * Creates a domain proxy connected to a wider domain.
+ *
+ * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081
+ * @throws ActivationException
+ */
+ public SCADomainImpl(String domainURI) throws DomainException {
+ this.domainURI = domainURI;
+ this.domainClassLoader = SCADomainImpl.class.getClassLoader();
+ init();
+ }
+
+ /**
+ * Start the composite that connects to the domain manager
+ */
+ private void init()
+ throws DomainException {
+ try {
+ // 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() == true){
+ domainURL = tmpURI.toURL();
+ }
+ } catch(Exception ex) {
+ domainURL = null;
+ }
+
+ // Check if node has been given a valid domain name to connect to
+ if (domainURL == null) {
+ logger.log(Level.INFO, "Domain will be started stand-alone as domain URL is not provided");
+ } else {
+ // load the composite that allows this domain representation to
+ // connect to the rest of the domain
+ String domainCompositeName = "node.composite";
+ URL contributionURL = SCANodeUtil.findContributionURLFromCompositeNameOrPath(domainClassLoader, null, new String[]{domainCompositeName} );
+
+ if ( contributionURL != null ){
+ logger.log(Level.INFO, "Domain management configured from " + contributionURL);
+
+ // start a local domain in order to talk to the logical domain
+ domainManagementRuntime = new EmbeddedSCADomain(domainClassLoader, domainURI);
+ domainManagementRuntime.start();
+
+ // add node composite to the management domain
+ ContributionService contributionService = domainManagementRuntime.getContributionService();
+ Contribution contribution = null;
+
+ contribution = contributionService.contribute(domainURI,
+ contributionURL,
+ false);
+
+ Composite composite = null;
+ for (DeployedArtifact artifact: contribution.getArtifacts()) {
+ if (domainCompositeName.equals(artifact.getURI())) {
+ composite = (Composite)artifact.getModel();
+ }
+ }
+
+ if (composite != null) {
+
+ domainManagementRuntime.getDomainComposite().getIncludes().add(composite);
+ domainManagementRuntime.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(domainManagementRuntime.getDomainComposite().getIncludes().get(0).getComponents(), null);
+ SCANodeUtil.fixUpNodeReferenceUrls(domainManagementRuntime.getDomainComposite().getIncludes().get(0).getComponents(), domainURL);
+
+ domainManagementRuntime.getCompositeActivator().activate(composite);
+ domainManagementRuntime.getCompositeActivator().start(composite);
+
+ // get the management components out of the domain so that they
+ // can be configured/used.
+ domainManager = domainManagementRuntime.getService(DomainManagerNodeEventService.class, "DomainManagerComponent");
+ nodeManagerInit = domainManagementRuntime.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
+ nodeManagerUrl = SCANodeUtil.getNodeManagerServiceUrl(domainManagementRuntime.getDomainComposite().getIncludes().get(0).getComponents());
+
+ } else {
+ throw new ActivationException("Domain management contribution " +
+ contributionURL +
+ " found but could not be loaded");
+ }
+ } else {
+ throw new ActivationException("Doamin management contribution " +
+ domainCompositeName +
+ " not found on the classpath");
+ }
+ }
+ } catch(Exception ex) {
+ throw new DomainException(ex);
+ }
+ }
+
+ // SPI methods
+
+ public String addNode(String nodeURI, String nodeURL){
+ // Does nothing in the proxy
+ return null;
+ }
+
+ public String removeNode(String nodeURI){
+ // Does nothing in the proxy
+ return null;
+ }
+
+ public void addNode(SCANode nodeImpl) throws DomainException {
+ this.nodeImpl = (SCANodeImpl)nodeImpl;
+
+ // register node with wider domain
+ if (domainURL != null){
+ // pass this object into the node manager service
+ nodeManagerInit.setNode(nodeImpl);
+
+ try {
+ // go out and add this node to the wider domain
+ domainManager.registerNode(nodeImpl.getURI(),nodeManagerUrl);
+
+ } catch(Exception ex) {
+ logger.log(Level.SEVERE,
+ "Can't connect to domain manager at: " +
+ domainURL);
+ throw new DomainException(ex);
+ }
+ }
+ }
+
+ public void removeNode(SCANode nodeImpl) throws DomainException {
+
+ if (domainURL != null){
+ // remove the node from node manager service
+ //nodeManagerInit.removeNode(nodeImpl);
+
+ try {
+ // go out and add this node to the wider domain
+ domainManager.removeNode(nodeImpl.getURI());
+ } catch(Exception ex) {
+ logger.log(Level.SEVERE,
+ "Can't connect to domain manager at: " +
+ domainURL);
+ throw new DomainException(ex);
+ }
+ }
+
+ this.nodeImpl = null;
+ }
+
+ public void registerContribution(String nodeURI, String contributionURI, String contributionURL){
+ domainManager.registerContribution(nodeURI, contributionURI, contributionURL);
+ }
+
+ public void unregisterContribution(String contributionURI){
+ domainManager.unregisterContribution(contributionURI);
+ }
+
+
+ public String registerServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName, String URL){
+ return domainManager.registerServiceEndpoint(domainUri, nodeUri, serviceName, bindingName, URL);
+ }
+
+ public String removeServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName){
+ return domainManager.removeServiceEndpoint(domainUri, nodeUri, serviceName, bindingName);
+ }
+
+ public String findServiceEndpoint(String domainUri, String serviceName, String bindingName){
+ return domainManager.findServiceEndpoint(domainUri, serviceName, bindingName);
+ }
+
+ public Domain getDomainModel(){
+ return null;
+ }
+
+
+ // API methods
+
+ public void start() throws DomainException {
+ // TODO - what happens here?
+ }
+
+ public void stop() throws DomainException {
+ try {
+ // Stop the domain
+ domainManagementRuntime.stop();
+ } catch (Exception ex) {
+ throw new DomainException(ex);
+ }
+
+ }
+
+ public String getURI(){
+ return domainURI;
+ }
+
+ public void addContribution(String contributionURI, URL contributionURL) throws DomainException {
+ try {
+ nodeImpl.addContribution(contributionURI, contributionURL);
+ } catch(Exception ex) {
+ new DomainException(ex);
+ }
+ }
+
+ public void removeContribution(String uri) throws DomainException {
+ try {
+ //nodeImpl.removeContributions();
+ } catch(Exception ex) {
+ new DomainException(ex);
+ }
+ }
+
+ public void addDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ // TODO
+ }
+
+ public void addToDomainLevelComposite(QName qname) throws DomainException {
+ try {
+ nodeImpl.deployComposite(qname);
+ } catch(Exception ex) {
+ new DomainException(ex);
+ }
+ }
+
+ public void removeFromDomainLevelComposite(QName qname) throws DomainException {
+ try {
+ //nodeImpl.stopComposite();
+ } catch(Exception ex) {
+ new DomainException(ex);
+ }
+ }
+
+ public void startComposite(QName qname) throws DomainException {
+ try {
+ nodeImpl.deployComposite(qname);
+ } catch(Exception ex) {
+ new DomainException(ex);
+ }
+ }
+
+ public void stopComposite(QName qname) throws DomainException {
+ try {
+ //nodeImpl.stopComposite();
+ } catch(Exception ex) {
+ new DomainException(ex);
+ }
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ return (R)nodeImpl.getNodeRuntime().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 = nodeImpl.getNodeRuntime().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");
+ nodeImpl.getNodeRuntime().getCompositeActivator().configureComponentContext(component);
+ composite.getComponents().add(component);
+ RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference();
+ reference.setName("default");
+ ModelFactoryExtensionPoint factories =
+ nodeImpl.getNodeRuntime().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, nodeImpl.getNodeRuntime()
+ .getProxyFactory(), nodeImpl.getNodeRuntime().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 = null;
+
+ if (nodeImpl != null) {
+ component = nodeImpl.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);
+ }
+ }
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java
new file mode 100644
index 0000000000..adc15b7404
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java
@@ -0,0 +1,71 @@
+/*
+ * 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 org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.SCANode;
+import org.apache.tuscany.sca.node.SCANodeFactory;
+
+/**
+ * A finder for SCA domains.
+ *
+ * @version $Rev: 580520 $ $Date: 2007-09-29 00:50:25 +0100 (Sat, 29 Sep 2007) $
+ */
+public class SCANodeFactoryImpl extends SCANodeFactory {
+
+
+ /**
+ * Returns a new SCA domain finder instance.
+ *
+ * @return a new SCA domain finder
+ */
+ public SCANodeFactoryImpl() {
+
+ }
+
+ /**
+ * Finds an existing SCA domain.
+ *
+ * @param domainURI the URI of the domain, this is the endpoint
+ * URI of the domain administration service
+ * @return the SCA domain
+ */
+ public SCANode createSCANode(String nodeURI, String domainURI) throws NodeException {
+ return new SCANodeImpl(nodeURI, domainURI, null);
+ }
+
+ /**
+ * Creates a new SCA node as part of a node group. Groups of nodes are used in load balancing
+ * and failover scenarios where each node in the group runs the same contribution and
+ * active composites
+ *
+ * @param nodeURI the URI of the node, this is the endpoint URI of the
+ * node administration service
+ * @param domainURI the URI of the domain that the node belongs to
+ * @param nodeGroupURI the uri of the node group. This is the enpoint URI of the head of the
+ * group of nodes. For example, in load balancing scenarios this will be the loaded balancer itself
+ * @return a new SCA node.
+ */
+ public SCANode createSCANode(String nodeURI, String domainURI, String nodeGroupURI) throws NodeException {
+ return new SCANodeImpl(nodeURI, domainURI, nodeGroupURI);
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java
new file mode 100644
index 0000000000..de33e8db1f
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java
@@ -0,0 +1,378 @@
+ /*
+ * 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.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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.Component;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.xml.Constants;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.DeployedArtifact;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.impl.ModelResolverImpl;
+import org.apache.tuscany.sca.contribution.service.ContributionService;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.assembly.ActivationException;
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.NodeFactoryImpl;
+import org.apache.tuscany.sca.node.SCADomainFinder;
+import org.apache.tuscany.sca.node.SCANode;
+
+/**
+ * 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 implements SCANode {
+
+ private final static Logger logger = Logger.getLogger(SCANodeImpl.class.getName());
+
+ // class loader used to get application resources
+ private ClassLoader nodeClassLoader;
+
+ // identity and endpoints for the node and the domain it belongs to
+ private String nodeURI;
+ private URL nodeURL;
+ private String domainURI;
+ private URL domainURL;
+ private String nodeGroupURI;
+
+ // The tuscany runtime that does the hard work
+ private ReallySmallRuntime nodeRuntime;
+
+ // the top level components in this node. A subset of the the domain level composite
+ private Composite nodeComposite;
+
+ // the domain that the node belongs to. This object acts as a proxy to the domain
+ private SCADomain scaDomain;
+
+ // collection for managing contributions that have been added to the node
+ private Map<String, Contribution> contributions = new HashMap<String, Contribution>();
+ private Map<QName, Composite> composites = new HashMap<QName, Composite>();
+ private List<QName> compositesToStart = new ArrayList<QName>();
+
+ // methods defined on the implementation only
+
+ /**
+ * 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
+ * @param nodeGroupURI the uri of the node group. This is the enpoint URI of the head of the
+ * group of nodes. For example, in load balancing scenarios this will be the loaded balancer itself
+ * @throws ActivationException
+ */
+ public SCANodeImpl(String nodeURI, String domainURI, String nodeGroupURI) throws NodeException {
+ this.domainURI = domainURI;
+ this.nodeURI = nodeURI;
+ this.nodeGroupURI = nodeGroupURI;
+ this.nodeClassLoader = Thread.currentThread().getContextClassLoader();
+ 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 nodeGroupURI the uri of the node group. This is the enpoint URI of the head of the
+ * group of nodes. For example, in load balancing scenarios this will be the loaded balancer itself
+ * @param cl - the ClassLoader to use for loading system resources for the node
+ * @throws ActivationException
+ */
+ public SCANodeImpl(String nodeURI, String domainURI, String nodeGroupURI, ClassLoader cl) throws NodeException {
+ this.domainURI = domainURI;
+ this.nodeURI = nodeURI;
+ this.nodeGroupURI = nodeGroupURI;
+ this.nodeClassLoader = cl;
+ init();
+ }
+
+ /**
+ * 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 NodeException {
+ try {
+
+ // create a node runtime for the domain contributions to run on
+ nodeRuntime = new ReallySmallRuntime(nodeClassLoader);
+
+ // 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, "node"));
+ nodeComposite.setURI(nodeURI);
+
+ // add the top level composite into the composite activator
+ nodeRuntime.getCompositeActivator().setDomainComposite(nodeComposite);
+
+ // check whether node uri is an absolute url,
+ try {
+ URI tmpURI = new URI(nodeURI);
+ if (tmpURI.isAbsolute()){
+ nodeURL = tmpURI.toURL();
+ }
+ } catch(Exception ex) {
+ nodeURL = null;
+ }
+
+ // create a link to the domain
+ scaDomain = SCADomainFinder.newInstance().getSCADomain(domainURI);
+
+ // add the node to the domain
+ ((SCADomainImpl)scaDomain).addNode(this);
+
+ // If a non-null domain name is provided make the node available to the model
+ // this causes the runtime to start registering binding-sca service endpoints
+ // with the domain so only makes sense if we know we have a domain to talk to
+ if (domainURI != null) {
+ ModelFactoryExtensionPoint factories = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
+ NodeFactoryImpl nodeFactory = new NodeFactoryImpl(this);
+ factories.addFactory(nodeFactory);
+ }
+
+ } catch(Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ // temp methods to help integrate with existing code
+
+ public ReallySmallRuntime getNodeRuntime() {
+ return nodeRuntime;
+ }
+
+ public Component getComponent(String componentName) {
+ for (Composite composite: nodeComposite.getIncludes()) {
+ for (Component component: composite.getComponents()) {
+ if (component.getName().equals(componentName)) {
+ return component;
+ }
+ }
+ }
+ return null;
+ }
+
+ public List<Component> getComponents() {
+ List<Component> components = new ArrayList<Component>();
+ for (Composite composite: nodeComposite.getIncludes()) {
+ components.addAll(composite.getComponents());
+ }
+ return components;
+ }
+
+ /**
+ * Stating to think about how a node advertises what it can do.
+ * Maybe need to turn this round and ask the node to decide whether it
+ * can process a list of artifacts
+ * @return
+ */
+ public List<String> getFeatures() {
+ List<String> featureList = new ArrayList<String>();
+
+ ExtensionPointRegistry registry = nodeRuntime.getExtensionPointRegistry();
+
+ // TODO - how to get registered features?
+ ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class);
+
+ return null;
+ }
+
+
+ // API methods
+
+ public void start() throws NodeException {
+ startComposites();
+ }
+
+ public void stop() throws NodeException {
+ try {
+ // remove contributions
+ removeAllContributions();
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ public String getURI(){
+ return nodeURI;
+ }
+
+ public SCADomain getDomain(){
+ return scaDomain;
+ }
+
+ public void addContribution(String contributionURI, URL contributionURL) throws NodeException {
+ addContribution(contributionURI, contributionURL, null);
+ }
+
+ public void addContribution(String contributionURI, URL contributionURL, ClassLoader contributionClassLoader ) throws NodeException {
+ try {
+ if (contributionURL != null) {
+ ModelResolver modelResolver = null;
+
+ // if the contribution is to be resolved using a separate class loader
+ // then create a new model resolver
+ if (contributionClassLoader != null) {
+ modelResolver = new ModelResolverImpl(contributionClassLoader);
+ }
+
+ // Add the contribution to the node
+ ContributionService contributionService = nodeRuntime.getContributionService();
+ Contribution contribution = contributionService.contribute(contributionURI,
+ contributionURL,
+ modelResolver,
+ false);
+
+ // remember the contribution
+ contributions.put(contributionURI, contribution);
+
+ // remember all the composites that have been found
+ for (DeployedArtifact artifact : contribution.getArtifacts()) {
+ if (artifact.getModel() instanceof Composite) {
+ Composite composite = (Composite)artifact.getModel();
+ composites.put(composite.getName(), composite);
+ }
+ }
+
+ // remember all the deployable composites ready to be started
+ for (Composite composite : contribution.getDeployables()) {
+ compositesToStart.add(composite.getName());
+ }
+
+
+ // add the contribution to the domain. It will generally already be there
+ // unless the contribution has been added to the node itself.
+ ((SCADomainImpl)scaDomain).registerContribution(nodeURI, contributionURI, contributionURL.toExternalForm());
+
+ } else {
+ throw new ActivationException("Contribution " + contributionURL + " not found");
+ }
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ private void removeAllContributions() throws NodeException {
+ try {
+ // stop any running composites
+ stopComposites();
+
+ // Remove all contributions
+ for (String contributionURI : contributions.keySet()){
+ nodeRuntime.getContributionService().remove(contributionURI);
+ contributions.remove(contributionURI);
+ }
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ public void deployComposite(QName compositeName) throws NodeException {
+ // if the named composite is not already in the list then
+ // add it
+ if (compositesToStart.indexOf(compositeName) == -1 ){
+ compositesToStart.add(compositeName);
+ }
+ }
+
+ private void startComposites() throws NodeException {
+ try {
+ if (compositesToStart.size() == 0 ){
+ logger.log(Level.INFO, nodeURI +
+ " has no composites to start" );
+ } else {
+ for (QName compositeName : compositesToStart) {
+ Composite composite = composites.get(compositeName);
+
+ if (composite == null) {
+ logger.log(Level.INFO, "Composite not found during start: " + compositeName);
+ } else {
+ logger.log(Level.INFO, "Starting composite: " + compositeName);
+
+ // Add the composite to the top level domain
+ nodeComposite.getIncludes().add(composite);
+ nodeRuntime.getCompositeBuilder().build(composite);
+
+ // activate the composite
+ nodeRuntime.getCompositeActivator().activate(composite);
+
+ //start the composite
+ nodeRuntime.getCompositeActivator().start(composite);
+ }
+ }
+ }
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ private void stopComposites() throws NodeException {
+
+ try {
+ if (compositesToStart.size() == 0 ){
+ throw new NodeException("Stopping node " +
+ nodeURI +
+ " with no composite started");
+ }
+ for (QName compositeName : compositesToStart) {
+ logger.log(Level.INFO, "Stopping composite: " + compositeName);
+
+ Composite composite = composites.get(compositeName);
+
+ nodeRuntime.getCompositeActivator().stop(composite);
+ nodeRuntime.getCompositeActivator().deactivate(composite);
+
+ composites.remove(compositeName);
+ }
+
+ compositesToStart.clear();
+ } catch (NodeException ex) {
+ throw ex;
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java
new file mode 100644
index 0000000000..e01df1e32b
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java
@@ -0,0 +1,332 @@
+/*
+ * 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.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.logging.Logger;
+
+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.SCABinding;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.service.util.FileHelper;
+import org.apache.tuscany.sca.core.assembly.ActivationException;
+
+
+/**
+ * Some utility methods for the Node implementation
+ *
+ * @version $Rev: 556897 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class SCANodeUtil {
+ private final static Logger logger = Logger.getLogger(SCANodeUtil.class.getName());
+
+ /**
+ * Given a contribution path an array of composite names or neither this method finds
+ * a suitable contribution to load
+ *
+ * @param classLoader
+ * @param compositePath
+ * @param composites
+ * @return the contribution URL
+ * @throws MalformedURLException
+ */
+
+ public static URL findContributionURLFromCompositeNameOrPath(ClassLoader classLoader, String contributionPath, String[] composites)
+ throws MalformedURLException {
+
+ String contributionArtifactPath = null;
+ URL contributionArtifactURL = null;
+
+
+ if (contributionPath != null && contributionPath.length() > 0) {
+
+ //encode spaces as they would cause URISyntaxException
+ contributionPath = contributionPath.replace(" ", "%20");
+ URI contributionURI = URI.create(contributionPath);
+ if (contributionURI.isAbsolute() || composites.length == 0) {
+ return new URL(contributionPath);
+ } else {
+ // contributionArtifactURL = classLoader.getResource(contributionPath);
+ // if (contributionArtifactURL == null) {
+ // throw new IllegalArgumentException("Composite not found: " + contributionArtifactPath);
+ // }
+ }
+ }
+
+ if ( contributionArtifactURL == null){
+ if (composites != null && composites.length > 0 && composites[0].length() > 0) {
+
+ // Here the SCADomain was started with a reference to a composite file
+ contributionArtifactPath = composites[0];
+ contributionArtifactURL = classLoader.getResource(contributionArtifactPath);
+ if (contributionArtifactURL == null) {
+ throw new IllegalArgumentException("Composite not found: " + contributionArtifactPath);
+ }
+ } else {
+
+ // Here the SCANode was started without any reference to a composite file
+ // We are going to look for an sca-contribution.xml or sca-contribution-generated.xml
+
+ // Look for META-INF/sca-contribution.xml
+ contributionArtifactPath = Contribution.SCA_CONTRIBUTION_META;
+ contributionArtifactURL = classLoader.getResource(contributionArtifactPath);
+
+ // Look for META-INF/sca-contribution-generated.xml
+ if (contributionArtifactURL == null) {
+ contributionArtifactPath = Contribution.SCA_CONTRIBUTION_GENERATED_META;
+ contributionArtifactURL = classLoader.getResource(contributionArtifactPath);
+ }
+
+ // Look for META-INF/sca-deployables directory
+ if (contributionArtifactURL == null) {
+ contributionArtifactPath = Contribution.SCA_CONTRIBUTION_DEPLOYABLES;
+ contributionArtifactURL = classLoader.getResource(contributionArtifactPath);
+ }
+ }
+ }
+
+ if (contributionArtifactURL == null) {
+ throw new IllegalArgumentException("Can't determine contribution deployables. Either specify a composite file, or use an sca-contribution.xml file to specify the deployables.");
+ }
+
+ URL contributionURL = null;
+ // "jar:file://....../something.jar!/a/b/c/app.composite"
+ try {
+ String url = contributionArtifactURL.toExternalForm();
+ String protocol = contributionArtifactURL.getProtocol();
+ if ("file".equals(protocol)) {
+ // directory contribution
+ if (url.endsWith(contributionArtifactPath)) {
+ String location = url.substring(0, url.lastIndexOf(contributionArtifactPath));
+ // workaround from evil url/uri form maven
+ contributionURL = FileHelper.toFile(new URL(location)).toURI().toURL();
+ }
+
+ } else if ("jar".equals(protocol)) {
+ // jar contribution
+ String location = url.substring(4, url.lastIndexOf("!/"));
+ // workaround for evil url/uri from maven
+ contributionURL = FileHelper.toFile(new URL(location)).toURI().toURL();
+ }
+ } catch (MalformedURLException mfe) {
+ throw new IllegalArgumentException(mfe);
+ }
+
+ return contributionURL;
+ }
+
+ /**
+ * A rather ugly method to find and fix the url of the service, assuming that there
+ * is one.
+ *
+ * we can't get this out of a service reference
+ * the component itself doesn't know how to get it
+ * the binding can't to do it automatically as it's not the sca binding
+ *
+ * TODO - This would be better done by passing out a serializable reference to service discovery
+ * but this doesn't work yet
+ *
+ * @return node manager url
+ */
+ public static void fixUpNodeServiceUrls(List<Component> nodeComponents, URL nodeUrlString)
+ throws MalformedURLException, UnknownHostException {
+
+ for(Component component : nodeComponents){
+ for (ComponentService service : component.getServices() ){
+ for (Binding binding : service.getBindings() ) {
+ fixUpNodeServiceBindingUrl(binding, nodeUrlString);
+ }
+ }
+ }
+ }
+
+ /**
+ * Find and return the URL of the NodeManagerService
+ *
+ * @param nodeComponents
+ * @return
+ */
+ public static String getNodeManagerServiceUrl(List<Component> nodeComponents){
+ String nodeManagerUrl = null;
+
+ for(Component component : nodeComponents){
+ for (ComponentService service : component.getServices() ){
+
+ if ( service.getName().equals("NodeManagerService")) {
+ nodeManagerUrl = service.getBindings().get(0).getURI();
+ }
+ }
+ }
+
+ return nodeManagerUrl;
+ }
+
+ /**
+ * For node management services that use the http(s) protocol then use the node url as the enpoint
+ * if it has been specified otherwise find a port that isn't in use and make sure the domain name
+ * is the real domain name
+ *
+ * @param binding
+ * @param nodeURL the URL provided as the identifier of the node
+ */
+ public static void fixUpNodeServiceBindingUrl(Binding binding, URL manualUrl)
+ throws MalformedURLException, UnknownHostException{
+
+ String urlString = binding.getURI();
+
+ // only going to fiddle with bindings that use HTTP protocol
+ if( (urlString == null) ||
+ ((urlString.startsWith("http") != true ) &&
+ (urlString.startsWith("https") != true )) ||
+ (binding instanceof SCABinding)) {
+ return;
+ }
+
+ URL bindingUrl = new URL(urlString);
+ String originalHost = bindingUrl.getHost();
+ String newHost = null;
+ int originalPort = bindingUrl.getPort();
+ int newPort = 0;
+
+ if (manualUrl != null) {
+ // the required url has been specified manually
+ newHost = manualUrl.getHost();
+ newPort = manualUrl.getPort();
+
+ if ( newHost.equals("localhost")){
+ newHost = InetAddress.getLocalHost().getHostName();
+ }
+ } else {
+ // discover the host and port information
+ newHost = InetAddress.getLocalHost().getHostName();
+ newPort = findFreePort(originalPort);
+ }
+
+ // replace the old with the new
+ urlString = urlString.replace(String.valueOf(originalPort), String.valueOf(newPort));
+ urlString = urlString.replace(originalHost, newHost);
+
+ // set the address back into the NodeManager binding.
+ binding.setURI(urlString);
+ }
+
+ /**
+ * Find a port on this machine that isn't in use.
+ *
+ * @param startPort
+ * @return
+ */
+ public static int findFreePort(int startPort)
+ {
+ boolean portIsBusy = true;
+ int freePort = startPort;
+
+ do {
+ try {
+ ServerSocket socket = new ServerSocket(freePort);
+ portIsBusy = false;
+ socket.close();
+ break;
+ }
+ catch (IOException ex) {
+ // the port is busy
+ freePort = freePort + 1;
+ }
+ } while (portIsBusy || freePort > 9999);
+
+ return freePort;
+ }
+
+ /**
+ * For node services that have to talk to the domain fix up the reference URL using the
+ * provided domain url if it has been provided
+ *
+ * @param nodeComponents
+ * @param domainUrlString
+ * @throws MalformedURLException
+ * @throws UnknownHostException
+ */
+ public static void fixUpNodeReferenceUrls(List<Component> nodeComponents, URL domainUrl)
+ throws MalformedURLException, UnknownHostException, ActivationException{
+
+ for(Component component : nodeComponents){
+ for (ComponentReference reference : component.getReferences() ){
+ if ( reference.getName().equals("domainManager") ||
+ reference.getName().equals("scaDomainService")) {
+ for (Binding binding : reference.getBindings() ) {
+ fixUpNodeReferenceBindingUrl(binding, domainUrl);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * For node management references to the domain fix up the binding URLs so that they point
+ * to the endpoint described in the domainURL
+ *
+ * @param binding
+ * @param nodeURL the URL provided as the identifier of the node
+ */
+ public static void fixUpNodeReferenceBindingUrl(Binding binding, URL manualUrl)
+ throws MalformedURLException, UnknownHostException, ActivationException{
+
+ String urlString = binding.getURI();
+
+ // only going to fiddle with bindings that use HTTP protocol
+ if( (urlString == null) ||
+ ((urlString.startsWith("http") != true ) &&
+ (urlString.startsWith("https") != true )) ||
+ (binding instanceof SCABinding) ) {
+ return;
+ }
+
+ URL bindingUrl = new URL(urlString);
+ String originalHost = bindingUrl.getHost();
+ String newHost = null;
+ int originalPort = bindingUrl.getPort();
+ int newPort = 0;
+
+ if (manualUrl != null) {
+ // the required url has been specified manually
+ newHost = manualUrl.getHost();
+ newPort = manualUrl.getPort();
+ } else {
+ throw new ActivationException("domain uri can't be null");
+ }
+
+ // replace the old with the new
+ urlString = urlString.replace(String.valueOf(originalPort), String.valueOf(newPort));
+ urlString = urlString.replace(originalHost, newHost);
+
+ // set the address back into the NodeManager binding.
+ binding.setURI(urlString);
+ }
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/node.composite b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/node.composite
new file mode 100644
index 0000000000..63a3269f63
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/node.composite
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+
+
+<!--
+ The components used to interact with a Node. The components her are expect to be here
+ to edit with caution. In particular the service and reference urls are edited at runtime
+ in the in memory model. So don;t rely on the values here.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ targetNamespace="http://management"
+ xmlns:sample="http://management"
+ xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
+ name="Management">
+
+ <component name="DomainManagerComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.impl.DomainManagerServiceImpl"/>
+ <reference name="domainManager">
+ <interface.java interface="org.apache.tuscany.sca.domain.DomainManagerNodeEventService"/>
+ <binding.ws uri="http://localhost:8878/DomainManagerComponent/DomainManagerNodeEventService"/>
+ </reference>
+ </component>
+
+ <component name="NodeManagerComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.impl.NodeManagerServiceImpl"/>
+ <service name="NodeManagerInitService">
+ <interface.java interface="org.apache.tuscany.sca.node.NodeManagerInitService"/>
+ <binding.sca/>
+ </service>
+ <service name="NodeManagerService">
+ <interface.java interface="org.apache.tuscany.sca.node.NodeManagerService"/>
+ <binding.ws uri="http://localhost:8878/NodeManagerComponent/NodeManagerService"/>
+ </service>
+ <service name="ComponentManagerService">
+ <interface.java interface="org.apache.tuscany.sca.node.ComponentManagerService"/>
+ <tuscany:binding.jsonrpc uri="http://localhost:8878/NodeManagerComponent/ComponentManagerJson"/>
+ </service>
+ </component>
+
+ <component name="node">
+ <tuscany:implementation.resource location="webroot"/>
+ <service name="Resource">
+ <tuscany:binding.http uri="http://localhost:8878/node"/>
+ </service>
+ </component>
+
+</composite>
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/index.html b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/index.html
new file mode 100644
index 0000000000..d597fbbc25
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/index.html
@@ -0,0 +1,87 @@
+<html>
+<!--
+ * 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.
+ -->
+<head>
+<title>Apache Tuscany Node</TITLE>
+
+ <script type="text/javascript" src="../SCADomain/scaDomain.js"></script>
+
+ <script language="JavaScript">
+
+ nodeManager = new JSONRpcClient("../NodeManagerComponent/NodeManagerJson");
+ componentManager = new JSONRpcClient("../NodeManagerComponent/ComponentManagerJson");
+
+ function getNodeUri() {
+ nodeManager.NodeManagerService.getNodeUri(handleGetNodeUri);
+ getComponentInfos()
+ }
+
+ function handleGetNodeUri(result) {
+ document.getElementById('nodeUri').innerHTML=result;
+ }
+
+ function getComponentInfos() {
+ componentManager.ComponentManagerService.getComponentInfos(handleGetComponentInfos);
+ }
+
+ function handleGetComponentInfos(result) {
+
+ var text = ""
+
+ for (var i in result.list){
+ var component = result.list[i];
+
+ text = text + "<table>";
+ text = text + "<TR CLASS='source_2' >";
+ text = text + " <TD>" + component.name+ "</TD>";
+ text = text + " <TD>" + component.started+ "</TD>";
+ text = text + "</TR>";
+ text = text + "</table>";
+ }
+
+ document.getElementById('nodeInfo').innerHTML=text;
+ }
+
+
+ </script>
+
+ <link rel="stylesheet" type="text/css" href="style.css" />
+</head>
+
+<body onload="getNodeUri()">
+
+
+<h1 id="top">Apache Tuscany Node</h1>
+<div id="errors"></div>
+
+<p>Node Uri <span id="nodeUri"></span>:</p>
+
+<table>
+<TR>
+<TD>Component Name</TD>
+<TD>Component Is Started</TD>
+</TR>
+</table>
+
+<div id="nodeInfo"></div>
+
+<p /><input type="button" value="Refresh" onclick="getComponentInfos()" />
+
+</body>
+</html>
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/node.png b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/node.png
new file mode 100644
index 0000000000..fa01e64272
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/node.png
Binary files differ
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/style.css b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/style.css
new file mode 100644
index 0000000000..28a4d4540c
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/main/resources/webroot/style.css
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+p,table,li,h1,h2,h3
+{
+font-family: verdana, arial, 'sans serif';
+}
+
+p, h1, h2, h3, table, li, hr
+{
+margin-left: 10pt;
+}
+
+table
+{
+border-color: black;
+border-collapse: separate;
+border-spacing: 0px 1px;
+
+margin-right: 10pt;
+margin-left: 10pt;
+width: 800px;
+}
+
+.sourceDetailsTable
+{
+width: 600px;
+}
+
+tr, td
+{
+margin-left: 0pt;
+margin-right: 0pt;
+padding-left: 10pt;
+font-size: 90%;
+}
+
+p,li,th
+{
+font-size: 90%;
+margin-left: 10pt;
+}
+
+pre
+{
+margin-left: 10pt;
+}
+
+body
+{
+#ffffff;
+}
+
+h1,h2,h3,hr
+{
+color: firebrick;
+}
+
+a:link {COLOR: firebrick;}
+a:visited {COLOR: firebrick;}
+a:active {COLOR: navy;}
+
+.link
+{
+COLOR: firebrick;
+text-decoration: underline;
+}
+
+.clickable
+{
+cursor: pointer
+}
+
+.unread_title
+{
+font-weight: bold;
+}
+
+.read_title
+{
+font-weight: normal;
+}
+
+.summary
+{
+color: DimGrey;
+}
+
+.hidden
+{
+display: none;
+}
+
+.source_name
+{
+width: 600px;
+}
+
+.alert_text
+{
+width: 600px;
+}
+
+.alert_data
+{
+margin-left: 10px;
+width: 800px;
+height: 800px;
+}
+
+.source_0
+{
+background-color: LightGreen;
+}
+
+.source_1
+{
+background-color: LightSkyBlue;
+}
+
+.source_2
+{
+background-color: Khaki;
+}
+
+.source_3
+{
+background-color: LightPink;
+}
+
+.source_4
+{
+background-color: Orange;
+}
+
+.source_5
+{
+background-color: LightCoral;
+}
+
+.source_6
+{
+background-color: Orchid;
+}
+
+.source_7
+{
+background-color: Peru;
+}
+
+.source_8
+{
+background-color: SpringGreen;
+}
+
+.source_9
+{
+background-color: LightGrey;
+}
+
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddService.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddService.java
new file mode 100644
index 0000000000..797ebb4024
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddService.java
@@ -0,0 +1,31 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Remotable;
+
+/**
+ * The Add service interface
+ */
+@Remotable
+public interface AddService {
+
+ double add(double n1, double n2);
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddServiceImpl.java
new file mode 100644
index 0000000000..1a63d4ff77
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/AddServiceImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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 calculator;
+
+/**
+ * An implementation of the Add service
+ */
+public class AddServiceImpl implements AddService {
+
+ public double add(double n1, double n2) {
+ System.out.println("AddService - add " + n1 + " and " + n2);
+ return n1 + n2;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorService.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorService.java
new file mode 100644
index 0000000000..2718ab8772
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorService.java
@@ -0,0 +1,38 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Remotable;
+
+
+/**
+ * The Calculator service interface.
+ */
+@Remotable
+public interface CalculatorService {
+
+ double add(double n1, double n2);
+
+ double subtract(double n1, double n2);
+
+ double multiply(double n1, double n2);
+
+ double divide(double n1, double n2);
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java
new file mode 100644
index 0000000000..8ee640ed6b
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java
@@ -0,0 +1,74 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Reference;
+
+
+/**
+ * An implementation of the Calculator service.
+ */
+public class CalculatorServiceImpl implements CalculatorService {
+
+ private AddService addService;
+ private SubtractService subtractService;
+ private MultiplyService multiplyService;
+ private DivideService divideService;
+
+ @Reference
+ public void setAddService(AddService addService) {
+ this.addService = addService;
+ }
+
+ @Reference
+ public void setSubtractService(SubtractService subtractService) {
+ this.subtractService = subtractService;
+ }
+
+ @Reference
+ public void setMultiplyService(MultiplyService multiplyService) {
+ this.multiplyService = multiplyService;
+ }
+
+ @Reference
+ public void setDivideService(DivideService divideService) {
+ this.divideService = divideService;
+ }
+
+ public double add(double n1, double n2) {
+ System.out.println("CalculatorService - add " + n1 + " and " + n2);
+ return addService.add(n1, n2);
+ }
+
+ public double subtract(double n1, double n2) {
+ System.out.println("CalculatorService - subtract " + n1 + " and " + n2);
+ return subtractService.subtract(n1, n2);
+ }
+
+ public double multiply(double n1, double n2) {
+ System.out.println("CalculatorService - multiply " + n1 + " and " + n2);
+ return multiplyService.multiply(n1, n2);
+ }
+
+ public double divide(double n1, double n2) {
+ System.out.println("CalculatorService - divide " + n1 + " and " + n2);
+ return divideService.divide(n1, n2);
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideService.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideService.java
new file mode 100644
index 0000000000..ef6a8b375b
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideService.java
@@ -0,0 +1,28 @@
+/*
+ * 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 calculator;
+
+/**
+ * The divide service interface
+ */
+public interface DivideService {
+
+ double divide(double n1, double n2);
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java
new file mode 100644
index 0000000000..8c33862f6d
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java
@@ -0,0 +1,30 @@
+/*
+ * 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 calculator;
+
+/**
+ * An implementation of the Divide service.
+ */
+public class DivideServiceImpl implements DivideService {
+
+ public double divide(double n1, double n2) {
+ return n1 / n2;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyService.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyService.java
new file mode 100644
index 0000000000..db568cc762
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyService.java
@@ -0,0 +1,28 @@
+/*
+ * 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 calculator;
+
+/**
+ * The interface for the multiply service
+ */
+public interface MultiplyService {
+
+ double multiply(double n1, double n2);
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java
new file mode 100644
index 0000000000..c7fbc73c00
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java
@@ -0,0 +1,30 @@
+/*
+ * 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 calculator;
+
+/**
+ * An implementation of the Multiply service.
+ */
+public class MultiplyServiceImpl implements MultiplyService {
+
+ public double multiply(double n1, double n2) {
+ return n1 * n2;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractService.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractService.java
new file mode 100644
index 0000000000..615320e670
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractService.java
@@ -0,0 +1,31 @@
+/*
+ * 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 calculator;
+
+import org.osoa.sca.annotations.Remotable;
+
+/**
+ * The interface for the multiply service
+ */
+@Remotable
+public interface SubtractService {
+
+ double subtract(double n1, double n2);
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java
new file mode 100644
index 0000000000..abf2777c7d
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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 calculator;
+
+/**
+ * An implementation of the subtract service.
+ */
+public class SubtractServiceImpl implements SubtractService {
+
+ public double subtract(double n1, double n2) {
+ System.out.println("SubtractService - subtract " + n1 + " and " + n2);
+ return n1 - n2;
+ }
+
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCase.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCase.java
new file mode 100644
index 0000000000..6faf2007e7
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCase.java
@@ -0,0 +1,124 @@
+/*
+ * 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 javax.xml.namespace.QName;
+
+import junit.framework.Assert;
+
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.domain.SCADomainFactory;
+import org.apache.tuscany.sca.node.SCADomainFinder;
+import org.apache.tuscany.sca.node.SCANode;
+import org.apache.tuscany.sca.node.SCANodeFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import calculator.AddService;
+import calculator.CalculatorService;
+
+/**
+ * Runs a distributed domain in a single VM by using and in memory
+ * implementation of the distributed domain
+ */
+public class DomainDrivenTestCase {
+
+ private static String DEFAULT_DOMAIN_URI = "http://localhost:8877";
+
+ private static SCADomain domain;
+ private static SCANode nodeA;
+ private static SCANode nodeB;
+ private static SCANode nodeC;
+ private static CalculatorService calculatorServiceA;
+ private static CalculatorService calculatorServiceB;
+ private static AddService addServiceB;
+
+ @BeforeClass
+ public static void init() throws Exception {
+
+ try {
+ System.out.println("Setting up domain");
+
+ SCADomainFactory domainFactory = SCADomainFactory.newInstance();
+ domain = domainFactory.createSCADomain(DEFAULT_DOMAIN_URI);
+ domain.start();
+
+ System.out.println("Setting up calculator nodes");
+
+ ClassLoader cl = DomainDrivenTestCase.class.getClassLoader();
+
+ SCANodeFactory nodeFactory = SCANodeFactory.newInstance();
+
+ nodeA = nodeFactory.createSCANode("nodeA", DEFAULT_DOMAIN_URI);
+ nodeB = nodeFactory.createSCANode("nodeB", DEFAULT_DOMAIN_URI);
+ nodeC = nodeFactory.createSCANode("nodeC", DEFAULT_DOMAIN_URI);
+
+ domain.addContribution("nodeA", cl.getResource("nodeA/"));
+ domain.addContribution("nodeB", cl.getResource("nodeB/"));
+ domain.addContribution("nodeC", cl.getResource("nodeC/"));
+
+ domain.addToDomainLevelComposite(new QName("http://sample", "Calculator"));
+
+ domain.startComposite(new QName("http://sample", "Calculator"));
+
+ calculatorServiceA = domain.getService(CalculatorService.class, "CalculatorServiceComponentA");
+ calculatorServiceB = domain.getService(CalculatorService.class, "CalculatorServiceComponentB");
+
+/*
+ // get a reference to various services in the domain
+ calculatorServiceA = nodeA.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentA");
+ calculatorServiceB = nodeB.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentB");
+
+ //addServiceB = domain.getService(AddService.class, "AddServiceComponentB");
+ addServiceB = nodeA.getDomain().getService(AddService.class, "AddServiceComponentB");
+*/
+
+ } catch(Exception ex){
+ System.err.println(ex.toString());
+ }
+
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ // stop the nodes and hence the domains they contain
+ nodeA.stop();
+ nodeB.stop();
+ nodeC.stop();
+ domain.stop();
+ }
+
+ @Test
+ public void testCalculator() throws Exception {
+
+ // Calculate
+ Assert.assertEquals(calculatorServiceA.add(3, 2), 5.0);
+ Assert.assertEquals(calculatorServiceA.subtract(3, 2), 1.0);
+ Assert.assertEquals(calculatorServiceA.multiply(3, 2), 6.0);
+ Assert.assertEquals(calculatorServiceA.divide(3, 2), 1.5);
+ Assert.assertEquals(calculatorServiceB.add(3, 2), 5.0);
+ Assert.assertEquals(calculatorServiceB.subtract(3, 2), 1.0);
+ Assert.assertEquals(calculatorServiceB.multiply(3, 2), 6.0);
+ Assert.assertEquals(calculatorServiceB.divide(3, 2), 1.5);
+
+ }
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCase.java b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCase.java
new file mode 100644
index 0000000000..bd4dfd4d32
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCase.java
@@ -0,0 +1,126 @@
+/*
+ * 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 javax.xml.namespace.QName;
+
+import junit.framework.Assert;
+
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.domain.SCADomainFactory;
+import org.apache.tuscany.sca.node.SCADomainFinder;
+import org.apache.tuscany.sca.node.SCANode;
+import org.apache.tuscany.sca.node.SCANodeFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import calculator.AddService;
+import calculator.CalculatorService;
+
+/**
+ * Runs a distributed domain in a single VM by using and in memory
+ * implementation of the distributed domain
+ */
+public class NodeDrivenTestCase {
+
+ private static String DEFAULT_DOMAIN_URI = "http://localhost:8877";
+
+ private static SCADomain domain;
+ private static SCANode nodeA;
+ private static SCANode nodeB;
+ private static SCANode nodeC;
+ private static SCADomain domainProxy;
+ private static CalculatorService calculatorServiceA;
+ private static CalculatorService calculatorServiceB;
+ private static AddService addServiceB;
+
+ @BeforeClass
+ public static void init() throws Exception {
+
+ try {
+ System.out.println("Setting up domain");
+
+ SCADomainFactory domainFactory = SCADomainFactory.newInstance();
+ domain= domainFactory.createSCADomain(DEFAULT_DOMAIN_URI);
+
+ System.out.println("Setting up calculator nodes");
+
+ ClassLoader cl = NodeDrivenTestCase.class.getClassLoader();
+
+ SCANodeFactory nodeFactory = SCANodeFactory.newInstance();
+
+ // rely on meta data to start composite
+ nodeA = nodeFactory.createSCANode("nodeA", DEFAULT_DOMAIN_URI);
+ nodeA.addContribution("nodeA", cl.getResource("nodeA/"));
+ nodeA.start();
+
+ // rely on meta data to start composite
+ nodeB = nodeFactory.createSCANode("nodeB", DEFAULT_DOMAIN_URI);
+ nodeB.addContribution("nodeB", cl.getResource("nodeB/"));
+ nodeB.start();
+
+ // explicitly ask for composite to be started
+ nodeC = nodeFactory.createSCANode("nodeC", DEFAULT_DOMAIN_URI);
+ nodeC.addContribution("nodeC", cl.getResource("nodeC/"));
+ nodeC.deployComposite(new QName("http://sample", "Calculator"));
+ nodeC.start();
+
+ SCADomainFinder domainFinder = SCADomainFinder.newInstance();
+ domainProxy = domainFinder.getSCADomain(DEFAULT_DOMAIN_URI);
+
+ // get a reference to various services in the domain
+ calculatorServiceA = nodeA.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentA");
+ calculatorServiceB = nodeB.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentB");
+
+ //addServiceB = domain.getService(AddService.class, "AddServiceComponentB");
+ addServiceB = nodeA.getDomain().getService(AddService.class, "AddServiceComponentB");
+
+ } catch(Exception ex){
+ System.err.println(ex.toString());
+ }
+
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ // stop the nodes and hence the domains they contain
+ nodeA.stop();
+ nodeB.stop();
+ nodeC.stop();
+ }
+
+ @Test
+ public void testCalculator() throws Exception {
+
+ // Calculate
+ Assert.assertEquals(calculatorServiceA.add(3, 2), 5.0);
+ Assert.assertEquals(calculatorServiceA.subtract(3, 2), 1.0);
+ Assert.assertEquals(calculatorServiceA.multiply(3, 2), 6.0);
+ Assert.assertEquals(calculatorServiceA.divide(3, 2), 1.5);
+ Assert.assertEquals(calculatorServiceB.add(3, 2), 5.0);
+ Assert.assertEquals(calculatorServiceB.subtract(3, 2), 1.0);
+ Assert.assertEquals(calculatorServiceB.multiply(3, 2), 6.0);
+ Assert.assertEquals(calculatorServiceB.divide(3, 2), 1.5);
+ Assert.assertEquals(addServiceB.add(3, 2), 5.0);
+
+ }
+}
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/Calculator.composite b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/Calculator.composite
new file mode 100644
index 0000000000..e9ab7dc732
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/Calculator.composite
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ targetNamespace="http://sample"
+ xmlns:sample="http://sample"
+ name="Calculator">
+
+ <component name="CalculatorServiceComponentA">
+ <implementation.java class="calculator.CalculatorServiceImpl"/>
+ <service name="CalculatorService">
+ <binding.sca uri="http://localhost:8087/CalculatorServiceComponentA"/>
+ </service>
+ <reference name="addService" target="AddServiceComponentB" />
+ <reference name="subtractService" target="SubtractServiceComponentC" />
+ <reference name="multiplyService" target="MultiplyServiceComponentA"/>
+ <reference name="divideService" target="DivideServiceComponentA" />
+ </component>
+
+ <component name="MultiplyServiceComponentA">
+ <implementation.java class="calculator.MultiplyServiceImpl" />
+ </component>
+
+ <component name="DivideServiceComponentA">
+ <implementation.java class="calculator.DivideServiceImpl" />
+ </component>
+
+</composite>
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml
new file mode 100644
index 0000000000..3f9ed8024b
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<contribution xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ targetNamespace="http://sample"
+ xmlns:sample="http://sample">
+ <deployable composite="sample:Calculator"/>
+</contribution> \ No newline at end of file
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeB/META-INF/sca-deployables/Calculator.composite b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeB/META-INF/sca-deployables/Calculator.composite
new file mode 100644
index 0000000000..bd8fef194e
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeB/META-INF/sca-deployables/Calculator.composite
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ targetNamespace="http://sample"
+ xmlns:sample="http://sample"
+ name="Calculator">
+
+ <component name="CalculatorServiceComponentB">
+ <implementation.java class="calculator.CalculatorServiceImpl"/>
+ <reference name="addService" target="AddServiceComponentB" />
+ <reference name="subtractService" target="SubtractServiceComponentC" />
+ <reference name="multiplyService" target="MultiplyServiceComponentB"/>
+ <reference name="divideService" target="DivideServiceComponentB" />
+ </component>
+
+ <component name="MultiplyServiceComponentB">
+ <implementation.java class="calculator.MultiplyServiceImpl" />
+ </component>
+
+ <component name="DivideServiceComponentB">
+ <implementation.java class="calculator.DivideServiceImpl" />
+ </component>
+
+ <component name="AddServiceComponentB">
+ <implementation.java class="calculator.AddServiceImpl" />
+ </component>
+
+</composite>
diff --git a/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeC/Calculator.composite b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeC/Calculator.composite
new file mode 100644
index 0000000000..ababc1bd02
--- /dev/null
+++ b/branches/sca-java-1.0.1/modules/node-impl/src/test/resources/nodeC/Calculator.composite
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ targetNamespace="http://sample"
+ xmlns:sample="http://sample"
+ name="Calculator">
+
+ <component name="SubtractServiceComponentC">
+ <implementation.java class="calculator.SubtractServiceImpl" />
+ <service name="SubtractService">
+ <binding.sca uri="http://localhost:8086/SubtractServiceComponentC"/>
+ </service>
+ </component>
+
+</composite>