📄 webrequestcodingstrategy.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.wicket.protocol.http.request;import java.util.Collection;import java.util.Comparator;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.TreeMap;import java.util.TreeSet;import java.util.Map.Entry;import org.apache.wicket.Application;import org.apache.wicket.Component;import org.apache.wicket.IPageMap;import org.apache.wicket.IRedirectListener;import org.apache.wicket.IRequestTarget;import org.apache.wicket.IResourceListener;import org.apache.wicket.Page;import org.apache.wicket.PageMap;import org.apache.wicket.PageParameters;import org.apache.wicket.RequestContext;import org.apache.wicket.Request;import org.apache.wicket.RequestCycle;import org.apache.wicket.RequestListenerInterface;import org.apache.wicket.Session;import org.apache.wicket.WicketRuntimeException;import org.apache.wicket.behavior.AbstractAjaxBehavior;import org.apache.wicket.behavior.IActivePageBehaviorListener;import org.apache.wicket.behavior.IBehaviorListener;import org.apache.wicket.protocol.http.UnitTestSettings;import org.apache.wicket.protocol.http.WebRequestCycle;import org.apache.wicket.protocol.http.portlet.PortletRequestContext;import org.apache.wicket.request.IRequestCodingStrategy;import org.apache.wicket.request.IRequestTargetMountsInfo;import org.apache.wicket.request.RequestParameters;import org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy;import org.apache.wicket.request.target.coding.WebRequestEncoder;import org.apache.wicket.request.target.component.BookmarkableListenerInterfaceRequestTarget;import org.apache.wicket.request.target.component.IBookmarkablePageRequestTarget;import org.apache.wicket.request.target.component.IPageRequestTarget;import org.apache.wicket.request.target.component.listener.IListenerInterfaceRequestTarget;import org.apache.wicket.request.target.resource.ISharedResourceRequestTarget;import org.apache.wicket.util.string.AppendingStringBuffer;import org.apache.wicket.util.string.PrependingStringBuffer;import org.apache.wicket.util.string.Strings;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Request parameters factory implementation that uses http request parameters and path info to * construct the request parameters object. * * @author Eelco Hillenius * @author Jonathan Locke */public class WebRequestCodingStrategy implements IRequestCodingStrategy, IRequestTargetMountsInfo{ /** Name of interface target query parameter */ public static final String NAME_SPACE = "wicket:"; /** Name of interface target query parameter */ public static final String INTERFACE_PARAMETER_NAME = NAME_SPACE + "interface"; /** AJAX query parameter name */ public static final String BEHAVIOR_ID_PARAMETER_NAME = NAME_SPACE + "behaviorId"; /** Parameter name used all over the place */ public static final String BOOKMARKABLE_PAGE_PARAMETER_NAME = NAME_SPACE + "bookmarkablePage"; /** Pagemap parameter constant */ public static final String PAGEMAP = NAME_SPACE + "pageMapName"; /** * Url name of the default pagemap * * When we encode the default pagemap name in a url we cannot always use null or "" because it * breaks urls which are encoded with /param1/value1/ eg /product/14/wicket:pageMapName/ split * on / will split into {product,14,wicket:pageMapName} */ public static final String DEFAULT_PAGEMAP_NAME = "wicketdef"; /** The URL path prefix expected for (so called) resources (not html pages). */ public static final String RESOURCES_PATH_PREFIX = "resources/"; /** * Parameter name that tells decode to ignore this request if the page+version encoded in the * url is not on top of the stack. The value of this parameter is not important, it simply has * to be present to enable the behavior */ public static final String IGNORE_IF_NOT_ACTIVE_PARAMETER_NAME = NAME_SPACE + "ignoreIfNotActive"; /** * Various settings used to configure this strategy * * @author ivaynberg */ public static class Settings { /** whether or not mount paths are case sensitive */ private boolean mountsCaseSensitive = true; /** * Construct. */ public Settings() { } /** * Sets mountsCaseSensitive. * * @param mountsCaseSensitive * mountsCaseSensitive */ public void setMountsCaseSensitive(boolean mountsCaseSensitive) { this.mountsCaseSensitive = mountsCaseSensitive; } /** * Gets caseSensitive. * * @return caseSensitive */ public boolean areMountsCaseSensitive() { return mountsCaseSensitive; } } /** log. */ private static final Logger log = LoggerFactory.getLogger(WebRequestCodingStrategy.class); /** * map of path mounts for mount encoders on paths. * <p> * mountsOnPath is sorted by longest paths first to improve resolution of possible path * conflicts. <br /> * For example: <br/> we mount Page1 on /page and Page2 on /page/test <br /> * Page1 uses a parameters encoder that only encodes parameter values <br /> * now suppose we want to access Page1 with a single parameter param="test". we have a url * collision since both pages can be access with /page/test <br /> * the sorting by longest path first guarantees that the iterator will return the mount * /page/test before it returns mount /page therefore giving deterministic behavior to path * resolution by always trying to match the longest possible path first. * </p> */ private final MountsMap mountsOnPath; /** * Construct. */ public WebRequestCodingStrategy() { this(new Settings()); } /** * Construct. * * @param settings */ public WebRequestCodingStrategy(Settings settings) { if (settings == null) { throw new IllegalArgumentException("Argument [[settings]] cannot be null"); } mountsOnPath = new MountsMap(settings.areMountsCaseSensitive()); } /** * @see org.apache.wicket.request.IRequestCodingStrategy#decode(org.apache.wicket.Request) */ public final RequestParameters decode(final Request request) { final RequestParameters parameters = new RequestParameters(); final String pathInfo = getRequestPath(request); parameters.setPath(pathInfo); parameters.setPageMapName(request.getParameter(PAGEMAP)); addInterfaceParameters(request, parameters); addBookmarkablePageParameters(request, parameters); addResourceParameters(request, parameters); if (request.getParameter(IGNORE_IF_NOT_ACTIVE_PARAMETER_NAME) != null) { parameters.setOnlyProcessIfPathActive(true); } Map map = request.getParameterMap(); Iterator iterator = map.keySet().iterator(); while (iterator.hasNext()) { String key = (String)iterator.next(); if (key.startsWith(NAME_SPACE)) { iterator.remove(); } } parameters.setParameters(map); return parameters; } /** * Encode the given request target. If a mount is found, that mounted url will be returned. * Otherwise, one of the delegation methods will be called. In case you are using custom targets * that are not part of the default target hierarchy, you need to override * {@link #doEncode(RequestCycle, IRequestTarget)}, which will be called after the defaults * have been tried. When that doesn't provide a url either, an exception will be thrown saying * that encoding could not be done. * * @see org.apache.wicket.request.IRequestCodingStrategy#encode(org.apache.wicket.RequestCycle, * org.apache.wicket.IRequestTarget) */ public final CharSequence encode(final RequestCycle requestCycle, final IRequestTarget requestTarget) { // First check to see whether the target is mounted CharSequence url = pathForTarget(requestTarget); RequestContext requestContext = RequestContext.get(); boolean portletRequest = requestContext.isPortletRequest(); boolean sharedResourceURL = false; if (url != null && !portletRequest) { // Do nothing - we've found the URL and it's mounted. } else if (requestTarget instanceof IBookmarkablePageRequestTarget) { url = requestContext.encodeRenderURL(url == null ? encode(requestCycle, (IBookmarkablePageRequestTarget)requestTarget) : url); } else if (requestTarget instanceof ISharedResourceRequestTarget) { url = requestContext.encodeSharedResourceURL(url == null ? encode(requestCycle, (ISharedResourceRequestTarget)requestTarget) : url); sharedResourceURL = true; } else if (requestTarget instanceof IListenerInterfaceRequestTarget) { if (url == null) { url = encode(requestCycle, (IListenerInterfaceRequestTarget)requestTarget); } if (portletRequest) { IListenerInterfaceRequestTarget iliRequestTarget = (IListenerInterfaceRequestTarget)requestTarget; RequestListenerInterface rli = iliRequestTarget.getRequestListenerInterface(); if (IResourceListener.class.isAssignableFrom(rli.getMethod().getDeclaringClass()) || IBehaviorListener.class.isAssignableFrom(rli.getMethod() .getDeclaringClass())) { url = requestContext.encodeResourceURL(url); } else if (IRedirectListener.class.isAssignableFrom(rli.getMethod() .getDeclaringClass())) { if (((WebRequestCycle)requestCycle).getWebRequest().isAjax()) { // TODO: Probably not all Ajax based redirects need to break out of // ResourceURL encoding // Need to find out and/or provide some kind of extension how to indicate // this url = ((PortletRequestContext)requestContext).encodeRenderURL(url, true); } else { url = requestContext.encodeRenderURL(url); } } else { PortletRequestContext prc = (PortletRequestContext)requestContext; boolean forceActionURL = prc.isAjax(); if (forceActionURL) { List behaviors = iliRequestTarget.getTarget().getBehaviors(); for (int i = 0, size = behaviors.size(); i < size; i++) { if (AbstractAjaxBehavior.class.isAssignableFrom(behaviors.get(i) .getClass())) { forceActionURL = false; break; } } } url = prc.encodeActionURL(url, forceActionURL); } } } else if (url == null) { if (requestTarget instanceof IPageRequestTarget) { // This calls page.urlFor(IRedirectListener.INTERFACE), which calls // the function we're in again. We therefore need to jump out here // and return the url immediately, otherwise we end up prefixing it // with relative path or absolute prefixes twice. return encode(requestCycle, (IPageRequestTarget)requestTarget); } // fall through for non-default request targets else { url = doEncode(requestCycle, requestTarget); } } if (url != null) { String result = null; if (!sharedResourceURL && portletRequest) { result = url.toString(); } else { // Add the actual URL. This will be relative to the Wicket // Servlet/Filter, with no leading '/'. PrependingStringBuffer prepender = new PrependingStringBuffer(url.toString()); // Prepend prefix to the URL to make it relative to the current // request. prepender.prepend(requestCycle.getRequest().getRelativePathPrefixToWicketHandler()); result = prepender.toString(); // We need to special-case links to the home page if we're at the // same level. if (result.length() == 0) { result = "./"; } } return requestCycle.getOriginalResponse().encodeURL(result); } // Just return null instead of throwing an exception. So that it can be // handled better return null; } /** * Returns the given url encoded. * * @param url * The URL to encode * @return The encoded url */ public CharSequence encode(CharSequence url) { // no further encoding needed return url; } /** * @see org.apache.wicket.request.IRequestTargetMountsInfo#listMounts() */ public IRequestTargetUrlCodingStrategy[] listMounts() { synchronized (mountsOnPath) { return (IRequestTargetUrlCodingStrategy[])mountsOnPath.strategies().toArray( new IRequestTargetUrlCodingStrategy[mountsOnPath.size()]); } } /** * @see org.apache.wicket.request.IRequestTargetMounter#urlCodingStrategyForPath(java.lang.String) */ public IRequestTargetUrlCodingStrategy urlCodingStrategyForPath(String path) { synchronized (mountsOnPath) { if (path == null) { return mountsOnPath.strategyForMount(null); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -