Source Code Cross Referenced for WebRequestCodingStrategy.java in  » J2EE » wicket » org » apache » wicket » protocol » http » request » 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.protocol.http.request 
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.protocol.http.request;
0018:
0019:        import java.util.Collection;
0020:        import java.util.Comparator;
0021:        import java.util.Iterator;
0022:        import java.util.Map;
0023:        import java.util.TreeMap;
0024:        import java.util.TreeSet;
0025:        import java.util.Map.Entry;
0026:
0027:        import org.apache.wicket.Application;
0028:        import org.apache.wicket.Component;
0029:        import org.apache.wicket.IPageMap;
0030:        import org.apache.wicket.IRedirectListener;
0031:        import org.apache.wicket.IRequestTarget;
0032:        import org.apache.wicket.Page;
0033:        import org.apache.wicket.PageMap;
0034:        import org.apache.wicket.PageParameters;
0035:        import org.apache.wicket.Request;
0036:        import org.apache.wicket.RequestCycle;
0037:        import org.apache.wicket.RequestListenerInterface;
0038:        import org.apache.wicket.Session;
0039:        import org.apache.wicket.WicketRuntimeException;
0040:        import org.apache.wicket.protocol.http.UnitTestSettings;
0041:        import org.apache.wicket.request.IRequestCodingStrategy;
0042:        import org.apache.wicket.request.IRequestTargetMountsInfo;
0043:        import org.apache.wicket.request.RequestParameters;
0044:        import org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy;
0045:        import org.apache.wicket.request.target.coding.WebRequestEncoder;
0046:        import org.apache.wicket.request.target.component.BookmarkableListenerInterfaceRequestTarget;
0047:        import org.apache.wicket.request.target.component.IBookmarkablePageRequestTarget;
0048:        import org.apache.wicket.request.target.component.IPageRequestTarget;
0049:        import org.apache.wicket.request.target.component.listener.IListenerInterfaceRequestTarget;
0050:        import org.apache.wicket.request.target.resource.ISharedResourceRequestTarget;
0051:        import org.apache.wicket.util.string.AppendingStringBuffer;
0052:        import org.apache.wicket.util.string.PrependingStringBuffer;
0053:        import org.apache.wicket.util.string.Strings;
0054:        import org.slf4j.Logger;
0055:        import org.slf4j.LoggerFactory;
0056:
0057:        /**
0058:         * Request parameters factory implementation that uses http request parameters
0059:         * and path info to construct the request parameters object.
0060:         * 
0061:         * @author Eelco Hillenius
0062:         * @author Jonathan Locke
0063:         */
0064:        public class WebRequestCodingStrategy implements 
0065:                IRequestCodingStrategy, IRequestTargetMountsInfo {
0066:            /** Name of interface target query parameter */
0067:            public static final String NAME_SPACE = "wicket:";
0068:
0069:            /** Name of interface target query parameter */
0070:            public static final String INTERFACE_PARAMETER_NAME = NAME_SPACE
0071:                    + "interface";
0072:
0073:            /** AJAX query parameter name */
0074:            public static final String BEHAVIOR_ID_PARAMETER_NAME = NAME_SPACE
0075:                    + "behaviorId";
0076:
0077:            /** Parameter name used all over the place */
0078:            public static final String BOOKMARKABLE_PAGE_PARAMETER_NAME = NAME_SPACE
0079:                    + "bookmarkablePage";
0080:
0081:            /** Pagemap parameter constant */
0082:            public static final String PAGEMAP = NAME_SPACE + "pageMapName";
0083:
0084:            /**
0085:             * Url name of the default pagemap
0086:             * 
0087:             * When we encode the default pagemap name in a url we cannot always use
0088:             * null or "" because it breaks urls which are encoded with /param1/value1/
0089:             * eg /product/14/wicket:pageMapName/ split on / will split into
0090:             * {product,14,wicket:pageMapName}
0091:             */
0092:            public static final String DEFAULT_PAGEMAP_NAME = "wicketdef";
0093:
0094:            /** The URL path prefix expected for (so called) resources (not html pages). */
0095:            public static final String RESOURCES_PATH_PREFIX = "resources/";
0096:
0097:            /**
0098:             * Parameter name that tells decode to ignore this request if the
0099:             * page+version encoded in the url is not on top of the stack. The value of
0100:             * this parameter is not important, it simply has to be present to enable
0101:             * the behavior
0102:             */
0103:            public static final String IGNORE_IF_NOT_ACTIVE_PARAMETER_NAME = NAME_SPACE
0104:                    + "ignoreIfNotActive";
0105:
0106:            /**
0107:             * Various settings used to configure this strategy
0108:             * 
0109:             * @author ivaynberg
0110:             */
0111:            public static class Settings {
0112:                /** whether or not mount paths are case sensitive */
0113:                private boolean mountsCaseSensitive = true;
0114:
0115:                /**
0116:                 * Construct.
0117:                 */
0118:                public Settings() {
0119:                }
0120:
0121:                /**
0122:                 * Sets mountsCaseSensitive.
0123:                 * 
0124:                 * @param mountsCaseSensitive
0125:                 *            mountsCaseSensitive
0126:                 */
0127:                public void setMountsCaseSensitive(boolean mountsCaseSensitive) {
0128:                    this .mountsCaseSensitive = mountsCaseSensitive;
0129:                }
0130:
0131:                /**
0132:                 * Gets caseSensitive.
0133:                 * 
0134:                 * @return caseSensitive
0135:                 */
0136:                public boolean areMountsCaseSensitive() {
0137:                    return mountsCaseSensitive;
0138:                }
0139:            }
0140:
0141:            /** log. */
0142:            private static final Logger log = LoggerFactory
0143:                    .getLogger(WebRequestCodingStrategy.class);
0144:
0145:            /**
0146:             * map of path mounts for mount encoders on paths.
0147:             * <p>
0148:             * mountsOnPath is sorted by longest paths first to improve resolution of
0149:             * possible path conflicts. <br />
0150:             * For example: <br/> we mount Page1 on /page and Page2 on /page/test <br />
0151:             * Page1 uses a parameters encoder that only encodes parameter values <br />
0152:             * now suppose we want to access Page1 with a single paramter param="test".
0153:             * we have a url collision since both pages can be access with /page/test
0154:             * <br />
0155:             * the sorting by longest path first guarantees that the iterator will
0156:             * return the mount /page/test before it returns mount /page therefore
0157:             * giving deterministic behavior to path resolution by always trying to
0158:             * match the longest possible path first.
0159:             * </p>
0160:             */
0161:            private final MountsMap mountsOnPath;
0162:
0163:            /**
0164:             * Construct.
0165:             */
0166:            public WebRequestCodingStrategy() {
0167:                this (new Settings());
0168:            }
0169:
0170:            /**
0171:             * Construct.
0172:             * 
0173:             * @param settings
0174:             */
0175:            public WebRequestCodingStrategy(Settings settings) {
0176:                if (settings == null) {
0177:                    throw new IllegalArgumentException(
0178:                            "Argument [[settings]] cannot be null");
0179:                }
0180:                mountsOnPath = new MountsMap(settings.areMountsCaseSensitive());
0181:            }
0182:
0183:            /**
0184:             * @see org.apache.wicket.request.IRequestCodingStrategy#decode(org.apache.wicket.Request)
0185:             */
0186:            public final RequestParameters decode(final Request request) {
0187:                final RequestParameters parameters = new RequestParameters();
0188:                final String pathInfo = getRequestPath(request);
0189:                parameters.setPath(pathInfo);
0190:                parameters.setPageMapName(WebRequestCodingStrategy
0191:                        .decodePageMapName(request.getParameter(PAGEMAP)));
0192:                addInterfaceParameters(request, parameters);
0193:                addBookmarkablePageParameters(request, parameters);
0194:                addResourceParameters(request, parameters);
0195:                if (request.getParameter(IGNORE_IF_NOT_ACTIVE_PARAMETER_NAME) != null) {
0196:                    parameters.setOnlyProcessIfPathActive(true);
0197:                }
0198:
0199:                Map map = request.getParameterMap();
0200:                Iterator iterator = map.keySet().iterator();
0201:                while (iterator.hasNext()) {
0202:                    String key = (String) iterator.next();
0203:                    if (key.startsWith(NAME_SPACE)) {
0204:                        iterator.remove();
0205:                    }
0206:                }
0207:                parameters.setParameters(map);
0208:                return parameters;
0209:            }
0210:
0211:            /**
0212:             * Encode the given request target. If a mount is found, that mounted url
0213:             * will be returned. Otherwise, one of the delegation methods will be
0214:             * called. In case you are using custom targets that are not part of the
0215:             * default target hierarchy, you need to override
0216:             * {@link #doEncode(RequestCycle, IRequestTarget)}, which will be called
0217:             * after the defaults have been tried. When that doesn't provide a url
0218:             * either, and exception will be thrown saying that encoding could not be
0219:             * done.
0220:             * 
0221:             * @see org.apache.wicket.request.IRequestCodingStrategy#encode(org.apache.wicket.RequestCycle,
0222:             *      org.apache.wicket.IRequestTarget)
0223:             */
0224:            public final CharSequence encode(final RequestCycle requestCycle,
0225:                    final IRequestTarget requestTarget) {
0226:                // First check to see whether the target is mounted
0227:                CharSequence url = pathForTarget(requestTarget);
0228:
0229:                if (url != null) {
0230:                    // Do nothing - we've found the URL and it's mounted.
0231:                } else if (requestTarget instanceof  IBookmarkablePageRequestTarget) {
0232:                    url = encode(requestCycle,
0233:                            (IBookmarkablePageRequestTarget) requestTarget);
0234:                } else if (requestTarget instanceof  ISharedResourceRequestTarget) {
0235:                    url = encode(requestCycle,
0236:                            (ISharedResourceRequestTarget) requestTarget);
0237:                } else if (requestTarget instanceof  IListenerInterfaceRequestTarget) {
0238:                    url = encode(requestCycle,
0239:                            (IListenerInterfaceRequestTarget) requestTarget);
0240:                } else if (requestTarget instanceof  IPageRequestTarget) {
0241:                    // This calls page.urlFor(IRedirectListener.INTERFACE), which calls
0242:                    // the function we're in again. We therefore need to jump out here
0243:                    // and return the url immediately, otherwise we end up prefixing it
0244:                    // with relative path or absolute prefixes twice.
0245:                    return encode(requestCycle,
0246:                            (IPageRequestTarget) requestTarget);
0247:                }
0248:                // fallthough for non-default request targets
0249:                else {
0250:                    url = doEncode(requestCycle, requestTarget);
0251:                }
0252:
0253:                if (url != null) {
0254:                    // Add the actual URL. This will be relative to the Wicket
0255:                    // Servlet/Filter, with no leading '/'.
0256:                    PrependingStringBuffer prepender = new PrependingStringBuffer(
0257:                            url.toString());
0258:
0259:                    // Prepend prefix to the URL to make it relative to the current
0260:                    // request.
0261:                    prepender.prepend(requestCycle.getRequest()
0262:                            .getRelativePathPrefixToWicketHandler());
0263:
0264:                    String result = prepender.toString();
0265:                    // We need to special-case links to the home page if we're at the
0266:                    // same level.
0267:                    if (result.length() == 0) {
0268:                        result = "./";
0269:                    }
0270:                    return requestCycle.getOriginalResponse().encodeURL(result);
0271:                }
0272:
0273:                // Just return null intead of throwing an exception. So that it can be
0274:                // handled better
0275:                return null;
0276:            }
0277:
0278:            /**
0279:             * @see org.apache.wicket.request.IRequestTargetMountsInfo#listMounts()
0280:             */
0281:            public IRequestTargetUrlCodingStrategy[] listMounts() {
0282:                return (IRequestTargetUrlCodingStrategy[]) mountsOnPath
0283:                        .strategies()
0284:                        .toArray(
0285:                                new IRequestTargetUrlCodingStrategy[mountsOnPath
0286:                                        .size()]);
0287:            }
0288:
0289:            /**
0290:             * @see org.apache.wicket.request.IRequestTargetMounter#urlCodingStrategyForPath(java.lang.String)
0291:             */
0292:            public final IRequestTargetUrlCodingStrategy urlCodingStrategyForPath(
0293:                    String path) {
0294:                if (path == null) {
0295:                    return mountsOnPath.strategyForMount(null);
0296:                } else {
0297:                    IRequestTargetUrlCodingStrategy strategy = mountsOnPath
0298:                            .strategyForPath(path);
0299:                    if (strategy != null) {
0300:                        return strategy;
0301:                    }
0302:                }
0303:                return null;
0304:            }
0305:
0306:            /**
0307:             * @see org.apache.wicket.request.IRequestTargetMounter#mount(java.lang.String,
0308:             *      org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy)
0309:             */
0310:            public final void mount(IRequestTargetUrlCodingStrategy encoder) {
0311:                if (encoder == null) {
0312:                    throw new IllegalArgumentException(
0313:                            "Argument encoder must not be null");
0314:                }
0315:
0316:                String path = encoder.getMountPath();
0317:                if (path == null) {
0318:                    throw new IllegalArgumentException(
0319:                            "Argument path must not be null");
0320:                }
0321:
0322:                if (path.equals("/") || path.equals("")) {
0323:                    throw new IllegalArgumentException(
0324:                            "The mount path '/' is reserved for the application home page");
0325:                }
0326:
0327:                // Sanity check in case someone doesn't read the javadoc while
0328:                // implementing IRequestTargetUrlCodingStrategy
0329:                if (path.startsWith("/")) {
0330:                    path = path.substring(1);
0331:                }
0332:
0333:                if (mountsOnPath.strategyForMount(path) != null) {
0334:                    throw new WicketRuntimeException(path
0335:                            + " is already mounted for "
0336:                            + mountsOnPath.strategyForMount(path));
0337:                }
0338:                mountsOnPath.mount(path, encoder);
0339:            }
0340:
0341:            /**
0342:             * @see org.apache.wicket.request.IRequestCodingStrategy#pathForTarget(org.apache.wicket.IRequestTarget)
0343:             */
0344:            public final CharSequence pathForTarget(IRequestTarget requestTarget) {
0345:                // first check whether the target was mounted
0346:                IRequestTargetUrlCodingStrategy encoder = getMountEncoder(requestTarget);
0347:                if (encoder != null) {
0348:                    return encoder.encode(requestTarget);
0349:                }
0350:                return null;
0351:            }
0352:
0353:            /**
0354:             * @see org.apache.wicket.request.IRequestCodingStrategy#targetForRequest(org.apache.wicket.request.RequestParameters)
0355:             */
0356:            public final IRequestTarget targetForRequest(
0357:                    RequestParameters requestParameters) {
0358:                IRequestTargetUrlCodingStrategy encoder = urlCodingStrategyForPath(requestParameters
0359:                        .getPath());
0360:                if (encoder == null) {
0361:                    return null;
0362:                }
0363:                return encoder.decode(requestParameters);
0364:            }
0365:
0366:            /**
0367:             * @see org.apache.wicket.request.IRequestCodingStrategy#unmount(java.lang.String)
0368:             */
0369:            public final void unmount(String path) {
0370:                if (path == null) {
0371:                    throw new IllegalArgumentException(
0372:                            "Argument path must be not-null");
0373:                }
0374:
0375:                // sanity check
0376:                if (path.startsWith("/")) {
0377:                    path = path.substring(1);
0378:                }
0379:
0380:                mountsOnPath.unmount(path);
0381:            }
0382:
0383:            /**
0384:             * Adds bookmarkable page related parameters (page alias and optionally page
0385:             * parameters). Any bookmarkable page alias mount will override this method;
0386:             * hence if a mount is found, this method will not be called.
0387:             * 
0388:             * If you override this method to behave differently then
0389:             * {@link #encode(RequestCycle, IBookmarkablePageRequestTarget)} should also be
0390:             * overridden to be in sync with that behaviour.
0391:             * 
0392:             * @param request
0393:             *            the incoming request
0394:             * @param parameters
0395:             *            the parameters object to set the found values on
0396:             */
0397:            protected void addBookmarkablePageParameters(final Request request,
0398:                    final RequestParameters parameters) {
0399:                final String requestString = request
0400:                        .getParameter(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME);
0401:                if (requestString != null) {
0402:                    final String[] components = Strings.split(requestString,
0403:                            Component.PATH_SEPARATOR);
0404:                    if (components.length != 2) {
0405:                        throw new WicketRuntimeException(
0406:                                "Invalid bookmarkablePage parameter: "
0407:                                        + requestString
0408:                                        + ", expected: 'pageMapName:pageClassName'");
0409:                    }
0410:
0411:                    // Extract any pagemap name
0412:                    final String pageMapName = components[0];
0413:                    parameters
0414:                            .setPageMapName(pageMapName.length() == 0 ? PageMap.DEFAULT_NAME
0415:                                    : pageMapName);
0416:
0417:                    // Extract bookmarkable page class name
0418:                    final String pageClassName = components[1];
0419:                    parameters.setBookmarkablePageClass(pageClassName);
0420:                }
0421:            }
0422:
0423:            /**
0424:             * Adds page related parameters (path and pagemap and optionally version and
0425:             * interface).
0426:             * 
0427:             * If you override this method to behave different then also
0428:             * {@link #encode(RequestCycle, IListenerInterfaceRequestTarget)} should be
0429:             * overridden to by in sync with that behaviour.
0430:             * 
0431:             * @param request
0432:             *            the incoming request
0433:             * @param parameters
0434:             *            the parameters object to set the found values on
0435:             */
0436:            protected void addInterfaceParameters(final Request request,
0437:                    final RequestParameters parameters) {
0438:                addInterfaceParameters(request
0439:                        .getParameter(INTERFACE_PARAMETER_NAME), parameters);
0440:            }
0441:
0442:            /**
0443:             * Analyses the passed in interfaceParameter for the relevant parts and puts
0444:             * the parts as parameters in the provided request parameters object.
0445:             * 
0446:             * @param interfaceParameter
0447:             *            The format of the interfaceParameter is: <code>
0448:             * page-map-name:path:version:interface:behaviourId:urlDepth
0449:             * </code>
0450:             * @param parameters
0451:             *            parameters object to set the found parts in
0452:             */
0453:            public static void addInterfaceParameters(
0454:                    final String interfaceParameter,
0455:                    final RequestParameters parameters) {
0456:                if (interfaceParameter == null) {
0457:                    return;
0458:                }
0459:
0460:                // Split into array of strings
0461:                String[] pathComponents = Strings.split(interfaceParameter,
0462:                        Component.PATH_SEPARATOR);
0463:
0464:                // There must be 6 components
0465:                // pagemap:(pageid:componenta:componentb:...):version:interface:behavior:depth
0466:                if (pathComponents.length < 6) {
0467:                    throw new WicketRuntimeException("Internal error parsing "
0468:                            + INTERFACE_PARAMETER_NAME + " = "
0469:                            + interfaceParameter);
0470:                }
0471:
0472:                // Extract version
0473:                String versionNumberString = null;
0474:                try {
0475:                    versionNumberString = pathComponents[pathComponents.length - 4];
0476:                    final int versionNumber = Strings
0477:                            .isEmpty(versionNumberString) ? 0 : Integer
0478:                            .parseInt(versionNumberString);
0479:                    parameters.setVersionNumber(versionNumber);
0480:                } catch (NumberFormatException e) {
0481:                    throw new WicketRuntimeException(
0482:                            "Internal error parsing "
0483:                                    + INTERFACE_PARAMETER_NAME
0484:                                    + " = "
0485:                                    + interfaceParameter
0486:                                    + "; wrong format for page version argument. Expected a number but was '"
0487:                                    + versionNumberString + "'", e);
0488:                }
0489:
0490:                // Set pagemap name
0491:                final String pageMapName = pathComponents[0];
0492:                parameters
0493:                        .setPageMapName(pageMapName.length() == 0 ? PageMap.DEFAULT_NAME
0494:                                : pageMapName);
0495:
0496:                // Extract URL depth after last colon
0497:                final String urlDepthString = pathComponents[pathComponents.length - 1];
0498:                final int urlDepth = Strings.isEmpty(urlDepthString) ? -1
0499:                        : Integer.parseInt(urlDepthString);
0500:                parameters.setUrlDepth(urlDepth);
0501:
0502:                // Extract behaviour ID after last colon
0503:                final String behaviourId = pathComponents[pathComponents.length - 2];
0504:                parameters
0505:                        .setBehaviorId(behaviourId.length() != 0 ? behaviourId
0506:                                : null);
0507:
0508:                // Extract interface name after second-to-last colon
0509:                final String interfaceName = pathComponents[pathComponents.length - 3];
0510:                parameters
0511:                        .setInterfaceName(interfaceName.length() != 0 ? interfaceName
0512:                                : IRedirectListener.INTERFACE.getName());
0513:
0514:                // Component path is everything after pageMapName and before version
0515:                final int start = pageMapName.length() + 1;
0516:                final int end = interfaceParameter.length()
0517:                        - behaviourId.length() - interfaceName.length()
0518:                        - versionNumberString.length()
0519:                        - urlDepthString.length() - 4;
0520:                final String componentPath = interfaceParameter.substring(
0521:                        start, end);
0522:                parameters.setComponentPath(componentPath);
0523:            }
0524:
0525:            /**
0526:             * Adds (shared) resource related parameters (resource key). Any shared
0527:             * resource key mount will override this method; hence if a mount is found,
0528:             * this method will not be called.
0529:             * 
0530:             * If you override this method to behave different then also
0531:             * {@link #encode(RequestCycle, ISharedResourceRequestTarget)} should be
0532:             * overridden to by in sync with that behaviour.
0533:             * 
0534:             * @param request
0535:             *            the incomming request
0536:             * @param parameters
0537:             *            the parameters object to set the found values on
0538:             */
0539:            protected void addResourceParameters(Request request,
0540:                    RequestParameters parameters) {
0541:                String pathInfo = request.getPath();
0542:                if (pathInfo != null
0543:                        && pathInfo.startsWith(RESOURCES_PATH_PREFIX)) {
0544:                    int ix = RESOURCES_PATH_PREFIX.length();
0545:                    if (pathInfo.length() > ix) {
0546:                        StringBuffer path = new StringBuffer(pathInfo
0547:                                .substring(ix));
0548:                        int ixSemiColon = path.indexOf(";");
0549:                        // strip off any jsession id
0550:                        if (ixSemiColon != -1) {
0551:                            int ixEnd = path.indexOf("?");
0552:                            if (ixEnd == -1) {
0553:                                ixEnd = path.length();
0554:                            }
0555:                            path.delete(ixSemiColon, ixEnd);
0556:                        }
0557:                        parameters.setResourceKey(path.toString());
0558:                    }
0559:                }
0560:            }
0561:
0562:            /**
0563:             * In case you are using custom targets that are not part of the default
0564:             * target hierarchy, you need to override this method, which will be called
0565:             * after the defaults have been tried. When this doesn't provide a url
0566:             * either (returns null), an exception will be thrown by the encode method
0567:             * saying that encoding could not be done.
0568:             * 
0569:             * @param requestCycle
0570:             *            the current request cycle (for efficient access)
0571:             * 
0572:             * @param requestTarget
0573:             *            the request target
0574:             * @return the url to the provided target, as a relative path from the
0575:             *         filter root.
0576:             */
0577:            protected String doEncode(RequestCycle requestCycle,
0578:                    IRequestTarget requestTarget) {
0579:                return null;
0580:            }
0581:
0582:            /**
0583:             * Encode a page class target.
0584:             * 
0585:             * If you override this method to behave different then also
0586:             * {@link #addBookmarkablePageParameters(Request, RequestParameters)} should
0587:             * be overridden to by in sync with that behaviour.
0588:             * 
0589:             * @param requestCycle
0590:             *            the current request cycle
0591:             * @param requestTarget
0592:             *            the target to encode
0593:             * @return the encoded url
0594:             */
0595:            protected CharSequence encode(RequestCycle requestCycle,
0596:                    IBookmarkablePageRequestTarget requestTarget) {
0597:                // Begin encoding URL
0598:                final AppendingStringBuffer url = new AppendingStringBuffer(64);
0599:
0600:                // Get page Class
0601:                final Class pageClass = requestTarget.getPageClass();
0602:                final Application application = Application.get();
0603:
0604:                // Find pagemap name
0605:                String pageMapName = requestTarget.getPageMapName();
0606:                if (pageMapName == null) {
0607:                    IRequestTarget currentTarget = requestCycle
0608:                            .getRequestTarget();
0609:                    if (currentTarget instanceof  IPageRequestTarget) {
0610:                        Page currentPage = ((IPageRequestTarget) currentTarget)
0611:                                .getPage();
0612:                        final IPageMap pageMap = currentPage.getPageMap();
0613:                        if (pageMap.isDefault()) {
0614:                            pageMapName = "";
0615:                        } else {
0616:                            pageMapName = pageMap.getName();
0617:                        }
0618:                    } else {
0619:                        pageMapName = "";
0620:                    }
0621:                }
0622:
0623:                WebRequestEncoder encoder = new WebRequestEncoder(url);
0624:                if (!application.getHomePage().equals(pageClass)
0625:                        || !"".equals(pageMapName)
0626:                        || (application.getHomePage().equals(pageClass) && requestTarget instanceof  BookmarkableListenerInterfaceRequestTarget)) {
0627:                    /*
0628:                     * Add <page-map-name>:<bookmarkable-page-class>
0629:                     * 
0630:                     * Encode the url so it is correct even for class names containing
0631:                     * non ASCII characters, like ä, æ, ø, å etc.
0632:                     * 
0633:                     * The reason for this is that when redirecting to these
0634:                     * bookmarkable pages, we need to have the url encoded correctly
0635:                     * because we can't rely on the browser to interpret the unencoded
0636:                     * url correctly.
0637:                     */
0638:                    encoder
0639:                            .addValue(
0640:                                    WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME,
0641:                                    pageMapName + Component.PATH_SEPARATOR
0642:                                            + pageClass.getName());
0643:                }
0644:
0645:                // Get page parameters
0646:                final PageParameters parameters = requestTarget
0647:                        .getPageParameters();
0648:                if (parameters != null) {
0649:                    final Iterator iterator;
0650:                    if (UnitTestSettings.getSortUrlParameters()) {
0651:                        iterator = new TreeSet(parameters.keySet()).iterator();
0652:                    } else {
0653:                        iterator = parameters.keySet().iterator();
0654:                    }
0655:                    while (iterator.hasNext()) {
0656:                        final String key = (String) iterator.next();
0657:                        final String values[] = parameters.getStringArray(key);
0658:                        if (values != null) {
0659:                            for (int i = 0; i < values.length; i++) {
0660:                                encoder.addValue(key, values[i]);
0661:                            }
0662:                        }
0663:                    }
0664:                }
0665:                return url;
0666:            }
0667:
0668:            /**
0669:             * Encode a shared resource target.
0670:             * 
0671:             * If you override this method to behave different then also
0672:             * {@link #addResourceParameters(Request, RequestParameters)} should be
0673:             * overridden to by in sync with that behaviour.
0674:             * 
0675:             * @param requestCycle
0676:             *            the current request cycle
0677:             * @param requestTarget
0678:             *            the target to encode
0679:             * @return the encoded url
0680:             */
0681:            protected CharSequence encode(RequestCycle requestCycle,
0682:                    ISharedResourceRequestTarget requestTarget) {
0683:                final String sharedResourceKey = requestTarget.getResourceKey();
0684:                if ((sharedResourceKey == null)
0685:                        || (sharedResourceKey.trim().length() == 0)) {
0686:                    return "";
0687:                } else {
0688:                    final AppendingStringBuffer buffer = new AppendingStringBuffer(
0689:                            sharedResourceKey.length());
0690:                    buffer.append("resources/");
0691:                    buffer.append(sharedResourceKey);
0692:                    Map map = requestTarget.getRequestParameters()
0693:                            .getParameters();
0694:                    if (map != null && map.size() > 0) {
0695:                        buffer.append('?');
0696:                        Iterator it = map.entrySet().iterator();
0697:                        while (it.hasNext()) {
0698:                            Map.Entry entry = (Entry) it.next();
0699:                            buffer.append(entry.getKey());
0700:                            buffer.append('=');
0701:                            buffer.append(entry.getValue());
0702:                            if (it.hasNext()) {
0703:                                buffer.append("&amp;");
0704:                            }
0705:                        }
0706:                    }
0707:                    return buffer;
0708:                }
0709:            }
0710:
0711:            /**
0712:             * Encode a listener interface target.
0713:             * 
0714:             * If you override this method to behave different then also
0715:             * {@link #addInterfaceParameters(Request, RequestParameters)} should be
0716:             * overridden to by in sync with that behaviour.
0717:             * 
0718:             * @param requestCycle
0719:             *            the current request cycle
0720:             * @param requestTarget
0721:             *            the target to encode
0722:             * @return the encoded url
0723:             */
0724:            protected CharSequence encode(RequestCycle requestCycle,
0725:                    IListenerInterfaceRequestTarget requestTarget) {
0726:                final RequestListenerInterface rli = requestTarget
0727:                        .getRequestListenerInterface();
0728:
0729:                // Start string buffer for url
0730:                final AppendingStringBuffer url = new AppendingStringBuffer(64);
0731:                url.append('?');
0732:                url.append(INTERFACE_PARAMETER_NAME);
0733:                url.append('=');
0734:
0735:                // Get component and page for request target
0736:                final Component component = requestTarget.getTarget();
0737:                final Page page = component.getPage();
0738:
0739:                // Add pagemap
0740:                final IPageMap pageMap = page.getPageMap();
0741:                if (!pageMap.isDefault()) {
0742:                    url.append(pageMap.getName());
0743:                }
0744:                url.append(Component.PATH_SEPARATOR);
0745:
0746:                // Add path to component
0747:                url.append(component.getPath());
0748:                url.append(Component.PATH_SEPARATOR);
0749:
0750:                // Add version
0751:                final int versionNumber = component.getPage()
0752:                        .getCurrentVersionNumber();
0753:                if (!rli.getRecordsPageVersion()) {
0754:                    url.append(Page.LATEST_VERSION);
0755:                } else if (versionNumber > 0) {
0756:                    url.append(versionNumber);
0757:                }
0758:                url.append(Component.PATH_SEPARATOR);
0759:
0760:                // Add listener interface
0761:                final String listenerName = rli.getName();
0762:                if (!IRedirectListener.INTERFACE.getName().equals(listenerName)) {
0763:                    url.append(listenerName);
0764:                }
0765:                url.append(Component.PATH_SEPARATOR);
0766:
0767:                // Add behaviourId
0768:                RequestParameters params = requestTarget.getRequestParameters();
0769:                if (params != null && params.getBehaviorId() != null) {
0770:                    url.append(params.getBehaviorId());
0771:                }
0772:                url.append(Component.PATH_SEPARATOR);
0773:
0774:                // Add URL depth
0775:                if (params != null && params.getUrlDepth() != 0) {
0776:                    url.append(params.getUrlDepth());
0777:                }
0778:
0779:                return url;
0780:            }
0781:
0782:            /**
0783:             * Encode a page target.
0784:             * 
0785:             * @param requestCycle
0786:             *            the current request cycle
0787:             * @param requestTarget
0788:             *            the target to encode
0789:             * @return the encoded url
0790:             */
0791:            protected CharSequence encode(RequestCycle requestCycle,
0792:                    IPageRequestTarget requestTarget) {
0793:                // Get the page we want a url from:
0794:                Page page = requestTarget.getPage();
0795:
0796:                // A url to a page is the IRedirectListener interface:
0797:                CharSequence urlRedirect = page
0798:                        .urlFor(IRedirectListener.INTERFACE);
0799:
0800:                // Touch the page once because it could be that it did go from stateless
0801:                // to statefull or it was a internally made page where just a url must
0802:                // be made for (frames)
0803:                Session.get().touch(page);
0804:                return urlRedirect;
0805:            }
0806:
0807:            /**
0808:             * Gets the mount encoder for the given request target if any.
0809:             * 
0810:             * @param requestTarget
0811:             *            the request target to match
0812:             * @return the mount encoder if any
0813:             */
0814:            protected IRequestTargetUrlCodingStrategy getMountEncoder(
0815:                    IRequestTarget requestTarget) {
0816:                // TODO Post 1.2: Performance: Optimize algorithm if possible and/ or
0817:                // cache lookup results
0818:                for (Iterator i = mountsOnPath.strategies().iterator(); i
0819:                        .hasNext();) {
0820:                    IRequestTargetUrlCodingStrategy encoder = (IRequestTargetUrlCodingStrategy) i
0821:                            .next();
0822:                    if (encoder.matches(requestTarget)) {
0823:                        return encoder;
0824:                    }
0825:                }
0826:
0827:                return null;
0828:            }
0829:
0830:            /**
0831:             * Gets the request info path. This is an overridable method in order to
0832:             * provide users with a means to implement e.g. a path encryption scheme.
0833:             * This method by default returns {@link Request#getPath()}.
0834:             * 
0835:             * @param request
0836:             *            the request
0837:             * @return the path info object, possibly processed
0838:             */
0839:            protected String getRequestPath(Request request) {
0840:                return request.getPath();
0841:            }
0842:
0843:            /**
0844:             * Map used to store mount paths and their corresponding url coding
0845:             * strategies.
0846:             * 
0847:             * @author ivaynberg
0848:             */
0849:            private static class MountsMap {
0850:                private static final long serialVersionUID = 1L;
0851:
0852:                /** case sensitive flag */
0853:                private final boolean caseSensitiveMounts;
0854:
0855:                /** backing map */
0856:                private final TreeMap map;
0857:
0858:                /**
0859:                 * Constructor
0860:                 * 
0861:                 * @param caseSensitiveMounts
0862:                 *            whether or not keys of this map are case-sensitive
0863:                 */
0864:                public MountsMap(boolean caseSensitiveMounts) {
0865:                    map = new TreeMap(LENGTH_COMPARATOR);
0866:                    this .caseSensitiveMounts = caseSensitiveMounts;
0867:                }
0868:
0869:                /**
0870:                 * Checks if the specified path matches any mount, and if so returns the
0871:                 * coding strategy for that mount. Returns null if the path doesnt match
0872:                 * any mounts.
0873:                 * 
0874:                 * NOTE: path here is not the mount - it is the full url path
0875:                 * 
0876:                 * @param path
0877:                 *            non-null url path
0878:                 * @return coding strategy or null
0879:                 */
0880:                public IRequestTargetUrlCodingStrategy strategyForPath(
0881:                        String path) {
0882:                    if (path == null) {
0883:                        throw new IllegalArgumentException(
0884:                                "Argument [[path]] cannot be null");
0885:                    }
0886:                    if (caseSensitiveMounts == false) {
0887:                        path = path.toLowerCase();
0888:                    }
0889:                    for (final Iterator it = map.entrySet().iterator(); it
0890:                            .hasNext();) {
0891:                        final Map.Entry entry = (Entry) it.next();
0892:                        final String key = (String) entry.getKey();
0893:                        if (path.startsWith(key)) {
0894:                            IRequestTargetUrlCodingStrategy strategy = (IRequestTargetUrlCodingStrategy) entry
0895:                                    .getValue();
0896:                            if (strategy.matches(path)) {
0897:                                return strategy;
0898:                            }
0899:                        }
0900:                    }
0901:                    return null;
0902:                }
0903:
0904:                /**
0905:                 * @return number of mounts in the map
0906:                 */
0907:                public int size() {
0908:                    return map.size();
0909:                }
0910:
0911:                /**
0912:                 * @return collection of coding strategies associated with every mount
0913:                 */
0914:                public Collection strategies() {
0915:                    return map.values();
0916:                }
0917:
0918:                /**
0919:                 * Removes mount from the map
0920:                 * 
0921:                 * @param mount
0922:                 */
0923:                public void unmount(String mount) {
0924:                    if (caseSensitiveMounts == false && mount != null) {
0925:                        mount = mount.toLowerCase();
0926:                    }
0927:
0928:                    map.remove(mount);
0929:                }
0930:
0931:                /**
0932:                 * Gets the coding strategy for the specified mount path
0933:                 * 
0934:                 * @param mount
0935:                 *            mount paht
0936:                 * @return associated coding strategy or null if none
0937:                 */
0938:                public IRequestTargetUrlCodingStrategy strategyForMount(
0939:                        String mount) {
0940:                    if (caseSensitiveMounts == false && mount != null) {
0941:                        mount = mount.toLowerCase();
0942:                    }
0943:
0944:                    return (IRequestTargetUrlCodingStrategy) map.get(mount);
0945:                }
0946:
0947:                /**
0948:                 * Associates a mount with a coding strategy
0949:                 * 
0950:                 * @param mount
0951:                 * @param encoder
0952:                 * @return previous coding strategy associated with the mount, or null
0953:                 *         if none
0954:                 */
0955:                public IRequestTargetUrlCodingStrategy mount(String mount,
0956:                        IRequestTargetUrlCodingStrategy encoder) {
0957:                    if (caseSensitiveMounts == false && mount != null) {
0958:                        mount = mount.toLowerCase();
0959:                    }
0960:                    return (IRequestTargetUrlCodingStrategy) map.put(mount,
0961:                            encoder);
0962:                }
0963:
0964:                /** Comparator implementation that sorts longest strings first */
0965:                private static final Comparator LENGTH_COMPARATOR = new Comparator() {
0966:                    public int compare(Object o1, Object o2) {
0967:                        // longer first
0968:                        if (o1 == o2) {
0969:                            return 0;
0970:                        } else if (o1 == null) {
0971:                            return 1;
0972:                        } else if (o2 == null) {
0973:                            return -1;
0974:                        } else {
0975:                            final String lhs = (String) o1;
0976:                            final String rhs = (String) o2;
0977:                            return rhs.compareTo(lhs);
0978:                        }
0979:                    }
0980:                };
0981:            }
0982:
0983:            /**
0984:             * Makes page map name url safe.
0985:             * 
0986:             * Since the default page map name in wicket is null and null does not
0987:             * encode well into urls this method will substitute null for a known token.
0988:             * If the <code>pageMapName</code> passed in is not null it is returned
0989:             * without modification.
0990:             * 
0991:             * @param pageMapName
0992:             *            page map name
0993:             * @return encoded pagemap name
0994:             */
0995:            public static final String encodePageMapName(String pageMapName) {
0996:                if (Strings.isEmpty(pageMapName)) {
0997:                    return DEFAULT_PAGEMAP_NAME;
0998:                } else {
0999:                    return pageMapName;
1000:                }
1001:            }
1002:
1003:            /**
1004:             * Undoes the effect of {@link #encodePageMapName(String)}
1005:             * 
1006:             * @param pageMapName
1007:             *            page map name
1008:             * @return decoded page map name
1009:             */
1010:            public static String decodePageMapName(String pageMapName) {
1011:                if (DEFAULT_PAGEMAP_NAME.equals(pageMapName)) {
1012:                    return null;
1013:                } else {
1014:                    return pageMapName;
1015:                }
1016:            }
1017:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.