From ece4fd35da7b7fc76264776f81705e6b5b52d3e0 Mon Sep 17 00:00:00 2001 From: lresende Date: Wed, 11 Nov 2009 23:11:48 +0000 Subject: Moving 1.x branches git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835140 13f79535-47bb-0310-9956-ffa450edef68 --- .../rhino/assembly/JavaScriptImplementation.java | 74 +++ .../builder/JavaScriptContextFactoryBuilder.java | 132 +++++ .../rhino/builder/JavaScriptTargetWireBuilder.java | 40 ++ .../rhino/config/JavaScriptContextFactory.java | 114 ++++ .../rhino/context/JavaScriptComponentContext.java | 140 +++++ .../loader/JavaScriptImplementationLoader.java | 168 ++++++ .../container/rhino/rhino/E4XDataBinding.java | 108 ++++ .../container/rhino/rhino/RhinoE4XScript.java | 76 +++ .../tuscany/container/rhino/rhino/RhinoScript.java | 290 +++++++++++ .../container/rhino/shell/ScriptEngine.java | 573 +++++++++++++++++++++ .../container/rhino/shell/TuscanyShell.java | 42 ++ 11 files changed, 1757 insertions(+) create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/assembly/JavaScriptImplementation.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptContextFactoryBuilder.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptTargetWireBuilder.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/config/JavaScriptContextFactory.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/context/JavaScriptComponentContext.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/loader/JavaScriptImplementationLoader.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/E4XDataBinding.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoE4XScript.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoScript.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/ScriptEngine.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/TuscanyShell.java (limited to 'sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org') diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/assembly/JavaScriptImplementation.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/assembly/JavaScriptImplementation.java new file mode 100644 index 0000000000..c68bf239a3 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/assembly/JavaScriptImplementation.java @@ -0,0 +1,74 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.assembly; + +import org.apache.tuscany.common.resource.ResourceLoader; +import org.apache.tuscany.model.assembly.impl.AtomicImplementationImpl; + +import commonj.sdo.helper.TypeHelper; + +/** + * Default implementation of a JavScript component implementation type + * + * @version $Rev$ $Date$ + */ +public class JavaScriptImplementation extends AtomicImplementationImpl { + + private String scriptFile; + + private String script; + + private ResourceLoader resourceLoader; + + private TypeHelper typeHelper; + + public JavaScriptImplementation() { + super(); + } + + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + public ResourceLoader getResourceLoader() { + return resourceLoader; + } + + public TypeHelper getTypeHelper() { + return typeHelper; + } + + public void setTypeHelper(TypeHelper typeHelper) { + this.typeHelper = typeHelper; + } + + public String getScriptFile() { + return scriptFile; + } + + public void setScriptFile(String fn) { + scriptFile = fn; + } + + public String getScript() { + return script; + } + + public void setScript(String script) { + this.script = script; + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptContextFactoryBuilder.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptContextFactoryBuilder.java new file mode 100644 index 0000000000..2012971014 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptContextFactoryBuilder.java @@ -0,0 +1,132 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.builder; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.wsdl.Input; +import javax.wsdl.Message; +import javax.wsdl.Operation; +import javax.wsdl.Part; +import javax.wsdl.PortType; + +import org.apache.tuscany.container.rhino.assembly.JavaScriptImplementation; +import org.apache.tuscany.container.rhino.config.JavaScriptContextFactory; +import org.apache.tuscany.container.rhino.rhino.E4XDataBinding; +import org.apache.tuscany.container.rhino.rhino.RhinoE4XScript; +import org.apache.tuscany.container.rhino.rhino.RhinoScript; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.ContextFactory; +import org.apache.tuscany.core.extension.ContextFactoryBuilderSupport; +import org.apache.tuscany.model.assembly.Scope; +import org.apache.tuscany.model.assembly.Service; +import org.apache.tuscany.model.assembly.ServiceContract; +import org.apache.tuscany.model.types.wsdl.WSDLServiceContract; + +import commonj.sdo.helper.TypeHelper; + +/** + * Builds {@link org.apache.tuscany.container.rhino.config.JavaScriptContextFactory}s from a JavaScript component type + * + * @version $Rev$ $Date$ + */ +@org.osoa.sca.annotations.Scope("MODULE") +public class JavaScriptContextFactoryBuilder extends ContextFactoryBuilderSupport { + + @Override + protected ContextFactory createContextFactory(String componentName, JavaScriptImplementation jsImplementation, Scope scope) { + + Map services = new HashMap(); + for (Service service : jsImplementation.getComponentType().getServices()) { + services.put(service.getName(), service.getServiceContract().getInterface()); + } + + Map defaultProperties = new HashMap(); + for (org.apache.tuscany.model.assembly.Property property : jsImplementation.getComponentType().getProperties()) { + defaultProperties.put(property.getName(), property.getDefaultValue()); + } + + String script = jsImplementation.getScript(); + ClassLoader cl = jsImplementation.getResourceLoader().getClassLoader(); + + RhinoScript invoker; + if (isE4XStyle(componentName, jsImplementation.getComponentType().getServices())) { + E4XDataBinding dataBinding = createDataBinding(jsImplementation); + invoker = new RhinoE4XScript(componentName, script, defaultProperties, cl, dataBinding); + } else { + invoker = new RhinoScript(componentName, script, defaultProperties, cl); + } + + Map properties = new HashMap(); + JavaScriptContextFactory contextFactory = new JavaScriptContextFactory(componentName, scope, services, properties, invoker); + + return contextFactory; + } + + /** + * Tests if this should be an E4X style service + * Its E4X if the JavaScript component uses WSDL to define its interface + */ + protected boolean isE4XStyle(String componentName, List services) { + Boolean isE4XStyle = null; + for (Service service : services) { + ServiceContract sc = service.getServiceContract(); + if (sc instanceof WSDLServiceContract) { + if (isE4XStyle != null && !isE4XStyle.booleanValue()) { + throw new BuilderConfigException("mixed service interface types not supportted"); + } + isE4XStyle = Boolean.TRUE; + } else { + isE4XStyle = Boolean.FALSE; + } + } + return isE4XStyle.booleanValue(); + } + + /** + * Create the data binding for the component initialized for each operation in the service + */ + protected E4XDataBinding createDataBinding(JavaScriptImplementation jsImplementation) { + ClassLoader classLoader = jsImplementation.getResourceLoader().getClassLoader(); + TypeHelper typeHelper = jsImplementation.getTypeHelper(); + E4XDataBinding dataBinding = new E4XDataBinding(classLoader, typeHelper); + for (Service service : jsImplementation.getComponentType().getServices()) { + ServiceContract sc = service.getServiceContract(); + if (sc instanceof WSDLServiceContract) { + PortType pt = ((WSDLServiceContract) sc).getPortType(); + for (Object o : pt.getOperations()) { + Operation operation = (Operation) o; + Input input = operation.getInput(); + if (input != null) { + Message message = input.getMessage(); + if (message != null) { + List parts = message.getOrderedParts(null); + if (parts != null && parts.size() > 0) { + Part part = (Part) parts.get(0); + dataBinding.addElementQName(operation.getName(), part.getElementName()); + } + } + } + } + } + } + return dataBinding; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptTargetWireBuilder.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptTargetWireBuilder.java new file mode 100644 index 0000000000..0c45aee35e --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/builder/JavaScriptTargetWireBuilder.java @@ -0,0 +1,40 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.builder; + +import java.lang.reflect.Method; + +import org.apache.tuscany.container.rhino.config.JavaScriptContextFactory; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.extension.ComponentTargetInvoker; +import org.apache.tuscany.core.extension.WireBuilderSupport; +import org.apache.tuscany.core.wire.TargetInvoker; +import org.osoa.sca.annotations.Scope; + +/** + * Responsible for bridging source- and target-side invocations chains when the target type is a JavaScript implementation + * + * @version $Rev$ $Date$ + */ +@Scope("MODULE") +public class JavaScriptTargetWireBuilder extends WireBuilderSupport { + + protected TargetInvoker createInvoker(QualifiedName targetName, Method operation, ScopeContext context, boolean downScope) { + return new ComponentTargetInvoker(targetName, operation, context); + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/config/JavaScriptContextFactory.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/config/JavaScriptContextFactory.java new file mode 100644 index 0000000000..28a0302a4f --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/config/JavaScriptContextFactory.java @@ -0,0 +1,114 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.config; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.container.rhino.context.JavaScriptComponentContext; +import org.apache.tuscany.container.rhino.rhino.RhinoScript; +import org.apache.tuscany.core.builder.ContextCreationException; +import org.apache.tuscany.core.builder.ContextFactory; +import org.apache.tuscany.core.builder.ContextResolver; +import org.apache.tuscany.core.context.AtomicContext; +import org.apache.tuscany.core.context.CompositeContext; +import org.apache.tuscany.core.wire.SourceWireFactory; +import org.apache.tuscany.core.wire.TargetWireFactory; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Creates instance contexts for JavaScript component types + * + * @version $Rev$ $Date$ + */ +public class JavaScriptContextFactory implements ContextFactory, ContextResolver { + + private Scope scope; + + private String name; + + private Map targetProxyFactories = new HashMap(); + + private List sourceProxyFactories = new ArrayList(); + + private Map services; + + private Map properties; + + private RhinoScript invoker; + + private CompositeContext parentContext; + + public JavaScriptContextFactory(String name, Scope scope, Map services, Map properties, RhinoScript invoker) { + this.name = name; + this.scope = scope; + this.services = services; + this.properties = properties; + this.invoker = invoker; + } + + public AtomicContext createContext() throws ContextCreationException { + return new JavaScriptComponentContext(name, services, properties, sourceProxyFactories, targetProxyFactories, invoker.copy()); + } + + public Scope getScope() { + return scope; + } + + public String getName() { + return name; + } + + public void addProperty(String propertyName, Object value) { + properties.put(propertyName, value); + } + + public void addTargetWireFactory(String serviceName, TargetWireFactory factory) { + targetProxyFactories.put(serviceName, factory); + } + + public TargetWireFactory getTargetWireFactory(String serviceName) { + return targetProxyFactories.get(serviceName); + } + + public Map getTargetWireFactories() { + return targetProxyFactories; + } + + public void addSourceWireFactory(String referenceName, SourceWireFactory factory) { + sourceProxyFactories.add(factory); + } + + public void addSourceWireFactories(String referenceName, Class referenceInterface, List factories, boolean multiplicity) { + sourceProxyFactories.addAll(factories); + } + + public List getSourceWireFactories() { + return sourceProxyFactories; + } + + public void prepare(CompositeContext parent) { + parentContext = parent; + } + + public CompositeContext getCurrentContext() { + return parentContext; + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/context/JavaScriptComponentContext.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/context/JavaScriptComponentContext.java new file mode 100644 index 0000000000..bfa4eeaffb --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/context/JavaScriptComponentContext.java @@ -0,0 +1,140 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.context; + +import org.apache.tuscany.container.rhino.rhino.RhinoScript; +import org.apache.tuscany.core.context.AtomicContext; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.context.event.InstanceCreated; +import org.apache.tuscany.core.context.impl.AbstractContext; +import org.apache.tuscany.core.wire.ProxyCreationException; +import org.apache.tuscany.core.wire.WireFactory; +import org.apache.tuscany.core.wire.SourceWireFactory; +import org.apache.tuscany.core.wire.TargetWireFactory; +import org.osoa.sca.ServiceRuntimeException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JavaScriptComponentContext extends AbstractContext implements AtomicContext { + + private Map services; + + private RhinoScript rhinoInvoker; + + private Map properties; + + private List sourceProxyFactories; + + private Map targetProxyFactories; + + private Object instance; + + public JavaScriptComponentContext(String name, Map services, Map properties, + List sourceProxyFactories, Map targetProxyFactories, RhinoScript invoker) { + super(name); + assert (services != null) : "No service interface mapping specified"; + assert (properties != null) : "No properties specified"; + this.services = services; + this.properties = properties; + this.rhinoInvoker = invoker; + this.sourceProxyFactories = sourceProxyFactories; + this.targetProxyFactories = targetProxyFactories; + } + + public Object getInstance(QualifiedName qName) throws TargetException { + return getInstance(qName, true); + } + + public void init() throws TargetException { + getInstance(null, false); + } + + public void destroy() throws TargetException { + + } + + private synchronized Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + String portName = qName.getPortName(); + WireFactory targetFactory; + if (portName != null) { + targetFactory = targetProxyFactories.get(portName); + } else { + //FIXME The port name is null here, either locateService needs more information (the expected interface) to + // select the correct port, or we need to return a factory that matches the whole set of services exposed by + // the component. + targetFactory = targetProxyFactories.values().iterator().next(); + } + if (targetFactory == null) { + TargetException e = new TargetException("Target service not found"); + e.setIdentifier(qName.getPortName()); + e.addContextName(getName()); + throw e; + } + try { + Object proxy = targetFactory.createProxy(); //createProxy(new Class[] { iface }); + if (notify) { + publish(new InstanceCreated(this)); + } + return proxy; + } catch (ProxyCreationException e) { + TargetException te = new TargetException("Error returning target", e); + e.setIdentifier(qName.getPortName()); + e.addContextName(getName()); + throw te; + } + } + + public Object getTargetInstance() throws TargetException { + rhinoInvoker.updateScriptScope(createServiceReferences()); // create references + rhinoInvoker.updateScriptScope(properties); // create prop values + return rhinoInvoker; + } + + /** + * Creates a map containing any ServiceReferences + */ + private Map createServiceReferences() { + try { + Map context = new HashMap(); + for (SourceWireFactory proxyFactory : sourceProxyFactories) { + context.put(proxyFactory.getConfiguration().getReferenceName(), proxyFactory.createProxy()); + } + return context; + } catch (ProxyCreationException e) { + throw new ServiceRuntimeException(e); + } + } + + public boolean isEagerInit() { + return false; + } + + public boolean isDestroyable() { + return false; + } + + public void start() throws CoreRuntimeException { + } + + public void stop() throws CoreRuntimeException { + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/loader/JavaScriptImplementationLoader.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/loader/JavaScriptImplementationLoader.java new file mode 100644 index 0000000000..e28776049c --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/loader/JavaScriptImplementationLoader.java @@ -0,0 +1,168 @@ +/** + * + * Copyright 2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.loader; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.common.resource.ResourceLoader; +import org.apache.tuscany.container.rhino.assembly.JavaScriptImplementation; +import org.apache.tuscany.core.config.ConfigurationLoadException; +import org.apache.tuscany.core.config.InvalidRootElementException; +import org.apache.tuscany.core.config.MissingResourceException; +import org.apache.tuscany.core.config.SidefileLoadException; +import org.apache.tuscany.core.loader.LoaderContext; +import org.apache.tuscany.core.loader.StAXElementLoader; +import org.apache.tuscany.core.loader.StAXLoaderRegistry; +import org.apache.tuscany.core.loader.assembly.AssemblyConstants; +import org.apache.tuscany.core.system.annotation.Autowire; +import org.apache.tuscany.model.assembly.ComponentType; +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +@Scope("MODULE") +public class JavaScriptImplementationLoader implements StAXElementLoader { + + public static final QName IMPLEMENTATION_JS = new QName("http://org.apache.tuscany/xmlns/js/0.9", "implementation.js"); + + protected StAXLoaderRegistry registry; + + private XMLInputFactory xmlFactory; + + public JavaScriptImplementationLoader() { + // todo make this a reference to a system service + xmlFactory = XMLInputFactory.newInstance(); + } + + @Autowire + public void setRegistry(StAXLoaderRegistry registry) { + this.registry = registry; + } + + @Init(eager = true) + public void start() { + registry.registerLoader(IMPLEMENTATION_JS, this); + } + + @Destroy + public void stop() { + registry.unregisterLoader(IMPLEMENTATION_JS, this); + } + + public JavaScriptImplementation load(XMLStreamReader reader, LoaderContext loaderContext) throws XMLStreamException, ConfigurationLoadException { + String scriptFile = reader.getAttributeValue(null, "scriptFile"); + String script = loadScript(scriptFile, loaderContext.getResourceLoader()); + ComponentType componentType = loadComponentType(scriptFile, loaderContext); + + JavaScriptImplementation jsImpl = new JavaScriptImplementation(); + jsImpl.setComponentType(componentType); + jsImpl.setScriptFile(scriptFile); + jsImpl.setScript(script); + jsImpl.setResourceLoader(loaderContext.getResourceLoader()); + jsImpl.setTypeHelper(registry.getContext().getTypeHelper()); + return jsImpl; + } + + protected String loadScript(String scriptFile, ResourceLoader resourceLoader) throws ConfigurationLoadException { + URL url = resourceLoader.getResource(scriptFile); + if (url == null) { + throw new ConfigurationLoadException(scriptFile); + } + InputStream inputStream; + try { + inputStream = url.openStream(); + } catch (IOException e) { + throw new ConfigurationLoadException(scriptFile, e); + } + try { + StringBuilder sb = new StringBuilder(1024); + int n; + while ((n = inputStream.read()) != -1) { + sb.append((char) n); + } + return sb.toString(); + } catch (IOException e) { + throw new ConfigurationLoadException(scriptFile, e); + } finally { + try { + inputStream.close(); + } catch (IOException e) { + // ignore + } + } + } + + protected ComponentType loadComponentType(String scriptFile, LoaderContext loaderContext) throws SidefileLoadException, MissingResourceException{ + String sidefile = scriptFile.substring(0, scriptFile.lastIndexOf('.')) + ".componentType"; + URL componentTypeFile = loaderContext.getResourceLoader().getResource(sidefile); + if (componentTypeFile == null) { + throw new MissingResourceException(sidefile); + } + + try { + XMLStreamReader reader; + InputStream is; + is = componentTypeFile.openStream(); + try { + reader = xmlFactory.createXMLStreamReader(is); + try { + reader.nextTag(); + if (!AssemblyConstants.COMPONENT_TYPE.equals(reader.getName())) { + InvalidRootElementException e = new InvalidRootElementException(AssemblyConstants.COMPONENT_TYPE, reader.getName()); + e.setResourceURI(componentTypeFile.toString()); + throw e; + } + return (ComponentType) registry.load(reader, loaderContext); + } finally { + try { + reader.close(); + } catch (XMLStreamException e) { + // ignore + } + } + } finally { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } catch (IOException e) { + SidefileLoadException sfe = new SidefileLoadException(e.getMessage()); + sfe.setResourceURI(componentTypeFile.toString()); + throw sfe; + } catch (XMLStreamException e) { + SidefileLoadException sfe = new SidefileLoadException(e.getMessage()); + sfe.setResourceURI(componentTypeFile.toString()); + throw sfe; + } catch (ConfigurationLoadException e) { + SidefileLoadException sfe = new SidefileLoadException(e.getMessage()); + sfe.setResourceURI(componentTypeFile.toString()); + throw sfe; + } + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/E4XDataBinding.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/E4XDataBinding.java new file mode 100644 index 0000000000..3969735b23 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/E4XDataBinding.java @@ -0,0 +1,108 @@ +/** + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.rhino; + +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.core.wire.InvocationRuntimeException; +import org.apache.tuscany.databinding.sdo.SDOXMLHelper; +import org.apache.xmlbeans.XmlObject; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; + +import commonj.sdo.helper.TypeHelper; + +/** + * DataBinding to convert between Java objects and JavaScript E4X XML objects. This uses SDO to do the conversion between XML and Java so WSDL/XSDs + * need to have be registered with the SDO runtime. + * + * TODO: suport non-wrapped WSDL + */ +public class E4XDataBinding { + + private ClassLoader classLoader; + + private TypeHelper typeHelper; + + private Map function2ElementMap; + + private static final boolean IS_WRAPPED = true; + + public E4XDataBinding(ClassLoader classLoader, TypeHelper typeHelper) { + this.classLoader = classLoader; + this.typeHelper = typeHelper; + this.function2ElementMap = new HashMap(); + } + + /** + * Convert E4X XML to Java objects + * + * @param e4xXML + * @return the array of Objects + */ + public Object[] toObjects(Scriptable e4xXML) { + byte[] xmlBytes = e4xXML.toString().getBytes(); + Object[] os = SDOXMLHelper.toObjects(classLoader, typeHelper, xmlBytes, IS_WRAPPED); + return os; + } + + /** + * Convert request Java objects to XML + * + * @param functionName + * @param os + * @param scope + * @return a JavaScript E4X XML object + */ + public Scriptable toE4X(String functionName, Object[] os, Scriptable scope) { + QName elementQN = function2ElementMap.get(functionName); + byte[] xmlBytes = SDOXMLHelper.toXMLBytes(classLoader, typeHelper, os, elementQN, IS_WRAPPED); + + XmlObject xmlObject; + try { + xmlObject = XmlObject.Factory.parse(new ByteArrayInputStream(xmlBytes)); + } catch (Exception e) { + throw new InvocationRuntimeException(e); + } + + Context cx = Context.enter(); + try { + + Object xml = cx.getWrapFactory().wrap(cx, scope, xmlObject, XmlObject.class); + Scriptable jsXML = cx.newObject(scope, "XML", new Object[] { xml }); + + return jsXML; + + } finally { + Context.exit(); + } + } + + /** + * Add the XML element name to use for an operation when converting from + * Java objects to XML. + * + * @param functionName + * @param elementQN + */ + public void addElementQName(String functionName, QName elementQN) { + function2ElementMap.put(functionName, elementQN); + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoE4XScript.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoE4XScript.java new file mode 100644 index 0000000000..5f42f6d164 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoE4XScript.java @@ -0,0 +1,76 @@ +/** + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.rhino; + +import java.util.Map; + +import org.mozilla.javascript.Function; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.xml.XMLObject; + +/** + * Invokes a JavaScript/E4X function with argument and return values that may be E4X XML objects. + */ +public class RhinoE4XScript extends RhinoScript { + + private E4XDataBinding dataBinding; + + public RhinoE4XScript(String scriptName, String script, Map context, ClassLoader cl, E4XDataBinding dataBinding) { + super(scriptName, script, context, cl); + this.dataBinding = dataBinding; + } + + protected RhinoE4XScript(String scriptName, String script, Scriptable scriptScope, E4XDataBinding dataBinding) { + super(scriptName, script, scriptScope); + this.dataBinding = dataBinding; + } + + /** + * Turn args to JS objects and convert any OMElement to E4X XML + */ + @Override + protected Object[] processArgs(String functionName, Object[] args, Scriptable scope) { + return new Object[] { dataBinding.toE4X(functionName, args, scope) }; + } + + /** + * Unwrap and convert response converting any E4X XML into Java objects + */ + @Override + protected Object processResponse(String functionName, Object response, Class responseClass) { + if (response instanceof XMLObject) { + Object[] os = dataBinding.toObjects((XMLObject) response); + if (os == null || os.length < 1) { + return null; + } else { + return os[0]; + } + } else { + return super.processResponse(functionName, response, responseClass); + } + } + + @Override + protected Function getFunction(Scriptable scope, String functionName) { + return super.getFunction(scope, "process"); + } + + @Override + public RhinoE4XScript copy() { + return new RhinoE4XScript(scriptName, script, scriptScope, dataBinding); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoScript.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoScript.java new file mode 100644 index 0000000000..5518159f69 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/rhino/RhinoScript.java @@ -0,0 +1,290 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.container.rhino.rhino; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.tuscany.core.extension.ExternalServiceInvoker; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.ContextFactory; +import org.mozilla.javascript.Function; +import org.mozilla.javascript.ImporterTopLevel; +import org.mozilla.javascript.Script; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.Wrapper; + +/** + * Represents, and is responsible for dispatching to, a JavaScript artifact in Rhino + */ +public class RhinoScript implements ExternalServiceInvoker { + + protected String scriptName; + + protected String script; + + protected Scriptable scriptScope; + + private Scriptable sharedScope; + + /* + * Enable dynamic scopes so a script can be used concurrently with a global shared scope and individual execution + * scopes. See http://www.mozilla.org/rhino/scopes.html TODO: need to review how ths fits in with Tuscany scopes + */ + private static class MyFactory extends ContextFactory { + protected boolean hasFeature(Context cx, int featureIndex) { + if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) { + return true; + } + return super.hasFeature(cx, featureIndex); + } + } + + static { + ContextFactory.initGlobal(new MyFactory()); + } + + /** + * Create a new RhinoInvoker. + * + * @param scriptName the name of the script. Can be anything, only used in messages to identify the script + * @param script the complete script + */ + public RhinoScript(String scriptName, String script) { + this(scriptName, script, (Map) null, null); + } + + /** + * Create a new RhinoInvoker. + * + * @param scriptName the name of the script. Can be anything, only used in messages to identify the script + * @param script the complete script + * @param context name-value pairs that are added in to the scope where the script is compiled. May be null. The + * value objects are made available to the script by using a variable with the name. + */ + public RhinoScript(String scriptName, String script, Map context, ClassLoader cl) { + this.scriptName = scriptName; + this.script = script; + initScriptScope(scriptName, script, context, cl); + initSharedScope(); + } + + /** + * Construct a RhinoInvoker from another RhinoInvoker object. This uses the original script scope so the script + * doesn't need to be recompiled. + */ + protected RhinoScript(String scriptName, String script, Scriptable scriptScope) { + this.scriptName = scriptName; + this.script = script; + this.scriptScope = scriptScope; + initSharedScope(); + } + + /** + * Invoke a script function + * + * @param functionName the name of the function to invoke. + * @param arg arguments to the function, may be a single object or an array of objects. + * @return the function return value. + */ + public Object invoke(String functionName, Object[] args) { + return invoke(functionName, args, null, null); + } + + /** + * Invoke a script function + * + * @param functionName the name of the function to invoke. + * @param arg arguments to the function, may be a single object or an array of objects. + * @param contexts a Map of name-value pairs which are added to the wire Scope to enable the script to access + * the values by using the variable in name. + * @return the function return value. + */ + public Object invoke(String functionName, Object[] args, Map contexts) { + return invoke(functionName, args, null, contexts); + } + + /** + * Invoke a script function + * + * @param functionName the name of the function to invoke. + * @param arg arguments to the function, may be a single object or an array of objects. + * @param responseClass the desired class of the response object. + * @param contexts a Map of name-value pairs which are added to the wire Scope to enable the script to access + * the values by using the variable in name. + * @return the function return value. + */ + public Object invoke(String functionName, Object[] args, Class responseClass, Map contexts) { + Context cx = Context.enter(); + try { + Function function = getFunction(scriptScope, functionName); + Scriptable invocationScope = getInvocationScope(cx, contexts); + Object[] jsArgs = processArgs(functionName, args, invocationScope); + Object jsResponse = function.call(cx, invocationScope, invocationScope, jsArgs); + Object response = processResponse(functionName, jsResponse, responseClass); + return response; + } finally { + Context.exit(); + } + } + + /** + * Turn args to JS objects and convert any OMElement to E4X XML + */ + protected Object[] processArgs(String functionName, Object[] arg, Scriptable scope) { + Object[] args; + if (arg == null) { + args = new Object[] { null }; + } else if (arg.getClass().isArray()) { + args = (Object[]) arg; + for (int i = 0; i < args.length; i++) { + args[i] = Context.toObject(args[i], scope); + } + } else { + args = new Object[] { Context.toObject(arg, scope) }; + } + return args; + } + + /** + * Unwrap and convert response + */ + protected Object processResponse(String functionName, Object response, Class responseClass) { + if (Context.getUndefinedValue().equals(response)) { + response = null; + } else if (response instanceof Wrapper) { + response = ((Wrapper) response).unwrap(); + } else { + if (responseClass != null) { + response = Context.jsToJava(response, responseClass); + } else { + response = Context.jsToJava(response, String.class); + } + } + return response; + } + + /** + * Create a Rhino scope and compile the script into it + */ + protected void initScriptScope(String fileName, String scriptCode, Map context, ClassLoader cl) { + Context cx = Context.enter(); + try { + + if (cl != null) { + cx.setApplicationClassLoader(cl); + } + this.scriptScope = new ImporterTopLevel( cx, true ); + Script compiledScript = cx.compileString(scriptCode, fileName, 1, null); + compiledScript.exec(cx, scriptScope); + addContexts(scriptScope, context); + + } finally { + Context.exit(); + } + } + + /** + * Initializes the shared scope + */ + protected void initSharedScope() { + Context cx = Context.enter(); + try { + + this.sharedScope = cx.newObject(scriptScope); + sharedScope.setPrototype(scriptScope); + sharedScope.setParentScope(null); + + } finally { + Context.exit(); + } + } + + /** + * Get a Rhino scope for the function wire. If the wire has no context objects then this will use the + * shared scope otherwise a new scope is created to hold the context objects. Any new variables the executing script + * might define will go in the sharedScope. This new scope is just to hold the wire specific context objects. + */ + protected Scriptable getInvocationScope(Context cx, Map contexts) { + + Scriptable scope; + if (contexts == null || contexts.size() == 0) { + scope = sharedScope; + } else { + scope = cx.newObject(sharedScope); + scope.setPrototype(sharedScope); + scope.setParentScope(null); + addContexts(scope, contexts); + } + + return scope; + } + + /** + * Add the context to the scope. This will make the objects available to a script by using the name it was added + * with. + */ + protected void addContexts(Scriptable scope, Map contexts) { + if (contexts != null) { + for (Iterator i = contexts.keySet().iterator(); i.hasNext();) { + String name = (String) i.next(); + Object value = contexts.get(name); + if (value != null) { + scope.put(name, scope, Context.toObject(value, scope)); + } + } + } + } + + /** + * Get the Rhino Function object for the named script function + */ + protected Function getFunction(Scriptable scope, String functionName) { + + Object handleObj = scope.get(functionName, scope); + + if (!(handleObj instanceof Function)) { + throw new RuntimeException("script function '" + functionName + "' is undefined or not a function in script " + + scriptName); + } + + return (Function) handleObj; + } + + /** + * Make a copy of this RhinoScript object. This shares the script scope to avoid the overhead of recompiling the + * script, and to allow any initialization done by the script to be shared. + */ + public RhinoScript copy() { + return new RhinoScript(scriptName, script, scriptScope); + } + + /** + * Update the scope where the script is complied with new context values + * + * @param properties + */ + public void updateScriptScope(Map context) { + Context.enter(); + try { + addContexts(scriptScope, context); + } finally { + Context.exit(); + } + } + +} \ No newline at end of file diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/ScriptEngine.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/ScriptEngine.java new file mode 100644 index 0000000000..e8e6605300 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/ScriptEngine.java @@ -0,0 +1,573 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tuscany.container.rhino.shell; + +import java.io.BufferedReader; +import java.io.CharArrayWriter; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.net.URL; +import java.net.URLClassLoader; + +import org.apache.tuscany.core.client.TuscanyRuntime; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Function; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; +import org.mozilla.javascript.WrappedException; +import org.osoa.sca.CurrentModuleContext; +import org.osoa.sca.ModuleContext; + +/** + * + * This class implements a Scripting Engine for the Tuscany runitme. This engine uses the Rhino javaScript Engine. + * + *

+ * The defulat script functions supported by this engine are the follwing: + *

    + *
  • echo
  • + *
  • version
  • + *
  • load
  • + *
  • help
  • + *
  • exit
  • + *
  • printStackTrace
  • + *
  • loadModule
  • + *
  • listComponents
  • + *
  • getComponent
  • + *
  • listServices
  • + *
  • getService
  • + *
+ * + * This class was based on ideas in the Rhino shell sample at http://lxr.mozilla.org/mozilla/source/js/rhino/examples/Shell.java + */ +public class ScriptEngine extends ScriptableObject implements Runnable { + + /** + * The context with which this script engine will be run + */ + private Context jsContext = null; + + /** + * Set of parameters passes to the script engine + */ + private String[] params = null; + + /** + * instance of Tuscany runtime + */ + private TuscanyRuntime tuscany; + + /** + * A reference to the old class loader + */ + private ClassLoader oldClassLoader = null; + + /** + * Flag to indicate, if the shoutdown has requested by the user + */ + private boolean shutdown; + + /** + * The current output stream + */ + private static PrintStream out = System.out; + + /** + * The current error output stream + */ + private PrintStream err = System.err; + + /** + * The current input stream + */ + private InputStream in = System.in; + + /** + * The prompt used + */ + private String prompt = "js> "; + + /** + * The last exception that occured, used for debugging + */ + private Throwable lastException = null; + + /** + * Names of the global functions particular to the shell. Note that these functions are not part of ECMA. + */ + public static final String[] SCRIPT_FUNCTIONS = { "echo", "version", "load", "help", "exit", "printStackTrace", "loadModule", "listComponents", + "getComponent", "listServices", "getService", }; + + /** + * get the class name + * + * @return "global" + */ + @Override + public String getClassName() { + return "global"; + } + + /** + * Construct a script engine + * + * @param command + * line arguments + */ + public ScriptEngine(String[] params) { + this.params = params; + } + + /** + * Run the script engine. Invoking this method will initialize the script engine, Tuscany Runtime and load any SCA modules if found in the + * classpath. + * + */ + public void run() { + // Associate a new Context with this thread + jsContext = Context.enter(); + try { + // initialize standard objects + jsContext.initStandardObjects(this); + // define supported script functions + this.defineFunctionProperties(SCRIPT_FUNCTIONS, ScriptEngine.class, ScriptableObject.DONTENUM); + + // init the tuscany runtime + // this.initTuscanyRuntime(); + // initialize the script engine + this.startScriptEngin(); + } finally { + if (tuscany != null) { + tuscany.stop(); + } + Thread.currentThread().setContextClassLoader(oldClassLoader); + Context.exit(); + } + } + + /** + * Print the help message. + * + * This method is defined as a script function. + */ + public void help() { + final String helpMsg = "Command Description \n" + "======= =========== \n" + + "help() Display this message. \n" + + "load(['f1.js', ...]) Load and execute javaScript source files named f1.js, etc. \n" + + "echo([expr ...]) Evaluate and print a variable or an expressions. \n" + "exit() Exit this shell. \n" + + "version([number]) Get or set the javaScript version. \n" + + "printStackTrace() Print the stacktrace of the last exception \n" + "loadModule(jar|war) Not yet implemented. \n" + + "listComponents() Not yet implemented. \n" + + "getComponent('name') Get an instance of the component with the given name. \n" + + "listServices() Not yet implemented. \n" + "getService('name') Not yet implemented. \n"; + + out.println(); + out.println(helpMsg); + } + + /** + * Load a given module with the tuscany runtime + * + * This method is defined as a script function. + * + * @param moduleName + * absolute path of the module + */ + public void loadModule(final String moduleName) { + // TODO complete this method + if (tuscany != null) { + tuscany.stop(); + } + + try { + File file = new File(moduleName); + URL[] urls = new URL[] { file.toURL(), }; + final ClassLoader newCL = new URLClassLoader(urls); + Thread.currentThread().setContextClassLoader(newCL); + + tuscany = new TuscanyRuntime(moduleName, null); + tuscany.start(); + + } catch (Exception e) { + e.printStackTrace(); + err.println(e.getMessage()); + lastException = e; + } + } + + /** + * List the components available within the current module + * + * This method is defined as a script function. + */ + public void listComponents() { + // TODO complete this method + } + + /** + * Get the component available within the current module with a given name + * + * This method is defined as a script function. + * + * @param name + * name of the component + * @return service component object represented by the given name + */ + public Object getComponent(String name) { + ModuleContext tuscanyContext = CurrentModuleContext.getContext(); + Object component = tuscanyContext.locateService(name); + + return component; + } + + /** + * List the external services available within the current module + * + * This method is defined as a script function. + */ + public void listServices() { + // TODO complete this method + } + + /** + * Get an external service defined within the current module with a given name + * + * This method is defined as a script function. + * + * @param name + * name of the service + * @return service object represented by the given name + */ + public Object getService(String name) { + // get a service proxy + ModuleContext tuscanyContext = CurrentModuleContext.getContext(); + Object service = tuscanyContext.locateService(name); + out.println("service obj = " + service); + + return service; + } + + /** + * Echo a variable or a message. + * + * This method is defined as a script function. + * + * @param jsContext + * @param thisObj + * @param args + * @param function + */ + public static void echo(Context jsContext, Scriptable thisObj, Object[] args, Function function) { + if (args.length > 0) { + out.println(args[0]); + for (int i = 1; i < args.length; i++) { + out.print(" " + Context.toString(args[i])); + } + } + out.println(); + } + + /** + * print the stacktrace of the last exception + * + * This method is defined as a script function. + */ + public void printStackTrace() { + if (lastException == null) { + out.println("No stacktrace available"); + } else { + err.println(getStackTrace(lastException)); + } + } + + /** + * Exit the shell when it is in the interactive mode. + * + * This method is defined as a script function. + */ + public void exit() { + shutdown = true; + } + + /** + * Get and set the language version. + * + * This method is defined as a JavaScript function. + * + * @param jsContext + * @param thisObj + * @param args + * @param function + */ + public static double version(Context jsContext, Scriptable thisObj, Object[] args, Function function) { + if (args.length > 0) { + int i = (int) Context.toNumber(args[0]); + jsContext.setLanguageVersion(i); + } + return (double) jsContext.getLanguageVersion(); + } + + /** + * Load and execute a set of JavaScript source files. + * + * This method is defined as a JavaScript function. + * + * @param jsContext + * @param thisObj + * @param args + * @param function + */ + public static void load(Context jsContext, Scriptable thisObj, Object[] args, Function function) { + ScriptEngine engine = (ScriptEngine) getTopLevelScope(thisObj); + for (int i = 0; i < args.length; i++) { + engine.processFile(Context.toString(args[i])); + } + } + + /** + * Get the current output stream + * + * @return current output stream + */ + public PrintStream getOut() { + return out; + } + + /** + * Set the current output stream + * + * @param out + * the new output stream + */ + public void setOut(PrintStream out) { + ScriptEngine.out = out; + } + + /** + * Get the current error output stream + * + * @return Returns the current error output stream. + */ + public PrintStream getErr() { + return err; + } + + /** + * Set the current error output stream + * + * @param err + * The new error output stream to set. + */ + public void setErr(PrintStream err) { + this.err = err; + } + + /** + * Get the current input stream + * + * @return Returns the current input stream. + */ + public InputStream getIn() { + return in; + } + + /** + * Set the current input stream + * + * @param in + * The new input stream to set. + */ + public void setIn(InputStream in) { + this.in = in; + } + + /** + * initialize the Tuscany runtime + * + */ + protected void initTuscanyRuntime() { + + // Required to allow the SDO runtime to use the correct classloader + oldClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + + // Obtain and start the Tuscany runtime + try { + tuscany = new TuscanyRuntime("TuscanyClient", null); + tuscany.start(); + + // this will get the module name; either specified by user or from the classpath + String moduleName = getCurrentModuleName(); + // TODO how do we get all the components, services exposed by this module ? + + } catch (Exception ce) { + ce.printStackTrace(); + err.println("Failed to start Tuscany runtime: " + ce.getMessage()); + // ce.printStackTrace(err); + lastException = ce; + } + } + + /** + * start the script engine + * + */ + protected void startScriptEngin() { + + out.println("Tuscany SCA Shell 0.1, type help() for a list of supported functions."); + + // set up "arguments" in the global scope + if (params.length > 1) { + int length = params.length - 1; + Object obj[] = new Object[length]; + System.arraycopy(params, 1, obj, 0, length); + + Scriptable argsObj = jsContext.newArray(this, obj); + this.defineProperty("arguments", argsObj, ScriptableObject.DONTENUM); + } + + if (params.length == 0) { + // no file name specified, go to interactive mode + this.startInteractiveMode(); + } else { + // TODO this could be a jar file or a script file + // process the specified file + this.processFile(params[0]); + } + System.gc(); + } + + /** + * Evaluate JavaScript source in the interactive mode. + * + */ + private void startInteractiveMode() { + // see if org.mozilla.javascript.tools.shell.Main.processSource() can handle this + // Main.setErr(this.getErr()); + // Main.setOut(this.getOut()); + // Main.setIn(this.getIn()); + // Main.processSource(jsContext, filename); + + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + int currentLine = 1; + boolean done = false; + while (!shutdown && !done) { + out.print(prompt); + out.flush(); + int lineToCompile = currentLine; + try { + StringBuffer source = new StringBuffer(); + // read the next line entered by user + boolean compilable = false; + while (!compilable) { + String nextLine = reader.readLine(); + if (nextLine != null) { + currentLine += 1; + source.append(nextLine).append("\n"); + compilable = jsContext.stringIsCompilableUnit(source.toString()); + } else { + // TODO check if this can handle Ctrl+C + System.out.println("=== Ctrl+C pressed =="); + // break both the loops + done = true; + compilable = true; + } + } + Object result = jsContext.evaluateString(this, source.toString(), "", lineToCompile, null); + if (result != Context.getUndefinedValue()) { + out.println(Context.toString(result)); + } + } catch (Exception e) { + if (e instanceof WrappedException) { + WrappedException we = (WrappedException) e; + err.println(we.getWrappedException().getMessage()); + } + err.println(e.getMessage()); + // e.printStackTrace(err); + lastException = e; + } + } + out.println(); + } + + /** + * Read the contents from a script file and execute it. + * + * @param filename + * the name of the file to compile + */ + private void processFile(String fileName) { + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(fileName)); + jsContext.evaluateReader(this, reader, fileName, 1, null); + } catch (Exception e) { + if (e instanceof WrappedException) { + WrappedException we = (WrappedException) e; + err.println(we.getWrappedException().getMessage()); + } + err.println(e.getLocalizedMessage()); + // e.printStackTrace(err); + lastException = e; + } finally { + try { + reader.close(); + } catch (IOException ioe) { + err.println(ioe.getLocalizedMessage()); + // ioe.printStackTrace(err); + lastException = ioe; + } + } + } + + /** + * Find the SCA module name. If the user have specified one, use that, otherwise, if there is a module definition in the path, pick it up. + * + * @return name of the module + */ + private String getCurrentModuleName() { + String moduleName = ""; + + // TODO parse the arguments to see if there is an SCA module name + return moduleName; + } + + /** + * Get the stacktrace for a give exception + * + * @param t + * Throwable from which the stacktrace need to be obtained + * @return char array containing the stack trace + */ + private char[] getStackTrace(Throwable t) { + CharArrayWriter charWriter = new CharArrayWriter(2048); + PrintWriter writer = new PrintWriter(charWriter); + t.printStackTrace(writer); + + return charWriter.toCharArray(); + } + + public static void main(String args[]) { + new ScriptEngine(args).run(); + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/TuscanyShell.java b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/TuscanyShell.java new file mode 100644 index 0000000000..c26dd213b1 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/containers/container.rhino/src/main/java/org/apache/tuscany/container/rhino/shell/TuscanyShell.java @@ -0,0 +1,42 @@ +/** + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tuscany.container.rhino.shell; + +/** + * This class provides a scripting shell that can be used as a Tuscany client. + * This shell extends from the Rhino JavaScript Engine's shell and + * provides capablities for working with the Tuscany Runtime. + * + *

+ * This shell initializt the Tuscany Engine, using the input parameters that point + * to an SCA jar or war or a directory with an sca.module file. The Shell will + * load that module and then all the components and external services in the + * sca.module become available in the Shell, so that you can invoke them dynamically. + * + */ +public class TuscanyShell { + + /** + * Main entry point into the shell. This method invokes the ScriptEngine. + * + */ + public static void main(String args[]) { + ScriptEngine engine = new ScriptEngine(args); + new Thread(engine).start(); + } + +} -- cgit v1.2.3