KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > flow > javascript > fom > FOM_Cocoon


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.flow.javascript.fom;
17
18 import java.beans.IntrospectionException JavaDoc;
19 import java.beans.Introspector JavaDoc;
20 import java.beans.PropertyDescriptor JavaDoc;
21 import java.io.OutputStream JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Enumeration JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Set JavaDoc;
31
32 import org.apache.avalon.framework.CascadingRuntimeException;
33 import org.apache.avalon.framework.component.WrapperComponentManager;
34 import org.apache.avalon.framework.context.Context;
35 import org.apache.avalon.framework.context.ContextException;
36 import org.apache.avalon.framework.logger.Logger;
37 import org.apache.avalon.framework.service.ServiceManager;
38 import org.apache.cocoon.components.ContextHelper;
39 import org.apache.cocoon.components.LifecycleHelper;
40 import org.apache.cocoon.components.flow.ContinuationsManager;
41 import org.apache.cocoon.components.flow.WebContinuation;
42 import org.apache.cocoon.components.flow.Interpreter.Argument;
43 import org.apache.cocoon.environment.ObjectModelHelper;
44 import org.apache.cocoon.environment.Redirector;
45 import org.apache.cocoon.environment.Request;
46 import org.apache.cocoon.environment.Response;
47 import org.apache.cocoon.environment.Session;
48 import org.apache.cocoon.util.ClassUtils;
49 import org.mozilla.javascript.JavaScriptException;
50 import org.mozilla.javascript.NativeJavaClass;
51 import org.mozilla.javascript.NativeJavaObject;
52 import org.mozilla.javascript.Script;
53 import org.mozilla.javascript.Scriptable;
54 import org.mozilla.javascript.ScriptableObject;
55 import org.mozilla.javascript.Undefined;
56 import org.mozilla.javascript.Wrapper;
57 import org.mozilla.javascript.continuations.Continuation;
58
59 /**
60  * Implementation of FOM (Flow Object Model).
61  *
62  * @since 2.1
63  * @author <a HREF="mailto:coliver.at.apache.org">Christopher Oliver</a>
64  * @author <a HREF="mailto:reinhard.at.apache.org">Reinhard Pötz</a>
65  * @version CVS $Id: FOM_Cocoon.java 158581 2005-03-22 09:16:17Z cziegeler $
66  */

