vgritsenko 2003/05/07 17:05:05
Modified: . status.xml src/java/org/apache/cocoon/components/flow TODO src/java/org/apache/cocoon/components/flow/javascript JSCocoon.java JavaScriptInterpreter.java system.js src/webapp sitemap.xmap welcome.xslt src/webapp/samples sitemap.xmap src/webapp/samples/flow sitemap.xmap Added: src/java/org/apache/cocoon/components/flow InvalidContinuationException.java Removed: src/webapp/samples/flow invalidContinuation.xml Log: Fix Bug #19526: Throw InvalidContinuationException instead of redirecting. Change welcome.xslt - add contextPath parameter to properly render error page (not-found.xml) Add InvalidContinuationException handler to the main sitemap. Revision Changes Path 1.26 +4 -0 cocoon-2.1/status.xml Index: status.xml =================================================================== RCS file: /home/cvs/cocoon-2.1/status.xml,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- status.xml 7 May 2003 21:20:04 -0000 1.25 +++ status.xml 8 May 2003 00:05:04 -0000 1.26 @@ -191,6 +191,10 @@ <changes> <release version="@version@" date="@date@"> + <action dev="VG" type="fix" fixes-bug="19526" due-to="Tony Collen" due-to-email="[EMAIL PROTECTED]"> + Throw InvalidContinuationException when flow continuation is not found or not valid, + instead of forwarding to hard-coded 'invalidContinuation' page. + </action> <action dev="CZ" type="fix" fixes-bug="14564"> Fixing NPE in JspEngineImpl. </action> 1.2 +1 -0 cocoon-2.1/src/java/org/apache/cocoon/components/flow/TODO Index: TODO =================================================================== RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/components/flow/TODO,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TODO 9 Mar 2003 00:08:49 -0000 1.1 +++ TODO 8 May 2003 00:05:04 -0000 1.2 @@ -16,6 +16,7 @@ - [ADVANCED] implement leaky bucket algorithm or similar to protect the server from creating too many continuations. + -- Try o.a.cocoon.util.MRUBucketMap - [ADVANCED] define a boolean parameter, to be set in either cocoon.xconf or web.xml, that specifies that session affinity is to be 1.1 cocoon-2.1/src/java/org/apache/cocoon/components/flow/InvalidContinuationException.java Index: InvalidContinuationException.java =================================================================== /* ============================================================================ 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. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi <[EMAIL PROTECTED]>. For more information on the Apache Software Foundation, please see <http://www.apache.org/>. */ package org.apache.cocoon.components.flow; import org.apache.cocoon.ProcessingException; /** * This Exception is thrown whenever an invalid continuation is given. * * @author <a href="mailto:[EMAIL PROTECTED]">Tony Collen</a> * @version CVS $Id: InvalidContinuationException.java,v 1.1 2003/05/08 00:05:04 vgritsenko Exp $ */ public class InvalidContinuationException extends ProcessingException { /** * Construct a new <code>InvalidContinuationException</code> instance. */ public InvalidContinuationException(String message) { super(message, null); } /** * Construct a new <code>InvalidContinuationException</code> that references * a parent Exception. */ public InvalidContinuationException(String message, Throwable t) { super(message, t); } } 1.11 +10 -10 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.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- JSCocoon.java 7 May 2003 04:36:33 -0000 1.10 +++ JSCocoon.java 8 May 2003 00:05:04 -0000 1.11 @@ -269,21 +269,21 @@ } /** - Set the Scope object in the session object of the current - user. This effectively means that at the next invocation from the - sitemap of a JavaScript function (using the <map:call - function="...">), will obtain the same scope as the current - one. - */ + * Set the Scope object in the session object of the current + * user. This effectively means that at the next invocation from the + * sitemap of a JavaScript function (using the <map:call + * function="...">), will obtain the same scope as the current + * one. + */ public void jsFunction_createSession() { interpreter.setSessionScope(environment, getParentScope()); } /** - Remove the Scope object from the session object of the current - user. - */ + * Remove the Scope object from the session object of the current + * user. + */ public void jsFunction_removeSession() { interpreter.removeSessionScope(environment); 1.19 +48 -34 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.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- JavaScriptInterpreter.java 7 May 2003 04:36:33 -0000 1.18 +++ JavaScriptInterpreter.java 8 May 2003 00:05:04 -0000 1.19 @@ -59,8 +59,10 @@ 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; @@ -98,7 +100,7 @@ /** * LAST_EXEC_TIME - * A long value is stored under this key in each top level JavaScript + * 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. @@ -151,7 +153,7 @@ } public Script getScript(Context context, Scriptable scope, - boolean refresh) + boolean refresh) throws Exception { if (refresh) { source.refresh(); @@ -182,15 +184,15 @@ 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.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.setExitAction(new Runnable() { + public void run() { + db.setVisible(false); + } }); db.setOptimizationLevel(OPTIMIZATION_LEVEL); db.setVisible(true); @@ -322,7 +324,7 @@ userScopes = new HashMap(); session.setAttribute(USER_GLOBAL_SCOPE, userScopes); } - + String uriPrefix = environment.getURIPrefix(); userScopes.put(uriPrefix, scope); } @@ -440,13 +442,13 @@ } needResolve.clear(); } - thrScope.put(LAST_EXEC_TIME, thrScope, + 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 entry = (ScriptSourceEntry)compiledScripts.get(sourceURI); if (entry == null) { Source src = environment.resolveURI(sourceURI); @@ -459,13 +461,13 @@ // Execute the scripts if necessary for (int i = 0, size = execList.size(); i < size; i++) { String sourceURI = (String)execList.get(i); - ScriptSourceEntry entry = + 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; @@ -479,7 +481,7 @@ protected void exitContext(Scriptable thrScope) { // thrScope may be null if an exception occurred compiling a script - if (thrScope != null) { + if (thrScope != null) { JSCocoon cocoon = (JSCocoon)thrScope.get("cocoon", thrScope); cocoon.invalidateContext(); } @@ -495,21 +497,21 @@ * @return compiled script */ - public Script compileScript(Context cx, - Environment environment, + 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 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; } @@ -523,11 +525,11 @@ } Reader reader = new BufferedReader(new InputStreamReader(is)); Script compiledScript = cx.compileReader(scope, reader, - src.getURI(), + 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 @@ -581,13 +583,17 @@ } catch (JavaScriptException ex) { EvaluatorException ee = Context.reportRuntimeError(ToolErrorReporter.getMessage("msg.uncaughtJSException", - ex.getMessage())); - throw new CascadingRuntimeException(ee.getMessage(), unwrap(ex)); + 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, + Context.reportRuntimeError(msg, ee.getSourceName(), ee.getLineNumber(), ee.getLineSource(), @@ -608,10 +614,12 @@ WebContinuation wk = continuationsMgr.lookupWebContinuation(id); if (wk == null) { - List p = new ArrayList(); - p.add(new Interpreter.Argument("kontId", id)); - callFunction("handleInvalidContinuation", p, environment); - return; + + /* + * 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(); @@ -633,9 +641,10 @@ // We can now resume the processing from the state saved by the // continuation object. Setup the JavaScript Context object. Object handleContFunction = kScope.get("handleContinuation", kScope); - if (handleContFunction == Scriptable.NOT_FOUND) + if (handleContFunction == Scriptable.NOT_FOUND) { throw new RuntimeException("Cannot find 'handleContinuation' " + "(system.js not loaded?)"); + } Object args[] = { jswk }; @@ -654,14 +663,19 @@ try { ((Function)handleContFunction).call(context, kScope, kScope, args); } catch (JavaScriptException ex) { - EvaluatorException ee = + EvaluatorException ee = Context.reportRuntimeError(ToolErrorReporter.getMessage("msg.uncaughtJSException", ex.getMessage())); - throw new CascadingRuntimeException(ee.getMessage(), unwrap(ex)); + 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, + Context.reportRuntimeError(msg, ee.getSourceName(), ee.getLineNumber(), ee.getLineSource(), @@ -674,7 +688,7 @@ Context.exit(); } } - + private Throwable unwrap(JavaScriptException e) { Object value = e.getValue(); while (value instanceof Wrapper) { @@ -692,10 +706,10 @@ throws Exception { Map objectModel = environment.getObjectModel(); // Make the live-connect objects available to the view layer - JavaScriptFlow.setPackages(objectModel, + JavaScriptFlow.setPackages(objectModel, (Scriptable)ScriptableObject.getProperty(scope, "Packages")); - JavaScriptFlow.setJavaPackage(objectModel, + JavaScriptFlow.setJavaPackage(objectModel, (Scriptable)ScriptableObject.getProperty(scope, "java")); super.forwardTo(uri, bizData, continuation, environment); 1.6 +3 -3 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.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- system.js 4 Apr 2003 23:08:13 -0000 1.5 +++ system.js 8 May 2003 00:05:04 -0000 1.6 @@ -60,7 +60,8 @@ // identified by 'id' function handleInvalidContinuation(id) { - sendPage("invalidContinuation", {"ident" : id}); + // Throw an exception which can be handled in sitemap's handle-error section + throw new Packages.org.apache.cocoon.components.flow.InvalidContinuationException("Continuation ID + " + id + " is invalid"); } // Redirect Support @@ -126,5 +127,4 @@ cocoon.outputModuleRollback(type); } } - 1.14 +22 -11 cocoon-2.1/src/webapp/sitemap.xmap Index: sitemap.xmap =================================================================== RCS file: /home/cvs/cocoon-2.1/src/webapp/sitemap.xmap,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- sitemap.xmap 6 May 2003 07:10:50 -0000 1.13 +++ sitemap.xmap 8 May 2003 00:05:04 -0000 1.14 @@ -199,10 +199,11 @@ +--> <map:selector logger="sitemap.selector.exception" name="exception" src="org.apache.cocoon.selection.ExceptionSelector"> <exception name="not-found" class="org.apache.cocoon.ResourceNotFoundException"/> + <exception name="invalid-continuation" class="org.apache.cocoon.components.flow.InvalidContinuationException"/> <!-- The statement below tells the selector to unroll as much exceptions as possible --> <exception class="java.lang.Throwable" unroll="true"/> </map:selector> - + <map:selector logger="sitemap.selector.request-parameter" name="request-parameter" src="org.apache.cocoon.selection.RequestParameterSelector"> <!-- Define now which request parameter to use; or do it later, @@ -399,7 +400,9 @@ | and sending the output down the pipeline to be processed by the | next stage. +--> - <map:transform src="welcome.xslt"/> + <map:transform src="welcome.xslt"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + </map:transform> <!--+ | The serializer concludes the SAX events journey into the pipeline @@ -496,7 +499,7 @@ <map:match pattern="*/**"> <map:mount check-reload="yes" src="{1}/" uri-prefix="{1}"/> </map:match> - + <!--+ | At the very end of a pipeline, you can catch the errors triggered | by the pipeline execution. The error handler is an internal sitemap @@ -511,25 +514,33 @@ +--> <map:handle-errors> <map:select type="exception"> - + <map:when test="not-found"> <map:generate src="not-found.xml"/> - <map:transform src="welcome.xslt"/> + <map:transform src="welcome.xslt"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + </map:transform> </map:when> - + + <map:when test="invalid-continuation"> + <map:generate src="not-found.xml"/> + <map:transform src="welcome.xslt"> + <map:parameter name="contextPath" value="{request:contextPath}"/> + </map:transform> + </map:when> + <map:otherwise> <map:generate type="notifying"/> <map:transform src="stylesheets/system/error2html.xslt"> <map:parameter name="contextPath" value="{request:contextPath}"/> - </map:transform> + </map:transform> </map:otherwise> </map:select> - + <map:serialize/> - </map:handle-errors> - </map:pipeline> + </map:pipeline> </map:pipelines> </map:sitemap> 1.7 +5 -3 cocoon-2.1/src/webapp/welcome.xslt Index: welcome.xslt =================================================================== RCS file: /home/cvs/cocoon-2.1/src/webapp/welcome.xslt,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- welcome.xslt 29 Mar 2003 01:08:38 -0000 1.6 +++ welcome.xslt 8 May 2003 00:05:04 -0000 1.7 @@ -4,6 +4,8 @@ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:param name="contextPath" select="'/cocoon'"/> + <xsl:template match="welcome"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> @@ -17,7 +19,7 @@ stream --> <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8"/> - <link href="styles/main.css" type="text/css" rel="stylesheet"/> + <link href="{$contextPath}/styles/main.css" type="text/css" rel="stylesheet"/> <link href="favicon.ico" rel="SHORTCUT ICON" /> </head> <body> @@ -27,7 +29,7 @@ Copyright © @year@ <a href="http://www.apache.org/">The Apache Software Foundation</a>. All rights reserved. </p> <p class="block"> - <a href="http://cocoon.apache.org/"><img src="images/powered.gif" alt="Powered by Apache Cocoon"/></a> + <a href="http://cocoon.apache.org/"><img src="{$contextPath}/images/powered.gif" alt="Powered by Apache Cocoon"/></a> </p> </body> </html> 1.12 +4 -8 cocoon-2.1/src/webapp/samples/sitemap.xmap Index: sitemap.xmap =================================================================== RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/sitemap.xmap,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- sitemap.xmap 30 Mar 2003 12:48:32 -0000 1.11 +++ sitemap.xmap 8 May 2003 00:05:05 -0000 1.12 @@ -26,7 +26,6 @@ <!-- =========================== Views =================================== --> <map:views> - <map:view name="content" from-label="content"> <map:serialize type="xml"/> </map:view> @@ -39,13 +38,11 @@ <map:view name="links" from-position="last"> <map:serialize type="links"/> </map:view> - </map:views> <!-- =========================== Pipelines ================================= --> <map:pipelines> - <map:pipeline> <map:match pattern=""> @@ -155,15 +152,14 @@ <map:generate src="error-giving-page.xml"/> <map:serialize/> </map:match> - + <!-- ======================== Automount =============================== --> - + <map:match pattern="*/**"> <map:mount uri-prefix="{1}" src="{1}/" check-reload="yes"/> </map:match> - + </map:pipeline> - </map:pipelines> </map:sitemap> 1.7 +7 -3 cocoon-2.1/src/webapp/samples/flow/sitemap.xmap Index: sitemap.xmap =================================================================== RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/flow/sitemap.xmap,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- sitemap.xmap 26 Mar 2003 21:21:43 -0000 1.6 +++ sitemap.xmap 8 May 2003 00:05:05 -0000 1.7 @@ -1,9 +1,10 @@ <?xml version="1.0"?> +<!-- CVS $Id$ --> + <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> <map:pipelines> - <map:pipeline> <map:match pattern=""> @@ -14,12 +15,15 @@ <map:serialize/> </map:match> + <map:match pattern="*"> + <map:redirect-to uri="{1}/"/> + </map:match> + <map:match pattern="*/**"> <map:mount uri-prefix="{1}" src="{1}/" check-reload="yes"/> </map:match> - + </map:pipeline> - </map:pipelines> </map:sitemap>