Source Code Cross Referenced for PageMap.java in  » J2EE » wicket » 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 » wicket 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: PageMap.java 529917 2007-04-18 08:42:01Z jcompagner $ $Revision:
003:         * 1.67 $ $Date: 2007-04-18 10:42:01 +0200 (Wed, 18 Apr 2007) $
004:         * 
005:         * ==============================================================================
006:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007:         * use this file except in compliance with the License. You may obtain a copy of
008:         * the License at
009:         * 
010:         * http://www.apache.org/licenses/LICENSE-2.0
011:         * 
012:         * Unless required by applicable law or agreed to in writing, software
013:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015:         * License for the specific language governing permissions and limitations under
016:         * the License.
017:         */
018:        package wicket;
019:
020:        import java.io.Serializable;
021:        import java.util.ArrayList;
022:        import java.util.Iterator;
023:        import java.util.List;
024:
025:        import org.apache.commons.logging.Log;
026:        import org.apache.commons.logging.LogFactory;
027:
028:        import wicket.session.pagemap.IPageMapEntry;
029:        import wicket.util.collections.ArrayListStack;
030:        import wicket.util.lang.Objects;
031:
032:        /**
033:         * A container for pages held in the session. PageMap is a parameter to several
034:         * methods in the Wicket API. You can get a PageMap by name from a Session with
035:         * Session.getPageMap(String pageMapName) or more conveniently with
036:         * PageMap.forName(String pageMapName). But you should not hold onto a reference
037:         * to the pagemap (just as you should not hold onto a reference to your Session
038:         * but should get it each time you need it instead). Instead, create a strongly
039:         * typed accessor method like this:
040:         * 
041:         * <pre>
042:         * public PageMap getMyPageMap()
043:         * {
044:         * 	return PageMap.forName(&quot;myPageMapName&quot;);
045:         * }
046:         * </pre>
047:         * 
048:         * If the page map with the given name is not found, one will be automatically
049:         * created.
050:         * 
051:         * @author Jonathan Locke
052:         */
053:        public final class PageMap implements  Serializable {
054:            /** Name of default pagemap */
055:            public static final String DEFAULT_NAME = null;
056:
057:            /** Log. */
058:            private static final Log log = LogFactory.getLog(PageMap.class);
059:
060:            private static final long serialVersionUID = 1L;
061:
062:            /** Stack of entry accesses by id */
063:            private final ArrayListStack/* <Access> */accessStack = new ArrayListStack(
064:                    8);
065:
066:            /** URL to continue to after a given page. */
067:            private String interceptContinuationURL;
068:
069:            /** Name of this page map */
070:            private final String name;
071:
072:            /** Next available page identifier in this page map. */
073:            private int pageId = 0;
074:
075:            /** The session where this PageMap resides */
076:            private transient Session session;
077:
078:            /**
079:             * Holds information about a pagemap access
080:             * 
081:             * @author Jonathan
082:             */
083:            public static class Access implements  Serializable {
084:                private static final long serialVersionUID = 1L;
085:
086:                int id;
087:                int version;
088:
089:                /**
090:                 * @see java.lang.Object#equals(java.lang.Object)
091:                 */
092:                public boolean equals(Object obj) {
093:                    if (obj instanceof  Access) {
094:                        Access tmp = (Access) obj;
095:                        return tmp.id == id && tmp.version == version;
096:                    }
097:                    return false;
098:                }
099:
100:                /**
101:                 * Gets id.
102:                 * 
103:                 * @return id
104:                 */
105:                public final int getId() {
106:                    return id;
107:                }
108:
109:                /**
110:                 * Gets version.
111:                 * 
112:                 * @return version
113:                 */
114:                public final int getVersion() {
115:                    return version;
116:                }
117:
118:                /**
119:                 * @see java.lang.Object#hashCode()
120:                 */
121:                public int hashCode() {
122:                    return id + (version << 16);
123:                }
124:
125:                /**
126:                 * @see java.lang.Object#toString()
127:                 */
128:                public String toString() {
129:                    return "[Access id=" + id + ", version=" + version + "]";
130:                }
131:            }
132:
133:            /**
134:             * Visitor interface for visiting entries in this map
135:             * 
136:             * @author Jonathan Locke
137:             */
138:            static interface IVisitor {
139:                /**
140:                 * @param entry
141:                 *            The page map entry
142:                 */
143:                public void entry(final IPageMapEntry entry);
144:            }
145:
146:            /**
147:             * Gets a page map for a page map name, automatically creating the page map
148:             * if it does not exist. If you do not want the pagemap to be automatically
149:             * created, you can call Session.pageMapForName(pageMapName, false).
150:             * 
151:             * @param pageMapName
152:             *            The name of the page map to get
153:             * @return The PageMap with the given name from the current session
154:             */
155:            public static PageMap forName(final String pageMapName) {
156:                Session session = Session.get();
157:                return (session != null) ? session.pageMapForName(pageMapName,
158:                        true) : null;
159:            }
160:
161:            /**
162:             * Constructor
163:             * 
164:             * @param name
165:             *            The name of this page map
166:             * @param session
167:             *            The session holding this page map
168:             */
169:            PageMap(final String name, final Session session) {
170:                this .name = name;
171:                if (session == null) {
172:                    throw new IllegalArgumentException(
173:                            "session must be not null");
174:                }
175:                this .session = session;
176:            }
177:
178:            /**
179:             * Removes all pages from this map
180:             */
181:            public final void clear() {
182:                // Remove all entries
183:                visitEntries(new IVisitor() {
184:                    public void entry(IPageMapEntry entry) {
185:                        removeEntry(entry);
186:                    }
187:                });
188:
189:                // Clear access stack
190:                accessStack.clear();
191:            }
192:
193:            // TODO Post 1.2: We should encode the page id of the current page into the
194:            // URL for truly stateless pages so we can adjust the stack correctly
195:
196:            /**
197:             * Returns a stack of PageMap.Access entries pushed in the order that the
198:             * pages and versions were accessed.
199:             * 
200:             * @return Stack containing ids of entries in access order.
201:             */
202:            public final ArrayListStack getAccessStack() {
203:                return accessStack;
204:            }
205:
206:            /**
207:             * Retrieves entry with given id.
208:             * 
209:             * @param id
210:             *            The page identifier
211:             * @return Any entry having the given id
212:             */
213:            public final IPageMapEntry getEntry(final int id) {
214:                return (IPageMapEntry) session.getAttribute(attributeForId(id));
215:            }
216:
217:            /**
218:             * @return Returns the name.
219:             */
220:            public final String getName() {
221:                return name;
222:            }
223:
224:            /**
225:             * @return The session that this PageMap is in.
226:             */
227:            public final Session getSession() {
228:                if (session != Session.get()) {
229:                    log.error("Session [" + session.getId()
230:                            + "]in pagemap wasn't the current session ["
231:                            + Session.get().getId() + "]");
232:                    session = Session.get();
233:                }
234:                return session;
235:            }
236:
237:            /**
238:             * @return Size of this page map in bytes, including a sum of the sizes of
239:             *         all the pages it contains.
240:             */
241:            public final long getSizeInBytes() {
242:                long size = Objects.sizeof(this );
243:                for (Iterator iterator = getEntries().iterator(); iterator
244:                        .hasNext();) {
245:                    IPageMapEntry entry = (IPageMapEntry) iterator.next();
246:                    if (entry instanceof  Page) {
247:                        size += ((Page) entry).getSizeInBytes();
248:                    } else {
249:                        size += Objects.sizeof(entry);
250:                    }
251:                }
252:                return size;
253:            }
254:
255:            /**
256:             * @return Number of page versions stored in this page map
257:             */
258:            public final int getVersions() {
259:                return accessStack.size();
260:            }
261:
262:            /**
263:             * @return True if this is the default page map
264:             */
265:            public final boolean isDefault() {
266:                return name == PageMap.DEFAULT_NAME;
267:            }
268:
269:            /**
270:             * Gets the most recently accessed page map entry off the top of the entry
271:             * access stack. This is guaranteed to be the most recently accessed entry
272:             * IF AND ONLY IF the user just came from a stateful page. If the user could
273:             * get to the current page from a stateless page, this method may not work
274:             * if the user uses the back button. For a detailed explanation of this
275:             * issue, see getAccessStack().
276:             * 
277:             * @see PageMap#getAccessStack()
278:             * 
279:             * @return Previous pagemap entry in terms of access
280:             */
281:            public final IPageMapEntry lastAccessedEntry() {
282:                return getEntry(peekAccess().getId());
283:            }
284:
285:            /**
286:             * Removes this PageMap from the Session.
287:             */
288:            public final void remove() {
289:                // First clear all pages from the session for this pagemap
290:                clear();
291:
292:                // Then remove the pagemap itself
293:                session.removePageMap(this );
294:            }
295:
296:            /**
297:             * Removes the page from the pagemap
298:             * 
299:             * @param page
300:             *            page to be removed from the pagemap
301:             */
302:            public final void remove(final Page page) {
303:                // Remove the pagemap entry from session
304:                removeEntry(page.getPageMapEntry());
305:            }
306:
307:            /**
308:             * @param entry
309:             *            The entry to remove
310:             */
311:            public final void removeEntry(final IPageMapEntry entry) {
312:                if (entry == null) {
313:                    // TODO this shouldn't happen but to many people are still getting this now and then/
314:                    // so first this "fix"
315:                    log.warn("PageMap.removeEntry called with an null entry");
316:                    return;
317:                }
318:                // Remove entry from session
319:                synchronized (session) {
320:                    session
321:                            .removeAttribute(attributeForId(entry
322:                                    .getNumericId()));
323:
324:                    // Remove page from acccess stack
325:                    final Iterator stack = accessStack.iterator();
326:                    while (stack.hasNext()) {
327:                        final Access access = (Access) stack.next();
328:                        if (access.id == entry.getNumericId()) {
329:                            stack.remove();
330:                        }
331:                    }
332:
333:                    // Let the session know we changed the pagemap
334:                    session.dirtyPageMap(this );
335:                }
336:            }
337:
338:            /**
339:             * @see java.lang.Object#toString()
340:             */
341:            public String toString() {
342:                return "[PageMap name=" + name + ", access=" + accessStack
343:                        + "]";
344:            }
345:
346:            /**
347:             * @param id
348:             *            The page id to create an attribute for
349:             * @return The session attribute for the given page (for replication of
350:             *         state)
351:             */
352:            final String attributeForId(final int id) {
353:                return attributePrefix() + id;
354:            }
355:
356:            /**
357:             * @return The attribute prefix for this page map
358:             */
359:            final String attributePrefix() {
360:                return Session.pageMapEntryAttributePrefix + name + ":";
361:            }
362:
363:            /**
364:             * Redirects to any intercept page previously specified by a call to
365:             * redirectToInterceptPage.
366:             * 
367:             * @return True if an original destination was redirected to
368:             * @see PageMap#redirectToInterceptPage(Page)
369:             */
370:            final boolean continueToOriginalDestination() {
371:                // Get request cycle
372:                final RequestCycle cycle = RequestCycle.get();
373:
374:                // If there's a place to go to
375:                if (interceptContinuationURL != null) {
376:                    cycle.setRequestTarget(new IRequestTarget() {
377:                        final String responseUrl = interceptContinuationURL;
378:
379:                        public void detach(RequestCycle requestCycle) {
380:                        }
381:
382:                        public Object getLock(RequestCycle requestCycle) {
383:                            return null;
384:                        }
385:
386:                        public void respond(RequestCycle requestCycle) {
387:                            // Redirect there
388:                            cycle.getResponse().redirect(responseUrl);
389:                        }
390:
391:                    });
392:
393:                    // Reset interception URL
394:                    interceptContinuationURL = null;
395:
396:                    // Force session to replicate page maps
397:                    session.dirtyPageMap(this );
398:                    return true;
399:                }
400:                return false;
401:            }
402:
403:            /**
404:             * Retrieves page with given id.
405:             * 
406:             * @param id
407:             *            The page identifier
408:             * @param versionNumber
409:             *            The version to get
410:             * @return Any page having the given id
411:             */
412:            final Page get(final int id, int versionNumber) {
413:                final IPageMapEntry entry = (IPageMapEntry) session
414:                        .getAttribute(attributeForId(id));
415:                if (entry != null) {
416:                    // Get page as dirty
417:                    Page page = entry.getPage();
418:
419:                    // TODO Performance: Is this really the case is a page always dirty
420:                    // even if we just render it again? POSSIBLE ANSWER: The page could
421:                    // mark itself as clean to prevent replication, but the reverse is
422:                    // probably not desirable (pages marking themselves dirty manually)
423:                    // We ought to think about this a bit and consider whether this
424:                    // could be tied in with version management. It's only when a page's
425:                    // version changes that it should be considered dirty, because then
426:                    // some kind of state changed. Right? - Jonathan
427:                    page.dirty();
428:
429:                    // Get the version of the page requested from the page
430:                    final Page version = page.getVersion(versionNumber);
431:
432:                    // Entry has been accessed
433:                    //pushAccess(entry);
434:                    // Entry has been accessed
435:                    access(entry, versionOf(entry));
436:
437:                    // Is the requested version available?
438:                    if (version != null) {
439:                        // Need to update session with new page?
440:                        if (version != page) {
441:                            // This is our new page
442:                            page = version;
443:
444:                            // Replaces old page entry
445:                            page.getPageMap().put(page);
446:                        }
447:                    } else {
448:                        if (log.isInfoEnabled()) {
449:                            log.info("Unable to get version " + versionNumber
450:                                    + " of page " + page);
451:                        }
452:                        return null;
453:                    }
454:                    return page;
455:                }
456:                return null;
457:            }
458:
459:            /**
460:             * @return The next id for this pagemap
461:             */
462:            final int nextId() {
463:                session.dirtyPageMap(this );
464:                return this .pageId++;
465:            }
466:
467:            /**
468:             * @param page
469:             *            The page to put into this map
470:             */
471:            final void put(final Page page) {
472:                // Page only goes into session if it is stateless
473:                if (!page.isStateless()) {
474:                    // Get page map entry from page
475:                    final IPageMapEntry entry = page.getPageMapEntry();
476:
477:                    // Entry has been accessed
478:                    pushAccess(entry);
479:
480:                    // Store entry in session
481:                    final String attribute = attributeForId(entry
482:                            .getNumericId());
483:
484:                    if (session.getAttribute(attribute) == null) {
485:                        // Set attribute if it is a new page, so that it will exists
486:                        // already for other threads that can come on the same time.
487:                        session.setAttribute(attribute, entry);
488:                    } else {
489:                        // Else don't set it directly but add to the dirty map
490:                        session.dirtyPage(page);
491:                    }
492:
493:                    // Evict any page(s) as need be
494:                    session.getApplication().getSessionSettings()
495:                            .getPageMapEvictionStrategy().evict(this );
496:                }
497:            }
498:
499:            /**
500:             * Redirects browser to an intermediate page such as a sign-in page. The
501:             * current request's URL is saved exactly as it was requested for future use
502:             * by continueToOriginalDestination(); Only use this method when you plan to
503:             * continue to the current URL at some later time; otherwise just use
504:             * setResponsePage or, when you are in a constructor, redirectTo.
505:             * 
506:             * @param page
507:             *            The page to temporarily redirect to
508:             */
509:            final void redirectToInterceptPage(final Page page) {
510:                // Get the request cycle
511:                final RequestCycle cycle = RequestCycle.get();
512:
513:                // The intercept continuation URL should be saved exactly as the
514:                // original request specified.
515:                interceptContinuationURL = cycle.getRequest().getURL();
516:
517:                // Page map is dirty
518:                session.dirtyPageMap(this );
519:
520:                // Redirect to the page
521:                cycle.setRedirect(true);
522:                cycle.setResponsePage(page);
523:            }
524:
525:            /**
526:             * Redirects browser to an intermediate page such as a sign-in page. The
527:             * current request's URL is saved exactly as it was requested for future use
528:             * by continueToOriginalDestination(); Only use this method when you plan to
529:             * continue to the current URL at some later time; otherwise just use
530:             * setResponsePage or, when you are in a constructor, redirectTo.
531:             * 
532:             * @param pageClazz
533:             *            The page clazz to temporarily redirect to
534:             */
535:            final void redirectToInterceptPage(final Class pageClazz) {
536:                // Get the request cycle
537:                final RequestCycle cycle = RequestCycle.get();
538:
539:                // The intercept continuation URL should be saved exactly as the
540:                // original request specified.
541:                interceptContinuationURL = cycle.getRequest().getURL();
542:
543:                // Page map is dirty
544:                session.dirtyPageMap(this );
545:
546:                // Redirect to the page
547:                cycle.setRedirect(true);
548:                cycle.setResponsePage(pageClazz);
549:            }
550:
551:            /**
552:             * @param session
553:             *            Session to set
554:             */
555:            final void setSession(final Session session) {
556:                this .session = session;
557:            }
558:
559:            /**
560:             * @param visitor
561:             *            The visitor to call at each Page in this PageMap.
562:             */
563:            final void visitEntries(final IVisitor visitor) {
564:                final List attributes = session.getAttributeNames();
565:                for (final Iterator iterator = attributes.iterator(); iterator
566:                        .hasNext();) {
567:                    final String attribute = (String) iterator.next();
568:                    if (attribute.startsWith(attributePrefix())) {
569:                        visitor.entry((IPageMapEntry) session
570:                                .getAttribute(attribute));
571:                    }
572:                }
573:            }
574:
575:            /**
576:             * @param entry
577:             *            Add entry to access list
578:             * @param version
579:             *            Version number being accessed
580:             */
581:            private final void access(final IPageMapEntry entry,
582:                    final int version) {
583:                // See if the version being accessed is already in the stack
584:                boolean add = true;
585:                int id = entry.getNumericId();
586:                for (int i = accessStack.size() - 1; i >= 0; i--) {
587:                    final Access access = (Access) accessStack.get(i);
588:
589:                    // If we found id and version in access stack
590:                    if (access.id == id && access.version == version) {
591:                        // No need to add since id and version are already in stack
592:                        add = false;
593:
594:                        // Pop entries to reveal that version at top of stack
595:                        // because the user used the back button
596:                        while (i < accessStack.size() - 1) {
597:                            // Pop unreachable access off top of stack
598:                            final Access topAccess = popAccess();
599:
600:                            // Get entry for access
601:                            final IPageMapEntry top = getEntry(topAccess
602:                                    .getId());
603:
604:                            // If it's a page we can remove version info
605:                            if (top instanceof  Page) {
606:                                // If there's more than one version
607:                                Page topPage = (Page) top;
608:                                if (topPage.getVersions() > 1) {
609:                                    // Remove version the top access version (-1)
610:                                    topPage
611:                                            .getVersion(topAccess.getVersion() - 1);
612:                                } else {
613:                                    // Remove whole page
614:                                    remove(topPage);
615:                                }
616:                            } else {
617:                                // Remove entry
618:                                removeEntry(top);
619:                            }
620:                        }
621:                        break;
622:                    }
623:                }
624:
625:                // If the user did not use the back button
626:                if (add) {
627:                    pushAccess(entry);
628:                }
629:            }
630:
631:            /**
632:             * @return List of entries in this page map
633:             */
634:            private final List getEntries() {
635:                final List attributes = session.getAttributeNames();
636:                final List list = new ArrayList();
637:                for (final Iterator iterator = attributes.iterator(); iterator
638:                        .hasNext();) {
639:                    final String attribute = (String) iterator.next();
640:                    if (attribute.startsWith(attributePrefix())) {
641:                        list.add(session.getAttribute(attribute));
642:                    }
643:                }
644:                return list;
645:            }
646:
647:            /**
648:             * @return Access entry on top of the access stack
649:             */
650:            private final Access peekAccess() {
651:                return (Access) accessStack.peek();
652:            }
653:
654:            /**
655:             * Removes access entry on top of stack
656:             * 
657:             * @return Access entry on top of the access stack
658:             */
659:            private final Access popAccess() {
660:                session.dirtyPageMap(this );
661:                return (Access) accessStack.pop();
662:            }
663:
664:            /**
665:             * @param entry
666:             *            Entry that was accessed
667:             */
668:            private final void pushAccess(IPageMapEntry entry) {
669:                // Create new access entry
670:                final Access access = new Access();
671:                access.id = entry.getNumericId();
672:                access.version = versionOf(entry);
673:                if (accessStack.size() > 0) {
674:                    if (peekAccess().equals(access)) {
675:                        return;
676:                    }
677:                    int index = accessStack.indexOf(access);
678:                    if (index >= 0) {
679:                        accessStack.remove(index);
680:                    }
681:                }
682:                accessStack.push(access);
683:                session.dirtyPageMap(this );
684:            }
685:
686:            /**
687:             * @param entry
688:             *            Page map entry
689:             * @return Version of entry
690:             */
691:            private final int versionOf(final IPageMapEntry entry) {
692:                if (entry instanceof  Page) {
693:                    return ((Page) entry).getCurrentVersionNumber();
694:                }
695:
696:                // If entry is not a page, it cannot have versions because the Page
697:                // is constructed on the fly.
698:                return 0;
699:            }
700:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.