You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by kn...@apache.org on 2008/11/16 23:04:29 UTC

svn commit: r718123 [6/10] - in /wicket/sandbox/knopp/experimental/wicket: ./ .settings/ src/main/java/org/apache/wicket/ src/main/java/org/apache/wicket/ajax/ src/main/java/org/apache/wicket/ajax/form/ src/main/java/org/apache/wicket/ajax/markup/html/...

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketPortlet.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketPortlet.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketPortlet.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketPortlet.java Sun Nov 16 14:04:19 2008
@@ -27,6 +27,7 @@
 import javax.portlet.GenericPortlet;
 import javax.portlet.PortletConfig;
 import javax.portlet.PortletException;
+import javax.portlet.PortletMode;
 import javax.portlet.PortletRequest;
 import javax.portlet.PortletRequestDispatcher;
 import javax.portlet.PortletResponse;
@@ -40,34 +41,111 @@
 
 import org.apache.portals.bridges.common.PortletResourceURLFactory;
 import org.apache.portals.bridges.common.ServletContextProvider;
+import org.apache.wicket.Resource;
+import org.apache.wicket.protocol.http.WicketFilter;
 
 /**
+ * Adapter between the Portlet world requests and the internal Wicket engine. I.e. simulates the
+ * web/servlet environment for Wicket, while it's actually running as a Portlet.
+ * 
+ * <p>
+ * It receives a portlet request and dispatches to a a Wicket filter; wrapping the servlet context,
+ * request and response objects; intercepts response writing (especially urls and redirects) and
+ * rewrites and adapts the output to accommodate the portlet requirements.
+ * 
+ * <p>
+ * The WicketPortlet is configured (using an initParameter) against a specific filter path, e.g.
+ * Wicket WebApplication. The WicketPortlet maintains a parameter for the current Wicket page url,
+ * based against the filter path (e.g. fully qualified to the context path). When a request (action,
+ * render or direct resource/ajax call) is received by the WicketPortlet, it dispatches it to Wicket
+ * as a servlet request using the provided Wicket page url parameter.
+ * 
+ * @see WicketFilter
  * @author Ate Douma
  */
 public class WicketPortlet extends GenericPortlet
 {
+	/**
+	 * FIXME javadoc
+	 * 
+	 * <p>
+	 * The prefix for the parameter name for storing Wicket URLs.
+	 */
 	public static final String WICKET_URL_PORTLET_PARAMETER = "_wu";
+
+	/**
+	 * FIXME javadoc
+	 * 
+	 * <p>
+	 * The prefix for the parameter name for storing Wicket Resource URLs.
+	 * 
+	 * @see Resource
+	 */
 	public static final String PORTLET_RESOURCE_URL_PARAMETER = "_ru";
+
+	/**
+	 * FIXME javadoc
+	 * 
+	 * <p>
+	 * The attribute name for storing if the request is a Resource request or not.
+	 * 
+	 * @see Resource
+	 */
 	public static final String PORTLET_RESOURCE_URL_ATTR = "_ru";
+
+	/**
+	 * FIXME javadoc
+	 */
 	public static final String WICKET_FILTER_PATH_PARAM = "wicketFilterPath";
+
+	/**
+	 * FIXME javadoc
+	 * 
+	 * <p>
+	 * Parameter name to store the {@link ServletContextProvider}.
+	 */
 	public static final String PARAM_SERVLET_CONTEXT_PROVIDER = "ServletContextProvider";
+
+	/**
+	 * FIXME javadoc
+	 * 
+	 * <p>
+	 * Parameter name to store the {@link PortletResourceURLFactory}.
+	 */
 	public static final String PARAM_PORTLET_RESOURCE_URL_FACTORY = "PortletResourceURLFactory";
+	/** Portal Action request */
 	public static final String ACTION_REQUEST = "ACTION";
-	public static final String VIEW_REQUEST = "VIEW";
+	/** Portal Resource request */
 	public static final String RESOURCE_REQUEST = "RESOURCE";
+
+	/** Portal Custom request */
 	public static final String CUSTOM_REQUEST = "CUSTOM";
+	/** Portal View request - i.e. doView */
+	public static final String VIEW_REQUEST = "VIEW";
+	/** Portal Edit request - i.e. doEdit */
 	public static final String EDIT_REQUEST = "EDIT";
+	/** Portal Help request - i.e. doHelp */
 	public static final String HELP_REQUEST = "HELP";
+	/**
+	 * Marker used as key to store the type of request as a request attribute - i.e. resource /
+	 * action / event request etc .
+	 */
 	public static final String REQUEST_TYPE_ATTR = WicketPortlet.class.getName() + ".REQUEST_TYPE";
+	/**
+	 * FIXME javadoc
+	 * <p>
+	 * The parameter name to store the URL to the Wicket porlet.
+	 */
 	public static final String WICKET_URL_PORTLET_PARAMETER_ATTR = WicketPortlet.class.getName() +
-			".WICKET_URL_PORTLET_PARAMETER";
+		".WICKET_URL_PORTLET_PARAMETER";
 	public static final String CONFIG_PARAM_PREFIX = WicketPortlet.class.getName() + ".";
+	/** Marker used as key for the WicketResponseState object stored as a request attribute. */
 	public static final String RESPONSE_STATE_ATTR = WicketResponseState.class.getName();
-	public static final String RESOURCE_URL_FACTORY_ATTR = PortletResourceURLFactory.class
-			.getName();
+	public static final String RESOURCE_URL_FACTORY_ATTR = PortletResourceURLFactory.class.getName();
+	/** FIXME javadoc */
 	public static final String WICKET_PORTLET_PROPERTIES = WicketPortlet.class.getName().replace(
-			'.', '/') +
-			".properties";
+		'.', '/') +
+		".properties";
 	public static final String WICKET_FILTER_PATH = WicketPortlet.class.getName() + ".FILTERPATH";
 	public static final String WICKET_FILTER_QUERY = WicketPortlet.class.getName() + ".FILTERQUERY";
 
@@ -93,11 +171,16 @@
 	public static final String PARAM_VIEW_PAGE = "viewPage";
 
 	private ServletContextProvider servletContextProvider;
+	/**
+	 * {@link PortletResourceURLFactory}, used to generate {@link Resource} URLs for Portal 168
+	 * support.
+	 */
 	private PortletResourceURLFactory resourceURLFactory;
 	private String wicketFilterPath;
 	private String wicketFilterQuery;
 	private final HashMap defaultPages = new HashMap();
 
+	@Override
 	public void init(PortletConfig config) throws PortletException
 	{
 		super.init(config);
@@ -106,21 +189,20 @@
 		if (contextProviderClassName == null)
 		{
 			contextProviderClassName = config.getPortletContext().getInitParameter(
-					ServletContextProvider.class.getName());
+				ServletContextProvider.class.getName());
 		}
 		if (contextProviderClassName == null)
 		{
 			wicketPortletProperties = getWicketPortletProperties(wicketPortletProperties);
-			contextProviderClassName = wicketPortletProperties
-					.getProperty(ServletContextProvider.class.getName());
+			contextProviderClassName = wicketPortletProperties.getProperty(ServletContextProvider.class.getName());
 		}
 		if (contextProviderClassName == null)
 		{
 			throw new PortletException("Portlet " + config.getPortletName() +
-					" is incorrectly configured. Init parameter " + PARAM_SERVLET_CONTEXT_PROVIDER +
-					" not specified, nor as context parameter " +
-					ServletContextProvider.class.getName() + " or as property in " +
-					WICKET_PORTLET_PROPERTIES + " in the classpath.");
+				" is incorrectly configured. Init parameter " + PARAM_SERVLET_CONTEXT_PROVIDER +
+				" not specified, nor as context parameter " +
+				ServletContextProvider.class.getName() + " or as property in " +
+				WICKET_PORTLET_PROPERTIES + " in the classpath.");
 		}
 		try
 		{
@@ -140,22 +222,20 @@
 		if (resourceURLFactoryClassName == null)
 		{
 			resourceURLFactoryClassName = config.getPortletContext().getInitParameter(
-					PortletResourceURLFactory.class.getName());
+				PortletResourceURLFactory.class.getName());
 		}
 		if (resourceURLFactoryClassName == null)
 		{
 			wicketPortletProperties = getWicketPortletProperties(wicketPortletProperties);
-			resourceURLFactoryClassName = wicketPortletProperties
-					.getProperty(PortletResourceURLFactory.class.getName());
+			resourceURLFactoryClassName = wicketPortletProperties.getProperty(PortletResourceURLFactory.class.getName());
 		}
 		if (resourceURLFactoryClassName == null)
 		{
 			throw new PortletException("Portlet " + config.getPortletName() +
-					" is incorrectly configured. Init parameter " +
-					PARAM_PORTLET_RESOURCE_URL_FACTORY +
-					" not specified, nor as context parameter " +
-					PortletResourceURLFactory.class.getName() + " or as property in " +
-					WICKET_PORTLET_PROPERTIES + " in the classpath.");
+				" is incorrectly configured. Init parameter " + PARAM_PORTLET_RESOURCE_URL_FACTORY +
+				" not specified, nor as context parameter " +
+				PortletResourceURLFactory.class.getName() + " or as property in " +
+				WICKET_PORTLET_PROPERTIES + " in the classpath.");
 		}
 		try
 		{
@@ -183,6 +263,7 @@
 		validateDefaultPages(defaultPages, wicketFilterPath, wicketFilterQuery);
 	}
 
+	@Override
 	public void destroy()
 	{
 		resourceURLFactory = null;
@@ -231,6 +312,19 @@
 		}
 	}
 
+	/**
+	 * FIXME javadoc
+	 * 
+	 * <p>
+	 * Corrects the incoming URL if the old home page style, or if it's missing the filter path
+	 * prefix.
+	 * 
+	 * @param url
+	 *            the URL to fix
+	 * @param wicketFilterPath
+	 * @param wicketFilterQuery
+	 * @return the corrected URL
+	 */
 	protected String fixWicketUrl(String url, String wicketFilterPath, String wicketFilterQuery)
 	{
 		if (url == null)
@@ -254,14 +348,30 @@
 		return url;
 	}
 