67 public class FOM_Cocoon extends ScriptableObject {
68
69     class CallContext {
70         CallContext caller;
71         Context avalonContext;
72         ServiceManager serviceManager;
73         FOM_JavaScriptInterpreter interpreter;
74         Redirector redirector;
75         Logger logger;
76         Scriptable request;
77         Scriptable response;
78         Scriptable session;
79         Scriptable context;
80         Scriptable parameters;
81         Scriptable log;
82         WebContinuation lastContinuation;
83         FOM_WebContinuation fwk;
84         PageLocalScopeImpl currentPageLocal;
85
86         public CallContext(CallContext caller,
87                            FOM_JavaScriptInterpreter interp,
88                            Redirector redirector,
89                            ServiceManager manager,
90                            Context avalonContext,
91                            Logger logger,
92                            WebContinuation lastContinuation) {
93             this.caller = caller;
94             this.interpreter = interp;
95             this.redirector = redirector;
96             this.serviceManager = manager;
97             this.avalonContext = avalonContext;
98             this.logger = logger;
99             this.lastContinuation = lastContinuation;
100             if (lastContinuation != null) {
101                 fwk = new FOM_WebContinuation(lastContinuation);
102                 Scriptable scope = FOM_Cocoon.this.getParentScope();
103                 fwk.setParentScope(scope);
104                 fwk.setPrototype(getClassPrototype(scope, fwk.getClassName()));
105                 this.currentPageLocal = fwk.getPageLocal();
106             }
107             if (this.currentPageLocal != null) {
108                 // "clone" the page local scope
109
this.currentPageLocal = this.currentPageLocal.duplicate();
110             } else {
111                 this.currentPageLocal = new PageLocalScopeImpl(getTopLevelScope(FOM_Cocoon.this));
112             }
113             pageLocal.setDelegate(this.currentPageLocal);
114         }
115
116         public FOM_WebContinuation getLastContinuation() {
117             return fwk;
118         }
119
120         public void setLastContinuation(FOM_WebContinuation fwk) {
121             this.fwk = fwk;
122             if (fwk != null) {
123                 pageLocal.setDelegate(fwk.getPageLocal());
124                 this.lastContinuation = fwk.getWebContinuation();
125             } else {
126                 this.lastContinuation = null;
127             }
128         }
129
130         public Scriptable getSession() {
131             if (session != null) {
132                 return session;
133             }
134             Map JavaDoc objectModel = ContextHelper.getObjectModel(this.avalonContext);
135             session = new FOM_Session(
136                     getParentScope(),
137                     ObjectModelHelper.getRequest(objectModel).getSession(true));
138             return session;
139         }
140
141         public Scriptable getRequest() {
142             if (request != null) {
143                 return request;
144             }
145             Map JavaDoc objectModel = ContextHelper.getObjectModel(this.avalonContext);
146             request = new FOM_Request(
147                     getParentScope(),
148                     ObjectModelHelper.getRequest(objectModel));
149             return request;
150         }
151
152         public Scriptable getContext() {
153             if (context != null) {
154                 return context;
155             }
156             Map JavaDoc objectModel = ContextHelper.getObjectModel(this.avalonContext);
157             context = new FOM_Context(
158                     getParentScope(),
159                     ObjectModelHelper.getContext(objectModel));
160             return context;
161         }
162
163         public Scriptable getResponse() {
164             if (response != null) {
165                 return response;
166             }
167             Map JavaDoc objectModel = ContextHelper.getObjectModel(this.avalonContext);
168             response = org.mozilla.javascript.Context.toObject(
169                     ObjectModelHelper.getResponse(objectModel),
170                     getParentScope());
171             return response;
172         }
173
174         public Scriptable getLog() {
175             if (log != null) {
176                 return log;
177             }
178             log = org.mozilla.javascript.Context.toObject(logger, getParentScope());
179             return log;
180         }
181
182         public Scriptable getParameters() {
183             return parameters;
184         }
185
186         public void setParameters(Scriptable parameters) {
187             this.parameters = parameters;
188         }
189     }
190
191     private CallContext currentCall;
192     protected PageLocalScopeHolder pageLocal;
193
194     public String JavaDoc getClassName() {
195         return "FOM_Cocoon";
196     }
197
198
199     // Called by FOM_JavaScriptInterpreter
200
static void init(Scriptable scope) throws Exception JavaDoc {
201         //FIXME(SW) what is the exact purpose of defineClass() ??
202
defineClass(scope, FOM_Cocoon.class);
203 // defineClass(scope, FOM_Request.class);
204
// defineClass(scope, FOM_Response.class);
205
// defineClass(scope, FOM_Cookie.class);
206
// defineClass(scope, FOM_Session.class);
207
// defineClass(scope, FOM_Context.class);
208
// defineClass(scope, FOM_Log.class);
209
defineClass(scope, FOM_WebContinuation.class);
210         defineClass(scope, PageLocalImpl.class);
211     }
212
213     void pushCallContext(FOM_JavaScriptInterpreter interp,
214                          Redirector redirector,
215                          ServiceManager manager,
216                          Context avalonContext,
217                          Logger logger,
218                          WebContinuation lastContinuation) {
219         if (pageLocal == null) {
220             pageLocal = new PageLocalScopeHolder(getTopLevelScope(this));
221         }
222         
223         // The call context will use the current sitemap's service manager when looking up components
224
ServiceManager sitemapManager;
225         try {
226             sitemapManager = (ServiceManager)avalonContext.get(ContextHelper.CONTEXT_SITEMAP_SERVICE_MANAGER);
227         } catch (ContextException e) {
228             throw new CascadingRuntimeException("Cannot get sitemap service manager", e);
229         }
230
231         this.currentCall = new CallContext(currentCall, interp, redirector, sitemapManager,
232                                            avalonContext,
233                                            logger, lastContinuation);
234     }
235
236     void popCallContext() {
237         // Clear the scope attribute
238
FOM_JavaScriptFlowHelper.setFOM_FlowScope(this.getObjectModel(), null);
239
240         this.currentCall = this.currentCall.caller;
241         // reset current page locals
242
if (this.currentCall != null) {
243             pageLocal.setDelegate(this.currentCall.currentPageLocal);
244         } else {
245             pageLocal.setDelegate(null);
246         }
247     }
248
249
250     public FOM_WebContinuation jsGet_continuation() {
251         // FIXME: This method can return invalid continuation! Is it OK to do so?
252
return currentCall.getLastContinuation();
253     }
254
255     public void jsSet_continuation(Object JavaDoc obj) {
256         FOM_WebContinuation fwk = (FOM_WebContinuation)unwrap(obj);
257         currentCall.setLastContinuation(fwk);
258     }
259
260     public FOM_WebContinuation jsFunction_sendPage(String JavaDoc uri,
261                                                    Object JavaDoc obj,
262                                                    Object JavaDoc wk)
263         throws Exception JavaDoc {
264         FOM_WebContinuation fom_wk = (FOM_WebContinuation)unwrap(wk);
265         if (fom_wk != null) {
266             // save page locals
267
fom_wk.setPageLocal(pageLocal.getDelegate());
268         }
269         forwardTo(uri, unwrap(obj), fom_wk);
270         return fom_wk;
271     }
272
273     public Scriptable jsFunction_createPageLocal() {
274         return pageLocal.createPageLocal();
275     }
276
277     public void jsFunction_processPipelineTo(String JavaDoc uri,
278                                              Object JavaDoc map,
279                                              Object JavaDoc outputStream)
280     throws Exception JavaDoc {
281         Object JavaDoc out = unwrap(outputStream);
282         if (!(out instanceof OutputStream JavaDoc)) {
283             throw new JavaScriptException("expected a java.io.OutputStream instead of " + out);
284         }
285         getInterpreter().process(getParentScope(), this, uri, map,
286                                  (OutputStream JavaDoc)out);
287     }
288
289     public void jsFunction_redirectTo(String JavaDoc uri, boolean isGlobal) throws Exception JavaDoc {
290         if (isGlobal) {
291             this.currentCall.redirector.globalRedirect(false, uri);
292         } else {
293             this.currentCall.redirector.redirect(false, uri);
294         }
295     }
296
297     public void jsFunction_sendStatus(int sc) {
298         this.currentCall.redirector.sendStatus(sc);
299     }
300
301 /*
302
303  NOTE (SM): These are the hooks to the future FOM Event Model that will be
304  designed in the future. It has been postponed because we think
305  there are more important things to do at the moment, but these
306  are left here to indicate that they are planned.
307
308     public void jsFunction_addEventListener(String eventName,
309                                             Object function) {
310         // what is this?
311     }
312
313     public void jsFunction_removeEventListener(String eventName,
314                                                Object function) {
315         // what is this?
316     }
317
318 */

319
320     /**
321      * Access components.
322      *
323      * TODO: Do we want to restrict the access of sitemap components? (RP)
324      * TODO: Do we want to raise an error or return null? (RP)
325      */

326     public Object JavaDoc jsFunction_getComponent(String JavaDoc id)
327         throws Exception JavaDoc {
328         return getServiceManager().lookup(id);
329     }
330
331     /**
332      * Release pooled components.
333      *
334      * @param component a component
335      */

336     public void jsFunction_releaseComponent( Object JavaDoc component ) throws Exception JavaDoc {
337         this.getServiceManager().release( unwrap(component) );
338     }
339
340     /**
341      * Load the script file specified as argument.
342      *
343      * @param filename a <code>String</code> value
344      * @return an <code>Object</code> value
345      * @exception JavaScriptException if an error occurs
346      */

347     public Object JavaDoc jsFunction_load( String JavaDoc filename )
348         throws Exception JavaDoc {
349         org.mozilla.javascript.Context cx =
350             org.mozilla.javascript.Context.getCurrentContext();
351         Scriptable scope = getParentScope();
352         Script script = getInterpreter().compileScript(cx, filename);
353         return script.exec( cx, scope );
354     }
355
356     /**
357      * Setup an object so that it can access the information provided to regular components.
358      * This is done by calling the various Avalon lifecycle interfaces implemented by the object, which
359      * are <code>LogEnabled</code>, <code>Contextualizable</code>, <code>Serviceable</code>,
360      * <code>Composable</code> (even if deprecated) and <code>Initializable</code>.
361      * <p>
362      * <code>Contextualizable</code> is of primary importance as it gives access to the whole object model
363      * (request, response, etc.) through the {@link org.apache.cocoon.components.ContextHelper} class.
364      * <p>
365      * Note that <code>Configurable</code> is ignored, as no configuration exists in a flowscript that
366      * can be passed to the object.
367      *
368      * @param obj the object to setup
369      * @return the same object (convenience that allows to write <code>var foo = cocoon.setupObject(new Foo());</code>).
370      * @throws Exception if something goes wrong during setup.
371      */

372     public Object JavaDoc jsFunction_setupObject(Object JavaDoc obj) throws Exception JavaDoc {
373         LifecycleHelper.setupComponent(
374              unwrap(obj),
375              this.getLogger(),
376              this.getAvalonContext(),
377              this.getServiceManager(),
378              new WrapperComponentManager(this.getServiceManager()),
379              null,// roleManager
380
null,// configuration
381
true);
382          return obj;
383     }
384
385     /**
386      * Create and setup an object so that it can access the information provided to regular components.
387      * This is done by calling the various Avalon lifecycle interfaces implemented by the object, which
388      * are <code>LogEnabled</code>, <code>Contextualizable</code>, <code>Serviceable</code>,
389      * <code>Composable</code> (even if deprecated) and <code>Initializable</code>.
390      * <p>
391      * <code>Contextualizable</code> is of primary importance as it gives access to the whole object model
392      * (request, response, etc.) through the {@link org.apache.cocoon.components.ContextHelper} class.
393      * <p>
394      * Note that <code>Configurable</code> is ignored, as no configuration exists in a flowscript that
395      * can be passed to the object.
396      *
397      * @param classObj the class to instantiate, either as a String or a Rhino NativeJavaClass object
398      * @return an set up instance of <code>clazz</code>
399      * @throws Exception if something goes wrong either during instantiation or setup.
400      */

401     public Object JavaDoc jsFunction_createObject(Object JavaDoc classObj) throws Exception JavaDoc {
402         Object JavaDoc result;
403
404         if (classObj instanceof String JavaDoc) {
405             result = ClassUtils.newInstance((String JavaDoc)classObj);
406
407         } else if (classObj instanceof NativeJavaClass) {
408             Class JavaDoc clazz = ((NativeJavaClass)classObj).getClassObject();
409             result = clazz.newInstance();
410
411         } else {
412             throw new IllegalArgumentException JavaDoc("cocoon.createObject expects either a String or Class argument, but got "
413                 + classObj.getClass());
414         }
415
416         return jsFunction_setupObject(result);
417     }
418
419     /**
420      * Dispose an object that has been created using {@link #jsFunction_createObject(Object)}.
421      *
422      * @param obj
423      * @throws Exception
424      */

425     public void jsFunction_disposeObject(Object JavaDoc obj) throws Exception JavaDoc {
426         LifecycleHelper.decommission(obj);
427     }
428
429     /**
430      * Base JS wrapper for Cocoon's request/session/context objects.
431      * <p>
432      * FIXME(SW): The only thing added to the regular Java object is the fact that
433      * attributes can be accessed as properties. Do we want to keep this?
434      */

435     private static abstract class AttributeHolderJavaObject extends NativeJavaObject {
436         
437         private static Map JavaDoc classProps = new HashMap JavaDoc();
438         private Set JavaDoc propNames;
439
440         public AttributeHolderJavaObject(Scriptable scope, Object JavaDoc object, Class JavaDoc clazz) {
441             super(scope, object, clazz);
442             this.propNames = getProperties(object.getClass());
443         }
444         
445         /** Compute the names of JavaBean properties so that we can filter them our in get() */
446         private static Set JavaDoc getProperties(Class JavaDoc clazz) {
447             Set JavaDoc result = (Set JavaDoc)classProps.get(clazz);
448             if (result == null) {
449                 try {
450                     PropertyDescriptor JavaDoc[] descriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
451                     result = new HashSet JavaDoc();
452                     for (int i = 0; i < descriptors.length; i++) {
453                         result.add(descriptors[i].getName());
454                     }
455                 } catch (IntrospectionException JavaDoc e) {
456                     // Cannot introspect: just consider there are no properties
457
result = Collections.EMPTY_SET;
458                 }
459                 classProps.put(clazz, result);
460             }
461             return result;
462         }
463         
464         
465         protected abstract Enumeration JavaDoc getAttributeNames();
466         protected abstract Object JavaDoc getAttribute(String JavaDoc name);
467         
468         public Object JavaDoc[] getIds() {
469             // Get class Ids
470
Object JavaDoc [] classIds = super.getIds();
471             
472             // and add attribute names
473
ArrayList JavaDoc idList = new ArrayList JavaDoc(Arrays.asList(classIds));
474             Enumeration JavaDoc iter = getAttributeNames();
475             while(iter.hasMoreElements()) {
476                 idList.add(iter.nextElement());
477             }
478             return idList.toArray();
479         }
480         
481         public boolean has(String JavaDoc name, Scriptable start) {
482             return super.has(name, start) || getAttribute(name) != null;
483         }
484         
485         public Object JavaDoc get(String JavaDoc name, Scriptable start) {
486             Object JavaDoc result;
487             // Filter out JavaBean properties. We only want methods of the underlying object.
488
if (this.propNames.contains(name)) {
489                 result = NOT_FOUND;
490             } else {
491                 result = super.get(name, start);
492             }
493             if (result == NOT_FOUND) {
494                 result = getAttribute(name);
495                 if (result != null) {
496                     result = wrap(start, result, null);
497                 } else {
498                     result = NOT_FOUND;
499                 }
500             }
501             return result;
502         }
503     }
504
505     /**
506      * JS wrapper for Cocoon's request object.
507      * <p>
508      * Request <em>parameters</em> are also present as properties on this object.
509      * Note that this is different from <code>FOM_Context</code> and <code>FOM_Session</code>
510      * that do the same with <em>attributes</em>.
511      */

512     public static class FOM_Request extends AttributeHolderJavaObject {
513         private final Request request;
514         
515         public FOM_Request(Scriptable scope, Request request) {
516             super(scope, request, Request.class);
517             this.request = request;
518         }
519         
520         protected Enumeration JavaDoc getAttributeNames() {
521             return this.request.getParameterNames();
522         }
523         
524         protected Object JavaDoc getAttribute(String JavaDoc name) {
525             return this.request.getParameter(name);
526         }
527     }
528
529     /**
530      * JS wrapper for Cocoon's session object.
531      * <p>
532      * Session attributes are also present as properties on this object.
533      */

534     public static class FOM_Session extends AttributeHolderJavaObject {
535         private final Session session;
536         
537         public FOM_Session(Scriptable scope, Session session) {
538             super(scope, session, Session.class);
539             this.session = session;
540         }
541         
542         protected Enumeration JavaDoc getAttributeNames() {
543             return this.session.getAttributeNames();
544         }
545         
546         protected Object JavaDoc getAttribute(String JavaDoc name) {
547             return this.session.getAttribute(name);
548         }
549     }
550
551     /**
552      * JS wrapper for Cocoon's context object.
553      * <p>
554      * Context attributes are also present as properties on this object.
555      */

556     public static class FOM_Context extends AttributeHolderJavaObject {
557         private final org.apache.cocoon.environment.Context context;
558         
559         public FOM_Context(Scriptable scope, org.apache.cocoon.environment.Context context) {
560             super(scope, context, org.apache.cocoon.environment.Context.class);
561             this.context = context;
562         }
563         
564         protected Enumeration JavaDoc getAttributeNames() {
565             return this.context.getAttributeNames();
566         }
567         
568         protected Object JavaDoc getAttribute(String JavaDoc name) {
569             return this.context.getAttribute(name);
570         }
571     }
572
573     public Scriptable jsGet_request() {
574         return currentCall.getRequest();
575     }
576
577     public Scriptable jsGet_response() {
578         return currentCall.getResponse();
579     }
580
581     public Scriptable jsGet_log() {
582         return currentCall.getLog();
583     }
584
585     public Scriptable jsGet_context() {
586         return currentCall.getContext();
587     }
588
589     public Scriptable jsGet_session() {
590         return currentCall.getSession();
591     }
592
593     /**
594      * Get Sitemap parameters
595      *
596      * @return a <code>Scriptable</code> value whose properties represent
597      * the Sitemap parameters from <map:call>
598      */

599     public Scriptable jsGet_parameters() {
600         return getParameters();
601     }
602
603     public Scriptable getParameters() {
604         return currentCall.getParameters();
605     }
606
607     void setParameters(Scriptable value) {
608         currentCall.setParameters(value);
609     }
610
611     // unwrap Wrapper's and convert undefined to null
612
private static Object JavaDoc unwrap(Object JavaDoc obj) {
613         if (obj instanceof Wrapper) {
614             obj = ((Wrapper)obj).unwrap();
615         } else if (obj == Undefined.instance) {
616             obj = null;
617         }
618         return obj;
619     }
620
621     // Make everything available to JavaScript objects implemented in Java:
622

623     /**
624      * Get the current request
625      * @return The request
626      */

627     public Request getRequest() {
628         return ObjectModelHelper.getRequest(ContextHelper.getObjectModel(currentCall.avalonContext));
629     }
630
631     /**
632      * Get the current session
633      * @return The session (may be null)
634      */

635     public Session getSession() {
636         return ObjectModelHelper.getRequest(ContextHelper.getObjectModel(currentCall.avalonContext)).getSession(true);
637     }
638
639     /**
640      * Get the current response
641      * @return The response
642      */

643     public Response getResponse() {
644         return ObjectModelHelper.getResponse(ContextHelper.getObjectModel(currentCall.avalonContext));
645     }
646
647     /**
648      * Get the current context
649      * @return The context
650      */

651     public org.apache.cocoon.environment.Context getContext() {
652         return ObjectModelHelper.getContext(ContextHelper.getObjectModel(currentCall.avalonContext));
653     }
654
655     /**
656      * Get the current object model
657      * @return The object model
658      */

659     public Map JavaDoc getObjectModel() {
660         return ContextHelper.getObjectModel(currentCall.avalonContext);
661     }
662
663     private Context getAvalonContext() {
664         return currentCall.avalonContext;
665     }
666
667     private Logger getLogger() {
668         return currentCall.logger;
669     }
670
671     public ServiceManager getServiceManager() {
672         return currentCall.serviceManager;
673     }
674
675     private FOM_JavaScriptInterpreter getInterpreter() {
676         return currentCall.interpreter;
677     }
678
679     /**
680      * Required by FOM_WebContinuation. This way we do not make whole Interpreter public
681      * @return interpreter Id associated with this FOM.
682      */

683     public String JavaDoc getInterpreterId() {
684         return getInterpreter().getInterpreterID();
685     }
686     
687     /**
688      * Call the Cocoon Sitemap to process a page
689      * @param uri Uri to match
690      * @param bean Input to page
691      * @param fom_wk Current Web continuation (may be null)
692      */

693
694     public void forwardTo(String JavaDoc uri,
695                           Object JavaDoc bean,
696                           FOM_WebContinuation fom_wk)
697         throws Exception JavaDoc {
698         getInterpreter().forwardTo(getTopLevelScope(this),
699                                    this,
700                                    uri,
701                                    bean,
702                                    fom_wk,
703                                    this.currentCall.redirector);
704     }
705
706     /**
707      * Perform the behavior of <map:call continuation="blah">
708      * This can be used in cases where the continuation id is not encoded
709      * in the request in a form convenient to access in the sitemap.
710      * Your script can extract the id from the request and then call
711      * this method to process it as normal.
712      * @param kontId The continuation id
713      * @param parameters Any parameters you want to pass to the continuation (may be null)
714      */

715     public void handleContinuation(String JavaDoc kontId, Scriptable parameters)
716         throws Exception JavaDoc {
717         List JavaDoc list = null;
718         if (parameters == null || parameters == Undefined.instance) {
719             parameters = getParameters();
720         }
721         Object JavaDoc[] ids = parameters.getIds();
722         list = new ArrayList JavaDoc();
723         for (int i = 0; i < ids.length; i++) {
724             String JavaDoc name = ids[i].toString();
725             Argument arg = new Argument(name,
726                                         org.mozilla.javascript.Context.toString(getProperty(parameters, name)));
727             list.add(arg);
728         }
729         getInterpreter().handleContinuation(kontId, list, this.currentCall.redirector);
730     }
731
732     /**
733      * Return this continuation if it is valid, or first valid parent
734      */

735     private FOM_WebContinuation findValidParent(FOM_WebContinuation wk) {
736         if (wk != null) {
737             WebContinuation wc = wk.getWebContinuation();
738             while (wc != null && wc.disposed()) {
739                 wc = wc.getParentContinuation();
740             }
741             if (wc != null) {
742                 return new FOM_WebContinuation(wc);
743             }
744         }
745
746         return null;
747     }
748
749     /**
750      * Create a Bookmark WebContinuation from a JS Continuation with the last
751      * continuation of sendPageAndWait as its parent.
752      * PageLocal variables will be shared with the continuation of
753      * the next call to sendPageAndWait().
754      * @param k The JS continuation
755      * @param ttl Lifetime for this continuation (zero means no limit)
756      */

757     public FOM_WebContinuation jsFunction_makeWebContinuation(Object JavaDoc k,
758                                                               Object JavaDoc ttl)
759         throws Exception JavaDoc {
760         double d = org.mozilla.javascript.Context.toNumber(ttl);
761         FOM_WebContinuation result =
762             makeWebContinuation((Continuation)unwrap(k),
763                                 findValidParent(jsGet_continuation()),
764                                 (int)d);
765         result.setPageLocal(pageLocal.getDelegate());
766         currentCall.setLastContinuation(result);
767         return result;
768     }
769
770     /**
771      * Create a Web Continuation from a JS Continuation
772      * @param k The JS continuation (may be null - null will be returned in that case)
773      * @param parent The parent of this continuation (may be null)
774      * @param timeToLive Lifetime for this continuation (zero means no limit)
775      */

776     public FOM_WebContinuation makeWebContinuation(Continuation k,
777                                                    FOM_WebContinuation parent,
778                                                    int timeToLive)
779         throws Exception JavaDoc {
780         if (k == null) {
781             return null;
782         }
783         WebContinuation wk;
784         ContinuationsManager contMgr;
785         contMgr = (ContinuationsManager)
786             getServiceManager().lookup(ContinuationsManager.ROLE);
787         wk = contMgr.createWebContinuation(unwrap(k),
788                                            (parent == null ? null : parent.getWebContinuation()),
789                                            timeToLive,
790                                            getInterpreter().getInterpreterID(),
791                                            null);
792         FOM_WebContinuation result = new FOM_WebContinuation(wk);
793         result.setParentScope(getParentScope());
794         result.setPrototype(getClassPrototype(getParentScope(),
795                                               result.getClassName()));
796         return result;
797     }
798 }
799
Popular Tags