I spent an afternoon implementing it. It's a complicated beast, and it uses the intercepted flowscript in a big huge ugly hack... BUT... it works, which makes me happy :) Check it out at [1] -- please go easy on it since this is my personal box at home and on my cablemodem. I will clean it up and add it to the samples once I get my CVS problems straightened out.
very cool ...but why was the intercepted flowscript necessary here?
To be honest, I couldn't get it to work with "regular" FS, so I used a brute force way of getting it to work. It's ugly, and there's probably a simpler way of doing it -- in fact... PLEASE find a better way of doing it :)
Let me see if I can explain, since I don't have my code here with me right now.
<map:match pattern=""> <map:call function="main"/> </map:match>
function main() { var secret = generateSecret();
while (true) { cocoon.sendPageAndWait("main");
if (cocoon.request.get("secret") == secret) { break; }
cocoon.sendPage("success"); } }
The problem comes in when we need to generate an image based off the same continuation ID that we get from the first sendPageAndWait. For instance, say we have the following pipeline to generate an image, and we want the requested image to actually be the continuation ID.
<map:match pattern="auth/*.jpg"> <map:call continuation="{1}"/> </map:match>
Ok, simple enough, but then the problem is that once we jump back into the continuation (which is the same as the one we get from the first sendPageAndWait), how do we know that we should be serving an image instead of letting the loop continue? If we use intercepted flow, we can check for this.
Changing the above snippet to:
<map:match pattern="auth/*.jpg"> <map:call continuation="{1}"> <!-- bigass hack --> <map:parameter name="msg" value="doImage"/> </map:call> </map:match>
Then we write the interceptions for the main() method above:
// callbacks.js function main() { continueExecution(): { if (cocoon.parameters.msg == "doImage") { cocoon.sendPage("internal/" + secret + ".jpg"); } } }
This is probably breaking some sort of good design practice... it's already approaching spaghetti code status ;)
Anyway, whenever the continuation is restarted, continueExecution() is run, and we obviously check to see if we're getting a parameter named msg with a value of doImage, and if so, we sendPage to a secret url that actually generates the image:
<!-- this would most likely be in an internal-only pipeline -->
<map:match pattern="internal/*.jpg"> <map:generate src="docs/foo.xml"/> <map:transform src="xslt/foo2svg.xsl"> <map:parameter name="secret" value="{1}"/> </map:transform> <map:serialize type="svg2jpeg"/> </map:match>
Pretty self-explanatory... here we just pass the wildcard match to the XSLT which in turn adds the appropriate <svg:text> element with the secret code. There's a lot of little details missing here since I don't have all the stuff in front of me. There has to be a much much simpler way of doing this, while also obscuring the URL of the image to generate. Using continuation ID's seemed the most straightforward way to me, but it ended up also being quite complex.
Regards,
Tony