+	/**
+	 * FIXME javadoc
+	 * 
+	 * <p>
+	 * Registers the default pages and their URLs for the different {@link PortletMode}s. Also
+	 * corrects and slightly incorrect URLs (see {@link #fixWicketUrl(String, String, String)}).
+	 * 
+	 * <p>
+	 * If no specific page was specified for a given portlet mode (VIEW, EDIT etc) then the page for
+	 * that mode is set to be the same page as that of the VIEW mode.
+	 * 
+	 * @see PortletMode
+	 * @see #fixWicketUrl(String, String, String)
+	 * @param defaultPages
+	 * @param wicketFilterPath
+	 * @param wicketFilterQuery
+	 */
 	protected void validateDefaultPages(Map defaultPages, String wicketFilterPath,
-			String wicketFilterQuery)
+		String wicketFilterQuery)
 	{
 		String viewPage = fixWicketUrl((String)defaultPages.get(PARAM_VIEW_PAGE), wicketFilterPath,
-				wicketFilterQuery);
-		defaultPages.put(PARAM_VIEW_PAGE, viewPage.startsWith(wicketFilterPath)
-				? viewPage
-				: wicketFilterPath);
+			wicketFilterQuery);
+		defaultPages.put(PARAM_VIEW_PAGE, viewPage.startsWith(wicketFilterPath) ? viewPage
+			: wicketFilterPath);
 
 		String defaultPage = (String)defaultPages.get(PARAM_ACTION_PAGE);
 		if (defaultPage == null)
@@ -272,8 +382,7 @@
 		{
 			defaultPage = fixWicketUrl(defaultPage, wicketFilterPath, wicketFilterQuery);
 			defaultPages.put(PARAM_ACTION_PAGE, defaultPage.startsWith(wicketFilterPath)
-					? defaultPage
-					: viewPage);
+				? defaultPage : viewPage);
 		}
 
 		defaultPage = (String)defaultPages.get(PARAM_CUSTOM_PAGE);
@@ -285,8 +394,7 @@
 		{
 			defaultPage = fixWicketUrl(defaultPage, wicketFilterPath, wicketFilterQuery);
 			defaultPages.put(PARAM_CUSTOM_PAGE, defaultPage.startsWith(wicketFilterPath)
-					? defaultPage
-					: viewPage);
+				? defaultPage : viewPage);
 		}
 
 		defaultPage = (String)defaultPages.get(PARAM_HELP_PAGE);
@@ -298,8 +406,7 @@
 		{
 			defaultPage = fixWicketUrl(defaultPage, wicketFilterPath, wicketFilterQuery);
 			defaultPages.put(PARAM_HELP_PAGE, defaultPage.startsWith(wicketFilterPath)
-					? defaultPage
-					: viewPage);
+				? defaultPage : viewPage);
 		}
 
 		defaultPage = (String)defaultPages.get(PARAM_EDIT_PAGE);
@@ -311,11 +418,22 @@
 		{
 			defaultPage = fixWicketUrl(defaultPage, wicketFilterPath, wicketFilterQuery);
 			defaultPages.put(PARAM_EDIT_PAGE, defaultPage.startsWith(wicketFilterPath)
-					? defaultPage
-					: viewPage);
+				? defaultPage : viewPage);
 		}
 	}
 
+	/**
+	 * Loads the Wicket Portlet properties file off the class path.
+	 * 
+	 * FIXME javadoc - check properties
+	 * 
+	 * @param properties
+	 *            appends the portlet properties to
+	 * @return Wicket portlet properties. Returns an empty or unchanged properties object if Wicket
+	 *         Portlet properties could not be found
+	 * @throws PortletException
+	 *             if loading the properties fails
+	 */
 	protected Properties getWicketPortletProperties(Properties properties) throws PortletException
 	{
 		if (properties == null)
@@ -323,7 +441,7 @@
 			properties = new Properties();
 		}
 		InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(
-				WICKET_PORTLET_PROPERTIES);
+			WICKET_PORTLET_PROPERTIES);
 		if (is != null)
 		{
 			try
@@ -333,47 +451,70 @@
 			catch (IOException e)
 			{
 				throw new PortletException(
-						"Failed to load WicketPortlet.properties from classpath", e);
+					"Failed to load WicketPortlet.properties from classpath", e);
 			}
 		}
 		return properties;
 	}
 
+	/**
+	 * Gets the Context Provider ClassName Parameter from the config object.
+	 * 
+	 * @param config
+	 * @return Context Provider ClassName
+	 */
 	protected String getContextProviderClassNameParameter(PortletConfig config)
 	{
 		return config.getInitParameter(PARAM_SERVLET_CONTEXT_PROVIDER);
 	}
 
+	/**
+	 * Gets the portlet resource url factory class name from the config object.
+	 * 
+	 * @param config
+	 * @return portlet resource url factory class name
+	 */
 	protected String getPortletResourceURLFactoryClassNameParameter(PortletConfig config)
 	{
 		return config.getInitParameter(PARAM_PORTLET_RESOURCE_URL_FACTORY);
 	}
 
+	/**
+	 * 
+	 * @return servlet context provider
+	 */
 	protected ServletContextProvider getServletContextProvider()
 	{
 		return servletContextProvider;
 	}
 
+	/**
+	 * 
+	 * @param portlet
+	 * @param request
+	 * @param response
+	 * @return
+	 */
 	protected ServletContext getServletContext(GenericPortlet portlet, PortletRequest request,
-			PortletResponse response)
+		PortletResponse response)
 	{
 		return getServletContextProvider().getServletContext(portlet);
 	}
 
 	protected HttpServletRequest getHttpServletRequest(GenericPortlet portlet,
-			PortletRequest request, PortletResponse response)
+		PortletRequest request, PortletResponse response)
 	{
 		return getServletContextProvider().getHttpServletRequest(portlet, request);
 	}
 
 	protected HttpServletResponse getHttpServletResponse(GenericPortlet portlet,
-			PortletRequest request, PortletResponse response)
+		PortletRequest request, PortletResponse response)
 	{
 		return getServletContextProvider().getHttpServletResponse(portlet, response);
 	}
 
 	protected String getWicketConfigParameter(PortletRequest request, String paramName,
-			String defaultValue)
+		String defaultValue)
 	{
 		return defaultValue;
 	}
@@ -388,73 +529,95 @@
 		return wicketFilterPath;
 	}
 
+	/**
+	 * Retrieves the Wicket URL from the request object, or if none exists returns the default URL.
+	 * 
+	 * @see PortletRequestContext#getLastEncodedPath()
+	 * @param request
+	 * @param pageType
+	 * @param defaultPage
+	 * @return the Wicket URL from within the specified request
+	 */
 	protected String getWicketURL(PortletRequest request, String pageType, String defaultPage)
 	{
 		String wicketURL = null;
 		if (request instanceof ActionRequest)
 		{
-			wicketURL = request.getParameter((String)request
-					.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR));
+			wicketURL = request.getParameter((String)request.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR));
 		}
 		else
 		{
-			wicketURL = request.getParameter((String)request
-					.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR) +
-					request.getPortletMode().toString());
+			wicketURL = request.getParameter((String)request.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR) +
+				request.getPortletMode().toString());
 		}
 		if (wicketURL == null)
 		{
 			wicketURL = getWicketConfigParameter(request, CONFIG_PARAM_PREFIX + pageType,
-					defaultPage);
+				defaultPage);
 		}
 		return wicketURL;
 	}
 
+	@Override
 	protected void doView(RenderRequest request, RenderResponse response) throws PortletException,
-			IOException
+		IOException
 	{
 		processRequest(request, response, VIEW_REQUEST, PARAM_VIEW_PAGE);
 	}
 
+	@Override
 	protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException,
-			IOException
+		IOException
 	{
 		processRequest(request, response, EDIT_REQUEST, PARAM_EDIT_PAGE);
 	}
 
+	@Override
 	protected void doHelp(RenderRequest request, RenderResponse response) throws PortletException,
-			IOException
+		IOException
 	{
 		processRequest(request, response, HELP_REQUEST, PARAM_HELP_PAGE);
 	}
 
 	protected void doCustom(RenderRequest request, RenderResponse response)
-			throws PortletException, IOException
+		throws PortletException, IOException
 	{
 		processRequest(request, response, CUSTOM_REQUEST, PARAM_CUSTOM_PAGE);
 	}
 
+	@Override
 	public void processAction(ActionRequest request, ActionResponse response)
-			throws PortletException, IOException
+		throws PortletException, IOException
 	{
 		processRequest(request, response, ACTION_REQUEST, PARAM_ACTION_PAGE);
 	}
 
+	/**
+	 * Consumes and processes all portlet requests. All the doX methods delegate to this method,
+	 * including processAction and serveResource.
+	 * 
+	 * @param request
+	 * @param response
+	 * @param requestType
+	 * @param pageType
+	 * @throws PortletException
+	 * @throws IOException
+	 */
 	protected void processRequest(PortletRequest request, PortletResponse response,
-			String requestType, String pageType) throws PortletException, IOException
+		String requestType, String pageType) throws PortletException, IOException
 	{
 		String wicketURL = null;
 		String wicketFilterPath = null;
 		String wicketFilterQuery = null;
 
 		request.setAttribute(WICKET_URL_PORTLET_PARAMETER_ATTR,
-				getWicketUrlPortletParameter(request));
+			getWicketUrlPortletParameter(request));
 
 		wicketURL = getWicketURL(request, pageType, getDefaultPage(pageType));
 		wicketFilterPath = getWicketConfigParameter(request, WICKET_FILTER_PATH,
-				this.wicketFilterPath);
+			this.wicketFilterPath);
 		wicketFilterQuery = getWicketConfigParameter(request, WICKET_FILTER_QUERY,
-				this.wicketFilterQuery);
+			this.wicketFilterQuery);
 
 		boolean actionRequest = ACTION_REQUEST.equals(requestType);
 
