coliver     2003/06/20 01:28:20

  Added:       src/scratchpad/src/org/apache/cocoon/components/flow/javascript/fom
                        FOM_Cocoon.java FOM_JavaScriptInterpreter.java
                        fom_system.js
  Log:
  Prototype implementation of FOM
  
  Revision  Changes    Path
  1.1                  
cocoon-2.1/src/scratchpad/src/org/apache/cocoon/components/flow/javascript/fom/FOM_Cocoon.java
  
  Index: FOM_Cocoon.java
  ===================================================================
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  */
  package org.apache.cocoon.components.flow.javascript.fom;
  import org.mozilla.javascript.JavaScriptException;
  import org.mozilla.javascript.Scriptable;
  import org.mozilla.javascript.Function;
  import org.mozilla.javascript.ScriptableObject;
  import org.mozilla.javascript.Context;
  import org.mozilla.javascript.Undefined;
  import org.mozilla.javascript.Wrapper;
  import org.mozilla.javascript.continuations.Continuation;
  import org.apache.cocoon.environment.Environment;
  import org.apache.cocoon.environment.Request;
  import org.apache.cocoon.environment.Response;
  import org.apache.cocoon.environment.Session;
  import org.apache.cocoon.environment.Cookie;
  import org.apache.cocoon.environment.ObjectModelHelper;
  import org.apache.cocoon.components.flow.WebContinuation;
  import org.apache.cocoon.components.flow.ContinuationsManager;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.logger.Logger;
  import java.util.Map;
  import java.io.OutputStream;
  /**
   * Implementation of FOM (Flow Object Model)
   */
  
  public class FOM_Cocoon extends ScriptableObject {
  
      private FOM_JavaScriptInterpreter interpreter;
  
      private Environment environment;
      private ComponentManager componentManager;
  
      private FOM_Request request;
      private FOM_Response response;
      private FOM_Session session;
      private FOM_Context context;
      private FOM_Log log;
  
      private WebContinuation lastContinuation;
  
      public String getClassName() {
          return "FOM_Cocoon";
      }
  
      public void setup(FOM_JavaScriptInterpreter interp,
                        Environment env, 
                        ComponentManager manager) {
          this.interpreter = interp;
          this.environment = env;
          this.componentManager = manager;
      }
  
      public void invalidate() {
          this.request = null;
          this.response = null;
          this.session = null;
          this.context = null;
          this.componentManager = null;
          this.environment = null;
          this.interpreter = null;
      }
  
      private void forwardTo(String uri, Object bizData,
                             Continuation continuation) 
        throws Exception {
          WebContinuation wk = null;
          if (continuation != null) {
              ContinuationsManager contMgr = (ContinuationsManager)
                  componentManager.lookup(ContinuationsManager.ROLE);
              wk = lastContinuation = 
                  contMgr.createWebContinuation(continuation,
                                                lastContinuation,
                                                0);
          }
          interpreter.forwardTo("cocoon://"+
                                environment.getURIPrefix() + uri,
                                bizData, wk, environment);
      }
  
      public void jsFunction_sendPage(String uri, 
                                      Object obj, 
                                      Object continuation) 
        throws Exception {
          forwardTo(uri, obj, (Continuation)unwrap(continuation)); 
      }
                                      
  
      public void jsFunction_processPipelineTo(String uri,
                                               Object map,
                                               Object outputStream) 
          throws Exception {
        if (!(unwrap(outputStream) instanceof OutputStream)) {
            throw new JavaScriptException("expected a java.io.OutputStream instead of 
" + outputStream);
        }
          interpreter.process(uri, map, 
                            (OutputStream)unwrap(outputStream), 
                            environment);
      }
  
      public void jsFunction_redirectTo(String uri) throws Exception {
          environment.redirect(false, uri);
      }
  
      public void jsFunction_addEventListener(String eventName, 
                                              Object function) {
          // what is this?
      }
      
      public void jsFunction_removeEventListener(String eventName,
                                                 Object function) {
          // what is this?
      }
  
      public Object jsFunction_getComponent(String id) {
          // what is this?
          return null;
      }
  
      public static class FOM_Request extends ScriptableObject {
  
          Request request;
  
          public FOM_Request() {
            // prototype ctor
        }
  
          public FOM_Request(Object request) {
              this.request = (Request)unwrap(request);
          }
  
          public String getClassName() {
              return "FOM_Request";
          }
  
          public Object jsFunction_get(String name) {
              return request.get(name);
          }
  
          public Object jsFunction_getAttribute(String name) {
              return request.getAttribute(name);
          }
  
          public void jsFunction_removeAttribute(String name) {
            request.removeAttribute(name);
          }
  
          public void jsFunction_setAttribute(String name,
                                              Object value) {
              
              request.setAttribute(name, unwrap(value));
          }
  
          public Object get(String name, Scriptable start) {
              Object result = super.get(name, start);
              if (result == NOT_FOUND && request != null) {
                  result = request.getParameter(name);
                  if (result == null) {
                      result = NOT_FOUND;
                  }
              }
              return result;
          }
  
          public String jsFunction_getCharacterEncoding() {
              return request.getCharacterEncoding();
          }
  
          public void jsFunction_setCharacterEncoding(String value) 
            throws Exception {
              request.setCharacterEncoding(value);
          }
  
          public int jsFunction_getContentLength() {
              return request.getContentLength();
          }
  
          public String jsFunction_getContentType() {
              return request.getContentType();
          }
  
          public String jsFunction_getParameter(String name) {
              return request.getParameter(name);
          }
  
          public Object jsFunction_getParameterValues(String name) {
              return request.getParameterValues(name);
          }
  
          public Object jsFunction_getParameterNames() {
              return request.getParameterNames();
          }
  
          public String jsFunction_getAuthType() {
              return request.getAuthType();
          }
          
          public String jsFunction_getProtocol() {
              return request.getProtocol();
          }
      }
  
      public static class FOM_Cookie extends ScriptableObject {
  
        Cookie cookie;
  
        public FOM_Cookie() {
            // prototype ctor
        }
  
        public FOM_Cookie(Object cookie) {
            this.cookie = (Cookie)unwrap(cookie);
        }
  
          public String getClassName() {
              return "FOM_Cookie";
          }
  
        public String jsGet_name() {
            return cookie.getName();
        }
  
        public int jsGet_version() {
            return cookie.getVersion();
        }
  
        public void jsSet_version(int value) {
            cookie.setVersion(value);
        }
  
        public String jsGet_value() {
            return cookie.getValue();
        }
  
        public void jsSet_value(String value) {
            cookie.setValue(value);
        }
  
        public void jsSet_comment(String purpose) {
            cookie.setComment(purpose);
        }
  
        public String jsGet_comment() {
            return cookie.getComment();
        }
  
        public void jsSet_domain(String pattern) {
            cookie.setDomain(pattern);
        }
  
        public String jsGet_domain() {
            return cookie.getDomain();
        }
  
        public void jsSet_maxAge(int value) {
            cookie.setMaxAge(value);
        }
  
        public int jsGet_maxAge() {
            return cookie.getMaxAge();
        }
  
        public void jsSet_path(String value) {
            cookie.setPath(value);
        }
  
        public String jsGet_path() {
            return cookie.getPath();
        }
  
        public void jsSet_secure(boolean value) {
            cookie.setSecure(value);
        }
  
        public boolean jsGet_secure() {
            return cookie.getSecure();
        }
      }
  
      public static class FOM_Response extends ScriptableObject {
  
          Response response;
  
        public FOM_Response() {
            // prototype ctor
        }
  
        public FOM_Response(Object response) {
            this.response = (Response)unwrap(response);
        }
  
          public String getClassName() {
              return "FOM_Response";
          }
  
        public Object jsFunction_createCookie(String name, String value) {
            FOM_Cookie result = 
                new FOM_Cookie(response.createCookie(name, value));
            result.setParentScope(getParentScope());
            result.setPrototype(getClassPrototype(this, "FOM_Cookie"));
            return result;
        }
  
        public void jsFunction_addCookie(Object cookie) 
            throws JavaScriptException {
            if (!(cookie instanceof FOM_Cookie)) {
                throw new JavaScriptException("expected a Cookie instead of "+cookie);
            }
            FOM_Cookie fom_cookie = (FOM_Cookie)cookie;
            response.addCookie(fom_cookie.cookie);
        }
  
        public boolean jsFunction_containsHeader(String name) {
            return response.containsHeader(name);
        }
  
        public void jsFunction_setHeader(String name, String value) {
            response.setHeader(name, value);
        }
  
        public void jsFunction_addHeader(String name, String value) {
            response.addHeader(name, value);
        }
      }
  
      public static class FOM_Session extends ScriptableObject {
  
          Session session;
  
        public FOM_Session() {
            // prototype ctor
        }
  
        public FOM_Session(Object session) {
            this.session = (Session)unwrap(session);
        }
  
          public String getClassName() {
              return "FOM_Session";
          }
  
        public Object get(String name, Scriptable start) {
            Object result = super.get(name, start);
            if (result == NOT_FOUND && session != null) {
                result = session.getAttribute(name);
                if (result == null) {
                    result = NOT_FOUND;
                }
            }
            return result;
        }
  
        public Object jsFunction_getAttribute(String name) {
            return session.getAttribute(name);
        }
        
        public void jsFunction_setAttribute(String name, Object value) {
            session.setAttribute(name, value);
        }
  
        public void jsFunction_removeAttribute(String name) {
            session.removeAttribute(name);
        }
  
        public Object jsFunction_getAttributeNames() {
            return session.getAttributeNames();
        }
  
        public void jsFunction_invalidate() {
            session.invalidate();
        }
  
        public boolean jsFunction_isNew() {
            return session.isNew();
        }
  
        public String jsFunction_getId() {
            return session.getId();
        }
  
        public long jsFunction_getCreationTime() {
            return session.getCreationTime();
        }
  
        public long jsFunction_getLastAccessedTime() {
            return session.getLastAccessedTime();
        }
  
        public void jsFunction_setMaxInactiveInterval(int interval) {
            session.setMaxInactiveInterval(interval);
        }
  
        public int jsFunction_getMaxInactiveInterval() {
            return session.getMaxInactiveInterval();
        }
      }
  
      public static class FOM_Context extends ScriptableObject {
  
          org.apache.cocoon.environment.Context context;
  
        public FOM_Context() {
            // prototype ctor
        }
  
        public FOM_Context(Object context) {
            this.context = (org.apache.cocoon.environment.Context)unwrap(context);
        }
  
          public String getClassName() {
              return "FOM_Context";
          }
  
        public Object jsFunction_getAttribute(String name) {
            return context.getAttribute(name);
        }
  
        public void jsFunction_setAttribute(String name, Object value) {
            context.setAttribute(name, unwrap(value));
        }
  
        public void jsFunction_removeAttribute(String name) {
            context.removeAttribute(name);
        }
  
        public Object jsFunction_getAttributeNames() {
            return context.getAttributeNames();
        }
  
        public Object jsFunction_getInitParameter(String name) {
            return context.getInitParameter(name);
        }
  
        public Object get(String name, Scriptable start) {
            Object value = super.get(name, start);
            if (value == NOT_FOUND && context != null) {
                value = context.getAttribute(name);
                if (value == null) {
                    value = NOT_FOUND;
                }
            }
            return value;
        }
      }
  
      public static class FOM_Log extends ScriptableObject {
  
          private Logger logger;
  
          public FOM_Log() {
          }
  
          public String getClassName() {
              return "FOM_Log";
          }
          
          public void enableLogging(Logger logger) {
              this.logger = logger;
          }
          
          public void jsFunction_debug(String message) {
              logger.debug(message);
          }
          
          public void jsFunction_info(String message) {
              logger.info(message);
          }
          
          public void jsFunction_warn(String message) {
              logger.warn(message);
          }
          
          public void jsFunction_error(String message) {
              logger.error(message);
          }
  
        public boolean jsFunction_isDebugEnabled() {
            return logger.isDebugEnabled();
        }
  
        public boolean jsFunction_isInfoEnabled() {
            return logger.isInfoEnabled();
        }
  
        public boolean jsFunction_isWarnEnabled() {
            return logger.isWarnEnabled();
        }
  
        public boolean jsFunction_isErrorEnabled() {
            return logger.isErrorEnabled();
        }
      }
  
      public FOM_Request jsGet_request() {
          if (request != null) {
              return request;
          }
          if (environment == null) {
              // context has been invalidated
              return null;
          }
          Map objectModel = environment.getObjectModel();
          request = 
              new FOM_Request(ObjectModelHelper.getRequest(objectModel));
          request.setParentScope(getParentScope());
          request.setPrototype(getClassPrototype(getParentScope(),
                                                 "FOM_Request"));
          return request;
      }
  
      public FOM_Response jsGet_response() {
          if (response != null) {
              return response;
          }
          if (environment == null) {
              // context has been invalidated
              return null;
          }
          Map objectModel = environment.getObjectModel();
          response = 
              new FOM_Response(ObjectModelHelper.getResponse(objectModel));
          response.setParentScope(getParentScope());
          response.setPrototype(getClassPrototype(this,
                                                 "FOM_Response"));
          return response;
      }
  
      public FOM_Log jsGet_log() {
          if (log != null) {
            return log;
        }
          log = new FOM_Log();
          log.setParentScope(getParentScope());
          log.setPrototype(getClassPrototype(this, "FOM_Log"));
          return log;
      }
  
      public FOM_Context jsGet_context() {
          if (context != null) {
              return context;
          }
          Map objectModel = environment.getObjectModel();
          context = 
              new FOM_Context(ObjectModelHelper.getContext(objectModel));
          context.setParentScope(getParentScope());
          context.setPrototype(getClassPrototype(this, "FOM_Context"));
          return context;
      }
  
      public FOM_Session jsGet_session() {
          if (session != null) {
              return session;
          }
          if (environment == null) {
              // session has been invalidated
              return null;
          }
          Map objectModel = environment.getObjectModel();
          session = 
              new 
FOM_Session(ObjectModelHelper.getRequest(objectModel).getSession(true));
          session.setParentScope(getParentScope());
          session.setPrototype(getClassPrototype(this,
                                                 "FOM_Session"));
          return session;
      }
  
      // unwrap Wrapper's and convert undefined to null
      private static Object unwrap(Object obj) {
          if (obj instanceof Wrapper) {
              obj = ((Wrapper)obj).unwrap();
          } else if (obj == Undefined.instance) {
            obj = null;
        }
        return obj;
      }
  
  }
  
  
  
  1.1                  
cocoon-2.1/src/scratchpad/src/org/apache/cocoon/components/flow/javascript/fom/FOM_JavaScriptInterpreter.java
  
  Index: FOM_JavaScriptInterpreter.java
  ===================================================================
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  */
  package org.apache.cocoon.components.flow.javascript.fom;
  
  import java.io.BufferedReader;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  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.cocoon.ResourceNotFoundException;
  import org.apache.cocoon.ProcessingException;
  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.environment.Environment;
  import org.apache.cocoon.environment.ObjectModelHelper;
  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.mozilla.javascript.Context;
  import org.mozilla.javascript.EcmaError;
  import org.mozilla.javascript.EvaluatorException;
  import org.mozilla.javascript.Function;
  import org.mozilla.javascript.JavaScriptException;
  import org.mozilla.javascript.NativeArray;
  import org.mozilla.javascript.PropertyException;
  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;
  
  import org.apache.cocoon.components.flow.javascript.JSErrorReporter;
  import org.apache.cocoon.components.flow.javascript.JavaScriptFlow;
  import org.apache.cocoon.components.flow.javascript.ScriptablePointer;
  import org.apache.cocoon.components.flow.javascript.ScriptablePropertyHandler;
  import org.apache.cocoon.components.flow.javascript.ScriptablePointerFactory;
  /**
   * Interface with the JavaScript interpreter.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Ovidiu Predescu</a>
   * @author <a href="mailto:[EMAIL PROTECTED]">Marcus Crafter</a>
   * @since March 25, 2002
   * @version CVS $Id: FOM_JavaScriptInterpreter.java,v 1.1 2003/06/20 08:28:20 
coliver Exp $
   */
  public class FOM_JavaScriptInterpreter extends AbstractInterpreter
      implements Configurable, Initializable
  {
  
      /**
       * 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;
  
      /**
       * When was the last time we checked for script modifications. Used
       * only if [EMAIL PROTECTED] #reloadScripts} is true.
       */
      protected long lastTimeCheck = 0;
  
      /**
       * 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;
          }
  
          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);
                  compileTime = source.getLastModified();
              }
              return script;
          }
      }
      /**
       * 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;
      }
  
      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;
          }
      }
  
      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
              ScriptableObject.defineClass(scope, FOM_Cocoon.class);
              ScriptableObject.defineClass(scope,
                                           FOM_Cocoon.FOM_Request.class);
              ScriptableObject.defineClass(scope,
                                           FOM_Cocoon.FOM_Response.class);
              ScriptableObject.defineClass(scope,
                                           FOM_Cocoon.FOM_Session.class);
              ScriptableObject.defineClass(scope,
                                           FOM_Cocoon.FOM_Context.class);
              ScriptableObject.defineClass(scope,
                                           FOM_Cocoon.FOM_Cookie.class);
              ScriptableObject.defineClass(scope,
                                           FOM_Cocoon.FOM_Log.class);
              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 [EMAIL PROTECTED]
       * 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(Environment environment)
          throws Exception {
          Map objectModel = environment.getObjectModel();
          Request request = ObjectModelHelper.getRequest(objectModel);
          Session session = request.getSession(true);
          Scriptable scope = null;
          HashMap userScopes = (HashMap)session.getAttribute(USER_GLOBAL_SCOPE);
          if (userScopes != null) {
              String uriPrefix = environment.getURIPrefix();
              scope = (Scriptable)userScopes.get(uriPrefix);
          }
          if (scope == null) {
              return setSessionScope(environment, createThreadScope());
          }
          return scope;
      }
  
      /**
       * Associates a JavaScript scope, a Scriptable object, with the URI
       * prefix of the current sitemap, as returned by the [EMAIL PROTECTED]
       * org.apache.cocoon.environment.Environment#getURIPrefix} method.
       *
       * @param environment an <code>Environment</code> value
       * @param scope a <code>Scriptable</code> value
       */
      private Scriptable setSessionScope(Environment environment, Scriptable scope)
          throws Exception {
          Map objectModel = environment.getObjectModel();
          Request request = ObjectModelHelper.getRequest(objectModel);
          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);
          }
  
          String uriPrefix = environment.getURIPrefix();
          userScopes.put(uriPrefix, scope);
          return scope;
      }
  
      private Scriptable createThreadScope() 
          throws Exception {
          org.mozilla.javascript.Context context = 
              org.mozilla.javascript.Context.getCurrentContext();
  
          Scriptable thrScope = context.newObject(scope);
  
          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[] = {};
          FOM_Cocoon cocoon = (FOM_Cocoon)
              context.newObject(thrScope, "FOM_Cocoon", args);
          cocoon.setParentScope(thrScope);
          thrScope.put("cocoon", thrScope, cocoon);
          ((ScriptableObject)thrScope).defineProperty(LAST_EXEC_TIME,
                                                      new Long(0),
                                                      ScriptableObject.DONTENUM |
                                                      ScriptableObject.PERMANENT);
          
          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 invoke from the JavaScript
       * script <code>cocoon.createSession()</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 [EMAIL PROTECTED] 
#callFunction}.</p>
       *
       * @param environment an <code>Environment</code> value
       * @return a <code>Scriptable</code> value
       * @exception Exception if an error occurs
       */
      protected Scriptable enterContext(Environment environment)
          throws Exception
      {
          Context context = Context.enter();
          context.setOptimizationLevel(OPTIMIZATION_LEVEL);
          context.setGeneratingDebug(true);
          context.setCompileFunctionsWithDynamicScope(true);
          context.setErrorReporter(errorReporter);
          Scriptable thrScope = null;
  
  
          // 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.
          thrScope = getSessionScope(environment);
          FOM_Cocoon cocoon = (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, environment, manager);
  
          // 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 (!needsRefresh) {
                      execList.addAll(needResolve);
                  } else {
                      execList.addAll(topLevelScripts);
                  }
                  needResolve.clear();
              }
              thrScope.put(LAST_EXEC_TIME, thrScope,
                           new Long(System.currentTimeMillis()));
              // 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 = environment.resolveURI(sourceURI);
                      entry = new ScriptSourceEntry(src);
                      compiledScripts.put(sourceURI, entry);
                  }
                  // 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);
                  }
              }
          }
          return thrScope;
      }
  
      /**
       * Remove the Cocoon object from the JavaScript thread scope so it
       * can be garbage collected, together with all the objects it
       * contains.
       */
      protected void exitContext(Scriptable thrScope)
      {
          // thrScope may be null if an exception occurred compiling a script
          if (thrScope != null) {
              FOM_Cocoon cocoon = (FOM_Cocoon)thrScope.get("cocoon", thrScope);
              cocoon.invalidate();
          }
          Context.exit();
      }
  
  
      /**
       * Compile filename as JavaScript code
       * @param cx Rhino context
       * @param environment source resolver
       * @param fileName resource uri
       * @return compiled script
       */
  
      public Script compileScript(Context cx,
                                  Environment environment,
                                  String fileName) throws Exception {
          Source src = environment.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;
          }
      }
  
      private Script compileScript(Context cx, Scriptable scope,
                                   Source src) throws Exception {
          InputStream is = src.getInputStream();
          if (is == null) {
              throw new ResourceNotFoundException(src.getURI() + ": not found");
          }
          Reader reader = new BufferedReader(new InputStreamReader(is));
          Script compiledScript = cx.compileReader(scope, reader,
                                                   src.getURI(),
                                                   1, null);
          return compiledScript;
      }
  
      /**
       * 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 environment an <code>Environment</code> value
       * @exception Exception if an error occurs
       */
      public void callFunction(String funName, List params,
                               Environment environment)
          throws Exception
      {
          Scriptable thrScope = null;
          try {
              thrScope = enterContext(environment);
  
              Context context = Context.getCurrentContext();
              FOM_Cocoon cocoon = (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];
              NativeArray parameters = new NativeArray(size);
              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) {
                  fun = funName; // this will produce a better error message
              }
              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 {
              exitContext(thrScope);
          }
      }
  
      public void handleContinuation(String id, List params,
                                     Environment environment)
          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();
          FOM_Cocoon cocoon = (FOM_Cocoon)kScope.get("cocoon", kScope);
          cocoon.setup(this, environment, manager);
          if (enableDebugger) {
              getDebugger().setVisible(true);
          }
          int size = (params != null ? params.size() : 0);
          NativeArray parameters = new NativeArray(size);
  
          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);
              }
          }
          Object[] args = new Object[] {k};
          //cocoon.setParameters(parameters);
          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 {
              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(String uri, Object bizData,
                            WebContinuation continuation,
                            Environment environment)
          throws Exception {
          Map objectModel = environment.getObjectModel();
          // Make the live-connect objects available to the view layer
          JavaScriptFlow.setPackages(objectModel,
                                     (Scriptable)ScriptableObject.getProperty(scope,
                                                                              
"Packages"));
          JavaScriptFlow.setJavaPackage(objectModel,
                                        (Scriptable)ScriptableObject.getProperty(scope,
                                                                     "java"));
          super.forwardTo(uri, bizData, continuation, environment);
      }
  }
  
  
  
  1.1                  
cocoon-2.1/src/scratchpad/src/org/apache/cocoon/components/flow/javascript/fom/fom_system.js
  
  Index: fom_system.js
  ===================================================================
  FOM_Cocoon.suicide = new Continuation();
  
  FOM_Cocoon.prototype.sendPageAndWait = function(uri, bizData) {
      this.sendPage(uri, bizData, new Continuation());
      FOM_Cocoon.suicide();
  }
  
  FOM_Cocoon.prototype.handleContinuation = function(k) {
      k(k);
  }
  
  
  

Reply via email to