Source Code Cross Referenced for Page.java in  » J2EE » wicket » org » apache » wicket » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » wicket » org.apache.wicket 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:        package org.apache.wicket;
0018:
0019:        import java.io.IOException;
0020:        import java.io.ObjectInputStream;
0021:        import java.io.ObjectOutputStream;
0022:        import java.io.ObjectStreamException;
0023:        import java.util.ArrayList;
0024:        import java.util.HashSet;
0025:        import java.util.List;
0026:        import java.util.Set;
0027:
0028:        import org.apache.wicket.authorization.IAuthorizationStrategy;
0029:        import org.apache.wicket.authorization.UnauthorizedActionException;
0030:        import org.apache.wicket.authorization.strategies.page.SimplePageAuthorizationStrategy;
0031:        import org.apache.wicket.feedback.IFeedback;
0032:        import org.apache.wicket.markup.MarkupException;
0033:        import org.apache.wicket.markup.MarkupStream;
0034:        import org.apache.wicket.markup.html.WebPage;
0035:        import org.apache.wicket.markup.html.form.Form;
0036:        import org.apache.wicket.model.IModel;
0037:        import org.apache.wicket.request.RequestParameters;
0038:        import org.apache.wicket.session.pagemap.IPageMapEntry;
0039:        import org.apache.wicket.settings.IDebugSettings;
0040:        import org.apache.wicket.util.concurrent.ConcurrentHashMap;
0041:        import org.apache.wicket.util.lang.Classes;
0042:        import org.apache.wicket.util.lang.Objects;
0043:        import org.apache.wicket.util.string.StringValue;
0044:        import org.apache.wicket.util.value.Count;
0045:        import org.apache.wicket.version.IPageVersionManager;
0046:        import org.apache.wicket.version.undo.Change;
0047:        import org.slf4j.Logger;
0048:        import org.slf4j.LoggerFactory;
0049:
0050:        /**
0051:         * Abstract base class for pages. As a MarkupContainer subclass, a Page can
0052:         * contain a component hierarchy and markup in some markup language such as
0053:         * HTML. Users of the framework should not attempt to subclass Page directly.
0054:         * Instead they should subclass a subclass of Page that is appropriate to the
0055:         * markup type they are using, such as WebPage (for HTML markup).
0056:         * <ul>
0057:         * <li><b>Construction </b>- When a page is constructed, it is automatically
0058:         * added to the current PageMap in the Session. When a Page is added to the
0059:         * Session's PageMap, the PageMap assigns the Page an id. A PageMap is roughly
0060:         * equivalent to a browser window and encapsulates a set of pages accessible
0061:         * through that window. When a popup window is created, a new PageMap is created
0062:         * for the popup.
0063:         * 
0064:         * <li><b>Identity </b>- The Session that a Page is contained in can be
0065:         * retrieved by calling Page.getSession(). Page identifiers start at 0 for each
0066:         * PageMap in the Session and increment as new pages are added to the map. The
0067:         * PageMap-(and Session)-unique identifier assigned to a given Page can be
0068:         * retrieved by calling getId(). So, the first Page added to a new user Session
0069:         * will always be named "0".
0070:         * 
0071:         * <li><b>LifeCycle </b>- Subclasses of Page which are interested in lifecycle
0072:         * events can override onBeginRequest, onEndRequest() and onModelChanged(). The
0073:         * onBeginRequest() method is inherited from Component. A call to
0074:         * onBeginRequest() is made for every Component on a Page before page rendering
0075:         * begins. At the end of a request (when rendering has completed) to a Page, the
0076:         * onEndRequest() method is called for every Component on the Page.
0077:         * 
0078:         * <li><b>Nested Component Hierarchy </b>- The Page class is a subclass of
0079:         * MarkupContainer. All MarkupContainers can have "associated markup", which
0080:         * resides alongside the Java code by default. All MarkupContainers are also
0081:         * Component containers. Through nesting, of containers, a Page can contain any
0082:         * arbitrary tree of Components. For more details on MarkupContainers, see
0083:         * {@link org.apache.wicket.MarkupContainer}.
0084:         * 
0085:         * <li><b>Bookmarkable Pages </b>- Pages can be constructed with any
0086:         * constructor when they are being used in a Wicket session, but if you wish to
0087:         * link to a Page using a URL that is "bookmarkable" (which implies that the URL
0088:         * will not have any session information encoded in it, and that you can call
0089:         * this page directly without having a session first directly from your
0090:         * browser), you need to implement your Page with a no-arg constructor or with a
0091:         * constructor that accepts a PageParameters argument (which wraps any query
0092:         * string parameters for a request). In case the page has both constructors, the
0093:         * constructor with PageParameters will be used.
0094:         * 
0095:         * <li><b>Models </b>- Pages, like other Components, can have models (see
0096:         * {@link IModel}). A Page can be assigned a model by passing one to the Page's
0097:         * constructor, by overriding initModel() or with an explicit invocation of
0098:         * setModel(). If the model is a
0099:         * {@link org.apache.wicket.model.CompoundPropertyModel}, Components on the
0100:         * Page can use the Page's model implicitly via container inheritance. If a
0101:         * Component is not assigned a model, the initModel() override in Component will
0102:         * cause that Component to use the nearest CompoundModel in the parent chain, in
0103:         * this case, the Page's model. For basic CompoundModels, the name of the
0104:         * Component determines which property of the implicit page model the component
0105:         * is bound to. If more control is desired over the binding of Components to the
0106:         * page model (for example, if you want to specify some property expression
0107:         * other than the component's name for retrieving the model object),
0108:         * BoundCompoundPropertyModel can be used.
0109:         * 
0110:         * <li><b>Back Button </b>- Pages can support the back button by enabling
0111:         * versioning with a call to setVersioned(boolean). If a Page is versioned and
0112:         * changes occur to it which need to be tracked, a verison manager will be
0113:         * installed using the overridable factory method newVersionManager(). The
0114:         * default version manager returned by the base implementation of this method is
0115:         * an instance of UndoPageVersionManager, which manages versions of a page by
0116:         * keeping change records that can be reversed at a later time.
0117:         * 
0118:         * <li><b>Security </b>- See {@link IAuthorizationStrategy},
0119:         * {@link SimplePageAuthorizationStrategy}
0120:         * 
0121:         * @see org.apache.wicket.markup.html.WebPage
0122:         * @see org.apache.wicket.MarkupContainer
0123:         * @see org.apache.wicket.model.CompoundPropertyModel
0124:         * @see org.apache.wicket.model.BoundCompoundPropertyModel
0125:         * @see org.apache.wicket.Component
0126:         * @see org.apache.wicket.version.IPageVersionManager
0127:         * @see org.apache.wicket.version.undo.UndoPageVersionManager
0128:         * 
0129:         * @author Jonathan Locke
0130:         * @author Chris Turner
0131:         * @author Eelco Hillenius
0132:         * @author Johan Compagner
0133:         */
0134:        public abstract class Page extends MarkupContainer implements 
0135:                IRedirectListener, IPageMapEntry {
0136:            /**
0137:             * You can set implementation of the interface in the
0138:             * {@link Page#serializer} then that implementation will handle the
0139:             * serialization of this page. The serializePage method is called from the
0140:             * writeObject method then the implementation override the default
0141:             * serialization.
0142:             * 
0143:             * @author jcompagner
0144:             */
0145:            public static interface IPageSerializer {
0146:                /**
0147:                 * Called when page is being deserialized
0148:                 * 
0149:                 * @param id
0150:                 *            TODO
0151:                 * @param name
0152:                 *            TODO
0153:                 * @param page
0154:                 * @param stream
0155:                 * @return New instance to replace page instance being deserialized
0156:                 * @throws IOException
0157:                 * @throws ClassNotFoundException
0158:                 * 
0159:                 */
0160:                public Page deserializePage(int id, String name, Page page,
0161:                        ObjectInputStream stream) throws IOException,
0162:                        ClassNotFoundException;
0163:
0164:                /**
0165:                 * Called from the {@link Page#writeObject()} method.
0166:                 * 
0167:                 * @param page
0168:                 *            The page that must be serialized.
0169:                 * @param stream
0170:                 *            ObjectOutputStream
0171:                 * @throws IOException
0172:                 */
0173:                public void serializePage(Page page, ObjectOutputStream stream)
0174:                        throws IOException;
0175:            }
0176:
0177:            /**
0178:             * When passed to {@link Page#getVersion(int)} the latest page version is
0179:             * returned.
0180:             */
0181:            public static final int LATEST_VERSION = -1;
0182:
0183:            /**
0184:             * This is a thread local that is used for serializing page references in
0185:             * this page.It stores a {@link IPageSerializer} which can be set by the
0186:             * outside world to do the serialization of this page.
0187:             */
0188:            public static final ThreadLocal serializer = new ThreadLocal();
0189:
0190:            /** True if a new version was created for this request. */
0191:            private static final short FLAG_NEW_VERSION = FLAG_RESERVED3;
0192:
0193:            /** True if the page should try to be stateless */
0194:            private static final int FLAG_STATELESS_HINT = FLAG_RESERVED5;
0195:
0196:            /** True if component changes are being tracked. */
0197:            private static final short FLAG_TRACK_CHANGES = FLAG_RESERVED4;
0198:
0199:            /** Log. */
0200:            private static final Logger log = LoggerFactory
0201:                    .getLogger(Page.class);
0202:
0203:            /**
0204:             * {@link #isBookmarkable()} is expensive, we cache the result here
0205:             */
0206:            private static final ConcurrentHashMap pageClassToBookmarkableCache = new ConcurrentHashMap();
0207:
0208:            private static final long serialVersionUID = 1L;
0209:
0210:            /** Used to create page-unique numbers */
0211:            private short autoIndex;
0212:
0213:            /** Numeric version of this page's id */
0214:            private int numericId;
0215:
0216:            /** The PageMap within the session that this page is stored in */
0217:            private transient IPageMap pageMap;
0218:
0219:            /** Name of PageMap that this page is stored in */
0220:            private String pageMapName;
0221:
0222:            // temporary variable to pass page instance from readObject to readResolve
0223:            private transient Page pageToResolve = null;
0224:
0225:            /** Set of components that rendered if component use checking is enabled */
0226:            private transient Set renderedComponents;
0227:
0228:            /**
0229:             * Boolean if the page is stateless, so it doesn't have to be in the page
0230:             * map, will be set in urlFor
0231:             */
0232:            private transient Boolean stateless = null;
0233:
0234:            /** Version manager for this page */
0235:            private IPageVersionManager versionManager;
0236:
0237:            /**
0238:             * Constructor.
0239:             */
0240:            protected Page() {
0241:                // A Page's id is not determined until setId is called when the Page is
0242:                // added to a PageMap in the Session.
0243:                super (null);
0244:                init();
0245:            }
0246:
0247:            /**
0248:             * Constructor.
0249:             * 
0250:             * @param model
0251:             *            See Component
0252:             * @see Component#Component(String, IModel)
0253:             */
0254:            protected Page(final IModel model) {
0255:                // A Page's id is not determined until setId is called when the Page is
0256:                // added to a PageMap in the Session.
0257:                super (null, model);
0258:                init();
0259:            }
0260:
0261:            /**
0262:             * Constructor.
0263:             * 
0264:             * @param pageMap
0265:             *            The page map to put this page in
0266:             */
0267:            protected Page(final IPageMap pageMap) {
0268:                // A Page's id is not determined until setId is called when the Page is
0269:                // added to a PageMap in the Session.
0270:                super (null);
0271:                init(pageMap);
0272:            }
0273:
0274:            /**
0275:             * Constructor.
0276:             * 
0277:             * @param pageMap
0278:             *            the name of the page map to put this page in
0279:             * @param model
0280:             *            See Component
0281:             * @see Component#Component(String, IModel)
0282:             */
0283:            protected Page(final IPageMap pageMap, final IModel model) {
0284:                // A Page's id is not determined until setId is called when the Page is
0285:                // added to a PageMap in the Session.
0286:                super (null, model);
0287:                init(pageMap);
0288:            }
0289:
0290:            /**
0291:             * Constructor.
0292:             * 
0293:             * @param parameters
0294:             *            externally passed parameters
0295:             * @see PageParameters
0296:             */
0297:            protected Page(final PageParameters parameters) {
0298:                super (null);
0299:                init();
0300:            }
0301:
0302:            /**
0303:             * Called right after a component's listener method (the provided method
0304:             * argument) was called. This method may be used to clean up dependencies,
0305:             * do logging, etc. NOTE: this method will also be called when
0306:             * {@link WebPage#beforeCallComponent(Component, RequestListenerInterface)}
0307:             * or the method invocation itself failed.
0308:             * 
0309:             * @param component
0310:             *            the component that is to be called
0311:             * @param listener
0312:             *            the listener of that component that is to be called
0313:             */
0314:            // TODO Post-1.3: We should create a listener on Application like
0315:            // IComponentInstantiationListener
0316:            // that forwards to IAuthorizationStrategy for RequestListenerInterface
0317:            // invocations.
0318:            public void afterCallComponent(final Component component,
0319:                    final RequestListenerInterface listener) {
0320:            }
0321:
0322:            /**
0323:             * Called just before a component's listener method (the provided method
0324:             * argument) is called. This method may be used to set up dependencies,
0325:             * enforce authorization, etc. NOTE: if this method fails, the method will
0326:             * not be excuted. Method
0327:             * {@link WebPage#afterCallComponent(Component, RequestListenerInterface)}
0328:             * will always be called.
0329:             * 
0330:             * @param component
0331:             *            the component that is to be called
0332:             * @param listener
0333:             *            the listener of that component that is to be called
0334:             */
0335:            // TODO Post-1.3: We should create a listener on Application like
0336:            // IComponentInstantiationListener
0337:            // that forwards to IAuthorizationStrategy for RequestListenerInterface
0338:            // invocations.
0339:            public void beforeCallComponent(final Component component,
0340:                    final RequestListenerInterface listener) {
0341:            }
0342:
0343:            /**
0344:             * Adds a component to the set of rendered components.
0345:             * 
0346:             * @param component
0347:             *            The component that was rendered
0348:             */
0349:            public final void componentRendered(final Component component) {
0350:                // Inform the page that this component rendered
0351:                if (Application.get().getDebugSettings().getComponentUseCheck()) {
0352:                    if (renderedComponents == null) {
0353:                        renderedComponents = new HashSet();
0354:                    }
0355:                    if (renderedComponents.add(component) == false) {
0356:                        throw new MarkupException(
0357:                                "The component "
0358:                                        + component
0359:                                        + " has the same wicket:id as another component already added at the same level");
0360:                    }
0361:                    if (log.isDebugEnabled()) {
0362:                        log.debug("Rendered " + component);
0363:                    }
0364:                }
0365:            }
0366:
0367:            /**
0368:             * Detaches any attached models referenced by this page.
0369:             */
0370:            public void detachModels() {
0371:                // // visit all this page's children to detach the models
0372:                // visitChildren(new IVisitor()
0373:                // {
0374:                // public Object component(Component component)
0375:                // {
0376:                // try
0377:                // {
0378:                // // detach any models of the component
0379:                // component.detachModels();
0380:                // }
0381:                // catch (Exception e) // catch anything; we MUST detach all models
0382:                // {
0383:                // log.error("detaching models of component " + component + " failed:",
0384:                // e);
0385:                // }
0386:                // return IVisitor.CONTINUE_TRAVERSAL;
0387:                // }
0388:                // });
0389:
0390:                super .detachModels();
0391:            }
0392:
0393:            /**
0394:             * Mark this page as dirty in the session
0395:             */
0396:            public final void dirty() {
0397:                Session.get().dirtyPage(this );
0398:            }
0399:
0400:            /**
0401:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL.
0402:             * 
0403:             * This method is called when a component was rendered standalone. If it is
0404:             * a markupcontainer then the rendering for that container is checked.
0405:             * 
0406:             * @param component
0407:             * 
0408:             */
0409:            public final void endComponentRender(Component component) {
0410:                if (component instanceof  MarkupContainer) {
0411:                    checkRendering((MarkupContainer) component);
0412:                } else {
0413:                    renderedComponents = null;
0414:                }
0415:            }
0416:
0417:            /**
0418:             * Expire the oldest version of this page
0419:             */
0420:            public final void expireOldestVersion() {
0421:                if (versionManager != null) {
0422:                    versionManager.expireOldestVersion();
0423:                }
0424:            }
0425:
0426:            /**
0427:             * @return The current ajax version number of this page.
0428:             */
0429:            public final int getAjaxVersionNumber() {
0430:                return versionManager == null ? 0 : versionManager
0431:                        .getAjaxVersionNumber();
0432:            }
0433:
0434:            /**
0435:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0436:             * 
0437:             * Get a page unique number, which will be increased with each call.
0438:             * 
0439:             * @return A page unique number
0440:             */
0441:            public final short getAutoIndex() {
0442:                return autoIndex++;
0443:            }
0444:
0445:            /**
0446:             * @return The current version number of this page. If the page has been
0447:             *         changed once, the return value will be 1. If the page has not yet
0448:             *         been revised, the version returned will be 0, indicating that the
0449:             *         page is still in its original state.
0450:             */
0451:            public final int getCurrentVersionNumber() {
0452:                return versionManager == null ? 0 : versionManager
0453:                        .getCurrentVersionNumber();
0454:            }
0455:
0456:            /**
0457:             * @see org.apache.wicket.Component#getId()
0458:             */
0459:            public final String getId() {
0460:                return Integer.toString(numericId);
0461:            }
0462:
0463:            /**
0464:             * @see org.apache.wicket.session.pagemap.IPageMapEntry#getNumericId()
0465:             */
0466:            public int getNumericId() {
0467:                return numericId;
0468:            }
0469:
0470:            /**
0471:             * @see org.apache.wicket.session.pagemap.IPageMapEntry#getPageClass()
0472:             */
0473:            public final Class getPageClass() {
0474:                return getClass();
0475:            }
0476:
0477:            /**
0478:             * @return Returns the PageMap that this Page is stored in.
0479:             */
0480:            public final IPageMap getPageMap() {
0481:                // If the transient needs to be restored
0482:                if (pageMap == null) {
0483:                    // Look the page map up in the session
0484:                    pageMap = PageMap.forName(pageMapName);
0485:                }
0486:                return pageMap;
0487:            }
0488:
0489:            /**
0490:             * @return Get a page map entry for this page. By default, this is the page
0491:             *         itself. But if you know of some way to compress the state for the
0492:             *         page, you can return a custom implementation that produces the
0493:             *         page on-the-fly.
0494:             */
0495:            public IPageMapEntry getPageMapEntry() {
0496:                return this ;
0497:            }
0498:
0499:            /**
0500:             * @return
0501:             */
0502:            public final String getPageMapName() {
0503:                return pageMapName;
0504:            }
0505:
0506:            /**
0507:             * @return Size of this page in bytes
0508:             */
0509:            public final long getSizeInBytes() {
0510:                pageMap = null;
0511:                return Objects.sizeof(this );
0512:            }
0513:
0514:            /**
0515:             * Returns whether the page should try to be stateless. To be stateless,
0516:             * getStatelessHint() of every component on page (and it's behavior) must
0517:             * return true and the page must be bookmarkable.
0518:             * 
0519:             * @see org.apache.wicket.Component#getStatelessHint()
0520:             */
0521:            public final boolean getStatelessHint() {
0522:                return getFlag(FLAG_STATELESS_HINT);
0523:            }
0524:
0525:            /**
0526:             * Override this method to implement a custom way of producing a version of
0527:             * a Page when it cannot be found in the Session.
0528:             * 
0529:             * @param versionNumber
0530:             *            The version desired
0531:             * @return A Page object with the component/model hierarchy that was
0532:             *         attached to this page at the time represented by the requested
0533:             *         version.
0534:             */
0535:            public Page getVersion(final int versionNumber) {
0536:                // If we're still the original Page and that's what's desired
0537:                if (versionManager == null) {
0538:                    if (versionNumber == 0 || versionNumber == LATEST_VERSION) {
0539:                        return this ;
0540:                    } else {
0541:                        log
0542:                                .info("No version manager available to retrieve requested versionNumber "
0543:                                        + versionNumber);
0544:                        return null;
0545:                    }
0546:                } else {
0547:                    // Save original change tracking state
0548:                    final boolean originalTrackChanges = getFlag(FLAG_TRACK_CHANGES);
0549:
0550:                    try {
0551:                        // While the version manager is potentially playing around with
0552:                        // the Page, it may change the page in order to undo changes and
0553:                        // we don't want change tracking going on while its doing this.
0554:                        setFlag(FLAG_TRACK_CHANGES, false);
0555:
0556:                        // Get page of desired version
0557:                        final Page page;
0558:                        if (versionNumber != LATEST_VERSION) {
0559:                            page = versionManager.getVersion(versionNumber);
0560:                        } else {
0561:                            page = versionManager
0562:                                    .getVersion(getCurrentVersionNumber());
0563:                        }
0564:
0565:                        // If we went all the way back to the original page
0566:                        if (page != null && page.getCurrentVersionNumber() == 0
0567:                                && page.getAjaxVersionNumber() == 0) {
0568:                            // remove version info
0569:                            page.versionManager = null;
0570:                        }
0571:
0572:                        return page;
0573:                    } finally {
0574:                        // Restore change tracking state
0575:                        setFlag(FLAG_TRACK_CHANGES, originalTrackChanges);
0576:                    }
0577:                }
0578:            }
0579:
0580:            /**
0581:             * @return Number of versions of this page
0582:             */
0583:            public final int getVersions() {
0584:                return versionManager == null ? 1 : versionManager
0585:                        .getVersions() + 1;
0586:            }
0587:
0588:            /**
0589:             * @return This page's component hierarchy as a string
0590:             */
0591:            public final String hierarchyAsString() {
0592:                final StringBuffer buffer = new StringBuffer();
0593:                buffer.append("Page " + getId() + " (version "
0594:                        + getCurrentVersionNumber() + ")");
0595:                visitChildren(new IVisitor() {
0596:                    public Object component(Component component) {
0597:                        int levels = 0;
0598:                        for (Component current = component; current != null; current = current
0599:                                .getParent()) {
0600:                            levels++;
0601:                        }
0602:                        buffer.append(StringValue.repeat(levels, "	")
0603:                                + component.getPageRelativePath() + ":"
0604:                                + Classes.simpleName(component.getClass()));
0605:                        return null;
0606:                    }
0607:                });
0608:                return buffer.toString();
0609:            }
0610:
0611:            /**
0612:             * Call this method when the current (ajax) request shouldn't merge the
0613:             * changes that are happening to the page with the previous version.
0614:             * 
0615:             * This is for example needed when you want to redirect to this page in an
0616:             * ajax request and then you do want to version normally..
0617:             * 
0618:             * This method doesn't do anything if the getRequest().mergeVersion doesn't
0619:             * return true.
0620:             */
0621:            public final void ignoreVersionMerge() {
0622:                if (getRequest().mergeVersion()) {
0623:                    mayTrackChangesFor(this , null);
0624:                    if (versionManager != null) {
0625:                        versionManager.ignoreVersionMerge();
0626:                    }
0627:                }
0628:            }
0629:
0630:            /**
0631:             * Bookmarkable page can be instantiated using a bookmarkable URL.
0632:             * 
0633:             * @return Returns true if the page is bookmarkable.
0634:             */
0635:            public boolean isBookmarkable() {
0636:                Boolean bookmarkable = (Boolean) pageClassToBookmarkableCache
0637:                        .get(getClass().getName());
0638:                if (bookmarkable == null) {
0639:                    try {
0640:
0641:                        if (getClass().getConstructor(new Class[] {}) != null) {
0642:                            bookmarkable = Boolean.TRUE;
0643:                        }
0644:
0645:                    } catch (Exception ignore) {
0646:                        try {
0647:                            if (getClass().getConstructor(
0648:                                    new Class[] { PageParameters.class }) != null) {
0649:                                bookmarkable = Boolean.TRUE;
0650:                            }
0651:                        } catch (Exception ignore2) {
0652:                        }
0653:                    }
0654:                    if (bookmarkable == null) {
0655:                        bookmarkable = Boolean.FALSE;
0656:                    }
0657:                    pageClassToBookmarkableCache.put(getClass().getName(),
0658:                            bookmarkable);
0659:                }
0660:                return bookmarkable.booleanValue();
0661:
0662:            }
0663:
0664:            /**
0665:             * Override this method and return true if your page is used to display
0666:             * Wicket errors. This can help the framework prevent infinite failure
0667:             * loops.
0668:             * 
0669:             * @return True if this page is intended to display an error to the end
0670:             *         user.
0671:             */
0672:            public boolean isErrorPage() {
0673:                return false;
0674:            }
0675:
0676:            /**
0677:             * Gets whether the page is stateless. Components on stateless page must not
0678:             * render any statefull urls, and components on statefull page must not
0679:             * render any stateless urls. Statefull urls are urls, which refer to a
0680:             * certain (current) page instance.
0681:             * 
0682:             * @return Whether to page is stateless
0683:             */
0684:            public final boolean isPageStateless() {
0685:                if (isBookmarkable() == false) {
0686:                    stateless = Boolean.FALSE;
0687:                    if (getStatelessHint()) {
0688:                        log
0689:                                .warn("Page '"
0690:                                        + this 
0691:                                        + "' is not stateless because it is not bookmarkable, "
0692:                                        + "but the stateless hint is set to true!");
0693:                    }
0694:                }
0695:
0696:                if (stateless == null) {
0697:                    final Object[] returnArray = new Object[1];
0698:                    Object returnValue = visitChildren(Component.class,
0699:                            new IVisitor() {
0700:                                public Object component(Component component) {
0701:                                    if (!component.isStateless()) {
0702:                                        returnArray[0] = component;
0703:                                        return Boolean.FALSE;
0704:                                    }
0705:
0706:                                    return CONTINUE_TRAVERSAL;
0707:                                }
0708:                            });
0709:                    if (returnValue == null) {
0710:                        stateless = Boolean.TRUE;
0711:                    } else if (returnValue instanceof  Boolean) {
0712:                        stateless = (Boolean) returnValue;
0713:                    }
0714:
0715:                    if (!stateless.booleanValue() && getStatelessHint()) {
0716:                        log.warn("Page '" + this 
0717:                                + "' is not stateless because of '"
0718:                                + returnArray[0]
0719:                                + "' but the stateless hint is set to true!");
0720:                    }
0721:                }
0722:
0723:                return stateless.booleanValue();
0724:            }
0725:
0726:            /**
0727:             * Redirect to this page.
0728:             * 
0729:             * @see org.apache.wicket.IRedirectListener#onRedirect()
0730:             */
0731:            public final void onRedirect() {
0732:            }
0733:
0734:            /**
0735:             * Convenience method. Search for children of type fromClass and invoke
0736:             * their respective removePersistedFormData() methods.
0737:             * 
0738:             * @see Form#removePersistentFormComponentValues(boolean)
0739:             * 
0740:             * @param formClass
0741:             *            Form to be selected. Pages may have more than one Form.
0742:             * @param disablePersistence
0743:             *            if true, disable persistence for all FormComponents on that
0744:             *            page. If false, it will remain unchanged.
0745:             */
0746:            public final void removePersistedFormData(final Class formClass,
0747:                    final boolean disablePersistence) {
0748:                // Check that formClass is an instanceof Form
0749:                if (!Form.class.isAssignableFrom(formClass)) {
0750:                    throw new WicketRuntimeException("Form class "
0751:                            + formClass.getName()
0752:                            + " is not a subclass of Form");
0753:                }
0754:
0755:                // Visit all children which are an instance of formClass
0756:                visitChildren(formClass, new IVisitor() {
0757:                    public Object component(final Component component) {
0758:                        // They must be of type Form as well
0759:                        if (component instanceof  Form) {
0760:                            // Delete persistet FormComponent data and disable
0761:                            // persistence
0762:                            ((Form) component)
0763:                                    .removePersistentFormComponentValues(disablePersistence);
0764:                        }
0765:                        return CONTINUE_TRAVERSAL;
0766:                    }
0767:                });
0768:            }
0769:
0770:            /**
0771:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0772:             */
0773:            public final void renderPage() {
0774:                // if not attached then attach the whole page.
0775:                if (!isAttached()) {
0776:                    attach();
0777:                }
0778:                // first try to check if the page can be rendered:
0779:                if (!isActionAuthorized(RENDER)) {
0780:                    if (log.isDebugEnabled()) {
0781:                        log.debug("Page not allowed to render: " + this );
0782:                    }
0783:                    throw new UnauthorizedActionException(this ,
0784:                            Component.RENDER);
0785:                }
0786:
0787:                // Make sure it is really empty
0788:                renderedComponents = null;
0789:
0790:                // Reset it to stateless so that it can be tested again
0791:                stateless = null;
0792:
0793:                // Set form component values from cookies
0794:                setFormComponentValuesFromCookies();
0795:
0796:                // First, give priority to IFeedback instances, as they have to
0797:                // collect their messages before components like ListViews
0798:                // remove any child components
0799:                visitChildren(IFeedback.class, new IVisitor() {
0800:                    public Object component(Component component) {
0801:                        ((IFeedback) component).updateFeedback();
0802:                        return IVisitor.CONTINUE_TRAVERSAL;
0803:                    }
0804:                });
0805:
0806:                if (this  instanceof  IFeedback) {
0807:                    ((IFeedback) this ).updateFeedback();
0808:                }
0809:
0810:                try {
0811:                    prepareForRender();
0812:                } catch (RuntimeException e) {
0813:                    // if an exception is thrown then we have to call after render
0814:                    // else the components could be in a wrong state (rendering)
0815:                    try {
0816:                        afterRender();
0817:                    } catch (RuntimeException e2) {
0818:                        // ignore this one could be a result off.
0819:                    }
0820:                    throw e;
0821:                }
0822:
0823:                // Visit all this page's children to reset markup streams and check
0824:                // rendering authorization, as appropriate. We set any result; positive
0825:                // or negative as a temporary boolean in the components, and when a
0826:                // authorization exception is thrown it will block the rendering of this
0827:                // page
0828:
0829:                // first the page itself
0830:                setRenderAllowed(isActionAuthorized(RENDER));
0831:                // children of the page
0832:                visitChildren(new IVisitor() {
0833:                    public Object component(final Component component) {
0834:                        // Find out if this component can be rendered
0835:                        final boolean renderAllowed = component
0836:                                .isActionAuthorized(RENDER);
0837:
0838:                        // Authorize rendering
0839:                        component.setRenderAllowed(renderAllowed);
0840:                        return IVisitor.CONTINUE_TRAVERSAL;
0841:                    }
0842:                });
0843:
0844:                // Handle request by rendering page
0845:                try {
0846:                    render(null);
0847:                } finally {
0848:                    afterRender();
0849:                }
0850:
0851:                // Check rendering if it happened fully
0852:                checkRendering(this );
0853:
0854:                // clean up debug meta data if component check is on
0855:                if (Application.get().getDebugSettings().getComponentUseCheck()) {
0856:                    visitChildren(new IVisitor() {
0857:                        public Object component(Component component) {
0858:                            component.setMetaData(Component.CONSTRUCTED_AT_KEY,
0859:                                    null);
0860:                            component.setMetaData(Component.ADDED_AT_KEY, null);
0861:                            return CONTINUE_TRAVERSAL;
0862:                        }
0863:                    });
0864:                }
0865:
0866:                if (!isPageStateless()) {
0867:                    // trigger creation of the actual session in case it was deferred
0868:                    Session.get().getSessionStore().getSessionId(
0869:                            RequestCycle.get().getRequest(), true);
0870:                    // Add/touch the response page in the session (its pagemap).
0871:                    getSession().touch(this );
0872:                }
0873:            }
0874:
0875:            /**
0876:             * This returns a page instance that is rollbacked the number of versions
0877:             * that is specified compared to the current page.
0878:             * 
0879:             * This is a rollback including ajax versions.
0880:             * 
0881:             * @param numberOfVersions
0882:             *            to rollback
0883:             * @return rollbacked page instance
0884:             */
0885:            public final Page rollbackPage(int numberOfVersions) {
0886:                Page page = versionManager == null ? this  : versionManager
0887:                        .rollbackPage(numberOfVersions);
0888:                getSession().touch(page);
0889:                return page;
0890:            }
0891:
0892:            /**
0893:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL.
0894:             * 
0895:             * Set the id for this Page. This method is called by PageMap when a Page is
0896:             * added because the id, which is assigned by PageMap, is not known until
0897:             * this time.
0898:             * 
0899:             * @param id
0900:             *            The id
0901:             */
0902:            public final void setNumericId(final int id) {
0903:                numericId = id;
0904:            }
0905:
0906:            /**
0907:             * Sets whether the page should try to be stateless. To be stateless,
0908:             * getStatelessHint() of every component on page (and it's behavior) must
0909:             * return true and the page must be bookmarkable.
0910:             * 
0911:             * @param value
0912:             *            whether the page should try to be stateless
0913:             */
0914:            public final void setStatelessHint(boolean value) {
0915:                if (value && !isBookmarkable()) {
0916:                    throw new WicketRuntimeException(
0917:                            "Can't set stateless hint to true on a page when the page is not bookmarkable, page: "
0918:                                    + this );
0919:                }
0920:                setFlag(FLAG_STATELESS_HINT, value);
0921:            }
0922:
0923:            /**
0924:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL.
0925:             * 
0926:             * This method is called when a component will be rendered standalone.
0927:             * 
0928:             * @param component
0929:             * 
0930:             */
0931:            public final void startComponentRender(Component component) {
0932:                renderedComponents = null;
0933:            }
0934:
0935:            /**
0936:             * Get the string representation of this container.
0937:             * 
0938:             * @return String representation of this container
0939:             */
0940:            public String toString() {
0941:                if (versionManager != null) {
0942:                    return "[Page class = " + getClass().getName() + ", id = "
0943:                            + getId() + ", version = "
0944:                            + versionManager.getCurrentVersionNumber()
0945:                            + ", ajax = "
0946:                            + versionManager.getAjaxVersionNumber() + "]";
0947:                } else {
0948:                    return "[Page class = " + getClass().getName() + ", id = "
0949:                            + getId() + ", version = " + 0 + "]";
0950:                }
0951:            }
0952:
0953:            /**
0954:             * Throw an exception if not all components rendered.
0955:             * 
0956:             * @param renderedContainer
0957:             *            The page itself if it was a full page render or the container
0958:             *            that was rendered standalone
0959:             */
0960:            private final void checkRendering(
0961:                    final MarkupContainer renderedContainer) {
0962:                // If the application wants component uses checked and
0963:                // the response is not a redirect
0964:                final IDebugSettings debugSettings = Application.get()
0965:                        .getDebugSettings();
0966:                if (debugSettings.getComponentUseCheck()
0967:                        && !getResponse().isRedirect()) {
0968:                    final Count unrenderedComponents = new Count();
0969:                    final List unrenderedAutoComponents = new ArrayList();
0970:                    final StringBuffer buffer = new StringBuffer();
0971:                    renderedContainer.visitChildren(new IVisitor() {
0972:                        public Object component(final Component component) {
0973:                            // If component never rendered
0974:                            if (renderedComponents == null
0975:                                    || !renderedComponents.contains(component)) {
0976:                                // If auto component ...
0977:                                if (component.isAuto()) {
0978:                                    // Add to list of unrendered auto components to
0979:                                    // delete below
0980:                                    unrenderedAutoComponents.add(component);
0981:                                } else if (component.isVisibleInHierarchy()) {
0982:                                    // Increase number of unrendered components
0983:                                    unrenderedComponents.increment();
0984:
0985:                                    // Add to explanatory string to buffer
0986:                                    buffer.append(Integer
0987:                                            .toString(unrenderedComponents
0988:                                                    .getCount())
0989:                                            + ". " + component + "\n");
0990:                                    String metadata = (String) component
0991:                                            .getMetaData(Component.CONSTRUCTED_AT_KEY);
0992:                                    if (metadata != null) {
0993:                                        buffer.append(metadata);
0994:                                    }
0995:                                    metadata = (String) component
0996:                                            .getMetaData(Component.ADDED_AT_KEY);
0997:                                    if (metadata != null) {
0998:                                        buffer.append(metadata);
0999:                                    }
1000:                                } else {
1001:                                    // if the component is not visible in hierarchy we
1002:                                    // should not visit its children since they are also
1003:                                    // not visible
1004:                                    return CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER;
1005:                                }
1006:                            }
1007:                            return CONTINUE_TRAVERSAL;
1008:                        }
1009:                    });
1010:
1011:                    // Remove any unrendered auto components since versioning couldn't
1012:                    // do it. We can't remove the component in the above visitChildren
1013:                    // callback because we're traversing the list at that time.
1014:                    for (int i = 0; i < unrenderedAutoComponents.size(); i++) {
1015:                        ((Component) unrenderedAutoComponents.get(i)).remove();
1016:                    }
1017:
1018:                    // Throw exception if any errors were found
1019:                    if (unrenderedComponents.getCount() > 0) {
1020:                        // Get rid of set
1021:                        renderedComponents = null;
1022:
1023:                        // Throw exception
1024:                        throw new WicketRuntimeException(
1025:                                "The component(s) below failed to render. A common problem is that you have added a component in code but forgot to reference it in the markup (thus the component will never be rendered).\n\n"
1026:                                        + buffer.toString());
1027:                    }
1028:                }
1029:
1030:                // Get rid of set
1031:                renderedComponents = null;
1032:            }
1033:
1034:            /**
1035:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL OR
1036:             * OVERRIDE.
1037:             * 
1038:             */
1039:            private final void endVersion() {
1040:                // Any changes to the page after this point will be tracked by the
1041:                // page's version manager. Since trackChanges is never set to false,
1042:                // this effectively means that change tracking begins after the
1043:                // first request to a page completes.
1044:                setFlag(FLAG_TRACK_CHANGES, true);
1045:
1046:                // If a new version was created
1047:                if (getFlag(FLAG_NEW_VERSION)) {
1048:                    // Reset boolean for next request
1049:                    setFlag(FLAG_NEW_VERSION, false);
1050:
1051:                    // We're done with this version
1052:                    if (versionManager != null) {
1053:                        versionManager.endVersion(getRequest().mergeVersion());
1054:                    }
1055:
1056:                    // Evict any page version(s) as need be
1057:                    getApplication().getSessionSettings()
1058:                            .getPageMapEvictionStrategy().evict(getPageMap());
1059:                }
1060:            }
1061:
1062:            /**
1063:             * Initializes Page by adding it to the Session and initializing it.
1064:             */
1065:            private final void init() {
1066:                final RequestCycle cycle = getRequestCycle();
1067:                String pageMapName = null;
1068:                if (cycle != null) {
1069:                    RequestParameters parameters = getRequest()
1070:                            .getRequestParameters();
1071:                    pageMapName = parameters.getPageMapName();
1072:                }
1073:                final IPageMap pageMap = PageMap.forName(pageMapName);
1074:                init(pageMap);
1075:            }
1076:
1077:            /**
1078:             * Initializes Page by adding it to the Session and initializing it.
1079:             * 
1080:             * @param pageMap
1081:             *            The page map to put this page in.
1082:             */
1083:            private final void init(final IPageMap pageMap) {
1084:                // Set the page map
1085:                if (pageMap != null) {
1086:                    setPageMap(pageMap);
1087:                } else {
1088:                    throw new IllegalStateException("PageMap cannot be null");
1089:                }
1090:
1091:                setNextAvailableId();
1092:
1093:                // Set versioning of page based on default
1094:                setVersioned(Application.get().getPageSettings()
1095:                        .getVersionPagesByDefault());
1096:
1097:                // All Pages are born dirty so they get clustered right away
1098:                dirty();
1099:            }
1100:
1101:            private void setNextAvailableId() {
1102:                if (getApplication().getSessionSettings()
1103:                        .isPageIdUniquePerSession()) {
1104:                    setNumericId(getSession().nextPageId());
1105:                } else {
1106:                    // Set the numeric id on this page
1107:                    setNumericId(getPageMap().nextId());
1108:                }
1109:            }
1110:
1111:            /**
1112:             * For the given component, whether we may record changes.
1113:             * 
1114:             * @param component
1115:             *            The component which is affected
1116:             * @param parent
1117:             * @return True if the change is okay to report
1118:             */
1119:            private final boolean mayTrackChangesFor(final Component component,
1120:                    MarkupContainer parent) {
1121:                // Auto components do not participate in versioning since they are
1122:                // added during the rendering phase (which is normally illegal).
1123:                if (component.isAuto()
1124:                        || (parent == null && !component.isVersioned())
1125:                        || (parent != null && !parent.isVersioned())) {
1126:                    return false;
1127:                } else {
1128:                    // the component is versioned... are we tracking changes at all?
1129:                    if (getFlag(FLAG_TRACK_CHANGES)) {
1130:                        // we are tracking changes... do we need to start new version?
1131:                        if (!getFlag(FLAG_NEW_VERSION)) {
1132:                            // if we have no version manager
1133:                            if (versionManager == null) {
1134:                                // then install a new version manager
1135:                                versionManager = getSession().getSessionStore()
1136:                                        .newVersionManager(this );
1137:                            }
1138:
1139:                            // start a new version
1140:                            versionManager.beginVersion(getRequest()
1141:                                    .mergeVersion());
1142:                            setFlag(FLAG_NEW_VERSION, true);
1143:                        }
1144:
1145:                        // return true as we are ready for versioning
1146:                        return true;
1147:                    }
1148:
1149:                    // we are not tracking changes or the component not versioned
1150:                    return false;
1151:                }
1152:            }
1153:
1154:            private void readObject(java.io.ObjectInputStream s)
1155:                    throws IOException, ClassNotFoundException {
1156:                int id = s.readShort();
1157:                String name = (String) s.readObject();
1158:
1159:                IPageSerializer ps = (IPageSerializer) serializer.get();
1160:                if (ps != null) {
1161:                    pageToResolve = ps.deserializePage(id, name, this , s);
1162:                } else {
1163:                    s.defaultReadObject();
1164:                }
1165:            }
1166:
1167:            // called after readObject
1168:            private Object readResolve() throws ObjectStreamException {
1169:                if (pageToResolve == null) {
1170:                    return this ;
1171:                } else {
1172:                    Page page = pageToResolve;
1173:                    pageToResolve = null;
1174:                    return page;
1175:                }
1176:            }
1177:
1178:            private void writeObject(java.io.ObjectOutputStream s)
1179:                    throws IOException {
1180:                s.writeShort(numericId);
1181:                s.writeObject(pageMapName);
1182:
1183:                IPageSerializer ps = (IPageSerializer) serializer.get();
1184:
1185:                if (ps != null) {
1186:                    ps.serializePage(this , s);
1187:                } else {
1188:                    s.defaultWriteObject();
1189:                }
1190:            }
1191:
1192:            /**
1193:             * Set-up response with appropriate content type, locale and encoding. The
1194:             * locale is set equal to the session's locale. The content type header
1195:             * contains information about the markup type (@see #getMarkupType()) and
1196:             * the encoding. The response (and request) encoding is determined by an
1197:             * application setting (@see
1198:             * ApplicationSettings#getResponseRequestEncoding()). In addition, if the
1199:             * page's markup contains a xml declaration like &lt?xml ... ?&gt; an xml
1200:             * declaration with proper encoding information is written to the output as
1201:             * well, provided it is not disabled by an applicaton setting (@see
1202:             * ApplicationSettings#getStripXmlDeclarationFromOutput()).
1203:             * <p>
1204:             * Note: Prior to Wicket 1.1 the output encoding was determined by the
1205:             * page's markup encoding. Because this caused uncertainties about the
1206:             * /request/ encoding, it has been changed in favour of the new, much safer,
1207:             * approach. Please see the Wiki for more details.
1208:             */
1209:            protected void configureResponse() {
1210:                // Get the response and application
1211:                final RequestCycle cycle = getRequestCycle();
1212:                final Application application = cycle.getApplication();
1213:                final Response response = cycle.getResponse();
1214:
1215:                // Determine encoding
1216:                final String encoding = application.getRequestCycleSettings()
1217:                        .getResponseRequestEncoding();
1218:
1219:                // Set content type based on markup type for page
1220:                response.setContentType("text/" + getMarkupType()
1221:                        + "; charset=" + encoding);
1222:
1223:                // Write out an xml declaration if the markup stream and settings allow
1224:                final MarkupStream markupStream = findMarkupStream();
1225:                if ((markupStream != null)
1226:                        && (markupStream.getXmlDeclaration() != null)
1227:                        && (application.getMarkupSettings()
1228:                                .getStripXmlDeclarationFromOutput() == false)) {
1229:                    response.write("<?xml version='1.0' encoding='");
1230:                    response.write(encoding);
1231:                    response.write("'?>");
1232:                }
1233:
1234:                // Set response locale from session locale
1235:                response.setLocale(getSession().getLocale());
1236:            }
1237:
1238:            /**
1239:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL OR
1240:             * OVERRIDE.
1241:             * 
1242:             * @see org.apache.wicket.Component#internalOnModelChanged()
1243:             */
1244:            protected final void internalOnModelChanged() {
1245:                visitChildren(new Component.IVisitor() {
1246:                    public Object component(final Component component) {
1247:                        // If form component is using form model
1248:                        if (component.sameInnermostModel(Page.this )) {
1249:                            component.modelChanged();
1250:                        }
1251:                        return IVisitor.CONTINUE_TRAVERSAL;
1252:                    }
1253:                });
1254:            }
1255:
1256:            /**
1257:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL OR
1258:             * OVERRIDE.
1259:             * 
1260:             * @param map
1261:             */
1262:            protected final void moveToPageMap(IPageMap map) {
1263:                // TODO post 1.2 shouldn't we remove this page from the pagemap/session
1264:                // if it would be in there?
1265:                // This should be done if the page was not cloned first, but shouldn't
1266:                // be done if it was cloned..
1267:                setPageMap(map);
1268:
1269:                setNextAvailableId();
1270:            }
1271:
1272:            /**
1273:             * @return Factory method that creates a version manager for this Page
1274:             */
1275:            protected final IPageVersionManager newVersionManager() {
1276:                return null;
1277:            }
1278:
1279:            /**
1280:             * @see org.apache.wicket.Component#onDetach()
1281:             */
1282:            protected void onDetach() {
1283:                if (log.isDebugEnabled()) {
1284:                    log.debug("ending request for page " + this  + ", request "
1285:                            + getRequest());
1286:                }
1287:
1288:                endVersion();
1289:
1290:                dirty();
1291:
1292:                super .onDetach();
1293:
1294:            }
1295:
1296:            /**
1297:             * Renders this container to the given response object.
1298:             * 
1299:             * @param markupStream
1300:             */
1301:            protected void onRender(final MarkupStream markupStream) {
1302:                // Set page's associated markup stream
1303:                final MarkupStream associatedMarkupStream = getAssociatedMarkupStream(true);
1304:                setMarkupStream(associatedMarkupStream);
1305:
1306:                // Configure response object with locale and content type
1307:                configureResponse();
1308:
1309:                // Render markup
1310:                renderAll(associatedMarkupStream);
1311:            }
1312:
1313:            /**
1314:             * A component was added.
1315:             * 
1316:             * @param component
1317:             *            The component that was added
1318:             */
1319:            final void componentAdded(final Component component) {
1320:                dirty();
1321:                if (mayTrackChangesFor(component, component.getParent())) {
1322:                    versionManager.componentAdded(component);
1323:                }
1324:            }
1325:
1326:            /**
1327:             * A component's model changed.
1328:             * 
1329:             * @param component
1330:             *            The component whose model is about to change
1331:             */
1332:            final void componentModelChanging(final Component component) {
1333:                dirty();
1334:                if (mayTrackChangesFor(component, null)) {
1335:                    versionManager.componentModelChanging(component);
1336:                }
1337:            }
1338:
1339:            /**
1340:             * A component was removed.
1341:             * 
1342:             * @param component
1343:             *            The component that was removed
1344:             */
1345:            final void componentRemoved(final Component component) {
1346:                dirty();
1347:                if (mayTrackChangesFor(component, component.getParent())) {
1348:                    versionManager.componentRemoved(component);
1349:                }
1350:            }
1351:
1352:            final void componentStateChanging(final Component component,
1353:                    Change change) {
1354:                dirty();
1355:                if (mayTrackChangesFor(component, null)) {
1356:                    versionManager.componentStateChanging(change);
1357:                }
1358:            }
1359:
1360:            /**
1361:             * Sets values for form components based on cookie values in the request.
1362:             * 
1363:             */
1364:            final void setFormComponentValuesFromCookies() {
1365:                // Visit all Forms contained in the page
1366:                visitChildren(Form.class, new Component.IVisitor() {
1367:                    // For each FormComponent found on the Page (not Form)
1368:                    public Object component(final Component component) {
1369:                        ((Form) component).loadPersistentFormComponentValues();
1370:                        return CONTINUE_TRAVERSAL;
1371:                    }
1372:                });
1373:            }
1374:
1375:            /**
1376:             * @param pageMap
1377:             *            Sets this page into the page map with the given name. If the
1378:             *            page map does not yet exist, it is automatically created.
1379:             */
1380:            final void setPageMap(final IPageMap pageMap) {
1381:                // Save transient reference to pagemap
1382:                this .pageMap = pageMap;
1383:
1384:                // Save name for restoring transient
1385:                pageMapName = pageMap.getName();
1386:            }
1387:
1388:            /**
1389:             * Set page stateless
1390:             * 
1391:             * @param stateless
1392:             */
1393:            void setPageStateless(Boolean stateless) {
1394:                this.stateless = stateless;
1395:            }
1396:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.