@@ -499,7 +662,7 @@
 				{
 					rd.include(req, res);
 					processActionResponseState(wicketURL, wicketFilterPath, wicketFilterQuery,
-							(ActionRequest)request, (ActionResponse)response, responseState);
+						(ActionRequest)request, (ActionResponse)response, responseState);
 				}
 				catch (ServletException e)
 				{
@@ -521,30 +684,28 @@
 					if (redirectLocation != null)
 					{
 						redirectLocation = fixWicketUrl(redirectLocation, wicketFilterPath,
-								wicketFilterQuery);
+							wicketFilterQuery);
 						boolean validWicketUrl = redirectLocation.startsWith(wicketFilterPath);
 						if (portletResourceURL != null)
 						{
 							if (validWicketUrl)
 							{
 								HashMap parameters = new HashMap(2);
-								parameters
-										.put(
-												(String)request
-														.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR) +
-														request.getPortletMode().toString(),
-												new String[] { redirectLocation });
+								parameters.put(
+									(String)request.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR) +
+										request.getPortletMode().toString(),
+									new String[] { redirectLocation });
 								parameters.put(PORTLET_RESOURCE_URL_PARAMETER,
-										new String[] { "true" });
+									new String[] { "true" });
 								redirectLocation = resourceURLFactory.createResourceURL(
-										getPortletConfig(), (RenderRequest)request,
-										(RenderResponse)response, parameters);
+									getPortletConfig(), (RenderRequest)request,
+									(RenderResponse)response, parameters);
 							}
 							getHttpServletResponse(this, request, response).sendRedirect(
-									redirectLocation);
+								redirectLocation);
 						}
 						else if (validWicketUrl &&
-								((previousURL == null || previousURL != redirectLocation)))
+							((previousURL == null || previousURL != redirectLocation)))
 						{
 							previousURL = wicketURL;
 							wicketURL = redirectLocation;
@@ -563,18 +724,33 @@
 		}
 	}
 
+	/**
+	 * Handles redirects set from processing the action. Checks the response state after the action
+	 * has been processed by Wicket for the presence of a redirect URL, and if present, portletifies
+	 * the URL. If the URL is a redirect to within the scope of this portlet, leaves it to be
+	 * handled in a subsequent render call, or if not, sends the redirect to the client.
+	 * 
+	 * @param wicketURL
+	 * @param wicketFilterPath
+	 * @param wicketFilterQuery
+	 * @param request
+	 * @param response
+	 * @param responseState
+	 * @throws PortletException
+	 * @throws IOException
+	 */
 	protected void processActionResponseState(String wicketURL, String wicketFilterPath,
-			String wicketFilterQuery, ActionRequest request, ActionResponse response,
-			WicketResponseState responseState) throws PortletException, IOException
+		String wicketFilterQuery, ActionRequest request, ActionResponse response,
+		WicketResponseState responseState) throws PortletException, IOException
 	{
 		if (responseState.getRedirectLocation() != null)
 		{
 			wicketURL = fixWicketUrl(responseState.getRedirectLocation(), wicketFilterPath,
-					wicketFilterQuery);
+				wicketFilterQuery);
 			if (wicketURL.startsWith(wicketFilterPath))
 			{
-				response.setRenderParameter((String)request
-						.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR) +
+				response.setRenderParameter(
+					(String)request.getAttribute(WicketPortlet.WICKET_URL_PORTLET_PARAMETER_ATTR) +
 						request.getPortletMode().toString(), wicketURL);
 			}
 			else

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketResponseState.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketResponseState.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketResponseState.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/portlet/WicketResponseState.java Sun Nov 16 14:04:19 2008
@@ -17,6 +17,8 @@
 package org.apache.wicket.protocol.http.portlet;
 
 /**
+ * Holds the current state of the response and the redirect location for Portlets.
+ * 
  * @author Ate Douma
  */
 public class WicketResponseState

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/CryptedUrlWebRequestCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/CryptedUrlWebRequestCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/CryptedUrlWebRequestCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/CryptedUrlWebRequestCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -27,14 +27,15 @@
 import org.apache.wicket.RequestCycle;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.protocol.http.RequestUtils;
-import org.apache.wicket.protocol.http.WicketURLEncoder;
 import org.apache.wicket.protocol.http.WicketURLDecoder;
+import org.apache.wicket.protocol.http.WicketURLEncoder;
 import org.apache.wicket.request.IRequestCodingStrategy;
 import org.apache.wicket.request.RequestParameters;
 import org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy;
 import org.apache.wicket.util.crypt.ICrypt;
 import org.apache.wicket.util.string.AppendingStringBuffer;
 import org.apache.wicket.util.string.Strings;
+import org.apache.wicket.util.string.UrlUtils;
 import org.apache.wicket.util.value.ValueMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -122,8 +123,7 @@
 	}
 
 	/**
-	 * @see org.apache.wicket.request.IRequestTargetMounter#mount(
-	 *      org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy)
+	 * @see org.apache.wicket.request.IRequestTargetMounter#mount(org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy)
 	 */
 	public void mount(IRequestTargetUrlCodingStrategy urlCodingStrategy)
 	{
@@ -205,7 +205,7 @@
 					// encrypt the query string
 					String encryptedQueryString = urlCrypt.encryptUrlSafe(queryString);
 
-                    encryptedQueryString = WicketURLEncoder.QUERY_INSTANCE.encode(encryptedQueryString);
+					encryptedQueryString = WicketURLEncoder.QUERY_INSTANCE.encode(encryptedQueryString);
 
 					// build the new complete url
 					return new AppendingStringBuffer(urlPrefix).append("?x=").append(
@@ -262,7 +262,7 @@
 			}
 			catch (Exception ex)
 			{
-				return onError(ex);
+				return onError(ex, url);
 			}
 		}
 		return null;
@@ -272,14 +272,20 @@
 	 * @param ex
 	 * 
 	 * @return decoded URL
+	 * @deprecated Use {@link #onError(Exception, String)}
 	 */
 	protected String onError(final Exception ex)
 	{
-		log.error("Invalid URL", ex);
-
 		throw new HackAttackException("Invalid URL");
 	}
 
+	protected String onError(final Exception ex, String url)
+	{
+		log.error("Invalid URL: " + url, ex);
+
+		return onError(ex);
+	}
+
 	/**
 	 * Try to shorten the querystring without loosing information. Note: WebRequestWithCryptedUrl
 	 * must implement exactly the opposite logic.
@@ -386,8 +392,12 @@
 
 			// Remove the 'x' parameter which contains ALL the encoded params
 			parameterMap.remove("x");
-			String decodedParamReplacement = encodedParamReplacement;
-            decodedParamReplacement = WicketURLDecoder.QUERY_INSTANCE.decode(encodedParamReplacement);
+			// first replace all &amp; with & else the they wont be encoded because there where
+			// encrypted.
+			String decodedParamReplacement = Strings.replaceAll(encodedParamReplacement, "&amp;",
+				"&").toString();
+
+			decodedParamReplacement = WicketURLDecoder.QUERY_INSTANCE.decode(decodedParamReplacement);
 
 			// Add ALL of the params from the decoded 'x' param
 			ValueMap params = new ValueMap();
@@ -573,4 +583,10 @@
 			return getMessage();
 		}
 	}
+
+	/** {@inheritDoc} */
+	public String rewriteStaticRelativeUrl(String string)
+	{
+		return UrlUtils.rewriteToContextRelative(string, RequestCycle.get().getRequest());
+	}
 }

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/WebRequestCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/WebRequestCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/WebRequestCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/WebRequestCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -22,7 +22,6 @@
 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;
@@ -32,6 +31,7 @@
 import org.apache.wicket.IRequestTarget;
 import org.apache.wicket.IResourceListener;
 import org.apache.wicket.Page;
+import org.apache.wicket.PageId;
 import org.apache.wicket.PageMap;
 import org.apache.wicket.PageParameters;
 import org.apache.wicket.Request;
@@ -44,7 +44,6 @@
 import org.apache.wicket.behavior.IActivePageBehaviorListener;
 import org.apache.wicket.behavior.IBehavior;
 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;
@@ -56,11 +55,14 @@
 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.PageIdRequestTarget;
 import org.apache.wicket.request.target.component.listener.IListenerInterfaceRequestTarget;
 import org.apache.wicket.request.target.resource.ISharedResourceRequestTarget;
+import org.apache.wicket.util.lang.Objects;
 import org.apache.wicket.util.string.AppendingStringBuffer;
 import org.apache.wicket.util.string.PrependingStringBuffer;
 import org.apache.wicket.util.string.Strings;
+import org.apache.wicket.util.string.UrlUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -155,7 +157,8 @@
 	 * <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 />
+	 * 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 />
@@ -206,11 +209,11 @@
 			parameters.setOnlyProcessIfPathActive(true);
 		}
 
-		Map map = request.getParameterMap();
-		Iterator iterator = map.keySet().iterator();
+		Map<String, String[]> map = request.getParameterMap();
+		Iterator<String> iterator = map.keySet().iterator();
 		while (iterator.hasNext())
 		{
-			String key = (String)iterator.next();
+			String key = iterator.next();
 			if (key.startsWith(NAME_SPACE))
 			{
 				iterator.remove();
@@ -225,9 +228,9 @@
 	 * 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.
+	 * {@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)
@@ -257,6 +260,10 @@
 				(ISharedResourceRequestTarget)requestTarget) : url);
 			sharedResourceURL = true;
 		}
