summaryrefslogtreecommitdiffstats
path: root/sandbox/sebastien/java/sca-node/modules/domain-impl/src
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/sebastien/java/sca-node/modules/domain-impl/src')
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainFactoryImpl.java52
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainImpl.java1293
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADummyNodeImpl.java80
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/launch/SCADomainControllerLauncher.java68
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/ContributionInfoImpl.java89
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/DomainInfoImpl.java93
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/NodeInfoImpl.java93
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/SCADomainManagerServiceImpl.java227
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/CompositeModelImpl.java75
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ContributionModelImpl.java110
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelFactoryImpl.java80
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelImpl.java115
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/NodeModelImpl.java143
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ServiceModelImpl.java89
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/domain.composite52
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/binding-jsonrpc.js492
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/domain.pngbin0 -> 718 bytes
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/index.html139
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/node.pngbin0 -> 296 bytes
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/style.css176
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/AddService.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/AddServiceImpl.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/CalculatorService.java37
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/CalculatorServiceImpl.java76
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/DivideService.java30
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/DivideServiceImpl.java32
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/MultiplyService.java30
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/MultiplyServiceImpl.java32
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/SubtractService.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/SubtractServiceImpl.java33
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/DomainImplTestCaseOFF.java133
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestCallableReferenceImpl.java84
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestNodeManagerServiceImpl.java68
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeA/Calculator.composite41
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml24
-rw-r--r--sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeB/Calculator.composite29
36 files changed, 4214 insertions, 0 deletions
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainFactoryImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainFactoryImpl.java
new file mode 100644
index 0000000000..acce630bf7
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainFactoryImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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.domain.impl;
+
+import org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.domain.SCADomainFactory;
+
+/**
+ * A finder for SCA domains.
+ *
+ * @version $Rev: 580520 $ $Date: 2007-09-29 00:50:25 +0100 (Sat, 29 Sep 2007) $
+ */
+public class SCADomainFactoryImpl extends SCADomainFactory {
+
+
+ /**
+ * Constructs a new SCA domain finder instance.
+ */
+ public SCADomainFactoryImpl() {
+
+ }
+
+ /**
+ * 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 createSCADomain(String domainURI) throws DomainException {
+ return new SCADomainImpl(domainURI);
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainImpl.java
new file mode 100644
index 0000000000..ea36d4d357
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADomainImpl.java
@@ -0,0 +1,1293 @@
+/*
+ * 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.domain.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.CompositeService;
+import org.apache.tuscany.sca.assembly.SCABinding;
+import org.apache.tuscany.sca.assembly.SCABindingFactory;
+import org.apache.tuscany.sca.assembly.Service;
+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.Export;
+import org.apache.tuscany.sca.contribution.Import;
+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.core.context.ServiceReferenceImpl;
+import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter.Base64Binary;
+import org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.domain.management.SCADomainManagerInitService;
+import org.apache.tuscany.sca.domain.model.CompositeModel;
+import org.apache.tuscany.sca.domain.model.ContributionModel;
+import org.apache.tuscany.sca.domain.model.DomainModel;
+import org.apache.tuscany.sca.domain.model.DomainModelFactory;
+import org.apache.tuscany.sca.domain.model.NodeModel;
+import org.apache.tuscany.sca.domain.model.ServiceModel;
+import org.apache.tuscany.sca.domain.model.NodeModel.LifecyleState;
+import org.apache.tuscany.sca.domain.model.impl.DomainModelFactoryImpl;
+import org.apache.tuscany.sca.domain.model.impl.NodeModelImpl;
+import org.apache.tuscany.sca.domain.spi.SCADomainEventService;
+import org.apache.tuscany.sca.domain.spi.SCADomainSPI;
+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.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.spi.NodeFactoryImpl;
+import org.apache.tuscany.sca.node.util.SCAContributionUtil;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentContext;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.osoa.sca.CallableReference;
+import org.osoa.sca.ServiceReference;
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * The SCA domain implementation. In Tuscany we currently have a model of the
+ * SCA Domain that relies on a central domain manager this class provides that
+ * central manager.
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-09 23:54:46 +0100 (Sun, 09 Sep 2007) $
+ */
+public class SCADomainImpl implements SCADomain, SCADomainEventService, SCADomainSPI {
+
+ private static final Logger logger = Logger.getLogger(SCADomainImpl.class.getName());
+
+ // class loader used to get the runtime going
+ protected ClassLoader domainClassLoader;
+
+ // domain management application runtime
+ protected ReallySmallRuntime domainManagementRuntime;
+ protected ContributionService domainManagementContributionService;
+ protected Contribution domainManagementContribution;
+ protected Composite domainManagementComposite;
+
+ // domain application runtime
+ protected Composite domainComposite;
+
+ // the logic for wiring up references and services at the domain level
+ protected DomainBuilder domainBuilder;
+
+ // Used to pipe dummy node information into the domain management runtime
+ // primarily so that the sca binding can resolve endpoints.
+ protected NodeFactoryImpl nodeFactory;
+
+ // The domain model
+ protected DomainModelFactory domainModelFactory = new DomainModelFactoryImpl();
+ protected DomainModel domainModel;
+
+ // management services
+ private SCADomainManagerInitService domainManagerInitService;
+
+
+ // Implementation methods
+
+ /**
+ * Create a domain giving the URI for the domain.
+ *
+ * @param domainURI - identifies what host and port the domain service is running on, e.g. http://localhost:8081
+ * @throws ActivationException
+ */
+ public SCADomainImpl(String domainURI) throws DomainException {
+ this.domainModel = domainModelFactory.createDomain();
+ this.domainModel.setDomainURI(domainURI);
+ this.domainClassLoader = SCADomainImpl.class.getClassLoader();
+ init();
+ }
+
+ /**
+ * Create the domain management runtime etc
+ */
+ protected void init() throws DomainException {
+ try {
+ // check whether domain URI is a URL
+ URI tmpURI;
+ try {
+ tmpURI = new URI(domainModel.getDomainURI());
+ domainModel.setDomainURL(tmpURI.toURL().toExternalForm());
+ } catch(Exception ex) {
+ throw new ActivationException("domain uri " +
+ domainModel.getDomainURI() +
+ " must be a valid url");
+ }
+
+ // create a runtime for the domain management services to run on
+ domainManagementRuntime = new ReallySmallRuntime(domainClassLoader);
+ domainManagementRuntime.start();
+
+ // Configure the default server port and path
+ int port = URI.create(domainModel.getDomainURI()).getPort();
+ String path = URI.create(domainModel.getDomainURI()).getPath();
+ if (port != -1) {
+ 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);
+ }
+ }
+ }
+
+ // 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");
+
+ // Create an in-memory domain level composite
+ domainComposite = assemblyFactory.createComposite();
+ domainComposite.setName(new QName(Constants.SCA10_NS, "domain"));
+ domainComposite.setURI(domainModel.getDomainURI() + "/domain");
+
+ domainModel.setDomainLevelComposite(domainComposite);
+
+ // Set up the domain so that local CallableReferences can find
+ // service out there in the domain
+ SCADummyNodeImpl node = new SCADummyNodeImpl(this);
+ ModelFactoryExtensionPoint factories = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
+ nodeFactory = new NodeFactoryImpl(node);
+ factories.addFactory(nodeFactory);
+
+ // Find the composite that will configure the domain
+ String domainCompositeName = "domain.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();
+ Contribution contribution = null;
+ contribution = domainManagementContributionService.contribute(domainModel.getDomainURI(),
+ contributionURL,
+ false);
+
+ //get the domain builder
+ domainBuilder = domainManagementRuntime.getDomainBuilder();
+
+
+ Composite composite = null;
+ for (Artifact artifact: contribution.getArtifacts()) {
+ if (domainCompositeName.equals(artifact.getURI())) {
+ composite = (Composite)artifact.getModel();
+ }
+ }
+
+ if (composite != null) {
+
+ domainManagementComposite.getIncludes().add(composite);
+ domainManagementRuntime.buildComposite(composite);
+ domainManagementRuntime.getCompositeActivator().activate(composite);
+ domainManagementRuntime.getCompositeActivator().start(composite);
+
+ // get the management components out of the domain so that they
+ // can be configured/used.
+ domainManagerInitService = getService(SCADomainManagerInitService.class,
+ "SCADomainManagerComponent/SCADomainManagerInitService",
+ domainManagementRuntime,
+ domainManagementComposite);
+ domainManagerInitService.setDomain(this);
+ domainManagerInitService.setDomainSPI((SCADomainSPI)this);
+ domainManagerInitService.setDomainEventService((SCADomainEventService)this);
+
+
+ } 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);
+ }
+ }
+
+ private void notifyDomainChange() throws DomainException {
+ List<Composite> changedComposites = domainBuilder.wireDomain(domainComposite);
+
+ // notify nodes that have composites that the composites have changed
+ for (Composite composite : changedComposites){
+ String compositeXML = getComposite(composite.getName());
+
+ for (NodeModel node : domainModel.getNodes().values()){
+ if (node.getDeployedComposites().containsKey(composite.getName())){
+ try {
+ if (((NodeModelImpl)node).getSCANodeManagerService() != null) {
+
+ logger.log(Level.FINE, "Updating node: " +
+ node.getNodeURI() +
+ " with composite: " +
+ compositeXML);
+
+ // notify node
+ ((NodeModelImpl)node).getSCANodeManagerService().updateComposite(composite.getName().toString(),
+ Base64Binary.encode(compositeXML.getBytes()));
+ }
+ } catch (Exception ex) {
+ throw new DomainException(ex);
+ }
+ }
+ }
+ }
+ }
+
+ private ContributionModel findContributionFromComposite(QName compositeQName){
+ ContributionModel returnContributionModel = null;
+
+ for(ContributionModel contributionModel : domainModel.getContributions().values()){
+ if (contributionModel.getComposites().containsKey(compositeQName)){
+ returnContributionModel = contributionModel;
+ }
+ }
+
+ return returnContributionModel;
+ }
+
+ private CompositeModel findComposite(QName compositeQName){
+ CompositeModel returnCompositeModel = null;
+
+ for(ContributionModel contributionModel : domainModel.getContributions().values()){
+ returnCompositeModel = contributionModel.getComposites().get(compositeQName);
+
+ if (returnCompositeModel != null){
+ break;
+ }
+ }
+
+ return returnCompositeModel;
+ }
+
+ // Recursively look for contributions that contain included artifacts. Deepest dependencies
+ // appear first in the list
+ // This function should be moved to the contribution package.
+ private void findDependentContributions(Contribution contribution, List<Contribution> dependentContributions){
+
+ for (Import contribImport : contribution.getImports()) {
+ for (ContributionModel tmpContributionModel : domainModel.getContributions().values()) {
+ Contribution tmpContribution = tmpContributionModel.getContribution();
+ for (Export export : tmpContribution.getExports()) {
+ if (contribImport.match(export)) {
+ if (tmpContribution.getImports().isEmpty()) {
+ dependentContributions.add(tmpContribution);
+ } else {
+ findDependentContributions(tmpContribution, dependentContributions);
+ }
+ }
+ }
+ }
+ }
+
+ dependentContributions.add(contribution);
+ }
+
+ private ContributionModel parseContribution(String contributionURI, String contributionURL) throws DomainException {
+ // add the contribution information to the domain model
+ ContributionModel contributionModel = domainModelFactory.createContribution();
+ contributionModel.setContributionURI(contributionURI);
+ contributionModel.setContributionURL(contributionURL);
+ domainModel.getContributions().put(contributionURI, contributionModel);
+
+ // read the assembly model objects.
+ try {
+ // Create a local model from the contribution. Using the contribution
+ // processor from the domain management runtime just because we already have it
+ Contribution contribution = domainManagementContributionService.contribute(contributionURI,
+ new URL(contributionURL),
+ false);
+
+ contributionModel.setContribution(contribution);
+
+ // add the composites into the domain model
+ for (Artifact artifact : contribution.getArtifacts()) {
+ if (artifact.getModel() instanceof Composite) {
+ Composite composite = (Composite)artifact.getModel();
+ CompositeModel compositeModel = domainModelFactory.createComposite();
+ compositeModel.setCompositeQName(composite.getName());
+ compositeModel.setComposite(composite);
+ contributionModel.getComposites().put(compositeModel.getCompositeQName(), compositeModel);
+ }
+ }
+
+ // add the deployable composite info to the domain model
+ for (Composite composite : contribution.getDeployables()) {
+ CompositeModel compositeModel = contributionModel.getComposites().get(composite.getName());
+
+ if (compositeModel != null){
+ contributionModel.getDeployableComposites().put(compositeModel.getCompositeQName(), compositeModel);
+ } else {
+ throw new DomainException("Deployable composite name " +
+ composite.getName() +
+ " doesn't match a composite in the contribution " +
+ contributionURI );
+ }
+ }
+ } catch(DomainException ex) {
+ throw ex;
+ } catch(Exception ex) {
+ throw new DomainException(ex);
+ }
+
+ return contributionModel;
+ }
+
+
+ // SCADomainSPI methods
+
+ public DomainModel getDomainModel(){
+ return domainModel;
+ }
+
+ public String getComposite(QName compositeQName){
+ CompositeModel compositeModel = domainModel.getDeployedComposites().get(compositeQName);
+ Composite composite = compositeModel.getComposite();
+
+ 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();
+ //outputFactory.setProperty("javax.xml.stream.isPrefixDefaulting",Boolean.TRUE);
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(bos);
+
+ processor.write(composite, writer);
+ writer.flush();
+ writer.close();
+ } catch (Exception ex) {
+ System.out.println(ex.toString());
+ }
+
+ String compositeString = bos.toString();
+
+ return compositeString;
+ }
+
+ public String getComponent(QName compositeQName, String componentName){
+
+ String componentString = null;
+
+ return componentString;
+ }
+
+
+ // SCADomainEventService methods
+
+ public void registerNode(String nodeURI, String nodeURL, Externalizable nodeManagerReference) throws DomainException {
+ // try and remove it first just in case it's already registered
+ unregisterNode(nodeURI);
+
+ NodeModel node = domainModelFactory.createNode();
+ node.setNodeURI(nodeURI);
+ node.setNodeURL(nodeURL);
+ node.setNodeManagerReference(nodeManagerReference);
+ node.setLifecycleState(LifecyleState.AVAILABLE);
+ domainModel.getNodes().put(nodeURI, node);
+
+ logger.log(Level.INFO, "Registered node: " +
+ nodeURI +
+ " at endpoint " +
+ nodeURL);
+ }
+
+ public void unregisterNode(String nodeURI) throws DomainException{
+
+ domainModel.getNodes().remove(nodeURI);
+
+ logger.log(Level.FINE, "Removed node: " + nodeURI);
+ }
+
+ public void registerNodeStart(String nodeURI) throws DomainException{
+/* TODO - no longer used
+ NodeModel node = domainModel.getNodes().get(nodeURI);
+
+ if (node != null) {
+ // if the node was started by the domain we already know it's running
+ if (node.getLifecycleState() != LifecyleState.RUNNING){
+ node.setLifecycleState(LifecyleState.RUNNING);
+
+ // run the update in a separate thread so that the caller doesn't block
+ scheduler.execute(domainUpdateProcessor);
+ }
+ } else {
+ logger.log(Level.WARNING, "trying to start node: " +
+ nodeURI +
+ " that isn't registered " );
+ }
+*/
+ }
+
+ public void registerNodeStop(String nodeURI) throws DomainException{
+/* TODO - no longer used
+ NodeModel node = domainModel.getNodes().get(nodeURI);
+
+ if (node != null) {
+ // if the node was stopped by the domain we already know it's running
+ if (node.getLifecycleState() == LifecyleState.RUNNING){
+ node.setLifecycleState(LifecyleState.DEPLOYED);
+
+ // run the update in a separate thread so that the caller doesn't block
+ scheduler.execute(domainUpdateProcessor);
+ }
+ } else {
+ logger.log(Level.WARNING, "trying to stop node: " +
+ nodeURI +
+ " that isn't registered " );
+ }
+*/
+ }
+
+ public void registerContribution(String nodeURI, String contributionURI, String contributionURL) throws DomainException{
+ try {
+ ContributionModel contributionModel = null;
+
+ if ( domainModel.getContributions().containsKey(contributionURI) == false ){
+ contributionModel = parseContribution(contributionURI, contributionURL);
+
+ // assign the contribution to the referenced node
+ NodeModel node = domainModel.getNodes().get(nodeURI);
+
+ if ((node != null) && (contributionModel != null)) {
+ node.getContributions().put(contributionURI, contributionModel);
+ }
+ } else {
+ // TODO - throw an exception here ?
+ }
+
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, "Exception when registering contribution " +
+ contributionURI +
+ ex.toString() );
+ }
+ }
+
+ public void unregisterContribution(String nodeURI, String contributionURI) throws DomainException {
+ try {
+
+ if ( domainModel.getContributions().containsKey(contributionURI) == true ){
+ // get the contribution model
+ ContributionModel contributionModel = domainModel.getContributions().get(contributionURI);
+
+ // remove deployed composites
+ for (QName compositeQName : contributionModel.getDeployedComposites().keySet()){
+ domainModel.getDomainLevelComposite().getIncludes().remove(contributionModel.getDeployedComposites().get(compositeQName));
+ domainModel.getDeployedComposites().remove(compositeQName);
+ }
+
+ // remove contribution from the domain
+ domainModel.getContributions().remove(contributionURI);
+
+ // remove the contribution from the referenced node
+ NodeModel nodeModel = domainModel.getNodes().get(nodeURI);
+
+ if ((nodeModel != null)) {
+ nodeModel.getContributions().remove(contributionURI);
+
+ // remove deployed composites
+ for (QName compositeQName : contributionModel.getDeployedComposites().keySet()){
+ nodeModel.getDeployedComposites().remove(compositeQName);
+ }
+ }
+ }
+
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, "Exception when removing contribution " +
+ contributionURI +
+ ex.toString() );
+ }
+ }
+
+ public void registerDomainLevelComposite(String nodeURI, String compositeQNameString) throws DomainException{
+ try {
+ QName compositeQName = QName.valueOf(compositeQNameString);
+
+ if (!domainModel.getDeployedComposites().containsKey(compositeQName)){
+ // get the composite from the node
+ NodeModel node = domainModel.getNodes().get(nodeURI);
+
+ if (node != null) {
+ if (node.getLifecycleState() != LifecyleState.AVAILABLE){
+ throw new DomainException("Node " + nodeURI + " is already marked as active");
+ } else {
+ for (ContributionModel contributionModel : node.getContributions().values()){
+ CompositeModel compositeModel = contributionModel.getComposites().get(compositeQName);
+
+ if (compositeModel != null){
+ contributionModel.getDeployedComposites().put(compositeQName, compositeModel);
+ node.getDeployedComposites().put(compositeQName, compositeModel);
+ domainModel.getDeployedComposites().put(compositeQName, compositeModel);
+ domainManagementRuntime.getCompositeBuilder().build(compositeModel.getComposite());
+ domainModel.getDomainLevelComposite().getIncludes().add(compositeModel.getComposite());
+
+
+ }
+ }
+ }
+ }
+ } else {
+ throw new DomainException("Composite " + compositeQNameString +
+ " is already marked as deployed on node " + nodeURI);
+ }
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, "Exception when registering domain level composite " +
+ nodeURI + " " +
+ compositeQNameString +
+ ex.toString() );
+ }
+ }
+
+ public void registerServiceEndpoint(String domainURI, String nodeURI, String targetServiceName, String bindingClassName, String URL)throws DomainException {
+
+ // the target service name is the component/service name combination
+ String componentName = null;
+ String serviceName = null;
+
+ // if the service name ends in a "/" remove it
+ if (targetServiceName.endsWith("/")) {
+ targetServiceName = targetServiceName.substring(0, targetServiceName.length() - 1);
+ }
+
+ // if the service name starts with a "/" remove it
+ if (targetServiceName.startsWith("/")) {
+ targetServiceName = targetServiceName.substring(1, targetServiceName.length());
+ }
+
+ // TODO - only interested if multiplicity is <= 1
+ componentName = domainBuilder.getComponentNameFromReference(targetServiceName);
+ serviceName = domainBuilder.getServiceNameFromReference(targetServiceName);
+
+ domainBuilder.updateDomainLevelServiceURI(domainComposite, targetServiceName, bindingClassName, URL);
+
+ // find the node with the service
+ NodeModel node = domainModel.getNodes().get(nodeURI);
+
+ if (node != null){
+
+ // collect the service info
+ ServiceModel serviceModel = domainModelFactory.createService();
+ serviceModel.setServiceURI(targetServiceName);
+ serviceModel.setServiceURL(URL);
+ serviceModel.setServiceBinding(bindingClassName);
+
+ //store the service
+ node.getServices().put(targetServiceName+bindingClassName, serviceModel);
+
+ if (componentName != null){
+ node.getServices().put(componentName+bindingClassName, serviceModel);
+ }
+ logger.log(Level.INFO, "Registering service: [" +
+ domainURI + " " +
+ targetServiceName + " " +
+ URL + " " +
+ bindingClassName + "]");
+ } else {
+ logger.log(Level.WARNING, "Trying to register service: " +
+ targetServiceName +
+ " for a node " +
+ nodeURI +
+ "that isn't registered");
+ }
+
+ }
+
+ public void unregisterServiceEndpoint(String domainURI, String nodeURI, String serviceName, String bindingClassName) throws DomainException{
+ NodeModel node = domainModel.getNodes().get(nodeURI);
+ node.getServices().remove(serviceName + bindingClassName);
+
+ // extract the short name from the long name
+ String shortServiceName = null;
+ if (serviceName.indexOf("/") >= 0 ) {
+ shortServiceName = serviceName.substring(0, serviceName.indexOf("/"));
+ }
+
+ node.getServices().remove(shortServiceName + bindingClassName);
+
+ logger.log(Level.FINE, "Removed service: " + serviceName );
+
+ }
+
+ public String findServiceEndpoint(String domainURI, String serviceName, String bindingName) throws DomainException{
+ logger.log(Level.INFO, "Finding service: [" +
+ domainURI + " " +
+ serviceName + " " +
+ bindingName +
+ "]");
+
+ String url = SERVICE_NOT_REGISTERED;
+ if (serviceName.startsWith("/")) {
+ serviceName = serviceName.substring(1);
+ }
+ String serviceKey = serviceName + bindingName;
+
+ for (NodeModel node : domainModel.getNodes().values()){
+ ServiceModel service = node.getServices().get(serviceKey);
+
+ if (service != null){
+ url = service.getServiceURL();
+ // uncomment for debugging
+ //url = url.replace("8085", "8086");
+ logger.log(Level.INFO, "Found service " + serviceName + " url: " + url);
+ break;
+ }
+ }
+
+ return url;
+ }
+
+ public String findServiceNode(String domainURI, String serviceName, String bindingName) throws DomainException{
+ logger.log(Level.FINE, "Finding service node: [" +
+ domainURI + " " +
+ serviceName + " " +
+ bindingName +
+ "]");
+
+ String nodeURI = SERVICE_NOT_KNOWN;
+
+ for (NodeModel node : domainModel.getNodes().values()){
+ Service service = null;
+ for (CompositeModel compositeModel : node.getDeployedComposites().values()){
+ service = domainBuilder.findServiceForReference(compositeModel.getComposite(), serviceName);
+ if (service != null) {
+ nodeURI = node.getNodeURI();
+ break;
+ }
+ }
+ }
+
+ return nodeURI;
+ }
+
+
+
+ // SCADomain API methods
+
+ public void start() throws DomainException {
+
+ // notify any top level domain changes before composites are started
+ notifyDomainChange();
+
+ // call start on all nodes with deployed composites
+ for(NodeModel node : domainModel.getNodes().values()) {
+ if ( !node.getDeployedComposites().isEmpty()){
+ try {
+ if (node.getLifecycleState() != LifecyleState.RUNNING) {
+ ((NodeModelImpl)node).getSCANodeManagerService().start();
+ node.setLifecycleState(LifecyleState.RUNNING);
+ }
+ } catch (Exception ex) {
+ // TODO - collate errors and report
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void stop() throws DomainException {
+ // call stop on all nodes
+ for(NodeModel node : domainModel.getNodes().values()) {
+ try {
+ if (node.getLifecycleState() == LifecyleState.RUNNING) {
+ ((NodeModelImpl)node).getSCANodeManagerService().stop();
+ node.setLifecycleState(LifecyleState.DEPLOYED);
+ }
+ } catch (Exception ex) {
+ // TODO - collate errors and report
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ public void destroy() throws DomainException {
+ try {
+
+ // unregister all nodes
+ domainModel.getNodes().clear();
+
+ // remove all management components
+ Composite composite = domainManagementComposite.getIncludes().get(0);
+
+ domainManagementRuntime.getCompositeActivator().stop(composite);
+ domainManagementRuntime.getCompositeActivator().deactivate(composite);
+
+ // remove the node factory
+ ModelFactoryExtensionPoint factories = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
+ factories.removeFactory(nodeFactory);
+ nodeFactory.setNode(null);
+
+ // Stop the SCA runtime that the domain is using
+ domainManagementRuntime.stop();
+
+
+ } catch(ActivationException ex) {
+ throw new DomainException(ex);
+ }
+ }
+
+ public String getURI(){
+ return domainModel.getDomainURI();
+ }
+
+ public void addContribution(String contributionURI, URL contributionURL) throws DomainException {
+ // add the contribution information to the domain model
+ org.apache.tuscany.sca.domain.model.ContributionModel contributionModel =
+ parseContribution(contributionURI, contributionURL.toExternalForm());
+ }
+
+ public void updateContribution(String contributionURI, URL contributionURL) throws DomainException {
+ if ( domainModel.getContributions().containsKey(contributionURI) == true ){
+
+ List<QName> deployedCompositeNames = new ArrayList<QName>();
+
+ // record the names of composites that must be restarted after the
+ // contribution has been removed
+ for ( NodeModel node : domainModel.getNodes().values()){
+ if ((node.getLifecycleState() == LifecyleState.RUNNING) && (node.getContributions().containsKey(contributionURI))) {
+ for (CompositeModel tmpCompositeModel : node.getDeployedComposites().values()){
+ deployedCompositeNames.add(tmpCompositeModel.getCompositeQName());
+ }
+ }
+ }
+
+ // remove the old version of the contribution
+ removeContribution(contributionURI);
+
+ // Add the updated contribution back into the domain model
+ // TODO - there is a problem here with dependent contributions
+ // as it doesn't look like the contribution listeners
+ // are working quite right
+ addContribution(contributionURI, contributionURL);
+
+ // add the deployed composites back into the domain if they still exist
+ // if they don't then the user will have to add and start any new composites manually
+ for (QName compositeQName : deployedCompositeNames) {
+ // make sure the composite still exists
+ CompositeModel compositeModel = findComposite(compositeQName);
+
+ if (compositeModel != null){
+ addToDomainLevelComposite(compositeModel.getCompositeQName());
+ } else {
+ // the composite has been removed from the contribution
+ // by the update
+ }
+ }
+
+ // automatically start all the composites
+ for (QName compositeName : deployedCompositeNames) {
+ startComposite(compositeName);
+ }
+ } else {
+ throw new DomainException("Contribution " + contributionURI + " not found in domain contributions");
+ }
+ }
+
+ public void removeContribution(String contributionURI) throws DomainException {
+ if ( domainModel.getContributions().containsKey(contributionURI) == true ){
+
+ // get the contribution model
+ ContributionModel contributionModel = domainModel.getContributions().get(contributionURI);
+
+ // remove potentially deployed composites
+ for (QName compositeQName : contributionModel.getDeployableComposites().keySet()){
+ domainModel.getDeployedComposites().remove(compositeQName);
+ domainModel.getDomainLevelComposite().getIncludes().remove(contributionModel.getDeployableComposites().get(compositeQName));
+ }
+
+ // remove contribution from the domain model
+ domainModel.getContributions().remove(contributionURI);
+
+ // remove contribution from the contribution processor
+ try {
+ domainManagementContributionService.remove(contributionURI);
+ } catch (Exception ex){
+ throw new DomainException(ex);
+ }
+
+ // stop and tidy any nodes running this contribution
+ for ( NodeModel node : domainModel.getNodes().values()){
+ if (node.getContributions().containsKey(contributionURI)) {
+ try {
+ if (node.getLifecycleState() == LifecyleState.RUNNING) {
+ ((NodeModelImpl)node).getSCANodeManagerService().stop();
+ node.setLifecycleState(LifecyleState.DEPLOYED);
+ }
+
+ // remove all contributions from this node including the
+ // one that is specifically being removed.
+ for (ContributionModel tmpContributionModel : node.getContributions().values()){
+ ((NodeModelImpl)node).getSCANodeManagerService().removeContribution(tmpContributionModel.getContributionURI());
+ }
+
+ node.getContributions().clear();
+ node.getDeployedComposites().clear();
+ node.setLifecycleState(LifecyleState.AVAILABLE);
+ node.getServices().clear();
+ } catch (Exception ex) {
+ // TODO - collate errors and report
+ ex.printStackTrace();
+ }
+ }
+ }
+ } else {
+ throw new DomainException("Contribution " + contributionURI + " not found in domain contributions");
+ }
+ }
+
+ public void addDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ // TODO
+ throw new DomainException("Not yet implemented");
+ }
+
+ public void updateDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ // TODO
+ throw new DomainException("Not yet implemented");
+ }
+
+ public void addToDomainLevelComposite(QName compositeQName) throws DomainException {
+ addToDomainLevelComposite(compositeQName, null);
+ }
+
+ public void addToDomainLevelComposite(QName compositeQName, String nodeURI) throws DomainException {
+
+ try {
+ // check to see if this composite has already been added
+ if (domainModel.getDeployedComposites().containsKey(compositeQName) ){
+ throw new DomainException("Composite " + compositeQName.toString() +
+ " had already been added to the domain level composite");
+ }
+
+ // find the contribution that has this composite
+ ContributionModel contributionModel = findContributionFromComposite(compositeQName);
+
+ if (contributionModel == null){
+ throw new DomainException("Can't find contribution for composite " + compositeQName.toString());
+ }
+
+ // find the composite object from the contribution
+ CompositeModel compositeModel = contributionModel.getComposites().get(compositeQName);
+
+ if (compositeModel == null){
+ throw new DomainException("Can't find composite model " + compositeQName.toString() +
+ " in contribution " + contributionModel.getContributionURI());
+ }
+
+ // build the contribution to create the services and references
+ domainModel.getDeployedComposites().put(compositeQName, compositeModel);
+ domainManagementRuntime.getCompositeBuilder().build(compositeModel.getComposite());
+ domainModel.getDomainLevelComposite().getIncludes().add(compositeModel.getComposite());
+
+ NodeModel node = null;
+
+ // find the node for the composite to run on
+ if (nodeURI != null) {
+ // find the named node
+ node = domainModel.getNodes().get(nodeURI);
+
+ if (node == null){
+ throw new DomainException("Node " + nodeURI + " not found in domain");
+ }
+ } else {
+ // noddy algorithm to find a free node
+ // TODO - do something better
+ for(NodeModel tmpNode : domainModel.getNodes().values()) {
+ if (tmpNode.getLifecycleState() == LifecyleState.AVAILABLE){
+ node = tmpNode;
+ }
+ }
+
+ if (node == null){
+ throw new DomainException("No free node available to run composite " + compositeQName.toString());
+ }
+ }
+
+ // find all the composites that the node must know about
+ List<Contribution> dependentContributions = new ArrayList<Contribution>();
+ findDependentContributions(contributionModel.getContribution(), dependentContributions);
+
+ // assign the set of contributions to the node model
+ for (Contribution tmpContribution : dependentContributions){
+ node.getContributions().put(tmpContribution.getURI(),
+ domainModel.getContributions().get(tmpContribution.getURI()));
+ }
+
+ // assign the composite to the node model
+ node.getDeployedComposites().put(compositeQName, compositeModel);
+
+ node.setLifecycleState(LifecyleState.DEPLOYED);
+
+ // now pass this information over to the real node
+
+
+ // add contributions. Use the dependent contribution list here rather than the
+ // one built up in the node model to ensure that contributions are added in the correct order
+ // I.e. the top most in the dependency tree last.
+ for (Contribution tmpContribution : dependentContributions){
+ ((NodeModelImpl)node).getSCANodeManagerService().addContribution(tmpContribution.getURI(),
+ domainModel.getContributions().get(tmpContribution.getURI()).getContributionURL());
+ }
+
+ // deploy composite
+ ((NodeModelImpl)node).getSCANodeManagerService().addToDomainLevelComposite(compositeQName.toString());
+
+ // spray all of the service endpoints from this composite out to interested nodes
+ notifyDomainChange();
+ } catch (DomainException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new DomainException(ex);
+ }
+
+ }
+
+ public void removeFromDomainLevelComposite(QName compositeQName) throws DomainException {
+
+ domainModel.getDomainLevelComposite().getIncludes().remove(domainModel.getDeployedComposites().get(compositeQName).getComposite());
+ domainModel.getDeployedComposites().remove(compositeQName);
+
+ ContributionModel contributionModel = findContributionFromComposite(compositeQName);
+
+ if (contributionModel != null){
+ contributionModel.getDeployedComposites().remove(compositeQName);
+
+ for(NodeModel node : domainModel.getNodes().values()) {
+ if ( node.getDeployedComposites().containsKey(compositeQName)){
+ try {
+ if (node.getLifecycleState() == LifecyleState.RUNNING) {
+ ((NodeModelImpl)node).getSCANodeManagerService().stop();
+ node.setLifecycleState(LifecyleState.DEPLOYED);
+ }
+ // TODO - how to remove it from the node. Remove all contributions???
+
+ node.getDeployedComposites().remove(compositeQName);
+ } catch (Exception ex) {
+ // TODO - collate errors and report
+ ex.printStackTrace();
+ }
+ }
+ }
+ } else {
+ throw new DomainException("Composite " + compositeQName.toString() + " not found in domain contributions");
+ }
+ }
+
+ public String getDomainLevelComposite() throws DomainException {
+
+ String domainLevelComposite = "<composite xmlns=\"http://www.osoa.org/xmlns/sca/1.0\"" +
+ " targetNamespace=\"http://tuscany.apache.org/domain\"" +
+ " xmlns:domain=\"http://tuscany.apache.org/domain\"";
+
+ int includeCount = 0;
+ for (CompositeModel compositeModel : domainModel.getDeployedComposites().values()){
+ domainLevelComposite = domainLevelComposite + " xmlns:include" +
+ includeCount +
+ "=\"" + compositeModel.getCompositeQName().getNamespaceURI() + "\"";
+ includeCount++;
+ }
+
+ domainLevelComposite = domainLevelComposite + " name=\"DomainLevelComposite\">";
+
+ includeCount = 0;
+ for (CompositeModel compositeModel : domainModel.getDeployedComposites().values()){
+ domainLevelComposite = domainLevelComposite + "<include name=\"include" +
+ includeCount +
+ ":" +
+ compositeModel.getCompositeQName().getLocalPart() +
+ "\"/>";
+ includeCount++;
+ }
+
+ domainLevelComposite = domainLevelComposite + "</composite>";
+
+ return domainLevelComposite;
+ }
+
+ public String getQNameDefinition(QName artifact) throws DomainException {
+ // TODO - no absolutely sure what is intended here as I don't have
+ // an explicit scenario but here is some code to get me thinking about it
+ String artifactString = null;
+
+ // find the composite that matches and return its XML
+ CompositeModel compositeModel = domainModel.getDeployedComposites().get(artifact);
+
+ if (compositeModel != null){
+ // convert the composite to XML
+ }
+
+ return artifactString;
+ }
+
+ public void startComposite(QName compositeQName) throws DomainException {
+ try {
+ // find the composite object from the list of deployed composites
+ CompositeModel compositeModel = domainModel.getDeployedComposites().get(compositeQName);
+
+ if (compositeModel == null){
+ throw new DomainException("Can't start composite " + compositeQName.toString() +
+ " as it hasn't been added to the domain level composite");
+ }
+
+ // find the contribution that has this composite
+ ContributionModel contributionModel = findContributionFromComposite(compositeQName);
+
+ if (contributionModel == null){
+ throw new DomainException("Can't find contribution for composite " + compositeQName.toString());
+ }
+
+ NodeModel node = null;
+
+ // find the node that has this composite
+ for(NodeModel tmpNode : domainModel.getNodes().values()) {
+ if (tmpNode.getDeployedComposites().containsKey(compositeQName)){
+ node = tmpNode;
+ break;
+ }
+ }
+
+ if (node != null){
+ if (node.getLifecycleState() == LifecyleState.DEPLOYED){
+ // start the node
+ ((NodeModelImpl)node).getSCANodeManagerService().start();
+ node.setLifecycleState(LifecyleState.RUNNING);
+ }
+
+ } else {
+ // composite not assigned to node for some reason
+ throw new DomainException("Composite " + compositeQName.toString() +
+ " is not associated with a node and cannot be started");
+ }
+ } catch (NodeException ex){
+ throw new DomainException(ex);
+ }
+
+ }
+
+ public void stopComposite(QName compositeName) throws DomainException {
+ // find the composite object from the list of deployed composites
+ CompositeModel composite = domainModel.getDeployedComposites().get(compositeName);
+
+ if (composite == null){
+ throw new DomainException("Can't stop composite " + compositeName.toString() +
+ " as it hasn't been added to the domain level composite");
+ }
+
+ // stop all the nodes running this composite
+ for(NodeModel node : domainModel.getNodes().values()) {
+ if ( node.getDeployedComposites().containsKey(compositeName)){
+ try {
+ if (node.getLifecycleState() == LifecyleState.RUNNING) {
+ node.setLifecycleState(LifecyleState.DEPLOYED);
+ ((NodeModelImpl)node).getSCANodeManagerService().stop();
+ }
+ } catch (Exception ex) {
+ // TODO - how to report this?
+ }
+ }
+ }
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ return (R)cast(target, domainManagementRuntime);
+ }
+
+ protected <B, R extends CallableReference<B>> R cast(B target, ReallySmallRuntime runtime) throws IllegalArgumentException {
+ return (R)runtime.getProxyFactory().cast(target);
+ }
+
+ public <B> B getService(Class<B> businessInterface, String serviceName) {
+ return getService( businessInterface, serviceName, domainManagementRuntime, null);
+ }
+
+ protected <B> B getService(Class<B> businessInterface, String serviceName, ReallySmallRuntime runtime, Composite domainComposite) {
+
+ ServiceReference<B> serviceReference = getServiceReference(businessInterface, serviceName, runtime, domainComposite);
+ if (serviceReference == null) {
+ throw new ServiceRuntimeException("Service not found: " + serviceName);
+ }
+ return serviceReference.getService();
+ }
+
+ protected <B> ServiceReference<B> createServiceReference(Class<B> businessInterface, String targetURI) {
+ return createServiceReference(businessInterface, targetURI, domainManagementRuntime, null);
+ }
+
+
+ protected <B> ServiceReference<B> createServiceReference(Class<B> businessInterface, String targetURI, ReallySmallRuntime runtime, Composite domainComposite) {
+ try {
+
+ AssemblyFactory assemblyFactory = runtime.getAssemblyFactory();
+ Composite composite = assemblyFactory.createComposite();
+ composite.setName(new QName(Constants.SCA10_TUSCANY_NS, "default"));
+ RuntimeComponent component = (RuntimeComponent)assemblyFactory.createComponent();
+ component.setName("default");
+ component.setURI("default");
+ runtime.getCompositeActivator().configureComponentContext(component);
+ composite.getComponents().add(component);
+ RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference();
+ reference.setName("default");
+ ModelFactoryExtensionPoint factories =
+ runtime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class);
+ JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);
+ InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
+ interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface));
+ reference.setInterfaceContract(interfaceContract);
+ component.getReferences().add(reference);
+ reference.setComponent(component);
+ SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class);
+ SCABinding binding = scaBindingFactory.createSCABinding();
+
+ // find the service endpoint somewhere else in the domain
+ try {
+ String endpointURL = findServiceEndpoint(domainModel.getDomainURI(),
+ targetURI,
+ binding.getClass().getName());
+
+ if (endpointURL.equals(SERVICE_NOT_REGISTERED)){
+ logger.log(Level.WARNING, "Created a sevice reference for service that is not yet started: Service " + targetURI);
+ } else {
+ targetURI = endpointURL;
+ }
+ } catch (DomainException ex){
+ throw new ServiceRuntimeException(ex);
+ }
+
+ binding.setURI(targetURI);
+ reference.getBindings().add(binding);
+ return new ServiceReferenceImpl<B>(businessInterface, component, reference, binding, runtime
+ .getProxyFactory(), runtime.getCompositeActivator());
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) {
+ return getServiceReference(businessInterface, name, domainManagementRuntime, null);
+ }
+
+
+ protected <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name, ReallySmallRuntime runtime, Composite domainComposite) {
+
+ // Extract the component name
+ String componentName;
+ String serviceName;
+ int i = name.indexOf('/');
+ if (i != -1) {
+ componentName = name.substring(0, i);
+ serviceName = name.substring(i + 1);
+
+ } else {
+ componentName = name;
+ serviceName = null;
+ }
+
+ // Lookup the component
+ Component component = null;
+
+ if ( domainComposite != null ) {
+ for (Composite composite: domainComposite.getIncludes()) {
+ for (Component compositeComponent: composite.getComponents()) {
+ if (compositeComponent.getName().equals(componentName)) {
+ component = compositeComponent;
+ }
+ }
+ }
+ }
+
+ if (component == null) {
+ // look to see of the service exists somewhere else in the domain
+ try {
+ String nodeName = findServiceNode(domainModel.getDomainURI(),
+ name,
+ "org.apache.tuscany.sca.binding.sca.impl.SCABindingImpl");
+
+ if (nodeName.equals(SERVICE_NOT_KNOWN)){
+ throw new ServiceRuntimeException("The service " + name + " has not been contributed to the domain");
+ }
+ } catch (DomainException ex){
+ throw new ServiceRuntimeException(ex);
+ }
+
+ // now create a service reference
+ return createServiceReference(businessInterface, name, runtime, domainComposite);
+ }
+ RuntimeComponentContext componentContext = null;
+
+ // If the component is a composite, then we need to find the
+ // non-composite component that provides the requested service
+ if (component.getImplementation() instanceof Composite) {
+ for (ComponentService componentService : component.getServices()) {
+ if (serviceName == null || serviceName.equals(componentService.getName())) {
+ CompositeService compositeService = (CompositeService)componentService.getService();
+ if (compositeService != null) {
+ if (serviceName != null) {
+ serviceName = "$promoted$." + serviceName;
+ }
+ componentContext =
+ ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext();
+ return componentContext.createSelfReference(businessInterface, compositeService
+ .getPromotedService());
+ }
+ break;
+ }
+ }
+ // No matching service is found
+ throw new ServiceRuntimeException("Composite service not found: " + name);
+ } else {
+ componentContext = ((RuntimeComponent)component).getComponentContext();
+ if (serviceName != null) {
+ return componentContext.createSelfReference(businessInterface, serviceName);
+ } else {
+ return componentContext.createSelfReference(businessInterface);
+ }
+ }
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADummyNodeImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADummyNodeImpl.java
new file mode 100644
index 0000000000..9ecc3e9bc7
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/impl/SCADummyNodeImpl.java
@@ -0,0 +1,80 @@
+ /*
+ * 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.domain.impl;
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.SCANode;
+
+/**
+ * A dummy representation of and SCA Node used simply to allow
+ * CallableReferences in the JVM where the domain is being run
+ * to be looked up
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-09 23:54:46 +0100 (Sun, 09 Sep 2007) $
+ */
+public class SCADummyNodeImpl implements SCANode {
+
+ private SCADomain scaDomain = null;
+
+ public SCADummyNodeImpl(SCADomain scaDomain) {
+ this.scaDomain = scaDomain;
+ }
+
+ // API methods
+
+ public void start() throws NodeException {
+ }
+
+ public void stop() throws NodeException {
+
+ }
+
+ public void destroy() throws NodeException {
+ }
+
+ public String getURI(){
+ return null;
+ }
+
+ public SCADomain getDomain(){
+ return scaDomain;
+ }
+
+ public void addContribution(String contributionURI, URL contributionURL) throws NodeException {
+ }
+
+ public void removeContribution(String contributionURI) throws NodeException {
+ }
+
+ public void addToDomainLevelComposite(QName compositeName) throws NodeException {
+ }
+
+ public void addToDomainLevelComposite(String compositePath) throws NodeException {
+ }
+
+ public void startContribution(String contributionURI) throws NodeException {
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/launch/SCADomainControllerLauncher.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/launch/SCADomainControllerLauncher.java
new file mode 100644
index 0000000000..3b97af33b1
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/launch/SCADomainControllerLauncher.java
@@ -0,0 +1,68 @@
+/*
+ * 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.domain.launch;
+
+import java.io.IOException;
+
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.domain.SCADomainFactory;
+
+/**
+ * Launcher for the Tuscany Domain Controller.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SCADomainControllerLauncher {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ System.out.println("Tuscany Domain Controller starting...");
+
+ SCADomain domain = null;
+ try {
+ SCADomainFactory domainFactory = SCADomainFactory.newInstance();
+ domain = domainFactory.createSCADomain("http://localhost:9999");
+
+ } catch (Exception e) {
+ System.err.println("Exception starting domain controller");
+ e.printStackTrace();
+ System.exit(0);
+ }
+
+ System.out.println("Domain controller ready...");
+ System.out.println("Press enter to shutdown");
+ try {
+ System.in.read();
+ } catch (IOException e) {
+ }
+
+ try {
+ domain.destroy();
+ } catch (Exception e) {
+ System.err.println("Exception stopping domain controller");
+ e.printStackTrace();
+ }
+
+ System.exit(0);
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/ContributionInfoImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/ContributionInfoImpl.java
new file mode 100644
index 0000000000..4bb22b3363
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/ContributionInfoImpl.java
@@ -0,0 +1,89 @@
+/*
+ * 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.domain.management.impl;
+
+import java.io.Serializable;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.domain.management.ContributionInfo;
+/**
+ * Information relating to an exposed service
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class ContributionInfoImpl implements ContributionInfo, Serializable {
+
+ static final long serialVersionUID = 7669181086005969428L;
+
+ private String contributionURI;
+ private URL contributionURL;
+ private List<QName> composites = new ArrayList<QName>();
+ private List<QName> deployableComposites = new ArrayList<QName>();
+
+
+ /**
+ * Retrieve the contribution URI
+ *
+ * @return contribution URI
+ */
+ public String getContributionURI() {
+ return contributionURI;
+ }
+
+ /**
+ * Set the contribution URI
+ *
+ * @param contributionURI
+ */
+ public void setContributionURI(String contributionURI){
+ this.contributionURI = contributionURI;
+ }
+
+ /**
+ * Retrieve the contribution URL
+ *
+ * @return contribution URL
+ */
+ public URL getContributionURL(){
+ return contributionURL;
+ }
+
+ /**
+ * Set the contribution URL
+ *
+ * @param contributionURL
+ */
+ public void setContributionURL(URL contributionURL){
+ this.contributionURL = contributionURL;
+ }
+
+ public List<QName> getComposites(){
+ return composites;
+ }
+
+ public List<QName> getDeployableComposites(){
+ return deployableComposites;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/DomainInfoImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/DomainInfoImpl.java
new file mode 100644
index 0000000000..92b27a0340
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/DomainInfoImpl.java
@@ -0,0 +1,93 @@
+/*
+ * 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.domain.management.impl;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.domain.management.DomainInfo;
+
+/**
+ * A data transport object for the management interface
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class DomainInfoImpl implements DomainInfo, Serializable {
+
+ static final long serialVersionUID = 7669181086005969428L;
+
+ private String domainURI;
+ private String domainURL;
+ private List<String> nodes = new ArrayList<String>();
+ private List<String> contributions = new ArrayList<String>();
+ private List<QName> composites = new ArrayList<QName>();
+
+ /**
+ * Retrieve the domain URI
+ *
+ * @return domain URI
+ */
+ public String getDomainURI(){
+ return domainURI;
+ }
+
+ /**
+ * Set the domain URI
+ *
+ * @param domainURI
+ */
+ public void setDomainURI(String domainURI){
+ this.domainURI = domainURI;
+ }
+
+ /**
+ * Retrieve the domain URL
+ *
+ * @return domain URL
+ */
+ public String getDomainURL(){
+ return domainURL;
+ }
+
+ /**
+ * Set the domain URL
+ *
+ * @param domainURL
+ */
+ public void setDomainURL(String domainURL){
+ this.domainURL = domainURL;
+ }
+
+ public List<String> getNodes(){
+ return nodes;
+ }
+
+ public List<String> getContributions(){
+ return contributions;
+ }
+
+ public List<QName> getDeployedComposites(){
+ return composites;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/NodeInfoImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/NodeInfoImpl.java
new file mode 100644
index 0000000000..41191d5033
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/NodeInfoImpl.java
@@ -0,0 +1,93 @@
+/*
+ * 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.domain.management.impl;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.domain.management.NodeInfo;
+
+/**
+ * Information relating to an exposed service
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class NodeInfoImpl implements NodeInfo, Serializable {
+
+ static final long serialVersionUID = 7669181086005969428L;
+
+ private String nodeURI;
+ private String nodeURL;
+ private List<String> contributions = new ArrayList<String>();
+ private List<QName> composites = new ArrayList<QName>();
+ private List<String> services = new ArrayList<String>();
+
+ /**
+ * Retrieve the node URI
+ *
+ * @return node URI
+ */
+ public String getNodeURI(){
+ return nodeURI;
+ }
+
+ /**
+ * Set the node URI
+ *
+ * @param nodeURI
+ */
+ public void setNodeURI(String nodeURI){
+ this.nodeURI = nodeURI;
+ }
+
+ /**
+ * Retrieve the node URL
+ *
+ * @return node URL
+ */
+ public String getNodeURL() {
+ return nodeURL;
+ }
+
+ /**
+ * Set the node URL
+ *
+ * @param nodeURL
+ */
+ public void setNodeURL(String nodeURL){
+ this.nodeURL = nodeURL;
+ }
+
+ public List<String> getContributions(){
+ return contributions;
+ }
+
+ public List<QName> getDeployedComposites(){
+ return composites;
+ }
+
+ public List<String> getServices(){
+ return services;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/SCADomainManagerServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/SCADomainManagerServiceImpl.java
new file mode 100644
index 0000000000..8cc0b381ec
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/management/impl/SCADomainManagerServiceImpl.java
@@ -0,0 +1,227 @@
+/*
+ * 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.domain.management.impl;
+
+import java.io.Externalizable;
+import java.net.URL;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.domain.DomainException;
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.domain.management.DomainInfo;
+import org.apache.tuscany.sca.domain.management.NodeInfo;
+import org.apache.tuscany.sca.domain.management.SCADomainManagerInitService;
+import org.apache.tuscany.sca.domain.management.SCADomainManagerService;
+import org.apache.tuscany.sca.domain.model.DomainModel;
+import org.apache.tuscany.sca.domain.model.NodeModel;
+import org.apache.tuscany.sca.domain.spi.SCADomainAPIService;
+import org.apache.tuscany.sca.domain.spi.SCADomainEventService;
+import org.apache.tuscany.sca.domain.spi.SCADomainSPI;
+import org.apache.tuscany.sca.node.management.SCANodeManagerService;
+import org.osoa.sca.CallableReference;
+import org.osoa.sca.annotations.Scope;
+import org.osoa.sca.annotations.Service;
+
+
+/**
+ * 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")
+@Service(interfaces = {SCADomainEventService.class, SCADomainManagerInitService.class, SCADomainManagerService.class, SCADomainAPIService.class})
+public class SCADomainManagerServiceImpl implements SCADomainEventService, SCADomainManagerInitService, SCADomainManagerService, SCADomainAPIService {
+
+ private static final Logger logger = Logger.getLogger(SCADomainManagerServiceImpl.class.getName());
+
+ private SCADomain domain;
+ private SCADomainSPI domainSPI;
+ private SCADomainEventService domainEventService;
+
+ // DomainManagerInitService methods
+
+ public void setDomain(SCADomain domain) {
+ this.domain = domain;
+ }
+
+ public void setDomainSPI(SCADomainSPI domainSPI) {
+ this.domainSPI = domainSPI;
+ }
+
+ public void setDomainEventService(SCADomainEventService domainEventService) {
+ this.domainEventService = domainEventService;
+ }
+
+ // DomainEventService methods
+
+ public void registerNode(String nodeURI, String nodeURL, Externalizable nodeManagerReference) throws DomainException{
+ // get a reference to the node manager here so that the CallableReference
+ // the right context to construct itself. Don't actually have to do
+ // anything with the result as the context is cached inside the CallableReference
+ ((CallableReference<SCANodeManagerService>)nodeManagerReference).getService();
+
+ // pass on to the domain
+ domainEventService.registerNode(nodeURI, nodeURL, nodeManagerReference);
+ }
+
+ public void unregisterNode(String nodeURI) throws DomainException {
+ domainEventService.unregisterNode(nodeURI);
+ }
+
+ public void registerNodeStart(String nodeURI) throws DomainException {
+ domainEventService.registerNodeStart(nodeURI);
+ }
+
+ public void registerNodeStop(String nodeURI) throws DomainException {
+ domainEventService.registerNodeStop(nodeURI);
+ }
+
+ public void registerContribution(String nodeURI, String contributionURI, String contributionURL) throws DomainException {
+ domainEventService.registerContribution(nodeURI, contributionURI, contributionURL);
+ }
+
+ public void unregisterContribution(String nodeURI,String contributionURI)throws DomainException {
+ domainEventService.unregisterContribution(nodeURI, contributionURI);
+ }
+
+ public void registerDomainLevelComposite(String nodeURI, String compositeQNameString) throws DomainException{
+ domainEventService.registerDomainLevelComposite(nodeURI, compositeQNameString);
+ }
+
+ public void registerServiceEndpoint(String domainURI, String nodeUri, String serviceName, String bindingName, String URL) throws DomainException {
+ domainEventService.registerServiceEndpoint(domainURI, nodeUri, serviceName, bindingName, URL);
+ }
+
+ public void unregisterServiceEndpoint(String domainURI, String nodeUri, String serviceName, String bindingName) throws DomainException{
+ domainEventService.unregisterServiceEndpoint(domainURI, nodeUri, serviceName, bindingName);
+ }
+
+
+ public String findServiceEndpoint(String domainURI, String serviceName, String bindingName) throws DomainException{
+ return domainEventService.findServiceEndpoint(domainURI, serviceName, bindingName);
+ }
+
+ public String findServiceNode(String domainURI, String serviceName, String bindingName) throws DomainException {
+ return domainEventService.findServiceNode(domainURI, serviceName, bindingName);
+ }
+
+ // DomainAPIService methods
+
+ public void start() throws DomainException {
+ domain.start();
+ }
+
+ public void stop() throws DomainException {
+ domain.stop();
+ }
+
+ public void destroyDomain() throws DomainException {
+ domain.destroy();
+ }
+
+ public String getURI() {
+ return domain.getURI();
+ }
+
+ public void addContribution(String contributionURI, String contributionURL) throws DomainException {
+ try {
+ domain.addContribution(contributionURI, new URL(contributionURL));
+ } catch (Exception ex) {
+ throw new DomainException (ex);
+ }
+ }
+
+ public void updateContribution(String contributionURI, String contributionURL) throws DomainException {
+ try {
+ domain.updateContribution(contributionURI, new URL(contributionURL));
+ } catch (Exception ex) {
+ throw new DomainException (ex);
+ }
+ }
+
+ public void removeContribution(String contributionURI) throws DomainException {
+ domain.removeContribution(contributionURI);
+ }
+
+ public void addDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ domain.addDeploymentComposite(contributionURI, compositeXML);
+ }
+
+ public void updateDeploymentComposite(String contributionURI, String compositeXML) throws DomainException {
+ domain.updateDeploymentComposite(contributionURI, compositeXML);
+ }
+
+ public void addToDomainLevelComposite(String compositeQName) throws DomainException {
+ domain.addToDomainLevelComposite(QName.valueOf(compositeQName));
+ }
+
+ public void removeFromDomainLevelComposite(String compositeQName) throws DomainException {
+ domain.removeFromDomainLevelComposite(QName.valueOf(compositeQName));
+ }
+
+ public String getDomainLevelComposite() throws DomainException {
+ return domain.getDomainLevelComposite();
+ }
+
+ public String getQNameDefinition(String artifact) throws DomainException {
+ return domain.getQNameDefinition(QName.valueOf(artifact));
+ }
+
+ public void startComposite(String compositeQName) throws DomainException {
+ domain.startComposite(QName.valueOf(compositeQName));
+ }
+
+ public void stopComposite(String compositeQName) throws DomainException {
+ domain.stopComposite(QName.valueOf(compositeQName));
+ }
+
+ // DomainManagementService methods
+
+ public DomainInfo getDomainDescription(){
+
+ DomainInfo domainInfo = new DomainInfoImpl();
+ DomainModel domain = domainSPI.getDomainModel();
+
+ domainInfo.setDomainURI(domain.getDomainURI());
+ domainInfo.setDomainURL(domain.getDomainURL());
+ domainInfo.getNodes().addAll(domain.getNodes().keySet());
+ domainInfo.getContributions().addAll(domain.getContributions().keySet());
+ domainInfo.getDeployedComposites().addAll(domain.getDeployedComposites().keySet());
+
+ return domainInfo;
+ }
+
+ public NodeInfo getNodeDescription(String nodeURI){
+
+ NodeInfo nodeInfo = new NodeInfoImpl();
+ DomainModel domain = domainSPI.getDomainModel();
+ NodeModel node = domain.getNodes().get(nodeURI);
+
+ nodeInfo.setNodeURI(nodeURI);
+ nodeInfo.setNodeURL(node.getNodeURL());
+ nodeInfo.getContributions().addAll(node.getContributions().keySet());
+ nodeInfo.getDeployedComposites().addAll(node.getDeployedComposites().keySet());
+ nodeInfo.getServices().addAll(node.getServices().keySet());
+
+ return nodeInfo;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/CompositeModelImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/CompositeModelImpl.java
new file mode 100644
index 0000000000..4f7d3d3e19
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/CompositeModelImpl.java
@@ -0,0 +1,75 @@
+/*
+ * 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.domain.model.impl;
+
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.domain.model.CompositeModel;
+
+
+/**
+ * A wrapper for the assembly model composite
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class CompositeModelImpl implements CompositeModel {
+
+ private QName compositeQName;
+ private Composite composite;
+
+ /**
+ * Retrieve the composite QName
+ *
+ * @return composite QName
+ */
+ public QName getCompositeQName(){
+ return compositeQName;
+ }
+
+ /**
+ * Set the composite QName
+ *
+ * @param compositeQName
+ */
+ public void setCompositeQName(QName compositeQName) {
+ this.compositeQName = compositeQName;
+ }
+
+ /**
+ * Retrieve the assembly composite object
+ *
+ * @return composite
+ */
+ public Composite getComposite(){
+ return composite;
+ }
+
+ /**
+ * Set the assembly composite object
+ *
+ * @param composite
+ */
+ public void setComposite(Composite composite){
+ this.composite = composite;
+ }
+}
+
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ContributionModelImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ContributionModelImpl.java
new file mode 100644
index 0000000000..3c0492a973
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ContributionModelImpl.java
@@ -0,0 +1,110 @@
+/*
+ * 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.domain.model.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.domain.model.CompositeModel;
+import org.apache.tuscany.sca.domain.model.ContributionModel;
+
+/**
+ * A wrapper for the contribution
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class ContributionModelImpl implements ContributionModel {
+
+ private Contribution contribution;
+ private String contributionURI;
+ private String contributionURL;
+ private Map<QName, CompositeModel> composites = new HashMap<QName, CompositeModel>();
+ private Map<QName, CompositeModel> deployableComposites = new HashMap<QName, CompositeModel>();
+ private Map<QName, CompositeModel> deployedComposites = new HashMap<QName, CompositeModel>();
+
+ /**
+ * Retrieve the contribution object
+ *
+ * @return contribution
+ */
+ public Contribution getContribution(){
+ return contribution;
+ }
+
+ /**
+ * Set the contribution object
+ *
+ * @param contribution
+ */
+ public void setContribution(Contribution contribution){
+ this.contribution = contribution;
+ }
+
+ /**
+ * Retrieve the contribution URI
+ *
+ * @return contribution URI
+ */
+ public String getContributionURI() {
+ return contributionURI;
+ }
+
+ /**
+ * Set the contribution URI
+ *
+ * @param contributionURI
+ */
+ public void setContributionURI(String contributionURI){
+ this.contributionURI = contributionURI;
+ }
+
+ /**
+ * Retrieve the contribution URL
+ *
+ * @return contribution URL
+ */
+ public String getContributionURL(){
+ return contributionURL;
+ }
+
+ /**
+ * Set the contribution URL
+ *
+ * @param contributionURL
+ */
+ public void setContributionURL(String contributionURL){
+ this.contributionURL = contributionURL;
+ }
+
+ public Map<QName, CompositeModel> getComposites(){
+ return composites;
+ }
+
+ public Map<QName, CompositeModel> getDeployableComposites(){
+ return deployableComposites;
+ }
+
+ public Map<QName, CompositeModel> getDeployedComposites(){
+ return deployedComposites;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelFactoryImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelFactoryImpl.java
new file mode 100644
index 0000000000..90c1b47e48
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelFactoryImpl.java
@@ -0,0 +1,80 @@
+/*
+ * 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.domain.model.impl;
+
+import org.apache.tuscany.sca.domain.model.CompositeModel;
+import org.apache.tuscany.sca.domain.model.ContributionModel;
+import org.apache.tuscany.sca.domain.model.DomainModel;
+import org.apache.tuscany.sca.domain.model.DomainModelFactory;
+import org.apache.tuscany.sca.domain.model.NodeModel;
+import org.apache.tuscany.sca.domain.model.ServiceModel;
+
+/**
+ * The factory used to create model elements
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class DomainModelFactoryImpl implements DomainModelFactory {
+
+ /**
+ * Create a new domain model
+ *
+ * @return new domain model
+ */
+ public DomainModel createDomain(){
+ return new DomainModelImpl();
+ }
+ /**
+ * Create a new node model
+ *
+ * @return new node model
+ */
+ public NodeModel createNode(){
+ return new NodeModelImpl();
+ }
+
+ /**
+ * Create a new contribution model
+ *
+ * @return new contribution model
+ */
+ public ContributionModel createContribution(){
+ return new ContributionModelImpl();
+ }
+
+ /**
+ * Create a new composite model
+ *
+ * @return new composite model
+ */
+ public CompositeModel createComposite(){
+ return new CompositeModelImpl();
+ }
+
+ /**
+ * Create a new service model
+ *
+ * @return new service model
+ */
+ public ServiceModel createService(){
+ return new ServiceModelImpl();
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelImpl.java
new file mode 100644
index 0000000000..d3b77bd4bb
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/DomainModelImpl.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.domain.model.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.domain.model.CompositeModel;
+import org.apache.tuscany.sca.domain.model.ContributionModel;
+import org.apache.tuscany.sca.domain.model.NodeModel;
+import org.apache.tuscany.sca.domain.model.DomainModel;
+
+
+/**
+ * A model of the domain and the artifacts that it managers. Acts as a holder for the
+ * various other Tuscany models involved
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class DomainModelImpl implements DomainModel {
+
+ private String domainURI;
+ private String domainURL;
+ private Map<String, NodeModel> nodes = new HashMap<String, NodeModel>();
+ private Map<String, ContributionModel> contributions = new HashMap<String, ContributionModel>();
+ private Map<QName, CompositeModel> deployedComposites = new HashMap<QName, CompositeModel>();
+ private Composite domainLevelComposite;
+
+
+ /**
+ * Retrieve the domain URI
+ *
+ * @return domain URI
+ */
+ public String getDomainURI(){
+ return domainURI;
+ }
+
+ /**
+ * Set the domain URI
+ *
+ * @param domainURI
+ */
+ public void setDomainURI(String domainURI){
+ this.domainURI = domainURI;
+ }
+
+ /**
+ * Retrieve the domain URL
+ *
+ * @return domain URL
+ */
+ public String getDomainURL(){
+ return domainURL;
+ }
+
+ /**
+ * Set the domain level composite
+ *
+ * @param domainLevelComposite
+ */
+ public void setDomainLevelComposite(Composite domainLevelComposite){
+ this.domainLevelComposite = domainLevelComposite;
+ }
+
+ /**
+ * Retrieve the domain level composite
+ *
+ * @return domainLevelComposite
+ */
+ public Composite getDomainLevelComposite(){
+ return domainLevelComposite;
+ }
+
+ /**
+ * Set the domain URL
+ *
+ * @param domainURL
+ */
+ public void setDomainURL(String domainURL){
+ this.domainURL = domainURL;
+ }
+
+ public Map<String, NodeModel> getNodes(){
+ return nodes;
+ }
+
+ public Map<String, ContributionModel> getContributions(){
+ return contributions;
+ }
+
+ public Map<QName, CompositeModel> getDeployedComposites(){
+ return deployedComposites;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/NodeModelImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/NodeModelImpl.java
new file mode 100644
index 0000000000..6e153a93bd
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/NodeModelImpl.java
@@ -0,0 +1,143 @@
+/*
+ * 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.domain.model.impl;
+
+import java.io.Externalizable;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.domain.model.CompositeModel;
+import org.apache.tuscany.sca.domain.model.ContributionModel;
+import org.apache.tuscany.sca.domain.model.NodeModel;
+import org.apache.tuscany.sca.domain.model.ServiceModel;
+import org.apache.tuscany.sca.node.management.SCANodeManagerService;
+import org.osoa.sca.CallableReference;
+
+
+/**
+ * A node. Runs SCA composites
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class NodeModelImpl implements NodeModel {
+
+ private LifecyleState state = LifecyleState.AVAILABLE;
+ private String nodeURI;
+ private String nodeURL;
+ private Externalizable nodeManagerReference;
+ private Map<String, ContributionModel> contributions = new HashMap<String, ContributionModel>();
+ private Map<QName, CompositeModel> deployedComposites = new HashMap<QName, CompositeModel>();
+ private Map<String, ServiceModel> services = new HashMap<String, ServiceModel>();
+
+ /**
+ * Retrieve the node URI
+ *
+ * @return node URI
+ */
+ public String getNodeURI(){
+ return nodeURI;
+ }
+
+ /**
+ * Set the node URI
+ *
+ * @param nodeURI
+ */
+ public void setNodeURI(String nodeURI){
+ this.nodeURI = nodeURI;
+ }
+
+ /**
+ * Retrieve the node URL
+ *
+ * @return node URL
+ */
+ public String getNodeURL() {
+ return nodeURL;
+ }
+
+ /**
+ * Set the node URL
+ *
+ * @param nodeURL
+ */
+ public void setNodeURL(String nodeURL){
+ this.nodeURL = nodeURL;
+ }
+
+ /**
+ * Returns the state of the node
+ *
+ * @return state
+ */
+ public LifecyleState getLifecycleState(){
+ return state;
+ }
+
+ /**
+ * Set the state of the node
+ *
+ * @param state
+ */
+ public void setLifecycleState(LifecyleState state){
+ this.state = state;
+ }
+
+ /**
+ * Retrieve the node manager reference
+ *
+ * @return node manager reference
+ */
+ public Externalizable getNodeManagerReference(){
+ return nodeManagerReference;
+ }
+
+ /**
+ * Set the node URL
+ *
+ * @param nodeURL
+ */
+ public void setNodeManagerReference(Externalizable nodeManagerReference){
+ this.nodeManagerReference = nodeManagerReference;
+ }
+
+ /**
+ * Get the service proxy for the node manager
+ *
+ * @return node manager service proxy
+ */
+ public SCANodeManagerService getSCANodeManagerService(){
+ return ((CallableReference<SCANodeManagerService>)nodeManagerReference).getService();
+ }
+
+ public Map<String, ContributionModel> getContributions(){
+ return contributions;
+ }
+
+ public Map<QName, CompositeModel> getDeployedComposites(){
+ return deployedComposites;
+ }
+
+ public Map<String, ServiceModel> getServices(){
+ return services;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ServiceModelImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ServiceModelImpl.java
new file mode 100644
index 0000000000..46a5f6f5e7
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/java/org/apache/tuscany/sca/domain/model/impl/ServiceModelImpl.java
@@ -0,0 +1,89 @@
+/*
+ * 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.domain.model.impl;
+
+import org.apache.tuscany.sca.domain.model.ServiceModel;
+
+/**
+ * A service.
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $
+ */
+public class ServiceModelImpl implements ServiceModel {
+
+ private String serviceURI;
+ private String serviceURL;
+ private String serviceBinding;
+
+ /**
+ * Retrieve the service URI
+ *
+ * @return service URI
+ */
+ public String getServiceURI(){
+ return serviceURI;
+ }
+
+ /**
+ * Set the service URI
+ *
+ * @param serviceURI
+ */
+ public void setServiceURI(String serviceURI){
+ this.serviceURI = serviceURI;
+ }
+
+ /**
+ * Retrieve the service URL
+ *
+ * @return service URL
+ */
+ public String getServiceURL(){
+ return serviceURL;
+ }
+
+ /**
+ * Set the service URL
+ *
+ * @param serviceURL
+ */
+ public void setServiceURL(String serviceURL){
+ this.serviceURL = serviceURL;
+ }
+
+
+ /**
+ * Retrieve the service binding
+ *
+ * @return service binding
+ */
+ public String getServiceBinding(){
+ return serviceBinding;
+ }
+
+ /**
+ * Set the service binding
+ *
+ * @param serviceBinding
+ */
+ public void setServiceBinding(String serviceBinding){
+ this.serviceBinding = serviceBinding;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/domain.composite b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/domain.composite
new file mode 100644
index 0000000000..a68a4b1ab3
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/domain.composite
@@ -0,0 +1,52 @@
+<?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://tuscany.apache.org/xmlns/tuscany/1.0"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"
+ name="Domain">
+
+ <component name="domain">
+ <t:implementation.resource location="webroot"/>
+ <service name="Resource">
+ <t:binding.http/>
+ </service>
+ </component>
+
+ <component name="SCADomainManagerComponent">
+ <implementation.java class="org.apache.tuscany.sca.domain.management.impl.SCADomainManagerServiceImpl"/>
+ <service name="SCADomainManagerInitService">
+ <interface.java interface="org.apache.tuscany.sca.domain.management.SCADomainManagerInitService"/>
+ <binding.sca/>
+ </service>
+ <service name="SCADomainManagerService">
+ <interface.java interface="org.apache.tuscany.sca.domain.management.SCADomainManagerService"/>
+ <t:binding.jsonrpc/>
+ </service>
+ <service name="SCADomainEventService">
+ <interface.java interface="org.apache.tuscany.sca.domain.spi.SCADomainEventService"/>
+ <binding.ws/>
+ </service>
+ <service name="SCADomainAPIService">
+ <interface.java interface="org.apache.tuscany.sca.domain.spi.SCADomainAPIService"/>
+ <binding.ws/>
+ </service>
+ </component>
+
+</composite>
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/binding-jsonrpc.js b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/binding-jsonrpc.js
new file mode 100644
index 0000000000..ca3c2a8605
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/binding-jsonrpc.js
@@ -0,0 +1,492 @@
+/*
+ * JSON-RPC JavaScript client
+ *
+ * $Id: jsonrpc.js,v 1.36.2.3 2006/03/08 15:09:37 mclark Exp $
+ *
+ * Copyright (c) 2003-2004 Jan-Klaas Kollhof
+ * Copyright (c) 2005 Michael Clark, Metaparadigm Pte Ltd
+ *
+ * This code is based on Jan-Klaas' JavaScript o lait library (jsolait).
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Modifications for Apache Tuscany:
+ * - JSONRpcClient_createMethod changed so callback is last arg
+ */
+
+/* escape a character */
+
+escapeJSONChar =
+function escapeJSONChar(c)
+{
+ if(c == "\"" || c == "\\") return "\\" + c;
+ else if (c == "\b") return "\\b";
+ else if (c == "\f") return "\\f";
+ else if (c == "\n") return "\\n";
+ else if (c == "\r") return "\\r";
+ else if (c == "\t") return "\\t";
+ var hex = c.charCodeAt(0).toString(16);
+ if(hex.length == 1) return "\\u000" + hex;
+ else if(hex.length == 2) return "\\u00" + hex;
+ else if(hex.length == 3) return "\\u0" + hex;
+ else return "\\u" + hex;
+};
+
+
+/* encode a string into JSON format */
+
+escapeJSONString =
+function escapeJSONString(s)
+{
+ /* The following should suffice but Safari's regex is b0rken
+ (doesn't support callback substitutions)
+ return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g,
+ escapeJSONChar) + "\"";
+ */
+
+ /* Rather inefficient way to do it */
+ var parts = s.split("");
+ for(var i=0; i < parts.length; i++) {
+ var c =parts[i];
+ if(c == '"' ||
+ c == '\\' ||
+ c.charCodeAt(0) < 32 ||
+ c.charCodeAt(0) >= 128)
+ parts[i] = escapeJSONChar(parts[i]);
+ }
+ return "\"" + parts.join("") + "\"";
+};
+
+
+/* Marshall objects to JSON format */
+
+toJSON = function toJSON(o)
+{
+ if(o == null) {
+ return "null";
+ } else if(o.constructor == String) {
+ return escapeJSONString(o);
+ } else if(o.constructor == Number) {
+ return o.toString();
+ } else if(o.constructor == Boolean) {
+ return o.toString();
+ } else if(o.constructor == Date) {
+ return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}';
+ } else if(o.constructor == Array) {
+ var v = [];
+ for(var i = 0; i < o.length; i++) v.push(toJSON(o[i]));
+ return "[" + v.join(", ") + "]";
+ } else {
+ var v = [];
+ for(attr in o) {
+ if(o[attr] == null) v.push("\"" + attr + "\": null");
+ else if(typeof o[attr] == "function"); /* skip */
+ else v.push(escapeJSONString(attr) + ": " + toJSON(o[attr]));
+ }
+ return "{" + v.join(", ") + "}";
+ }
+};
+
+
+/* JSONRpcClient constructor */
+
+JSONRpcClient =
+function JSONRpcClient_ctor(serverURL, user, pass, objectID)
+{
+ this.serverURL = serverURL;
+ this.user = user;
+ this.pass = pass;
+ this.objectID = objectID;
+
+ /* Add standard methods */
+ if(this.objectID) {
+ this._addMethods(["listMethods"]);
+ var req = this._makeRequest("listMethods", []);
+ } else {
+ this._addMethods(["system.listMethods"]);
+ var req = this._makeRequest("system.listMethods", []);
+ }
+ var m = this._sendRequest(req);
+ this._addMethods(m);
+};
+
+
+/* JSONRpcCLient.Exception */
+
+JSONRpcClient.Exception =
+function JSONRpcClient_Exception_ctor(code, message, javaStack)
+{
+ this.code = code;
+ var name;
+ if(javaStack) {
+ this.javaStack = javaStack;
+ var m = javaStack.match(/^([^:]*)/);
+ if(m) name = m[0];
+ }
+ if(name) this.name = name;
+ else this.name = "JSONRpcClientException";
+ this.message = message;
+};
+
+JSONRpcClient.Exception.CODE_REMOTE_EXCEPTION = 490;
+JSONRpcClient.Exception.CODE_ERR_CLIENT = 550;
+JSONRpcClient.Exception.CODE_ERR_PARSE = 590;
+JSONRpcClient.Exception.CODE_ERR_NOMETHOD = 591;
+JSONRpcClient.Exception.CODE_ERR_UNMARSHALL = 592;
+JSONRpcClient.Exception.CODE_ERR_MARSHALL = 593;
+
+JSONRpcClient.Exception.prototype = new Error();
+
+JSONRpcClient.Exception.prototype.toString =
+function JSONRpcClient_Exception_toString(code, msg)
+{
+ return this.name + ": " + this.message;
+};
+
+
+/* Default top level exception handler */
+
+JSONRpcClient.default_ex_handler =
+function JSONRpcClient_default_ex_handler(e) { alert(e); };
+
+
+/* Client settable variables */
+
+JSONRpcClient.toplevel_ex_handler = JSONRpcClient.default_ex_handler;
+JSONRpcClient.profile_async = false;
+JSONRpcClient.max_req_active = 1;
+JSONRpcClient.requestId = 1;
+
+
+/* JSONRpcClient implementation */
+
+JSONRpcClient.prototype._createMethod =
+function JSONRpcClient_createMethod(methodName)
+{
+ var fn=function()
+ {
+ var args = [];
+ var callback = null;
+ for(var i=0;i<arguments.length;i++) args.push(arguments[i]);
+
+/* TUSCANY change callback to be last arg instead of first to match binding.ajax
+ if(typeof args[0] == "function") callback = args.shift();
+*/
+ if(typeof args[arguments.length-1] == "function") callback = args.pop();
+
+ var req = fn.client._makeRequest.call(fn.client, fn.methodName,
+ args, callback);
+ if(callback == null) {
+ return fn.client._sendRequest.call(fn.client, req);
+ } else {
+ JSONRpcClient.async_requests.push(req);
+ JSONRpcClient.kick_async();
+ return req.requestId;
+ }
+ };
+ fn.client = this;
+ fn.methodName = methodName;
+ return fn;
+};
+
+JSONRpcClient.prototype._addMethods =
+function JSONRpcClient_addMethods(methodNames)
+{
+ for(var i=0; i<methodNames.length; i++) {
+ var obj = this;
+ var names = methodNames[i].split(".");
+ for(var n=0; n<names.length-1; n++) {
+ var name = names[n];
+ if(obj[name]) {
+ obj = obj[name];
+ } else {
+ obj[name] = new Object();
+ obj = obj[name];
+ }
+ }
+ var name = names[names.length-1];
+ if(!obj[name]) {
+ var method = this._createMethod(methodNames[i]);
+ obj[name] = method;
+ }
+ }
+};
+
+JSONRpcClient._getCharsetFromHeaders =
+function JSONRpcClient_getCharsetFromHeaders(http)
+{
+ try {
+ var contentType = http.getResponseHeader("Content-type");
+ var parts = contentType.split(/\s*;\s*/);
+ for(var i =0; i < parts.length; i++) {
+ if(parts[i].substring(0, 8) == "charset=")
+ return parts[i].substring(8, parts[i].length);
+ }
+ } catch (e) {}
+ return "UTF-8"; /* default */
+};
+
+/* Async queue globals */
+JSONRpcClient.async_requests = [];
+JSONRpcClient.async_inflight = {};
+JSONRpcClient.async_responses = [];
+JSONRpcClient.async_timeout = null;
+JSONRpcClient.num_req_active = 0;
+
+JSONRpcClient._async_handler =
+function JSONRpcClient_async_handler()
+{
+ JSONRpcClient.async_timeout = null;
+
+ while(JSONRpcClient.async_responses.length > 0) {
+ var res = JSONRpcClient.async_responses.shift();
+ if(res.canceled) continue;
+ if(res.profile) res.profile.dispatch = new Date();
+ try {
+ res.cb(res.result, res.ex, res.profile);
+ } catch(e) {
+ JSONRpcClient.toplevel_ex_handler(e);
+ }
+ }
+
+ while(JSONRpcClient.async_requests.length > 0 &&
+ JSONRpcClient.num_req_active < JSONRpcClient.max_req_active) {
+ var req = JSONRpcClient.async_requests.shift();
+ if(req.canceled) continue;
+ req.client._sendRequest.call(req.client, req);
+ }
+};
+
+JSONRpcClient.kick_async =
+function JSONRpcClient_kick_async()
+{
+ if(JSONRpcClient.async_timeout == null)
+ JSONRpcClient.async_timeout =
+ setTimeout(JSONRpcClient._async_handler, 0);
+};
+
+JSONRpcClient.cancelRequest =
+function JSONRpcClient_cancelRequest(requestId)
+{
+ /* If it is in flight then mark it as canceled in the inflight map
+ and the XMLHttpRequest callback will discard the reply. */
+ if(JSONRpcClient.async_inflight[requestId]) {
+ JSONRpcClient.async_inflight[requestId].canceled = true;
+ return true;
+ }
+
+ /* If its not in flight yet then we can just mark it as canceled in
+ the the request queue and it will get discarded before being sent. */
+ for(var i in JSONRpcClient.async_requests) {
+ if(JSONRpcClient.async_requests[i].requestId == requestId) {
+ JSONRpcClient.async_requests[i].canceled = true;
+ return true;
+ }
+ }
+
+ /* It may have returned from the network and be waiting for its callback
+ to be dispatched, so mark it as canceled in the response queue
+ and the response will get discarded before calling the callback. */
+ for(var i in JSONRpcClient.async_responses) {
+ if(JSONRpcClient.async_responses[i].requestId == requestId) {
+ JSONRpcClient.async_responses[i].canceled = true;
+ return true;
+ }
+ }
+
+ return false;
+};
+
+JSONRpcClient.prototype._makeRequest =
+function JSONRpcClient_makeRequest(methodName, args, cb)
+{
+ var req = {};
+ req.client = this;
+ req.requestId = JSONRpcClient.requestId++;
+
+ var obj = {};
+ obj.id = req.requestId;
+ if (this.objectID)
+ obj.method = ".obj#" + this.objectID + "." + methodName;
+ else
+ obj.method = methodName;
+ obj.params = args;
+
+ if (cb) req.cb = cb;
+ if (JSONRpcClient.profile_async)
+ req.profile = { "submit": new Date() };
+ req.data = toJSON(obj);
+
+ return req;
+};
+
+JSONRpcClient.prototype._sendRequest =
+function JSONRpcClient_sendRequest(req)
+{
+ if(req.profile) req.profile.start = new Date();
+
+ /* Get free http object from the pool */
+ var http = JSONRpcClient.poolGetHTTPRequest();
+ JSONRpcClient.num_req_active++;
+
+ /* Send the request */
+ if (typeof(this.user) == "undefined") {
+ http.open("POST", this.serverURL, (req.cb != null));
+ } else {
+ http.open("POST", this.serverURL, (req.cb != null), this.user, this.pass);
+ }
+
+ /* setRequestHeader is missing in Opera 8 Beta */
+ try { http.setRequestHeader("Content-type", "text/plain"); } catch(e) {}
+
+ /* Construct call back if we have one */
+ if(req.cb) {
+ var self = this;
+ http.onreadystatechange = function() {
+ if(http.readyState == 4) {
+ http.onreadystatechange = function () {};
+ var res = { "cb": req.cb, "result": null, "ex": null};
+ if (req.profile) {
+ res.profile = req.profile;
+ res.profile.end = new Date();
+ }
+ try { res.result = self._handleResponse(http); }
+ catch(e) { res.ex = e; }
+ if(!JSONRpcClient.async_inflight[req.requestId].canceled)
+ JSONRpcClient.async_responses.push(res);
+ delete JSONRpcClient.async_inflight[req.requestId];
+ JSONRpcClient.kick_async();
+ }
+ };
+ } else {
+ http.onreadystatechange = function() {};
+ }
+
+ JSONRpcClient.async_inflight[req.requestId] = req;
+
+ try {
+ http.send(req.data);
+ } catch(e) {
+ JSONRpcClient.poolReturnHTTPRequest(http);
+ JSONRpcClient.num_req_active--;
+ throw new JSONRpcClient.Exception
+ (JSONRpcClient.Exception.CODE_ERR_CLIENT, "Connection failed");
+ }
+
+ if(!req.cb) return this._handleResponse(http);
+};
+
+JSONRpcClient.prototype._handleResponse =
+function JSONRpcClient_handleResponse(http)
+{
+ /* Get the charset */
+ if(!this.charset) {
+ this.charset = JSONRpcClient._getCharsetFromHeaders(http);
+ }
+
+ /* Get request results */
+ var status, statusText, data;
+ try {
+ status = http.status;
+ statusText = http.statusText;
+ data = http.responseText;
+ } catch(e) {
+ JSONRpcClient.poolReturnHTTPRequest(http);
+ JSONRpcClient.num_req_active--;
+ JSONRpcClient.kick_async();
+ throw new JSONRpcClient.Exception
+ (JSONRpcClient.Exception.CODE_ERR_CLIENT, "Connection failed");
+ }
+
+ /* Return http object to the pool; */
+ JSONRpcClient.poolReturnHTTPRequest(http);
+ JSONRpcClient.num_req_active--;
+
+ /* Unmarshall the response */
+ if(status != 200) {
+ throw new JSONRpcClient.Exception(status, statusText);
+ }
+ var obj;
+ try {
+ eval("obj = " + data);
+ } catch(e) {
+ throw new JSONRpcClient.Exception(550, "error parsing result");
+ }
+ if(obj.error)
+ throw new JSONRpcClient.Exception(obj.error.code, obj.error.msg,
+ obj.error.trace);
+ var res = obj.result;
+
+ /* Handle CallableProxy */
+ if(res && res.objectID && res.JSONRPCType == "CallableReference")
+ return new JSONRpcClient(this.serverURL, this.user,
+ this.pass, res.objectID);
+
+ return res;
+};
+
+
+/* XMLHttpRequest wrapper code */
+
+/* XMLHttpRequest pool globals */
+JSONRpcClient.http_spare = [];
+JSONRpcClient.http_max_spare = 8;
+
+JSONRpcClient.poolGetHTTPRequest =
+function JSONRpcClient_pool_getHTTPRequest()
+{
+ if(JSONRpcClient.http_spare.length > 0) {
+ return JSONRpcClient.http_spare.pop();
+ }
+ return JSONRpcClient.getHTTPRequest();
+};
+
+JSONRpcClient.poolReturnHTTPRequest =
+function JSONRpcClient_poolReturnHTTPRequest(http)
+{
+ if(JSONRpcClient.http_spare.length >= JSONRpcClient.http_max_spare)
+ delete http;
+ else
+ JSONRpcClient.http_spare.push(http);
+};
+
+JSONRpcClient.msxmlNames = [ "MSXML2.XMLHTTP.5.0",
+ "MSXML2.XMLHTTP.4.0",
+ "MSXML2.XMLHTTP.3.0",
+ "MSXML2.XMLHTTP",
+ "Microsoft.XMLHTTP" ];
+
+JSONRpcClient.getHTTPRequest =
+function JSONRpcClient_getHTTPRequest()
+{
+ /* Mozilla XMLHttpRequest */
+ try {
+ JSONRpcClient.httpObjectName = "XMLHttpRequest";
+ return new XMLHttpRequest();
+ } catch(e) {}
+
+ /* Microsoft MSXML ActiveX */
+ for (var i=0;i < JSONRpcClient.msxmlNames.length; i++) {
+ try {
+ JSONRpcClient.httpObjectName = JSONRpcClient.msxmlNames[i];
+ return new ActiveXObject(JSONRpcClient.msxmlNames[i]);
+ } catch (e) {}
+ }
+
+ /* None found */
+ JSONRpcClient.httpObjectName = null;
+ throw new JSONRpcClient.Exception(0, "Can't create XMLHttpRequest object");
+};
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/domain.png b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/domain.png
new file mode 100644
index 0000000000..e88c4f882a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/domain.png
Binary files differ
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/index.html b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/index.html
new file mode 100644
index 0000000000..4320a52b4c
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/index.html
@@ -0,0 +1,139 @@
+<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 Domain Debug</TITLE>
+
+ <script type="text/javascript" src="binding-jsonrpc.js"></script>
+
+ <script language="JavaScript">
+
+ domainManager = new JSONRpcClient("../SCADomainManagerComponent/SCADomainManagerService").Service;
+ var domainInfo;
+
+ function getDomainInfo() {
+ domainManager.getDomainDescription(handleGetDomainInfo);
+ }
+
+ function handleGetDomainInfo(result) {
+
+ domainInfo = result;
+ var text = "";
+ document.getElementById('domainName').innerHTML="Domain:&nbsp;&nbsp;" + domainInfo.domainURI;
+
+ text = text + "<H2>Nodes</H2>";
+
+ for (var i in domainInfo.nodes){
+ var nodeURI = domainInfo.nodes[i];
+
+ text = text + "<table>";
+ text = text + "<TR CLASS='source_1' >";
+ text = text + " <TD CLASS='clickable link' ONCLICK=\"getNodeInfo('" + nodeURI + "')\">" ;
+ text = text + " <IMG SRC='node.png'/>&nbsp;&nbsp;" + nodeURI;
+ text = text + " </TD>";
+ //text = text + " <TD CLASS='clickable link' ONCLICK=\"showNode('" + node.nodeURI + "')\">" + nodeManagerWebUrl + "</TD>";
+ text = text + "</TR>";
+ text = text + "<div id=\"" + nodeURI + "\">";
+ text = text + "</table>";
+ }
+
+ text = text + "<H2>Domain Contributions</H2>";
+
+ for (var i in domainInfo.contributions){
+ var contributionURI = domainInfo.contributions[i];
+ text = text + "<table>";
+ text = text + "<TR CLASS='source_1' >";
+ text = text + " <TD>";
+ text = text + " <IMG SRC='node.png'/>&nbsp;&nbsp;" + contributionURI;
+ text = text + " </TD>";
+ text = text + "</TR>";
+ text = text + "</table>";
+ }
+
+ text = text + "<H2>Deployable Composites</H2>";
+
+ for (var i in domainInfo.deployedComposites){
+ var compositeQName = domainInfo.deployedComposites[i];
+ text = text + "<table>";
+ text = text + "<TR CLASS='source_1' >";
+ text = text + " <TD>";
+ text = text + " <IMG SRC='node.png'/>&nbsp;&nbsp;" + compositeQName.namespaceURI + "#" + compositeQName.localPart;
+ text = text + " </TD>";
+ text = text + "</TR>";
+ text = text + "</table>";
+ }
+
+ document.getElementById('domainInfo').innerHTML=text;
+ }
+
+ function getNodeInfo(nodeURI) {
+ domainManager.getNodeDescription(nodeURI, handleGetNodeInfo);
+ }
+
+ function handleGetNodeInfo(result) {
+
+ var nodeInfo = result;
+ var text = "";
+
+
+ for (var i in nodeInfo.contributions){
+ var contributionURI = nodeInfo.contributions[i];
+
+ text = text + "<TR CLASS='source_2' >";
+ text = text + " <TD/>";
+ text = text + " <TD>";
+ text = text + "&nbsp;&nbsp;" + contributionURI;
+ text = text + " </TD>";
+ text = text + "</TR>";
+ }
+
+ document.getElementById(nodeInfo.nodeURI).innerHTML=text;
+ }
+
+ function showNode(url)
+ {
+ document.getElementById("nodePage").innerHTML="<IFRAME CLASS='alert_data' SRC='"+url+"'/>";
+ window.location="#data";
+ return;
+ }
+
+ </script>
+
+ <link rel="stylesheet" type="text/css" href="style.css" />
+</head>
+
+<body onload="getDomainInfo()">
+
+<h1 id="top">Apache Tuscany Domain Debug</h1>
+<div id="errors"></div>
+
+<table>
+<TR>
+<TD>
+<div id="domainName"></div>
+</TD>
+</TR>
+</table>
+
+<div id="domainInfo"></div>
+
+<p /><input type="button" value="Refresh" onclick="getDomainInfo()" />
+
+</body>
+</html>
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/node.png b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/node.png
new file mode 100644
index 0000000000..fa01e64272
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/node.png
Binary files differ
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/style.css b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/main/resources/webroot/style.css
new file mode 100644
index 0000000000..28a4d4540c
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/AddService.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/AddService.java
new file mode 100644
index 0000000000..1c115bb92d
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/AddServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/AddServiceImpl.java
new file mode 100644
index 0000000000..f52e42f497
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/CalculatorService.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/CalculatorService.java
new file mode 100644
index 0000000000..03c9b5947a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/CalculatorService.java
@@ -0,0 +1,37 @@
+/*
+ * 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 Calculator service interface.
+ *
+ * @version $Rev$ $Date$
+ */
+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/domain-impl/src/test/java/calculator/CalculatorServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/CalculatorServiceImpl.java
new file mode 100644
index 0000000000..4f11e02e0d
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/DivideService.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/DivideService.java
new file mode 100644
index 0000000000..3373eb2c7a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/DivideServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/DivideServiceImpl.java
new file mode 100644
index 0000000000..0421c217e0
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/MultiplyService.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/MultiplyService.java
new file mode 100644
index 0000000000..783a7eccd6
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/MultiplyServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/MultiplyServiceImpl.java
new file mode 100644
index 0000000000..f93e614a08
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/SubtractService.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/SubtractService.java
new file mode 100644
index 0000000000..eb32e26896
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/calculator/SubtractServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/calculator/SubtractServiceImpl.java
new file mode 100644
index 0000000000..c9e2f2e314
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/DomainImplTestCaseOFF.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/DomainImplTestCaseOFF.java
new file mode 100644
index 0000000000..d84bd4e17a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/DomainImplTestCaseOFF.java
@@ -0,0 +1,133 @@
+/*
+ * 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.domain.impl;
+
+import java.io.Externalizable;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.domain.SCADomain;
+import org.apache.tuscany.sca.domain.SCADomainFactory;
+import org.apache.tuscany.sca.domain.spi.SCADomainEventService;
+import org.apache.tuscany.sca.node.management.SCANodeManagerService;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.osoa.sca.CallableReference;
+
+
+/**
+ * This server program that loads a composite to provide simple registry function.
+ * This server can be replaced with any registry that is appropriate but the components
+ * in each node that talk to the registry should be replaced also.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DomainImplTestCaseOFF {
+
+ private static SCADomain domain;
+ private static SCADomainEventService domainEventService;
+ private static ClassLoader cl;
+
+ @BeforeClass
+ public static void init() throws Exception {
+
+ try {
+ cl = DomainImplTestCaseOFF.class.getClassLoader();
+ SCADomainFactory domainFactory = SCADomainFactory.newInstance();
+ domain = domainFactory.createSCADomain("http://localhost:9999");
+ domainEventService = (SCADomainEventService)domain;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("Domain started");
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ // stop the domain
+ domain.destroy();
+ System.out.println("Domain stopped");
+ }
+
+ @Test
+ public void testRegisterNodes() throws Exception {
+ CallableReference<SCANodeManagerService> node1Ref = new TestCallableReferenceImpl<SCANodeManagerService>();
+ domainEventService.registerNode("http://localhost:8100/mynode1", "http://localhost:9999", (Externalizable)node1Ref);
+
+ CallableReference<SCANodeManagerService> node2Ref = new TestCallableReferenceImpl<SCANodeManagerService>();
+ domainEventService.registerNode("http://localhost:8200/mynode2", "http://localhost:9999", (Externalizable)node2Ref);
+ }
+
+ @Test
+ public void testAddContributionWithMetaData() throws Exception {
+ domain.addContribution("contributionNodeA", cl.getResource("nodeA/"));
+ }
+
+ @Test
+ public void testAddContributionWithoutMetaData() throws Exception {
+ domain.addContribution("contributionNodeB", cl.getResource("nodeB/"));
+ }
+
+ @Test
+ public void testAddToDomainLevelComposite() throws Exception {
+ domain.addToDomainLevelComposite(new QName("http://sample", "CalculatorA"));
+ }
+
+ @Test
+ public void testGetDomainLevelComposite() throws Exception {
+ System.out.println(domain.getDomainLevelComposite());
+ }
+
+ @Test
+ public void testGetComposite() throws Exception {
+ System.out.println(((SCADomainImpl)domain).getComposite(new QName("http://sample", "CalculatorA")));
+ }
+
+ @Test
+ public void testStartComposite() throws Exception {
+ domain.startComposite(new QName("http://sample", "CalculatorA"));
+ }
+
+ @Test
+ public void testStopComposite() throws Exception {
+ domain.stopComposite(new QName("http://sample", "CalculatorA"));
+ }
+
+ @Test
+ public void testRemoveContributions() throws Exception {
+ domain.removeContribution("contributionNodeA");
+ domain.removeContribution("contributionNodeB");
+ }
+
+ @Test
+ public void testUnregisterNodes() throws Exception {
+ domainEventService.unregisterNode("http://localhost:8100/mynode1");
+ domainEventService.unregisterNode("http://localhost:8200/mynode2");
+ }
+
+ //@Test
+ public void testKeepServerRunning() throws Exception {
+ System.out.println("press enter to continue");
+ System.in.read();
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestCallableReferenceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestCallableReferenceImpl.java
new file mode 100644
index 0000000000..ff4b96ac0e
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestCallableReferenceImpl.java
@@ -0,0 +1,84 @@
+/*
+ * 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.domain.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.osoa.sca.CallableReference;
+import org.osoa.sca.Conversation;
+
+/**
+ * Test Callablereference used to test the domain when no nodes are running
+ *
+ * @param <B> the type of the business interface
+ * @version $Rev$ $Date$
+ */
+public class TestCallableReferenceImpl<B> implements CallableReference<B>, Externalizable {
+
+ protected TestCallableReferenceImpl() {
+ super();
+ }
+
+ public RuntimeWire getRuntimeWire() {
+ return null;
+ }
+
+ public B getProxy() throws ObjectCreationException {
+ return null;
+ }
+
+ public B getService() {
+ return (B) new TestNodeManagerServiceImpl();
+ }
+
+ public Class<B> getBusinessInterface() {
+ return null;
+ }
+
+ public boolean isConversational() {
+ return false;
+ }
+
+ public Conversation getConversation() {
+ return null;
+ }
+
+ public Object getCallbackID() {
+ return null;
+ }
+
+ /**
+ * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
+ */
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ }
+
+
+ /**
+ * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
+ */
+ public void writeExternal(ObjectOutput out) throws IOException {
+
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestNodeManagerServiceImpl.java b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestNodeManagerServiceImpl.java
new file mode 100644
index 0000000000..11deef5906
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/java/org/apache/tuscany/sca/domain/impl/TestNodeManagerServiceImpl.java
@@ -0,0 +1,68 @@
+/*
+ * 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.domain.impl;
+
+import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter.Base64Binary;
+import org.apache.tuscany.sca.node.NodeException;
+import org.apache.tuscany.sca.node.management.SCANodeManagerService;
+
+/**
+ * A dummy interface for the domain to talk to when testing the domain and no nodes are running
+ *
+ * @version $Rev: 552343 $ $Date: 2007-09-11 18:45:36 +0100 (Tue, 11 Sep 2007) $
+ */
+public class TestNodeManagerServiceImpl implements SCANodeManagerService {
+
+
+
+ // SCANodeManagerService methods
+
+ public String getURI() {
+ return null;
+ }
+
+ public void addContribution(String contributionURI, String contributionURL) throws NodeException {
+ System.out.println("addContribution " + contributionURI + " " + contributionURL);
+ }
+
+ public void removeContribution(String contributionURI) throws NodeException {
+ System.out.println("addContribution " + contributionURI);
+ }
+
+ public void addToDomainLevelComposite(String compositeName) throws NodeException {
+ System.out.println("addToDomainLevelComposite " + compositeName);
+ }
+
+ public void start() throws NodeException {
+ System.out.println("start");
+ }
+
+ public void stop() throws NodeException {
+ System.out.println("stop");
+ }
+
+ public void destroyNode() {
+ System.out.println("destroy");
+ }
+
+ public void updateComposite(String compositeQName, String compositeXMLBase64) throws NodeException {
+ System.out.println("updateComposite " + compositeQName + " " + Base64Binary.decode(compositeXMLBase64).toString());
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeA/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeA/Calculator.composite
new file mode 100644
index 0000000000..172676a3c7
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeA/Calculator.composite
@@ -0,0 +1,41 @@
+<?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"/>
+ <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/domain-impl/src/test/resources/nodeA/META-INF/sca-contribution.xml b/sandbox/sebastien/java/sca-node/modules/domain-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/domain-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/domain-impl/src/test/resources/nodeB/Calculator.composite b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeB/Calculator.composite
new file mode 100644
index 0000000000..b770dbe8d4
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/domain-impl/src/test/resources/nodeB/Calculator.composite
@@ -0,0 +1,29 @@
+<?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="AddServiceComponentB">
+ <implementation.java class="calculator.AddServiceImpl" />
+ </component>
+
+</composite>