Package org.apache.cocoon.components.flow.javascript.fom

Source Code of org.apache.cocoon.components.flow.javascript.fom.AO_FOM_JavaScriptInterpreter$ScriptSourceEntry

/*
* Copyright 1999-2004 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.cocoon.components.flow.javascript.fom;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.components.flow.AbstractInterpreter;
import org.apache.cocoon.components.flow.Interpreter;
import org.apache.cocoon.components.flow.InvalidContinuationException;
import org.apache.cocoon.components.flow.WebContinuation;
import org.apache.cocoon.components.flow.javascript.JSErrorReporter;
import org.apache.cocoon.components.flow.javascript.ScriptablePointerFactory;
import org.apache.cocoon.components.flow.javascript.ScriptablePropertyHandler;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.commons.jxpath.JXPathIntrospector;
import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Wrapper;
import org.mozilla.javascript.continuations.Continuation;
import org.mozilla.javascript.tools.ToolErrorReporter;
import org.mozilla.javascript.tools.shell.Global;

/**
* <p>Interface with the JavaScript interpreter.</p>
* <p>This version of the JavaScript interpreter provides enhanced
*    functionality and supports interception.</p>
*
* <p>Changes:
*   <ul>
*     <li>Use of the AO_FOM_Cocoon object encapsulating the Cocoon object.
*         All references to the FOM_Cocoon object had to be changed.
*     </li>
*     <li>Additional configurations</li>
*     <li>adding the <code>JavaScriptAspectWeaver</code> to the SourceEntry
*         object if interceptions are enabled</li>
*    </ul>
* </p>
*
* @author <a href="mailto:ovidiu@apache.org">Ovidiu Predescu</a>
* @author <a href="mailto:crafterm@apache.org">Marcus Crafter</a>
* @author <a href="mailto:coliver@apache.org">Christopher Oliver</a> 
* @author <a href="mailto:reinhard@apache.org">Reinhard P�tz</a>
* @since 2.1
* @version CVS $Id: AO_FOM_JavaScriptInterpreter.java,v 1.9 2004/03/05 10:07:25 bdelacretaz Exp $
*/
public class AO_FOM_JavaScriptInterpreter extends AbstractInterpreter
    implements Serviceable, Configurable, Initializable
{

    private SourceResolver sourceResolver;

    /**
     * LAST_EXEC_TIME
     * A long value is stored under this key in each top level JavaScript
     * thread scope object. When you enter a context any scripts whose
     * modification time is later than this value will be recompiled and reexecuted,
     * and this value will be updated to the current time.
     */
    private final static String LAST_EXEC_TIME = "__PRIVATE_LAST_EXEC_TIME__";

    /**
     * Key for storing a JavaScript global scope object in the Cocoon session
     */
    public static final String USER_GLOBAL_SCOPE = "FOM JavaScript GLOBAL SCOPE";

    // This is the only optimization level that supports continuations
    // in the Christoper Oliver's Rhino JavaScript implementation
    static int OPTIMIZATION_LEVEL = -2;

    // the postfix of the resulting file streamed into the same directory as
    // the basescript
    // (RPO) added/changed by interception layer       
    public static final String INTERCEPTION_POSTFIX = "_intercepted.js";
    // end
        
    /**
     * When was the last time we checked for script modifications. Used
     * only if {@link #reloadScripts} is true.
     */
    protected long lastTimeCheck = 0;

    // (RPO) added/changed by interception layer     
    /**
     * Are interceptions enabled?
     */
    private boolean isInterceptionEnabled;
    // end

    /**
     * Shared global scope for scripts and other immutable objects
     */
    Global scope;


    /**
     * List of <code>String</code> objects that represent files to be
     * read in by the JavaScript interpreter.
     */
    List topLevelScripts = new ArrayList();

    class ScriptSourceEntry {
        final private Source source;
        private Script script;
        private long compileTime;

        public ScriptSourceEntry(Source source) {
            this.source = source;
        }

        public ScriptSourceEntry(Source source, Script script, long t) {
            this.source = source;
            this.script = script;
            this.compileTime = t;
        }

        public Source getSource() {
            return source;
        }
        // (RPO) added/changed by interception layer   
        private JavaScriptAspectWeaver aspectWeaver = null;

        public void setAspectWeaver( JavaScriptAspectWeaver aspectWeaver ) {
            this.aspectWeaver = aspectWeaver;
        }

        public Script getScript(Context context, Scriptable scope,
                                             boolean refresh)
            throws Exception {
            if (refresh) {
                source.refresh();
            }
            if (script == null || compileTime < source.getLastModified()) {          
                script = compileScript(context, scope, source, aspectWeaver);                   
                compileTime = source.getLastModified();
            }
            return script;
        }
        //  -- end       
    }
   
    /**
     * Mapping of String objects (source uri's) to ScriptSourceEntry's
     *
     */
    Map compiledScripts = new HashMap();
    JSErrorReporter errorReporter;
   
    boolean enableDebugger = false;

    /**
     * JavaScript debugger: there's only one of these: it can debug multiple
     * threads executing JS code.
     */
    static org.mozilla.javascript.tools.debugger.Main debugger;

    static synchronized org.mozilla.javascript.tools.debugger.Main getDebugger() {
        if (debugger == null) {
            final org.mozilla.javascript.tools.debugger.Main db
                = new org.mozilla.javascript.tools.debugger.Main("Cocoon Flow Debugger");
            db.pack();
            java.awt.Dimension size =
                java.awt.Toolkit.getDefaultToolkit().getScreenSize();
            size.width *= 0.75;
            size.height *= 0.75;
            db.setSize(size);
            db.setExitAction(new Runnable() {
                    public void run() {
                        db.setVisible(false);
                    }
                });
            db.setOptimizationLevel(OPTIMIZATION_LEVEL);
            db.setVisible(true);
            debugger = db;
            Context.addContextListener(debugger);
        }
        return debugger;
    }

    // (RPO) added by interception layer      
    Configuration stopExecutionFunctionsConf = null;
    boolean serializeResultScript = false;
    // --end
   
    public void service(ServiceManager manager) throws ServiceException {
        super.service(manager);
        this.sourceResolver = (SourceResolver)manager.lookup(SourceResolver.ROLE);
    }

    public void configure(Configuration config)
        throws ConfigurationException {
           
        super.configure(config);

        String loadOnStartup
            = config.getChild("load-on-startup", true).getValue(null);
        if (loadOnStartup != null) {
            register(loadOnStartup);
        }

        String debugger
            = config.getChild("debugger").getValue(null);
        if ("enabled".equalsIgnoreCase(debugger)) {
            enableDebugger = true;
        }
       
        // (RPO) added by interception layer   
        isInterceptionEnabled =
            config.getChild( "enable-interception" ).getValueAsBoolean( true );
        stopExecutionFunctionsConf =
            config.getChild( "cont-creating-functions" );
        serializeResultScript =
           config.getChild( "serialize-result-script" ).getValueAsBoolean( false );
        // --end
    }

    public void initialize()
        throws Exception
    {
        if (enableDebugger) {
            if (getLogger().isDebugEnabled()) {
                getLogger().debug("Flow debugger enabled, creating");
            }
            getDebugger().doBreak();
        }
        Context context = Context.enter();
        context.setOptimizationLevel(OPTIMIZATION_LEVEL);
        context.setCompileFunctionsWithDynamicScope(true);
        context.setGeneratingDebug(true);
        // add support for Rhino objects to JXPath
        JXPathIntrospector.registerDynamicClass(org.mozilla.javascript.Scriptable.class,
                                                ScriptablePropertyHandler.class);
        JXPathContextReferenceImpl.addNodePointerFactory(new ScriptablePointerFactory());

        try {
            scope = new Global(context);
            // Access to Cocoon internal objects
            AO_FOM_Cocoon.init(scope);
            errorReporter = new JSErrorReporter(getLogger());
        }
        catch (Exception e) {
            Context.exit();
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * Returns the JavaScript scope, a Scriptable object, from the user
     * session instance. Each URI prefix, as returned by the {@link
     * org.apache.cocoon.environment.Environment#getURIPrefix} method,
     * can have a scope associated with it.
     *
     * @param environment an <code>Environment</code> value
     * @return a <code>Scriptable</code> value
     */
    private Scriptable getSessionScope()
        throws Exception {
        Request request = ContextHelper.getRequest(avalonContext);
        Scriptable scope = null;
        Session session = request.getSession(false);
        if (session != null) {
            HashMap userScopes = (HashMap)session.getAttribute(USER_GLOBAL_SCOPE);
            if (userScopes != null) {
                // Get context prefix
                Source src = this.sourceResolver.resolveURI(".");
                String uriPrefix = src.getURI();
                this.sourceResolver.release(src);
                scope = (Scriptable)userScopes.get(uriPrefix);
            }
        }
        if (scope == null) {
            scope = createThreadScope();
        }
        return scope;
    }

    void updateSession(Scriptable scope) throws Exception {
        ThreadScope thrScope = (ThreadScope)scope;
        if (thrScope.useSession) {
            setSessionScope(scope);
        }
    }

    /**
     * Associates a JavaScript scope, a Scriptable object, with the URI
     * prefix of the current sitemap, as returned by the {@link
     * org.apache.cocoon.environment.Environment#getURIPrefix} method.
     *
     * @param environment an <code>Environment</code> value
     * @param scope a <code>Scriptable</code> value
     */
    private Scriptable setSessionScope(Scriptable scope)
        throws Exception {
        Request request = ContextHelper.getRequest(this.avalonContext);
        Session session = request.getSession(true);

        HashMap userScopes = (HashMap)session.getAttribute(USER_GLOBAL_SCOPE);
        if (userScopes == null) {
            userScopes = new HashMap();
            session.setAttribute(USER_GLOBAL_SCOPE, userScopes);
        }
        // Get context prefix
        Source src = this.sourceResolver.resolveURI(".");
        String uriPrefix = src.getURI();
        this.sourceResolver.release(src);
        userScopes.put(uriPrefix, scope);
        return scope;
    }

    public static class ThreadScope extends ScriptableObject {

        /* true if this scope has assigned any global vars */
        boolean useSession = false;

        public ThreadScope() {
        }

        public String getClassName() {
            return "ThreadScope";
        }
       
        public void put(String name, Scriptable start,
                        Object value) {
            useSession = true;
            super.put(name, start, value);
        }
       
        public void put(int index, Scriptable start,
                        Object value) {
            useSession = true;
            super.put(index, start, value);
        }
       
        void reset() {
            useSession = false;
        }
    }

    private Scriptable createThreadScope()
        throws Exception {
        org.mozilla.javascript.Context context =
            org.mozilla.javascript.Context.getCurrentContext();

        ThreadScope thrScope = new ThreadScope();

        thrScope.setPrototype(scope);
        // We want 'thrScope' to be a new top-level scope, so set its
        // parent scope to null. This means that any variables created
        // by assignments will be properties of "thrScope".
        thrScope.setParentScope(null);
       
        // Put in the thread scope the Cocoon object, which gives access
        // to the interpreter object, and some Cocoon objects. See
        // FOM_Cocoon for more details.
        Object args[] = {};
        AO_FOM_Cocoon cocoon = (AO_FOM_Cocoon)
            context.newObject(thrScope, "AO_FOM_Cocoon", args);
        cocoon.setParentScope(thrScope);
        thrScope.put("cocoon", thrScope, cocoon);
        ((ScriptableObject)thrScope).defineProperty(LAST_EXEC_TIME,
                                                    new Long(0),
                                                    ScriptableObject.DONTENUM |
                                                    ScriptableObject.PERMANENT);
       
        thrScope.reset();
        return thrScope;
    }

    /**
     * Returns a new Scriptable object to be used as the global scope
     * when running the JavaScript scripts in the context of a request.
     *
     * <p>If you want to maintain the state of global variables across
     * multiple invocations of <code>&lt;map:call
     * function="..."&gt;</code>, you need to instanciate the session
     * object which is a property of the cocoon object
     * <code>var session = cocoon.session</code>. This will place the
     * newly create Scriptable object in the user's session, where it
     * will be retrieved from at the next invocation of {@link #callFunction}.</p>
     *
     * @param environment an <code>Environment</code> value
     * @exception Exception if an error occurs
     */
    private void setupContext(Redirector redirector,
                              org.mozilla.javascript.Context context,
                              Scriptable thrScope)
        throws Exception {
        // Try to retrieve the scope object from the session instance. If
        // no scope is found, we create a new one, but don't place it in
        // the session.
        //
        // When a user script "creates" a session using
        // cocoon.createSession() in JavaScript, the thrScope is placed in
        // the session object, where it's later retrieved from here. This
        // behaviour allows multiple JavaScript functions to share the
        // same global scope.

        AO_FOM_Cocoon cocoon = (AO_FOM_Cocoon)thrScope.get("cocoon", thrScope);
        long lastExecTime = ((Long)thrScope.get(LAST_EXEC_TIME,
                                                thrScope)).longValue();
        // We need to setup the FOM_Cocoon object according to the current
        // request. Everything else remains the same.
        cocoon.setup( this, redirector, avalonContext, manager, getLogger());
       
        // Check if we need to compile and/or execute scripts
        synchronized (compiledScripts) {
            List execList = new ArrayList();
            boolean needsRefresh = false;
            if (reloadScripts) {
                long now = System.currentTimeMillis();
                if (now >= lastTimeCheck + checkTime) {
                    needsRefresh = true;
                }
                lastTimeCheck = now;
            }
            // If we've never executed scripts in this scope or
            // if reload-scripts is true and the check interval has expired
            // or if new scripts have been specified in the sitemap,
            // then create a list of scripts to compile/execute
            if (lastExecTime == 0 || needsRefresh || needResolve.size() > 0) {
                topLevelScripts.addAll(needResolve);
                if (lastExecTime != 0 && !needsRefresh) {
                    execList.addAll(needResolve);
                } else {
                    execList.addAll(topLevelScripts);
                }
                needResolve.clear();
            }
            // Compile all the scripts first. That way you can set breakpoints
            // in the debugger before they execute.
            for (int i = 0, size = execList.size(); i < size; i++) {
                String sourceURI = (String)execList.get(i);
                ScriptSourceEntry entry =
                    (ScriptSourceEntry)compiledScripts.get(sourceURI);
                if (entry == null) {
                    Source src = this.sourceResolver.resolveURI(sourceURI);
                    entry = new ScriptSourceEntry(src);
                    compiledScripts.put(sourceURI, entry);
                }
                // (RPO) added/changed by interception layer           
                // add interception support
                if( isInterceptionEnabled ) {
                    JavaScriptAspectWeaver aspectWeaver = new JavaScriptAspectWeaver();
                    aspectWeaver.enableLogging( this.getLogger() );
                    aspectWeaver.service(this.manager);
                    aspectWeaver.setSerializeResultScriptParam( this.serializeResultScript );
                    aspectWeaver.setStopExecutionFunctionsConf( this.stopExecutionFunctionsConf );
                    entry.setAspectWeaver( aspectWeaver );
                }       
                // --end          
                // Compile the script if necessary
                entry.getScript(context, this.scope, needsRefresh);
            }
            // Execute the scripts if necessary
            for (int i = 0, size = execList.size(); i < size; i++) {
                String sourceURI = (String)execList.get(i);
                ScriptSourceEntry entry =
                    (ScriptSourceEntry)compiledScripts.get(sourceURI);
                long lastMod = entry.getSource().getLastModified();
                Script script = entry.getScript(context, this.scope, false);
                if (lastExecTime == 0 || lastMod > lastExecTime) {
                    script.exec(context, thrScope);
                    thrScope.put(LAST_EXEC_TIME, thrScope,
                                 new Long(System.currentTimeMillis()));
                    ((ThreadScope)thrScope).reset();
                }
            }
        }
    }

    /**
     * Compile filename as JavaScript code
     *
     * @param cx Rhino context
     * @param fileName resource uri
     * @return compiled script
     */
    Script compileScript(Context cx,
                         String fileName) throws Exception {
        Source src = sourceResolver.resolveURI(fileName);
        if (src == null) {
            throw new ResourceNotFoundException(fileName + ": not found");
        }
        synchronized (compiledScripts) {
            ScriptSourceEntry entry =
                (ScriptSourceEntry)compiledScripts.get(src.getURI());
            Script compiledScript = null;
            if (entry == null) {
                compiledScripts.put(src.getURI(),
                                    entry = new ScriptSourceEntry(src));
            }
            compiledScript = entry.getScript(cx, this.scope, false);
            return compiledScript;
        }
    }
    // (RPO) added/changed by interception layer  
    protected Script compileScript( Context cx, Scriptable scope,
                                  Source src, JavaScriptAspectWeaver aspectWeaver)
        throws Exception {
        Script compiledScript = null;

        boolean areScriptsApplied = false;

        // test base script if scripts are applied to
        if( aspectWeaver != null ) {
            aspectWeaver.setBaseScript( src );     
            areScriptsApplied = aspectWeaver.areScriptsApplied();     
        }

        // no scripts applied or compileScript was called with null AspectWeaver
        if( aspectWeaver == null || ! areScriptsApplied ) {
            InputStream is = src.getInputStream();
            if (is == null) {
                throw new ResourceNotFoundException(src.getURI() + ": not found");
            }
            Reader reader = new BufferedReader(new InputStreamReader(is));
            compiledScript = cx.compileReader(scope, reader, src.getURI(), 1, null );
        }
        // script applied
        else {
            this.getLogger().info( "Adding interceptions to script " + src.getURI() );
            Reader reader = new BufferedReader(
                                    aspectWeaver.getInterceptedScriptAsReader() );
            compiledScript = cx.compileReader(scope, reader, src.getURI() + INTERCEPTION_POSTFIX, 1, null );           
        }
        return compiledScript;
    }
    // -- end
   
    /**
     * Calls a JavaScript function, passing <code>params</code> as its
     * arguments. In addition to this, it makes available the parameters
     * through the <code>cocoon.parameters</code> JavaScript array
     * (indexed by the parameter names).
     *
     * @param funName a <code>String</code> value
     * @param params a <code>List</code> value
     * @param redirector
     * @exception Exception if an error occurs
     */
    public void callFunction(String funName, List params,
                             Redirector redirector)
        throws Exception
    {
        Context context = Context.enter();
        context.setOptimizationLevel(OPTIMIZATION_LEVEL);
        context.setGeneratingDebug(true);
        context.setCompileFunctionsWithDynamicScope(true);
        context.setErrorReporter(errorReporter);
        AO_FOM_Cocoon cocoon = null;
        Scriptable thrScope = getSessionScope();
        synchronized (thrScope) {
            try {
                setupContext(redirector, context, thrScope);
                cocoon = (AO_FOM_Cocoon)thrScope.get("cocoon", thrScope);
                if (enableDebugger) {
                    if (!getDebugger().isVisible()) {
                        // only raise the debugger window if it isn't already visible
                        getDebugger().setVisible(true);
                    }
                }
                int size = (params != null ? params.size() : 0);
                Object[] funArgs = new Object[size];
                Scriptable parameters = context.newObject(thrScope);
                if (size != 0) {
                    for (int i = 0; i < size; i++) {
                        Interpreter.Argument arg = (Interpreter.Argument)params.get(i);
                        funArgs[i] = arg.value;
                        if (arg.name == null) arg.name = "";
                        parameters.put(arg.name, parameters, arg.value);
                    }
                }
                cocoon.setParameters(parameters);
                Object fun = ScriptableObject.getProperty(thrScope, funName);
                if (fun == Scriptable.NOT_FOUND) {
                    throw new ResourceNotFoundException("Function \"javascript:"+funName+ "()\" not found");
                }
                ScriptRuntime.call(context, fun, thrScope,
                                   funArgs, thrScope);
            } catch (JavaScriptException ex) {
                EvaluatorException ee =
                    Context.reportRuntimeError(ToolErrorReporter.getMessage("msg.uncaughtJSException",
                                                                            ex.getMessage()));
                Throwable unwrapped = unwrap(ex);
                if (unwrapped instanceof ProcessingException) {
                    throw (ProcessingException)unwrapped;
                }
               
                throw new CascadingRuntimeException(ee.getMessage(), unwrapped);
            } catch (EcmaError ee) {
                String msg = ToolErrorReporter.getMessage("msg.uncaughtJSException", ee.toString());
                if (ee.getSourceName() != null) {
                    Context.reportRuntimeError(msg,
                                               ee.getSourceName(),
                                               ee.getLineNumber(),
                                               ee.getLineSource(),
                                               ee.getColumnNumber());
                } else {
                    Context.reportRuntimeError(msg);
                }
                throw new CascadingRuntimeException(ee.getMessage(), ee);
            } finally {
                updateSession(thrScope);
                if (cocoon != null) cocoon.invalidate();
                Context.exit();
            }
        }
    }

    public void handleContinuation(String id, List params,
                                   Redirector redirector)
        throws Exception
    {
        WebContinuation wk = continuationsMgr.lookupWebContinuation(id);

        if (wk == null) {

            /*
             * Throw an InvalidContinuationException to be handled inside the
             * <map:handle-errors> sitemap element.
             */
            throw new InvalidContinuationException("The continuation ID " + id + " is invalid.");
        }

        Context context = Context.enter();
        context.setOptimizationLevel(OPTIMIZATION_LEVEL);
        context.setGeneratingDebug(true);
        context.setCompileFunctionsWithDynamicScope(true);

        // Obtain the continuation object from it, and setup the
        // FOM_Cocoon object associated in the dynamic scope of the saved
        // continuation with the environment and context objects.
        Continuation k = (Continuation)wk.getContinuation();
        Scriptable kScope = k.getParentScope();
        synchronized (kScope) {
            AO_FOM_Cocoon cocoon = (AO_FOM_Cocoon)kScope.get("cocoon", kScope);
            cocoon.setup(this, redirector, avalonContext, manager, getLogger());
            if (enableDebugger) {
                getDebugger().setVisible(true);
            }
            int size = (params != null ? params.size() : 0);
            Scriptable parameters = context.newObject(kScope);
            if (size != 0) {
                for (int i = 0; i < size; i++) {
                    Interpreter.Argument arg = (Interpreter.Argument)params.get(i);
                    parameters.put(arg.name, parameters, arg.value);
                }
            }
            cocoon.setParameters(parameters);
            FOM_WebContinuation fom_wk =
                new FOM_WebContinuation(wk);
            fom_wk.setParentScope(kScope);
            fom_wk.setPrototype(ScriptableObject.getClassPrototype(kScope,
                                                                   fom_wk.getClassName()));
                                 
            Object[] args = new Object[] {k, fom_wk};

            try {
                ScriptableObject.callMethod(cocoon,
                                            "handleContinuation",
                                            args);
            } catch (JavaScriptException ex) {
                EvaluatorException ee =
                    Context.reportRuntimeError(ToolErrorReporter.getMessage("msg.uncaughtJSException",
                                                                            ex.getMessage()));
                Throwable unwrapped = unwrap(ex);
                if (unwrapped instanceof ProcessingException) {
                    throw (ProcessingException)unwrapped;
                }
               
                throw new CascadingRuntimeException(ee.getMessage(), unwrapped);
            } catch (EcmaError ee) {
                String msg = ToolErrorReporter.getMessage("msg.uncaughtJSException", ee.toString());
                if (ee.getSourceName() != null) {
                    Context.reportRuntimeError(msg,
                                               ee.getSourceName(),
                                               ee.getLineNumber(),
                                               ee.getLineSource(),
                                               ee.getColumnNumber());
                } else {
                    Context.reportRuntimeError(msg);
                }
                throw new CascadingRuntimeException(ee.getMessage(), ee);
            } finally {
                updateSession(kScope);
                cocoon.invalidate();
                Context.exit();
            }
        }
    }

    private Throwable unwrap(JavaScriptException e) {
        Object value = e.getValue();
        while (value instanceof Wrapper) {
            value = ((Wrapper)value).unwrap();
        }
        if (value instanceof Throwable) {
            return (Throwable)value;
        }
        return e;
    }

    public void forwardTo(Scriptable scope, AO_FOM_Cocoon cocoon,
                          String uri, Object bizData,
                          FOM_WebContinuation fom_wk,
                          Redirector redirector)
        throws Exception {
        setupView(scope, cocoon, fom_wk);
        super.forwardTo(uri, bizData,
                        fom_wk == null ? null :
                           fom_wk.getWebContinuation(),
                        redirector);
    }

    // package access as this is called by FOM_Cocoon
    void process(Scriptable scope, AO_FOM_Cocoon cocoon,
                    String uri, Object bizData,
                    OutputStream out)
        throws Exception {
        setupView(scope, cocoon, null);
        super.process(uri, bizData, out);
    }
   
    private void setupView(Scriptable scope,
                           AO_FOM_Cocoon cocoon,
                           FOM_WebContinuation kont) {
        Map objectModel = ContextHelper.getObjectModel(this.avalonContext);
        // Make the JS live-connect objects available to the view layer
        FOM_JavaScriptFlowHelper.setPackages(objectModel,
                                   (Scriptable)ScriptableObject.getProperty(scope,
                                                                            "Packages"));
        FOM_JavaScriptFlowHelper.setJavaPackage(objectModel,
                                                (Scriptable)ScriptableObject.getProperty(scope,
                                                                                         "java"));
        // Make the FOM objects available to the view layer
        FOM_JavaScriptFlowHelper.setFOM_Request(objectModel,
                                            cocoon.jsGet_request());
        FOM_JavaScriptFlowHelper.setFOM_Response(objectModel,
                                             cocoon.jsGet_response());
        Request request = ObjectModelHelper.getRequest(objectModel);
        Scriptable session = null;
        if (request.getSession(false) != null) {
            session = cocoon.jsGet_session();
        }
        FOM_JavaScriptFlowHelper.setFOM_Session(objectModel, session);

        FOM_JavaScriptFlowHelper.setFOM_Context(objectModel,
                                                cocoon.jsGet_context());
        if (kont != null) {
            FOM_JavaScriptFlowHelper.setFOM_WebContinuation(objectModel,
                                                            kont);
        }
    }

}
TOP

Related Classes of org.apache.cocoon.components.flow.javascript.fom.AO_FOM_JavaScriptInterpreter$ScriptSourceEntry

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.