+		else if (requestTarget instanceof PageIdRequestTarget)
+		{
+			url = encode(requestCycle, (PageIdRequestTarget)requestTarget);
+		}
 		else if (requestTarget instanceof IListenerInterfaceRequestTarget)
 		{
 			if (url == null)
@@ -409,8 +416,7 @@
 	}
 
 	/**
-	 * @see org.apache.wicket.request.IRequestTargetMounter#mount(
-	 *      org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy)
+	 * @see org.apache.wicket.request.IRequestTargetMounter#mount(org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy)
 	 */
 	public final void mount(IRequestTargetUrlCodingStrategy encoder)
 	{
@@ -771,18 +777,10 @@
 		final PageParameters parameters = requestTarget.getPageParameters();
 		if (parameters != null)
 		{
-			final Iterator iterator;
-			if (UnitTestSettings.getSortUrlParameters())
-			{
-				iterator = new TreeSet(parameters.keySet()).iterator();
-			}
-			else
-			{
-				iterator = parameters.keySet().iterator();
-			}
+			final Iterator<String> iterator = parameters.keySet().iterator();
 			while (iterator.hasNext())
 			{
-				final String key = (String)iterator.next();
+				final String key = iterator.next();
 				final String values[] = parameters.getStringArray(key);
 				if (values != null)
 				{
@@ -827,10 +825,10 @@
 			if (map != null && map.size() > 0)
 			{
 				buffer.append('?');
-				Iterator it = map.entrySet().iterator();
+				Iterator<Entry<String, String[]>> it = map.entrySet().iterator();
 				while (it.hasNext())
 				{
-					Map.Entry entry = (Entry)it.next();
+					Map.Entry<String, String[]> entry = it.next();
 					buffer.append(entry.getKey());
 					buffer.append('=');
 					buffer.append(entry.getValue());
@@ -844,6 +842,50 @@
 		}
 	}
 
+
+	/**
+	 * Encode a pageid request target.
+	 * 
+	 * @param requestCycle
+	 *            the current request cycle
+	 * @param requestTarget
+	 *            the target to encode
+	 * @return the encoded url
+	 */
+	protected CharSequence encode(RequestCycle requestCycle, PageIdRequestTarget requestTarget)
+	{
+		final PageId id = requestTarget.getPageId();
+
+		// Start string buffer for url
+		final AppendingStringBuffer url = new AppendingStringBuffer(64);
+		url.append('?');
+		url.append(INTERFACE_PARAMETER_NAME);
+		url.append('=');
+
+		// add pagemap
+		if (!Objects.equal(PageMap.DEFAULT_NAME, id.getPageMapName()))
+		{
+			url.append(id.getPageMapName());
+		}
+		url.append(Component.PATH_SEPARATOR);
+
+		// add page id
+		url.append(id.getPageNumber());
+		url.append(Component.PATH_SEPARATOR);
+
+		// add version
+		url.append(id.getPageVersion());
+		url.append(Component.PATH_SEPARATOR);
+
+		// add listener interface (noop because we default to redirect listener which is default)
+		url.append(Component.PATH_SEPARATOR);
+
+		// behavior id (noop because we dont care aboute behaviors
+		url.append(Component.PATH_SEPARATOR);
+
+		return url;
+	}
+
 	/**
 	 * Encode a listener interface target.
 	 * 
@@ -1151,8 +1193,8 @@
 	 * Makes page map name url safe.
 	 * 
 	 * Since the default page map name in wicket is null and null does not encode well into urls
-	 * this method will substitute null for a known token. If the <code>pageMapName</code> passed
-	 * in is not null it is returned without modification.
+	 * this method will substitute null for a known token. If the <code>pageMapName</code> passed in
+	 * is not null it is returned without modification.
 	 * 
 	 * @param pageMapName
 	 *            page map name
@@ -1218,4 +1260,10 @@
 		}
 	}
 
+	/** {@inheritDoc} */
+	public String rewriteStaticRelativeUrl(String string)
+	{
+		return UrlUtils.rewriteToContextRelative(string, RequestCycle.get().getRequest());
+	}
+
 }

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressingWebCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressingWebCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressingWebCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressingWebCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -60,7 +60,7 @@
 	 * @return the encoded url
 	 */
 	protected CharSequence encode(RequestCycle requestCycle,
-			IListenerInterfaceRequestTarget requestTarget)
+		IListenerInterfaceRequestTarget requestTarget)
 	{
 		final RequestListenerInterface rli = requestTarget.getRequestListenerInterface();
 
@@ -89,7 +89,7 @@
 			url.append(page.getId());
 			url.append(Component.PATH_SEPARATOR);
 			url.append(((WebPage)page).getUrlCompressor().getUIDForComponentAndInterface(component,
-					listenerName));
+				listenerName));
 			listenerName = null;
 		}
 		else
@@ -131,10 +131,10 @@
 		{
 			url.append(params.getUrlDepth());
 		}
-		if (IActivePageBehaviorListener.INTERFACE.getName().equals(listenerName))
+		if (IActivePageBehaviorListener.INTERFACE.getName().equals(rli.getName()))
 		{
 			url.append(url.indexOf("?") > -1 ? "&amp;" : "?").append(
-					IGNORE_IF_NOT_ACTIVE_PARAMETER_NAME).append("=true");
+				IGNORE_IF_NOT_ACTIVE_PARAMETER_NAME).append("=true");
 		}
 		return requestCycle.getOriginalResponse().encodeURL(url);
 	}

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressor.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressor.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressor.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/request/urlcompressing/UrlCompressor.java Sun Nov 16 14:04:19 2008
@@ -24,7 +24,6 @@
 import org.apache.wicket.Component;
 import org.apache.wicket.IClusterable;
 import org.apache.wicket.util.collections.IntHashMap;
-import org.apache.wicket.util.collections.IntHashMap.Entry;
 
 
 /**
@@ -82,7 +81,7 @@
 		}
 	}
 
-	private static class IntKeyWeakReference extends WeakReference
+	private static class IntKeyWeakReference extends WeakReference<Object>
 	{
 		private final int uid;
 
@@ -91,7 +90,7 @@
 		 * @param referent
 		 * @param q
 		 */
-		public IntKeyWeakReference(int uid, Object referent, ReferenceQueue q)
+		public IntKeyWeakReference(int uid, Object referent, ReferenceQueue<Object> q)
 		{
 			super(referent, q);
 			this.uid = uid;
@@ -100,9 +99,14 @@
 
 	private static final long serialVersionUID = 1L;
 
-	private transient ReferenceQueue queue = new ReferenceQueue();
+	private transient ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
 
-	private transient IntHashMap directComponentRefs = new IntHashMap(); // uid->component/interface
+	private transient IntHashMap<ComponentAndInterface> directComponentRefs = new IntHashMap<ComponentAndInterface>(); // uid
+	// -
+	// >
+	// component
+	// /
+	// interface
 
 	private int uid = 1;
 
@@ -120,7 +124,7 @@
 			directComponentRefs.remove(ref.uid);
 		}
 		int uid = Integer.parseInt(uidString);
-		ComponentAndInterface cai = (ComponentAndInterface)directComponentRefs.get(uid);
+		ComponentAndInterface cai = directComponentRefs.get(uid);
 		return cai;
 	}
 
