Source Code Cross Referenced for HybridUrlCodingStrategy.java in  » J2EE » wicket » org » apache » wicket » request » target » coding » 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.request.target.coding 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.wicket.request.target.coding;
018:
019:        import java.lang.ref.WeakReference;
020:
021:        import org.apache.wicket.Application;
022:        import org.apache.wicket.IRedirectListener;
023:        import org.apache.wicket.IRequestTarget;
024:        import org.apache.wicket.MetaDataKey;
025:        import org.apache.wicket.Page;
026:        import org.apache.wicket.PageParameters;
027:        import org.apache.wicket.RequestCycle;
028:        import org.apache.wicket.Session;
029:        import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
030:        import org.apache.wicket.request.RequestParameters;
031:        import org.apache.wicket.request.target.component.BookmarkableListenerInterfaceRequestTarget;
032:        import org.apache.wicket.request.target.component.BookmarkablePageRequestTarget;
033:        import org.apache.wicket.request.target.component.PageRequestTarget;
034:        import org.apache.wicket.request.target.component.listener.ListenerInterfaceRequestTarget;
035:        import org.apache.wicket.util.string.AppendingStringBuffer;
036:        import org.apache.wicket.util.string.Strings;
037:
038:        /**
039:         * An URL coding strategy that encodes the mount point, page parameters and page
040:         * instance information into the URL. The benefits compared to mounting page
041:         * with {@link BookmarkablePageRequestTargetUrlCodingStrategy} are that the
042:         * mount point is preserved even after invoking listener interfaces (thus you
043:         * don't lose bookmarkability after clicking links) and that for ajax only pages
044:         * the state is preserved on refresh.
045:         * <p>
046:         * The url with {@link HybridUrlCodingStrategy} looks like
047:         * /mount/path/param1/value1.3. or /mount/path/param1/value1.3.2 where 3 is page
048:         * Id and 2 is version number.
049:         * <p>
050:         * Also to preserve state on refresh with ajax-only pages the
051:         * {@link HybridUrlCodingStrategy} does an immediate redirect after hitting
052:         * bookmarkable URL, e.g. it immediately redirects from /mount/path to
053:         * /mount/path.3 where 3 is the next page id. This preserves the page instance
054:         * on subsequent page refresh.
055:         * 
056:         * @author Matej Knopp
057:         */
058:        public class HybridUrlCodingStrategy extends
059:                AbstractRequestTargetUrlCodingStrategy {
060:            /** bookmarkable page class. */
061:            protected final WeakReference/* <Class> */pageClassRef;
062:
063:            private final boolean redirectOnBookmarkableRequest;
064:
065:            /**
066:             * Construct.
067:             * 
068:             * @param mountPath
069:             * @param pageClass
070:             * @param redirectOnBookmarkableRequest
071:             *            whether after hitting the page with URL in bookmarkable form
072:             *            it should be redirected to hybrid URL - needed for ajax to
073:             *            work properly after page refresh
074:             */
075:            public HybridUrlCodingStrategy(String mountPath, Class pageClass,
076:                    boolean redirectOnBookmarkableRequest) {
077:                super (mountPath);
078:                pageClassRef = new WeakReference(pageClass);
079:                this .redirectOnBookmarkableRequest = redirectOnBookmarkableRequest;
080:            }
081:
082:            /**
083:             * Construct.
084:             * 
085:             * @param mountPath
086:             * @param pageClass
087:             */
088:            public HybridUrlCodingStrategy(String mountPath, Class pageClass) {
089:                this (mountPath, pageClass, true);
090:            }
091:
092:            /**
093:             * Returns the amount of trailing slashes in the given string
094:             * 
095:             * @param seq
096:             * @return
097:             */
098:            private int getTrailingSlashesCount(CharSequence seq) {
099:                int count = 0;
100:                for (int i = seq.length() - 1; i >= 0; --i) {
101:                    if (seq.charAt(i) == '/') {
102:                        ++count;
103:                    } else {
104:                        break;
105:                    }
106:                }
107:                return count;
108:            }
109:
110:            /**
111:             * Returns whether after hitting bookmarkable url the request should be
112:             * redirected to a hybrid URL. This is recommended for pages with Ajax.
113:             * 
114:             * @return
115:             */
116:            protected boolean isRedirectOnBookmarkableRequest() {
117:                return redirectOnBookmarkableRequest;
118:            }
119:
120:            /**
121:             * Returns whether to redirect when there is pageMap specified in
122:             * bookmarkable URL
123:             * 
124:             * @return
125:             */
126:            protected boolean alwaysRedirectWhenPageMapIsSpecified() {
127:                // returns true if the pageId is unique, so we can get rid of the
128:                // pageMap name in the url this way
129:                return Application.exists()
130:                        && Application.get().getSessionSettings()
131:                                .isPageIdUniquePerSession();
132:            }
133:
134:            /**
135:             * @see org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy#decode(org.apache.wicket.request.RequestParameters)
136:             */
137:            public IRequestTarget decode(RequestParameters requestParameters) {
138:                String parametersFragment = requestParameters.getPath()
139:                        .substring(getMountPath().length());
140:
141:                // try to extract page info
142:                PageInfoExtraction extraction = extractPageInfo(parametersFragment);
143:
144:                PageInfo pageInfo = extraction.getPageInfo();
145:                String pageMapName = pageInfo != null ? pageInfo
146:                        .getPageMapName() : null;
147:                Integer pageVersion = pageInfo != null ? pageInfo
148:                        .getVersionNumber() : null;
149:                Integer pageId = pageInfo != null ? pageInfo.getPageId() : null;
150:
151:                // decode parameters
152:                PageParameters parameters = new PageParameters(
153:                        decodeParameters(extraction.getUrlAfterExtraction(),
154:                                requestParameters.getParameters()));
155:
156:                if (requestParameters.getPageMapName() == null) {
157:                    requestParameters.setPageMapName(pageMapName);
158:                } else {
159:                    pageMapName = requestParameters.getPageMapName();
160:                }
161:
162:                // do some extra work for checking whether this is a normal request to a
163:                // bookmarkable page, or a request to a stateless page (in which case a
164:                // wicket:interface parameter should be available
165:                final String interfaceParameter = (String) parameters
166:                        .remove(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME);
167:
168:                // we need to remember the amount of trailing slashes after the redirect
169:                // (otherwise we'll break relative urls)
170:                int originalUrlTrailingSlashesCount = getTrailingSlashesCount(extraction
171:                        .getUrlAfterExtraction());
172:
173:                boolean redirect = isRedirectOnBookmarkableRequest();
174:                if (Strings.isEmpty(pageMapName) != true
175:                        && alwaysRedirectWhenPageMapIsSpecified()) {
176:                    redirect = true;
177:                }
178:
179:                if (interfaceParameter != null) {
180:                    // stateless listener interface
181:                    WebRequestCodingStrategy.addInterfaceParameters(
182:                            interfaceParameter, requestParameters);
183:                    return new BookmarkableListenerInterfaceRequestTarget(
184:                            pageMapName, (Class) pageClassRef.get(),
185:                            parameters, requestParameters.getComponentPath(),
186:                            requestParameters.getInterfaceName());
187:                } else if (pageId == null) {
188:                    // bookmarkable page request
189:                    return new HybridBookmarkablePageRequestTarget(pageMapName,
190:                            (Class) pageClassRef.get(), parameters,
191:                            originalUrlTrailingSlashesCount, redirect);
192:                } else
193:                // hybrid url
194:                {
195:                    Page page;
196:
197:                    if (Strings.isEmpty(pageMapName)
198:                            && Application.exists()
199:                            && Application.get().getSessionSettings()
200:                                    .isPageIdUniquePerSession()) {
201:                        page = Session.get().getPage(
202:                                pageId.intValue(),
203:                                pageVersion != null ? pageVersion.intValue()
204:                                        : 0);
205:                    } else {
206:                        page = Session.get().getPage(
207:                                pageMapName,
208:                                "" + pageId,
209:                                pageVersion != null ? pageVersion.intValue()
210:                                        : 0);
211:                    }
212:
213:                    // check if the found page match the required class
214:                    if (page != null
215:                            && page.getClass().equals(pageClassRef.get())) {
216:                        requestParameters
217:                                .setInterfaceName(IRedirectListener.INTERFACE
218:                                        .getName());
219:                        RequestCycle.get().getRequest().setPage(page);
220:                        return new PageRequestTarget(page);
221:                    } else {
222:                        // we didn't find the page, act as bookmarkable page request -
223:                        // create new instance
224:                        return new HybridBookmarkablePageRequestTarget(
225:                                pageMapName, (Class) pageClassRef.get(),
226:                                parameters, originalUrlTrailingSlashesCount,
227:                                redirect);
228:                    }
229:                }
230:
231:            }
232:
233:            /**
234:             * Returns the number of traling slashes in the url when the page in request
235:             * target was created or null if the number can't be determined.
236:             * 
237:             * @param requestTarget
238:             * @return
239:             */
240:            private Integer getOriginalOriginalTrailingSlashesCount(
241:                    IRequestTarget requestTarget) {
242:                if (requestTarget instanceof  ListenerInterfaceRequestTarget) {
243:                    ListenerInterfaceRequestTarget target = (ListenerInterfaceRequestTarget) requestTarget;
244:                    Page page = target.getPage();
245:                    return (Integer) page
246:                            .getMetaData(ORIGINAL_TRAILING_SLASHES_COUNT_METADATA_KEY);
247:                }
248:                return null;
249:            }
250:
251:            /**
252:             * Extracts the PageParameters from given request target
253:             * 
254:             * @param requestTarget
255:             * @return
256:             */
257:            private PageParameters getPageParameters(
258:                    IRequestTarget requestTarget) {
259:                if (requestTarget instanceof  BookmarkablePageRequestTarget) {
260:                    BookmarkablePageRequestTarget target = (BookmarkablePageRequestTarget) requestTarget;
261:                    return target.getPageParameters();
262:                } else if (requestTarget instanceof  ListenerInterfaceRequestTarget) {
263:                    ListenerInterfaceRequestTarget target = (ListenerInterfaceRequestTarget) requestTarget;
264:                    Page page = target.getPage();
265:                    return getInitialPagePageParameters(page);
266:                } else {
267:                    return null;
268:                }
269:            }
270:
271:            /**
272:             * Extracts the PageInfo from given request target
273:             * 
274:             * @param requestTarget
275:             * @return
276:             */
277:            private PageInfo getPageInfo(IRequestTarget requestTarget) {
278:                if (requestTarget instanceof  BookmarkablePageRequestTarget) {
279:                    BookmarkablePageRequestTarget target = (BookmarkablePageRequestTarget) requestTarget;
280:                    if (target.getPageMapName() != null) {
281:                        return new PageInfo(null, null, target.getPageMapName());
282:                    } else {
283:                        return null;
284:                    }
285:                } else if (requestTarget instanceof  ListenerInterfaceRequestTarget) {
286:                    ListenerInterfaceRequestTarget target = (ListenerInterfaceRequestTarget) requestTarget;
287:                    Page page = target.getPage();
288:                    return new PageInfo(new Integer(page.getNumericId()),
289:                            new Integer(page.getCurrentVersionNumber()), page
290:                                    .getPageMapName());
291:                } else {
292:                    return null;
293:                }
294:            }
295:
296:            /**
297:             * Sets the initial page parameters for page instance. Use this only if you
298:             * know what you are doing.
299:             * 
300:             * @param page
301:             * @param pageParameters
302:             */
303:            public static void setInitialPageParameters(Page page,
304:                    PageParameters pageParameters) {
305:                page.setMetaData(PAGE_PARAMETERS_META_DATA_KEY, pageParameters);
306:            }
307:
308:            /**
309:             * @param page
310:             * @return
311:             */
312:            public static PageParameters getInitialPagePageParameters(Page page) {
313:                return (PageParameters) page
314:                        .getMetaData(PAGE_PARAMETERS_META_DATA_KEY);
315:            }
316:
317:            // meta data key to store PageParameters in page instance. This is used to
318:            // save the PageParameters that were
319:            // used to create the page instance so that later we can used them when
320:            // generating page URL
321:            private static final PageParametersMetaDataKey PAGE_PARAMETERS_META_DATA_KEY = new PageParametersMetaDataKey();
322:
323:            private static class PageParametersMetaDataKey extends MetaDataKey {
324:                private static final long serialVersionUID = 1L;
325:
326:                /**
327:                 * Construct.
328:                 */
329:                public PageParametersMetaDataKey() {
330:                    super (PageParameters.class);
331:                }
332:            };
333:
334:            // used to store number of traling slashes in page url (prior the PageInfo)
335:            // part. This is necessary to maintain
336:            // the exact number of slashes after page redirect, so that we don't break
337:            // things that rely on URL depth
338:            // (other mounted URLs)
339:            private static final OriginalUrlTrailingSlashesCountMetaDataKey ORIGINAL_TRAILING_SLASHES_COUNT_METADATA_KEY = new OriginalUrlTrailingSlashesCountMetaDataKey();
340:
341:            private static class OriginalUrlTrailingSlashesCountMetaDataKey
342:                    extends MetaDataKey {
343:                private static final long serialVersionUID = 1L;
344:
345:                /**
346:                 * Construct.
347:                 */
348:                public OriginalUrlTrailingSlashesCountMetaDataKey() {
349:                    super (Integer.class);
350:                }
351:
352:            }
353:
354:            /**
355:             * Fix the amount of traling slashes in the speciffied buffer.
356:             * 
357:             * @param buffer
358:             * @param desiredCount
359:             */
360:            private void fixTrailingSlashes(AppendingStringBuffer buffer,
361:                    int desiredCount) {
362:                int current = getTrailingSlashesCount(buffer);
363:                if (current > desiredCount) {
364:                    buffer
365:                            .setLength(buffer.length()
366:                                    - (current - desiredCount));
367:                } else if (desiredCount > current) {
368:                    int toAdd = desiredCount - current;
369:                    while (toAdd > 0) {
370:                        buffer.append("/");
371:                        --toAdd;
372:                    }
373:                }
374:            }
375:
376:            /**
377:             * @see org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy#encode(org.apache.wicket.IRequestTarget)
378:             */
379:            public CharSequence encode(IRequestTarget requestTarget) {
380:                if (matches(requestTarget) == false) {
381:                    throw new IllegalArgumentException(
382:                            "Unsupported request target type.");
383:                }
384:
385:                PageParameters parameters = getPageParameters(requestTarget);
386:                PageInfo pageInfo = getPageInfo(requestTarget);
387:
388:                final AppendingStringBuffer url = new AppendingStringBuffer(40);
389:                url.append(getMountPath());
390:                appendParameters(url, parameters);
391:
392:                // check whether we know if the initial URL ended with slash
393:                Integer trailingSlashesCount = getOriginalOriginalTrailingSlashesCount(requestTarget);
394:                if (trailingSlashesCount != null) {
395:                    fixTrailingSlashes(url, trailingSlashesCount.intValue());
396:                }
397:
398:                return addPageInfo(url.toString(), pageInfo);
399:            }
400:
401:            /**
402:             * @see org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy#matches(org.apache.wicket.IRequestTarget)
403:             */
404:            public boolean matches(IRequestTarget requestTarget) {
405:                if (requestTarget instanceof  BookmarkablePageRequestTarget) {
406:                    BookmarkablePageRequestTarget target = (BookmarkablePageRequestTarget) requestTarget;
407:                    return target.getPageClass().equals(pageClassRef.get());
408:                } else if (requestTarget instanceof  ListenerInterfaceRequestTarget) {
409:                    ListenerInterfaceRequestTarget target = (ListenerInterfaceRequestTarget) requestTarget;
410:                    return target.getPage().getClass().equals(
411:                            pageClassRef.get())
412:                            && target.getRequestListenerInterface().equals(
413:                                    IRedirectListener.INTERFACE);
414:                }
415:                return false;
416:            }
417:
418:            /**
419:             * Class that encapsulates {@link PageInfo} instance and the URL part prior
420:             * the PageInfo part
421:             * 
422:             * @author Matej Knopp
423:             */
424:            protected static class PageInfoExtraction {
425:                private final String urlAfterExtraction;
426:
427:                private final PageInfo pageInfo;
428:
429:                /**
430:                 * Construct.
431:                 * 
432:                 * @param urlAfterExtraction
433:                 * @param pageInfo
434:                 */
435:                public PageInfoExtraction(String urlAfterExtraction,
436:                        PageInfo pageInfo) {
437:                    this .urlAfterExtraction = urlAfterExtraction;
438:                    this .pageInfo = pageInfo;
439:                }
440:
441:                /**
442:                 * @return
443:                 */
444:                public PageInfo getPageInfo() {
445:                    return pageInfo;
446:                }
447:
448:                /**
449:                 * @return
450:                 */
451:                public String getUrlAfterExtraction() {
452:                    return urlAfterExtraction;
453:                }
454:            }
455:
456:            /**
457:             * Extracts the PageInfo string.
458:             * 
459:             * @param url
460:             * @return
461:             */
462:            protected PageInfoExtraction extractPageInfo(String url) {
463:                int begin = url.lastIndexOf(getBeginSeparator());
464:                PageInfo last = null;
465:                String lastSubstring = "";
466:                while (begin != -1) {
467:                    lastSubstring = url.substring(begin);
468:                    if (lastSubstring.length() > getBeginSeparator().length()
469:                            + getEndSeparator().length()
470:                            && lastSubstring.startsWith(getBeginSeparator())
471:                            && lastSubstring.endsWith(getEndSeparator())) {
472:                        String pageInfoString = lastSubstring.substring(
473:                                getBeginSeparator().length(), // 
474:                                lastSubstring.length()
475:                                        - getEndSeparator().length());
476:                        PageInfo info = PageInfo.parsePageInfo(pageInfoString);
477:                        last = info;
478:                    }
479:                    begin = url.lastIndexOf(getBeginSeparator(), begin - 1);
480:                }
481:                return new PageInfoExtraction(url.substring(0, url.length()
482:                        - lastSubstring.length()), last);
483:            }
484:
485:            protected String getBeginSeparator() {
486:                return ".";
487:            }
488:
489:            protected String getEndSeparator() {
490:                return "";
491:            }
492:
493:            /**
494:             * Encodes the PageInfo part to the URL
495:             * 
496:             * @param url
497:             * @param pageInfo
498:             * @return
499:             */
500:            protected String addPageInfo(String url, PageInfo pageInfo) {
501:                if (pageInfo != null) {
502:                    return url + getBeginSeparator() + pageInfo.toString()
503:                            + getEndSeparator();
504:                } else {
505:                    return url;
506:                }
507:            }
508:
509:            /**
510:             * Possible string representation of PageInfo:
511:             * <ul>
512:             * <li>pageId
513:             * <li>pageId.version
514:             * <li>pageMap (only if pageMap starts with a letter)
515:             * <li>.pageMap
516:             * <li>pageMap.pageId.version
517:             * <li>pageMap.pageId (only if pageMap name starts with a letter)
518:             * </ul>
519:             * 
520:             * @author Matej Knopp
521:             */
522:            protected static class PageInfo {
523:                private final Integer pageId;
524:                private final Integer versionNumber;
525:                private final String pageMapName;
526:
527:                /**
528:                 * Construct.
529:                 * 
530:                 * @param pageId
531:                 * @param versionNumber
532:                 * @param pageMapName
533:                 */
534:                public PageInfo(Integer pageId, Integer versionNumber,
535:                        String pageMapName) {
536:                    if ((pageId == null && (versionNumber != null || pageMapName == null))
537:                            || (versionNumber == null && (pageId != null || pageMapName == null))) {
538:                        throw new IllegalArgumentException(
539:                                "Either both pageId and versionNumber must be null or none of them.");
540:                    }
541:                    this .pageId = pageId;
542:                    this .versionNumber = versionNumber;
543:                    this .pageMapName = pageMapName;
544:                }
545:
546:                /**
547:                 * @return
548:                 */
549:                public Integer getPageId() {
550:                    return pageId;
551:                }
552:
553:                /**
554:                 * @return
555:                 */
556:                public Integer getVersionNumber() {
557:                    return versionNumber;
558:                }
559:
560:                /**
561:                 * @return
562:                 */
563:                public String getPageMapName() {
564:                    return pageMapName;
565:                }
566:
567:                private static char getPageInfoSeparator() {
568:                    return '.';
569:                }
570:
571:                /**
572:                 * <ul>
573:                 * <li>pageId
574:                 * <li>pageId.version
575:                 * <li>pageMap (only in if pagemap strats with a letter)
576:                 * <li>.pageMap
577:                 * <li>pageMap.pageId (only in if pageMap name starts with a letter)
578:                 * <li>pageMap.pageId.version
579:                 * </ul>
580:                 */
581:                public String toString() {
582:                    String pageMapName = this .pageMapName;
583:
584:                    // we don't need to encode the pageMapName when the pageId is unique
585:                    // per session
586:                    if (pageMapName != null
587:                            && pageId != null
588:                            && Application.exists()
589:                            && Application.get().getSessionSettings()
590:                                    .isPageIdUniquePerSession()) {
591:                        pageMapName = null;
592:                    }
593:
594:                    AppendingStringBuffer buffer = new AppendingStringBuffer(5);
595:
596:                    final boolean pmEmpty = Strings.isEmpty(pageMapName);
597:                    final boolean pmContainsLetter = !pmEmpty
598:                            && !isNumber(pageMapName);
599:
600:                    if (pageId != null && pmEmpty
601:                            && versionNumber.intValue() == 0) {
602:                        // pageId
603:                        buffer.append(pageId);
604:                    } else if (pageId != null && pmEmpty
605:                            && versionNumber.intValue() != 0) {
606:                        // pageId.version
607:                        buffer.append(pageId);
608:                        buffer.append(getPageInfoSeparator());
609:                        buffer.append(versionNumber);
610:                    } else if (pageId == null && pmContainsLetter) {
611:                        // pageMap (must start with letter)
612:                        buffer.append(pageMapName);
613:                    } else if (pageId == null && !pmEmpty && !pmContainsLetter) {
614:                        // .pageMap
615:                        buffer.append(getPageInfoSeparator());
616:                        buffer.append(pageMapName);
617:                    } else if (pmContainsLetter && pageId != null
618:                            && versionNumber.intValue() == 0) {
619:                        // pageMap.pageId (pageMap must start with a letter)
620:                        buffer.append(pageMapName);
621:                        buffer.append(getPageInfoSeparator());
622:                        buffer.append(pageId);
623:                    } else if (!pmEmpty && pageId != null) {
624:                        // pageMap.pageId.pageVersion
625:                        buffer.append(pageMapName);
626:                        buffer.append(getPageInfoSeparator());
627:                        buffer.append(pageId);
628:                        buffer.append(getPageInfoSeparator());
629:                        buffer.append(versionNumber);
630:                    }
631:
632:                    return buffer.toString();
633:                }
634:
635:                /**
636:                 * Method that rigidly checks if the string consists of digits only.
637:                 * 
638:                 * @param string
639:                 * @return
640:                 */
641:                private static boolean isNumber(String string) {
642:                    if (string == null || string.length() == 0) {
643:                        return false;
644:                    }
645:                    for (int i = 0; i < string.length(); ++i) {
646:                        if (Character.isDigit(string.charAt(i)) == false) {
647:                            return false;
648:                        }
649:                    }
650:                    return true;
651:                }
652:
653:                /**
654:                 * <ul>
655:                 * <li>pageId
656:                 * <li>pageId.version
657:                 * <li>pageMap (only in if pagemap strats with a letter)
658:                 * <li>.pageMap
659:                 * <li>pageMap.pageId (only in if pageMap name starts with a letter)
660:                 * <li>pageMap.pageId.version
661:                 * </ul>
662:                 * 
663:                 * @param src
664:                 * @return
665:                 */
666:                public static PageInfo parsePageInfo(String src) {
667:                    if (src == null || src.length() == 0) {
668:                        return null;
669:                    }
670:
671:                    String segments[] = Strings.split(src,
672:                            getPageInfoSeparator());
673:
674:                    if (segments.length > 3) {
675:                        return null;
676:                    }
677:
678:                    if (segments.length == 1 && isNumber(segments[0])) {
679:                        // pageId
680:                        return new PageInfo(Integer.valueOf(segments[0]),
681:                                new Integer(0), null);
682:                    } else if (segments.length == 2 && isNumber(segments[0])
683:                            && isNumber(segments[1])) {
684:                        // pageId:pageVersion
685:                        return new PageInfo(Integer.valueOf(segments[0]),
686:                                Integer.valueOf(segments[1]), null);
687:                    } else if (segments.length == 1 && !isNumber(segments[0])) {
688:                        // pageMap (starts with leter)
689:                        return new PageInfo(null, null, segments[0]);
690:                    } else if (segments.length == 2
691:                            && segments[0].length() == 0) {
692:                        // .pageMap
693:                        return new PageInfo(null, null, segments[1]);
694:                    } else if (segments.length == 2 && !isNumber(segments[0])) {
695:                        // pageMap.pageId (pageMap starts with letter)
696:                        return new PageInfo(Integer.valueOf(segments[1]),
697:                                new Integer(0), segments[0]);
698:                    } else if (segments.length == 3) {
699:                        if (segments[2].length() == 0 && isNumber(segments[1])) {
700:                            // we don't encode it like this, but we still should be able
701:                            // to parse it
702:                            // pageMapName.pageId.
703:                            return new PageInfo(Integer.valueOf(segments[1]),
704:                                    new Integer(0), segments[0]);
705:                        } else if (isNumber(segments[1])
706:                                && isNumber(segments[2])) {
707:                            // pageMapName.pageId.pageVersion
708:                            return new PageInfo(Integer.valueOf(segments[1]),
709:                                    Integer.valueOf(segments[2]), segments[0]);
710:                        }
711:                    }
712:
713:                    return null;
714:                }
715:
716:            };
717:
718:            /**
719:             * BookmarkablePage request target that does a redirect after bookmarkable
720:             * page was rendered (only if the bookmarkable page is stateful though)
721:             * 
722:             * @author Matej Knopp
723:             */
724:            private static class HybridBookmarkablePageRequestTarget extends
725:                    BookmarkablePageRequestTarget {
726:                private final int originalUrlTrailingSlashesCount;
727:                private final boolean redirect;
728:
729:                /**
730:                 * Construct.
731:                 * 
732:                 * @param pageMapName
733:                 * @param pageClass
734:                 * @param pageParameters
735:                 * @param originalUrlTrailingSlashesCount
736:                 * @param redirect
737:                 */
738:                public HybridBookmarkablePageRequestTarget(String pageMapName,
739:                        Class pageClass, PageParameters pageParameters,
740:                        int originalUrlTrailingSlashesCount, boolean redirect) {
741:                    super (pageMapName, pageClass, pageParameters);
742:                    this .originalUrlTrailingSlashesCount = originalUrlTrailingSlashesCount;
743:                    this .redirect = redirect;
744:                }
745:
746:                protected Page newPage(Class pageClass,
747:                        RequestCycle requestCycle) {
748:                    Page page = super .newPage(pageClass, requestCycle);
749:                    page.setMetaData(PAGE_PARAMETERS_META_DATA_KEY,
750:                            getPageParameters());
751:                    page.setMetaData(
752:                            ORIGINAL_TRAILING_SLASHES_COUNT_METADATA_KEY,
753:                            new Integer(originalUrlTrailingSlashesCount));
754:                    return page;
755:                }
756:
757:                public void respond(RequestCycle requestCycle) {
758:                    {
759:                        Page page = getPage(requestCycle);
760:                        if (page.isPageStateless() == false && redirect) {
761:                            requestCycle.redirectTo(page);
762:                        } else {
763:                            super .respond(requestCycle);
764:                        }
765:                    }
766:                }
767:            };
768:
769:            /**
770:             * @see org.apache.wicket.request.target.coding.AbstractRequestTargetUrlCodingStrategy#matches(java.lang.String)
771:             */
772:            public boolean matches(String path) {
773:                if (path.startsWith(getMountPath())) {
774:                    /*
775:                     * We need to match /mount/point or /mount/point/with/extra/path,
776:                     * but not /mount/pointXXX
777:                     */
778:                    String remainder = path.substring(getMountPath().length());
779:                    if (remainder.length() == 0 || remainder.startsWith("/")) {
780:                        return true;
781:                    }
782:                    /*
783:                     * We also need to accept /mount/point(XXX)
784:                     */
785:                    if (remainder.length() > getBeginSeparator().length()
786:                            + getEndSeparator().length()
787:                            && remainder.startsWith(getBeginSeparator())
788:                            && remainder.endsWith(getEndSeparator())) {
789:                        String substring = remainder
790:                                .substring(getBeginSeparator().length(), // 
791:                                        remainder.length()
792:                                                - getEndSeparator().length());
793:                        PageInfo info = PageInfo.parsePageInfo(substring);
794:                        if (info != null) {
795:                            return true;
796:                        }
797:                    }
798:                }
799:                return false;
800:            }
801:
802:            public String toString() {
803:                return "HybridUrlCodingStrategy[page=" + pageClassRef.get()
804:                        + "]";
805:            }
806:
807:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.