Package org.apache.tuscany.container.javascript.rhino

Source Code of org.apache.tuscany.container.javascript.rhino.RhinoScript$MyFactory

/*
* 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.javascript.rhino;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

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 RhinoScript {

    protected String scriptName;

    protected String script;

    protected Scriptable scriptScope;

    protected Map<String, Class> responseClasses;
   
    protected ClassLoader classLoader;

    /*
     * 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());
    }

    /**
     * Create a new RhinoScript.
     *
     * @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.
     * @param classLoader
     *            the ClassLoader Rhino should use to locate any user Java classes used in the script
     */
    public RhinoScript(String scriptName, String script, Map context, ClassLoader classLoader) {
        this.scriptName = scriptName;
        this.script = script;
        this.responseClasses = new HashMap<String, Class>();
        this.classLoader = classLoader;
        initScriptScope(scriptName, script, context, classLoader);
    }

    /**
     * Create a new invokeable instance of the script
     *
     * @return a RhinoScriptInstance
     */
    public RhinoScriptInstance createRhinoScriptInstance() {
        return createRhinoScriptInstance(null);
    }

    /**
     * Create a new invokeable instance of the script
     *
     * @param context
     *            objects to add to scope of the script instance
     * @return a RhinoScriptInstance
     */
    public RhinoScriptInstance createRhinoScriptInstance(Map<String, Object> context) {
        Scriptable instanceScope = createInstanceScope(context);
        RhinoScriptInstance rsi = new RhinoScriptInstance(scriptScope, instanceScope, context, responseClasses);
        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));
                }
            }
        }
    }

    public String getScript() {
        return script;
    }

    public String getScriptName() {
        return scriptName;
    }

    public Scriptable getScriptScope() {
        return scriptScope;
    }

    public Map<String, Class> getResponseClasses() {
        return responseClasses;
    }

    public ClassLoader getClassLoader() {
        return classLoader;
    }

    /**
     * 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);
    }
   
    public RhinoSCAConfig getSCAConfig() {
        return new RhinoSCAConfig(getScriptScope());
    }

    public void setScript(String script) {
        this.script = script;
    }

}
TOP

Related Classes of org.apache.tuscany.container.javascript.rhino.RhinoScript$MyFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.