Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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 }