Source code: org/apache/tapestry/engine/RequestCycle.java
1 /* $$ Clover has instrumented this file $$ */// Copyright 2004 The Apache Software Foundation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package org.apache.tapestry.engine;
16
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.Map;
20
21 import javax.servlet.http.HttpServletResponse;
22
23 import org.apache.commons.lang.builder.ToStringBuilder;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hivemind.ApplicationRuntimeException;
27 import org.apache.tapestry.IComponent;
28 import org.apache.tapestry.IEngine;
29 import org.apache.tapestry.IForm;
30 import org.apache.tapestry.IMarkupWriter;
31 import org.apache.tapestry.IPage;
32 import org.apache.tapestry.IRequestCycle;
33 import org.apache.tapestry.RenderRewoundException;
34 import org.apache.tapestry.StaleLinkException;
35 import org.apache.tapestry.Tapestry;
36 import org.apache.tapestry.event.ChangeObserver;
37 import org.apache.tapestry.event.ObservedChangeEvent;
38 import org.apache.tapestry.request.RequestContext;
39
40 /**
41 * Provides the logic for processing a single request cycle. Provides access to
42 * the {@link IEngine engine} and the {@link RequestContext}.
43 *
44 * @author Howard Lewis Ship
45 *
46 **/
47
48 public class RequestCycle implements IRequestCycle, ChangeObserver
49 {public static com.cortexeb.tools.clover.d __CLOVER_102_0 = com.cortexeb.tools.clover.aq.getRecorder(new char[] {67,58,92,119,111,114,107,115,112,97,99,101,92,106,97,107,97,114,116,97,45,116,97,112,101,115,116,114,121,92,102,114,97,109,101,119,111,114,107,92,116,97,114,103,101,116,92,99,108,111,118,101,114,45,100,98},1096998272901L);
50 private static final Log LOG = LogFactory.getLog(RequestCycle.class);
51
52 private IPage _page;
53 private IEngine _engine;
54 private IEngineService _service;
55
56 private RequestContext _requestContext;
57
58 private IMonitor _monitor;
59
60 private HttpServletResponse _response;
61
62 /**
63 * A mapping of pages loaded during the current request cycle.
64 * Key is the page name, value is the {@link IPage} instance.
65 *
66 **/
67
68 private Map _loadedPages;
69
70 /**
71 * A mapping of page recorders for the current request cycle.
72 * Key is the page name, value is the {@link IPageRecorder} instance.
73 *
74 **/
75
76 private Map _loadedRecorders;
77
78 private boolean _rewinding = false;
79
80 private Map _attributes;
81
82 private int _actionId;
83 private int _targetActionId;
84 private IComponent _targetComponent;
85
86 /** @since 2.0.3 **/
87
88 private Object[] _serviceParameters;
89
90 /**
91 * Standard constructor used to render a response page.
92 *
93 **/
94
95 public RequestCycle(
96 IEngine engine,
97 RequestContext requestContext,
98 IEngineService service,
99 IMonitor monitor)
100 {try { __CLOVER_102_0.M[548]++;
101 __CLOVER_102_0.S[2286]++;_engine = engine;
102 __CLOVER_102_0.S[2287]++;_requestContext = requestContext;
103 __CLOVER_102_0.S[2288]++;_service = service;
104 __CLOVER_102_0.S[2289]++;_monitor = monitor;
105 } finally { }}
106
107 /**
108 * Called at the end of the request cycle (i.e., after all responses have been
109 * sent back to the client), to release all pages loaded during the request cycle.
110 *
111 **/
112
113 public void cleanup()
114 {try { __CLOVER_102_0.M[549]++;
115 __CLOVER_102_0.S[2290]++;if ((((_loadedPages == null) && (++__CLOVER_102_0.CT[424] != 0)) || (++__CLOVER_102_0.CF[424] == 0))){
116 __CLOVER_102_0.S[2291]++;return;}
117
118 __CLOVER_102_0.S[2292]++;IPageSource source = _engine.getPageSource();
119 __CLOVER_102_0.S[2293]++;Iterator i = _loadedPages.values().iterator();
120
121 __CLOVER_102_0.S[2294]++;while ((((i.hasNext()) && (++__CLOVER_102_0.CT[425] != 0)) || (++__CLOVER_102_0.CF[425] == 0))){
122 {
123 __CLOVER_102_0.S[2295]++;IPage page = (IPage) i.next();
124
125 __CLOVER_102_0.S[2296]++;source.releasePage(page);
126 }}
127
128 __CLOVER_102_0.S[2297]++;_loadedPages = null;
129 __CLOVER_102_0.S[2298]++;_loadedRecorders = null;
130
131 } finally { }}
132
133 public IEngineService getService()
134 {try { __CLOVER_102_0.M[550]++;
135 __CLOVER_102_0.S[2299]++;return _service;
136 } finally { }}
137
138 public String encodeURL(String URL)
139 {try { __CLOVER_102_0.M[551]++;
140 __CLOVER_102_0.S[2300]++;if ((((_response == null) && (++__CLOVER_102_0.CT[426] != 0)) || (++__CLOVER_102_0.CF[426] == 0))){
141 __CLOVER_102_0.S[2301]++;_response = _requestContext.getResponse();}
142
143 __CLOVER_102_0.S[2302]++;return _response.encodeURL(URL);
144 } finally { }}
145
146 public IEngine getEngine()
147 {try { __CLOVER_102_0.M[552]++;
148 __CLOVER_102_0.S[2303]++;return _engine;
149 } finally { }}
150
151 public Object getAttribute(String name)
152 {try { __CLOVER_102_0.M[553]++;
153 __CLOVER_102_0.S[2304]++;if ((((_attributes == null) && (++__CLOVER_102_0.CT[427] != 0)) || (++__CLOVER_102_0.CF[427] == 0))){
154 __CLOVER_102_0.S[2305]++;return null;}
155
156 __CLOVER_102_0.S[2306]++;return _attributes.get(name);
157 } finally { }}
158
159 public IMonitor getMonitor()
160 {try { __CLOVER_102_0.M[554]++;
161 __CLOVER_102_0.S[2307]++;return _monitor;
162 } finally { }}
163
164 public String getNextActionId()
165 {try { __CLOVER_102_0.M[555]++;
166 __CLOVER_102_0.S[2308]++;return Integer.toHexString(++_actionId);
167 } finally { }}
168
169 public IPage getPage()
170 {try { __CLOVER_102_0.M[556]++;
171 __CLOVER_102_0.S[2309]++;return _page;
172 } finally { }}
173
174 /**
175 * Gets the page from the engines's {@link IPageSource}.
176 *
177 **/
178
179 public IPage getPage(String name)
180 {try { __CLOVER_102_0.M[557]++;
181 __CLOVER_102_0.S[2310]++;IPage result = null;
182
183 __CLOVER_102_0.S[2311]++;if ((((name == null) && (++__CLOVER_102_0.CT[428] != 0)) || (++__CLOVER_102_0.CF[428] == 0))){
184 __CLOVER_102_0.S[2312]++;throw new NullPointerException(Tapestry.getMessage("RequestCycle.invalid-null-name"));}
185
186 __CLOVER_102_0.S[2313]++;if ((((_loadedPages != null) && (++__CLOVER_102_0.CT[429] != 0)) || (++__CLOVER_102_0.CF[429] == 0))){
187 __CLOVER_102_0.S[2314]++;result = (IPage) _loadedPages.get(name);}
188
189 __CLOVER_102_0.S[2315]++;if ((((result == null) && (++__CLOVER_102_0.CT[430] != 0)) || (++__CLOVER_102_0.CF[430] == 0))){
190 {
191 __CLOVER_102_0.S[2316]++;_monitor.pageLoadBegin(name);
192
193 __CLOVER_102_0.S[2317]++;IPageSource pageSource = _engine.getPageSource();
194
195 __CLOVER_102_0.S[2318]++;result = pageSource.getPage(this, name, _monitor);
196
197 __CLOVER_102_0.S[2319]++;result.setRequestCycle(this);
198
199 // Get the recorder that will eventually observe and record
200 // changes to persistent properties of the page. If the page
201 // has never emitted any page changes, then it will
202 // not have a recorder.
203
204 __CLOVER_102_0.S[2320]++;IPageRecorder recorder = getPageRecorder(name);
205
206 __CLOVER_102_0.S[2321]++;if ((((recorder != null) && (++__CLOVER_102_0.CT[431] != 0)) || (++__CLOVER_102_0.CF[431] == 0))){
207 {
208 // Have it rollback the page to the prior state. Note that
209 // the page has a null observer at this time.
210
211 __CLOVER_102_0.S[2322]++;recorder.rollback(result);
212
213 // Now, have the page use the recorder for any future
214 // property changes.
215
216 __CLOVER_102_0.S[2323]++;result.setChangeObserver(recorder);
217
218 // And, if this recorder observed changes in a prior request cycle
219 // (and was locked after committing in that cycle), it's time
220 // to unlock.
221
222 __CLOVER_102_0.S[2324]++;recorder.setLocked(false);
223 }}
224 else{
225 {
226 // No page recorder for the page. We'll observe its
227 // changes and create the page recorder dynamically
228 // if it emits any.
229
230 __CLOVER_102_0.S[2325]++;result.setChangeObserver(this);
231 }}
232
233 __CLOVER_102_0.S[2326]++;_monitor.pageLoadEnd(name);
234
235 __CLOVER_102_0.S[2327]++;if ((((_loadedPages == null) && (++__CLOVER_102_0.CT[432] != 0)) || (++__CLOVER_102_0.CF[432] == 0))){
236 __CLOVER_102_0.S[2328]++;_loadedPages = new HashMap();}
237
238 __CLOVER_102_0.S[2329]++;_loadedPages.put(name, result);
239 }}
240
241 __CLOVER_102_0.S[2330]++;return result;
242 } finally { }}
243
244 /**
245 * Returns the page recorder for the named page. This may come
246 * from the cycle's cache of page recorders or, if not yet encountered
247 * in this request cycle, the {@link IEngine#getPageRecorder(String, IRequestCycle)} is
248 * invoked to get the recorder, if it exists.
249 *
250 **/
251
252 protected IPageRecorder getPageRecorder(String name)
253 {try { __CLOVER_102_0.M[558]++;
254 __CLOVER_102_0.S[2331]++;IPageRecorder result = null;
255
256 __CLOVER_102_0.S[2332]++;if ((((_loadedRecorders != null) && (++__CLOVER_102_0.CT[433] != 0)) || (++__CLOVER_102_0.CF[433] == 0))){
257 __CLOVER_102_0.S[2333]++;result = (IPageRecorder) _loadedRecorders.get(name);}
258
259 __CLOVER_102_0.S[2334]++;if ((((result != null) && (++__CLOVER_102_0.CT[434] != 0)) || (++__CLOVER_102_0.CF[434] == 0))){
260 __CLOVER_102_0.S[2335]++;return result;}
261
262 __CLOVER_102_0.S[2336]++;result = _engine.getPageRecorder(name, this);
263
264 __CLOVER_102_0.S[2337]++;if ((((result == null) && (++__CLOVER_102_0.CT[435] != 0)) || (++__CLOVER_102_0.CF[435] == 0))){
265 __CLOVER_102_0.S[2338]++;return null;}
266
267 __CLOVER_102_0.S[2339]++;if ((((_loadedRecorders == null) && (++__CLOVER_102_0.CT[436] != 0)) || (++__CLOVER_102_0.CF[436] == 0))){
268 __CLOVER_102_0.S[2340]++;_loadedRecorders = new HashMap();}
269
270 __CLOVER_102_0.S[2341]++;_loadedRecorders.put(name, result);
271
272 __CLOVER_102_0.S[2342]++;return result;
273 } finally { }}
274
275 /**
276 *
277 * Gets the page recorder from the loadedRecorders cache, or from the engine
278 * (putting it into loadedRecorders). If the recorder does not yet exist,
279 * it is created.
280 *
281 * @see IEngine#createPageRecorder(String, IRequestCycle)
282 * @since 2.0.3
283 *
284 **/
285
286 private IPageRecorder createPageRecorder(String name)
287 {try { __CLOVER_102_0.M[559]++;
288 __CLOVER_102_0.S[2343]++;IPageRecorder result = getPageRecorder(name);
289
290 __CLOVER_102_0.S[2344]++;if ((((result == null) && (++__CLOVER_102_0.CT[437] != 0)) || (++__CLOVER_102_0.CF[437] == 0))){
291 {
292 __CLOVER_102_0.S[2345]++;result = _engine.createPageRecorder(name, this);
293
294 __CLOVER_102_0.S[2346]++;if ((((_loadedRecorders == null) && (++__CLOVER_102_0.CT[438] != 0)) || (++__CLOVER_102_0.CF[438] == 0))){
295 __CLOVER_102_0.S[2347]++;_loadedRecorders = new HashMap();}
296
297 __CLOVER_102_0.S[2348]++;_loadedRecorders.put(name, result);
298 }}
299
300 __CLOVER_102_0.S[2349]++;return result;
301 } finally { }}
302
303 public RequestContext getRequestContext()
304 {try { __CLOVER_102_0.M[560]++;
305 __CLOVER_102_0.S[2350]++;return _requestContext;
306 } finally { }}
307
308 public boolean isRewinding()
309 {try { __CLOVER_102_0.M[561]++;
310 __CLOVER_102_0.S[2351]++;return _rewinding;
311 } finally { }}
312
313 public boolean isRewound(IComponent component) throws StaleLinkException
314 {try { __CLOVER_102_0.M[562]++;
315 // If not rewinding ...
316
317 __CLOVER_102_0.S[2352]++;if ((((!_rewinding) && (++__CLOVER_102_0.CT[439] != 0)) || (++__CLOVER_102_0.CF[439] == 0))){
318 __CLOVER_102_0.S[2353]++;return false;}
319
320 __CLOVER_102_0.S[2354]++;if ((((_actionId != _targetActionId) && (++__CLOVER_102_0.CT[440] != 0)) || (++__CLOVER_102_0.CF[440] == 0))){
321 __CLOVER_102_0.S[2355]++;return false;}
322
323 // OK, we're there, is the page is good order?
324
325 __CLOVER_102_0.S[2356]++;if ((((component == _targetComponent) && (++__CLOVER_102_0.CT[441] != 0)) || (++__CLOVER_102_0.CF[441] == 0))){
326 __CLOVER_102_0.S[2357]++;return true;}
327
328 // Woops. Mismatch.
329
330 __CLOVER_102_0.S[2358]++;throw new StaleLinkException(
331 component,
332 Integer.toHexString(_targetActionId),
333 _targetComponent.getExtendedId());
334 } finally { }}
335
336 public void removeAttribute(String name)
337 {try { __CLOVER_102_0.M[563]++;
338 __CLOVER_102_0.S[2359]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[442] != 0)) || (++__CLOVER_102_0.CF[442] == 0))){
339 __CLOVER_102_0.S[2360]++;LOG.debug("Removing attribute " + name);}
340
341 __CLOVER_102_0.S[2361]++;if ((((_attributes == null) && (++__CLOVER_102_0.CT[443] != 0)) || (++__CLOVER_102_0.CF[443] == 0))){
342 __CLOVER_102_0.S[2362]++;return;}
343
344 __CLOVER_102_0.S[2363]++;_attributes.remove(name);
345 } finally { }}
346
347 /**
348 * Renders the page by invoking
349 * {@link IPage#renderPage(IMarkupWriter, IRequestCycle)}.
350 * This clears all attributes.
351 *
352 **/
353
354 public void renderPage(IMarkupWriter writer)
355 {try { __CLOVER_102_0.M[564]++;
356 __CLOVER_102_0.S[2364]++;String pageName = _page.getPageName();
357 __CLOVER_102_0.S[2365]++;_monitor.pageRenderBegin(pageName);
358
359 __CLOVER_102_0.S[2366]++;_rewinding = false;
360 __CLOVER_102_0.S[2367]++;_actionId = -1;
361 __CLOVER_102_0.S[2368]++;_targetActionId = 0;
362
363 // Forget any attributes from a previous render cycle.
364
365 __CLOVER_102_0.S[2369]++;if ((((_attributes != null) && (++__CLOVER_102_0.CT[444] != 0)) || (++__CLOVER_102_0.CF[444] == 0))){
366 __CLOVER_102_0.S[2370]++;_attributes.clear();}
367
368 __CLOVER_102_0.S[2371]++;try
369 {
370 __CLOVER_102_0.S[2372]++;_page.renderPage(writer, this);
371
372 }
373 catch (ApplicationRuntimeException ex)
374 {
375 // Nothing much to add here.
376
377 __CLOVER_102_0.S[2373]++;throw ex;
378 }
379 catch (Throwable ex)
380 {
381 // But wrap other exceptions in a RequestCycleException ... this
382 // will ensure that some of the context is available.
383
384 __CLOVER_102_0.S[2374]++;throw new ApplicationRuntimeException(ex.getMessage(), _page, null, ex);
385 }
386 finally
387 {
388 __CLOVER_102_0.S[2375]++;_actionId = 0;
389 __CLOVER_102_0.S[2376]++;_targetActionId = 0;
390 }
391
392 __CLOVER_102_0.S[2377]++;_monitor.pageRenderEnd(pageName);
393
394 } finally { }}
395
396 /**
397 * Rewinds an individual form by invoking
398 * {@link IForm#rewind(IMarkupWriter, IRequestCycle)}.
399 *
400 * <p>The process is expected to end with a {@link RenderRewoundException}.
401 * If the entire page is renderred without this exception being thrown, it means
402 * that the target action id was not valid, and a
403 * {@link ApplicationRuntimeException}
404 * is thrown.
405 *
406 * <p>This clears all attributes.
407 *
408 * @since 1.0.2
409 **/
410
411 public void rewindForm(IForm form, String targetActionId)
412 {try { __CLOVER_102_0.M[565]++;
413 __CLOVER_102_0.S[2378]++;IPage page = form.getPage();
414 __CLOVER_102_0.S[2379]++;String pageName = page.getPageName();
415
416 __CLOVER_102_0.S[2380]++;_rewinding = true;
417
418 __CLOVER_102_0.S[2381]++;_monitor.pageRewindBegin(pageName);
419
420 __CLOVER_102_0.S[2382]++;if ((((_attributes != null) && (++__CLOVER_102_0.CT[445] != 0)) || (++__CLOVER_102_0.CF[445] == 0))){
421 __CLOVER_102_0.S[2383]++;_attributes.clear();}
422
423 // Fake things a little for getNextActionId() / isRewound()
424
425 __CLOVER_102_0.S[2384]++;_targetActionId = Integer.parseInt(targetActionId, 16);
426 __CLOVER_102_0.S[2385]++;_actionId = _targetActionId - 1;
427
428 __CLOVER_102_0.S[2386]++;_targetComponent = form;
429
430 __CLOVER_102_0.S[2387]++;try
431 {
432 __CLOVER_102_0.S[2388]++;page.beginPageRender();
433
434 __CLOVER_102_0.S[2389]++;form.rewind(NullWriter.getSharedInstance(), this);
435
436 // Shouldn't get this far, because the form should
437 // throw the RenderRewoundException.
438
439 __CLOVER_102_0.S[2390]++;throw new StaleLinkException(
440 Tapestry.format("RequestCycle.form-rewind-failure", form.getExtendedId()),
441 form);
442 }
443 catch (RenderRewoundException ex)
444 {
445 // This is acceptible and expected.
446 }
447 catch (ApplicationRuntimeException ex)
448 {
449 // RequestCycleExceptions don't need to be wrapped.
450 __CLOVER_102_0.S[2391]++;throw ex;
451 }
452 catch (Throwable ex)
453 {
454 // But wrap other exceptions in a ApplicationRuntimeException ... this
455 // will ensure that some of the context is available.
456
457 __CLOVER_102_0.S[2392]++;throw new ApplicationRuntimeException(ex.getMessage(), page, null, ex);
458 }
459 finally
460 {
461 __CLOVER_102_0.S[2393]++;_actionId = 0;
462 __CLOVER_102_0.S[2394]++;_targetActionId = 0;
463 __CLOVER_102_0.S[2395]++;_targetComponent = null;
464
465 __CLOVER_102_0.S[2396]++;page.endPageRender();
466
467 __CLOVER_102_0.S[2397]++;_monitor.pageRewindEnd(pageName);
468
469 __CLOVER_102_0.S[2398]++;_rewinding = false;
470 }
471 } finally { }}
472
473 /**
474 * Rewinds the page by invoking
475 * {@link IPage#renderPage(IMarkupWriter, IRequestCycle)}.
476 *
477 * <p>The process is expected to end with a {@link RenderRewoundException}.
478 * If the entire page is renderred without this exception being thrown, it means
479 * that the target action id was not valid, and a
480 * {@link ApplicationRuntimeException}
481 * is thrown.
482 *
483 * <p>This clears all attributes.
484 *
485 **/
486
487 public void rewindPage(String targetActionId, IComponent targetComponent)
488 {try { __CLOVER_102_0.M[566]++;
489 __CLOVER_102_0.S[2399]++;String pageName = _page.getPageName();
490
491 __CLOVER_102_0.S[2400]++;_rewinding = true;
492
493 __CLOVER_102_0.S[2401]++;_monitor.pageRewindBegin(pageName);
494
495 __CLOVER_102_0.S[2402]++;if ((((_attributes != null) && (++__CLOVER_102_0.CT[446] != 0)) || (++__CLOVER_102_0.CF[446] == 0))){
496 __CLOVER_102_0.S[2403]++;_attributes.clear();}
497
498 __CLOVER_102_0.S[2404]++;_actionId = -1;
499
500 // Parse the action Id as hex since that's whats generated
501 // by getNextActionId()
502 __CLOVER_102_0.S[2405]++;_targetActionId = Integer.parseInt(targetActionId, 16);
503 __CLOVER_102_0.S[2406]++;_targetComponent = targetComponent;
504
505 __CLOVER_102_0.S[2407]++;try
506 {
507 __CLOVER_102_0.S[2408]++;_page.renderPage(NullWriter.getSharedInstance(), this);
508
509 // Shouldn't get this far, because the target component should
510 // throw the RenderRewoundException.
511
512 __CLOVER_102_0.S[2409]++;throw new StaleLinkException(_page, targetActionId, targetComponent.getExtendedId());
513 }
514 catch (RenderRewoundException ex)
515 {
516 // This is acceptible and expected.
517 }
518 catch (ApplicationRuntimeException ex)
519 {
520 // ApplicationRuntimeExceptions don't need to be wrapped.
521 __CLOVER_102_0.S[2410]++;throw ex;
522 }
523 catch (Throwable ex)
524 {
525 // But wrap other exceptions in a RequestCycleException ... this
526 // will ensure that some of the context is available.
527
528 __CLOVER_102_0.S[2411]++;throw new ApplicationRuntimeException(ex.getMessage(), _page, null, ex);
529 }
530 finally
531 {
532
533 __CLOVER_102_0.S[2412]++;_actionId = 0;
534 __CLOVER_102_0.S[2413]++;_targetActionId = 0;
535 __CLOVER_102_0.S[2414]++;_targetComponent = null;
536
537 __CLOVER_102_0.S[2415]++;_monitor.pageRewindEnd(pageName);
538
539 __CLOVER_102_0.S[2416]++;_rewinding = false;
540 }
541
542 } finally { }}
543
544 public void setAttribute(String name, Object value)
545 {try { __CLOVER_102_0.M[567]++;
546 __CLOVER_102_0.S[2417]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[447] != 0)) || (++__CLOVER_102_0.CF[447] == 0))){
547 __CLOVER_102_0.S[2418]++;LOG.debug("Set attribute " + name + " to " + value);}
548
549 __CLOVER_102_0.S[2419]++;if ((((_attributes == null) && (++__CLOVER_102_0.CT[448] != 0)) || (++__CLOVER_102_0.CF[448] == 0))){
550 __CLOVER_102_0.S[2420]++;_attributes = new HashMap();}
551
552 __CLOVER_102_0.S[2421]++;_attributes.put(name, value);
553 } finally { }}
554
555 public void setPage(IPage value)
556 {try { __CLOVER_102_0.M[568]++;
557 __CLOVER_102_0.S[2422]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[449] != 0)) || (++__CLOVER_102_0.CF[449] == 0))){
558 __CLOVER_102_0.S[2423]++;LOG.debug("Set page to " + value);}
559
560 __CLOVER_102_0.S[2424]++;_page = value;
561 } finally { }}
562
563 public void setPage(String name)
564 {try { __CLOVER_102_0.M[569]++;
565 __CLOVER_102_0.S[2425]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[450] != 0)) || (++__CLOVER_102_0.CF[450] == 0))){
566 __CLOVER_102_0.S[2426]++;LOG.debug("Set page to " + name);}
567
568 __CLOVER_102_0.S[2427]++;_page = getPage(name);
569 } finally { }}
570
571 /**
572 * Invokes {@link IPageRecorder#commit()} on each page recorder loaded
573 * during the request cycle (even recorders marked for discard).
574 *
575 **/
576
577 public void commitPageChanges()
578 {try { __CLOVER_102_0.M[570]++;
579 __CLOVER_102_0.S[2428]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[451] != 0)) || (++__CLOVER_102_0.CF[451] == 0))){
580 __CLOVER_102_0.S[2429]++;LOG.debug("Committing page changes");}
581
582 __CLOVER_102_0.S[2430]++;if ((((_loadedRecorders == null || _loadedRecorders.isEmpty()) && (++__CLOVER_102_0.CT[452] != 0)) || (++__CLOVER_102_0.CF[452] == 0))){
583 __CLOVER_102_0.S[2431]++;return;}
584
585 __CLOVER_102_0.S[2432]++;Iterator i = _loadedRecorders.values().iterator();
586
587 __CLOVER_102_0.S[2433]++;while ((((i.hasNext()) && (++__CLOVER_102_0.CT[453] != 0)) || (++__CLOVER_102_0.CF[453] == 0))){
588 {
589 __CLOVER_102_0.S[2434]++;IPageRecorder recorder = (IPageRecorder) i.next();
590
591 __CLOVER_102_0.S[2435]++;recorder.commit();
592 }}
593 } finally { }}
594
595 /**
596 * For pages without a {@link IPageRecorder page recorder},
597 * we're the {@link ChangeObserver change observer}.
598 * If such a page actually emits a change, then
599 * we'll obtain a new page recorder from the
600 * {@link IEngine engine}, set the recorder
601 * as the page's change observer, and forward the event
602 * to the newly created recorder. In addition, the
603 * new page recorder is remembered so that it will
604 * be committed by {@link #commitPageChanges()}.
605 *
606 **/
607
608 public void observeChange(ObservedChangeEvent event)
609 {try { __CLOVER_102_0.M[571]++;
610 __CLOVER_102_0.S[2436]++;IPage page = event.getComponent().getPage();
611 __CLOVER_102_0.S[2437]++;String pageName = page.getPageName();
612
613 __CLOVER_102_0.S[2438]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[454] != 0)) || (++__CLOVER_102_0.CF[454] == 0))){
614 __CLOVER_102_0.S[2439]++;LOG.debug("Observed change in page " + pageName + "; creating page recorder.");}
615
616 __CLOVER_102_0.S[2440]++;IPageRecorder recorder = createPageRecorder(pageName);
617
618 __CLOVER_102_0.S[2441]++;page.setChangeObserver(recorder);
619
620 __CLOVER_102_0.S[2442]++;recorder.observeChange(event);
621 } finally { }}
622
623 /**
624 * Finds the page and its page recorder, creating the page recorder if necessary.
625 * The page recorder is marked for discard regardless of its current state.
626 *
627 * <p>This may make the application stateful even if the page recorder does
628 * not yet exist.
629 *
630 * <p>The page recorder will be discarded at the end of the current request cycle.
631 *
632 * @since 2.0.2
633 *
634 **/
635
636 public void discardPage(String name)
637 {try { __CLOVER_102_0.M[572]++;
638 __CLOVER_102_0.S[2443]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[455] != 0)) || (++__CLOVER_102_0.CF[455] == 0))){
639 __CLOVER_102_0.S[2444]++;LOG.debug("Discarding page " + name);}
640
641 __CLOVER_102_0.S[2445]++;IPageRecorder recorder = _engine.getPageRecorder(name, this);
642
643 __CLOVER_102_0.S[2446]++;if ((((recorder == null) && (++__CLOVER_102_0.CT[456] != 0)) || (++__CLOVER_102_0.CF[456] == 0))){
644 {
645 __CLOVER_102_0.S[2447]++;_page = getPage(name);
646
647 __CLOVER_102_0.S[2448]++;recorder = createPageRecorder(name);
648
649 __CLOVER_102_0.S[2449]++;_page.setChangeObserver(recorder);
650 }}
651
652 __CLOVER_102_0.S[2450]++;recorder.markForDiscard();
653 } finally { }}
654
655 /** @since 2.0.3 **/
656
657 public Object[] getServiceParameters()
658 {try { __CLOVER_102_0.M[573]++;
659 __CLOVER_102_0.S[2451]++;return _serviceParameters;
660 } finally { }}
661
662 /** @since 2.0.3 **/
663
664 public void setServiceParameters(Object[] serviceParameters)
665 {try { __CLOVER_102_0.M[574]++;
666 __CLOVER_102_0.S[2452]++;_serviceParameters = serviceParameters;
667 } finally { }}
668
669 /** @since 3.0 **/
670
671 public void activate(String name)
672 {try { __CLOVER_102_0.M[575]++;
673 __CLOVER_102_0.S[2453]++;IPage page = getPage(name);
674
675 __CLOVER_102_0.S[2454]++;activate(page);
676 } finally { }}
677
678 /** @since 3.0 */
679
680 public void activate(IPage page)
681 {try { __CLOVER_102_0.M[576]++;
682 __CLOVER_102_0.S[2455]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_102_0.CT[457] != 0)) || (++__CLOVER_102_0.CF[457] == 0))){
683 __CLOVER_102_0.S[2456]++;LOG.debug("Activating page " + page);}
684
685 __CLOVER_102_0.S[2457]++;Tapestry.clearMethodInvocations();
686
687 __CLOVER_102_0.S[2458]++;page.validate(this);
688
689 __CLOVER_102_0.S[2459]++;Tapestry.checkMethodInvocation(
690 Tapestry.ABSTRACTPAGE_VALIDATE_METHOD_ID,
691 "validate()",
692 page);
693
694 __CLOVER_102_0.S[2460]++;setPage(page);
695 } finally { }}
696
697 /**
698 * @since 3.0
699 */
700 public String toString()
701 {try { __CLOVER_102_0.M[577]++;
702 __CLOVER_102_0.S[2461]++;ToStringBuilder b = new ToStringBuilder(this);
703
704 __CLOVER_102_0.S[2462]++;b.append("rewinding", _rewinding);
705
706 __CLOVER_102_0.S[2463]++;if ((((_service != null) && (++__CLOVER_102_0.CT[458] != 0)) || (++__CLOVER_102_0.CF[458] == 0))){
707 __CLOVER_102_0.S[2464]++;b.append("service", _service.getName());}
708
709 __CLOVER_102_0.S[2465]++;b.append("serviceParameters", _serviceParameters);
710
711 __CLOVER_102_0.S[2466]++;if ((((_loadedPages != null) && (++__CLOVER_102_0.CT[459] != 0)) || (++__CLOVER_102_0.CF[459] == 0))){
712 __CLOVER_102_0.S[2467]++;b.append("loadedPages", _loadedPages.keySet());}
713
714 __CLOVER_102_0.S[2468]++;b.append("attributes", _attributes);
715 __CLOVER_102_0.S[2469]++;b.append("targetActionId", _targetActionId);
716 __CLOVER_102_0.S[2470]++;b.append("targetComponent", _targetComponent);
717
718 __CLOVER_102_0.S[2471]++;return b.toString();
719 } finally { }}
720 }