diff options
Diffstat (limited to 'sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher')
5 files changed, 640 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationDaemonBootstrap.java b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationDaemonBootstrap.java new file mode 100644 index 0000000000..edf2aefdde --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationDaemonBootstrap.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.node.launcher; + +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.node.SCANode2; + +/** + * Bootstrap class for the SCA node daemon. + * + * @version $Rev$ $Date$ + */ +public class NodeImplementationDaemonBootstrap { + private SCANode2 node; + + /** + * A node wrappering an instance of a node daemon. + */ + public static class NodeFacade implements SCANode2 { + private ClassLoader threadContextClassLoader; + private ClassLoader runtimeClassLoader; + private SCADomain daemon; + + private NodeFacade() { + runtimeClassLoader = Thread.currentThread().getContextClassLoader(); + } + + public void start() { + threadContextClassLoader = Thread.currentThread().getContextClassLoader(); + boolean started = false; + try { + Thread.currentThread().setContextClassLoader(runtimeClassLoader); + daemon = SCADomain.newInstance("NodeDaemon.composite"); + started = true; + } finally { + if (!started) { + Thread.currentThread().setContextClassLoader(threadContextClassLoader); + } + } + } + + public void stop() { + try { + Thread.currentThread().setContextClassLoader(runtimeClassLoader); + daemon.close(); + } finally { + Thread.currentThread().setContextClassLoader(threadContextClassLoader); + } + } + } + + /** + * Constructs a new daemon bootstrap. + */ + public NodeImplementationDaemonBootstrap() throws Exception { + node = new NodeFacade(); + } + + /** + * Returns the node representing the daemon. + * @return + */ + public SCANode2 getNode() { + return node; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationLauncherBootstrap.java b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationLauncherBootstrap.java new file mode 100644 index 0000000000..2e94f72c91 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationLauncherBootstrap.java @@ -0,0 +1,123 @@ +/* + * 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.implementation.node.launcher; + +import org.apache.tuscany.sca.node.SCAClient; +import org.apache.tuscany.sca.node.SCANode2; +import org.apache.tuscany.sca.node.SCANode2Factory; +import org.apache.tuscany.sca.node.SCANode2Factory.SCAContribution; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * Bootstrap class for standalone SCA nodes. + * + * @version $Rev$ $Date$ + */ +public class NodeImplementationLauncherBootstrap { + + private SCANode2 node; + + /** + * A node facade. + */ + public static class NodeFacade implements SCANode2, SCAClient { + private ClassLoader threadContextClassLoader; + private ClassLoader runtimeClassLoader; + private SCANode2 delegate; + + private NodeFacade(SCANode2 delegate) { + runtimeClassLoader = Thread.currentThread().getContextClassLoader(); + this.delegate = delegate; + } + + public void start() { + threadContextClassLoader = Thread.currentThread().getContextClassLoader(); + boolean started = false; + try { + Thread.currentThread().setContextClassLoader(runtimeClassLoader); + delegate.start(); + started = true; + } finally { + if (!started) { + Thread.currentThread().setContextClassLoader(threadContextClassLoader); + } + } + } + + public void stop() { + try { + Thread.currentThread().setContextClassLoader(runtimeClassLoader); + delegate.stop(); + } finally { + Thread.currentThread().setContextClassLoader(threadContextClassLoader); + } + } + + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + return (R)((SCAClient)delegate).cast(target); + } + + public <B> B getService(Class<B> businessInterface, String serviceName) { + return (B)((SCAClient)delegate).getService(businessInterface, serviceName); + } + + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) { + return (ServiceReference<B>)((SCAClient)delegate).getServiceReference(businessInterface, referenceName); + } + } + + /** + * Bootstrap a new SCA node. + * + * @param configurationURI + */ + public NodeImplementationLauncherBootstrap(String configurationURI) throws Exception { + SCANode2Factory nodeFactory = SCANode2Factory.newInstance(); + node = new NodeFacade(nodeFactory.createSCANode(configurationURI)); + } + + /** + * Bootstrap a new SCA node. + * + * @param compositeURI + * @param uris + * @param locations + */ + public NodeImplementationLauncherBootstrap(String compositeURI, String[] uris, String[] locations) throws Exception { + SCANode2Factory nodeFactory = SCANode2Factory.newInstance(); + SCAContribution[] contributions = new SCAContribution[uris.length]; + for (int i = 0; i < uris.length; i++) { + contributions[i] = new SCAContribution(uris[i], locations[i]); + } + node = new NodeFacade(nodeFactory.createSCANode(compositeURI, contributions)); + } + + /** + * Returns the SCA node. + * + * @return + */ + public SCANode2 getNode() { + return node; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationLauncherUtil.java b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationLauncherUtil.java new file mode 100644 index 0000000000..bfa2af61b1 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeImplementationLauncherUtil.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.node.launcher; + +/** + * Utility methods for node implementation launchers. + * + * @version $Rev$ $Date$ + */ +public class NodeImplementationLauncherUtil { + + private static final String TUSCANY_DOMAIN = "TUSCANY_DOMAIN"; + private static final String DEFAULT_DOMAIN = "http://localhost:9990"; + + /** + * Determine the URI of a node image. The domain URI can be configured + * using a TUSCANY_DOMAIN system property or environment variable. + * + * @param nodeName + * @return + */ + public static String nodeImageURI(String nodeName) { + String domain = System.getProperty(TUSCANY_DOMAIN); + if (domain == null || domain.length() == 0) { + domain = System.getenv(TUSCANY_DOMAIN); + } + if (domain == null || domain.length() ==0) { + domain = DEFAULT_DOMAIN; + } + String nodeImage = domain + "/node-image/" + nodeName; + return nodeImage; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeProcessCollectionImpl.java b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeProcessCollectionImpl.java new file mode 100644 index 0000000000..f22cea193e --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/NodeProcessCollectionImpl.java @@ -0,0 +1,321 @@ +/* + * 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.implementation.node.launcher; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.implementation.data.collection.Entry; +import org.apache.tuscany.sca.implementation.data.collection.Item; +import org.apache.tuscany.sca.implementation.data.collection.ItemCollection; +import org.apache.tuscany.sca.implementation.data.collection.LocalItemCollection; +import org.apache.tuscany.sca.implementation.data.collection.NotFoundException; +import org.apache.tuscany.sca.node.launcher.NodeLauncher; +import org.osoa.sca.ServiceRuntimeException; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; +import org.osoa.sca.annotations.Service; + +/** + * Implementation of a node process collection service. + * + * @version $Rev$ $Date$ + */ +@Scope("COMPOSITE") +@Service(interfaces={ItemCollection.class, LocalItemCollection.class}) +public class NodeProcessCollectionImpl implements ItemCollection, LocalItemCollection { + + private final static Logger logger = Logger.getLogger(NodeProcessCollectionImpl.class.getName()); + + private List<SCANodeVM> nodeVMs = new ArrayList<SCANodeVM>(); + + /** + * Initialize the component. + */ + @Init + public void initialize() { + } + + public Entry<String, Item>[] getAll() { + logger.info("getAll"); + + // Return all the running VMs + List<Entry<String, Item>> entries = new ArrayList<Entry<String, Item>>(); + for (SCANodeVM vm: nodeVMs) { + entries.add(entry(vm)); + } + return entries.toArray(new Entry[entries.size()]); + } + + public Item get(String key) throws NotFoundException { + logger.info("get " + key); + + // Return the specified VM + SCANodeVM vm = vm(key); + if (vm == null) { + throw new NotFoundException(); + } + + return item(vm); + } + + public String post(String key, Item item) { + logger.info("post " + key); + + // If the VM is already running just return it + SCANodeVM vm = vm(key); + if (vm != null) { + if (vm.isAlive()) { + return key; + } else { + // Remove dead VM entry + try { + vm.stop(); + } catch (InterruptedException e) { + throw new ServiceRuntimeException(e); + } + nodeVMs.remove(vm); + } + } + + // Start a new VM and add it to the collection + vm = new SCANodeVM(key); + nodeVMs.add(0, vm); + try { + vm.start(); + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } + + return key; + } + + public void put(String key, Item item) throws NotFoundException { + throw new UnsupportedOperationException(); + } + + public void delete(String key) throws NotFoundException { + logger.info("delete " + key); + + // Stop a VM and remove it from the collection + SCANodeVM vm = vm(key); + if (vm != null) { + try { + vm.stop(); + } catch (InterruptedException e) { + throw new ServiceRuntimeException(e); + } + nodeVMs.remove(vm); + } else { + //throw new NotFoundException(); + } + } + + public Entry<String, Item>[] query(String queryString) { + logger.info("query " + queryString); + + if (queryString.startsWith("node=")) { + + // Return the log for the specified VM + String key = queryString.substring(queryString.indexOf('=') + 1); + List<Entry<String, Item>> entries = new ArrayList<Entry<String, Item>>(); + for (SCANodeVM vm: nodeVMs) { + if (vm.getNodeName().equals(key)) { + entries.add(entry(vm)); + } + } + return entries.toArray(new Entry[entries.size()]); + + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Returns the specified VM. + * + * @param key + * @return + */ + private SCANodeVM vm(String key) { + for (SCANodeVM vm: nodeVMs) { + if (key.equals(vm.getNodeName())) { + return vm; + } + } + return null; + } + + /** + * Returns an entry representing a VM. + * + * @param vm + * @return + */ + private static Entry<String, Item> entry(SCANodeVM vm) { + Entry<String, Item> entry = new Entry<String, Item>(); + entry.setKey(vm.getNodeName()); + entry.setData(item(vm)); + return entry; + } + + /** + * Returns an item representing a VM. + * + * @param vm + * @return + */ + private static Item item(SCANodeVM vm) { + Item item = new Item(); + String key = vm.getNodeName(); + item.setTitle(title(key)); + item.setLink("/node-image/" + vm.getNodeName()); + item.setContents("<span id=\"log\" style=\"white-space: nowrap; font-size: small\">" + vm.getLog().toString() + "</span>"); + return item; + } + + /** + * Represent a child Java VM running an SCA node. + */ + private static class SCANodeVM { + private String nodeName; + private StringBuffer log; + private Process process; + private Thread monitor; + private int status; + + SCANodeVM(String nodeName) { + log = new StringBuffer(); + this.nodeName =nodeName; + } + + /** + * Starts a node in a new VM. + */ + private void start() throws IOException { + + // Determine the node image URI + String nodeImageURI = NodeImplementationLauncherUtil.nodeImageURI(nodeName); + + // Build the Java VM command line + Properties props = System.getProperties(); + String java = props.getProperty("java.home") + "/bin/java"; + String cp = props.getProperty("java.class.path"); + String main = NodeLauncher.class.getName(); + final String[] command = new String[]{ java, "-cp", cp, main , nodeImageURI}; + + logger.info("Starting " + "java " + main + " " + nodeImageURI); + + // Start the VM + ProcessBuilder builder = new ProcessBuilder(command); + builder.redirectErrorStream(true); + process = builder.start(); + + logger.info("Started " + process); + + // Start a thread to monitor the process + final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + monitor = new Thread(new Runnable() { + public void run() { + try { + for (;;) { + String s = reader.readLine(); + if (s != null) { + logger.info(s); + log.append(s + "<br>"); + } else { + break; + } + } + status = process.waitFor(); + } catch (IOException e) { + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + monitor.start(); + } + + /** + * Returns the composite used to start this VM. + * @return + */ + String getNodeName() { + return nodeName; + } + + /** + * Returns the log for this VM. + * + * @return + */ + StringBuffer getLog() { + return log; + } + + /** + * Returns true if the VM is alive + * + * @return + */ + private boolean isAlive() { + return monitor.isAlive(); + } + + /** + * Returns the VM status code. + * @return + */ + int getStatus() { + return status; + } + + /** + * Stops the VM. + * + * @throws InterruptedException + */ + private void stop() throws InterruptedException { + logger.info("Stopping " + process); + + process.destroy(); + monitor.join(); + + logger.info("Stopped " + process); + } + } + + /** + * Returns a node title. + * + * @param key + * @return + */ + private static String title(String key) { + return key; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/PingServiceImpl.java b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/PingServiceImpl.java new file mode 100644 index 0000000000..05d82e4dfc --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/implementation-node-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/launcher/PingServiceImpl.java @@ -0,0 +1,61 @@ +/* + * 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.implementation.node.launcher; + +import java.io.IOException; +import java.util.logging.Logger; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException; + +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; +import org.osoa.sca.annotations.Service; + +/** + * Implementation of a ping service component. + * + * @version $Rev$ $Date$ + */ +@Scope("COMPOSITE") +@Service(interfaces={Servlet.class}) +public class PingServiceImpl extends HttpServlet { + private static final long serialVersionUID = -3477992129462720901L; + + private final static Logger logger = Logger.getLogger(PingServiceImpl.class.getName()); + + /** + * Initialize the component. + */ + @Init + public void initialize() throws ParserConfigurationException { + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + logger.info("ping"); + response.getWriter().print("<html><body><span id=\"ping\">OK</span></body></html>"); + } + +} |