cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From coli...@apache.org
Subject cvs commit: cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript Database.js xmlForm.js JSCocoon.java JSErrorReporter.java JavaScriptInterpreter.java system.js
Date Mon, 17 Mar 2003 00:32:36 GMT
coliver     2003/03/16 16:32:35

  Modified:    src/java/org/apache/cocoon/components/flow/javascript
                        JSCocoon.java JSErrorReporter.java
                        JavaScriptInterpreter.java system.js
  Added:       src/java/org/apache/cocoon/components/flow/javascript
                        Database.js xmlForm.js
  Log:
  fixed script reloading and started preparing for refactoring of FOM
  
  Revision  Changes    Path
  1.5       +5 -14     cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/JSCocoon.java
  
  Index: JSCocoon.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/JSCocoon.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- JSCocoon.java	16 Mar 2003 18:03:53 -0000	1.4
  +++ JSCocoon.java	17 Mar 2003 00:32:35 -0000	1.5
  @@ -91,7 +91,6 @@
   {
       protected static String OBJECT_SOURCE_RESOLVER = "source-resolver";
       protected JavaScriptInterpreter interpreter;
  -    protected Scriptable scope;
       protected NativeArray parameters;
       protected Environment environment;
       protected ComponentManager manager;
  @@ -103,15 +102,6 @@
           return "Cocoon";
       }
   
  -    public void setScope(Scriptable scope)
  -    {
  -        this.scope = scope;
  -    }
  -
  -    public Scriptable getScope()
  -    {
  -        return scope;
  -    }
   
       public void setParameters(NativeArray parameters)
       {
  @@ -208,8 +198,9 @@
           org.mozilla.javascript.Context cx =
               org.mozilla.javascript.Context.getCurrentContext();
           try {
  -            Script script = interpreter.compileScript(cx, environment, filename);
  -            return script.exec(cx, ScriptableObject.getTopLevelScope(this));
  +	    Scriptable scope = getParentScope();
  +            Script script = interpreter.compileScript(cx, scope, environment, filename);
  +            return script.exec(cx, scope);
           } catch (JavaScriptException e) {
               throw e;
           } catch (Exception e) {
  @@ -273,7 +264,7 @@
       */
       public void jsFunction_createSession()
       {
  -        interpreter.setSessionScope(environment, scope);
  +        interpreter.setSessionScope(environment, getParentScope());
       }
   
       /**
  
  
  
  1.4       +6 -4      cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/JSErrorReporter.java
  
  Index: JSErrorReporter.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/JSErrorReporter.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- JSErrorReporter.java	16 Mar 2003 17:49:12 -0000	1.3
  +++ JSErrorReporter.java	17 Mar 2003 00:32:35 -0000	1.4
  @@ -44,9 +44,11 @@
                                            int line, String lineSrc,
                                            int column)
     {
  -      return new EvaluatorException(getErrorMessage("msg.error", message,
  -						    sourceName, line,
  -						    lineSrc, column));
  +      String errMsg = getErrorMessage("msg.error", message,
  +				      sourceName, line,
  +				      lineSrc, column);
  +      System.err.println(errMsg);
  +      return new EvaluatorException(errMsg);
     }
   
     /**
  
  
  
  1.4       +145 -125  cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/JavaScriptInterpreter.java
  
  Index: JavaScriptInterpreter.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/JavaScriptInterpreter.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- JavaScriptInterpreter.java	16 Mar 2003 17:49:12 -0000	1.3
  +++ JavaScriptInterpreter.java	17 Mar 2003 00:32:35 -0000	1.4
  @@ -86,6 +86,18 @@
   public class 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 = "JavaScript GLOBAL SCOPE";
   
       // This is the only optimization level that supports continuations
  @@ -93,18 +105,60 @@
       static int OPTIMIZATION_LEVEL = -2;
   
       /**
  -     * List of <code>Source</code> objects that represent files to be
  -     * read in by the JavaScript interpreter.
  -     */
  -    protected List scripts = new ArrayList();
  -
  -    /**
        * When was the last time we checked for script modifications. Used
        * only if {@link #reloadScripts} is true.
        */
       protected long lastTimeCheck = 0;
  +
  +    /**
  +     * Shared global scope for scripts and other immutable objects
  +     */
       JSGlobal scope;
  -    List compiledScripts = Collections.synchronizedList(new ArrayList());
  +
  +    /**
  +     * 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;
       org.mozilla.javascript.tools.debugger.Main debugger;
  @@ -153,6 +207,7 @@
   
           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,
  @@ -285,9 +340,7 @@
        * @return a <code>Scriptable</code> value
        * @exception Exception if an error occurs
        */
  -    protected Scriptable enterContext(Environment environment, 
  -                                      boolean needsExec,
  -                                      List sourcesToBeCompiled)
  +    protected Scriptable enterContext(Environment environment)
           throws Exception
       {
           Context context = Context.enter();
  @@ -297,7 +350,6 @@
           context.setErrorReporter(errorReporter);
           Scriptable thrScope = null;
   
  -        compileScripts(context, environment, sourcesToBeCompiled);
   
           // 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
  @@ -312,7 +364,12 @@
   
           // The Cocoon object exported to JavaScript needs to be setup here
           JSCocoon cocoon;
  +	boolean newScope = false;
  +	long lastExecTime = 0;
           if (thrScope == null) {
  +
  +	    newScope = true;
  +
               thrScope = context.newObject(scope);
   
               thrScope.setPrototype(scope);
  @@ -325,26 +382,65 @@
               // to the interpreter object, and some Cocoon objects. See
               // JSCocoon for more details.
               Object args[] = {};
  -            cocoon = (JSCocoon)context.newObject(scope, "Cocoon", args);
  -            ((JSCocoon)cocoon).setInterpreter(this);
  -            ((JSCocoon)cocoon).setScope(thrScope);
  +            cocoon = (JSCocoon)context.newObject(thrScope, "Cocoon", args);
  +            cocoon.setInterpreter(this);
  +            cocoon.setParentScope(thrScope);
               thrScope.put("cocoon", thrScope, cocoon);
  -            needsExec = true;
  +	    ((ScriptableObject)thrScope).defineProperty(LAST_EXEC_TIME,
  +							new Long(0),
  +							ScriptableObject.DONTENUM |
  +							ScriptableObject.PERMANENT);
  +
           } else {
               cocoon = (JSCocoon)thrScope.get("cocoon", thrScope);
  +	    lastExecTime = ((Long)thrScope.get(LAST_EXEC_TIME,
  +					       thrScope)).longValue();
  +
           }
           // We need to setup the JSCocoon object according to the current
           // request. Everything else remains the same.
           cocoon.setContext(manager, environment);
   
  -        if (needsExec) {
  -            for (int i = 0; i < compiledScripts.size(); i++) {
  -                Script compiledScript = (Script)compiledScripts.get(i);
  -                compiledScript.exec(context, thrScope);
  -            }
  +	// Check if we need to compile and/or execute scripts
  +	List execList = new ArrayList();
  +	boolean needsRefresh = false;
  +	synchronized (this) {
  +	    if (reloadScripts) {
  +		long now = System.currentTimeMillis();
  +		if (now >= lastTimeCheck + checkTime) {
  +		    needsRefresh = true;
  +		}
  +		lastTimeCheck = now;
  +	    }
  +	    if (needsRefresh || needResolve.size() > 0) {
  +		topLevelScripts.addAll(needResolve);
  +		if (!newScope && !needsRefresh) {
  +		    execList.addAll(needResolve);
  +		} else {
  +		    execList.addAll(topLevelScripts);
  +		}
  +		needResolve.clear();
  +	    }
  +	}
  +	thrScope.put(LAST_EXEC_TIME, thrScope, 
  +		     new Long(System.currentTimeMillis()));
  +	for (int i = 0; i < execList.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
  +	    Script script = entry.getScript(context, thrScope, needsRefresh);
  +	    long lastMod = entry.getSource().getLastModified();
  +	    // Execute the script if necessary
  +	    if (lastExecTime == 0 || lastMod > lastExecTime) {
  +		script.exec(context, thrScope);
  +	    } 
           }
  -
  -
           return thrScope;
       }
   
  @@ -363,18 +459,6 @@
           Context.exit();
       }
   
  -    private void compileScripts(Context cx, Environment environment, List sources)
  -        throws Exception
  -    {
  -        if (getLogger().isDebugEnabled()) {
  -            getLogger().debug("Reading scripts");
  -        }
  -        Iterator iter = sources.iterator();
  -        while (iter.hasNext()) {
  -            Source src = (Source)iter.next();
  -            compileScript(cx, src);
  -        }
  -    }
   
       /**
        * Compile filename as JavaScript code
  @@ -385,90 +469,32 @@
        */
   
       public Script compileScript(Context cx, 
  +				Scriptable scope,
                                   Environment environment, 
                                   String fileName) throws Exception {
           Source src = environment.resolveURI(fileName);
           if (src == null) {
               throw new ResourceNotFoundException(fileName + ": not found");
           }
  -        return compileScript(cx, src);
  +	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, Source src) throws Exception {
  +    private Script compileScript(Context cx, Scriptable scope, 
  +				 Source src) throws Exception {
           InputStream is = src.getInputStream();
           Reader reader = new BufferedReader(new InputStreamReader(is));
  -        Script compiledScript = cx.compileReader(scope, reader,
  +        Script compiledScript = cx.compileReader(this.scope, reader,
                                                    src.getURI(), 
                                                    1, null);
  -        compiledScripts.add(compiledScript);
  -        return compiledScript;
  -    }
  -
  -    /**
  -     * Reloads any modified script files.
  -     *
  -     * <p>It checks to see if any of the files already read in (those
  -     * present in the <code>scripts</code> hash map) have been
  -     * modified.
  -     *
  -     * <p>It also checks to see if any script files have been registered
  -     * with the interpreter since the last call to
  -     * <code>checkForModifiedScripts</code>. These files are stored in
  -     * the temporary array <code>needResolve</code>. If any such files
  -     * are found, they are read in.
  -     *
  -     * @param environment an <code>Environment</code> value
  -     * @param toBeCompiled output parameter: the list of <code>Source</code>
objects to be compiled
  -     * @return true if any existing Source script has changed
  -     */
  -    public boolean checkForModifiedScripts(Environment environment, 
  -                                           List toBeCompiled)
  -        throws Exception
  -    {
  -        boolean needsRefresh = false;
  -        if (reloadScripts
  -            && System.currentTimeMillis() >= lastTimeCheck + checkTime) {
  -            // FIXME: should we worry about synchronization?
  -            for (int i = 0, size = scripts.size(); i < size; i++) {
  -                Source src = (Source)scripts.get(i);
  -                src.refresh();
  -                getLogger().debug("Checking " + src.getURI()
  -                                  + ", source " + src
  -                                  + ", last modified " + src.getLastModified()
  -                                  + ", last time check " + lastTimeCheck);
  -                if (src.getLastModified() > lastTimeCheck) {
  -                    needsRefresh = true;
  -                    break;
  -                }
  -            }
  -        }
  -        
  -        // FIXME: remove the need for synchronization
  -        synchronized (this) {
  -            int size = needResolve.size();
  -            
  -            // If there's no need to re-read any file, and no files
  -            // have been requested to be read since the last time,
  -            // don't do anything.
  -            if (!needsRefresh && size == 0) {
  -                lastTimeCheck = System.currentTimeMillis();
  -                return false;
  -            }
  -            
  -            for (int i = 0; i < size; i++) {
  -                String source = (String)needResolve.get(i);
  -                Source src = environment.resolveURI(source);
  -                scripts.add(src);
  -                toBeCompiled.add(src);
  -            }
  -            needResolve.clear();
  -        }
  -        
  -        // Update the time of the last check. If an exception occurs, this
  -        // is not executed, so the next request will force a reparse of
  -        // the script files because of an old time stamp.
  -        lastTimeCheck = System.currentTimeMillis();
  -        return needsRefresh;
  +	return compiledScript;
       }
       
       /**
  @@ -487,14 +513,11 @@
           throws Exception
       {
           Scriptable thrScope = null;
  -        List toBeCompiled = new ArrayList(); 
  -        boolean needsRefresh = checkForModifiedScripts(environment, toBeCompiled);
           try {
  -            thrScope = enterContext(environment, needsRefresh, toBeCompiled);
  +            thrScope = enterContext(environment);
   
               Context context = Context.getCurrentContext();
               JSCocoon cocoon = (JSCocoon)thrScope.get("cocoon", thrScope);
  -          
               if (enableDebugger) {
                   final Scriptable s = thrScope;
                   debugger.setScopeProvider(
  @@ -504,18 +527,6 @@
                   if (!debugger.isVisible())
                       debugger.setVisible(true);
               }
  -          
  -            Object callFunction = thrScope.get("callFunction", thrScope);
  -            if (callFunction == Scriptable.NOT_FOUND)
  -                throw new RuntimeException("Cannot find 'callFunction' "
  -                                           + "(system.js not loaded?)");
  -          
  -            Object fun = thrScope.get(funName, thrScope);
  -            if (fun == Scriptable.NOT_FOUND)
  -                throw new RuntimeException("'" + funName + "' is undefined!");
  -            if (!(fun instanceof Function))
  -                throw new RuntimeException("'" + funName + "' is not a function!");
  -          
               int size = (params != null ? params.size() : 0);
               Object[] funArgs = new Object[size];
               NativeArray parameters = new NativeArray(size);
  @@ -523,13 +534,22 @@
                   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);
               NativeArray funArgsArray = new NativeArray(funArgs);
  +	    Object fun = ScriptableObject.getProperty(thrScope, funName);
  +            if (fun == Scriptable.NOT_FOUND) {
  +                fun = "funName";
  +	    }
               Object callFunArgs[] = { fun, funArgsArray };
  -            ((Function) callFunction).call(context, thrScope, thrScope, callFunArgs);
  +            Object callFun = ScriptableObject.getProperty(thrScope, "callFunction");
  +            if (callFun == Scriptable.NOT_FOUND) {
  +                callFun = "callFunction";
  +	    }
  +            ScriptRuntime.call(context, callFun, thrScope, callFunArgs, thrScope);
           }
           catch (JavaScriptException ex) {
               Context.reportError(ToolErrorReporter.getMessage("msg.uncaughtJSException",
  @@ -565,7 +585,7 @@
           JSWebContinuation jswk = (JSWebContinuation)wk.getUserObject();
           JSCocoon cocoon = jswk.getJSCocoon();
           cocoon.setContext(manager, environment);
  -        final Scriptable kScope = cocoon.getScope();
  +        final Scriptable kScope = cocoon.getParentScope();
   
           if (enableDebugger) {
               debugger.setScopeProvider(
  
  
  
  1.2       +0 -297    cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/system.js
  
  Index: system.js
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/system.js,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- system.js	9 Mar 2003 00:08:51 -0000	1.1
  +++ system.js	17 Mar 2003 00:32:35 -0000	1.2
  @@ -118,301 +118,4 @@
     }
   }
   
  -//
  -// XMLForm Support
  -//
  -
  -/**
  - * Creates a new JavaScript wrapper of a Form object
  - * see org.apache.cocoon.components.xmlform.Form
  - * @param id form id
  - * @param validatorNS Namespace of validator
  - * @param validatorDoc Validator document
  - */
  -
  -function XForm(id, validatorNS, validatorDoc) {
  -    cocoon.createSession();
  -    this.id = id;
  -    this.lastContinuation = null;
  -    XForm.forms[id] = this;
  -    this.validatorNS = validatorNS;
  -    this.validatorDoc = validatorDoc;
  -    this.dead = false;
  -}
  -
  -/**
  - * Global variable that stores XForm instances by id
  - */
  -XForm.forms = {};
  -
  -/**
  - * Return the model object of this form
  - * @return a Java bean, JavaScript, DOM, or JDOM object 
  - */
  -XForm.prototype.getModel = function() {
  -    return this.form.getModel();
  -}
  -
  -/**
  - * Set the model object of this form
  - * @param model Any Java bean, JavaScript, DOM, or JDOM object 
  - */
  -XForm.prototype.setModel = function(model) {
  -    this.form = 
  -       new Packages.org.apache.cocoon.components.xmlform.Form(this.id, 
  -                                                               model);
  -    this.context = 
  -       Packages.org.apache.commons.jxpath.JXPathContext.newContext(model);
  -    this.form.setAutoValidate(false);
  -    if (this.validatorNS != undefined && this.validatorDoc != undefined) {
  -        this._setValidator(this.validatorNS, this.validatorDoc);
  -    }
  -}
  -
  -/**
  - * Creates a new web continuation
  - * @param lastCont previous web continuation
  - * @param timeToLive expiration time for this continuation
  - * @return a new WebContinuation instance
  - */
  -XForm.prototype.start = function(lastCont, timeToLive) {
  -    var k = new Continuation();
  -    var kont = new WebContinuation(cocoon, k, 
  -                                   lastCont, timeToLive);
  -    return kont;
  -} 
  -
  -/**
  - * Adds a violation to this form
  - * @param xpath xpath expression of field that contains invalid data
  - * @param message error message
  - */
  -XForm.prototype.addViolation = function(xpath, message) {
  -    var violation = 
  -       new Packages.org.apache.cocoon.components.validation.Violation();
  -    violation.path = xpath;
  -    violation.message = message;
  -    var list = new java.util.LinkedList();
  -    list.add(violation);
  -    try {
  -        this.form.addViolations(list);
  -    } catch (e) {
  -        print(e);
  -        if (e instanceof java.lang.Throwable) {
  -            e.printStackTrace();
  -        }
  -    }
  -}
  -
  -/**
  - * Computes the value of an xpath expression against the model of this form
  - * @param expr xpath expression
  - * @return result of computing <code>expr</code>
  - */
  -XForm.prototype.getValue = function(expr) {
  -    return this.context.getValue(expr);
  -}
  -
  -/**
  - * Returns an iterator over a nodeset value of an xpath expression evaluated 
  - * against the model of this form
  - * @param expr xpath expression
  - * @return java.util.Iterator representing a nodeset 
  - */
  -XForm.prototype.iterate = function(expr) {
  -    return this.context.iterate(expr);
  -}
  -
  -XForm.prototype._sendView = function(uri, lastCont, timeToLive) {
  -  var k = new Continuation();
  -  var kont = new WebContinuation(cocoon, k, lastCont, timeToLive);
  -  var bizData = this.form.getModel();
  -  if (bizData == undefined) {
  -      bizData = null;
  -  }
  -  cocoon.forwardTo("cocoon://" + cocoon.environment.getURIPrefix() + uri,
  -                   bizData, kont);
  -  this.lastContinuation = kont;
  -  suicide();
  -}
  -
  -/**
  - * Sends view to presentation pipeline and waits for subsequent submission.
  - * Automatically resends view if validation fails.
  - * Creates two continuations: one immediately before the page is sent 
  - * and one immediately after. These are used to implement automated support
  - * for back/forward navigation in the form. When you move forward in the
  - * form the second continuation is invoked. When you move back from the
  - * following page the first continuation is invoked.
  - * @param phase view to send (and phase to validate)
  - * @param uri presentation pipeline resource identifier
  - * @param validator optional function invoked to perform validation
  - */
  -XForm.prototype.sendView = function(phase, uri, validator) {
  -    var lastCont = this.lastContinuation;
  -    this.form.clearViolations();
  -    var view = this.form.getFormView(cocoon.environment.objectModel);
  -    while (true) {
  -        // create a continuation, the invocation of which will resend
  -        // the page: this is used to implement <xf:submit continuation="back">
  -        var k = this.start(lastCont);
  -        if (cocoon.request == null) {
  -            // this continuation has been invalidated
  -            this.dead = true;
  -            handleInvalidContinuation();
  -            suicide();
  -        }
  -        // reset the view in case this is a re-invocation of a continuation
  -        cocoon.request.setAttribute("view", view);
  -        try {
  -            this.form.save(cocoon.environment.objectModel, "request");
  -        } catch (e if (e instanceof java.lang.IllegalStateException)) {
  -            if (cocoon.session.getAttribute(this.id) != null) {
  -                // someone else has taken my session
  -                this.dead = true;
  -                cocoon.removeSession();
  -                handleInvalidContinuation();
  -                suicide();
  -            }
  -            throw e;
  -        }
  -        this._sendView(uri, k);
  -        // _sendView creates a continuation, the invocation of which
  -        // will return right here: it is used to implement 
  -        // <xf:submit continuation="forward">
  -        if (this.dead || cocoon.request == null) {
  -            // this continuation has been invalidated
  -            handleInvalidContinuation();
  -            suicide();
  -        }
  -        this.form.populate(cocoon.environment.objectModel);
  -        if (validator != undefined) {
  -            validator(this);
  -        }
  -        this.form.validate(phase);
  -        if (this.form.violationsAsSortedSet == null ||
  -            this.form.violationsAsSortedSet.size() == 0) {
  -            break;
  -        }
  -    }
  -}
  -
  -XForm.prototype._setValidator = function(schNS, schDoc) {
  -    // if validator params are not specified, then
  -    // there is no validation by default
  -    if (schNS == null || schDoc == null ) return null;
  -    var resolver = cocoon.environment;
  -    var schemaSrc = resolver.resolveURI( schDoc );
  -    try {
  -        var is = Packages.org.apache.cocoon.components.source.SourceUtil.getInputSource(schemaSrc);
  -        var schf = Packages.org.apache.cocoon.components.validation.SchemaFactory.lookup
( schNS );
  -        var sch = schf.compileSchema ( is );
  -        this.form.setValidator(sch.newValidator());
  -    } finally {
  -        resolver.release(schemaSrc);
  -    }
  -}
  -
  -/**
  - * Sends view to presentation pipeline but doesn't wait for submission
  - * @param view view to send
  - * @param uri presentation pipeline uri
  - */
  -
  -XForm.prototype.finish = function(view, uri) {
  -    try {
  -        this.form.save(cocoon.environment.objectModel, "request");
  -    } catch (e if (e instanceof java.lang.IllegalStateException)) {
  -        if (cocoon.session.getAttribute(this.id) != null) {
  -            // someone else has taken my session
  -            this.dead = true;
  -            cocoon.removeSession();
  -            handleInvalidContinuation();
  -            suicide();
  -        }
  -        throw e;
  -    }
  -    cocoon.forwardTo("cocoon://" + cocoon.environment.getURIPrefix() + uri,
  -                     this.form.getModel(), null);
  -    delete XForm.forms[this.id]; // delete myself
  -    this.dead = true;
  -    cocoon.removeSession();
  -    if (this.lastContinuation != null) {
  -        this.lastContinuation.invalidate();
  -        this.lastContinuation = null;
  -    }
  -    
  -}
  -
  -/**
  - * Entry point to a flow-based XMLForm application. Replaces the functionality
  - * of XMLForm actions.
  - * @param application Name of a JavaScript function that represents the page flow for a
form
  - * @param id form id
  - * @param validator_ns XML namespace of validator
  - * @param validator_doc validator document
  - */
  -
  -function xmlForm(application, id, validator_ns, validator_doc) {
  -    if (cocoon.request == null) {
  -        handleInvalidContinuation("");
  -        return;
  -    }
  -    function getCommand() {
  -        var enum_ = cocoon.request.parameterNames;
  -        var command = undefined;
  -        while (enum_.hasMoreElements()) {
  -            var paramName = enum_.nextElement();
  -            // search for the command
  -            if (paramName.startsWith(Packages.org.apache.cocoon.Constants.ACTION_PARAM_PREFIX))
{
  -                command =
  -                    paramName.substring(Packages.org.apache.cocoon.Constants.ACTION_PARAM_PREFIX.length(),
paramName.length());
  -                break;
  -            }
  -        }
  -        // command encodes the continuation id for "back" or "next" actions
  -        return command;
  -    }
  -    var command = getCommand();
  -    if (command != undefined) {
  -        var xform = XForm.forms[id];
  -        if (xform != undefined) {
  -            // invoke a continuation 
  -            var continuationsMgr =
  -                cocoon.componentManager.lookup(Packages.org.apache.cocoon.components.flow.ContinuationsManager.ROLE);
  -            var wk = continuationsMgr.lookupWebContinuation(command);
  -            cocoon.componentManager.release(continuationsMgr);
  -            if (wk != null) {
  -                var jswk = wk.userObject;
  -                xform.form.clearViolations();
  -                jswk.continuation(jswk);
  -            }
  -        }
  -        handleInvalidContinuation(command);
  -        return;
  -    } 
  -    // Just start a new instance of the application
  -    cocoon.session.removeAttribute(id);
  -    this[application](new XForm(id, validator_ns, validator_doc));
  -}
  -
  -//
  -// Prototype Database API
  -//
  -// TBD: Move this Database stuff to its own library outside of flow
  -//
  -
  -defineClass("org.apache.cocoon.components.flow.javascript.ScriptableConnection");
  -defineClass("org.apache.cocoon.components.flow.javascript.ScriptableResult");
  -
  -Database.getConnection = function(selectorValue) {
  -    var selector = cocoon.componentManager.lookup(Packages.org.apache.avalon.excalibur.datasource.DataSourceComponent.ROLE
+ "Selector");
  -    try {
  -	var ds = selector.select(selectorValue);
  -	return new Database(ds.getConnection());
  -    } finally {
  -	cocoon.componentManager.release(selector);
  -    }
  -}
  -
   
  
  
  
  1.1                  cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/Database.js
  
  Index: Database.js
  ===================================================================
  //
  // Prototype Database API
  //
  // TBD: Move this Database stuff to its own library outside of flow
  //
  
  defineClass("org.apache.cocoon.components.flow.javascript.ScriptableConnection");
  defineClass("org.apache.cocoon.components.flow.javascript.ScriptableResult");
  
  Database.getConnection = function(selectorValue) {
      var selector = cocoon.componentManager.lookup(Packages.org.apache.avalon.excalibur.datasource.DataSourceComponent.ROLE
+ "Selector");
      try {
  	var ds = selector.select(selectorValue);
  	return new Database(ds.getConnection());
      } finally {
  	cocoon.componentManager.release(selector);
      }
  }
  
  
  
  
  
  1.1                  cocoon-2.1/src/java/org/apache/cocoon/components/flow/javascript/xmlForm.js
  
  Index: xmlForm.js
  ===================================================================
  //
  // XMLForm Support
  //
  
  /**
   * Creates a new JavaScript wrapper of a Form object
   * see org.apache.cocoon.components.xmlform.Form
   * @param id [String] unique form id
   * @param validatorNS [String] Namespace of validator
   * @param validatorDoc [String] Validator document
   * @param scope [String] either "request" or "session"
   */
  
  function XForm(id, validatorNS, validatorDoc, scope) {
      if (scope == "session") {
  	cocoon.createSession();
      }
      this.id = id;
      this.lastContinuation = null;
      XForm.forms[id] = this;
      this.validatorNS = validatorNS;
      this.validatorDoc = validatorDoc;
      this.dead = false;
  }
  
  /**
   * Global variable that stores XForm instances by id
   */
  XForm.forms = {};
  
  /**
   * Return the model object of this form
   * @return a Java bean, JavaScript, DOM, or JDOM object 
   */
  XForm.prototype.getModel = function() {
      return this.form.getModel();
  }
  
  /**
   * Set the model object of this form
   * @param model [Object] Any Java bean, JavaScript, DOM, or JDOM object 
   */
  XForm.prototype.setModel = function(model) {
      this.form = 
         new Packages.org.apache.cocoon.components.xmlform.Form(this.id, 
                                                                 model);
      this.context = 
         Packages.org.apache.commons.jxpath.JXPathContext.newContext(model);
      this.form.setAutoValidate(false);
      if (this.validatorNS != undefined && this.validatorDoc != undefined) {
          this._setValidator(this.validatorNS, this.validatorDoc);
      }
  }
  
  /**
   * Creates a new web continuation
   * @param lastCont [WebContinuation] previous web continuation
   * @param timeToLive [Number] expiration time for this continuation in milliseconds
   * @return [WebContinuation] a new WebContinuation instance
   */
  XForm.prototype.start = function(lastCont, timeToLive) {
      var k = new Continuation();
      var kont = new WebContinuation(cocoon, k, 
                                     lastCont, timeToLive);
      return kont;
  } 
  
  /**
   * Adds a violation to this form
   * @param xpath [String] xpath location of field that contains invalid data
   * @param message [String] error message
   */
  XForm.prototype.addViolation = function(xpath, message) {
      var violation = 
         new Packages.org.apache.cocoon.components.validation.Violation();
      violation.path = xpath;
      violation.message = message;
      var list = new java.util.LinkedList();
      list.add(violation);
      try {
          this.form.addViolations(list);
      } catch (e) {
          print(e);
          if (e instanceof java.lang.Throwable) {
              e.printStackTrace();
          }
      }
  }
  
  /**
   * Computes the value of an xpath expression against the model of this form
   * @param expr [String] xpath expression
   * @return [Object] result of computing <code>expr</code>
   */
  XForm.prototype.getValue = function(expr) {
      return this.context.getValue(expr);
  }
  
  /**
   * Returns an iterator over a nodeset value of an xpath expression evaluated 
   * against the model of this form
   * @param expr [String] xpath expression
   * @return [java.util.Iterator] representing a nodeset 
   */
  XForm.prototype.iterate = function(expr) {
      return this.context.iterate(expr);
  }
  
  XForm.prototype._sendView = function(uri, lastCont, timeToLive) {
    var k = new Continuation();
    var kont = new WebContinuation(cocoon, k, lastCont, timeToLive);
    var bizData = this.form.getModel();
    if (bizData == undefined) {
        bizData = null;
    }
    cocoon.forwardTo("cocoon://" + cocoon.environment.getURIPrefix() + uri,
                     bizData, kont);
    this.lastContinuation = kont;
    suicide();
  }
  
  /**
   * Sends view to presentation pipeline and waits for subsequent submission.
   * Automatically resends view if validation fails.
   * Creates two continuations: one immediately before the page is sent 
   * and one immediately after. These are used to implement automated support
   * for back/forward navigation in the form. When you move forward in the
   * form the second continuation is invoked. When you move back from the
   * following page the first continuation is invoked.
   * @param phase [String] phase to validate
   * @param uri [String] presentation pipeline resource identifier of view
   * @param validator [Function] optional function invoked to perform validation
   */
  XForm.prototype.sendView = function(phase, uri, validator) {
      var lastCont = this.lastContinuation;
      this.form.clearViolations();
      var view = this.form.getFormView(cocoon.environment.objectModel);
      while (true) {
          // create a continuation, the invocation of which will resend
          // the page: this is used to implement <xf:submit continuation="back">
          var k = this.start(lastCont);
          if (cocoon.request == null) {
              // this continuation has been invalidated
              this.dead = true;
              handleInvalidContinuation();
              suicide();
          }
          // reset the view in case this is a re-invocation of a continuation
          cocoon.request.setAttribute("view", view);
          try {
              this.form.save(cocoon.environment.objectModel, "request");
          } catch (e if (e instanceof java.lang.IllegalStateException)) {
              if (cocoon.session.getAttribute(this.id) != null) {
                  // someone else has taken my session
                  this.dead = true;
                  handleInvalidContinuation();
                  suicide();
              }
              throw e;
          }
          this._sendView(uri, k);
          // _sendView creates a continuation, the invocation of which
          // will return right here: it is used to implement 
          // <xf:submit continuation="forward">
          if (this.dead || cocoon.request == null) {
              // this continuation has been invalidated
              handleInvalidContinuation();
              suicide();
          }
          this.form.populate(cocoon.environment.objectModel);
          if (validator != undefined) {
              validator(this);
          }
          this.form.validate(phase);
          if (this.form.violationsAsSortedSet == null ||
              this.form.violationsAsSortedSet.size() == 0) {
              break;
          }
      }
  }
  
  XForm.prototype._setValidator = function(schNS, schDoc) {
      // if validator params are not specified, then
      // there is no validation by default
      if (schNS == null || schDoc == null ) return null;
      var resolver = cocoon.environment;
      var schemaSrc = resolver.resolveURI( schDoc );
      try {
          var is = Packages.org.apache.cocoon.components.source.SourceUtil.getInputSource(schemaSrc);
          var schf = Packages.org.apache.cocoon.components.validation.SchemaFactory.lookup
( schNS );
          var sch = schf.compileSchema ( is );
          this.form.setValidator(sch.newValidator());
      } finally {
          resolver.release(schemaSrc);
      }
  }
  
  /**
   * Sends view to presentation pipeline but doesn't wait for submission
   * @param uri [String] presentation pipeline uri
   */
  
  XForm.prototype.finish = function(uri) {
      try {
          this.form.save(cocoon.environment.objectModel, "request");
      } catch (e if (e instanceof java.lang.IllegalStateException)) {
          if (cocoon.session.getAttribute(this.id) != null) {
              // someone else has taken my session
              this.dead = true;
              handleInvalidContinuation();
              suicide();
          }
          throw e;
      }
      cocoon.forwardTo("cocoon://" + cocoon.environment.getURIPrefix() + uri,
                       this.form.getModel(), null);
      delete XForm.forms[this.id]; // delete myself
      this.dead = true;
      if (this.lastContinuation != null) {
          this.lastContinuation.invalidate();
          this.lastContinuation = null;
      }
      
  }
  
  /**
   * Entry point to a flow-based XMLForm application. Replaces the functionality
   * of XMLForm actions.
   * @param application Name of a JavaScript function that represents the page flow for a
form
   * @param id form id
   * @param validator_ns XML namespace of validator
   * @param validator_doc validator document
   * @param scope 
   */
  
  function xmlForm(application, id, validator_ns, validator_doc, scope) {
      if (cocoon.request == null) {
          handleInvalidContinuation("");
          return;
      }
      function getCommand() {
          var enum_ = cocoon.request.parameterNames;
          var command = undefined;
          while (enum_.hasMoreElements()) {
              var paramName = enum_.nextElement();
              // search for the command
              if (paramName.startsWith(Packages.org.apache.cocoon.Constants.ACTION_PARAM_PREFIX))
{
                  command =
                      paramName.substring(Packages.org.apache.cocoon.Constants.ACTION_PARAM_PREFIX.length(),
paramName.length());
                  break;
              }
          }
          // command encodes the continuation id for "back" or "next" actions
          return command;
      }
      var command = getCommand();
      if (command != undefined) {
          var xform = XForm.forms[id];
          if (xform != undefined) {
              // invoke a continuation 
              var continuationsMgr =
                  cocoon.componentManager.lookup(Packages.org.apache.cocoon.components.flow.ContinuationsManager.ROLE);
              var wk = continuationsMgr.lookupWebContinuation(command);
              cocoon.componentManager.release(continuationsMgr);
              if (wk != null) {
                  var jswk = wk.userObject;
                  xform.form.clearViolations();
                  jswk.continuation(jswk);
              }
          }
          handleInvalidContinuation(command);
          return;
      } 
      // Just start a new instance of the application
      cocoon.session.removeAttribute(id);
      var args = new Array(arguments.length - 4 + 1);
      args[0] = new XForm(id, validator_ns, validator_doc, scope);
      for (var i = 4; i < arguments.length; i++) {
  	args[i-3] = arguments[i];
      }
      this[application].apply(this, args);
  }
  
  
  

Mime
View raw message