summaryrefslogtreecommitdiffstats
path: root/sandbox/ant/container.rhino/src/main/java/org/apache/tuscany/container/rhino/RhinoScriptInstanceFactory.java
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sandbox/ant/container.rhino/src/main/java/org/apache/tuscany/container/rhino/RhinoScriptInstanceFactory.java145
1 files changed, 145 insertions, 0 deletions
diff --git a/sandbox/ant/container.rhino/src/main/java/org/apache/tuscany/container/rhino/RhinoScriptInstanceFactory.java b/sandbox/ant/container.rhino/src/main/java/org/apache/tuscany/container/rhino/RhinoScriptInstanceFactory.java
new file mode 100644
index 0000000000..ea55669696
--- /dev/null
+++ b/sandbox/ant/container.rhino/src/main/java/org/apache/tuscany/container/rhino/RhinoScriptInstanceFactory.java
@@ -0,0 +1,145 @@
+/*
+ * 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.container.rhino;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.container.easy.EasyInstanceFactory;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+import org.mozilla.javascript.ImporterTopLevel;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * A RhinoScript represents a compiled JavaScript script
+ */
+public class RhinoScriptInstanceFactory extends EasyInstanceFactory<RhinoScriptInstance> {
+
+ protected String scriptSource;
+
+ protected Scriptable scriptScope;
+
+ protected Map<String, Class> responseClasses;
+
+ private String className;
+
+ /*
+ * 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
+ */
+ 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());
+ }
+
+ public RhinoScriptInstanceFactory(String resourceName, String className, String scriptSource, ClassLoader classLoader) {
+ super(resourceName, classLoader);
+ this.className = className;
+ this.scriptSource = scriptSource;
+ this.responseClasses = new HashMap<String, Class>();
+ initScriptScope(resourceName, scriptSource, null, classLoader);
+ }
+
+ @Override
+ public RhinoScriptInstance createInstance(List<Class> services, Map<String, Object> context) {
+ // TODO services should really be on the constructor of this class, not on this method
+ // and the responseClasses done in the constructor/init
+ Scriptable instanceScope = createInstanceScope(context);
+ RhinoScriptInstance rsi = new RhinoScriptInstance(scriptScope, instanceScope, context, getResponseClasses(services));
+ return rsi;
+ }
+
+ /**
+ * Initialize the Rhino Scope for this script instance
+ */
+ public Scriptable createInstanceScope(Map<String, Object> context) {
+ Context cx = Context.enter();
+ try {
+
+ Scriptable instanceScope = cx.newObject(scriptScope);
+ instanceScope.setPrototype(scriptScope);
+ instanceScope.setParentScope(null);
+
+ addContexts(instanceScope, context);
+
+ return instanceScope;
+
+ } finally {
+ Context.exit();
+ }
+ }
+
+ /**
+ * Create a Rhino scope and compile the script into it
+ */
+ public void initScriptScope(String fileName, String scriptCode, Map context, ClassLoader cl) {
+ Context cx = Context.enter();
+ try {
+ if (cl != null) {
+ // TODO: broken with the way the tuscany launcher now uses class loaders
+ // 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();
+ }
+ }
+
+ /**
+ * 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));
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the Java type of a response value. JavaScript is dynamically typed so Rhino cannot always work out what the intended Java type of a
+ * response should be, for example should the statement "return 42" be a Java int, or Integer or Double etc. When Rhino can't determine the type
+ * it will default to returning a String, using this method enables overriding the Rhino default to use a specific Java type.
+ */
+ public void setResponseClass(String functionName, Class responseClasses) {
+ this.responseClasses.put(functionName, responseClasses);
+ }
+
+}