diff options
Diffstat (limited to 'branches/sca-java-1.2.1/modules/node-impl/src/main')
15 files changed, 2976 insertions, 0 deletions
diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java new file mode 100644 index 0000000000..396b789794 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentInfoImpl.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.io.Serializable; + +import org.apache.tuscany.sca.node.ComponentInfo; + +public class ComponentInfoImpl implements ComponentInfo, Serializable { + + private String name; + private boolean started; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java new file mode 100644 index 0000000000..b00825be45 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/ComponentManagerServiceImpl.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl; +import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime; +import org.apache.tuscany.sca.node.ComponentListener; +import org.apache.tuscany.sca.node.ComponentManager; + +public class ComponentManagerServiceImpl implements ComponentManager { + + protected List<ComponentListener> listeners = new CopyOnWriteArrayList<ComponentListener>(); + protected String domainURI; + protected String nodeName; + protected Composite nodeComposite; + protected ReallySmallRuntime nodeRuntime; + + public ComponentManagerServiceImpl(String domainURI, String nodeName, Composite nodeComposite, ReallySmallRuntime nodeRuntime) { + this.domainURI = domainURI; + this.nodeName = nodeName; + this.nodeComposite = nodeComposite; + this.nodeRuntime = nodeRuntime; + } + + public void addComponentListener(ComponentListener listener) { + this.listeners.add(listener); + } + + public void removeComponentListener(ComponentListener listener) { + this.listeners.remove(listener); + } + + public Component getComponent(String componentName) { + for (Composite composite: nodeComposite.getIncludes()) { + for (Component component: composite.getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + return null; + } + + public List<Component> getComponents() { + List<Component> components = new ArrayList<Component>(); + for (Composite composite: nodeComposite.getIncludes()) { + components.addAll(composite.getComponents()); + } + return components; + } + + public void startComponent(Component component) throws ActivationException { + nodeRuntime.getCompositeActivator().start(component); + notifyComponentStarted(component); + } + + public void stopComponent(Component component) throws ActivationException { + nodeRuntime.getCompositeActivator().stop(component); + notifyComponentStopped(component); + } + + public void notifyComponentStarted(Component component) { + for (ComponentListener listener : listeners) { + try { + listener.componentStarted(component); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public void notifyComponentStopped(Component component) { + for (ComponentListener listener : listeners) { + try { + listener.componentStopped(component); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public boolean isComponentStarted(Component component) { + RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)component; + return runtimeComponent.isStarted(); + } + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainAPIServiceProxyImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainAPIServiceProxyImpl.java new file mode 100644 index 0000000000..1c208e2464 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainAPIServiceProxyImpl.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.io.Externalizable; +import java.lang.reflect.UndeclaredThrowableException; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.domain.DomainException; +import org.apache.tuscany.sca.domain.SCADomainAPIService; +import org.apache.tuscany.sca.domain.SCADomainEventService; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Scope; + + +/** + * Stores details of services exposed and retrieves details of remote services + * + * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $ + */ +@Scope("COMPOSITE") +public class SCADomainAPIServiceProxyImpl implements SCADomainAPIService{ + + private final static Logger logger = Logger.getLogger(SCADomainAPIServiceProxyImpl.class.getName()); + + @Reference + protected SCADomainAPIService domainManager; + + public void start() throws DomainException { + domainManager.start(); + } + + public void stop() throws DomainException { + domainManager.stop(); + } + + public void destroyDomain() throws DomainException { + domainManager.destroyDomain(); + } + + public String getURI() { + return domainManager.getURI(); + } + + public void addContribution(String contributionURI, String contributionURL) throws DomainException { + domainManager.addContribution(contributionURI, contributionURL); + } + + public void updateContribution(String contributionURI, String contributionURL) throws DomainException { + domainManager.updateContribution(contributionURI, contributionURL); + } + + public void removeContribution(String contributionURI) throws DomainException { + domainManager.removeContribution(contributionURI); + } + + public void addDeploymentComposite(String contributionURI, String compositeXML) throws DomainException { + domainManager.addDeploymentComposite(contributionURI, compositeXML); + } + + public void updateDeploymentComposite(String contributionURI, String compositeXML) throws DomainException { + domainManager.updateDeploymentComposite(contributionURI, compositeXML); + } + + public void addToDomainLevelComposite(String compositeQName) throws DomainException { + domainManager.addToDomainLevelComposite(compositeQName); + } + + public void removeFromDomainLevelComposite(String compositeQName) throws DomainException { + domainManager.removeFromDomainLevelComposite(compositeQName); + } + + public String getDomainLevelComposite() throws DomainException { + return domainManager.getDomainLevelComposite(); + } + + public String getQNameDefinition(String artifact) throws DomainException { + return domainManager.getQNameDefinition(artifact); + } + + public void startComposite(String compositeQName) throws DomainException { + domainManager.startComposite(compositeQName); + } + + public void stopComposite(String compositeQName) throws DomainException { + domainManager.stopComposite(compositeQName); + } + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainEventServiceProxyImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainEventServiceProxyImpl.java new file mode 100644 index 0000000000..42d4be1df4 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainEventServiceProxyImpl.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.io.Externalizable; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.domain.DomainException; +import org.apache.tuscany.sca.domain.SCADomainEventService; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Scope; + + +/** + * Stores details of services exposed and retrieves details of remote services + * + * @version $Rev: 552343 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $ + */ +@Scope("COMPOSITE") +public class SCADomainEventServiceProxyImpl implements SCADomainEventService{ + + private final static Logger logger = Logger.getLogger(SCADomainEventServiceProxyImpl.class.getName()); + + @Property + protected int retryCount = 100; + + @Property + protected int retryInterval = 5000; //ms + + @Reference + protected SCADomainEventService domainManager; + + public void registerNode(String nodeURI, String nodeURL, Externalizable nodeManagerService) throws DomainException { + + // a rety loop is included on node registration in case the node + // comes up before the domain it is registering with + for (int i =0; i < retryCount; i++){ + try { + domainManager.registerNode(nodeURI, nodeURL, nodeManagerService); + break; + } catch(UndeclaredThrowableException ex) { + ex.printStackTrace(); + logger.log(Level.INFO, "Trying to register node " + + nodeURI + + " at endpoint " + + nodeURL); + + } + + try { + Thread.sleep(retryInterval); + } catch(InterruptedException ex) { + } + } + } + + public void unregisterNode(String nodeURI) throws DomainException { + domainManager.unregisterNode(nodeURI); + } + + public void registerNodeStart(String nodeURI) throws DomainException { + domainManager.registerNodeStart(nodeURI); + } + + public void registerNodeStop(String nodeURI) throws DomainException { + domainManager.registerNodeStop(nodeURI); + } + + public void registerContribution(String nodeURI, String contributionURI, String contributionURL) throws DomainException { + domainManager.registerContribution(nodeURI, contributionURI, contributionURL); + } + + public void unregisterContribution(String nodeURI, String contributionURI) throws DomainException { + domainManager.unregisterContribution(nodeURI, contributionURI); + } + + public void registerDomainLevelComposite(String nodeURI, String compositeQNameString) throws DomainException{ + domainManager.registerDomainLevelComposite(nodeURI, compositeQNameString); + } + + public void registerServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName, String URL) throws DomainException { + domainManager.registerServiceEndpoint(domainUri, nodeUri, serviceName, bindingName, URL); + } + + public void unregisterServiceEndpoint(String domainUri, String nodeUri, String serviceName, String bindingName) throws DomainException { + domainManager.unregisterServiceEndpoint(domainUri, nodeUri, serviceName, bindingName); + } + + public String findServiceEndpoint(String domainUri, String serviceName, String bindingName) throws DomainException { + return domainManager.findServiceEndpoint(domainUri, serviceName, bindingName); + } + + public String findServiceNode(String domainUri, String serviceName, String bindingName) throws DomainException { + return domainManager.findServiceNode(domainUri, serviceName, bindingName); + } + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java new file mode 100644 index 0000000000..f1480d5ded --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainFinderImpl.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.util.HashMap; + +import org.apache.tuscany.sca.domain.DomainException; +import org.apache.tuscany.sca.domain.SCADomain; +import org.apache.tuscany.sca.domain.SCADomainSPI; +import org.apache.tuscany.sca.domain.impl.SCADummyNodeImpl; +import org.apache.tuscany.sca.node.SCADomainFinder; +import org.apache.tuscany.sca.node.SCADomainProxySPI; +import org.apache.tuscany.sca.node.SCANode; + +/** + * A finder for SCA domains. + * + * @version $Rev: 580520 $ $Date: 2007-09-29 00:50:25 +0100 (Sat, 29 Sep 2007) $ + */ +public class SCADomainFinderImpl extends SCADomainFinder { + + private static HashMap<String, SCADomain> domains = new HashMap<String, SCADomain>(); + + /** + * Returns a new SCA domain finder instance. + * + * @return a new SCA domain finder + */ + public SCADomainFinderImpl() { + + } + + /** + * Finds an existing SCA domain. + * + * @param domainURI the URI of the domain, this is the endpoint + * URI of the domain administration service + * @return the SCA domain + */ + public SCADomain getSCADomain(String domainURI) throws DomainException { + SCADomain scaDomain = domains.get(domainURI); + + if (scaDomain == null) { + scaDomain = new SCADomainProxyImpl(domainURI); + //domains.put(domainURI, scaDomain); + // TODO - not caching local domains as currently the local domain can + // - only handle one node + // - provides the management endpoint for that node + + // Add the dummy node as there will be no real node in this case + SCANode scaNode = new SCADummyNodeImpl(scaDomain); + ((SCADomainProxyImpl)scaDomain).addNode(scaNode); + } + return scaDomain; + } + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainProxyImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainProxyImpl.java new file mode 100644 index 0000000000..dcfd186515 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCADomainProxyImpl.java @@ -0,0 +1,622 @@ + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.io.ByteArrayOutputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.context.CallableReferenceImpl; +import org.apache.tuscany.sca.domain.DomainException; +import org.apache.tuscany.sca.domain.SCADomainAPIService; +import org.apache.tuscany.sca.domain.SCADomainEventService; +import org.apache.tuscany.sca.domain.impl.SCADomainImpl; +import org.apache.tuscany.sca.domain.impl.SCADummyNodeImpl; +import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime; +import org.apache.tuscany.sca.host.http.ServletHost; +import org.apache.tuscany.sca.host.http.ServletHostExtensionPoint; +import org.apache.tuscany.sca.node.NodeFactoryImpl; +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.SCANodeSPI; +import org.apache.tuscany.sca.node.management.SCANodeManagerInitService; +import org.apache.tuscany.sca.node.management.SCANodeManagerService; +import org.apache.tuscany.sca.node.util.SCAContributionUtil; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; + + +/** + * A local representation of the sca domain running on a single node + * + * @version $Rev$ $Date$ + */ +public class SCADomainProxyImpl extends SCADomainImpl { + + private final static Logger logger = Logger.getLogger(SCADomainProxyImpl.class.getName()); + + // management services + private SCADomainAPIService domainAPIService; + private SCADomainEventService domainEventService; + private SCANodeManagerInitService nodeManagerInitService; + private CallableReferenceImpl<SCANodeManagerService> nodeManagerService; + + // the local node implementation + private SCANode node; + + // methods defined on the implementation only + + /** + * Creates a domain proxy connected to a wider domain. + * + * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081 + * @throws ActivationException + */ + public SCADomainProxyImpl(String domainURI) throws DomainException { + super(domainURI); + } + + /** + * Creates a domain proxy connected to a wider domain. + * + * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081 + * @throws ActivationException + */ + public SCADomainProxyImpl(String domainURI, ClassLoader cl) throws DomainException { + super(domainURI); + domainClassLoader = cl; + } + + /** + * Start the composite that connects to the domain manager + */ + protected void init() throws DomainException { + try { + // check where domain uris are urls, they will be used to configure various + // endpoints if they are + URI tmpURI; + try { + tmpURI = new URI(domainModel.getDomainURI()); + domainModel.setDomainURL(tmpURI.toURL().toExternalForm()); + } catch(Exception ex) { + domainModel.setDomainURL(null); + } + + // Check if node has been given a valid domain name to connect to + if (domainModel.getDomainURL() == null) { + logger.log(Level.INFO, "Domain will be started stand-alone as domain URL is not provided"); + } + + } catch(Exception ex) { + throw new DomainException(ex); + } + } + + private void createRuntime() throws DomainException { + try { + // check we don't try to do this twice + if (domainManagementRuntime != null){ + return; + } + + // if there is no node create a runtime otherwise use the runtime from the node + if ((node == null) || + ( (node != null) && (node.getClass().equals(SCADummyNodeImpl.class)))){ + // create a runtime for the domain management services to run on + domainManagementRuntime = new ReallySmallRuntime(domainClassLoader); + domainManagementRuntime.start(); + + String path = URI.create(domainModel.getDomainURI()).getPath(); + + // invent a default URL for the runtime + String host = InetAddress.getLocalHost().getHostName(); + ServerSocket socket = new ServerSocket(0); + int port = socket.getLocalPort(); + socket.close(); + + ServletHostExtensionPoint servletHosts = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class); + for (ServletHost servletHost: servletHosts.getServletHosts()) { + servletHost.setDefaultPort(port); + if (path != null && path.length() > 0 && !path.equals("/")) { + servletHost.setContextPath(path); + } + } + + // make the node available to the model + // this causes the runtime to start registering binding-sca service endpoints + // with the domain proxy + // TODO - This code is due to be pulled out and combined with the register and + // resolution code that appears in this class + ModelFactoryExtensionPoint factories = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + nodeFactory = new NodeFactoryImpl(node); + factories.addFactory(nodeFactory); + + // Create an in-memory domain level management composite + AssemblyFactory assemblyFactory = domainManagementRuntime.getAssemblyFactory(); + domainManagementComposite = assemblyFactory.createComposite(); + domainManagementComposite.setName(new QName(Constants.SCA10_NS, "domainManagement")); + domainManagementComposite.setURI(domainModel.getDomainURI() + "/Management"); + + + } else { + domainManagementRuntime = (ReallySmallRuntime)((SCANodeSPI)node).getNodeRuntime(); + domainManagementComposite = domainManagementRuntime.getCompositeActivator().getDomainComposite(); + + // set the context path for the node + String path = URI.create(node.getURI()).getPath(); + if (path != null && path.length() > 0 && !path.equals("/")) { + ServletHostExtensionPoint servletHosts = domainManagementRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class); + for (ServletHost servletHost: servletHosts.getServletHosts()) { + servletHost.setContextPath(path); + } + } + } + + // Find the composite that will configure the domain + String domainCompositeName = "node.composite"; + URL contributionURL = SCAContributionUtil.findContributionFromResource(domainClassLoader, domainCompositeName); + + if ( contributionURL != null ){ + logger.log(Level.INFO, "Domain management configured from " + contributionURL); + + // add node composite to the management domain + domainManagementContributionService = domainManagementRuntime.getContributionService(); + domainManagementContribution = domainManagementContributionService.contribute("nodedomain", + contributionURL, + false); + + Composite composite = null; + + for (Artifact artifact: domainManagementContribution.getArtifacts()) { + if (domainCompositeName.equals(artifact.getURI())) { + composite = (Composite)artifact.getModel(); + } + } + + if (composite != null) { + + domainManagementComposite.getIncludes().add(composite); + domainManagementRuntime.buildComposite(composite); + + if (domainModel.getDomainURL() != null) { + URI domainURI = URI.create(domainModel.getDomainURI()); + String domainHost = domainURI.getHost(); + int domainPort = domainURI.getPort(); + + // override any domain URLs in node.composite and replace with the + // domain url provided on start up + for ( Component component : composite.getComponents()){ + for (ComponentReference reference : component.getReferences() ){ + for (Binding binding : reference.getBindings() ) { + String bindingURIString = binding.getURI(); + if (bindingURIString != null) { + URI bindingURI = URI.create(bindingURIString); + String bindingHost = bindingURI.getHost(); + int bindingPort = bindingURI.getPort(); + + if ( bindingPort == 9999){ + // replace the old with the new + bindingURIString = domainURI + bindingURI.getPath() ; + + // set the address back into the NodeManager binding. + binding.setURI(bindingURIString); + } + } + } + } + } + } + + domainManagementRuntime.getCompositeActivator().activate(composite); + domainManagementRuntime.getCompositeActivator().start(composite); + + // get the management components out of the domain so that they + // can be configured/used. + domainAPIService = getService(SCADomainAPIService.class, + "SCADomainAPIServiceProxyComponent", + domainManagementRuntime, + domainManagementComposite); + domainEventService = getService(SCADomainEventService.class, + "SCADomainEventServiceProxyComponent", + domainManagementRuntime, + domainManagementComposite); + + nodeManagerInitService = getService(SCANodeManagerInitService.class, + "SCANodeManagerComponent/SCANodeManagerInitService", + domainManagementRuntime, + domainManagementComposite); + + nodeManagerService = (CallableReferenceImpl<SCANodeManagerService>) + getServiceReference(SCANodeManagerService.class, + "SCANodeManagerComponent/SCANodeManagerService", + domainManagementRuntime, + domainManagementComposite); + + // add the registered node now that the runtime is started + if ((node != null) && (!node.getClass().equals(SCADummyNodeImpl.class))){ + addNode(); + } + + + } else { + throw new ActivationException("Domain management contribution " + + contributionURL + + " found but could not be loaded"); + } + } else { + throw new ActivationException("Domain management contribution " + + domainCompositeName + + " not found on the classpath"); + } + + } catch(Exception ex) { + throw new DomainException(ex); + } + } + + + public String getComposite(QName compositeQName){ + + Composite composite = null; + for(Composite tmpComposite : domainManagementComposite.getIncludes()){ + if (tmpComposite.getName().equals(compositeQName)){ + composite = tmpComposite; + } + } + + String compositeString = null; + + if (composite != null){ + ExtensionPointRegistry registry = domainManagementRuntime.getExtensionPointRegistry(); + + StAXArtifactProcessorExtensionPoint staxProcessors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(bos); + processor.write(composite, writer); + writer.flush(); + writer.close(); + } catch (Exception ex) { + System.out.println(ex.toString()); + } + + compositeString = bos.toString(); + } + + return compositeString; + } + + // SCADomainEventService methods + + public void addNode(SCANode node) throws DomainException { + this.node = node; + + // add the node into the local domain model + super.registerNode(node.getURI(), node.getURI(), null); + + // the registration of the node with the domain is delayed until + // after the runtime has been started + createRuntime(); + } + + private void addNode() throws DomainException { + + // pass this object into the node manager service + nodeManagerInitService.setNode(node); + + if (domainModel.getDomainURL() != null){ + // add the node to the domain + + try { + // create the node manager endpoint + // TODO - we really need to pass in a callable reference + URI nodeURI = new URI(node.getURI()); + String nodeHost = nodeURI.getHost(); + + if (nodeHost.equals("localhost")){ + nodeHost = InetAddress.getLocalHost().getHostName(); + } + + String nodeManagerURL = nodeURI.getScheme()+ "://" + + nodeHost + ":" + + nodeURI.getPort() + nodeURI.getPath() + "/SCANodeManagerComponent/SCANodeManagerService"; + + // go out and add this node to the wider domain + domainEventService.registerNode(node.getURI(), nodeManagerURL, nodeManagerService); + + } catch(Exception ex) { + logger.log(Level.SEVERE, + "Can't connect to domain manager at: " + + domainModel.getDomainURL()); + throw new DomainException(ex); + } + } + } + + public void removeNode(SCANode node) throws DomainException { + + // remove the node from the local domain model + super.unregisterNode(node.getURI()); + + if (domainModel.getDomainURL() != null){ + + try { + // go out and remove this node to the wider domain + domainEventService.unregisterNode(node.getURI()); + } catch(Exception ex) { + logger.log(Level.SEVERE, + "Can't connect to domain manager at: " + + domainModel.getDomainURL()); + throw new DomainException(ex); + } + } + + // remove this object from the node manager service + nodeManagerInitService.setNode(null); + + this.node = null; + } + + public void registerNodeStart(String nodeURI) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainEventService != null)){ + domainEventService.registerNodeStart(nodeURI); + } + } + + public void registerNodeStop(String nodeURI) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainEventService != null)){ + domainEventService.registerNodeStop(nodeURI); + } + } + + public void registerContribution(String nodeURI, String contributionURI, String contributionURL) throws DomainException { + + if ((domainModel.getDomainURL() != null) && (domainEventService != null)){ + domainEventService.registerContribution(nodeURI, contributionURI, contributionURL); + } + } + + public void unregisterContribution(String nodeURI, String contributionURI) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainEventService != null)) { + domainEventService.unregisterContribution(nodeURI, contributionURI); + } + } + + public void registerDomainLevelComposite(String nodeURI, String compositeQNameString) throws DomainException{ + if ((domainModel.getDomainURL() != null) && (domainEventService != null)) { + domainEventService.registerDomainLevelComposite(nodeURI, compositeQNameString); + } + } + + + public void registerServiceEndpoint(String domainURI, String nodeURI, String serviceName, String bindingName, String URL) throws DomainException { + + //super.registerServiceEndpoint(domainURI, nodeURI, serviceName, bindingName, URL); + + if ((domainModel.getDomainURL() != null) && (domainEventService != null)) { + domainEventService.registerServiceEndpoint(domainURI, nodeURI, serviceName, bindingName, URL); + } + } + + public void unregisterServiceEndpoint(String domainURI, String nodeURI, String serviceName, String bindingName) throws DomainException { + + //super.unregisterServiceEndpoint(domainURI, nodeURI, serviceName, bindingName); + + if ((domainModel.getDomainURL() != null) && (domainEventService != null)) { + domainEventService.unregisterServiceEndpoint(domainURI, nodeURI, serviceName, bindingName); + } + } + + public String findServiceEndpoint(String domainURI, String serviceName, String bindingName) throws DomainException { + + String endpoint = super.findServiceEndpoint(domainURI, serviceName, bindingName); + + if ( (endpoint.equals(SERVICE_NOT_REGISTERED)) && (domainModel.getDomainURL() != null) && (domainEventService != null)){ + endpoint = domainEventService.findServiceEndpoint(domainURI, serviceName, bindingName); + } + + return endpoint; + } + + public String findServiceNode(String domainURI, String serviceName, String bindingName) throws DomainException { + + String nodeName = super.findServiceEndpoint(domainURI, serviceName, bindingName); + + if ( (nodeName.equals(SERVICE_NOT_KNOWN)) && (domainModel.getDomainURL() != null) && (domainEventService != null)){ + nodeName = domainEventService.findServiceNode(domainURI, serviceName, bindingName); + } + + return nodeName; + } + + + // SCADomain API methods + public void start() throws DomainException { + + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.start(); + } else { + logger.log(Level.INFO,"Not connected to domain"); + } + } + + public void stop() throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.stop(); + } else { + logger.log(Level.INFO,"Not connected to domain"); + } + } + + public void destroy() throws DomainException { + + try { + + + if (domainManagementRuntime != null) { + Composite composite = domainManagementComposite.getIncludes().get(0); + + domainManagementRuntime.getCompositeActivator().stop(composite); + domainManagementRuntime.getCompositeActivator().deactivate(composite); + + domainManagementComposite.getIncludes().clear(); + domainManagementRuntime.getContributionService().remove(domainManagementContribution.getURI()); + + domainManagementRuntime.stop(); + + domainManagementRuntime = null; + domainManagementComposite = null; + + domainAPIService = null; + domainEventService = null; + nodeManagerInitService = null; + } + + + } catch (Exception ex) { + throw new DomainException(ex); + } + } + + + public void addContribution(String contributionURI, URL contributionURL) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.addContribution(contributionURI, contributionURL.toString()); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public void updateContribution(String contributionURI, URL contributionURL) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.updateContribution(contributionURI, contributionURL.toString()); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public void removeContribution(String contributionURI) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.removeContribution(contributionURI); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public void addDeploymentComposite(String contributionURI, String compositeXML) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.addDeploymentComposite(contributionURI, compositeXML); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public void updateDeploymentComposite(String contributionURI, String compositeXML) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.updateDeploymentComposite(contributionURI, compositeXML); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public void addToDomainLevelComposite(QName compositeQName) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.addToDomainLevelComposite(compositeQName.toString()); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public void removeFromDomainLevelComposite(QName compositeQName) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.removeFromDomainLevelComposite(compositeQName.toString()); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public String getDomainLevelComposite() throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + return domainAPIService.getDomainLevelComposite(); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public String getQNameDefinition(QName artifact) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + return domainAPIService.getQNameDefinition(artifact.toString()); + } else { + throw new DomainException("Not connected to domain"); + } + } + + public void startComposite(QName compositeQName) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.startComposite(compositeQName.toString()); + } else { + logger.log(Level.INFO,"Not connected to domain"); + } + } + + public void stopComposite(QName compositeQName) throws DomainException { + if ((domainModel.getDomainURL() != null) && (domainAPIService != null)){ + domainAPIService.stopComposite(compositeQName.toString()); + } else { + logger.log(Level.INFO,"Not connected to domain"); + } + } + + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + return (R)cast(target, domainManagementRuntime); + } + + public <B> B getService(Class<B> businessInterface, String serviceName) { + return getService( businessInterface, serviceName, domainManagementRuntime, domainManagementComposite); + } + + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) { + return getServiceReference(businessInterface, name, domainManagementRuntime, domainManagementComposite); + } +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java new file mode 100644 index 0000000000..5c6d372f11 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeFactoryImpl.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import org.apache.tuscany.sca.node.NodeException; +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.SCANodeFactory; + +/** + * A finder for SCA domains. + * + * @version $Rev: 580520 $ $Date: 2007-09-29 00:50:25 +0100 (Sat, 29 Sep 2007) $ + */ +public class SCANodeFactoryImpl extends SCANodeFactory { + + + /** + * Create a new SCA node factory instance. + * + * @return a new SCA node factory + */ + public SCANodeFactoryImpl() { + + } + + /** + * Creates a new SCA node. + * + * @param nodeURI the URI of the node, this URI is used to provide the default + * host and port information for the runtime for situations when bindings + * do provide this information + * @param domainURI the URI of the domain that the node belongs to. This URI is + * used to locate the domain manager on the network + * @return a new SCA node. + */ + public SCANode createSCANode(String physicalNodeURI, String domainURI) throws NodeException { + return new SCANodeImpl(physicalNodeURI, domainURI, null); + } + + /** + * Creates a new SCA node. Many physical nodes may share the same logical URL in load balancing + * and failover scenarios where each node in the group runs the same contribution and + * active composites + * + * @param physicalNodeURI the URI of the node, this URI is used to provide the default + * host and port information for the runtime for situations when bindings + * don't provide this information + * @param domainURI the URI of the domain that the node belongs to. This URI is + * used to locate the domain manager on the network + * @param logicalNodeURI the uri of the node to be used in situations where more than one node + * are grouped together for failover or load balancing scenarios. The logicalNodeURI + * will typically identify the logical node where requests are sent + * @return a new SCA node. + */ + public SCANode createSCANode(String physicalNodeURI, String domainURI, String logicalNodeURI) throws NodeException { + return new SCANodeImpl(physicalNodeURI, domainURI, logicalNodeURI); + } + + /** + * Creates a new SCA node. Many physical nodes may share the same logical URL in load balancing + * and failover scenarios where each node in the group runs the same contribution and + * active composites. Also allows a class loaded to b specified. This is the + * classloader that will be used to load the management application used by the + * node to talk to the domain + * + * @param physicalNodeURI the URI of the node, this URI is used to provide the default + * host and port information for the runtime for situations when bindings + * don't provide this information + * @param domainURI the URI of the domain that the node belongs to. This URI is + * used to locate the domain manager on the network + * @param logicalNodeURI the uri of the node to be used in situations where more than one node + * are grouped together for failover or load balancing scenarios. The logicalNodeURI + * will typically identify the logical node where requests are sent. If null is provided + * no logicalNodeURI is set. + * @param classLoader the class loader to use by default when loading contributions. If null is provided + * the classloader the dervied automatically. + * @return a new SCA node. + */ + public SCANode createSCANode(String physicalNodeURI, String domainURI, String logicalNodeURI, ClassLoader classLoader) throws NodeException { + return new SCANodeImpl(physicalNodeURI, domainURI, logicalNodeURI, classLoader); + } + + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java new file mode 100644 index 0000000000..cd5bc37b84 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeImpl.java @@ -0,0 +1,924 @@ + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.io.ByteArrayInputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.builder.DomainBuilder; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.databinding.impl.XSDDataTypeConverter.Base64Binary; +import org.apache.tuscany.sca.domain.SCADomain; +import org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntime; +import org.apache.tuscany.sca.host.http.ServletHost; +import org.apache.tuscany.sca.host.http.ServletHostExtensionPoint; +import org.apache.tuscany.sca.node.NodeException; +import org.apache.tuscany.sca.node.NodeFactoryImpl; +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.SCANodeSPI; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; + +/** + * A local representation of the sca domain running on a single node + * + * @version $Rev: 552343 $ $Date: 2007-09-09 23:54:46 +0100 (Sun, 09 Sep 2007) $ + */ +public class SCANodeImpl implements SCANode, SCANodeSPI { + + private final static Logger logger = Logger.getLogger(SCANodeImpl.class.getName()); + + // class loader used to get application resources + private ClassLoader nodeClassLoader; + + // identity and endpoints for the node and the domain it belongs to + private String nodeURI; + private URL nodeURL; + private String logicalNodeURI; + private String domainURI; + + // The tuscany runtime that does the hard work + private ReallySmallRuntime nodeRuntime; + + // the top level components in this node. A subset of the the domain level composite + private Composite nodeComposite; + + // the domain that the node belongs to. This object acts as a proxy to the domain + private SCADomainProxyImpl scaDomain; + + // the started status of the node + private boolean nodeStarted = false; + + // collection for managing contributions that have been added to the node + private Map<String, Contribution> contributions = new HashMap<String, Contribution>(); + private Map<QName, Composite> composites = new HashMap<QName, Composite>(); + private Map<String, Composite> compositeFiles = new HashMap<String, Composite>(); + + private QName nodeManagementCompositeName = new QName("http://tuscany.apache.org/xmlns/tuscany/1.0", "node"); + + // Used to pipe node information into the model + NodeFactoryImpl nodeFactory; + + // domain level wiring + DomainBuilder domainBuilder; + + // methods defined on the implementation only + + /** + * Creates a node connected to a wider domain. To find its place in the domain + * node and domain identifiers must be provided. + * + * @param physicalNodeUri - if this is a url it is assumed that this will be used as root url for management components, e.g. http://localhost:8082 + * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081 + * @param logicalNodeURI the uri of the node group. This is the enpoint URI of the head of the + * group of nodes. For example, in load balancing scenarios this will be the loaded balancer itself + * @throws ActivationException + */ + public SCANodeImpl(String physicalNodeURI, String domainURI, String logicalNodeURI) throws NodeException { + this.domainURI = domainURI; + this.nodeURI = physicalNodeURI; + this.logicalNodeURI = logicalNodeURI; + this.nodeClassLoader = Thread.currentThread().getContextClassLoader(); + init(); + } + + /** + * Creates a node connected to a wider domain and allows a classpath to be specified. + * To find its place in the domain node and domain identifiers must be provided. + * + * @param physicalNodeUri - if this is a url it is assumed that this will be used as root url for management components, e.g. http://localhost:8082 + * @param domainUri - identifies what host and port the domain service is running on, e.g. http://localhost:8081 + * @param logicalNodeURI the uri of the node group. This is the enpoint URI of the head of the + * group of nodes. For example, in load balancing scenarios this will be the loaded balancer itself + * @param cl - the ClassLoader to use for loading system resources for the node + * @throws ActivationException + */ + public SCANodeImpl(String physicalNodeURI, String domainURI, String logicalNodeURI, ClassLoader cl) throws NodeException { + this.domainURI = domainURI; + this.nodeURI = nodeURI; + this.logicalNodeURI = logicalNodeURI; + this.nodeClassLoader = cl; + init(); + } + + /** + * Work out if we are representing a domain in memory or can go out to the network to + * get domain information. This all depends on whether the domain URI has been specified + * on construction + */ + private void init() throws NodeException { + try { + + // Generate a unique node URI + if (nodeURI == null) { + + String host = InetAddress.getLocalHost().getHostName(); + ServerSocket socket = new ServerSocket(0); + nodeURI = "http://" + host + ":" + socket.getLocalPort(); + socket.close(); + } + + // check whether node uri is an absolute url, + try { + URI tmpURI = new URI(nodeURI); + nodeURL = tmpURI.toURL(); + } catch(Exception ex) { + throw new NodeException("node uri " + + nodeURI + + " must be a valid url"); + } + + // create a node runtime for the domain contributions to run on + nodeRuntime = new ReallySmallRuntime(nodeClassLoader); + nodeRuntime.start(); + + // get the domain builder + domainBuilder = nodeRuntime.getDomainBuilder(); + + // configure the default port and path for this runtime + int port = URI.create(nodeURI).getPort(); + String path = nodeURL.getPath(); + ServletHostExtensionPoint servletHosts = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class); + for (ServletHost servletHost: servletHosts.getServletHosts()) { + servletHost.setDefaultPort(port); + if (path != null && path.length() > 0 && !path.equals("/")) { + servletHost.setContextPath(path); + } + } + + // make the node available to the model + // this causes the runtime to start registering binding-sca service endpoints + // with the domain proxy + // TODO - This code is due to be pulled out and combined with the register and + // resolution code that appears in this class + ModelFactoryExtensionPoint factories = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + nodeFactory = new NodeFactoryImpl(this); + factories.addFactory(nodeFactory); + + // Create an in-memory domain level composite + AssemblyFactory assemblyFactory = nodeRuntime.getAssemblyFactory(); + nodeComposite = assemblyFactory.createComposite(); + nodeComposite.setName(new QName(Constants.SCA10_NS, "node")); + nodeComposite.setURI(nodeURI); + + // add the top level composite into the composite activator + nodeRuntime.getCompositeActivator().setDomainComposite(nodeComposite); + + // create a link to the domain + scaDomain = new SCADomainProxyImpl(domainURI, nodeClassLoader); + + // add the node URI to the domain + scaDomain.addNode(this); + + } catch(NodeException ex) { + throw ex; + } catch(Exception ex) { + throw new NodeException(ex); + } + } + + // temp methods to help integrate with existing code + + public Component getComponent(String componentName) { + for (Composite composite: nodeComposite.getIncludes()) { + for (Component component: composite.getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + return null; + } + + public List<Component> getComponents() { + List<Component> components = new ArrayList<Component>(); + for (Composite composite: nodeComposite.getIncludes()) { + components.addAll(composite.getComponents()); + } + return components; + } + + /** + * Stating to think about how a node advertises what it can do. + * Maybe need to turn this round and ask the node to decide whether it + * can process a list of artifacts + * @return + */ + public List<String> getFeatures() { + List<String> featureList = new ArrayList<String>(); + + ExtensionPointRegistry registry = nodeRuntime.getExtensionPointRegistry(); + + // TODO - how to get registered features? + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + + return null; + } + + // SCANode SPI methods + + public Object getNodeRuntime() { + return nodeRuntime; + } + + public void startFromDomain() throws NodeException { + if (!nodeStarted){ + startComposites(); + nodeStarted = true; + } + } + + public void stopFromDomain() throws NodeException { + if (nodeStarted){ + stopComposites(); + nodeStarted = false; + } + } + + public void addContributionFromDomain(String contributionURI, URL contributionURL, ClassLoader contributionClassLoader ) throws NodeException { + + if (nodeStarted){ + throw new NodeException("Can't add contribution " + contributionURI + " when the node is running. Call stop() on the node first"); + } + + if (contributionURI == null){ + throw new NodeException("Contribution URI cannot be null"); + } + + if (contributionURL == null){ + throw new NodeException("Contribution URL cannot be null"); + } + + if (contributions.containsKey(contributionURI)) { + throw new NodeException("Contribution " + contributionURI + " has already been added"); + } + + try { + + //FIXME What to do when a contribution uses a separate class loader ? (e.g contributionClassLoader != null) + + // Add the contribution to the node + ContributionService contributionService = nodeRuntime.getContributionService(); + Contribution contribution = contributionService.contribute(contributionURI, + contributionURL, + false); + + // remember the contribution + contributions.put(contributionURI, contribution); + + // remember all the composites that have been found + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + Composite composite = (Composite)artifact.getModel(); + composites.put(composite.getName(), composite); + compositeFiles.put(composite.getURI(), composite); + } + } + + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + public void removeContributionFromDomain(String contributionURI) throws NodeException { + + if (nodeStarted){ + throw new NodeException("Can't remove contribution " + contributionURI + " when the node is running. Call stop() on the node first"); + } + + if (contributionURI == null){ + throw new NodeException("Contribution URI cannot be null"); + } + + if (!contributions.containsKey(contributionURI)) { + throw new NodeException("Contribution " + contributionURI + " has not been added"); + } + + try { + + Contribution contribution = contributions.get(contributionURI); + + // remove the local record of composites associated with this contribution + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + Composite composite = (Composite)artifact.getModel(); + composites.remove(composite.getName()); + compositeFiles.remove(composite.getURI()); + } + } + + // remove the contribution from the contribution service + nodeRuntime.getContributionService().remove(contributionURI); + + // remove any deployed composites from the node level composite + for (Composite composite : contribution.getDeployables()) { + if (nodeComposite.getIncludes().contains(composite)){ + // deactivate it + deactivateComposite(composite); + + // remove it + nodeComposite.getIncludes().remove(composite); + } + } + + // remove the local record of the contribution + contributions.remove(contributionURI); + + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + public void addToDomainLevelCompositeFromDomain(QName compositeQName) throws NodeException { + + if (nodeStarted){ + throw new NodeException("Can't add composite " + compositeQName.toString() + " when the node is running. Call stop() on the node first"); + } + + Composite composite = composites.get(compositeQName); + + if (composite == null) { + throw new NodeException("Composite " + compositeQName.toString() + " not found" ); + } + + // if the named composite is not already in the list then deploy it + if (!nodeComposite.getIncludes().contains(composite)) { + nodeComposite.getIncludes().add(composite); + + try { + // build and activate the model for this composite + activateComposite(composite); + } catch (Exception ex) { + throw new NodeException(ex); + } + } + } + + // SCANode API methods + + public void start() throws NodeException { + if (domainURI != null){ + throw new NodeException("Node is part of domain " + + domainURI + + " so must be starterd from there"); + } else { + startFromDomain(); + } + } + + public void stop() throws NodeException { + if (domainURI != null){ + throw new NodeException("Node is part of domain " + + domainURI + + " so must be stopped from there"); + } else { + stopFromDomain(); + } + } + + public void destroy() throws NodeException { + try { + stopFromDomain(); + + removeAllContributions(); + + // remove the node factory + ModelFactoryExtensionPoint factories = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + factories.removeFactory(nodeFactory); + nodeFactory.setNode(null); + + // unregister the node + scaDomain.removeNode(this); + + // node runtime is stopped by the domain proxy once it has + // removed the management components + scaDomain.destroy(); + + scaDomain = null; + nodeRuntime = null; + contributions = null; + composites = null; + compositeFiles = null; + } catch(NodeException ex) { + throw ex; + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + public String getURI(){ + return nodeURI; + } + + public SCADomain getDomain(){ + return scaDomain; + } + + public void addContribution(String contributionURI, URL contributionURL) throws NodeException { + addContribution(contributionURI, contributionURL, null); + } + + public void addContribution(String contributionURI, URL contributionURL, ClassLoader contributionClassLoader ) throws NodeException { + + try { + addContributionFromDomain(contributionURI, contributionURL, contributionClassLoader); + + // add the contribution to the domain. + scaDomain.registerContribution(nodeURI, contributionURI, contributionURL.toExternalForm()); + + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + public void removeContribution(String contributionURI) throws NodeException { + + try { + removeContributionFromDomain(contributionURI); + + // remove the contribution from the domain. + scaDomain.unregisterContribution(nodeURI, contributionURI); + + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + private void removeAllContributions() throws NodeException { + try { + // copy the keys so we don't get a concurrency error + List<String> keys = new ArrayList<String>(); + + for (String contributionURI : contributions.keySet()){ + keys.add(contributionURI); + } + + // Remove all contributions + for (String contributionURI : keys){ + removeContribution(contributionURI); + } + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + private boolean isDeployable(Composite composite){ + boolean deployable = false; + + for (Contribution contribution : contributions.values()){ + if (contribution.getDeployables().contains(composite)) { + deployable = true; + break; + } + } + + return deployable; + } + + public void addToDomainLevelComposite(QName compositeQName) throws NodeException { + + if (nodeStarted){ + throw new NodeException("Can't add composite " + compositeQName.toString() + " when the node is running. Call stop() on the node first"); + } + + // if no composite name is specified add all deployable composites + // to the domain + if (compositeQName == null){ + for (Composite composite : composites.values()) { + if (!nodeComposite.getIncludes().contains(composite)) { + nodeComposite.getIncludes().add(composite); + + try { + // build and activate the model for this composite + activateComposite(composite); + + // register the composite with the domain + scaDomain.registerDomainLevelComposite(nodeURI, composite.getName().toString()); + + } catch (Exception ex) { + throw new NodeException(ex); + } + + } + } + } else { + Composite composite = composites.get(compositeQName); + + if (composite == null) { + throw new NodeException("Composite " + compositeQName.toString() + " not found" ); + } + + // if the named composite is not already in the list then deploy it + if (!nodeComposite.getIncludes().contains(composite)) { + nodeComposite.getIncludes().add(composite); + + try { + // build and activate the model for this composite + activateComposite(composite); + + // register the composite with the domain + scaDomain.registerDomainLevelComposite(nodeURI, composite.getName().toString()); + + } catch (Exception ex) { + throw new NodeException(ex); + } + } + } + + } + + public void addToDomainLevelComposite(String compositePath) throws NodeException { + + if (compositePath == null){ + addToDomainLevelComposite((QName)null); + } else { + Composite composite = compositeFiles.get(compositePath); + + if (composite != null){ + addToDomainLevelComposite(composite.getName()); + } else { + throw new NodeException("Composite " + compositePath + " not found" ); + } + } + } + + private void activateComposite(Composite composite) throws CompositeBuilderException, ActivationException { + logger.log(Level.INFO, "Building composite: " + composite.getName()); + + // Create the model for the composite + nodeRuntime.getCompositeBuilder().build(composite); + + // activate the composite + nodeRuntime.getCompositeActivator().activate(composite); + + // tell the domain where all the service endpoints are + registerRemoteServices(nodeURI, composite); + } + + private void deactivateComposite(Composite composite) throws CompositeBuilderException, ActivationException { + nodeRuntime.getCompositeActivator().deactivate(composite); + + // no deregistering of endpoints as endpoint handling is going to have to change + } + + + /** + * Configure the default HTTP port for this node. + * The motivation here is to set the default binding on the servlet container + * based on whatever information is available. In particular if no Node URL is + * provided then one of the ports from the first composite is used so that + * some recognizable default is provided for any bindings that are specified + * without URIs + */ + private void configureDefaultPort() { + if (composites.size() == 0){ + return; + } + + Composite composite = nodeComposite.getIncludes().get(1); + + if (composite == null) { + return; + } + + int port = -1; + for (Service service: composite.getServices()) { + for (Binding binding: service.getBindings()) { + String uri = binding.getURI(); + if (uri != null) { + port = URI.create(uri).getPort(); + if (port != -1) { + break; + } + } + } + if (port != -1) { + break; + } + } + for (Component component: composite.getComponents()) { + for (ComponentService service: component.getServices()) { + for (Binding binding: service.getBindings()) { + String uri = binding.getURI(); + if (uri != null) { + port = URI.create(uri).getPort(); + if (port != -1) { + break; + } + } + } + if (port != -1) { + break; + } + } + if (port != -1) { + break; + } + } + + // Then get the port from the node URI + if (port == -1) { + port = URI.create(nodeURI).getPort(); + } + + // Configure the default port + if (port != -1) { + ServletHostExtensionPoint servletHosts = nodeRuntime.getExtensionPointRegistry().getExtensionPoint(ServletHostExtensionPoint.class); + for (ServletHost servletHost: servletHosts.getServletHosts()) { + servletHost.setDefaultPort(port); + } + } + } + + private void startComposites() throws NodeException { + try { + if (nodeComposite.getIncludes().size() == 0 ){ + logger.log(Level.INFO, nodeURI + + " has no composites to start" ); + } else { +/* TODO - moved build/activate back to the point where the + * composite is added. What should I do about this default port business. + * I think that needs to be consumed by the domain model anyhow + // Configure the default server port for the node + configureDefaultPort(); +*/ + + // do cross composite wiring. This is here just in case + // the node has more than one composite and is stand alone + // If the node is not stand alone the domain will do this + if (domainURI == null){ + domainBuilder.wireDomain(nodeComposite); + } + + for (Composite composite : nodeComposite.getIncludes()) { + // don't try and restart the management composite + // they will already have been started by the domain proxy + if (!composite.getName().equals(nodeManagementCompositeName)){ + startComposite(composite); + } + } + } + + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + private void startComposite(Composite composite) throws CompositeBuilderException, ActivationException { + logger.log(Level.INFO, "Starting composite: " + composite.getName()); + + //start the composite + nodeRuntime.getCompositeActivator().start(composite); + } + + private void stopComposites() throws NodeException { + + try { + + for (Composite composite : nodeComposite.getIncludes()) { + // don't try and stop the management composite + // if we do that we can't manage the node + if (!composite.getName().equals(nodeManagementCompositeName)){ + stopComposite(composite); + } + } + + } catch (Exception ex) { + throw new NodeException(ex); + } + } + + private void stopComposite(Composite composite) + throws ActivationException { + logger.log(Level.INFO, "Stopping composite: " + composite.getName()); + nodeRuntime.getCompositeActivator().stop(composite); + } + + private void registerRemoteServices(String nodeURI, Composite composite){ + // Loop through all service binding URIs registering them with the domain + for (Service service: composite.getServices()) { + for (Binding binding: service.getBindings()) { + registerRemoteServiceBinding(nodeURI, null, service, binding); + } + } + + for (Component component: composite.getComponents()) { + for (ComponentService service: component.getServices()) { + for (Binding binding: service.getBindings()) { + registerRemoteServiceBinding(nodeURI, component, service, binding); + } + } + } + } + + private void registerRemoteServiceBinding(String nodeURI, Component component, Service service, Binding binding ){ + if (service.getInterfaceContract().getInterface().isRemotable()) { + String uriString = binding.getURI(); + if (uriString != null) { + + + String serviceName = service.getName(); + + if (component != null){ + serviceName = component.getName() + '/' + serviceName; + } + + try { + scaDomain.registerServiceEndpoint(domainURI, + nodeURI, + serviceName, + binding.getClass().getName(), + uriString); + } catch(Exception ex) { + logger.log(Level.WARNING, + "Unable to register service: " + + domainURI + " " + + nodeURI + " " + + service.getName()+ " " + + binding.getClass().getName() + " " + + uriString); + } + } + } + } + + public void updateComposite(QName compositeQName, String compositeXMLBase64 ) throws NodeException { + logger.log(Level.INFO, "Updating composite " + compositeQName.toString() + + " at node " + nodeURI); + + ByteArrayInputStream bais = new ByteArrayInputStream(Base64Binary.decode(compositeXMLBase64)); + + // find the composite that will be updated + Composite composite = composites.get(compositeQName); + + if (composite == null) { + throw new NodeException("trying to update composite " + compositeQName.toString() + + " which can't be found in node " + nodeURI); + } + + // parse the XML into an composite object + Composite newComposite = null; + + ExtensionPointRegistry registry = nodeRuntime.getExtensionPointRegistry(); + StAXArtifactProcessorExtensionPoint staxProcessors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class); + + try { + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + XMLStreamReader reader = inputFactory.createXMLStreamReader(bais); + newComposite = processor.read(reader); + reader.close(); + } catch (Exception ex) { + throw new NodeException(ex); + } + + + // for each component in the composite compare it against the live component + for (Component newComponent : newComposite.getComponents()){ + for (Component component : composite.getComponents()){ + if (component.getName().equals(newComponent.getName())){ + // compare the component references + for (Reference newReference : newComponent.getReferences()){ + for (Reference reference : component.getReferences()) { + if (reference.getName().equals(newReference.getName())) { + boolean referenceChanged = false; + List<Binding> removeCandidates = new ArrayList<Binding>(); + List<Binding> addCandidates = new ArrayList<Binding>(); + + removeCandidates.addAll(reference.getBindings()); + + for (Binding newBinding : newReference.getBindings()){ + boolean bindingFound = false; + for (Binding binding : reference.getBindings()){ + // find the matching target service binding + if (binding.getName().equals(newBinding.getName())){ + if ((binding.getURI() != null) && + (newBinding.getURI() != null) && + !binding.getURI().equals(newBinding.getURI())){ + binding.setURI(newBinding.getURI()); + referenceChanged = true; + + logger.log(Level.INFO, "Updating binding " + + component.getName() + + " reference " + + reference.getName() + + " binding " + + binding.getClass().getName() + + " URI " + + binding.getURI()); + } + bindingFound = true; + removeCandidates.remove(binding); + } + } + + if (bindingFound == false){ + addCandidates.add(newBinding); + } + + } + + for (Binding addBinding : addCandidates){ + reference.getBindings().add(addBinding); + referenceChanged = true; + logger.log(Level.INFO, "Adding binding " + + component.getName() + + " reference " + + reference.getName() + + " binding " + + addBinding.getClass().getName() + + " URI " + + addBinding.getURI()); + } + + // remove all of the old bindings + for (Binding removeBinding : removeCandidates){ + reference.getBindings().remove(removeBinding); + referenceChanged = true; + logger.log(Level.INFO, "Removing binding " + + component.getName() + + " reference " + + reference.getName() + + " binding " + + removeBinding.getClass().getName() + + " URI " + + removeBinding.getURI()); + } + + // if the node is running restart the reference and the component that holds it + if (referenceChanged && nodeStarted){ + try { + nodeRuntime.getCompositeActivator().stop((RuntimeComponent)component); + nodeRuntime.getCompositeActivator().deactivate((RuntimeComponent)component, + (RuntimeComponentReference)reference); + nodeRuntime.getCompositeActivator().start((RuntimeComponent)component, + (RuntimeComponentReference)reference); + nodeRuntime.getCompositeActivator().start((RuntimeComponent)component); + + } catch (Exception ex) { + throw new NodeException(ex); + } + + } + } + } + } + + // TODO - compare other parts of the component + } + } + } + + // TODO - Compare other parts of the composite? + } + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java new file mode 100644 index 0000000000..0c46050a4c --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/SCANodeUtil.java @@ -0,0 +1,328 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.impl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; +import org.apache.tuscany.sca.core.assembly.ActivationException; + + +/** + * Some utility methods for the Node implementation + * + * @version $Rev: 556897 $ $Date: 2007-09-07 12:41:52 +0100 (Fri, 07 Sep 2007) $ + */ +public class SCANodeUtil { + private final static Logger logger = Logger.getLogger(SCANodeUtil.class.getName()); + + /** + * Given a contribution path an array of composite names or neither this method finds + * a suitable contribution to load + * + * @param classLoader + * @param compositePath + * @param composites + * @return the contribution URL + * @throws MalformedURLException + */ +/* + public static URL findContributionURLFromCompositeNameOrPath(ClassLoader classLoader, String contributionPath, String[] composites) + throws MalformedURLException { + + String contributionArtifactPath = null; + URL contributionArtifactURL = null; + + + if (contributionPath != null && contributionPath.length() > 0) { + + //encode spaces as they would cause URISyntaxException + contributionPath = contributionPath.replace(" ", "%20"); + URI contributionURI = URI.create(contributionPath); + if (contributionURI.isAbsolute() || composites.length == 0) { + return new URL(contributionPath); + } else { + // contributionArtifactURL = classLoader.getResource(contributionPath); + // if (contributionArtifactURL == null) { + // throw new IllegalArgumentException("Composite not found: " + contributionArtifactPath); + // } + } + } + + if ( contributionArtifactURL == null){ + if (composites != null && composites.length > 0 && composites[0].length() > 0) { + + // Here the SCADomain was started with a reference to a composite file + contributionArtifactPath = composites[0]; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + if (contributionArtifactURL == null) { + throw new IllegalArgumentException("Composite not found: " + contributionArtifactPath); + } + } else { + + // Here the SCANode was started without any reference to a composite file + // We are going to look for an sca-contribution.xml or sca-contribution-generated.xml + + // Look for META-INF/sca-contribution.xml + contributionArtifactPath = Contribution.SCA_CONTRIBUTION_META; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + + // Look for META-INF/sca-contribution-generated.xml + if (contributionArtifactURL == null) { + contributionArtifactPath = Contribution.SCA_CONTRIBUTION_GENERATED_META; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + } + + // Look for META-INF/sca-deployables directory + if (contributionArtifactURL == null) { + contributionArtifactPath = Contribution.SCA_CONTRIBUTION_DEPLOYABLES; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + } + } + } + + if (contributionArtifactURL == null) { + throw new IllegalArgumentException("Can't determine contribution deployables. Either specify a composite file, or use an sca-contribution.xml file to specify the deployables."); + } + + URL contributionURL = null; + // "jar:file://....../something.jar!/a/b/c/app.composite" + try { + String url = contributionArtifactURL.toExternalForm(); + String protocol = contributionArtifactURL.getProtocol(); + if ("file".equals(protocol)) { + // directory contribution + if (url.endsWith(contributionArtifactPath)) { + String location = url.substring(0, url.lastIndexOf(contributionArtifactPath)); + // workaround from evil url/uri form maven + contributionURL = FileHelper.toFile(new URL(location)).toURI().toURL(); + } + + } else if ("jar".equals(protocol)) { + // jar contribution + String location = url.substring(4, url.lastIndexOf("!/")); + // workaround for evil url/uri from maven + contributionURL = FileHelper.toFile(new URL(location)).toURI().toURL(); + } + } catch (MalformedURLException mfe) { + throw new IllegalArgumentException(mfe); + } + + return contributionURL; + } +*/ + /** + * A rather ugly method to find and fix the url of the service, assuming that there + * is one. + * + * we can't get this out of a service reference + * the component itself doesn't know how to get it + * the binding can't to do it automatically as it's not the sca binding + * + * TODO - This would be better done by passing out a serializable reference to service discovery + * but this doesn't work yet + * + * @return node manager url + */ +/* + public static void fixUpNodeServiceUrls(List<Component> nodeComponents, URL nodeUrlString) + throws MalformedURLException, UnknownHostException, IOException { + + for(Component component : nodeComponents){ + for (ComponentService service : component.getServices() ){ + for (Binding binding : service.getBindings() ) { + fixUpNodeServiceBindingUrl(binding, nodeUrlString); + } + } + } + } +*/ + /** + * Find and return the URL of the NodeManagerService + * + * @param nodeComponents + * @return + */ +/* + public static String getNodeManagerServiceUrl(List<Component> nodeComponents){ + String nodeManagerUrl = null; + + for(Component component : nodeComponents){ + for (ComponentService service : component.getServices() ){ + + if ( service.getName().equals("NodeManagerService")) { + nodeManagerUrl = service.getBindings().get(0).getURI(); + } + } + } + + return nodeManagerUrl; + } +*/ + + /** + * For node management services that use the http(s) protocol then use the node url as the enpoint + * if it has been specified otherwise find a port that isn't in use and make sure the domain name + * is the real domain name + * + * @param binding + * @param nodeURL the URL provided as the identifier of the node + */ +/* + public static void fixUpNodeServiceBindingUrl(Binding binding, URL manualUrl) + throws MalformedURLException, UnknownHostException, IOException { + + String urlString = binding.getURI(); + + // only going to fiddle with bindings that use HTTP protocol + if( (urlString == null) || + ((urlString.startsWith("http") != true ) && + (urlString.startsWith("https") != true )) || + (binding instanceof SCABinding)) { + return; + } + + URL bindingUrl = new URL(urlString); + String originalHost = bindingUrl.getHost(); + String newHost = null; + int originalPort = bindingUrl.getPort(); + int newPort = 0; + + if (manualUrl != null) { + // the required url has been specified manually + newHost = manualUrl.getHost(); + newPort = manualUrl.getPort(); + + if ( newHost.equals("localhost")){ + newHost = InetAddress.getLocalHost().getHostName(); + } + } else { + // discover the host and port information + newHost = InetAddress.getLocalHost().getHostName(); + newPort = findFreePort(originalPort); + } + + // replace the old with the new + urlString = urlString.replace(String.valueOf(originalPort), String.valueOf(newPort)); + urlString = urlString.replace(originalHost, newHost); + + // set the address back into the NodeManager binding. + binding.setURI(urlString); + } +*/ + /** + * Find a port on this machine that isn't in use. + * + * @param startPort + * @return + */ +/* + public static int findFreePort(int startPort) throws IOException + { + ServerSocket socket = new ServerSocket(0); + int port = socket.getLocalPort(); + socket.close(); + return port; + } +*/ + + /** + * For node services that have to talk to the domain fix up the reference URL using the + * provided domain url if it has been provided + * + * @param nodeComponents + * @param domainUrlString + * @throws MalformedURLException + * @throws UnknownHostException + */ +/* + public static void fixUpNodeReferenceUrls(List<Component> nodeComponents, URL domainUrl) + throws MalformedURLException, UnknownHostException, ActivationException{ + + for(Component component : nodeComponents){ + for (ComponentReference reference : component.getReferences() ){ + if ( reference.getName().equals("domainManager") || + reference.getName().equals("scaDomainService")) { + for (Binding binding : reference.getBindings() ) { + fixUpNodeReferenceBindingUrl(binding, domainUrl); + } + } + } + } + } +*/ + /** + * For node management references to the domain fix up the binding URLs so that they point + * to the endpoint described in the domainURL + * + * @param binding + * @param nodeURL the URL provided as the identifier of the node + */ +/* + public static void fixUpNodeReferenceBindingUrl(Binding binding, URL manualUrl) + throws MalformedURLException, UnknownHostException, ActivationException{ + + String urlString = binding.getURI(); + + // only going to fiddle with bindings that use HTTP protocol + if( (urlString == null) || + ((urlString.startsWith("http") != true ) && + (urlString.startsWith("https") != true )) || + (binding instanceof SCABinding) ) { + return; + } + + URL bindingUrl = new URL(urlString); + String originalHost = bindingUrl.getHost(); + String newHost = null; + int originalPort = bindingUrl.getPort(); + int newPort = 0; + + if (manualUrl != null) { + // the required url has been specified manually + newHost = manualUrl.getHost(); + newPort = manualUrl.getPort(); + } else { + throw new ActivationException("domain uri can't be null"); + } + + // replace the old with the new + urlString = urlString.replace(String.valueOf(originalPort), String.valueOf(newPort)); + urlString = urlString.replace(originalHost, newHost); + + // set the address back into the NodeManager binding. + binding.setURI(urlString); + } + */ +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/launch/SCANodeLauncher.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/launch/SCANodeLauncher.java new file mode 100644 index 0000000000..0c12d75a25 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/launch/SCANodeLauncher.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.node.launch; + +import java.io.IOException; +import java.net.URL; + +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.SCANodeFactory; +import org.apache.tuscany.sca.node.util.SCAContributionUtil; + +public class SCANodeLauncher { + + /** + * @param args + */ + public static void main(String[] args) { + System.out.println("Tuscany starting..."); + + SCANode node = null; + try { + String compositeFile = args[0]; + System.out.println("Composite: " + compositeFile); + + SCANodeFactory nodeFactory = SCANodeFactory.newInstance(); + node = nodeFactory.createSCANode(null, "http://localhost:9999"); + + ClassLoader classLoader = SCANodeLauncher.class.getClassLoader(); + URL contribution = SCAContributionUtil.findContributionFromResource(classLoader, compositeFile); + node.addContribution(compositeFile, contribution); + + node.addToDomainLevelComposite(compositeFile); + + node.start(); + + } catch (Exception e) { + System.err.println("Exception starting node"); + e.printStackTrace(); + System.exit(0); + } + + System.out.println("Node ready..."); + System.out.println("Press enter to shutdown"); + try { + System.in.read(); + } catch (IOException e) { + } + + try { + node.destroy(); + } catch (Exception e) { + System.err.println("Exception stopping node"); + e.printStackTrace(); + } + + System.exit(0); + } +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/management/impl/SCANodeManagerServiceImpl.java b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/management/impl/SCANodeManagerServiceImpl.java new file mode 100644 index 0000000000..c19c51f28a --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/management/impl/SCANodeManagerServiceImpl.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.node.management.impl; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl; +import org.apache.tuscany.sca.domain.SCADomain; +import org.apache.tuscany.sca.node.ComponentInfo; +import org.apache.tuscany.sca.node.ComponentManagerService; +import org.apache.tuscany.sca.node.NodeException; +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.impl.ComponentInfoImpl; +import org.apache.tuscany.sca.node.impl.SCANodeImpl; +import org.apache.tuscany.sca.node.management.SCANodeManagerInitService; +import org.apache.tuscany.sca.node.management.SCANodeManagerService; +import org.osoa.sca.annotations.Scope; +import org.osoa.sca.annotations.Service; + +/** + * Manages a node implementation + * + * @version $Rev: 552343 $ $Date: 2007-09-11 18:45:36 +0100 (Tue, 11 Sep 2007) $ + */ +@Scope("COMPOSITE") +@Service(interfaces = {SCANodeManagerService.class, SCANodeManagerInitService.class, ComponentManagerService.class}) +public class SCANodeManagerServiceImpl implements SCANodeManagerService, SCANodeManagerInitService, ComponentManagerService { + + private final static Logger logger = Logger.getLogger(SCANodeManagerServiceImpl.class.getName()); + + private SCANodeImpl node; + + + // NodeManagerInitService + + public void setNode(SCANode node) { + this.node = (SCANodeImpl)node; + } + + // SCANodeManagerService methods + + public String getURI() { + return node.getURI(); + } + + public void addContribution(String contributionURI, String contributionURL) throws NodeException { + try { + node.addContributionFromDomain(contributionURI, new URL(contributionURL), null); + } catch (MalformedURLException ex){ + throw new NodeException(ex); + } + } + + public void removeContribution(String contributionURI) throws NodeException { + node.removeContributionFromDomain(contributionURI); + } + + public void addToDomainLevelComposite(String compositeName) throws NodeException { + node.addToDomainLevelCompositeFromDomain(QName.valueOf(compositeName)); + } + + public void start() throws NodeException { + node.startFromDomain(); + } + + public void stop() throws NodeException { + node.stopFromDomain(); + } + + public void destroyNode() throws NodeException { + // do nothing - the domain can't destroy nodes + } + + public void updateComposite(String compositeQName, String compositeXMLBase64 ) throws NodeException { + ((SCANodeImpl)node).updateComposite(QName.valueOf(compositeQName), compositeXMLBase64 ); + } + + // ComponentManagerService + + public List<ComponentInfo> getComponentInfos() { + List<ComponentInfo> componentInfos = new ArrayList<ComponentInfo>(); + for (Component component : node.getComponents()) { + ComponentInfo componentInfo = new ComponentInfoImpl(); + componentInfo.setName(component.getName()); + componentInfo.setStarted(((RuntimeComponentImpl)component).isStarted()); + componentInfos.add(componentInfo); + } + return componentInfos; + } + + public ComponentInfo getComponentInfo(String componentName) { + Component component = node.getComponent(componentName); + ComponentInfo componentInfo = new ComponentInfoImpl(); + componentInfo.setName(component.getName()); + componentInfo.setStarted(((RuntimeComponentImpl)component).isStarted()); + return componentInfo; + } + +} diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/node.composite b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/node.composite new file mode 100644 index 0000000000..137ae72467 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/node.composite @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+
+<!--
+ The components used to interact with a Node. The components here are expected to be here
+ so edit with caution. In particular the service and reference urls are edited at runtime
+ in the in memory model. So don't rely on the values here.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ targetNamespace="http://tuscany.apache.org/xmlns/tuscany/1.0"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"
+ name="node">
+
+ <component name="SCADomainEventServiceProxyComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.impl.SCADomainEventServiceProxyImpl"/>
+ <service name="SCADomainEventService">
+ <interface.java interface="org.apache.tuscany.sca.domain.SCADomainEventService"/>
+ <binding.sca/>
+ </service>
+ <reference name="domainManager">
+ <interface.java interface="org.apache.tuscany.sca.domain.SCADomainEventService"/>
+ <binding.ws uri="http://localhost:9999/SCADomainManagerComponent/SCADomainEventService"/>
+ </reference>
+ </component>
+
+ <component name="SCADomainAPIServiceProxyComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.impl.SCADomainAPIServiceProxyImpl"/>
+ <service name="SCADomainAPIService">
+ <interface.java interface="org.apache.tuscany.sca.domain.SCADomainAPIService"/>
+ <binding.sca/>
+ </service>
+ <reference name="domainManager">
+ <interface.java interface="org.apache.tuscany.sca.domain.SCADomainAPIService"/>
+ <binding.ws uri="http://localhost:9999/SCADomainManagerComponent/SCADomainAPIService"/>
+ </reference>
+ </component>
+
+ <component name="SCANodeManagerComponent">
+ <implementation.java class="org.apache.tuscany.sca.node.management.impl.SCANodeManagerServiceImpl"/>
+ <service name="SCANodeManagerInitService">
+ <interface.java interface="org.apache.tuscany.sca.node.management.SCANodeManagerInitService"/>
+ <binding.sca/>
+ </service>
+ <service name="SCANodeManagerService">
+ <interface.java interface="org.apache.tuscany.sca.node.management.SCANodeManagerService"/>
+ <binding.ws/>
+ </service>
+ <service name="ComponentManagerService">
+ <interface.java interface="org.apache.tuscany.sca.node.ComponentManagerService"/>
+ <t:binding.jsonrpc/>
+ </service>
+ </component>
+
+ <!--component name="node">
+ <t:implementation.resource location="webroot"/> + <service name="Resource">
+ <t:binding.http/>
+ </service>
+ </component-->
+
+</composite>
diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/index.html b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/index.html new file mode 100644 index 0000000000..e53f353b53 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/index.html @@ -0,0 +1,87 @@ +<html>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ -->
+<head>
+<title>Apache Tuscany Node</TITLE>
+
+ <script type="text/javascript" src="../SCADomain/scaDomain.js"></script>
+
+ <script language="JavaScript">
+
+ nodeManager = new JSONRpcClient("../NodeManagerComponent/NodeManagerJson").Service;
+ componentManager = new JSONRpcClient("../NodeManagerComponent/ComponentManagerJson").Service;
+
+ function getNodeUri() {
+ nodeManager.getNodeUri(handleGetNodeUri);
+ getComponentInfos()
+ }
+
+ function handleGetNodeUri(result) {
+ document.getElementById('nodeUri').innerHTML=result;
+ }
+
+ function getComponentInfos() {
+ componentManager.getComponentInfos(handleGetComponentInfos);
+ }
+
+ function handleGetComponentInfos(result) {
+
+ var text = ""
+
+ for (var i in result.list){
+ var component = result.list[i];
+
+ text = text + "<table>";
+ text = text + "<TR CLASS='source_2' >";
+ text = text + " <TD>" + component.name+ "</TD>";
+ text = text + " <TD>" + component.started+ "</TD>";
+ text = text + "</TR>";
+ text = text + "</table>";
+ }
+
+ document.getElementById('nodeInfo').innerHTML=text;
+ }
+
+
+ </script>
+
+ <link rel="stylesheet" type="text/css" href="style.css" />
+</head>
+
+<body onload="getNodeUri()">
+
+
+<h1 id="top">Apache Tuscany Node</h1>
+<div id="errors"></div>
+
+<p>Node Uri <span id="nodeUri"></span>:</p>
+
+<table>
+<TR>
+<TD>Component Name</TD>
+<TD>Component Is Started</TD>
+</TR>
+</table>
+
+<div id="nodeInfo"></div>
+
+<p /><input type="button" value="Refresh" onclick="getComponentInfos()" />
+
+</body>
+</html>
diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/node.png b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/node.png Binary files differnew file mode 100644 index 0000000000..fa01e64272 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/node.png diff --git a/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/style.css b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/style.css new file mode 100644 index 0000000000..f5bbf23379 --- /dev/null +++ b/branches/sca-java-1.2.1/modules/node-impl/src/main/resources/webroot/style.css @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +p,table,li,h1,h2,h3 +{ +font-family: verdana, arial, 'sans serif'; +} + +p, h1, h2, h3, table, li, hr +{ +margin-left: 10pt; +} + +table +{ +border-color: black; +border-collapse: separate; +border-spacing: 0px 1px; + +margin-right: 10pt; +margin-left: 10pt; +width: 800px; +} + +.sourceDetailsTable +{ +width: 600px; +} + +tr, td +{ +margin-left: 0pt; +margin-right: 0pt; +padding-left: 10pt; +font-size: 90%; +} + +p,li,th +{ +font-size: 90%; +margin-left: 10pt; +} + +pre +{ +margin-left: 10pt; +} + +body +{ +#ffffff; +} + +h1,h2,h3,hr +{ +color: firebrick; +} + +a:link {COLOR: firebrick;} +a:visited {COLOR: firebrick;} +a:active {COLOR: navy;} + +.link +{ +COLOR: firebrick; +text-decoration: underline; +} + +.clickable +{ +cursor: pointer +} + +.unread_title +{ +font-weight: bold; +} + +.read_title +{ +font-weight: normal; +} + +.summary +{ +color: DimGrey; +} + +.hidden +{ +display: none; +} + +.source_name +{ +width: 600px; +} + +.alert_text +{ +width: 600px; +} + +.alert_data +{ +margin-left: 10px; +width: 800px; +height: 800px; +} + +.source_0 +{ +background-color: LightGreen; +} + +.source_1 +{ +background-color: LightSkyBlue; +} + +.source_2 +{ +background-color: Khaki; +} + +.source_3 +{ +background-color: LightPink; +} + +.source_4 +{ +background-color: Orange; +} + +.source_5 +{ +background-color: LightCoral; +} + +.source_6 +{ +background-color: Orchid; +} + +.source_7 +{ +background-color: Peru; +} + +.source_8 +{ +background-color: SpringGreen; +} + +.source_9 +{ +background-color: LightGrey; +} + |