summaryrefslogtreecommitdiffstats
path: root/sandbox/sebastien/java/sca-node/modules/node-impl
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/sebastien/java/sca-node/modules/node-impl')
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/DISCLAIMER8
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/LICENSE205
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/NOTICE6
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/pom.xml158
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java51
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java115
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainAPIServiceProxyImpl.java103
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainEventServiceProxyImpl.java117
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java70
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainProxyImpl.java625
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java101
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java936
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java311
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/launch/SCANodeLauncher.java79
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/management/impl/SCANodeManagerServiceImpl.java122
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/node.composite79
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/index.html87
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/node.pngbin0 -> 296 bytes
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/style.css176
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddService.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceImpl.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceUpdateImpl.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorService.java40
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java76
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideService.java30
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java32
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyService.java30
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java32
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractService.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCaseOFF.java124
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCaseOFF.java162
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeMemoryTestCaseOFF.java81
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/StandaloneNodeTestCaseOFF.java205
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/Calculator.composite33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/META-INF/sca-contribution.xml24
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/Calculator.composite47
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/META-INF/sca-contribution.xml25
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeA/Calculator.composite44
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml24
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeB/META-INF/sca-deployables/Calculator.composite45
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeC/META-INF/sca-deployables/Calculator.composite32
-rw-r--r--sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeD/META-INF/sca-deployables/Calculator.composite49
43 files changed, 4649 insertions, 0 deletions
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/DISCLAIMER b/sandbox/sebastien/java/sca-node/modules/node-impl/DISCLAIMER
new file mode 100644
index 0000000000..d68a410903
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/DISCLAIMER
@@ -0,0 +1,8 @@
+Apache Tuscany is an effort undergoing incubation at The Apache Software
+Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is
+required of all newly accepted projects until a further review indicates that
+the infrastructure, communications, and decision making process have stabilized
+in a manner consistent with other successful ASF projects. While incubation
+status is not necessarily a reflection of the completeness or stability of the
+code, it does indicate that the project has yet to be fully endorsed by the ASF.
+
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/LICENSE b/sandbox/sebastien/java/sca-node/modules/node-impl/LICENSE
new file mode 100644
index 0000000000..6e529a25c4
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/LICENSE
@@ -0,0 +1,205 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
+
+
+
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/NOTICE b/sandbox/sebastien/java/sca-node/modules/node-impl/NOTICE
new file mode 100644
index 0000000000..1325efd8bf
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/NOTICE
@@ -0,0 +1,6 @@
+${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/pom.xml b/sandbox/sebastien/java/sca-node/modules/node-impl/pom.xml
new file mode 100644
index 0000000000..5c5ce7e2b9
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/pom.xml
@@ -0,0 +1,158 @@
+<?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.
+-->
+<project>
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>tuscany-node-impl</artifactId>
+ <name>Apache Tuscany SCA Node Implementation</name>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-assembly</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-assembly-xml</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-contribution-impl</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-node</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-node-api</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-domain-api</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-host-embedded</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.axis2</groupId>
+ <artifactId>axis2-adb</artifactId>
+ <version>1.3</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-domain-impl</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-implementation-java-runtime</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-host-jetty</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-jsonrpc-runtime</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-http</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-implementation-resource</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-ws-axis2</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-sca-axis2</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ </dependencies>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+
+ <configuration>
+ <instructions>
+ <Bundle-Version>${tuscany.version}</Bundle-Version>
+ <Bundle-SymbolicName>org.apache.tuscany.sca.node.impl</Bundle-SymbolicName>
+ <Bundle-Description>${pom.name}</Bundle-Description>
+ <Export-Package>org.apache.tuscany.sca.node*</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java
new file mode 100644
index 0000000000..248c2b0620
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java
@@ -0,0 +1,51 @@
+/*
+ * 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.spi.ComponentInfo;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+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/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java
new file mode 100644
index 0000000000..19238ef176
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java
@@ -0,0 +1,115 @@
+/*
+ * 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.spi.ComponentListener;
+import org.apache.tuscany.sca.node.spi.ComponentManager;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+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/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainAPIServiceProxyImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainAPIServiceProxyImpl.java
new file mode 100644
index 0000000000..31ede6008e
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainAPIServiceProxyImpl.java
@@ -0,0 +1,103 @@
+/*
+ * 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.logging.Logger;
+
+import org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.domain.spi.SCADomainAPIService;
+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 SCADomainAPIServiceProxyImpl implements SCADomainAPIService{
+
+ private static final Logger logger = Logger.getLogger(SCADomainAPIServiceProxyImpl.class.getName());
+
+ @Reference
+ protected SCADomainAPIService domainManager;
+
+ public void start() throws DomainException {
+ domainManager.start();
+ }
+
+ public void stop() throws DomainException {
+ domainManager.stop();
+ }
+
+ public void destroyDomain() throws DomainException {
+ domainManager.destroyDomain();
+ }
+
+ public String getURI() {
+ return domainManager.getURI();
+ }
+
+ public void addContribution(String contributionURI, String contributionURL) throws DomainException {
+ domainManager.addContribution(contributionURI, contributionURL);
+ }
+
+ public void updateContribution(String contributionURI, String contributionURL) throws DomainException {
+ domainManager.updateContribution(contributionURI, contributionURL);
+ }
+
+ public void removeContribution(String contributionURI) throws DomainException {
+ domainManager.removeContribution(contributionURI);
+ }
+
+ public void addDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ domainManager.addDeploymentComposite(contributionURI, compositeXML);
+ }
+
+ public void updateDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ domainManager.updateDeploymentComposite(contributionURI, compositeXML);
+ }
+
+ public void addToDomainLevelComposite(String compositeQName) throws DomainException {
+ domainManager.addToDomainLevelComposite(compositeQName);
+ }
+
+ public void removeFromDomainLevelComposite(String compositeQName) throws DomainException {
+ domainManager.removeFromDomainLevelComposite(compositeQName);
+ }
+
+ public String getDomainLevelComposite() throws DomainException {
+ return domainManager.getDomainLevelComposite();
+ }
+
+ public String getQNameDefinition(String artifact) throws DomainException {
+ return domainManager.getQNameDefinition(artifact);
+ }
+
+ public void startComposite(String compositeQName) throws DomainException {
+ domainManager.startComposite(compositeQName);
+ }
+
+ public void stopComposite(String compositeQName) throws DomainException {
+ domainManager.stopComposite(compositeQName);
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainEventServiceProxyImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainEventServiceProxyImpl.java
new file mode 100644
index 0000000000..4f3a3eb906
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainEventServiceProxyImpl.java
@@ -0,0 +1,117 @@
+/*
+ * 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.Externalizable;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.domain.spi.SCADomainEventService;
+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 SCADomainEventServiceProxyImpl implements SCADomainEventService{
+
+ private static final Logger logger = Logger.getLogger(SCADomainEventServiceProxyImpl.class.getName());
+
+ @Property
+ protected int retryCount = 100;
+
+ @Property
+ protected int retryInterval = 5000; //ms
+
+ @Reference
+ protected SCADomainEventService domainManager;
+
+ public void registerNode(String nodeURI, String nodeURL, Externalizable nodeManagerService) throws DomainException {
+
+ // a retry loop is included on node registration in case the node
+ // comes up before the domain it is registering with
+ for (int i =0; i < retryCount; i++){
+ try {
+ domainManager.registerNode(nodeURI, nodeURL, nodeManagerService);
+ break;
+ } catch(UndeclaredThrowableException ex) {
+ ex.printStackTrace();
+ logger.log(Level.INFO, "Trying to register node " +
+ nodeURI +
+ " at endpoint " +
+ nodeURL);
+
+ }
+
+ try {
+ Thread.sleep(retryInterval);
+ } catch(InterruptedException ex) {
+ }
+ }
+ }
+
+ public void unregisterNode(String nodeURI) throws DomainException {
+ domainManager.unregisterNode(nodeURI);
+ }
+
+ public void registerNodeStart(String nodeURI) throws DomainException {
+ domainManager.registerNodeStart(nodeURI);
+ }
+
+ public void registerNodeStop(String nodeURI) throws DomainException {
+ domainManager.registerNodeStop(nodeURI);
+ }
+
+ public void registerContribution(String nodeURI, String contributionURI, String contributionURL) throws DomainException {
+ domainManager.registerContribution(nodeURI, contributionURI, contributionURL);
+ }
+
+ public void unregisterContribution(String nodeURI, String contributionURI) throws DomainException {
+ domainManager.unregisterContribution(nodeURI, contributionURI);
+ }
+
+ public void registerDomainLevelComposite(String nodeURI, String compositeQNameString) throws DomainException{
+ domainManager.registerDomainLevelComposite(nodeURI, compositeQNameString);
+ }
+
+ public void registerServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName, String URL) throws DomainException {
+ domainManager.registerServiceEndpoint(domainUri, nodeUri, serviceName, bindingName, URL);
+ }
+
+ public void unregisterServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName) throws DomainException {
+ domainManager.unregisterServiceEndpoint(domainUri, nodeUri, serviceName, bindingName);
+ }
+
+ public String findServiceEndpoint(String domainUri, String serviceName, String bindingName) throws DomainException {
+ return domainManager.findServiceEndpoint(domainUri, serviceName, bindingName);
+ }
+
+ public String findServiceNode(String domainUri, String serviceName, String bindingName) throws DomainException {
+ return domainManager.findServiceNode(domainUri, serviceName, bindingName);
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java
new file mode 100644
index 0000000000..b2b719b092
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java
@@ -0,0 +1,70 @@
+/*
+ * 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.domain.impl.SCADummyNodeImpl;
+import org.apache.tuscany.sca.node.SCADomainFinder;
+import org.apache.tuscany.sca.node.SCANode;
+
+/**
+ * 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>();
+
+ /**
+ * Constructs a new SCA domain finder instance.
+ */
+ 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 SCADomainProxyImpl(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
+
+ // Add the dummy node as there will be no real node in this case
+ SCANode scaNode = new SCADummyNodeImpl(scaDomain);
+ ((SCADomainProxyImpl)scaDomain).addNode(scaNode);
+ }
+ return scaDomain;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainProxyImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainProxyImpl.java
new file mode 100644
index 0000000000..859e347c1a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainProxyImpl.java
@@ -0,0 +1,625 @@
+ /*
+ * 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.ByteArrayOutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.xml.Constants;
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.assembly.ActivationException;
+import org.apache.tuscany.sca.core.context.CallableReferenceImpl;
+import org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.domain.impl.SCADomainImpl;
+import org.apache.tuscany.sca.domain.impl.SCADummyNodeImpl;
+import org.apache.tuscany.sca.domain.spi.SCADomainAPIService;
+import org.apache.tuscany.sca.domain.spi.SCADomainEventService;
+import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.host.http.ServletHostExtensionPoint;
+import org.apache.tuscany.sca.node.SCANode;
+import org.apache.tuscany.sca.node.management.SCANodeManagerInitService;
+import org.apache.tuscany.sca.node.management.SCANodeManagerService;
+import org.apache.tuscany.sca.node.spi.NodeFactoryImpl;
+import org.apache.tuscany.sca.node.spi.SCANodeSPI;
+import org.apache.tuscany.sca.node.util.SCAContributionUtil;
+import org.osoa.sca.CallableReference;
+import org.osoa.sca.ServiceReference;
+
+
+/**
+ * A local representation of the SCA Domain running on a single node
+ *
+ * @version $Rev$ $Date$
+ */
+public class SCADomainProxyImpl extends SCADomainImpl {
+
+ private static final Logger logger = Logger.getLogger(SCADomainProxyImpl.class.getName());
+
+ // management services
+ private SCADomainAPIService domainAPIService;
+ private SCADomainEventService domainEventService;
+ private SCANodeManagerInitService nodeManagerInitService;
+ private CallableReferenceImpl<SCANodeManagerService> nodeManagerService;
+
+ // the local node implementation
+ private SCANode node;
+
+ // 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
+ * @throws DomainException
+ */
+ public SCADomainProxyImpl(String domainURI) throws DomainException {
+ super(domainURI);
+ }
+
+ /**
+ * 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
+ * @param cl The ClassLoader to use as the Domain ClassLoader
+ * @throws ActivationException
+ * @throws DomainException
+ */
+ public SCADomainProxyImpl(String domainURI, ClassLoader cl) throws DomainException {
+ super(domainURI);
+ domainClassLoader = cl;
+ }
+
+ /**
+ * Start the composite that connects to the domain manager
+ */
+ protected void init() throws DomainException {
+ try {
+ // check where domain URIs are URLs, they will be used to configure various
+ // endpoints if they are
+ URI tmpURI;
+ try {
+ tmpURI = new URI(domainModel.getDomainURI());
+ domainModel.setDomainURL(tmpURI.toURL().toExternalForm());
+ } catch(Exception ex) {
+ domainModel.setDomainURL(null);
+ }
+
+ // Check if node has been given a valid domain name to connect to
+ if (domainModel.getDomainURL() == null) {
+ logger.log(Level.INFO, "Domain will be started stand-alone as domain URL is not provided");
+ }
+
+ } catch(Exception ex) {
+ throw new DomainException(ex);
+ }
+ }
+
+ private void createRuntime() throws DomainException {
+ try {
+ // check we don't try to do this twice
+ if (domainManagementRuntime != null){
+ return;
+ }
+
+ // if there is no node create a runtime otherwise use the runtime from the node
+ if ((node == null) ||
+ ( (node != null) && (node.getClass().equals(SCADummyNodeImpl.class)))){
+ // create a runtime for the domain management services to run on
+ domainManagementRuntime = new ReallySmallRuntime(domainClassLoader);
+ domainManagementRuntime.start();
+
+ String path = URI.create(domainModel.getDomainURI()).getPath();
+
+ // invent a default URL for the runtime
+ String host = InetAddress.getLocalHost().getHostName();
+ ServerSocket socket = new ServerSocket(0);
+ int port = socket.getLocalPort();
+ socket.close();
+
+ ServletHostExtensionPoint servletHosts = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class);
+ for (ServletHost servletHost: servletHosts.getServletHosts()) {
+ servletHost.setDefaultPort(port);
+ if (path != null && path.length() > 0 && !path.equals("/")) {
+ servletHost.setContextPath(path);
+ }
+ }
+
+ // make the node available to the model
+ // this causes the runtime to start registering binding-sca service endpoints
+ // with the domain proxy
+ // TODO - This code is due to be pulled out and combined with the register and
+ // resolution code that appears in this class
+ ModelFactoryExtensionPoint factories = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
+ nodeFactory = new NodeFactoryImpl(node);
+ factories.addFactory(nodeFactory);
+
+ // Create an in-memory domain level management composite
+ AssemblyFactory assemblyFactory = domainManagementRuntime.getAssemblyFactory();
+ domainManagementComposite = assemblyFactory.createComposite();
+ domainManagementComposite.setName(new QName(Constants.SCA10_NS, "domainManagement"));
+ domainManagementComposite.setURI(domainModel.getDomainURI() + "/Management");
+
+
+ } else {
+ domainManagementRuntime = (ReallySmallRuntime)((SCANodeSPI)node).getNodeRuntime();
+ domainManagementComposite = domainManagementRuntime.getCompositeActivator().getDomainComposite();
+
+ // set the context path for the node
+ String path = URI.create(node.getURI()).getPath();
+ if (path != null && path.length() > 0 && !path.equals("/")) {
+ ServletHostExtensionPoint servletHosts = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class);
+ for (ServletHost servletHost: servletHosts.getServletHosts()) {
+ servletHost.setContextPath(path);
+ }
+ }
+ }
+
+ // Find the composite that will configure the domain
+ String domainCompositeName = "node.composite";
+ URL contributionURL = SCAContributionUtil.findContributionFromResource(domainClassLoader, domainCompositeName);
+
+ if ( contributionURL != null ){
+ logger.log(Level.INFO, "Domain management configured from " + contributionURL);
+
+ // add node composite to the management domain
+ domainManagementContributionService = domainManagementRuntime.getContributionService();
+ domainManagementContribution = domainManagementContributionService.contribute("nodedomain",
+ contributionURL,
+ false);
+
+ Composite composite = null;
+
+ for (Artifact artifact: domainManagementContribution.getArtifacts()) {
+ if (domainCompositeName.equals(artifact.getURI())) {
+ composite = (Composite)artifact.getModel();
+ }
+ }
+
+ if (composite != null) {
+
+ domainManagementComposite.getIncludes().add(composite);
+ domainManagementRuntime.buildComposite(composite);
+
+ if (domainModel.getDomainURL() != null) {
+ URI domainURI = URI.create(domainModel.getDomainURI());
+ String domainHost = domainURI.getHost();
+ int domainPort = domainURI.getPort();
+
+ // override any domain URLs in node.composite and replace with the
+ // domain URL provided on start up
+ for ( Component component : composite.getComponents()){
+ for (ComponentReference reference : component.getReferences() ){
+ for (Binding binding : reference.getBindings() ) {
+ String bindingURIString = binding.getURI();
+ if (bindingURIString != null) {
+ URI bindingURI = URI.create(bindingURIString);
+ String bindingHost = bindingURI.getHost();
+ int bindingPort = bindingURI.getPort();
+
+ if ( bindingPort == 9999){
+ // replace the old with the new
+ bindingURIString = domainURI + bindingURI.getPath() ;
+
+ // set the address back into the NodeManager binding.
+ binding.setURI(bindingURIString);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ domainManagementRuntime.getCompositeActivator().activate(composite);
+ domainManagementRuntime.getCompositeActivator().start(composite);
+
+ // get the management components out of the domain so that they
+ // can be configured/used.
+ domainAPIService = getService(SCADomainAPIService.class,
+ "SCADomainAPIServiceProxyComponent",
+ domainManagementRuntime,
+ domainManagementComposite);
+ domainEventService = getService(SCADomainEventService.class,
+ "SCADomainEventServiceProxyComponent",
+ domainManagementRuntime,
+ domainManagementComposite);
+
+ nodeManagerInitService = getService(SCANodeManagerInitService.class,
+ "SCANodeManagerComponent/SCANodeManagerInitService",
+ domainManagementRuntime,
+ domainManagementComposite);
+
+ nodeManagerService = (CallableReferenceImpl<SCANodeManagerService>)
+ getServiceReference(SCANodeManagerService.class,
+ "SCANodeManagerComponent/SCANodeManagerService",
+ domainManagementRuntime,
+ domainManagementComposite);
+
+ // add the registered node now that the runtime is started
+ if ((node != null) && (!node.getClass().equals(SCADummyNodeImpl.class))){
+ addNode();
+ }
+
+
+ } else {
+ throw new ActivationException("Domain management contribution " +
+ contributionURL +
+ " found but could not be loaded");
+ }
+ } else {
+ throw new ActivationException("Domain management contribution " +
+ domainCompositeName +
+ " not found on the classpath");
+ }
+
+ } catch(Exception ex) {
+ throw new DomainException(ex);
+ }
+ }
+
+
+ public String getComposite(QName compositeQName){
+
+ Composite composite = null;
+ for(Composite tmpComposite : domainManagementComposite.getIncludes()){
+ if (tmpComposite.getName().equals(compositeQName)){
+ composite = tmpComposite;
+ }
+ }
+
+ String compositeString = null;
+
+ if (composite != null){
+ ExtensionPointRegistry registry = domainManagementRuntime.getExtensionPointRegistry();
+
+ StAXArtifactProcessorExtensionPoint staxProcessors =
+ registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+
+ StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try {
+ XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(bos);
+ processor.write(composite, writer);
+ writer.flush();
+ writer.close();
+ } catch (Exception ex) {
+ System.out.println(ex.toString());
+ }
+
+ compositeString = bos.toString();
+ }
+
+ return compositeString;
+ }
+
+ // SCADomainEventService methods
+
+ public void addNode(SCANode node) throws DomainException {
+ this.node = node;
+
+ // add the node into the local domain model
+ super.registerNode(node.getURI(), node.getURI(), null);
+
+ // the registration of the node with the domain is delayed until
+ // after the runtime has been started
+ createRuntime();
+ }
+
+ private void addNode() throws DomainException {
+
+ // pass this object into the node manager service
+ nodeManagerInitService.setNode(node);
+
+ if (domainModel.getDomainURL() != null){
+ // add the node to the domain
+
+ try {
+ // create the node manager endpoint
+ // TODO - we really need to pass in a CallableReference
+ URI nodeURI = new URI(node.getURI());
+ String nodeHost = nodeURI.getHost();
+
+ if (nodeHost.equals("localhost")){
+ nodeHost = InetAddress.getLocalHost().getHostName();
+ }
+
+ String nodeManagerURL = nodeURI.getScheme()+ "://" +
+ nodeHost + ":" +
+ nodeURI.getPort() + nodeURI.getPath() + "/SCANodeManagerComponent/SCANodeManagerService";
+
+ // go out and add this node to the wider domain
+ domainEventService.registerNode(node.getURI(), nodeManagerURL, nodeManagerService);
+
+ } catch(Exception ex) {
+ logger.log(Level.SEVERE,
+ "Can't connect to domain manager at: " +
+ domainModel.getDomainURL());
+ throw new DomainException(ex);
+ }
+ }
+ }
+
+ public void removeNode(SCANode node) throws DomainException {
+
+ // remove the node from the local domain model
+ super.unregisterNode(node.getURI());
+
+ if (domainModel.getDomainURL() != null){
+
+ try {
+ // go out and remove this node to the wider domain
+ domainEventService.unregisterNode(node.getURI());
+ } catch(Exception ex) {
+ logger.log(Level.SEVERE,
+ "Can't connect to domain manager at: " +
+ domainModel.getDomainURL());
+ throw new DomainException(ex);
+ }
+ }
+
+ // remove this object from the node manager service
+ nodeManagerInitService.setNode(null);
+
+ this.node = null;
+ }
+
+ public void registerNodeStart(String nodeURI) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainEventService != null)){
+ domainEventService.registerNodeStart(nodeURI);
+ }
+ }
+
+ public void registerNodeStop(String nodeURI) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainEventService != null)){
+ domainEventService.registerNodeStop(nodeURI);
+ }
+ }
+
+ public void registerContribution(String nodeURI, String contributionURI, String contributionURL) throws DomainException {
+
+ if ((domainModel.getDomainURL() != null) && (domainEventService != null)){
+ domainEventService.registerContribution(nodeURI, contributionURI, contributionURL);
+ }
+ }
+
+ public void unregisterContribution(String nodeURI, String contributionURI) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainEventService != null)) {
+ domainEventService.unregisterContribution(nodeURI, contributionURI);
+ }
+ }
+
+ public void registerDomainLevelComposite(String nodeURI, String compositeQNameString) throws DomainException{
+ if ((domainModel.getDomainURL() != null) && (domainEventService != null)) {
+ domainEventService.registerDomainLevelComposite(nodeURI, compositeQNameString);
+ }
+ }
+
+
+ public void registerServiceEndpoint(String domainURI, String nodeURI, String serviceName, String bindingName, String URL) throws DomainException {
+
+ //super.registerServiceEndpoint(domainURI, nodeURI, serviceName, bindingName, URL);
+
+ if ((domainModel.getDomainURL() != null) && (domainEventService != null)) {
+ domainEventService.registerServiceEndpoint(domainURI, nodeURI, serviceName, bindingName, URL);
+ }
+ }
+
+ public void unregisterServiceEndpoint(String domainURI, String nodeURI, String serviceName, String bindingName) throws DomainException {
+
+ //super.unregisterServiceEndpoint(domainURI, nodeURI, serviceName, bindingName);
+
+ if ((domainModel.getDomainURL() != null) && (domainEventService != null)) {
+ domainEventService.unregisterServiceEndpoint(domainURI, nodeURI, serviceName, bindingName);
+ }
+ }
+
+ public String findServiceEndpoint(String domainURI, String serviceName, String bindingName) throws DomainException {
+
+ String endpoint = super.findServiceEndpoint(domainURI, serviceName, bindingName);
+
+ if ( (endpoint.equals(SERVICE_NOT_REGISTERED)) && (domainModel.getDomainURL() != null) && (domainEventService != null)){
+ endpoint = domainEventService.findServiceEndpoint(domainURI, serviceName, bindingName);
+ }
+
+ return endpoint;
+ }
+
+ public String findServiceNode(String domainURI, String serviceName, String bindingName) throws DomainException {
+
+ String nodeName = super.findServiceEndpoint(domainURI, serviceName, bindingName);
+
+ if ( (nodeName.equals(SERVICE_NOT_KNOWN)) && (domainModel.getDomainURL() != null) && (domainEventService != null)){
+ nodeName = domainEventService.findServiceNode(domainURI, serviceName, bindingName);
+ }
+
+ return nodeName;
+ }
+
+
+ // SCADomain API methods
+ public void start() throws DomainException {
+
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.start();
+ } else {
+ logger.log(Level.INFO,"Not connected to domain");
+ }
+ }
+
+ public void stop() throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.stop();
+ } else {
+ logger.log(Level.INFO,"Not connected to domain");
+ }
+ }
+
+ public void destroy() throws DomainException {
+
+ try {
+
+
+ if (domainManagementRuntime != null) {
+ Composite composite = domainManagementComposite.getIncludes().get(0);
+
+ domainManagementRuntime.getCompositeActivator().stop(composite);
+ domainManagementRuntime.getCompositeActivator().deactivate(composite);
+
+ domainManagementComposite.getIncludes().clear();
+ domainManagementRuntime.getContributionService().remove(domainManagementContribution.getURI());
+
+ domainManagementRuntime.stop();
+
+ domainManagementRuntime = null;
+ domainManagementComposite = null;
+
+ domainAPIService = null;
+ domainEventService = null;
+ nodeManagerInitService = null;
+ }
+
+
+ } catch (Exception ex) {
+ throw new DomainException(ex);
+ }
+ }
+
+
+ public void addContribution(String contributionURI, URL contributionURL) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.addContribution(contributionURI, contributionURL.toString());
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public void updateContribution(String contributionURI, URL contributionURL) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.updateContribution(contributionURI, contributionURL.toString());
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public void removeContribution(String contributionURI) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.removeContribution(contributionURI);
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public void addDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.addDeploymentComposite(contributionURI, compositeXML);
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public void updateDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.updateDeploymentComposite(contributionURI, compositeXML);
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public void addToDomainLevelComposite(QName compositeQName) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.addToDomainLevelComposite(compositeQName.toString());
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public void removeFromDomainLevelComposite(QName compositeQName) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.removeFromDomainLevelComposite(compositeQName.toString());
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public String getDomainLevelComposite() throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ return domainAPIService.getDomainLevelComposite();
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public String getQNameDefinition(QName artifact) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ return domainAPIService.getQNameDefinition(artifact.toString());
+ } else {
+ throw new DomainException("Not connected to domain");
+ }
+ }
+
+ public void startComposite(QName compositeQName) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.startComposite(compositeQName.toString());
+ } else {
+ logger.log(Level.INFO,"Not connected to domain");
+ }
+ }
+
+ public void stopComposite(QName compositeQName) throws DomainException {
+ if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){
+ domainAPIService.stopComposite(compositeQName.toString());
+ } else {
+ logger.log(Level.INFO,"Not connected to domain");
+ }
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ return (R)cast(target, domainManagementRuntime);
+ }
+
+ public <B> B getService(Class<B> businessInterface, String serviceName) {
+ return getService( businessInterface, serviceName, domainManagementRuntime, domainManagementComposite);
+ }
+
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) {
+ return getServiceReference(businessInterface, name, domainManagementRuntime, domainManagementComposite);
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java
new file mode 100644
index 0000000000..ce07327a8d
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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.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 {
+
+
+ /**
+ * Create a new SCA node factory instance.
+ *
+ * @return a new SCA node factory
+ */
+ public SCANodeFactoryImpl() {
+
+ }
+
+ /**
+ * Creates a new SCA node.
+ *
+ * @param physicalNodeURI the URI of the node, this URI is used to provide the default
+ * host and port information for the runtime for situations when bindings
+ * do provide this information
+ * @param domainURI the URI of the domain that the node belongs to. This URI is
+ * used to locate the domain manager on the network
+ * @return a new SCA node.
+ */
+ public SCANode createSCANode(String physicalNodeURI, String domainURI) throws NodeException {
+ return new SCANodeImpl(physicalNodeURI, domainURI, null);
+ }
+
+ /**
+ * Creates a new SCA node. Many physical nodes may share the same logical URL in load balancing
+ * and failover scenarios where each node in the group runs the same contribution and
+ * active composites
+ *
+ * @param physicalNodeURI the URI of the node, this URI is used to provide the default
+ * host and port information for the runtime for situations when bindings
+ * don't provide this information
+ * @param domainURI the URI of the domain that the node belongs to. This URI is
+ * used to locate the domain manager on the network
+ * @param logicalNodeURI the URI of the node to be used in situations where more than one node
+ * are grouped together for failover or load balancing scenarios. The logicalNodeURI
+ * will typically identify the logical node where requests are sent
+ * @return a new SCA node.
+ */
+ public SCANode createSCANode(String physicalNodeURI, String domainURI, String logicalNodeURI) throws NodeException {
+ return new SCANodeImpl(physicalNodeURI, domainURI, logicalNodeURI);
+ }
+
+ /**
+ * Creates a new SCA node. Many physical nodes may share the same logical URL in load balancing
+ * and failover scenarios where each node in the group runs the same contribution and
+ * active composites. Also allows a class loaded to b specified. This is the
+ * ClassLoader that will be used to load the management application used by the
+ * node to talk to the domain
+ *
+ * @param physicalNodeURI the URI of the node, this URI is used to provide the default
+ * host and port information for the runtime for situations when bindings
+ * don't provide this information
+ * @param domainURI the URI of the domain that the node belongs to. This URI is
+ * used to locate the domain manager on the network
+ * @param logicalNodeURI the URI of the node to be used in situations where more than one node
+ * are grouped together for failover or load balancing scenarios. The logicalNodeURI
+ * will typically identify the logical node where requests are sent. If null is provided
+ * no logicalNodeURI is set.
+ * @param classLoader the class loader to use by default when loading contributions. If null is provided
+ * the ClassLoader the derived automatically.
+ * @return a new SCA node.
+ */
+ public SCANode createSCANode(String physicalNodeURI, String domainURI, String logicalNodeURI, ClassLoader classLoader) throws NodeException {
+ return new SCANodeImpl(physicalNodeURI, domainURI, logicalNodeURI, classLoader);
+ }
+
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java
new file mode 100644
index 0000000000..90ee2158f4
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java
@@ -0,0 +1,936 @@
+ /*
+ * 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.ByteArrayInputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+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 javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
+import org.apache.tuscany.sca.assembly.builder.DomainBuilder;
+import org.apache.tuscany.sca.assembly.xml.Constants;
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+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.databinding.impl.XSDDataTypeConverter.Base64Binary;
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime;
+import org.apache.tuscany.sca.host.http.ServletHost;
+import org.apache.tuscany.sca.host.http.ServletHostExtensionPoint;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.SCANode;
+import org.apache.tuscany.sca.node.spi.NodeFactoryImpl;
+import org.apache.tuscany.sca.node.spi.SCANodeSPI;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+
+/**
+ * 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, SCANodeSPI {
+
+ private static final 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 logicalNodeURI;
+ private String domainURI;
+
+ // 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 SCADomainProxyImpl scaDomain;
+
+ // the started status of the node
+ private boolean nodeStarted = false;
+
+ // 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 Map<String, Composite> compositeFiles = new HashMap<String, Composite>();
+
+ private QName nodeManagementCompositeName = new QName("http://tuscany.apache.org/xmlns/tuscany/1.0", "node");
+
+ // Used to pipe node information into the model
+ NodeFactoryImpl nodeFactory;
+
+ // domain level wiring
+ DomainBuilder domainBuilder;
+
+ // 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 physicalNodeURI - 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 domainURI - identifies what host and port the domain service is running on, e.g. http://localhost:8081
+ * @param logicalNodeURI the URI of the node group. This is the endpoint 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 physicalNodeURI, String domainURI, String logicalNodeURI) throws NodeException {
+ this.domainURI = domainURI;
+ this.nodeURI = physicalNodeURI;
+ this.logicalNodeURI = logicalNodeURI;
+ 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 physicalNodeURI - 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 domainURI - identifies what host and port the domain service is running on, e.g. http://localhost:8081
+ * @param logicalNodeURI the URI of the node group. This is the endpoint 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 physicalNodeURI, String domainURI, String logicalNodeURI, ClassLoader cl) throws NodeException {
+ this.domainURI = domainURI;
+ this.nodeURI = nodeURI;
+ this.logicalNodeURI = logicalNodeURI;
+ 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 the domain URI has been specified
+ * on construction
+ */
+ private void init() throws NodeException {
+ try {
+
+ // Generate a unique node URI
+ if (nodeURI == null) {
+
+ String host = InetAddress.getLocalHost().getHostName();
+ ServerSocket socket = new ServerSocket(0);
+ nodeURI = "http://" + host + ":" + socket.getLocalPort();
+ socket.close();
+ }
+
+ // check whether node URI is an absolute URL,
+ try {
+ URI tmpURI = new URI(nodeURI);
+ nodeURL = tmpURI.toURL();
+ } catch(Exception ex) {
+ throw new NodeException("node uri " +
+ nodeURI +
+ " must be a valid url");
+ }
+
+ // create a node runtime for the domain contributions to run on
+ nodeRuntime = new ReallySmallRuntime(nodeClassLoader);
+ nodeRuntime.start();
+
+ // get the domain builder
+ domainBuilder = nodeRuntime.getDomainBuilder();
+
+ // configure the default port and path for this runtime
+ int port = URI.create(nodeURI).getPort();
+ String path = nodeURL.getPath();
+ ServletHostExtensionPoint servletHosts = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class);
+ for (ServletHost servletHost: servletHosts.getServletHosts()) {
+ servletHost.setDefaultPort(port);
+ if (path != null && path.length() > 0 && !path.equals("/")) {
+ servletHost.setContextPath(path);
+ }
+ }
+
+ // make the node available to the model
+ // this causes the runtime to start registering binding-sca service endpoints
+ // with the domain proxy
+ // TODO - This code is due to be pulled out and combined with the register and
+ // resolution code that appears in this class
+ ModelFactoryExtensionPoint factories = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
+ nodeFactory = new NodeFactoryImpl(this);
+ factories.addFactory(nodeFactory);
+
+ // 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);
+
+ // create a link to the domain
+ scaDomain = new SCADomainProxyImpl(domainURI, nodeClassLoader);
+
+ // add the node URI to the domain
+ scaDomain.addNode(this);
+
+ } catch(NodeException ex) {
+ throw ex;
+ } catch(Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ // temp methods to help integrate with existing code
+
+ 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;
+ }
+
+ // SCANode SPI methods
+
+ public Object getNodeRuntime() {
+ return nodeRuntime;
+ }
+
+ public void startFromDomain() throws NodeException {
+ if (!nodeStarted){
+ startComposites();
+ nodeStarted = true;
+ }
+ }
+
+ public void stopFromDomain() throws NodeException {
+ if (nodeStarted){
+ stopComposites();
+ nodeStarted = false;
+ }
+ }
+
+ public void addContributionFromDomain(String contributionURI, URL contributionURL, ClassLoader contributionClassLoader ) throws NodeException {
+
+ if (nodeStarted){
+ throw new NodeException("Can't add contribution " + contributionURI + " when the node is running. Call stop() on the node first");
+ }
+
+ if (contributionURI == null){
+ throw new NodeException("Contribution URI cannot be null");
+ }
+
+ if (contributionURL == null){
+ throw new NodeException("Contribution URL cannot be null");
+ }
+
+ if (contributions.containsKey(contributionURI)) {
+ throw new NodeException("Contribution " + contributionURI + " has already been added");
+ }
+
+ try {
+
+ //FIXME What to do when a contribution uses a separate class loader ? (e.g contributionClassLoader != null)
+
+ // Add the contribution to the node
+ ContributionService contributionService = nodeRuntime.getContributionService();
+ Contribution contribution = contributionService.contribute(contributionURI,
+ contributionURL,
+ false);
+
+ // remember the contribution
+ contributions.put(contributionURI, contribution);
+
+ // remember all the composites that have been found
+ for (Artifact artifact : contribution.getArtifacts()) {
+ if (artifact.getModel() instanceof Composite) {
+ Composite composite = (Composite)artifact.getModel();
+ composites.put(composite.getName(), composite);
+ compositeFiles.put(composite.getURI(), composite);
+ }
+ }
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ public void removeContributionFromDomain(String contributionURI) throws NodeException {
+
+ if (nodeStarted){
+ throw new NodeException("Can't remove contribution " + contributionURI + " when the node is running. Call stop() on the node first");
+ }
+
+ if (contributionURI == null){
+ throw new NodeException("Contribution URI cannot be null");
+ }
+
+ if (!contributions.containsKey(contributionURI)) {
+ throw new NodeException("Contribution " + contributionURI + " has not been added");
+ }
+
+ try {
+
+ Contribution contribution = contributions.get(contributionURI);
+
+ // remove the local record of composites associated with this contribution
+ for (Artifact artifact : contribution.getArtifacts()) {
+ if (artifact.getModel() instanceof Composite) {
+ Composite composite = (Composite)artifact.getModel();
+ composites.remove(composite.getName());
+ compositeFiles.remove(composite.getURI());
+ }
+ }
+
+ // remove the contribution from the contribution service
+ nodeRuntime.getContributionService().remove(contributionURI);
+
+ // remove any deployed composites from the node level composite
+ for (Composite composite : contribution.getDeployables()) {
+ if (nodeComposite.getIncludes().contains(composite)){
+ // deactivate it
+ deactivateComposite(composite);
+
+ // remove it
+ nodeComposite.getIncludes().remove(composite);
+ }
+ }
+
+ // remove the local record of the contribution
+ contributions.remove(contributionURI);
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ public void addToDomainLevelCompositeFromDomain(QName compositeQName) throws NodeException {
+
+ if (nodeStarted){
+ throw new NodeException("Can't add composite " + compositeQName.toString() + " when the node is running. Call stop() on the node first");
+ }
+
+ Composite composite = composites.get(compositeQName);
+
+ if (composite == null) {
+ throw new NodeException("Composite " + compositeQName.toString() + " not found" );
+ }
+
+ // if the named composite is not already in the list then deploy it
+ if (!nodeComposite.getIncludes().contains(composite)) {
+ nodeComposite.getIncludes().add(composite);
+
+ try {
+ // build and activate the model for this composite
+ activateComposite(composite);
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+ }
+
+ // SCANode API methods
+
+ public void start() throws NodeException {
+ if (domainURI != null){
+ throw new NodeException("Node is part of domain " +
+ domainURI +
+ " so must be starterd from there");
+ } else {
+ startFromDomain();
+ }
+ }
+
+ public void stop() throws NodeException {
+ if (domainURI != null){
+ throw new NodeException("Node is part of domain " +
+ domainURI +
+ " so must be stopped from there");
+ } else {
+ stopFromDomain();
+ }
+ }
+
+ public void destroy() throws NodeException {
+ try {
+ stopFromDomain();
+
+ removeAllContributions();
+
+ // remove the node factory
+ ModelFactoryExtensionPoint factories = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
+ factories.removeFactory(nodeFactory);
+ nodeFactory.setNode(null);
+
+ // unregister the node
+ scaDomain.removeNode(this);
+
+ // node runtime is stopped by the domain proxy once it has
+ // removed the management components
+ scaDomain.destroy();
+
+ scaDomain = null;
+ nodeRuntime = null;
+ contributions = null;
+ composites = null;
+ compositeFiles = null;
+ } catch(NodeException ex) {
+ throw ex;
+ } 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 {
+ addContributionFromDomain(contributionURI, contributionURL, contributionClassLoader);
+
+ // add the contribution to the domain.
+ scaDomain.registerContribution(nodeURI, contributionURI, contributionURL.toExternalForm());
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ public void removeContribution(String contributionURI) throws NodeException {
+
+ try {
+ removeContributionFromDomain(contributionURI);
+
+ // remove the contribution from the domain.
+ scaDomain.unregisterContribution(nodeURI, contributionURI);
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ private void removeAllContributions() throws NodeException {
+ try {
+ // copy the keys so we don't get a concurrency error
+ List<String> keys = new ArrayList<String>();
+
+ for (String contributionURI : contributions.keySet()){
+ keys.add(contributionURI);
+ }
+
+ // Remove all contributions
+ for (String contributionURI : keys){
+ removeContribution(contributionURI);
+ }
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ private boolean isDeployable(Composite composite){
+ boolean deployable = false;
+
+ for (Contribution contribution : contributions.values()){
+ if (contribution.getDeployables().contains(composite)) {
+ deployable = true;
+ break;
+ }
+ }
+
+ return deployable;
+ }
+
+ public void addToDomainLevelComposite(QName compositeQName) throws NodeException {
+
+ if (nodeStarted){
+ throw new NodeException("Can't add composite " + compositeQName.toString() + " when the node is running. Call stop() on the node first");
+ }
+
+ // if no composite name is specified add all deployable composites
+ // to the domain
+ if (compositeQName == null){
+ for (Composite composite : composites.values()) {
+ if (!nodeComposite.getIncludes().contains(composite)) {
+ nodeComposite.getIncludes().add(composite);
+
+ try {
+ // build and activate the model for this composite
+ activateComposite(composite);
+
+ // register the composite with the domain
+ scaDomain.registerDomainLevelComposite(nodeURI, composite.getName().toString());
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+
+ }
+ }
+ } else {
+ Composite composite = composites.get(compositeQName);
+
+ if (composite == null) {
+ throw new NodeException("Composite " + compositeQName.toString() + " not found" );
+ }
+
+ // if the named composite is not already in the list then deploy it
+ if (!nodeComposite.getIncludes().contains(composite)) {
+ nodeComposite.getIncludes().add(composite);
+
+ try {
+ // build and activate the model for this composite
+ activateComposite(composite);
+
+ // register the composite with the domain
+ scaDomain.registerDomainLevelComposite(nodeURI, composite.getName().toString());
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+ }
+
+ }
+
+ public void addToDomainLevelComposite(String compositePath) throws NodeException {
+
+ if (compositePath == null){
+ addToDomainLevelComposite((QName)null);
+ } else {
+ Composite composite = compositeFiles.get(compositePath);
+
+ if (composite != null){
+ addToDomainLevelComposite(composite.getName());
+ } else {
+ throw new NodeException("Composite " + compositePath + " not found" );
+ }
+ }
+ }
+ public ContributionService getContributionService()
+ {
+ return nodeRuntime.getContributionService();
+ }
+ /* TODO - giorgio: These are just little steps to support contribution-updater,
+ *
+ * in order to have more fine grain on updating stuffs.
+ public void addComponentToComposite(MetaComponent mc, String contributionURI, String compositeURI)
+ {
+ }
+ public void removeComponentFromComposite(String nodeName, String compositeURI,String componentName)
+ {
+ }
+ */
+ private void activateComposite(Composite composite) throws CompositeBuilderException, ActivationException {
+ logger.log(Level.INFO, "Building composite: " + composite.getName());
+
+ // Create the model for the composite
+ nodeRuntime.getCompositeBuilder().build(composite);
+
+ // activate the composite
+ nodeRuntime.getCompositeActivator().activate(composite);
+
+ // tell the domain where all the service endpoints are
+ registerRemoteServices(nodeURI, composite);
+ }
+
+ private void deactivateComposite(Composite composite) throws CompositeBuilderException, ActivationException {
+ nodeRuntime.getCompositeActivator().deactivate(composite);
+
+ // no deregistering of endpoints as endpoint handling is going to have to change
+ }
+
+
+ /**
+ * Configure the default HTTP port for this node.
+ * The motivation here is to set the default binding on the Servlet container
+ * based on whatever information is available. In particular if no Node URL is
+ * provided then one of the ports from the first composite is used so that
+ * some recognizable default is provided for any bindings that are specified
+ * without URIs
+ */
+ private void configureDefaultPort() {
+ if (composites.size() == 0){
+ return;
+ }
+
+ Composite composite = nodeComposite.getIncludes().get(1);
+
+ if (composite == null) {
+ return;
+ }
+
+ int port = -1;
+ for (Service service: composite.getServices()) {
+ for (Binding binding: service.getBindings()) {
+ String uri = binding.getURI();
+ if (uri != null) {
+ port = URI.create(uri).getPort();
+ if (port != -1) {
+ break;
+ }
+ }
+ }
+ if (port != -1) {
+ break;
+ }
+ }
+ for (Component component: composite.getComponents()) {
+ for (ComponentService service: component.getServices()) {
+ for (Binding binding: service.getBindings()) {
+ String uri = binding.getURI();
+ if (uri != null) {
+ port = URI.create(uri).getPort();
+ if (port != -1) {
+ break;
+ }
+ }
+ }
+ if (port != -1) {
+ break;
+ }
+ }
+ if (port != -1) {
+ break;
+ }
+ }
+
+ // Then get the port from the node URI
+ if (port == -1) {
+ port = URI.create(nodeURI).getPort();
+ }
+
+ // Configure the default port
+ if (port != -1) {
+ ServletHostExtensionPoint servletHosts = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class);
+ for (ServletHost servletHost: servletHosts.getServletHosts()) {
+ servletHost.setDefaultPort(port);
+ }
+ }
+ }
+
+ private void startComposites() throws NodeException {
+ try {
+ if (nodeComposite.getIncludes().size() == 0 ){
+ logger.log(Level.INFO, nodeURI +
+ " has no composites to start" );
+ } else {
+/* TODO - moved build/activate back to the point where the
+ * composite is added. What should I do about this default port business.
+ * I think that needs to be consumed by the domain model anyhow
+ // Configure the default server port for the node
+ configureDefaultPort();
+*/
+
+ // do cross composite wiring. This is here just in case
+ // the node has more than one composite and is stand alone
+ // If the node is not stand alone the domain will do this
+ if (domainURI == null){
+ domainBuilder.wireDomain(nodeComposite);
+ }
+
+ for (Composite composite : nodeComposite.getIncludes()) {
+ // don't try and restart the management composite
+ // they will already have been started by the domain proxy
+ if (!composite.getName().equals(nodeManagementCompositeName)){
+ startComposite(composite);
+ }
+ }
+ }
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ private void startComposite(Composite composite) throws CompositeBuilderException, ActivationException {
+ logger.log(Level.INFO, "Starting composite: " + composite.getName());
+
+ //start the composite
+ nodeRuntime.getCompositeActivator().start(composite);
+ }
+
+ private void stopComposites() throws NodeException {
+
+ try {
+
+ for (Composite composite : nodeComposite.getIncludes()) {
+ // don't try and stop the management composite
+ // if we do that we can't manage the node
+ if (!composite.getName().equals(nodeManagementCompositeName)){
+ stopComposite(composite);
+ }
+ }
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+ }
+
+ private void stopComposite(Composite composite)
+ throws ActivationException {
+ logger.log(Level.INFO, "Stopping composite: " + composite.getName());
+ nodeRuntime.getCompositeActivator().stop(composite);
+ }
+
+ private void registerRemoteServices(String nodeURI, Composite composite){
+ // Loop through all service binding URIs registering them with the domain
+ for (Service service: composite.getServices()) {
+ for (Binding binding: service.getBindings()) {
+ registerRemoteServiceBinding(nodeURI, null, service, binding);
+ }
+ }
+
+ for (Component component: composite.getComponents()) {
+ for (ComponentService service: component.getServices()) {
+ for (Binding binding: service.getBindings()) {
+ registerRemoteServiceBinding(nodeURI, component, service, binding);
+ }
+ }
+ }
+ }
+
+ private void registerRemoteServiceBinding(String nodeURI, Component component, Service service, Binding binding ){
+ if (service.getInterfaceContract().getInterface().isRemotable()) {
+ String uriString = binding.getURI();
+ if (uriString != null) {
+
+
+ String serviceName = service.getName();
+
+ if (component != null){
+ serviceName = component.getName() + '/' + serviceName;
+ }
+
+ try {
+ scaDomain.registerServiceEndpoint(domainURI,
+ nodeURI,
+ serviceName,
+ binding.getClass().getName(),
+ uriString);
+ } catch(Exception ex) {
+ logger.log(Level.WARNING,
+ "Unable to register service: " +
+ domainURI + " " +
+ nodeURI + " " +
+ service.getName()+ " " +
+ binding.getClass().getName() + " " +
+ uriString);
+ }
+ }
+ }
+ }
+
+ public void updateComposite(QName compositeQName, String compositeXMLBase64 ) throws NodeException {
+ logger.log(Level.INFO, "Updating composite " + compositeQName.toString() +
+ " at node " + nodeURI);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(Base64Binary.decode(compositeXMLBase64));
+
+ // find the composite that will be updated
+ Composite composite = composites.get(compositeQName);
+
+ if (composite == null) {
+ throw new NodeException("trying to update composite " + compositeQName.toString() +
+ " which can't be found in node " + nodeURI);
+ }
+
+ // parse the XML into an composite object
+ Composite newComposite = null;
+
+ ExtensionPointRegistry registry = nodeRuntime.getExtensionPointRegistry();
+ StAXArtifactProcessorExtensionPoint staxProcessors =
+ registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+
+ StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class);
+
+ try {
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(bais);
+ newComposite = processor.read(reader);
+ reader.close();
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+
+
+ // for each component in the composite compare it against the live component
+ for (Component newComponent : newComposite.getComponents()){
+ for (Component component : composite.getComponents()){
+ if (component.getName().equals(newComponent.getName())){
+ // compare the component references
+ for (Reference newReference : newComponent.getReferences()){
+ for (Reference reference : component.getReferences()) {
+ if (reference.getName().equals(newReference.getName())) {
+ boolean referenceChanged = false;
+ List<Binding> removeCandidates = new ArrayList<Binding>();
+ List<Binding> addCandidates = new ArrayList<Binding>();
+
+ removeCandidates.addAll(reference.getBindings());
+
+ for (Binding newBinding : newReference.getBindings()){
+ boolean bindingFound = false;
+ for (Binding binding : reference.getBindings()){
+ // find the matching target service binding
+ if (binding.getName().equals(newBinding.getName())){
+ if ((binding.getURI() != null) &&
+ (newBinding.getURI() != null) &&
+ !binding.getURI().equals(newBinding.getURI())){
+ binding.setURI(newBinding.getURI());
+ referenceChanged = true;
+
+ logger.log(Level.INFO, "Updating binding " +
+ component.getName() +
+ " reference " +
+ reference.getName() +
+ " binding " +
+ binding.getClass().getName() +
+ " URI " +
+ binding.getURI());
+ }
+ bindingFound = true;
+ removeCandidates.remove(binding);
+ }
+ }
+
+ if (bindingFound == false){
+ addCandidates.add(newBinding);
+ }
+
+ }
+
+ for (Binding addBinding : addCandidates){
+ reference.getBindings().add(addBinding);
+ referenceChanged = true;
+ logger.log(Level.INFO, "Adding binding " +
+ component.getName() +
+ " reference " +
+ reference.getName() +
+ " binding " +
+ addBinding.getClass().getName() +
+ " URI " +
+ addBinding.getURI());
+ }
+
+ // remove all of the old bindings
+ for (Binding removeBinding : removeCandidates){
+ reference.getBindings().remove(removeBinding);
+ referenceChanged = true;
+ logger.log(Level.INFO, "Removing binding " +
+ component.getName() +
+ " reference " +
+ reference.getName() +
+ " binding " +
+ removeBinding.getClass().getName() +
+ " URI " +
+ removeBinding.getURI());
+ }
+
+ // if the node is running restart the reference and the component that holds it
+ if (referenceChanged && nodeStarted){
+ try {
+ nodeRuntime.getCompositeActivator().stop((RuntimeComponent)component);
+ nodeRuntime.getCompositeActivator().deactivate((RuntimeComponent)component,
+ (RuntimeComponentReference)reference);
+ nodeRuntime.getCompositeActivator().start((RuntimeComponent)component,
+ (RuntimeComponentReference)reference);
+ nodeRuntime.getCompositeActivator().start((RuntimeComponent)component);
+
+ } catch (Exception ex) {
+ throw new NodeException(ex);
+ }
+
+ }
+ }
+ }
+ }
+
+ // TODO - compare other parts of the component
+ }
+ }
+ }
+
+ // TODO - Compare other parts of the composite?
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java
new file mode 100644
index 0000000000..b4a42dd896
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java
@@ -0,0 +1,311 @@
+/*
+ * 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.logging.Logger;
+
+
+/**
+ * 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 static final 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, IOException {
+
+ 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, IOException {
+
+ 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) throws IOException
+ {
+ ServerSocket socket = new ServerSocket(0);
+ int port = socket.getLocalPort();
+ socket.close();
+ return port;
+ }
+*/
+
+ /**
+ * 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/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/launch/SCANodeLauncher.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/launch/SCANodeLauncher.java
new file mode 100644
index 0000000000..63f5cc87fb
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/launch/SCANodeLauncher.java
@@ -0,0 +1,79 @@
+/*
+ * 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.launch;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.tuscany.sca.node.SCANode;
+import org.apache.tuscany.sca.node.SCANodeFactory;
+import org.apache.tuscany.sca.node.util.SCAContributionUtil;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class SCANodeLauncher {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ System.out.println("Tuscany starting...");
+
+ SCANode node = null;
+ try {
+ String compositeFile = args[0];
+ System.out.println("Composite: " + compositeFile);
+
+ SCANodeFactory nodeFactory = SCANodeFactory.newInstance();
+ node = nodeFactory.createSCANode(null, "http://localhost:9999");
+
+ ClassLoader classLoader = SCANodeLauncher.class.getClassLoader();
+ URL contribution = SCAContributionUtil.findContributionFromResource(classLoader, compositeFile);
+ node.addContribution(compositeFile, contribution);
+
+ node.addToDomainLevelComposite(compositeFile);
+
+ node.start();
+
+ } catch (Exception e) {
+ System.err.println("Exception starting node");
+ e.printStackTrace();
+ System.exit(0);
+ }
+
+ System.out.println("Node ready...");
+ System.out.println("Press enter to shutdown");
+ try {
+ System.in.read();
+ } catch (IOException e) {
+ }
+
+ try {
+ node.destroy();
+ } catch (Exception e) {
+ System.err.println("Exception stopping node");
+ e.printStackTrace();
+ }
+
+ System.exit(0);
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/management/impl/SCANodeManagerServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/management/impl/SCANodeManagerServiceImpl.java
new file mode 100644
index 0000000000..7b49166acf
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/management/impl/SCANodeManagerServiceImpl.java
@@ -0,0 +1,122 @@
+/*
+ * 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.management.impl;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.SCANode;
+import org.apache.tuscany.sca.node.impl.ComponentInfoImpl;
+import org.apache.tuscany.sca.node.impl.SCANodeImpl;
+import org.apache.tuscany.sca.node.management.SCANodeManagerInitService;
+import org.apache.tuscany.sca.node.management.SCANodeManagerService;
+import org.apache.tuscany.sca.node.spi.ComponentInfo;
+import org.apache.tuscany.sca.node.spi.ComponentManagerService;
+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 = {SCANodeManagerService.class, SCANodeManagerInitService.class, ComponentManagerService.class})
+public class SCANodeManagerServiceImpl implements SCANodeManagerService, SCANodeManagerInitService, ComponentManagerService {
+
+ private static final Logger logger = Logger.getLogger(SCANodeManagerServiceImpl.class.getName());
+
+ private SCANodeImpl node;
+
+
+ // NodeManagerInitService
+
+ public void setNode(SCANode node) {
+ this.node = (SCANodeImpl)node;
+ }
+
+ // SCANodeManagerService methods
+
+ public String getURI() {
+ return node.getURI();
+ }
+
+ public void addContribution(String contributionURI, String contributionURL) throws NodeException {
+ try {
+ node.addContributionFromDomain(contributionURI, new URL(contributionURL), null);
+ } catch (MalformedURLException ex){
+ throw new NodeException(ex);
+ }
+ }
+
+ public void removeContribution(String contributionURI) throws NodeException {
+ node.removeContributionFromDomain(contributionURI);
+ }
+
+ public void addToDomainLevelComposite(String compositeName) throws NodeException {
+ node.addToDomainLevelCompositeFromDomain(QName.valueOf(compositeName));
+ }
+
+ public void start() throws NodeException {
+ node.startFromDomain();
+ }
+
+ public void stop() throws NodeException {
+ node.stopFromDomain();
+ }
+
+ public void destroyNode() {
+ // do nothing - the domain can't destroy nodes
+ }
+
+ public void updateComposite(String compositeQName, String compositeXMLBase64 ) throws NodeException {
+ ((SCANodeImpl)node).updateComposite(QName.valueOf(compositeQName), compositeXMLBase64 );
+ }
+
+ // 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/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/node.composite b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/node.composite
new file mode 100644
index 0000000000..bbf3b98d27
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/node.composite
@@ -0,0 +1,79 @@
+<?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 here are expected to be here
+ so 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://tuscany.apache.org/xmlns/tuscany/1.0"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"
+ name="node">
+
+ <component name="SCADomainEventServiceProxyComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.impl.SCADomainEventServiceProxyImpl"/>
+ <service name="SCADomainEventService">
+ <interface.java interface="org.apache.tuscany.sca.domain.spi.SCADomainEventService"/>
+ <binding.sca/>
+ </service>
+ <reference name="domainManager">
+ <interface.java interface="org.apache.tuscany.sca.domain.spi.SCADomainEventService"/>
+ <binding.ws uri="http://localhost:9999/SCADomainManagerComponent/SCADomainEventService"/>
+ </reference>
+ </component>
+
+ <component name="SCADomainAPIServiceProxyComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.impl.SCADomainAPIServiceProxyImpl"/>
+ <service name="SCADomainAPIService">
+ <interface.java interface="org.apache.tuscany.sca.domain.spi.SCADomainAPIService"/>
+ <binding.sca/>
+ </service>
+ <reference name="domainManager">
+ <interface.java interface="org.apache.tuscany.sca.domain.spi.SCADomainAPIService"/>
+ <binding.ws uri="http://localhost:9999/SCADomainManagerComponent/SCADomainAPIService"/>
+ </reference>
+ </component>
+
+ <component name="SCANodeManagerComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.management.impl.SCANodeManagerServiceImpl"/>
+ <service name="SCANodeManagerInitService">
+ <interface.java interface="org.apache.tuscany.sca.node.management.SCANodeManagerInitService"/>
+ <binding.sca/>
+ </service>
+ <service name="SCANodeManagerService">
+ <interface.java interface="org.apache.tuscany.sca.node.management.SCANodeManagerService"/>
+ <binding.ws/>
+ </service>
+ <service name="ComponentManagerService">
+ <interface.java interface="org.apache.tuscany.sca.node.spi.ComponentManagerService"/>
+ <t:binding.jsonrpc/>
+ </service>
+ </component>
+
+ <!--component name="node">
+ <t:implementation.resource location="webroot"/>
+ <service name="Resource">
+ <t:binding.http/>
+ </service>
+ </component-->
+
+</composite>
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/index.html b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/index.html
new file mode 100644
index 0000000000..e53f353b53
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/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").Service;
+ componentManager = new JSONRpcClient("../NodeManagerComponent/ComponentManagerJson").Service;
+
+ function getNodeUri() {
+ nodeManager.getNodeUri(handleGetNodeUri);
+ getComponentInfos()
+ }
+
+ function handleGetNodeUri(result) {
+ document.getElementById('nodeUri').innerHTML=result;
+ }
+
+ function getComponentInfos() {
+ componentManager.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/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/node.png b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/node.png
new file mode 100644
index 0000000000..fa01e64272
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/node.png
Binary files differ
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/style.css b/sandbox/sebastien/java/sca-node/modules/node-impl/src/main/resources/webroot/style.css
new file mode 100644
index 0000000000..28a4d4540c
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddService.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddService.java
new file mode 100644
index 0000000000..1c115bb92d
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddService.java
@@ -0,0 +1,33 @@
+/*
+ * 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
+ *
+ * @version $Rev$ $Date$
+ */
+@Remotable
+public interface AddService {
+
+ double add(double n1, double n2);
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceImpl.java
new file mode 100644
index 0000000000..f52e42f497
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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
+ *
+ * @version $Rev$ $Date$
+ */
+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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceUpdateImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceUpdateImpl.java
new file mode 100644
index 0000000000..0d5d8a602c
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/AddServiceUpdateImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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
+ *
+ * @version $Rev$ $Date$
+ */
+public class AddServiceUpdateImpl implements AddService {
+
+ public double add(double n1, double n2) {
+ System.out.println("AddService Update - add " + n1 + " and " + n2);
+ return n1 + n2;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorService.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorService.java
new file mode 100644
index 0000000000..e838b65b8c
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ * @version $Rev$ $Date$
+ */
+@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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java
new file mode 100644
index 0000000000..4f11e02e0d
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/CalculatorServiceImpl.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ *
+ * @version $Rev$ $Date$
+ */
+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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideService.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideService.java
new file mode 100644
index 0000000000..3373eb2c7a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideService.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;
+
+/**
+ * The divide service interface
+ *
+ * @version $Rev$ $Date$
+ */
+public interface DivideService {
+
+ double divide(double n1, double n2);
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java
new file mode 100644
index 0000000000..0421c217e0
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/DivideServiceImpl.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DivideServiceImpl implements DivideService {
+
+ public double divide(double n1, double n2) {
+ return n1 / n2;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyService.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyService.java
new file mode 100644
index 0000000000..783a7eccd6
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyService.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;
+
+/**
+ * The interface for the multiply service
+ *
+ * @version $Rev$ $Date$
+ */
+public interface MultiplyService {
+
+ double multiply(double n1, double n2);
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java
new file mode 100644
index 0000000000..f93e614a08
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/MultiplyServiceImpl.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MultiplyServiceImpl implements MultiplyService {
+
+ public double multiply(double n1, double n2) {
+ return n1 * n2;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractService.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractService.java
new file mode 100644
index 0000000000..eb32e26896
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractService.java
@@ -0,0 +1,33 @@
+/*
+ * 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
+ *
+ * @version $Rev$ $Date$
+ */
+@Remotable
+public interface SubtractService {
+
+ double subtract(double n1, double n2);
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java
new file mode 100644
index 0000000000..c9e2f2e314
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/calculator/SubtractServiceImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+ * @version $Rev$ $Date$
+ */
+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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCaseOFF.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCaseOFF.java
new file mode 100644
index 0000000000..498d1a27e7
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/DomainDrivenTestCaseOFF.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.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
+ *
+ * @version $Rev$ $Date$
+ */
+public class DomainDrivenTestCaseOFF {
+
+ 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("http://localhost:9999");
+
+ System.out.println("Setting up calculator nodes");
+
+ ClassLoader cl = DomainDrivenTestCaseOFF.class.getClassLoader();
+
+ SCANodeFactory nodeFactory = SCANodeFactory.newInstance();
+
+ nodeA = nodeFactory.createSCANode("http://localhost:8100/nodeA", "http://localhost:9999");
+ nodeB = nodeFactory.createSCANode("http://localhost:8200/nodeB", "http://localhost:9999");
+ nodeC = nodeFactory.createSCANode("http://localhost:8300/nodeC", "http://localhost:9999");
+
+ domain.addContribution("nodeA", cl.getResource("nodeA/"));
+ domain.addContribution("nodeB", cl.getResource("nodeB/"));
+ domain.addContribution("nodeC", cl.getResource("nodeC/"));
+
+ domain.addToDomainLevelComposite(new QName("http://sample", "CalculatorA"));
+ domain.addToDomainLevelComposite(new QName("http://sample", "CalculatorB"));
+ domain.addToDomainLevelComposite(new QName("http://sample", "CalculatorC"));
+
+ domain.start();
+
+ calculatorServiceA = domain.getService(CalculatorService.class, "CalculatorServiceComponentA");
+ calculatorServiceB = domain.getService(CalculatorService.class, "CalculatorServiceComponentB");
+
+ } catch(Exception ex){
+ ex.printStackTrace();
+ }
+
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ // stop the domain
+ domain.stop();
+
+ // destroy the nodes
+ nodeA.destroy();
+ nodeB.destroy();
+ nodeC.destroy();
+
+ // destroy the domain
+ domain.destroy();
+ }
+
+ //@Test
+ public void testKeepServerRunning() throws Exception {
+ System.out.println("press enter to continue");
+ System.in.read();
+ }
+
+ @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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCaseOFF.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCaseOFF.java
new file mode 100644
index 0000000000..1c1230db80
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeDrivenTestCaseOFF.java
@@ -0,0 +1,162 @@
+/*
+ * 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
+ *
+ * @version $Rev$ $Date$
+ */
+public class NodeDrivenTestCaseOFF {
+
+ 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 addServiceBDomainFinder;
+ private static AddService addServiceBDomainProxy;
+ private static AddService addServiceBDomain;
+
+ @BeforeClass
+ public static void init() throws Exception {
+
+ try {
+ System.out.println("Setting up domain");
+
+ SCADomainFactory domainFactory = SCADomainFactory.newInstance();
+ domain= domainFactory.createSCADomain("http://localhost:9999");
+
+ System.out.println("Setting up calculator nodes");
+
+ ClassLoader cl = NodeDrivenTestCaseOFF.class.getClassLoader();
+
+ SCANodeFactory nodeFactory = SCANodeFactory.newInstance();
+
+ // sca-contribution.xml test
+ nodeA = nodeFactory.createSCANode("http://localhost:8100/nodeA", "http://localhost:9999");
+ nodeA.addContribution("nodeA", cl.getResource("nodeA/"));
+ nodeA.addToDomainLevelComposite(new QName("http://sample", "CalculatorA"));
+
+ // sca-deployables test
+ nodeB = nodeFactory.createSCANode("http://localhost:8200/nodeB", "http://localhost:9999");
+ nodeB.addContribution("nodeB", cl.getResource("nodeB/"));
+ nodeB.addToDomainLevelComposite(new QName("http://sample", "CalculatorB"));
+
+ // sca-deployables test
+ nodeC = nodeFactory.createSCANode("http://localhost:8300/nodeC", "http://localhost:9999");
+ nodeC.addContribution("nodeC", cl.getResource("nodeC/"));
+ nodeC.addToDomainLevelComposite(new QName("http://sample", "CalculatorC"));
+ nodeC.addToDomainLevelComposite(new QName("http://sample", "CalculatorC"));
+
+ // start the domain
+ domain.start();
+
+ } catch(Exception ex){
+ ex.printStackTrace();
+ }
+
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ // stop the domain
+ domain.stop();
+
+ // destroy the nodes
+ nodeA.destroy();
+ nodeB.destroy();
+ nodeC.destroy();
+
+ // destroy the domain
+ domain.destroy();
+ }
+
+ //@Test
+ public void testKeepServerRunning() throws Exception {
+ System.out.println("press enter to continue");
+ System.in.read();
+ }
+
+ @Test
+ public void testDomainProxyNode() throws Exception {
+ // the domain proxy associated with each node used to get local services
+ calculatorServiceA = nodeA.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentA");
+ calculatorServiceB = nodeB.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentB");
+
+ // 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);
+
+ // the domain proxy associate with each node used to get remote services
+ addServiceBDomainProxy = nodeA.getDomain().getService(AddService.class, "AddServiceComponentB");
+
+ Assert.assertEquals(addServiceBDomainProxy.add(3, 2), 5.0);
+ }
+
+ @Test
+ public void testDomain() throws Exception {
+ // the domain itself
+ addServiceBDomain = domain.getService(AddService.class, "AddServiceComponentB");
+
+ System.out.println(((SCADomainProxyImpl)nodeA.getDomain()).getComposite(new QName("http://sample", "CalculatorA")));
+
+ Assert.assertEquals(addServiceBDomain.add(3, 2), 5.0);
+ }
+
+ @Test
+ public void testDomainProxyFinder() throws Exception {
+ // the domain proxy retrieved via the domain finder
+ SCADomainFinder domainFinder = SCADomainFinder.newInstance();
+ domainProxy = domainFinder.getSCADomain("http://localhost:9999");
+ addServiceBDomainFinder = domainProxy.getService(AddService.class, "AddServiceComponentB");
+
+ Assert.assertEquals(addServiceBDomainFinder.add(3, 2), 5.0);
+
+ System.out.println(domainProxy.getDomainLevelComposite());
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeMemoryTestCaseOFF.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeMemoryTestCaseOFF.java
new file mode 100644
index 0000000000..c20d49a0ae
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeMemoryTestCaseOFF.java
@@ -0,0 +1,81 @@
+/*
+ * 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.node.SCANode;
+import org.apache.tuscany.sca.node.SCANodeFactory;
+import org.junit.Test;
+
+import calculator.CalculatorService;
+import calculator.SubtractService;
+
+/**
+ * Runs a distributed domain in a single VM by using and in memory
+ * implementation of the distributed domain. The test repeatedly
+ * creates and destroys the node to see if memory is being leaked.
+ * Looking for leaked memory is a manual task.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NodeMemoryTestCaseOFF {
+
+ @Test
+ public void testDoNothing() throws Exception {
+
+ }
+
+ //@Test
+ public void testNodeMemoryUseage() throws Exception {
+
+ ClassLoader cl = NodeMemoryTestCaseOFF.class.getClassLoader();
+ SCANodeFactory nodeFactory;
+ SCANode node;
+ CalculatorService calculatorServiceB;
+ SubtractService subtractServiceC;
+
+ for(int i=0; i < 40; i++) {
+
+ nodeFactory = SCANodeFactory.newInstance();
+ node = nodeFactory.createSCANode("http://localhost:8200/node", null);
+ node.addContribution("nodeB", cl.getResource("nodeB/"));
+ node.addContribution("nodeC", cl.getResource("nodeC/"));
+ node.addToDomainLevelComposite(new QName("http://sample", "CalculatorB"));
+ node.addToDomainLevelComposite(new QName("http://sample", "CalculatorC"));
+ node.start();
+
+ calculatorServiceB = node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentB");
+ subtractServiceC = node.getDomain().getService(SubtractService.class, "SubtractServiceComponentC");
+
+ for(int j=0; j < 20; j++){
+ Assert.assertEquals(calculatorServiceB.subtract(3, 2), 1.0);
+ Assert.assertEquals(subtractServiceC.subtract(3, 2), 1.0);
+ }
+
+ node.destroy();
+ }
+
+ //com.ibm.jvm.Dump.HeapDump();
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/StandaloneNodeTestCaseOFF.java b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/StandaloneNodeTestCaseOFF.java
new file mode 100644
index 0000000000..2f06ffa732
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/StandaloneNodeTestCaseOFF.java
@@ -0,0 +1,205 @@
+/*
+ * 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.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;
+import calculator.SubtractService;
+
+/**
+ * Runs a distributed domain in a single VM by using and in memory
+ * implementation of the distributed domain
+ *
+ * @version $Rev$ $Date$
+ */
+public class StandaloneNodeTestCaseOFF {
+
+ private static SCANodeFactory nodeFactory;
+ private static SCANode node;
+ private static CalculatorService calculatorServiceA;
+ private static CalculatorService calculatorServiceB;
+ private static CalculatorService calculatorServiceD;
+ private static AddService addServiceD;
+ private static SubtractService subtractServiceC;
+ private static ClassLoader cl;
+
+
+ @BeforeClass
+ public static void init() throws Exception {
+
+ try {
+ System.out.println("Setting up add node");
+
+ cl = StandaloneNodeTestCaseOFF.class.getClassLoader();
+ nodeFactory = SCANodeFactory.newInstance();
+
+ } catch(Exception ex){
+ System.err.println(ex.toString());
+ }
+
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ // stop the node
+ node.destroy();
+ }
+
+
+ @Test
+ public void testAddContributionAndStartNode() throws Exception {
+ node = nodeFactory.createSCANode("http://localhost:8100/node", null);
+ node.addContribution("nodeC", cl.getResource("nodeC/"));
+ node.addToDomainLevelComposite(new QName("http://sample", "CalculatorC"));
+ node.start();
+
+ // get a reference to various services in the node
+ subtractServiceC = node.getDomain().getService(SubtractService.class, "SubtractServiceComponentC");
+ }
+
+ @Test
+ public void testSubtract() throws Exception {
+ Assert.assertEquals(subtractServiceC.subtract(3, 2), 1.0);
+ }
+
+ //@Test
+ public void testKeepServerRunning1() throws Exception {
+ System.out.println("press enter to continue");
+ System.in.read();
+ }
+
+ @Test
+ public void testStopNode() throws Exception {
+ node.stop();
+ try {
+ subtractServiceC.subtract(3, 2);
+// TODO - stopping the node doesn't actually stop the local wires?
+// Assert.fail();
+ } catch (Exception ex) {
+ // System.out.println(ex.toString());
+ }
+ }
+
+ @Test
+ public void testAddOtherContributionsAndStartNode() throws Exception {
+ node.addContribution("nodeB", cl.getResource("nodeB/"));
+ node.addToDomainLevelComposite(new QName("http://sample", "CalculatorB"));
+ node.addContribution("nodeD", cl.getResource("nodeD/"));
+ node.addToDomainLevelComposite(new QName("http://sample", "CalculatorD"));
+ node.start();
+ subtractServiceC = node.getDomain().getService(SubtractService.class, "SubtractServiceComponentC");
+ calculatorServiceD = node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentD");
+ calculatorServiceB = node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentB");
+ addServiceD = node.getDomain().getService(AddService.class, "AddServiceComponentD");
+
+ }
+
+ //@Test
+ public void testKeepServerRunning2() throws Exception {
+ System.out.println("press enter to continue");
+ System.in.read();
+ }
+
+ @Test
+ public void testCalculate() throws Exception {
+ // Calculate
+ 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(calculatorServiceD.add(3, 2), 5.0);
+ Assert.assertEquals(calculatorServiceD.subtract(3, 2), 1.0);
+ Assert.assertEquals(calculatorServiceD.multiply(3, 2), 6.0);
+ Assert.assertEquals(calculatorServiceD.divide(3, 2), 1.5);
+ Assert.assertEquals(addServiceD.add(3, 2), 5.0);
+ Assert.assertEquals(subtractServiceC.subtract(3, 2), 1.0);
+
+ }
+
+ @Test
+ public void testRemoveContribution() throws Exception {
+ node.stop();
+ node.removeContribution("nodeD");
+
+ try {
+ calculatorServiceD.add(3, 2);
+ Assert.fail();
+ } catch (Exception ex) {
+ // System.out.println(ex.toString());
+ }
+
+ calculatorServiceD = node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentD");
+
+ try {
+ Assert.assertEquals(calculatorServiceD.add(3, 2), 5.0);
+ Assert.fail();
+ } catch (Exception ex) {
+ // System.out.println(ex.toString());
+ }
+
+ }
+
+ @Test
+ public void testAddContributionBackAgain() throws Exception {
+
+ node.addContribution("nodeD", cl.getResource("nodeD/"));
+ node.addToDomainLevelComposite(new QName("http://sample", "CalculatorD"));
+ node.start();
+
+ calculatorServiceD = node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentD");
+
+ Assert.assertEquals(calculatorServiceD.add(3, 2), 5.0);
+
+ // stop and remove all the contributions to date
+ node.stop();
+ node.removeContribution("nodeB");
+ node.removeContribution("nodeC");
+ node.removeContribution("nodeD");
+ }
+
+ @Test
+ public void testAddDepdendentContributions() throws Exception {
+ node = nodeFactory.createSCANode("http://localhost:8200/node", null);
+
+ // add one contribution that depends on another
+ node.addContribution("dependent", cl.getResource("calculatordependent/"));
+ node.addContribution("primary", cl.getResource("calculatorprimary/"));
+ node.addToDomainLevelComposite(new QName("http://primary", "CalculatorA"));
+ node.start();
+ calculatorServiceA = node.getDomain().getService(CalculatorService.class, "CalculatorServiceComponentA");
+ 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);
+ }
+
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/Calculator.composite
new file mode 100644
index 0000000000..538ad2e4c8
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/Calculator.composite
@@ -0,0 +1,33 @@
+<?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://dependent"
+ xmlns:dependent="http://dependent"
+ name="CalculatorB">
+
+ <component name="AddServiceComponentB">
+ <implementation.java class="calculator.AddServiceImpl" />
+ </component>
+
+ <component name="SubtractServiceComponentB">
+ <implementation.java class="calculator.SubtractServiceImpl" />
+ </component>
+
+</composite>
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/META-INF/sca-contribution.xml b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/META-INF/sca-contribution.xml
new file mode 100644
index 0000000000..8264a8243f
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatordependent/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://dependent"
+ xmlns:sample="http://dependent">
+ <export namespace="http://dependent"/>
+</contribution> \ No newline at end of file
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/Calculator.composite
new file mode 100644
index 0000000000..c120fed3ca
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/Calculator.composite
@@ -0,0 +1,47 @@
+<?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://primary"
+ xmlns:primary="http://primary"
+ xmlns:dependent="http://dependent"
+ name="CalculatorA">
+
+ <include name="dependent:CalculatorB"/>
+
+ <component name="CalculatorServiceComponentA">
+ <implementation.java class="calculator.CalculatorServiceImpl"/>
+ <service name="CalculatorService">
+ <binding.sca/>
+ </service>
+ <reference name="addService" target="AddServiceComponentB" />
+ <reference name="subtractService" target="SubtractServiceComponentB" />
+ <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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/META-INF/sca-contribution.xml b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/META-INF/sca-contribution.xml
new file mode 100644
index 0000000000..e53c14a651
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/calculatorprimary/META-INF/sca-contribution.xml
@@ -0,0 +1,25 @@
+<?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://primary"
+ xmlns:sample="http://primary">
+ <deployable composite="sample:CalculatorA"/>
+ <import namespace="http://dependent"/>
+</contribution> \ No newline at end of file
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeA/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeA/Calculator.composite
new file mode 100644
index 0000000000..534e1a29af
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/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="CalculatorA">
+
+ <component name="CalculatorServiceComponentA">
+ <implementation.java class="calculator.CalculatorServiceImpl"/>
+ <service name="CalculatorService">
+ <binding.sca/>
+ </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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml
new file mode 100644
index 0000000000..1b1c0291e2
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/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:CalculatorA"/>
+</contribution> \ No newline at end of file
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeB/META-INF/sca-deployables/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeB/META-INF/sca-deployables/Calculator.composite
new file mode 100644
index 0000000000..bdb89803d1
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/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="CalculatorB">
+
+ <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/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeC/META-INF/sca-deployables/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeC/META-INF/sca-deployables/Calculator.composite
new file mode 100644
index 0000000000..c5af8dd3cc
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeC/META-INF/sca-deployables/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="CalculatorC">
+
+ <component name="SubtractServiceComponentC">
+ <implementation.java class="calculator.SubtractServiceImpl" />
+ <service name="SubtractService">
+ <binding.sca/>
+ </service>
+ </component>
+
+</composite>
diff --git a/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeD/META-INF/sca-deployables/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeD/META-INF/sca-deployables/Calculator.composite
new file mode 100644
index 0000000000..119c52cbf8
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/node-impl/src/test/resources/nodeD/META-INF/sca-deployables/Calculator.composite
@@ -0,0 +1,49 @@
+<?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="CalculatorD">
+
+ <component name="CalculatorServiceComponentD">
+ <implementation.java class="calculator.CalculatorServiceImpl"/>
+ <reference name="addService" target="AddServiceComponentD" />
+ <reference name="subtractService" target="SubtractServiceComponentD" />
+ <reference name="multiplyService" target="MultiplyServiceComponentD"/>
+ <reference name="divideService" target="DivideServiceComponentD" />
+ </component>
+
+ <component name="MultiplyServiceComponentD">
+ <implementation.java class="calculator.MultiplyServiceImpl" />
+ </component>
+
+ <component name="DivideServiceComponentD">
+ <implementation.java class="calculator.DivideServiceImpl" />
+ </component>
+
+ <component name="AddServiceComponentD">
+ <implementation.java class="calculator.AddServiceImpl" />
+ </component>
+
+ <component name="SubtractServiceComponentD">
+ <implementation.java class="calculator.SubtractServiceImpl" />
+ </component>
+
+</composite>