KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > AbstractPage


1 // Copyright 2004, 2005 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;
16
17 import java.util.EventListener JavaDoc;
18 import java.util.Locale JavaDoc;
19
20 import javax.swing.event.EventListenerList JavaDoc;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.hivemind.ApplicationRuntimeException;
25 import org.apache.tapestry.event.ChangeObserver;
26 import org.apache.tapestry.event.PageBeginRenderListener;
27 import org.apache.tapestry.event.PageDetachListener;
28 import org.apache.tapestry.event.PageEndRenderListener;
29 import org.apache.tapestry.event.PageEvent;
30 import org.apache.tapestry.event.PageAttachListener;
31 import org.apache.tapestry.event.PageRenderListener;
32 import org.apache.tapestry.event.PageValidateListener;
33 import org.apache.tapestry.util.StringSplitter;
34
35 /**
36  * Abstract base class implementing the {@link IPage}interface.
37  *
38  * @author Howard Lewis Ship, David Solis
39  * @since 0.2.9
40  */

41
42 public abstract class AbstractPage extends BaseComponent implements IPage
43 {
44     private static final Log LOG = LogFactory.getLog(AbstractPage.class);
45
46     /**
47      * Object to be notified when a observered property changes. Observered properties are the ones
48      * that will be persisted between request cycles. Unobserved properties are reconstructed.
49      */

50
51     private ChangeObserver _changeObserver;
52
53     /**
54      * The {@link IEngine}the page is currently attached to.
55      */

56
57     private IEngine _engine;
58
59     /**
60      * The visit object, if any, for the application. Set inside {@link #attach(IEngine)}and
61      * cleared by {@link #detach()}.
62      */

63
64     private Object JavaDoc _visit;
65
66     /**
67      * The qualified name of the page, which may be prefixed by the namespace.
68      *
69      * @since 2.3
70      */

71
72     private String JavaDoc _pageName;
73
74     /**
75      * Set when the page is attached to the engine.
76      */

77
78     private IRequestCycle _requestCycle;
79
80     /**
81      * The locale of the page, initially determined from the {@link IEngine engine}.
82      */

83
84     private Locale JavaDoc _locale;
85
86     /**
87      * A list of listeners for the page.
88      *
89      * @see PageBeginRenderListener
90      * @see PageEndRenderListener
91      * @see PageDetachListener
92      * @since 1.0.5
93      */

94
95     private EventListenerList JavaDoc _listenerList;
96
97     /**
98      * The output encoding to be used when rendering this page. This value is cached from the
99      * engine.
100      *
101      * @since 3.0
102      */

103     private String JavaDoc _outputEncoding;
104
105     /**
106      * Standard constructor; invokes {@link #initialize()}to configure initial values for
107      * properties of the page.
108      *
109      * @since 2.2
110      */

111
112     public AbstractPage()
113     {
114         initialize();
115     }
116
117     /**
118      * Prepares the page to be returned to the pool.
119      * <ul>
120      * <li>Clears the changeObserved property
121      * <li>Invokes {@link PageDetachListener#pageDetached(PageEvent)}on all listeners
122      * <li>Invokes {@link #initialize()}to clear/reset any properties
123      * <li>Clears the engine, visit and requestCycle properties
124      * </ul>
125      * <p>
126      * Subclasses may override this method, but must invoke this implementation (usually, last).
127      * @see PageDetachListener
128      */

129
130     public void detach()
131     {
132         Tapestry.addMethodInvocation(Tapestry.ABSTRACTPAGE_DETACH_METHOD_ID);
133
134         // Do this first,so that any changes to persistent properties do not
135
// cause errors.
136

137         _changeObserver = null;
138
139         firePageDetached();
140
141         initialize();
142
143         _engine = null;
144         _visit = null;
145         _requestCycle = null;
146     }
147
148     /**
149      * Method invoked from the constructor, and from {@link #detach()}to (re-)initialize properties
150      * of the page. This is most useful when properties have non-null initial values.
151      * <p>
152      * Subclasses may override this implementation (which is empty).
153      *
154      * @since 2.2
155      * @deprecated To be removed in 4.1 with no replacement.
156      * @see PageDetachListener
157      * @see PageAttachListener
158      */

159
160     protected void initialize()
161     {
162         // Does nothing.
163
}
164
165     public IEngine getEngine()
166     {
167         return _engine;
168     }
169
170     public ChangeObserver getChangeObserver()
171     {
172         return _changeObserver;
173     }
174
175     /**
176      * Returns the name of the page.
177      */

178
179     public String JavaDoc getExtendedId()
180     {
181         return _pageName;
182     }
183
184     /**
185      * Pages always return null for idPath.
186      */

187
188     public String JavaDoc getIdPath()
189     {
190         return null;
191     }
192
193     /**
194      * Returns the locale for the page, which may be null if the locale is not known (null
195      * corresponds to the "default locale").
196      */

197
198     public Locale JavaDoc getLocale()
199     {
200         return _locale;
201     }
202
203     public void setLocale(Locale JavaDoc value)
204     {
205         if (_locale != null)
206             throw new ApplicationRuntimeException(Tapestry
207                     .getMessage("AbstractPage.attempt-to-change-locale"));
208
209         _locale = value;
210     }
211
212     public IComponent getNestedComponent(String JavaDoc path)
213     {
214         StringSplitter splitter;
215         IComponent current;
216         String JavaDoc[] elements;
217         int i;
218
219         if (path == null)
220             return this;
221
222         splitter = new StringSplitter('.');
223         current = this;
224
225         elements = splitter.splitToArray(path);
226         for (i = 0; i < elements.length; i++)
227         {
228             current = current.getComponent(elements[i]);
229         }
230
231         return current;
232
233     }
234
235     /**
236      * Called by the {@link IEngine engine}to attach the page to itself. Does <em>not</em> change
237      * the locale, but since a page is selected from the
238      * {@link org.apache.tapestry.engine.IPageSource}pool based on its locale matching the engine's
239      * locale, they should match anyway.
240      */

241
242     public void attach(IEngine engine, IRequestCycle cycle)
243     {
244         if (_engine != null)
245             LOG.error(this + " attach(" + engine + "), but engine = " + _engine);
246
247         _engine = engine;
248         _requestCycle = cycle;
249
250         firePageAttached();
251     }
252
253     /**
254      * <ul>
255      * <li>Invokes {@link PageBeginRenderListener#pageBeginRender(PageEvent)}
256      * <li>Invokes {@link #beginResponse(IMarkupWriter, IRequestCycle)}
257      * <li>Invokes {@link IRequestCycle#commitPageChanges()}(if not rewinding)
258      * <li>Invokes {@link #render(IMarkupWriter, IRequestCycle)}
259      * <li>Invokes {@link PageEndRenderListener#pageEndRender(PageEvent)}(this occurs even if a
260      * previous step throws an exception)
261      */

262
263     public void renderPage(IMarkupWriter writer, IRequestCycle cycle)
264     {
265         try
266         {
267             firePageBeginRender();
268
269             beginResponse(writer, cycle);
270
271             if (!cycle.isRewinding())
272                 cycle.commitPageChanges();
273
274             render(writer, cycle);
275         }
276         finally
277         {
278             firePageEndRender();
279         }
280     }
281
282     public void setChangeObserver(ChangeObserver value)
283     {
284         _changeObserver = value;
285     }
286
287     /** @since 3.0 * */
288
289     public void setPageName(String JavaDoc pageName)
290     {
291         if (_pageName != null)
292             throw new ApplicationRuntimeException(Tapestry
293                     .getMessage("AbstractPage.attempt-to-change-name"));
294
295         _pageName = pageName;
296     }
297
298     /**
299      * By default, pages are not protected and this method does nothing.
300      */

301
302     public void validate(IRequestCycle cycle)
303     {
304         Tapestry.addMethodInvocation(Tapestry.ABSTRACTPAGE_VALIDATE_METHOD_ID);
305
306         firePageValidate();
307     }
308
309     /**
310      * Does nothing, subclasses may override as needed.
311      *
312      * @deprecated To be removed in 4.0. Implement {@link PageRenderListener}instead.
313      */

314
315     public void beginResponse(IMarkupWriter writer, IRequestCycle cycle)
316     {
317     }
318
319     public IRequestCycle getRequestCycle()
320     {
321         return _requestCycle;
322     }
323
324     /**
325      * Returns the visit object obtained from the engine via {@link IEngine#getVisit(IRequestCycle)}.
326      */

327
328     public Object JavaDoc getVisit()
329     {
330         if (_visit == null)
331             _visit = _engine.getVisit(_requestCycle);
332
333         return _visit;
334     }
335
336     /**
337      * Convienience methods, simply invokes {@link IEngine#getGlobal()}.
338      *
339      * @since 2.3
340      */

341
342     public Object JavaDoc getGlobal()
343     {
344         return _engine.getGlobal();
345     }
346
347     public void addPageDetachListener(PageDetachListener listener)
348     {
349         addListener(PageDetachListener.class, listener);
350     }
351
352     private void addListener(Class JavaDoc listenerClass, EventListener JavaDoc listener)
353     {
354         if (_listenerList == null)
355             _listenerList = new EventListenerList JavaDoc();
356
357         _listenerList.add(listenerClass, listener);
358     }
359
360     /**
361      * @since 2.1-beta-2
362      */

363
364     private void removeListener(Class JavaDoc listenerClass, EventListener JavaDoc listener)
365     {
366         if (_listenerList != null)
367             _listenerList.remove(listenerClass, listener);
368     }
369
370     public void addPageRenderListener(PageRenderListener listener)
371     {
372         addPageBeginRenderListener(listener);
373         addPageEndRenderListener(listener);
374     }
375
376     /** @since 4.0 */
377     public void addPageBeginRenderListener(PageBeginRenderListener listener)
378     {
379         addListener(PageBeginRenderListener.class, listener);
380     }
381
382     /** @since 4.0 */
383     public void addPageEndRenderListener(PageEndRenderListener listener)
384     {
385         addListener(PageEndRenderListener.class, listener);
386     }
387
388     /** @since 4.0 */
389     public void removePageBeginRenderListener(PageBeginRenderListener listener)
390     {
391         removeListener(PageBeginRenderListener.class, listener);
392     }
393
394     /** @since 4.0 */
395     public void removePageEndRenderListener(PageEndRenderListener listener)
396     {
397         removeListener(PageEndRenderListener.class, listener);
398     }
399
400     /**
401      * @since 4.0
402      */

403
404     protected void firePageAttached()
405     {
406         if (_listenerList == null)
407             return;
408
409         PageEvent event = null;
410         Object JavaDoc[] listeners = _listenerList.getListenerList();
411
412         for (int i = 0; i < listeners.length; i += 2)
413         {
414             if (listeners[i] == PageAttachListener.class)
415             {
416                 PageAttachListener l = (PageAttachListener) listeners[i + 1];
417
418                 if (event == null)
419                     event = new PageEvent(this, _requestCycle);
420
421                 l.pageAttached(event);
422             }
423         }
424     }
425
426     /**
427      * @since 1.0.5
428      */

429
430     protected void firePageDetached()
431     {
432         if (_listenerList == null)
433             return;
434
435         PageEvent event = null;
436         Object JavaDoc[] listeners = _listenerList.getListenerList();
437
438         for (int i = 0; i < listeners.length; i += 2)
439         {
440             if (listeners[i] == PageDetachListener.class)
441             {
442                 PageDetachListener l = (PageDetachListener) listeners[i + 1];
443
444                 if (event == null)
445                     event = new PageEvent(this, _requestCycle);
446
447                 l.pageDetached(event);
448             }
449         }
450     }
451
452     /**
453      * @since 1.0.5
454      */

455
456     protected void firePageBeginRender()
457     {
458         if (_listenerList == null)
459             return;
460
461         PageEvent event = null;
462         Object JavaDoc[] listeners = _listenerList.getListenerList();
463
464         for (int i = 0; i < listeners.length; i += 2)
465         {
466             if (listeners[i] == PageBeginRenderListener.class)
467             {
468                 PageBeginRenderListener l = (PageBeginRenderListener) listeners[i + 1];
469
470                 if (event == null)
471                     event = new PageEvent(this, _requestCycle);
472
473                 l.pageBeginRender(event);
474             }
475         }
476     }
477
478     /**
479      * @since 1.0.5
480      */

481
482     protected void firePageEndRender()
483     {
484         if (_listenerList == null)
485             return;
486
487         PageEvent event = null;
488         Object JavaDoc[] listeners = _listenerList.getListenerList();
489
490         for (int i = 0; i < listeners.length; i += 2)
491         {
492             if (listeners[i] == PageEndRenderListener.class)
493             {
494                 PageEndRenderListener l = (PageEndRenderListener) listeners[i + 1];
495
496                 if (event == null)
497                     event = new PageEvent(this, _requestCycle);
498
499                 l.pageEndRender(event);
500             }
501         }
502     }
503
504     /**
505      * @since 2.1-beta-2
506      */

507
508     public void removePageDetachListener(PageDetachListener listener)
509     {
510         removeListener(PageDetachListener.class, listener);
511     }
512
513     public void removePageRenderListener(PageRenderListener listener)
514     {
515         removePageBeginRenderListener(listener);
516         removePageEndRenderListener(listener);
517     }
518
519     /** @since 2.2 * */
520
521     public void beginPageRender()
522     {
523         firePageBeginRender();
524     }
525
526     /** @since 2.2 * */
527
528     public void endPageRender()
529     {
530         firePageEndRender();
531     }
532
533     /** @since 3.0 * */
534
535     public String JavaDoc getPageName()
536     {
537         return _pageName;
538     }
539
540     public void addPageValidateListener(PageValidateListener listener)
541     {
542         addListener(PageValidateListener.class, listener);
543     }
544
545     public void removePageValidateListener(PageValidateListener listener)
546     {
547         removeListener(PageValidateListener.class, listener);
548     }
549
550     /** @since 4.0 */
551     public void addPageAttachListener(PageAttachListener listener)
552     {
553         addListener(PageAttachListener.class, listener);
554     }
555
556     /** @since 4.0 */
557     public void removePageAttachListener(PageAttachListener listener)
558     {
559         removeListener(PageAttachListener.class, listener);
560     }
561
562     protected void firePageValidate()
563     {
564         if (_listenerList == null)
565             return;
566
567         PageEvent event = null;
568         Object JavaDoc[] listeners = _listenerList.getListenerList();
569
570         for (int i = 0; i < listeners.length; i += 2)
571         {
572             if (listeners[i] == PageValidateListener.class)
573             {
574                 PageValidateListener l = (PageValidateListener) listeners[i + 1];
575
576                 if (event == null)
577                     event = new PageEvent(this, _requestCycle);
578
579                 l.pageValidate(event);
580             }
581         }
582     }
583
584     /**
585      * Returns the output encoding to be used when rendering this page. This value is usually cached
586      * from the Engine.
587      *
588      * @since 3.0
589      */

590     protected String JavaDoc getOutputEncoding()
591     {
592         if (_outputEncoding == null)
593             _outputEncoding = getEngine().getOutputEncoding();
594
595         return _outputEncoding;
596     }
597 }
Popular Tags