@@ -145,11 +149,12 @@
 	public int getUIDForComponentAndInterface(Component component, String interfaceName)
 	{
 		int uid = 0;
-		Iterator it = directComponentRefs.entrySet().iterator();
+		Iterator<IntHashMap.Entry<ComponentAndInterface>> it = directComponentRefs.entrySet()
+			.iterator();
 		while (it.hasNext())
 		{
-			IntHashMap.Entry entry = (IntHashMap.Entry)it.next();
-			ComponentAndInterface cai = (ComponentAndInterface)entry.getValue();
+			IntHashMap.Entry<ComponentAndInterface> entry = it.next();
+			ComponentAndInterface cai = entry.getValue();
 			if (cai.getInterfaceName().equals(interfaceName) && cai.getComponent() == component)
 			{
 				uid = entry.getKey();
@@ -170,8 +175,8 @@
 		s.defaultReadObject();
 
 		int size = s.readInt();
-		queue = new ReferenceQueue();
-		directComponentRefs = new IntHashMap((int)(size * 1.25));
+		queue = new ReferenceQueue<Object>();
+		directComponentRefs = new IntHashMap<ComponentAndInterface>((int)(size * 1.25));
 
 		while (--size >= 0)
 		{
@@ -197,13 +202,14 @@
 
 		s.writeInt(directComponentRefs.size());
 
-		Iterator it = directComponentRefs.entrySet().iterator();
+		Iterator<IntHashMap.Entry<ComponentAndInterface>> it = directComponentRefs.entrySet()
+			.iterator();
 		while (it.hasNext())
 		{
-			IntHashMap.Entry entry = (Entry)it.next();
+			IntHashMap.Entry<ComponentAndInterface> entry = it.next();
 
 			s.writeInt(entry.getKey());
-			ComponentAndInterface cai = (ComponentAndInterface)entry.getValue();
+			ComponentAndInterface cai = entry.getValue();
 			s.writeObject(cai.getComponent());
 			s.writeUTF(cai.getInterfaceName());
 		}

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java Sun Nov 16 14:04:19 2008
@@ -19,6 +19,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -48,7 +49,7 @@
 public class MultipartServletWebRequest extends ServletWebRequest implements IMultipartWebRequest
 {
 	/** Map of file items. */
-	private final ValueMap files = new ValueMap();
+	private final Map<String, FileItem> files = new HashMap<String, FileItem>();
 
 	/** Map of parameters. */
 	private final ValueMap parameters = new ValueMap();
@@ -74,7 +75,7 @@
 	 *             Thrown if something goes wrong with upload
 	 */
 	public MultipartServletWebRequest(HttpServletRequest request, Bytes maxSize)
-			throws FileUploadException
+		throws FileUploadException
 	{
 		super(request);
 
@@ -108,12 +109,13 @@
 
 		upload.setSizeMax(maxSize.bytes());
 
-		final List items;
+		final List<FileItem> items;
 
 		if (wantUploadProgressUpdates())
 		{
 			ServletRequestContext ctx = new ServletRequestContext(request)
 			{
+				@Override
 				public InputStream getInputStream() throws IOException
 				{
 					return new CountingInputStream(super.getInputStream());
@@ -132,10 +134,10 @@
 		}
 
 		// Loop through items
-		for (Iterator i = items.iterator(); i.hasNext();)
+		for (Iterator<FileItem> i = items.iterator(); i.hasNext();)
 		{
 			// Get next item
-			final FileItem item = (FileItem)i.next();
+			final FileItem item = i.next();
 
 			// If item is a form field
 			if (item.isFormField())
@@ -200,7 +202,7 @@
 	/**
 	 * @return Returns the files.
 	 */
-	public Map getFiles()
+	public Map<String, FileItem> getFiles()
 	{
 		return files;
 	}
@@ -214,12 +216,13 @@
 	 */
 	public FileItem getFile(final String fieldName)
 	{
-		return (FileItem)files.get(fieldName);
+		return files.get(fieldName);
 	}
 
 	/**
 	 * @see org.apache.wicket.protocol.http.WebRequest#getParameter(java.lang.String)
 	 */
+	@Override
 	public String getParameter(final String key)
 	{
 		String[] val = (String[])parameters.get(key);
@@ -229,6 +232,7 @@
 	/**
 	 * @see org.apache.wicket.protocol.http.WebRequest#getParameterMap()
 	 */
+	@Override
 	public Map getParameterMap()
 	{
 		return parameters;
@@ -237,6 +241,7 @@
 	/**
 	 * @see org.apache.wicket.protocol.http.WebRequest#getParameters(java.lang.String)
 	 */
+	@Override
 	public String[] getParameters(final String key)
 	{
 		return (String[])parameters.get(key);
@@ -305,6 +310,7 @@
 		/**
 		 * @see java.io.InputStream#read()
 		 */
+		@Override
 		public int read() throws IOException
 		{
 			int read = in.read();
@@ -316,6 +322,7 @@
 		/**
 		 * @see java.io.InputStream#read(byte[])
 		 */
+		@Override
 		public int read(byte[] b) throws IOException
 		{
 			int read = in.read(b);
@@ -327,6 +334,7 @@
 		/**
 		 * @see java.io.InputStream#read(byte[], int, int)
 		 */
+		@Override
 		public int read(byte[] b, int off, int len) throws IOException
 		{
 			int read = in.read(b, off, len);

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/ServletWebRequest.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/ServletWebRequest.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/ServletWebRequest.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/protocol/http/servlet/ServletWebRequest.java Sun Nov 16 14:04:19 2008
@@ -413,8 +413,6 @@
 	@Override
 	public boolean isAjax()
 	{
-		boolean ajax = false;
-
 		if (Strings.isTrue(httpServletRequest.getParameter("wicket:ajax")))
 		{
 			return true;
@@ -425,7 +423,7 @@
 		{
 			try
 			{
-				ajax = Strings.isTrue(ajaxHeader);
+				return Strings.isTrue(ajaxHeader);
 			}
 			catch (StringValueConversionException e)
 			{
@@ -433,8 +431,7 @@
 				log.debug("Couldn't convert the Wicket-Ajax header: " + ajaxHeader);
 			}
 		}
-
-		return ajax;
+		return false;
 	}
 
 	/**

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/AbstractRequestCycleProcessor.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/AbstractRequestCycleProcessor.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/AbstractRequestCycleProcessor.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/AbstractRequestCycleProcessor.java Sun Nov 16 14:04:19 2008
@@ -127,14 +127,14 @@
 			// render?
 			// else we need to make a page (see below) or set it hard to a
 			// redirect.
-			Class accessDeniedPageClass = application.getApplicationSettings()
+			Class<? extends Page> accessDeniedPageClass = application.getApplicationSettings()
 				.getAccessDeniedPage();
 
 			throw new RestartResponseAtInterceptPageException(accessDeniedPageClass);
 		}
 		else if (e instanceof PageExpiredException)
 		{
-			Class pageExpiredErrorPageClass = application.getApplicationSettings()
+			Class<? extends Page> pageExpiredErrorPageClass = application.getApplicationSettings()
 				.getPageExpiredErrorPage();
 			boolean mounted = isPageMounted(pageExpiredErrorPageClass);
 			RequestCycle.get().setRedirect(mounted);
@@ -148,9 +148,10 @@
 			requestCycle.setRedirect(false);
 
 			// figure out which error page to show
-			Class internalErrorPageClass = application.getApplicationSettings()
+			Class<? extends Page> internalErrorPageClass = application.getApplicationSettings()
 				.getInternalErrorPage();
-			Class responseClass = responsePage != null ? responsePage.getClass() : null;
+			Class<? extends Page> responseClass = responsePage != null ? responsePage.getClass()
+				: null;
 
 			if (responseClass != internalErrorPageClass &&
 				settings.getUnexpectedExceptionDisplay() == IExceptionSettings.SHOW_INTERNAL_ERROR_PAGE)
@@ -183,7 +184,7 @@
 	 *            the <code>Class</code> of the <code>Page</code> to be checked
 	 * @return true if the given <code>pageClass</code> is mounted, false otherwise
 	 */
-	private boolean isPageMounted(Class /* <? extends Page> */pageClass)
+	private boolean isPageMounted(Class<? extends Page> pageClass)
 	{
 		RequestCycle cycle = RequestCycle.get();
 		CharSequence path = getRequestCodingStrategy().pathForTarget(
@@ -226,15 +227,17 @@
 	 *            the request parameters object
 	 * @return the bookmarkable page as a request target
 	 */
+	@SuppressWarnings("unchecked")
 	protected IRequestTarget resolveBookmarkablePage(final RequestCycle requestCycle,
 		final RequestParameters requestParameters)
 	{
 		String bookmarkablePageClass = requestParameters.getBookmarkablePageClass();
 		Session session = requestCycle.getSession();
-		Class pageClass;
+		Class<? extends Page> pageClass;
 		try
 		{
-			pageClass = session.getClassResolver().resolveClass(bookmarkablePageClass);
+			pageClass = (Class<? extends Page>)session.getClassResolver().resolveClass(
+				bookmarkablePageClass);
 		}
 		catch (ClassNotFoundException e)
 		{

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/IRequestCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/IRequestCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/IRequestCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/IRequestCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -19,6 +19,7 @@
 import org.apache.wicket.IRequestTarget;
 import org.apache.wicket.Request;
 import org.apache.wicket.RequestCycle;
+import org.apache.wicket.util.string.UrlUtils;
 
 /**
  * Implementations of this interface are responsible for digesting the incoming request and creating
@@ -56,4 +57,22 @@
 	 * @return the url to the provided target
 	 */
 	CharSequence encode(RequestCycle requestCycle, IRequestTarget requestTarget);
+
+
+	/**
+	 * Rewrites relative paths found in static markup attributes (<code>src,href,background</code>)
+	 * of wicket pages. Since we do not know the url depth at which the page will be rendered the
+	 * implementations should usually simply append a prefix, eg <code>../../</code>, to make the
+	 * path context-relative. If the url is not relative it is returned intact.
+	 * 
+	 * Implementations can be as simple as delegating to
+	 * {@link UrlUtils#rewriteToContextRelative(String, Request)}
+	 * 
+	 * @see Request#getRelativePathPrefixToContextRoot()
+	 * @see UrlUtils#rewriteToContextRelative(String, Request)
+	 * 
+	 * @param string
+	 * @return rewritten path
+	 */
+	String rewriteStaticRelativeUrl(String string);
 }

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/RedirectRequestTarget.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/RedirectRequestTarget.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/RedirectRequestTarget.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/RedirectRequestTarget.java Sun Nov 16 14:04:19 2008
@@ -71,6 +71,8 @@
 		response.reset();
 		if (redirectUrl.startsWith("/"))
 		{
+			// context-absolute url
+
 			RequestContext rc = RequestContext.get();
 			String continueTo = null;
 			if (rc.isPortletRequest() && ((PortletRequestContext)rc).isEmbedded())
@@ -79,18 +81,25 @@
 			}
 			else
 			{
-				response.redirect(RequestCycle.get()
-					.getRequest()
-					.getRelativePathPrefixToContextRoot() +
-					redirectUrl.substring(1));
+				String location = RequestCycle.get()
+					.getProcessor()
+					.getRequestCodingStrategy()
+					.rewriteStaticRelativeUrl(redirectUrl.substring(1));
+				if (location.startsWith("./"))
+				{
+					location = location.substring(2);
+				}
+				response.redirect(location);
 			}
 		}
-		else if (redirectUrl.startsWith("http://") || redirectUrl.startsWith("https://"))
+		else if (redirectUrl.contains("://"))
 		{
+			// absolute url
 			response.redirect(redirectUrl);
 		}
 		else
 		{
+			// relative url
 			response.redirect(RequestCycle.get()
 				.getRequest()
 				.getRelativePathPrefixToWicketHandler() +

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/StringRequestTarget.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/StringRequestTarget.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/StringRequestTarget.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/StringRequestTarget.java Sun Nov 16 14:04:19 2008
@@ -16,14 +16,14 @@
  */
 package org.apache.wicket.request.target.basic;
 
-import java.io.OutputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
 
+import org.apache.wicket.Application;
 import org.apache.wicket.IRequestTarget;
 import org.apache.wicket.RequestCycle;
 import org.apache.wicket.Response;
 import org.apache.wicket.WicketRuntimeException;
-import org.apache.wicket.util.io.Streams;
-import org.apache.wicket.util.resource.StringBufferResourceStream;
 import org.apache.wicket.util.string.Strings;
 
 
@@ -40,15 +40,20 @@
 	/** content type for the string */
 	private final String contentType;
 
+	/** charset of the string */
+	private final String encoding;
+
+
 	/**
-	 * Constructor
+	 * Creates a string request target with content type <code>text/plain</code> and default
+	 * charset (usually UTF-8)
 	 * 
 	 * @param string
 	 *            the string for the response
 	 */
 	public StringRequestTarget(String string)
 	{
-		this("text/plain", string);
+		this("text/plain", getDefaultEncoding(), string);
 	}
 
 	/**
@@ -57,10 +62,12 @@
 	 * @param contentType
 	 *            content type of the data the string represents eg
 	 *            <code>text/html; charset=utf-8</code>
+	 * @param encoding
+	 *            charset to use
 	 * @param string
 	 *            string for the response
 	 */
-	public StringRequestTarget(String contentType, String string)
+	public StringRequestTarget(String contentType, String encoding, String string)
 	{
 		if (string == null)
 		{
@@ -70,8 +77,41 @@
 		{
 			throw new IllegalArgumentException("Argument contentType must not be null or empty");
 		}
+		if (encoding == null)
+		{
+			throw new IllegalArgumentException("Argument charset must not be null");
+		}
 		this.contentType = contentType;
 		this.string = string;
+		this.encoding = encoding;
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param contentType
+	 *            content type of the data the string represents eg
+	 *            <code>text/html; charset=utf-8</code>
+	 * @param charset
+	 *            charset to use
+	 * @param string
+	 *            string for the response
+	 * @deprecated use {@link #StringRequestTarget(String, String, String)} instead
+	 */
+	@Deprecated
+	public StringRequestTarget(String contentType, Charset charset, String string)
+	{
+		this(contentType, charset.aliases().iterator().next(), string);
+	}
+
+	/**
+	 * Retrieves default charset configured in application
+	 * 
+	 * @return charset
+	 */
+	private static String getDefaultEncoding()
+	{
+		return Application.get().getRequestCycleSettings().getResponseRequestEncoding();
 	}
 
 
@@ -84,27 +124,16 @@
 	{
 		// Get servlet response to use when responding with resource
 		final Response response = requestCycle.getResponse();
-		response.setContentType(contentType);
-		final StringBufferResourceStream stream = new StringBufferResourceStream(contentType);
-		stream.append(string);
+		response.setContentType(contentType + ";charset=" + encoding);
 
-		// Respond with resource
+		// send string to client
 		try
 		{
-			final OutputStream out = response.getOutputStream();
-			try
-			{
-				Streams.copy(stream.getInputStream(), out);
-			}
-			finally
-			{
-				stream.close();
-				out.flush();
-			}
+			response.getOutputStream().write(string.getBytes(encoding));
 		}
-		catch (Exception e)
+		catch (IOException e)
 		{
-			throw new WicketRuntimeException("Unable to render resource stream " + stream, e);
+			throw new WicketRuntimeException("Unable to render string: " + e.getMessage(), e);
 		}
 	}
 
@@ -128,6 +157,7 @@
 	/**
 	 * @see java.lang.Object#equals(java.lang.Object)
 	 */
+	@Override
 	public boolean equals(Object obj)
 	{
 		if (obj instanceof StringRequestTarget)
@@ -141,6 +171,7 @@
 	/**
 	 * @see java.lang.Object#hashCode()
 	 */
+	@Override
 	public int hashCode()
 	{
 		int result = "StringRequestTarget".hashCode();
@@ -151,6 +182,7 @@
 	/**
 	 * @see java.lang.Object#toString()
 	 */
+	@Override
 	public String toString()
 	{
 		return "[StringRequestTarget@" + hashCode() + " " + string + "]";

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/URIRequestTargetUrlCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/URIRequestTargetUrlCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/URIRequestTargetUrlCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/basic/URIRequestTargetUrlCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -18,14 +18,12 @@
 
 import java.util.Iterator;
 import java.util.Map;
-import java.util.TreeMap;
 import java.util.Map.Entry;
 
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.wicket.IRequestTarget;
 import org.apache.wicket.PageParameters;
-import org.apache.wicket.protocol.http.UnitTestSettings;
 import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy;
 import org.apache.wicket.request.RequestParameters;
 import org.apache.wicket.request.target.coding.AbstractRequestTargetUrlCodingStrategy;
@@ -66,9 +64,9 @@
 	public PageParameters decodeParameters(RequestParameters requestParameters)
 	{
 		final String parametersFragment = requestParameters.getPath().substring(
-				getMountPath().length());
-		return new PageParameters(decodeParameters(parametersFragment, requestParameters
-				.getParameters()));
+			getMountPath().length());
+		return new PageParameters(decodeParameters(parametersFragment,
+			requestParameters.getParameters()));
 	}
 
 	/**
@@ -92,7 +90,7 @@
 		if (!(requestTarget instanceof IBookmarkablePageRequestTarget))
 		{
 			throw new IllegalArgumentException("This encoder can only be used with " +
-					"instances of " + IBookmarkablePageRequestTarget.class.getName());
+				"instances of " + IBookmarkablePageRequestTarget.class.getName());
 		}
 		final AppendingStringBuffer url = new AppendingStringBuffer(40);
 		url.append(getMountPath());
@@ -106,8 +104,8 @@
 			{
 				pageParameters = new PageParameters();
 			}
-			pageParameters.put(WebRequestCodingStrategy.PAGEMAP, WebRequestCodingStrategy
-					.encodePageMapName(pagemap));
+			pageParameters.put(WebRequestCodingStrategy.PAGEMAP,
+				WebRequestCodingStrategy.encodePageMapName(pagemap));
 		}
 		appendParameters(url, pageParameters);
 		return url;
@@ -133,6 +131,7 @@
 	 * @param parameters
 	 *            parameter names mapped to parameter values
 	 */
+	@Override
 	protected void appendParameters(AppendingStringBuffer url, Map parameters)
 	{
 
@@ -148,15 +147,7 @@
 		// Copied from QueryStringUrlCodingStrategy
 		if (parameters != null && parameters.size() > 0)
 		{
-			final Iterator entries;
-			if (UnitTestSettings.getSortUrlParameters())
-			{
-				entries = new TreeMap(parameters).entrySet().iterator();
-			}
-			else
-			{
-				entries = parameters.entrySet().iterator();
-			}
+			final Iterator entries = parameters.entrySet().iterator();
 			WebRequestEncoder encoder = new WebRequestEncoder(url);
 			while (entries.hasNext())
 			{
@@ -184,6 +175,7 @@
 	 *            query string parameters
 	 * @return Parameters created from the url fragment and query string
 	 */
+	@Override
 	protected ValueMap decodeParameters(String urlFragment, Map urlParameters)
 	{
 		// Hack off any leading slash

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/AbstractRequestTargetUrlCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/AbstractRequestTargetUrlCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/AbstractRequestTargetUrlCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/AbstractRequestTargetUrlCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -19,12 +19,11 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.TreeMap;
 import java.util.Map.Entry;
 
-import org.apache.wicket.protocol.http.UnitTestSettings;
-import org.apache.wicket.protocol.http.WicketURLEncoder;
 import org.apache.wicket.protocol.http.WicketURLDecoder;
+import org.apache.wicket.protocol.http.WicketURLEncoder;
+import org.apache.wicket.protocol.http.servlet.AbortWithWebErrorCodeException;
 import org.apache.wicket.util.string.AppendingStringBuffer;
 import org.apache.wicket.util.string.Strings;
 import org.apache.wicket.util.value.ValueMap;
@@ -39,13 +38,12 @@
  * @author Igor Vaynberg (ivaynberg)
  */
 public abstract class AbstractRequestTargetUrlCodingStrategy
-		implements
-			IRequestTargetUrlCodingStrategy,
-			IMountableRequestTargetUrlCodingStrategy
+	implements
+		IRequestTargetUrlCodingStrategy,
+		IMountableRequestTargetUrlCodingStrategy
 {
 	/** log. */
-	private static final Logger log = LoggerFactory
-			.getLogger(AbstractRequestTargetUrlCodingStrategy.class);
+	private static final Logger log = LoggerFactory.getLogger(AbstractRequestTargetUrlCodingStrategy.class);
 
 	/** mounted path. */
 	private final String mountPath;
@@ -90,15 +88,7 @@
 	{
 		if (parameters != null && parameters.size() > 0)
 		{
-			final Iterator entries;
-			if (UnitTestSettings.getSortUrlParameters())
-			{
-				entries = new TreeMap(parameters).entrySet().iterator();
-			}
-			else
-			{
-				entries = parameters.entrySet().iterator();
-			}
+			final Iterator entries = parameters.entrySet().iterator();
 			while (entries.hasNext())
 			{
 				Map.Entry entry = (Entry)entries.next();
@@ -168,9 +158,9 @@
 		// If we don't have an even number of pairs
 		if (pairs.length % 2 != 0)
 		{
-			// give up
-			throw new IllegalStateException("URL fragment has unmatched key/value " + "pair: " +
-					urlFragment);
+			log.warn("URL fragment has unmatched key/value pairs, responding with 404. Fragment: " +
+				urlFragment);
+			throw new AbortWithWebErrorCodeException(404);
 		}
 
 		// Loop through pairs
@@ -192,76 +182,78 @@
 		return parameters;
 	}
 
-    /**
-     * Url encodes a string that is mean for a URL path (e.g., between slashes)
-     *
-     * @param string
-     *            string to be encoded
-     * @return encoded string
-     */
-    protected String urlEncodePathComponent(String string)
-    {
-        return WicketURLEncoder.PATH_INSTANCE.encode(string);
-    }
+	/**
+	 * Url encodes a string that is mean for a URL path (e.g., between slashes)
+	 * 
+	 * @param string
+	 *            string to be encoded
+	 * @return encoded string
+	 */
+	protected String urlEncodePathComponent(String string)
+	{
+		return WicketURLEncoder.PATH_INSTANCE.encode(string);
+	}
 
-    /**
+	/**
 	 * Returns a decoded value of the given value (taken from a URL path section)
-	 *
+	 * 
 	 * @param value
 	 * @return Decodes the value
 	 */
 	protected String urlDecodePathComponent(String value)
 	{
-        return WicketURLDecoder.PATH_INSTANCE.decode(value);
+		return WicketURLDecoder.PATH_INSTANCE.decode(value);
 	}
 
-    /**
+	/**
 	 * Url encodes a string mean for a URL query string
-	 *
+	 * 
 	 * @param string
 	 *            string to be encoded
 	 * @return encoded string
 	 */
 	protected String urlEncodeQueryComponent(String string)
 	{
-        return WicketURLEncoder.QUERY_INSTANCE.encode(string);
+		return WicketURLEncoder.QUERY_INSTANCE.encode(string);
 	}
 
-    /**
-     * Returns a decoded value of the given value (taken from a URL query string)
-     *
-     * @param value
-     * @return Decodes the value
-     */
-    protected String urlDecodeQueryComponent(String value)
-    {
-        return WicketURLDecoder.QUERY_INSTANCE.decode(value);
-    }
+	/**
+	 * Returns a decoded value of the given value (taken from a URL query string)
+	 * 
+	 * @param value
+	 * @return Decodes the value
+	 */
+	protected String urlDecodeQueryComponent(String value)
+	{
+		return WicketURLDecoder.QUERY_INSTANCE.decode(value);
+	}
 
-    /**
-	 * @deprecated  Use urlEncodePathComponent or urlEncodeQueryComponent instead
+	/**
+	 * @deprecated Use urlEncodePathComponent or urlEncodeQueryComponent instead
 	 */
+	@Deprecated
 	protected String urlDecode(String value)
 	{
-        return urlDecodePathComponent(value);
+		return urlDecodePathComponent(value);
 	}
 
 	/**
-	 * @deprecated  Use urlEncodePathComponent or urlEncodeQueryComponent instead
+	 * @deprecated Use urlEncodePathComponent or urlEncodeQueryComponent instead
 	 */
+	@Deprecated
 	protected String urlEncode(String string)
 	{
-        return urlEncodePathComponent(string);
+		return urlEncodePathComponent(string);
 	}
 
-    /**
-     * Does given path match this mount? We match /mount/point or /mount/point/with/extra/path, but not
-	 * /mount/pointXXX.
-     *
-     * @param path
-     * @return true if matches, false otherwise
-     */
-    public boolean matches(String path)
+	/**
+	 * Does given path match this mount? We match /mount/point or /mount/point/with/extra/path, but
+	 * not /mount/pointXXX.
+	 * 
+	 * @param path
+	 * @return true if matches, false otherwise
+	 */
+	public boolean matches(String path)
 	{
 		if (path.startsWith(mountPath))
 		{

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/HybridUrlCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -75,6 +75,12 @@
 		boolean redirectOnBookmarkableRequest)
 	{
 		super(mountPath);
+		
+		if (mountPath.endsWith("/"))
+		{
+			throw new IllegalArgumentException("mountPath can not end with a '/': " + mountPath);
+		}
+		
 		pageClassRef = new WeakReference(pageClass);
 		this.redirectOnBookmarkableRequest = redirectOnBookmarkableRequest;
 	}

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/IndexedParamUrlCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/IndexedParamUrlCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/IndexedParamUrlCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/IndexedParamUrlCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -64,17 +64,28 @@
 	 *            name of pagemap
 	 */
 	public IndexedParamUrlCodingStrategy(String mountPath, Class bookmarkablePageClass,
-			String pageMapName)
+		String pageMapName)
 	{
 		super(mountPath, bookmarkablePageClass, pageMapName);
 	}
 
+	@Override
 	protected void appendParameters(AppendingStringBuffer url, Map parameters)
 	{
 		int i = 0;
 		while (parameters.containsKey(String.valueOf(i)))
 		{
-			String value = (String)parameters.get(String.valueOf(i));
+			String value = null;
+			Object parameter = parameters.get(String.valueOf(i));
+			if (parameter instanceof String[] && ((String[])parameter).length > 0)
+			{
+				value = ((String[])parameter)[0];
+			}
+			else
+			{
+				value = parameter.toString();
+			}
+
 			if (!url.endsWith("/"))
 			{
 				url.append("/");
@@ -92,8 +103,8 @@
 			{
 				url.append("/");
 			}
-			url.append(WebRequestCodingStrategy.PAGEMAP).append("/").append(urlEncodePathComponent(pageMap))
-					.append("/");
+			url.append(WebRequestCodingStrategy.PAGEMAP).append("/").append(
+				urlEncodePathComponent(pageMap)).append("/");
 		}
 
 		String intface = (String)parameters.get(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME);
@@ -105,16 +116,17 @@
 				url.append("/");
 			}
 			url.append(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME).append("/").append(
-					urlEncodePathComponent(intface)).append("/");
+				urlEncodePathComponent(intface)).append("/");
 		}
 		if (i != parameters.size())
 		{
 			throw new WicketRuntimeException(
-					"Not all parameters were encoded. Make sure all parameter names are integers in consecutive order starting with zero. Current parameter names are: " +
-							parameters.keySet().toString());
+				"Not all parameters were encoded. Make sure all parameter names are integers in consecutive order starting with zero. Current parameter names are: " +
+					parameters.keySet().toString());
 		}
 	}
 
+	@Override
 	protected ValueMap decodeParameters(String urlFragment, Map urlParameters)
 	{
 		PageParameters params = new PageParameters();
@@ -139,14 +151,15 @@
 				if (WebRequestCodingStrategy.PAGEMAP.equals(parts[i]))
 				{
 					i++;
-					params.put(WebRequestCodingStrategy.PAGEMAP, WebRequestCodingStrategy
-							.decodePageMapName(urlDecodePathComponent(parts[i])));
+					params.put(
+						WebRequestCodingStrategy.PAGEMAP,
+						WebRequestCodingStrategy.decodePageMapName(urlDecodePathComponent(parts[i])));
 				}
 				else if (WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME.equals(parts[i]))
 				{
 					i++;
 					params.put(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME,
-							urlDecodePathComponent(parts[i]));
+						urlDecodePathComponent(parts[i]));
 				}
 				else
 				{

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/MixedParamUrlCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/MixedParamUrlCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/MixedParamUrlCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/MixedParamUrlCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -20,46 +20,44 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeSet;
 
 import org.apache.wicket.PageMap;
 import org.apache.wicket.PageParameters;
-import org.apache.wicket.protocol.http.UnitTestSettings;
 import org.apache.wicket.util.string.AppendingStringBuffer;
 import org.apache.wicket.util.value.ValueMap;
 
 
 /**
- *
+ * 
  * Url coding strategy for bookmarkable pages that encodes a set of given parameters
- *
+ * 
  * in the url's path path and the rest in the querystring.
- *
+ * 
  * <p>
  * Strategy looks for path-parameters whose name is read from an array of
- *
+ * 
  * names e.g. ["param0", "param1"]. Found parameters will be appended to the url in
- *
+ * 
  * the form <code>/mount-path/paramvalue0/paramvalue1</code>.
  * </p>
- *
+ * 
  * <p>
  * All other parameters are added as parameter in the form:
- *
+ * 
  * <code>/mount-path/paramvalue0?otherparam0=otherparamvalue0&otherparam1=otherparamvalue1</code>.
  * </p>
- *
+ * 
  * <p>
  * Decode is symmetric except for when a path parameter that is not at the end has no value during
  * encode.
- *
+ * 
  * For example, the names for the path parameters are: "a", "b" and "c". When "b" is
- *
+ * 
  * not specified upon encoding, but "c" is, upon a decode "b" will get the empty string
- *
+ * 
  * as value. When both "b" and "c" are missing on encode, the will not get a value during decode.
  * </p>
- *
+ * 
  * @author erik.van.oosten
  */
 public class MixedParamUrlCodingStrategy extends BookmarkablePageRequestTargetUrlCodingStrategy
@@ -68,7 +66,7 @@
 
 	/**
 	 * Construct.
-	 *
+	 * 
 	 * @param mountPath
 	 *            mount path
 	 * @param bookmarkablePageClass
@@ -87,7 +85,7 @@
 
 	/**
 	 * Construct.
-	 *
+	 * 
 	 * @param mountPath
 	 *            mount path (not empty)
 	 * @param bookmarkablePageClass
@@ -139,22 +137,15 @@
 		if (!parameterNamesToAdd.isEmpty())
 		{
 			boolean first = true;
-			final Iterator iterator;
-			if (UnitTestSettings.getSortUrlParameters())
-			{
-				iterator = new TreeSet(parameterNamesToAdd).iterator();
-			}
-			else
-			{
-				iterator = parameterNamesToAdd.iterator();
-			}
+			final Iterator iterator = parameterNamesToAdd.iterator();
 			while (iterator.hasNext())
 			{
 				url.append(first ? '?' : '&');
 				String parameterName = (String)iterator.next();
 				final Object param = parameters.get(parameterName);
 				String value = param instanceof String[] ? ((String[])param)[0] : (String)param;
-				url.append(urlEncodeQueryComponent(parameterName)).append("=").append(urlEncodeQueryComponent(value));
+				url.append(urlEncodeQueryComponent(parameterName)).append("=").append(
+					urlEncodeQueryComponent(value));
 				first = false;
 			}
 		}

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/QueryStringUrlCodingStrategy.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/QueryStringUrlCodingStrategy.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/QueryStringUrlCodingStrategy.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/coding/QueryStringUrlCodingStrategy.java Sun Nov 16 14:04:19 2008
@@ -18,13 +18,11 @@
 
 import java.util.Iterator;
 import java.util.Map;
-import java.util.TreeMap;
 import java.util.Map.Entry;
 
 import org.apache.wicket.IRequestTarget;
 import org.apache.wicket.PageMap;
 import org.apache.wicket.PageParameters;
-import org.apache.wicket.protocol.http.UnitTestSettings;
 import org.apache.wicket.request.RequestParameters;
 import org.apache.wicket.request.target.component.BookmarkableListenerInterfaceRequestTarget;
 import org.apache.wicket.request.target.component.BookmarkablePageRequestTarget;
@@ -36,15 +34,15 @@
  * in a URL query string rather than integrated into a URL hierarchical path.
  * <p>
  * For example, whereas
- * {@link org.apache.wicket.request.target.coding.BookmarkablePageRequestTargetUrlCodingStrategy BookmarkablePageRequestTargetUrlCodingStrategy}
- * might encode a request target as
+ * {@link org.apache.wicket.request.target.coding.BookmarkablePageRequestTargetUrlCodingStrategy
+ * BookmarkablePageRequestTargetUrlCodingStrategy} might encode a request target as
  * "mywebapp/myservlet/admin/productmanagement/action/edit/product/4995",
  * <code>QueryStringRequestTargetUrlCodingStrategy</code> would encode the same target as
  * "mywebapp/myservlet/admin/productmanagement?action=edit&amp;product=4995".
  * <p>
  * URLs encoded in this way can be bookmarked just as easily as those produced by
- * <code>BookmarkablePageRequestTargetUrlCodingStrategy</code>. For example, Google searches
- * produce bookmarkable links with query strings.
+ * <code>BookmarkablePageRequestTargetUrlCodingStrategy</code>. For example, Google searches produce
+ * bookmarkable links with query strings.
  * <p>
  * Whether <code>BookmarkablePageRequestTargetUrlCodingStrategy</code> or
  * <code>QueryStringRequestTargetUrlCodingStrategy</code> is appropriate for a given mount depends
@@ -73,17 +71,17 @@
  * to insert a bookmarkable link to the request target.
  * <p>
  * This example demonstrates how to mount a path with
- * <code>QueryStringRequestTargetUrlCodingStrategy</code> within the <code>init</code> method of
- * a class implementing {@link org.apache.wicket.protocol.http.WebApplication WebApplication}:
+ * <code>QueryStringRequestTargetUrlCodingStrategy</code> within the <code>init</code> method of a
+ * class implementing {@link org.apache.wicket.protocol.http.WebApplication WebApplication}:
  * <p>
  * <code>mount(new QueryStringUrlCodingStrategy("/admin/productmanagement", admin.ProductManagement.class));</code>
  * <p>
  * Note that, as with the main BookmarkablePageRequestTargetUrlCodingStrategy, if the output of this
  * coding strategy is passed through
- * {@link javax.servlet.http.HttpServletResponse#encodeURL(java.lang.String) HttpServletResponse.encodeURL}
- * and the client has cookies turned off, the client's session ID will be stored in a path
- * parameter, like so:
- * "/mywebapp/myservlet/admin/productmanagement;jsessionid=730EC527564AF1C73F8C2FB19B604F55?action=edit&amp;product=4995".
+ * {@link javax.servlet.http.HttpServletResponse#encodeURL(java.lang.String)
+ * HttpServletResponse.encodeURL} and the client has cookies turned off, the client's session ID
+ * will be stored in a path parameter, like so:"/mywebapp/myservlet/admin/productmanagement;jsessionid=730EC527564AF1C73F8C2FB19B604F55?action=edit&amp;product=4995"
+ * .
  * 
  * @author Benjamin Hawkes-Lewis
  */
@@ -111,19 +109,12 @@
 	 * @param parameters
 	 *            parameter names mapped to parameter values
 	 */
+	@Override
 	protected void appendParameters(AppendingStringBuffer url, Map parameters)
 	{
 		if (parameters != null && parameters.size() > 0)
 		{
-			final Iterator entries;
-			if (UnitTestSettings.getSortUrlParameters())
-			{
-				entries = new TreeMap(parameters).entrySet().iterator();
-			}
-			else
-			{
-				entries = parameters.entrySet().iterator();
-			}
+			final Iterator entries = parameters.entrySet().iterator();
 			WebRequestEncoder encoder = new WebRequestEncoder(url);
 			while (entries.hasNext())
 			{
@@ -137,6 +128,7 @@
 		}
 	}
 
+	@Override
 	public IRequestTarget decode(RequestParameters requestParameters)
 	{
 		String pageMapName = requestParameters.getPageMapName();
@@ -147,9 +139,8 @@
 		if (requestParameters.getInterfaceName() != null)
 		{
 			return new BookmarkableListenerInterfaceRequestTarget(pageMapName,
-				(Class)bookmarkablePageClassRef.get(), parameters,
-				requestParameters.getComponentPath(), requestParameters.getInterfaceName(),
-				requestParameters.getVersionNumber());
+				bookmarkablePageClassRef.get(), parameters, requestParameters.getComponentPath(),
+				requestParameters.getInterfaceName(), requestParameters.getVersionNumber());
 		}
 		else
 		{
@@ -168,6 +159,7 @@
 	 * 
 	 * @return Parameters
 	 */
+	@Override
 	protected ValueMap decodeParameters(String fragment, Map passedParameters)
 	{
 		ValueMap parameters = new ValueMap();

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkableListenerInterfaceRequestTarget.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkableListenerInterfaceRequestTarget.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkableListenerInterfaceRequestTarget.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkableListenerInterfaceRequestTarget.java Sun Nov 16 14:04:19 2008
@@ -52,8 +52,9 @@
 	 * @param interfaceName
 	 * @param versionNumber
 	 */
-	public BookmarkableListenerInterfaceRequestTarget(String pageMapName, Class pageClass,
-		PageParameters pageParameters, String componentPath, String interfaceName, int versionNumber)
+	public BookmarkableListenerInterfaceRequestTarget(String pageMapName,
+		Class<? extends Page> pageClass, PageParameters pageParameters, String componentPath,
+		String interfaceName, int versionNumber)
 	{
 		super(pageMapName, pageClass, pageParameters);
 		this.componentPath = componentPath;
@@ -73,8 +74,8 @@
 	 * @param component
 	 * @param listenerInterface
 	 */
-	public BookmarkableListenerInterfaceRequestTarget(String pageMapName, Class pageClass,
-		PageParameters pageParameters, Component component,
+	public BookmarkableListenerInterfaceRequestTarget(String pageMapName,
+		Class<? extends Page> pageClass, PageParameters pageParameters, Component component,
 		RequestListenerInterface listenerInterface)
 	{
 		this(pageMapName, pageClass, pageParameters, component.getPath(),

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkablePageRequestTarget.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkablePageRequestTarget.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkablePageRequestTarget.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/BookmarkablePageRequestTarget.java Sun Nov 16 14:04:19 2008
@@ -29,7 +29,7 @@
  * Default implementation of {@link IBookmarkablePageRequestTarget}. Target that denotes a page
  * that is to be created from the provided page class. This is typically used for redirects to
  * bookmarkable pages or mounted pages.
- * 
+ *
  * @author Eelco Hillenius
  * @author Igor Vaynberg (ivaynberg)
  */
@@ -49,9 +49,9 @@
 
 	/**
 	 * Construct.
-	 * 
+	 *
 	 * @param <C>
-	 * 
+	 *
 	 * @param pageClass
 	 *            the class of the page
 	 */
@@ -62,9 +62,9 @@
 
 	/**
 	 * Construct.
-	 * 
+	 *
 	 * @param <C>
-	 * 
+	 *
 	 * @param pageClass
 	 *            the class of the page
 	 * @param pageParameters
@@ -78,12 +78,12 @@
 
 	/**
 	 * Construct.
-	 * 
+	 *
 	 * @param <C>
-	 * 
+	 *
 	 * @param pageMapName
 	 *            optional page map name
-	 * 
+	 *
 	 * @param pageClass
 	 *            the class of the page
 	 */
@@ -94,10 +94,10 @@
 
 	/**
 	 * Construct.
-	 * 
+	 *
 	 * @param <C>
 	 *            type of page
-	 * 
+	 *
 	 * @param pageMapName
 	 *            optional page map name
 	 * @param pageClass
@@ -237,6 +237,10 @@
 				String redirectUrl = processor.getRequestCodingStrategy()
 					.encode(requestCycle, this)
 					.toString();
+				if (redirectUrl.startsWith("./"))
+				{
+					redirectUrl = redirectUrl.substring(2);
+				}
 				requestCycle.getResponse().redirect(redirectUrl);
 			}
 			else
@@ -259,10 +263,10 @@
 
 	/**
 	 * Constructs a new instance of a page given its class name
-	 * 
+	 *
 	 * @param <C>
 	 *            type of page
-	 * 
+	 *
 	 * @param pageClass
 	 *            class name of the page to be created
 	 * @param requestCycle
@@ -292,7 +296,7 @@
 
 	/**
 	 * Gets a newly constructed page if we are not in a redirect.
-	 * 
+	 *
 	 * @param requestCycle
 	 *            the request cycle
 	 * @return the page

Added: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/PageIdRequestTarget.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/PageIdRequestTarget.java?rev=718123&view=auto
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/PageIdRequestTarget.java (added)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/component/PageIdRequestTarget.java Sun Nov 16 14:04:19 2008
@@ -0,0 +1,101 @@
+/*
+ * 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.request.target.component;
+
+import org.apache.wicket.IRequestTarget;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageId;
+import org.apache.wicket.RequestCycle;
+
+/**
+ * Target that navigates to a page pointed to by its id. The great benefit of this target over the
+ * PageRequestTarget is that no reference to the actual page is needed, which greatly facilitates
+ * navigational usecases where a list or a stack of page references is needed (ie breadcrumbs).
+ * 
+ * @see PageId
+ * 
+ * @author igor.vaynberg
+ */
+public class PageIdRequestTarget implements IRequestTarget
+{
+	private final PageId id;
+
+	/**
+	 * Constructor
+	 * 
+	 * Even though a page is passed in, only a reference to its {@link PageId} is kept
+	 * 
+	 * @param page
+	 */
+	public PageIdRequestTarget(Page page)
+	{
+		if (page == null)
+		{
+			throw new IllegalArgumentException("Argument `page` cannot be null");
+		}
+		id = page.getPageId();
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param pageId
+	 */
+	public PageIdRequestTarget(PageId pageId)
+	{
+		if (pageId == null)
+		{
+			throw new IllegalArgumentException("Argument `pageId` cannot be null");
+		}
+
+		id = pageId;
+	}
+
+
+	/**
+	 * @return id page id
+	 */
+	public final PageId getPageId()
+	{
+		return id;
+	}
+
+	/** {@inheritDoc} */
+	public void respond(RequestCycle requestCycle)
+	{
+		Page page = requestCycle.getSession().getPage(id.getPageMapName(), "" + id.getPageNumber(),
+			id.getPageVersion());
+
+		// Should page be redirected to?
+		if (requestCycle.isRedirect())
+		{
+			// Redirect to the page
+			requestCycle.redirectTo(page);
+		}
+		else
+		{
+			// Let page render itself
+			page.renderPage();
+		}
+	}
+
+	/** {@inheritDoc} */
+	public void detach(RequestCycle requestCycle)
+	{
+	}
+
+}

Modified: wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/resource/ISharedResourceRequestTarget.java
URL: http://svn.apache.org/viewvc/wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/resource/ISharedResourceRequestTarget.java?rev=718123&r1=718122&r2=718123&view=diff
==============================================================================
--- wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/resource/ISharedResourceRequestTarget.java (original)
+++ wicket/sandbox/knopp/experimental/wicket/src/main/java/org/apache/wicket/request/target/resource/ISharedResourceRequestTarget.java Sun Nov 16 14:04:19 2008
@@ -17,11 +17,20 @@
 package org.apache.wicket.request.target.resource;
 
 import org.apache.wicket.IRequestTarget;
+import org.apache.wicket.ResourceReference;
+import org.apache.wicket.SharedResources;
 import org.apache.wicket.request.RequestParameters;
 
 /**
- * Target that denotes a shared {@link org.apache.wicket.Resource}.
+ * Target that denotes a shared {@link org.apache.wicket.Resource}, i.e a resource that doesn't need
+ * a host component.
  * 
+ * <p>
+ * Shared resources for an application are contained in the {@link SharedResources} class.
+ * 
+ * @see SharedResources
+ * @see ResourceReference
+ * @see org.apache.wicket.Resource
  * @author Eelco Hillenius
  */
 public interface ISharedResourceRequestTarget extends IRequestTarget