You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by iv...@apache.org on 2010/03/01 01:01:58 UTC

svn commit: r917331 [1/2] - in /wicket/trunk/wicket/src: main/java/org/apache/wicket/ main/java/org/apache/wicket/ng/ main/java/org/apache/wicket/ng/mock/ main/java/org/apache/wicket/ng/request/mapper/ main/java/org/apache/wicket/protocol/http/ main/ja...

Author: ivaynberg
Date: Mon Mar  1 00:01:57 2010
New Revision: 917331

URL: http://svn.apache.org/viewvc?rev=917331&view=rev
Log:
text fixes and ../ handling inside resource paths

Added:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java   (contents, props changed)
      - copied, changed from r917266, wicket/trunk/wicket/src/test/java/org/apache/wicket/protocol/http/TestExpirePage.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java   (with props)
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletResponse.java   (with props)
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpSession.java   (with props)
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockServletContext.java   (with props)
Modified:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/DefaultExceptionMapper.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockWebResponse.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/mapper/ResourceReferenceMapper.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/RequestUtils.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/settings/Settings.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/cookies/CookieUtils.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/crypt/KeyInSessionSunJceCryptFactory.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/ParentResourceEscapePathTest.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/html/image/ImageTest.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/html/link/submitLink/FormPage.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/markup/resolver/TestHomePage.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/protocol/http/TestExpirePage.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/protocol/http/WebResponseExceptionsTest.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/stateless/StatelessComponentPageWithParams.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/util/cookies/CookieUtilsTest.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/util/tester/WicketTesterTest.java

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/Application.java Mon Mar  1 00:01:57 2010
@@ -85,6 +85,7 @@
 import org.apache.wicket.settings.ISecuritySettings;
 import org.apache.wicket.settings.ISessionSettings;
 import org.apache.wicket.settings.Settings;
+import org.apache.wicket.util.IProvider;
 import org.apache.wicket.util.convert.ConverterLocator;
 import org.apache.wicket.util.lang.Checks;
 import org.apache.wicket.util.lang.Objects;
@@ -192,7 +193,7 @@
 	private IRequestLogger requestLogger;
 
 	/** The session facade. */
-	private ISessionStore sessionStore;
+	private volatile ISessionStore sessionStore;
 
 	/** Settings for this application. */
 	private Settings settings;
@@ -206,6 +207,9 @@
 	/** request cycle provider */
 	private IRequestCycleProvider requestCycleProvider;
 
+	/** session store provider */
+	private IProvider<ISessionStore> sessionStoreProvider;
+
 	/**
 	 * Checks if the <code>Application</code> threadlocal is set in this thread
 	 * 
@@ -609,6 +613,17 @@
 	 */
 	public final ISessionStore getSessionStore()
 	{
+		if (sessionStore == null)
+		{
+			synchronized (this)
+			{
+				if (sessionStore == null)
+				{
+					sessionStore = sessionStoreProvider.get();
+					sessionStore.registerUnboundListener(this);
+				}
+			}
+		}
 		return sessionStore;
 	}
 
@@ -907,11 +922,9 @@
 		String applicationKey = getApplicationKey();
 		applicationKeyToApplication.put(applicationKey, this);
 
-		sessionStore = newSessionStore();
-		sessionStore.registerUnboundListener(this);
 		converterLocator = newConverterLocator();
 
-		pageManager = newPageManager(getPageManagerContext());
+		setPageManagerProvider(new DefaultPageManagerProvider());
 		resourceReferenceRegistry = newResourceReferenceRegistry();
 		sharedResources = newSharedResources(resourceReferenceRegistry);
 
@@ -923,6 +936,17 @@
 		requestCycleProvider = new DefaultRequestCycleProvider();
 	}
 
+
+	public final IProvider<ISessionStore> getSessionStoreProvider()
+	{
+		return sessionStoreProvider;
+	}
+
+	public final void setSessionStoreProvider(IProvider<ISessionStore> sessionStoreProvider)
+	{
+		this.sessionStoreProvider = sessionStoreProvider;
+	}
+
 	/**
 	 * Creates and returns a new instance of {@link IConverterLocator}.
 	 * 
@@ -945,14 +969,6 @@
 	}
 
 	/**
-	 * Creates a new session facade. Is called once per application, and is typically not something
-	 * clients reimplement.
-	 * 
-	 * @return The session facade
-	 */
-	protected abstract ISessionStore newSessionStore();
-
-	/**
 	 * Notifies the registered component instantiation listeners of the construction of the provided
 	 * component
 	 * 
@@ -1210,16 +1226,19 @@
 	// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 	// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-	protected IPageManager newPageManager(IPageManagerContext context)
+	private volatile IPageManager pageManager;
+	private IPageManagerProvider pageManagerProvider;
+
+
+	public final IPageManagerProvider getPageManagerProvider()
 	{
-		int cacheSize = 40;
-		int fileChannelPoolCapacity = 50;
-		IDataStore dataStore = new DiskDataStore(getName(), 1000000, fileChannelPoolCapacity);
-		IPageStore pageStore = new DefaultPageStore(getName(), dataStore, cacheSize);
-		return new PersistentPageManager(getName(), pageStore, context);
+		return pageManagerProvider;
 	}
 
-	private IPageManager pageManager;
+	public final void setPageManagerProvider(IPageManagerProvider pageManagerProvider)
+	{
+		this.pageManagerProvider = pageManagerProvider;
+	}
 
 	/**
 	 * Context for PageManager to interact with rest of Wicket
@@ -1230,8 +1249,18 @@
 	 * 
 	 * @return the page manager
 	 */
-	public IPageManager getPageManager()
+	public final IPageManager getPageManager()
 	{
+		if (pageManager == null)
+		{
+			synchronized (this)
+			{
+				if (pageManager == null)
+				{
+					pageManager = pageManagerProvider.get(getPageManagerContext());
+				}
+			}
+		}
 		return pageManager;
 	}
 
@@ -1470,6 +1499,16 @@
 			throw new IllegalStateException(
 				"An instance of IPageRendererProvider has not yet been set on this Application. @see Application#setPageRendererProvider");
 		}
+		if (getSessionStoreProvider() == null)
+		{
+			throw new IllegalStateException(
+				"An instance of ISessionStoreProvider has not yet been set on this Application. @see Application#setSessionStoreProvider");
+		}
+		if (getPageManagerProvider() == null)
+		{
+			throw new IllegalStateException(
+				"An instance of IPageManagerProvider has not yet been set on this Application. @see Application#setPageManagerProvider");
+		}
 	}
 
 	/**
@@ -1507,4 +1546,19 @@
 	{
 		return URLConnection.getFileNameMap().getContentTypeFor(fileName);
 	}
+
+	private class DefaultPageManagerProvider implements IPageManagerProvider
+	{
+
+		public IPageManager get(IPageManagerContext context)
+		{
+			int cacheSize = 40;
+			int fileChannelPoolCapacity = 50;
+			IDataStore dataStore = new DiskDataStore(getName(), 1000000, fileChannelPoolCapacity);
+			IPageStore pageStore = new DefaultPageStore(getName(), dataStore, cacheSize);
+			return new PersistentPageManager(getName(), pageStore, context);
+
+		}
+
+	}
 }

Copied: wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java (from r917266, wicket/trunk/wicket/src/test/java/org/apache/wicket/protocol/http/TestExpirePage.java)
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java?p2=wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java&p1=wicket/trunk/wicket/src/test/java/org/apache/wicket/protocol/http/TestExpirePage.java&r1=917266&r2=917331&rev=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/protocol/http/TestExpirePage.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java Mon Mar  1 00:01:57 2010
@@ -1,48 +1,25 @@
-/*
- * 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;
-
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.markup.html.WebPage;
-
-/**
- * Test page for session expiry (/ page not found).
- */
-public class TestExpirePage extends WebPage
-{
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * Construct.
-	 */
-	public TestExpirePage()
-	{
-
-		add(new AjaxLink("link")
-		{
-			private static final long serialVersionUID = 1L;
-
-			@Override
-			public void onClick(AjaxRequestTarget target)
-			{
-				target.addComponent(this);
-			}
-		});
-	}
-
-}
+/*
+ * 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;
+
+import org.apache.wicket.pageStore.IPageManager;
+import org.apache.wicket.pageStore.IPageManagerContext;
+
+public interface IPageManagerProvider
+{
+	IPageManager get(IPageManagerContext context);
+}

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/IPageManagerProvider.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/DefaultExceptionMapper.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/DefaultExceptionMapper.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/DefaultExceptionMapper.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/DefaultExceptionMapper.java Mon Mar  1 00:01:57 2010
@@ -22,6 +22,7 @@
 import org.apache.wicket.ng.request.handler.PageProvider;
 import org.apache.wicket.ng.request.handler.impl.RenderPageRequestHandler;
 import org.apache.wicket.ng.request.mapper.StalePageException;
+import org.apache.wicket.protocol.http.PageExpiredException;
 
 public class DefaultExceptionMapper implements IExceptionMapper
 {
@@ -33,6 +34,12 @@
 			// If the page was stale, just rerender it
 			return new RenderPageRequestHandler(new PageProvider(((StalePageException)e).getPage()));
 		}
+		else if (e instanceof PageExpiredException)
+		{
+			return new RenderPageRequestHandler(new PageProvider(Application.get()
+				.getApplicationSettings()
+				.getPageExpiredErrorPage()));
+		}
 		else
 		{
 			return new RenderPageRequestHandler(new PageProvider(Application.get()

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java Mon Mar  1 00:01:57 2010
@@ -16,12 +16,14 @@
  */
 package org.apache.wicket.ng.mock;
 
+import org.apache.wicket.IPageManagerProvider;
 import org.apache.wicket.Page;
 import org.apache.wicket.Session;
 import org.apache.wicket.pageStore.IPageManager;
 import org.apache.wicket.pageStore.IPageManagerContext;
 import org.apache.wicket.protocol.http.WebApplication;
 import org.apache.wicket.session.ISessionStore;
+import org.apache.wicket.util.IProvider;
 
 public class MockApplication extends WebApplication
 {
@@ -43,29 +45,43 @@
 	}
 
 
-	@Override
-	protected IPageManager newPageManager(IPageManagerContext context)
+	public Session getSession()
 	{
-		return new MockPageManager(context);
+		return getSessionStore().lookup(null);
 	}
 
-	/**
-	 * @see org.apache.wicket.ng.protocol.http.WebApplication#newSessionStore()
-	 */
 	@Override
-	public ISessionStore newSessionStore()
+	public final String getInitParameter(String key)
 	{
-		return new MockSessionStore();
+		return null;
 	}
 
-	public Session getSession()
+	@Override
+	protected void internalInit()
 	{
-		return getSessionStore().lookup(null);
+		super.internalInit();
+		setSessionStoreProvider(new MockSessionStoreProvider());
+		setPageManagerProvider(new MockPageManagerProvider());
 	}
 
-	@Override
-	public final String getInitParameter(String key)
+	private static class MockSessionStoreProvider implements IProvider<ISessionStore>
 	{
-		return null;
+
+		public ISessionStore get()
+		{
+			return new MockSessionStore();
+		}
+
 	}
+	private static class MockPageManagerProvider implements IPageManagerProvider
+	{
+
+		public IPageManager get(IPageManagerContext context)
+		{
+			return new MockPageManager(context);
+		}
+
+
+	}
+
 }

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java Mon Mar  1 00:01:57 2010
@@ -56,10 +56,12 @@
 
 	public void newSessionCreated()
 	{
+		pages.clear();
 	}
 
 	public void sessionExpired(String sessionId)
 	{
+		pages.clear();
 	}
 
 	public void setContext(IPageManagerContext context)

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockWebResponse.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockWebResponse.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockWebResponse.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockWebResponse.java Mon Mar  1 00:01:57 2010
@@ -273,7 +273,14 @@
 		}
 		else
 		{
-			return binaryResponse.toByteArray();
+			byte[] bytes = binaryResponse.toByteArray();
+			if (getContentLength() != null)
+			{
+				byte[] trimmed = new byte[getContentLength().intValue()];
+				System.arraycopy(bytes, 0, trimmed, 0, getContentLength().intValue());
+				return trimmed;
+			}
+			return bytes;
 		}
 	}
 

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/mapper/ResourceReferenceMapper.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/mapper/ResourceReferenceMapper.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/mapper/ResourceReferenceMapper.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/mapper/ResourceReferenceMapper.java Mon Mar  1 00:01:57 2010
@@ -16,6 +16,7 @@
  */
 package org.apache.wicket.ng.request.mapper;
 
+import org.apache.wicket.Application;
 import org.apache.wicket.IRequestHandler;
 import org.apache.wicket.Request;
 import org.apache.wicket.ng.request.Url;
@@ -69,6 +70,16 @@
 	public IRequestHandler mapRequest(Request request)
 	{
 		Url url = request.getUrl();
+
+		for (int i = 0; i < url.getSegments().size(); i++)
+		{
+			if (url.getSegments().get(i).equals(
+				Application.get().getResourceSettings().getParentFolderPlaceholder()))
+			{
+				url.getSegments().set(i, "..");
+			}
+		}
+
 		if (url.getSegments().size() >= 4 &&
 			urlStartsWith(url, getContext().getNamespace(), getContext().getResourceIdentifier()))
 		{
@@ -142,6 +153,19 @@
 				parameters.clearIndexedParameters();
 				url = encodePageParameters(url, parameters, pageParametersEncoder);
 			}
+
+			final CharSequence placeholder = Application.get()
+				.getResourceSettings()
+				.getParentFolderPlaceholder();
+
+			for (int i = 0; i < url.getSegments().size(); i++)
+			{
+				if ("..".equals(url.getSegments().get(i)))
+				{
+					url.getSegments().set(i, placeholder.toString());
+				}
+			}
+
 			return url;
 		}
 		return null;

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/RequestUtils.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/RequestUtils.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/RequestUtils.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/RequestUtils.java Mon Mar  1 00:01:57 2010
@@ -135,7 +135,7 @@
 	 * @param path
 	 * @return path string with double dots removed
 	 */
-	static String removeDoubleDots(String path)
+	public static String removeDoubleDots(String path)
 	{
 		List<String> newcomponents = new ArrayList<String>(Arrays.asList(path.split("/")));
 

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WebApplication.java Mon Mar  1 00:01:57 2010
@@ -46,6 +46,7 @@
 import org.apache.wicket.ng.resource.ResourceReference;
 import org.apache.wicket.session.HttpSessionStore;
 import org.apache.wicket.session.ISessionStore;
+import org.apache.wicket.util.IProvider;
 import org.apache.wicket.util.collections.MostRecentlyUsedMap;
 import org.apache.wicket.util.file.FileCleaner;
 import org.apache.wicket.util.file.IResourceFinder;
@@ -440,7 +441,7 @@
 		}
 
 		setPageRendererProvider(new WebPageRendererProvider());
-
+		setSessionStoreProvider(new WebSessionStoreProvider());
 		// Configure the app.
 		configure();
 	}
@@ -510,16 +511,6 @@
 	}
 
 	/**
-	 * @see org.apache.wicket.Application#newSessionStore()
-	 */
-	@Override
-	protected ISessionStore newSessionStore()
-	{
-		return new HttpSessionStore();
-	}
-
-
-	/**
 	 * Creates a new ajax request target used to control ajax responses
 	 * 
 	 * @param page
@@ -671,6 +662,15 @@
 		{
 			return new WebPageRenderer(handler);
 		}
+	}
+
+	private static class WebSessionStoreProvider implements IProvider<ISessionStore>
+	{
+
+		public ISessionStore get()
+		{
+			return new HttpSessionStore();
+		}
 
 	}
 }

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java?rev=917331&r1=917330&r2=917331&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java Mon Mar  1 00:01:57 2010
@@ -366,9 +366,16 @@
 				foundUrlPattern = n.getTextContent();
 			}
 		}
+
+		if (foundFilterName != null)
+		{
+			foundFilterName = foundFilterName.trim();
+		}
+
+
 		if (filterName.equals(foundFilterName))
 		{
-			return foundUrlPattern;
+			return (foundUrlPattern != null) ? foundUrlPattern.trim() : null;
 		}
 		else
 		{

Added: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java?rev=917331&view=auto
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java (added)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java Mon Mar  1 00:01:57 2010
@@ -0,0 +1,1505 @@
+/*
+ * 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.mock;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.protocol.http.RequestUtils;
+import org.apache.wicket.protocol.http.WicketURLDecoder;
+import org.apache.wicket.protocol.http.WicketURLEncoder;
+import org.apache.wicket.util.file.File;
+import org.apache.wicket.util.io.IOUtils;
+import org.apache.wicket.util.upload.FileUploadBase;
+import org.apache.wicket.util.value.ValueMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Mock servlet request. Implements all of the methods from the standard HttpServletRequest class
+ * plus helper methods to aid setting up a request.
+ * 
+ * @author Chris Turner
+ */
+public class MockHttpServletRequest implements HttpServletRequest
+{
+	/**
+	 * A holder class for an uploaded file.
+	 * 
+	 * @author Frank Bille (billen)
+	 */
+	private class UploadedFile
+	{
+		private String fieldName;
+		private File file;
+		private String contentType;
+
+		/**
+		 * Construct.
+		 * 
+		 * @param fieldName
+		 * @param file
+		 * @param contentType
+		 */
+		public UploadedFile(String fieldName, File file, String contentType)
+		{
+			this.fieldName = fieldName;
+			this.file = file;
+			this.contentType = contentType;
+		}
+
+		/**
+		 * @return The content type of the file. Mime type.
+		 */
+		public String getContentType()
+		{
+			return contentType;
+		}
+
+		/**
+		 * @param contentType
+		 *            The content type.
+		 */
+		public void setContentType(String contentType)
+		{
+			this.contentType = contentType;
+		}
+
+		/**
+		 * @return The field name.
+		 */
+		public String getFieldName()
+		{
+			return fieldName;
+		}
+
+		/**
+		 * @param fieldName
+		 */
+		public void setFieldName(String fieldName)
+		{
+			this.fieldName = fieldName;
+		}
+
+		/**
+		 * @return The uploaded file.
+		 */
+		public File getFile()
+		{
+			return file;
+		}
+
+		/**
+		 * @param file
+		 */
+		public void setFile(File file)
+		{
+			this.file = file;
+		}
+	}
+
+	/** Logging object */
+	private static final Logger log = LoggerFactory.getLogger(MockHttpServletRequest.class);
+
+	/** The application */
+	private final Application application;
+
+	private final ValueMap attributes = new ValueMap();
+
+	private String authType;
+
+	private String characterEncoding;
+
+	private final ServletContext context;
+
+	private final List<Cookie> cookies = new ArrayList<Cookie>();
+
+	private final ValueMap headers = new ValueMap();
+
+	private String method;
+
+	private final ValueMap parameters = new ValueMap();
+
+	private String path;
+
+	private final HttpSession session;
+
+	private String url;
+
+	private Map<String, UploadedFile> uploadedFiles;
+
+	private boolean useMultiPartContentType;
+
+	/**
+	 * Create the request using the supplied session object. Note that in order for temporary
+	 * sessions to work, the supplied session must be an instance of {@link MockHttpSession}
+	 * 
+	 * @param application
+	 *            The application that this request is for
+	 * @param session
+	 *            The session object
+	 * @param context
+	 *            The current servlet context
+	 */
+	public MockHttpServletRequest(final Application application, final HttpSession session,
+		final ServletContext context)
+	{
+		this.application = application;
+		this.session = session;
+		this.context = context;
+		initialize();
+	}
+
+	/**
+	 * Add a new cookie.
+	 * 
+	 * @param cookie
+	 *            The cookie
+	 */
+	public void addCookie(final Cookie cookie)
+	{
+		cookies.add(cookie);
+	}
+
+	public void addCookies(Iterable<Cookie> cookies)
+	{
+		for (Cookie cookie : cookies)
+		{
+			addCookie(cookie);
+		}
+	}
+
+
+	/**
+	 * Add an uploaded file to the request. Use this to simulate a file that has been uploaded to a
+	 * field.
+	 * 
+	 * @param fieldName
+	 *            The fieldname of the upload field.
+	 * @param file
+	 *            The file to upload.
+	 * @param contentType
+	 *            The content type of the file. Must be a correct mimetype.
+	 */
+	public void addFile(String fieldName, File file, String contentType)
+	{
+		if (file == null)
+		{
+			throw new IllegalArgumentException("File must not be null");
+		}
+
+		if (file.exists() == false)
+		{
+			throw new IllegalArgumentException(
+				"File does not exists. You must provide an existing file: " +
+					file.getAbsolutePath());
+		}
+
+		if (file.isFile() == false)
+		{
+			throw new IllegalArgumentException(
+				"You can only add a File, which is not a directory. Only files can be uploaded.");
+		}
+
+		if (uploadedFiles == null)
+		{
+			uploadedFiles = new HashMap<String, UploadedFile>();
+		}
+
+		UploadedFile uf = new UploadedFile(fieldName, file, contentType);
+
+		uploadedFiles.put(fieldName, uf);
+	}
+
+	/**
+	 * Add a header to the request.
+	 * 
+	 * @param name
+	 *            The name of the header to add
+	 * @param value
+	 *            The value
+	 */
+	public void addHeader(String name, String value)
+	{
+		@SuppressWarnings("unchecked")
+		List<String> list = (List<String>)headers.get(name);
+		if (list == null)
+		{
+			list = new ArrayList<String>(1);
+			headers.put(name, list);
+		}
+		list.add(value);
+	}
+
+	/**
+	 * @param name
+	 * @param date
+	 */
+	public void addDateHeader(String name, long date)
+	{
+		DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
+		String dateString = df.format(new Date(date));
+		addHeader(name, dateString);
+	}
+
+	/**
+	 * Get an attribute.
+	 * 
+	 * @param name
+	 *            The attribute name
+	 * @return The value, or null
+	 */
+	public Object getAttribute(final String name)
+	{
+		return attributes.get(name);
+	}
+
+	/**
+	 * Get the names of all of the values.
+	 * 
+	 * @return The names
+	 */
+	public Enumeration<String> getAttributeNames()
+	{
+		return Collections.enumeration(attributes.keySet());
+	}
+
+	// HttpServletRequest methods
+
+	/**
+	 * Get the auth type.
+	 * 
+	 * @return The auth type
+	 */
+	public String getAuthType()
+	{
+		return authType;
+	}
+
+	/**
+	 * Get the current character encoding.
+	 * 
+	 * @return The character encoding
+	 */
+	public String getCharacterEncoding()
+	{
+		return characterEncoding;
+	}
+
+	/**
+	 * true will force Request generate multiPart ContentType and ContentLength
+	 * 
+	 * @param useMultiPartContentType
+	 */
+	public void setUseMultiPartContentType(boolean useMultiPartContentType)
+	{
+		this.useMultiPartContentType = useMultiPartContentType;
+	}
+
+
+	/**
+	 * Return the length of the content. This is always -1 except if useMultiPartContentType set as
+	 * true. Then the length will be the length of the generated request.
+	 * 
+	 * @return -1 if useMultiPartContentType is false. Else the length of the generated request.
+	 */
+	public int getContentLength()
+	{
+		if (useMultiPartContentType)
+		{
+			byte[] request = buildRequest();
+			return request.length;
+		}
+
+		return -1;
+	}
+
+	/**
+	 * If useMultiPartContentType set as true return the correct content-type.
+	 * 
+	 * @return The correct multipart content-type if useMultiPartContentType is true. Else null.
+	 */
+	public String getContentType()
+	{
+		if (useMultiPartContentType)
+		{
+			return FileUploadBase.MULTIPART_FORM_DATA + "; boundary=abcdefgABCDEFG";
+		}
+
+		return null;
+	}
+
+	/**
+	 * Get the context path. For this mock implementation the name of the application is always
+	 * returned.
+	 * 
+	 * @return The context path
+	 */
+	public String getContextPath()
+	{
+		return "/" + application.getName();
+	}
+
+	/**
+	 * Get all of the cookies for this request.
+	 * 
+	 * @return The cookies
+	 */
+	public Cookie[] getCookies()
+	{
+		if (cookies.size() == 0)
+		{
+			return null;
+		}
+		Cookie[] result = new Cookie[cookies.size()];
+		return cookies.toArray(result);
+	}
+
+	/**
+	 * Get the given header as a date.
+	 * 
+	 * @param name
+	 *            The header name
+	 * @return The date, or -1 if header not found
+	 * @throws IllegalArgumentException
+	 *             If the header cannot be converted
+	 */
+	public long getDateHeader(final String name) throws IllegalArgumentException
+	{
+		String value = getHeader(name);
+		if (value == null)
+		{
+			return -1;
+		}
+
+		DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
+		try
+		{
+			return df.parse(value).getTime();
+		}
+		catch (ParseException e)
+		{
+			throw new IllegalArgumentException("Can't convert header to date " + name + ": " +
+				value);
+		}
+	}
+
+	/**
+	 * Get the given header value.
+	 * 
+	 * @param name
+	 *            The header name
+	 * @return The header value or null
+	 */
+	public String getHeader(final String name)
+	{
+		@SuppressWarnings("unchecked")
+		final List<String> l = (List<String>)headers.get(name);
+		if (l == null || l.size() < 1)
+		{
+			return null;
+		}
+		else
+		{
+			return l.get(0);
+		}
+	}
+
+	/**
+	 * Get the names of all of the headers.
+	 * 
+	 * @return The header names
+	 */
+	public Enumeration<String> getHeaderNames()
+	{
+		return Collections.enumeration(headers.keySet());
+	}
+
+	/**
+	 * Get enumeration of all header values with the given name.
+	 * 
+	 * @param name
+	 *            The name
+	 * @return The header values
+	 */
+	public Enumeration<String> getHeaders(final String name)
+	{
+		@SuppressWarnings("unchecked")
+		List<String> list = (List<String>)headers.get(name);
+		if (list == null)
+		{
+			list = new ArrayList<String>();
+		}
+		return Collections.enumeration(list);
+	}
+
+	/**
+	 * Returns an input stream if there has been added some uploaded files. Use
+	 * {@link #addFile(String, File, String)} to add some uploaded files.
+	 * 
+	 * @return The input stream
+	 * @throws IOException
+	 *             If an I/O related problem occurs
+	 */
+	public ServletInputStream getInputStream() throws IOException
+	{
+		byte[] request = buildRequest();
+
+		// Ok lets make an input stream to return
+		final ByteArrayInputStream bais = new ByteArrayInputStream(request);
+
+		return new ServletInputStream()
+		{
+			@Override
+			public int read()
+			{
+				return bais.read();
+			}
+		};
+	}
+
+	/**
+	 * Get the given header as an int.
+	 * 
+	 * @param name
+	 *            The header name
+	 * @return The header value or -1 if header not found
+	 * @throws NumberFormatException
+	 *             If the header is not formatted correctly
+	 */
+	public int getIntHeader(final String name)
+	{
+		String value = getHeader(name);
+		if (value == null)
+		{
+			return -1;
+		}
+		return Integer.valueOf(value).intValue();
+	}
+
+	/**
+	 * Get the locale of the request. Attempts to decode the Accept-Language header and if not found
+	 * returns the default locale of the JVM.
+	 * 
+	 * @return The locale
+	 */
+	public Locale getLocale()
+	{
+		return getLocales().nextElement();
+	}
+
+	/**
+	 * 
+	 * @param value
+	 * @return locale
+	 */
+	private Locale getLocale(final String value)
+	{
+		final String[] bits = value.split("-");
+		if (bits.length < 1)
+		{
+			return null;
+		}
+
+		final String language = bits[0].toLowerCase();
+		if (bits.length > 1)
+		{
+			final String country = bits[1].toUpperCase();
+			return new Locale(language, country);
+		}
+		else
+		{
+			return new Locale(language);
+		}
+	}
+
+	/**
+	 * Return all the accepted locales. This implementation always returns just one.
+	 * 
+	 * @return The locales
+	 */
+	public Enumeration<Locale> getLocales()
+	{
+		List<Locale> list = new ArrayList<Locale>();
+		final String header = getHeader("Accept-Language");
+		if (header != null)
+		{
+			final String[] locales = header.split(",");
+			for (String value : locales)
+			{
+				Locale locale = getLocale(value);
+				if (locale != null)
+				{
+					list.add(locale);
+				}
+			}
+		}
+
+		if (list.size() == 0)
+		{
+			list.add(Locale.getDefault());
+		}
+
+		return Collections.enumeration(list);
+	}
+
+	/**
+	 * Get the method.
+	 * 
+	 * @return The method
+	 */
+	public String getMethod()
+	{
+		return method;
+	}
+
+	/**
+	 * Get the request parameter with the given name.
+	 * 
+	 * @param name
+	 *            The parameter name
+	 * @return The parameter value, or null
+	 */
+	public String getParameter(final String name)
+	{
+		return parameters.getString(name);
+	}
+
+	/**
+	 * Get the map of all of the parameters.
+	 * 
+	 * @return The parameters
+	 */
+	public Map<String, Object> getParameterMap()
+	{
+		return parameters;
+	}
+
+	/**
+	 * Get the names of all of the parameters.
+	 * 
+	 * @return The parameter names
+	 */
+	public Enumeration<String> getParameterNames()
+	{
+		return Collections.enumeration(parameters.keySet());
+	}
+
+	/**
+	 * Get the values for the given parameter.
+	 * 
+	 * @param name
+	 *            The name of the parameter
+	 * @return The return values
+	 */
+	public String[] getParameterValues(final String name)
+	{
+		Object value = parameters.get(name);
+		if (value == null)
+		{
+			return new String[0];
+		}
+
+		if (value instanceof String[])
+		{
+			return (String[])value;
+		}
+		else
+		{
+			String[] result = new String[1];
+			result[0] = value.toString();
+			return result;
+		}
+	}
+
+	/**
+	 * Get the path info.
+	 * 
+	 * @return The path info
+	 */
+	public String getPathInfo()
+	{
+		return path;
+	}
+
+	/**
+	 * Always returns null.
+	 * 
+	 * @return null
+	 */
+	public String getPathTranslated()
+	{
+		return null;
+	}
+
+	/**
+	 * Get the protocol.
+	 * 
+	 * @return Always HTTP/1.1
+	 */
+	public String getProtocol()
+	{
+		return "HTTP/1.1";
+	}
+
+	/**
+	 * Get the query string part of the request.
+	 * 
+	 * @return The query string
+	 */
+	public String getQueryString()
+	{
+		if (parameters.size() == 0)
+		{
+			return null;
+		}
+		else
+		{
+			final StringBuffer buf = new StringBuffer();
+			for (Iterator<String> iterator = parameters.keySet().iterator(); iterator.hasNext();)
+			{
+				final String name = iterator.next();
+				final String value = parameters.getString(name);
+				if (name != null)
+				{
+					buf.append(WicketURLEncoder.QUERY_INSTANCE.encode(name));
+				}
+				buf.append('=');
+				if (value != null)
+				{
+					buf.append(WicketURLEncoder.QUERY_INSTANCE.encode(value));
+				}
+				if (iterator.hasNext())
+				{
+					buf.append('&');
+				}
+			}
+			return buf.toString();
+		}
+	}
+
+	/**
+	 * This feature is not implemented at this time as we are not supporting binary servlet input.
+	 * This functionality may be added in the future.
+	 * 
+	 * @return The reader
+	 * @throws IOException
+	 *             If an I/O related problem occurs
+	 */
+	public BufferedReader getReader() throws IOException
+	{
+		return new BufferedReader(new CharArrayReader(new char[0]));
+	}
+
+	/**
+	 * Deprecated method - should not be used.
+	 * 
+	 * @param name
+	 *            The name
+	 * @return The path
+	 * @deprecated Use ServletContext.getRealPath(String) instead.
+	 */
+	@Deprecated
+	public String getRealPath(String name)
+	{
+		return context.getRealPath(name);
+	}
+
+	/**
+	 * Get the remote address of the client.
+	 * 
+	 * @return Always 127.0.0.1
+	 */
+	public String getRemoteAddr()
+	{
+		return "127.0.0.1";
+	}
+
+	/**
+	 * Get the remote host.
+	 * 
+	 * @return Always localhost
+	 */
+	public String getRemoteHost()
+	{
+		return "localhost";
+	}
+
+	/**
+	 * Get the name of the remote user from the REMOTE_USER header.
+	 * 
+	 * @return The name of the remote user
+	 */
+	public String getRemoteUser()
+	{
+		return getHeader("REMOTE_USER");
+	}
+
+	/**
+	 * Return a dummy dispatcher that just records that dispatch has occurred without actually doing
+	 * anything.
+	 * 
+	 * @param name
+	 *            The name to dispatch to
+	 * @return The dispatcher
+	 */
+	public RequestDispatcher getRequestDispatcher(String name)
+	{
+		return context.getRequestDispatcher(name);
+	}
+
+	/**
+	 * Get the requested session id. Always returns the id of the current session.
+	 * 
+	 * @return The session id
+	 */
+	public String getRequestedSessionId()
+	{
+		if (session instanceof MockHttpSession && ((MockHttpSession)session).isTemporary())
+		{
+			return null;
+		}
+		return session.getId();
+	}
+
+	/**
+	 * Returns context path and servlet path concatenated, typically
+	 * /applicationClassName/applicationClassName
+	 * 
+	 * @return The path value
+	 * @see javax.servlet.http.HttpServletRequest#getRequestURI()
+	 */
+	public String getRequestURI()
+	{
+		if (url == null)
+		{
+			return getContextPath() + getServletPath();
+		}
+		else
+		{
+			int index = url.indexOf("?");
+			if (index != -1)
+			{
+				return url.substring(0, index);
+			}
+		}
+		return url;
+	}
+
+	/**
+	 * Try to build a rough URL.
+	 * 
+	 * @return The url
+	 */
+	public StringBuffer getRequestURL()
+	{
+		final StringBuffer buf = new StringBuffer();
+		buf.append("http://localhost");
+		buf.append(getContextPath());
+		if (getPathInfo() != null)
+		{
+			buf.append(getPathInfo());
+		}
+
+		final String query = getQueryString();
+		if (query != null)
+		{
+			buf.append('?');
+			buf.append(query);
+		}
+		return buf;
+	}
+
+	/**
+	 * Get the scheme.
+	 * 
+	 * @return Always http
+	 */
+	public String getScheme()
+	{
+		return "http";
+	}
+
+	/**
+	 * Get the server name.
+	 * 
+	 * @return Always localhost
+	 */
+	public String getServerName()
+	{
+		return "localhost";
+	}
+
+	/**
+	 * Get the server port.
+	 * 
+	 * @return Always 80
+	 */
+	public int getServerPort()
+	{
+		return 80;
+	}
+
+	/**
+	 * The servlet path may either be the application name or /. For test purposes we always return
+	 * the servlet name.
+	 * 
+	 * @return The servlet path
+	 */
+	public String getServletPath()
+	{
+		return getContextPath();
+	}
+
+	/**
+	 * Get the sessions.
+	 * 
+	 * @return The session
+	 */
+	public HttpSession getSession()
+	{
+		if (session instanceof MockHttpSession && ((MockHttpSession)session).isTemporary())
+		{
+			return null;
+		}
+		return session;
+	}
+
+	/**
+	 * Get the session.
+	 * 
+	 * @param b
+	 *            Ignored, there is always a session
+	 * @return The session
+	 */
+	public HttpSession getSession(boolean b)
+	{
+		if (b && session instanceof MockHttpSession)
+		{
+			((MockHttpSession)session).setTemporary(false);
+		}
+		return getSession();
+	}
+
+	/**
+	 * Get the user principal.
+	 * 
+	 * @return A user principal
+	 */
+	public Principal getUserPrincipal()
+	{
+		final String user = getRemoteUser();
+		if (user == null)
+		{
+			return null;
+		}
+		else
+		{
+			return new Principal()
+			{
+				public String getName()
+				{
+					return user;
+				}
+			};
+		}
+	}
+
+	/**
+	 * @return True if there has been added files to this request using
+	 *         {@link #addFile(String, File, String)}
+	 */
+	public boolean hasUploadedFiles()
+	{
+		return uploadedFiles != null;
+	}
+
+	/**
+	 * Reset the request back to a default state.
+	 */
+	public void initialize()
+	{
+		authType = null;
+		method = "post";
+		cookies.clear();
+		setDefaultHeaders();
+		path = null;
+		url = null;
+		characterEncoding = "UTF-8";
+		parameters.clear();
+		attributes.clear();
+	}
+
+	/**
+	 * Check whether session id is from a cookie. Always returns true.
+	 * 
+	 * @return Always true
+	 */
+	public boolean isRequestedSessionIdFromCookie()
+	{
+		return true;
+	}
+
+	/**
+	 * Check whether session id is from a url rewrite. Always returns false.
+	 * 
+	 * @return Always false
+	 */
+	public boolean isRequestedSessionIdFromUrl()
+	{
+		return false;
+	}
+
+	/**
+	 * Check whether session id is from a url rewrite. Always returns false.
+	 * 
+	 * @return Always false
+	 */
+	public boolean isRequestedSessionIdFromURL()
+	{
+		return false;
+	}
+
+	/**
+	 * Check whether the session id is valid.
+	 * 
+	 * @return Always true
+	 */
+	public boolean isRequestedSessionIdValid()
+	{
+		return true;
+	}
+
+	/**
+	 * Always returns false.
+	 * 
+	 * @return Always false
+	 */
+	public boolean isSecure()
+	{
+		return false;
+	}
+
+	/**
+	 * NOT IMPLEMENTED.
+	 * 
+	 * @param name
+	 *            The role name
+	 * @return Always false
+	 */
+	public boolean isUserInRole(String name)
+	{
+		return false;
+	}
+
+	/**
+	 * Remove the given attribute.
+	 * 
+	 * @param name
+	 *            The name of the attribute
+	 */
+	public void removeAttribute(final String name)
+	{
+		attributes.remove(name);
+	}
+
+	/**
+	 * Set the given attribute.
+	 * 
+	 * @param name
+	 *            The attribute name
+	 * @param o
+	 *            The value to set
+	 */
+	public void setAttribute(final String name, final Object o)
+	{
+		attributes.put(name, o);
+	}
+
+	/**
+	 * Set the auth type.
+	 * 
+	 * @param authType
+	 *            The auth type
+	 */
+	public void setAuthType(final String authType)
+	{
+		this.authType = authType;
+	}
+
+	/**
+	 * Set the character encoding.
+	 * 
+	 * @param encoding
+	 *            The character encoding
+	 * @throws UnsupportedEncodingException
+	 *             If encoding not supported
+	 */
+	public void setCharacterEncoding(final String encoding) throws UnsupportedEncodingException
+	{
+		characterEncoding = encoding;
+	}
+
+	/**
+	 * Set the cookies.
+	 * 
+	 * @param theCookies
+	 *            The cookies
+	 */
+	public void setCookies(final Cookie[] theCookies)
+	{
+		cookies.clear();
+		for (int i = 0; i < theCookies.length; i++)
+		{
+			cookies.add(theCookies[i]);
+		}
+	}
+
+	/**
+	 * Set the method.
+	 * 
+	 * @param method
+	 *            The method
+	 */
+	public void setMethod(final String method)
+	{
+		this.method = method;
+	}
+
+	/**
+	 * Set a parameter.
+	 * 
+	 * @param name
+	 *            The name
+	 * @param value
+	 *            The value
+	 */
+	public void setParameter(final String name, final String value)
+	{
+		parameters.put(name, value);
+	}
+
+	/**
+	 * Sets a map of parameters.
+	 * 
+	 * @param parameters
+	 *            the parameters to set
+	 */
+	public void setParameters(final Map<String, String[]> parameters)
+	{
+		this.parameters.putAll(parameters);
+	}
+
+	/**
+	 * Set the path that this request is supposed to be serving. The path is relative to the web
+	 * application root and should start with a / character
+	 * 
+	 * @param path
+	 */
+	public void setPath(final String path)
+	{
+		this.path = WicketURLDecoder.PATH_INSTANCE.decode(path);
+	}
+
+	/**
+	 * Set the complete url for this request. The url will be analyzed.
+	 * 
+	 * @param url
+	 */
+	public void setURL(String url)
+	{
+		if (url.startsWith("http://"))
+		{
+			int index = url.indexOf("/", 7);
+			url = url.substring(index);
+		}
+		if (!url.startsWith("/"))
+		{
+			url = getContextPath() + getServletPath() + "/" + url;
+		}
+		this.url = url;
+		if (url.startsWith(getContextPath()))
+		{
+			url = url.substring(getContextPath().length());
+		}
+		if (url.startsWith(getServletPath()))
+		{
+			url = url.substring(getServletPath().length());
+		}
+
+		int index = url.indexOf("?");
+		if (index == -1)
+		{
+			setPath(url);
+		}
+		else
+		{
+			setPath(url.substring(0, index));
+
+			String queryString = url.substring(index + 1);
+			Map<String, String[]> params = new HashMap<String, String[]>();
+			RequestUtils.decodeUrlParameters(queryString, params);
+			parameters.putAll(params);
+		}
+	}
+
+// /**
+// * Initialize the request parameters to point to the given bookmarkable page.
+// *
+// * @param page
+// * The page to point to
+// * @param params
+// * Additional parameters
+// */
+// public void setRequestToBookmarkablePage(final Page page, final Map<String, Object> params)
+// {
+// parameters.putAll(params);
+// parameters.put(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME, page.getClass()
+// .getName());
+// }
+//
+// /**
+// * Initialize the request parameters to point to the given component.
+// *
+// * @param component
+// * The component
+// */
+// public void setRequestToComponent(final Component component)
+// {
+// final IPageMap pageMap = component.getPage().getPageMap();
+// final String pageMapName = pageMap.isDefault() ? "" : pageMap.getName();
+// if (component instanceof BookmarkablePageLink)
+// {
+// final Class<? extends Page> clazz = ((BookmarkablePageLink<?>)component).getPageClass();
+// parameters.put(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME, pageMapName +
+// ':' + clazz.getName());
+// }
+// else
+// {
+// int version = component.getPage().getCurrentVersionNumber();
+// Class<?> clazz = null;
+// if (component instanceof IRedirectListener)
+// {
+// clazz = IRedirectListener.class;
+// }
+// else if (component instanceof IResourceListener)
+// {
+// clazz = IResourceListener.class;
+// }
+// else if (component instanceof IFormSubmitListener)
+// {
+// clazz = IFormSubmitListener.class;
+// }
+// else if (component instanceof ILinkListener)
+// {
+// clazz = ILinkListener.class;
+// }
+// else if (component instanceof IOnChangeListener)
+// {
+// clazz = IOnChangeListener.class;
+// }
+// else
+// {
+// throw new IllegalArgumentException(
+// "The component class doesn't seem to implement any of the known *Listener interfaces: " +
+// component.getClass());
+// }
+//
+// // manually create the url using default strategy and format
+// parameters.put(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME, pageMapName + ':' +
+// component.getPath() + ':' + (version == 0 ? "" : "" + version) + ':' +
+// Classes.simpleName(clazz) + "::");
+//
+// // see if we can replace our manual listener url with a properly generated one...
+//
+// try
+// {
+// RequestListenerInterface rli = (RequestListenerInterface)clazz.getField("INTERFACE")
+// .get(clazz);
+//
+// String auto = component.getRequestCycle().urlFor(component, rli).toString();
+//
+// // check for crypted strategy
+// if (auto.startsWith("?x="))
+// {
+// auto = auto.substring(3);
+// parameters.put("x", auto);
+// parameters.remove(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME);
+// }
+// else
+// {
+// int idx = auto.indexOf(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME);
+// if (idx >= 0)
+// {
+// auto = auto.substring(idx +
+// WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME.length() + 1);
+// }
+// else
+// {
+// idx = auto.indexOf("&");
+// if (idx >= 0)
+// {
+// auto = auto.substring(0, idx);
+// }
+// }
+// parameters.put(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME, auto);
+// }
+// }
+// catch (Exception e)
+// {
+// // noop
+// }
+//
+// if (component.isStateless() && component.getPage().isBookmarkable())
+// {
+// parameters.put(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME,
+// pageMapName + ':' + component.getPage().getClass().getName());
+// }
+// }
+// }
+
+// /**
+// * Initialize the request parameters to point to the given form component. The additional map
+// * should contain mappings between individual components that appear in the form and the string
+// * value that should be submitted for each of these components.
+// *
+// * @param form
+// * The for to send the request to
+// * @param values
+// * The values for each of the form components
+// */
+// public void setRequestToFormComponent(final Form<?> form, final Map<String, Object> values)
+// {
+// setRequestToComponent(form);
+//
+// final Map<String, Object> valuesApplied = new HashMap<String, Object>();
+// form.visitChildren(FormComponent.class, new Component.IVisitor<FormComponent<?>>()
+// {
+// public Object component(final FormComponent<?> component)
+// {
+// String value = (String)values.get(component);
+// if (value != null)
+// {
+// parameters.put(component.getInputName(), values.get(component));
+// valuesApplied.put(component.getId(), component);
+// }
+// return CONTINUE_TRAVERSAL;
+// }
+// });
+//
+// if (values.size() != valuesApplied.size())
+// {
+// Map<String, Object> diff = new HashMap<String, Object>();
+// diff.putAll(values);
+//
+// Iterator<String> iter = valuesApplied.keySet().iterator();
+// while (iter.hasNext())
+// {
+// diff.remove(iter.next());
+// }
+//
+// log.error("Parameter mismatch: didn't find all components referenced in parameter 'values': " +
+// diff.keySet());
+// }
+// }
+
+	/**
+	 * Initialize the request parameters from the given redirect string that redirects back to a
+	 * particular component for display.
+	 * 
+	 * @param redirect
+	 *            The redirect string to display from
+	 */
+	public void setRequestToRedirectString(final String redirect)
+	{
+		parameters.clear();
+
+		int queryStringPos = redirect.indexOf('?');
+
+		// Decode the parameters
+		if (queryStringPos != -1)
+		{
+			final String queryString = redirect.substring(queryStringPos + 1);
+			RequestUtils.decodeParameters(queryString, parameters);
+		}
+
+		// We need to absolutize the redirect URL as we are not as smart as a web-browser
+		// (WICKET-702)
+		url = redirect;
+		if ((url.length() == 0) || (url.charAt(0) != '/'))
+		{
+			url = getContextPath() + getServletPath() + "/" + redirect;
+		}
+
+		// Remove occurrences of ".." from the path
+		url = RequestUtils.removeDoubleDots(url);
+		log.info("Redirecting to " + url);
+	}
+
+	/**
+	 * Helper method to create some default headers for the request
+	 */
+	private void setDefaultHeaders()
+	{
+		headers.clear();
+		addHeader("Accept", "text/xml,application/xml,application/xhtml+xml,"
+			+ "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
+		addHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
+		Locale l = Locale.getDefault();
+		addHeader("Accept-Language", l.getLanguage().toLowerCase() + "-" +
+			l.getCountry().toLowerCase() + "," + l.getLanguage().toLowerCase() + ";q=0.5");
+		addHeader("User-Agent",
+			"Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2");
+	}
+
+	private static final String crlf = "\r\n";
+	private static final String boundary = "--abcdefgABCDEFG";
+
+	private void newAttachment(OutputStream out) throws IOException
+	{
+		out.write(boundary.getBytes());
+		out.write(crlf.getBytes());
+		out.write("Content-Disposition: form-data".getBytes());
+	}
+
+	/**
+	 * Build the request based on the uploaded files and the parameters.
+	 * 
+	 * @return The request as a string.
+	 */
+	private byte[] buildRequest()
+	{
+		try
+		{
+			// Build up the input stream based on the files and parameters
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+			// Add parameters
+			for (Iterator<String> iterator = parameters.keySet().iterator(); iterator.hasNext();)
+			{
+				final String name = iterator.next();
+				newAttachment(out);
+				out.write("; name=\"".getBytes());
+				out.write(name.getBytes());
+				out.write("\"".getBytes());
+				out.write(crlf.getBytes());
+				out.write(crlf.getBytes());
+				out.write(parameters.get(name).toString().getBytes());
+				out.write(crlf.getBytes());
+			}
+
+			// Add files
+			if (uploadedFiles != null)
+			{
+				for (Iterator<String> iterator = uploadedFiles.keySet().iterator(); iterator.hasNext();)
+				{
+					String fieldName = iterator.next();
+
+					UploadedFile uf = uploadedFiles.get(fieldName);
+
+					newAttachment(out);
+					out.write("; name=\"".getBytes());
+					out.write(fieldName.getBytes());
+					out.write("\"; filename=\"".getBytes());
+					out.write(uf.getFile().getName().getBytes());
+					out.write("\"".getBytes());
+					out.write(crlf.getBytes());
+					out.write("Content-Type: ".getBytes());
+					out.write(uf.getContentType().getBytes());
+					out.write(crlf.getBytes());
+					out.write(crlf.getBytes());
+
+					// Load the file and put it into the the inputstream
+					FileInputStream fis = new FileInputStream(uf.getFile());
+					IOUtils.copy(fis, out);
+					fis.close();
+					out.write(crlf.getBytes());
+				}
+			}
+
+			out.write(boundary.getBytes());
+			out.write("--".getBytes());
+			out.write(crlf.getBytes());
+			return out.toByteArray();
+		}
+		catch (IOException e)
+		{
+			// NOTE: IllegalStateException(Throwable) only exists since Java 1.5
+			throw new WicketRuntimeException(e);
+		}
+	}
+
+	/**
+	 * @return local address
+	 */
+	public String getLocalAddr()
+	{
+		return "127.0.0.1";
+	}
+
+	/**
+	 * @return local host name
+	 */
+	public String getLocalName()
+	{
+		return "127.0.0.1";
+	}
+
+	/**
+	 * @return local port
+	 */
+	public int getLocalPort()
+	{
+		return 80;
+	}
+
+	/**
+	 * @return remote port
+	 */
+	public int getRemotePort()
+	{
+		return 80;
+	}
+}

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java
------------------------------------------------------------------------------
    svn:executable = *

Added: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletResponse.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletResponse.java?rev=917331&view=auto
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletResponse.java (added)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletResponse.java Mon Mar  1 00:01:57 2010
@@ -0,0 +1,820 @@
+/*
+ * 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.mock;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TimeZone;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.wicket.protocol.http.RequestUtils;
+import org.apache.wicket.util.value.ValueMap;
+
+
+/**
+ * Mock servlet response. Implements all of the methods from the standard HttpServletResponse class
+ * plus helper methods to aid viewing the generated response.
+ * 
+ * @author Chris Turner
+ */
+public class MockHttpServletResponse implements HttpServletResponse
+{
+	private static final int MODE_BINARY = 1;
+
+	private static final int MODE_NONE = 0;
+
+	private static final int MODE_TEXT = 2;
+
+	private ByteArrayOutputStream byteStream;
+
+	private String characterEncoding = "UTF-8";
+
+	private int code = HttpServletResponse.SC_OK;
+
+	private final List<Cookie> cookies = new ArrayList<Cookie>();
+
+	private String errorMessage = null;
+
+	private final ValueMap headers = new ValueMap();
+
+	private Locale locale = null;
+
+	private int mode = MODE_NONE;
+
+	private PrintWriter printWriter;
+
+	private String redirectLocation = null;
+
+	private ServletOutputStream servletStream;
+
+	private int status = HttpServletResponse.SC_OK;
+
+	private StringWriter stringWriter;
+
+	private final MockHttpServletRequest servletRequest;
+
+	/**
+	 * Create the response object.
+	 * 
+	 * @param servletRequest
+	 */
+	public MockHttpServletResponse(MockHttpServletRequest servletRequest)
+	{
+		this.servletRequest = servletRequest;
+		initialize();
+	}
+
+	/**
+	 * Add a cookie to the response.
+	 * 
+	 * @param cookie
+	 *            The cookie to add
+	 */
+	public void addCookie(final Cookie cookie)
+	{
+		// remove any potential duplicates
+		cookies.remove(cookie);
+		cookies.add(cookie);
+	}
+
+	/**
+	 * Add a date header.
+	 * 
+	 * @param name
+	 *            The header value
+	 * @param l
+	 *            The long value
+	 */
+	public void addDateHeader(String name, long l)
+	{
+		DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
+		addHeader(name, df.format(new Date(l)));
+	}
+
+	/**
+	 * Add the given header value, including an additional entry if one already exists.
+	 * 
+	 * @param name
+	 *            The name for the header
+	 * @param value
+	 *            The value for the header
+	 */
+	@SuppressWarnings("unchecked")
+	public void addHeader(final String name, final String value)
+	{
+		List<String> list = (List<String>)headers.get(name);
+		if (list == null)
+		{
+			list = new ArrayList<String>(1);
+			headers.put(name, list);
+		}
+		list.add(value);
+	}
+
+	/**
+	 * Add an int header value.
+	 * 
+	 * @param name
+	 *            The header name
+	 * @param i
+	 *            The value
+	 */
+	public void addIntHeader(final String name, final int i)
+	{
+		addHeader(name, "" + i);
+	}
+
+	/**
+	 * Check if the response contains the given header name.
+	 * 
+	 * @param name
+	 *            The name to check
+	 * @return Whether header in response or not
+	 */
+	public boolean containsHeader(final String name)
+	{
+		return headers.containsKey(name);
+	}
+
+	/**
+	 * Encode the redirectLocation URL. Does no changes as this test implementation uses cookie
+	 * based url tracking.
+	 * 
+	 * @param url
+	 *            The url to encode
+	 * @return The encoded url
+	 */
+	public String encodeRedirectUrl(final String url)
+	{
+		return url;
+	}
+
+	/**
+	 * Encode the redirectLocation URL. Does no changes as this test implementation uses cookie
+	 * based url tracking.
+	 * 
+	 * @param url
+	 *            The url to encode
+	 * @return The encoded url
+	 */
+	public String encodeRedirectURL(final String url)
+	{
+		return url;
+	}
+
+	/**
+	 * Encode the URL. Does no changes as this test implementation uses cookie based url tracking.
+	 * 
+	 * @param url
+	 *            The url to encode
+	 * @return The encoded url
+	 */
+	public String encodeUrl(final String url)
+	{
+		return url;
+	}
+
+	/**
+	 * Encode the URL. Does no changes as this test implementation uses cookie based url tracking.
+	 * 
+	 * @param url
+	 *            The url to encode
+	 * @return The encoded url
+	 */
+	public String encodeURL(final String url)
+	{
+		return url;
+	}
+
+	/**
+	 * Flush the buffer.
+	 * 
+	 * @throws IOException
+	 */
+	public void flushBuffer() throws IOException
+	{
+	}
+
+	/**
+	 * Get the binary content that was written to the servlet stream.
+	 * 
+	 * @return The binary content
+	 */
+	public byte[] getBinaryContent()
+	{
+		return byteStream.toByteArray();
+	}
+
+	/**
+	 * Return the current buffer size
+	 * 
+	 * @return The buffer size
+	 */
+	public int getBufferSize()
+	{
+		if (mode == MODE_NONE)
+		{
+			return 0;
+		}
+		else if (mode == MODE_BINARY)
+		{
+			return byteStream.size();
+		}
+		else
+		{
+			return stringWriter.getBuffer().length();
+		}
+	}
+
+	/**
+	 * Get the character encoding of the response.
+	 * 
+	 * @return The character encoding
+	 */
+	public String getCharacterEncoding()
+	{
+		return characterEncoding;
+	}
+
+	/**
+	 * Get the response code for this request.
+	 * 
+	 * @return The response code
+	 */
+	public int getCode()
+	{
+		return code;
+	}
+
+	/**
+	 * Get all of the cookies that have been added to the response.
+	 * 
+	 * @return The collection of cookies
+	 */
+	public Collection<Cookie> getCookies()
+	{
+		return cookies;
+	}
+
+	/**
+	 * Get the text document that was written as part of this response.
+	 * 
+	 * @return The document
+	 */
+	public String getDocument()
+	{
+		if (mode == MODE_BINARY)
+		{
+			return new String(byteStream.toByteArray());
+		}
+		else
+		{
+			return stringWriter.getBuffer().toString();
+		}
+	}
+
+	/**
+	 * Get the error message.
+	 * 
+	 * @return The error message, or null if no message
+	 */
+	public String getErrorMessage()
+	{
+		return errorMessage;
+	}
+
+	/**
+	 * Return the value of the given named header.
+	 * 
+	 * @param name
+	 *            The header name
+	 * @return The value, or null
+	 */
+	@SuppressWarnings("unchecked")
+	public String getHeader(final String name)
+	{
+		List<String> l = (List<String>)headers.get(name);
+		if (l == null || l.size() < 1)
+		{
+			return null;
+		}
+		else
+		{
+			return l.get(0);
+		}
+	}
+
+	/**
+	 * Get the names of all of the headers.
+	 * 
+	 * @return The header names
+	 */
+	public Set<String> getHeaderNames()
+	{
+		return headers.keySet();
+	}
+
+	/**
+	 * Get the encoded locale
+	 * 
+	 * @return The locale
+	 */
+	public Locale getLocale()
+	{
+		return locale;
+	}
+
+	/**
+	 * Get the output stream for writing binary data from the servlet.
+	 * 
+	 * @return The binary output stream.
+	 */
+	public ServletOutputStream getOutputStream()
+	{
+		if (mode == MODE_TEXT)
+		{
+			throw new IllegalArgumentException("Can't write binary after already selecting text");
+		}
+		mode = MODE_BINARY;
+		return servletStream;
+	}
+
+	/**
+	 * Get the location that was redirected to.
+	 * 
+	 * @return The redirect location, or null if not a redirect
+	 */
+	public String getRedirectLocation()
+	{
+		return redirectLocation;
+	}
+
+	/**
+	 * Get the status code.
+	 * 
+	 * @return The status code
+	 */
+	public int getStatus()
+	{
+		return status;
+	}
+
+	/**
+	 * Get the print writer for writing text output for this response.
+	 * 
+	 * @return The writer
+	 * @throws IOException
+	 *             Not used
+	 */
+	public PrintWriter getWriter() throws IOException
+	{
+		if (mode == MODE_BINARY)
+		{
+			throw new IllegalArgumentException("Can't write text after already selecting binary");
+		}
+		mode = MODE_TEXT;
+		return printWriter;
+	}
+
+	/**
+	 * Reset the response ready for reuse.
+	 */
+	public void initialize()
+	{
+		cookies.clear();
+		headers.clear();
+		code = HttpServletResponse.SC_OK;
+		errorMessage = null;
+		redirectLocation = null;
+		status = HttpServletResponse.SC_OK;
+		characterEncoding = "UTF-8";
+		locale = null;
+
+		byteStream = new ByteArrayOutputStream();
+		servletStream = new ServletOutputStream()
+		{
+			@Override
+			public void write(int b)
+			{
+				byteStream.write(b);
+			}
+		};
+		stringWriter = new StringWriter();
+		printWriter = new PrintWriter(stringWriter)
+		{
+			@Override
+			public void close()
+			{
+				// Do nothing
+			}
+
+			@Override
+			public void flush()
+			{
+				// Do nothing
+			}
+		};
+		mode = MODE_NONE;
+	}
+
+	/**
+	 * Always returns false.
+	 * 
+	 * @return Always false
+	 */
+	public boolean isCommitted()
+	{
+		return false;
+	}
+
+	/**
+	 * Return whether the servlet returned an error code or not.
+	 * 
+	 * @return Whether an error occurred or not
+	 */
+	public boolean isError()
+	{
+		return (code != HttpServletResponse.SC_OK);
+	}
+
+	/**
+	 * Check whether the response was redirected or not.
+	 * 
+	 * @return Whether the state was redirected or not
+	 */
+	public boolean isRedirect()
+	{
+		return (redirectLocation != null);
+	}
+
+	/**
+	 * Delegate to initialize method.
+	 */
+	public void reset()
+	{
+		initialize();
+	}
+
+	/**
+	 * Clears the buffer.
+	 */
+	public void resetBuffer()
+	{
+		if (mode == MODE_BINARY)
+		{
+			byteStream.reset();
+		}
+		else if (mode == MODE_TEXT)
+		{
+			stringWriter.getBuffer().delete(0, stringWriter.getBuffer().length());
+		}
+	}
+
+	/**
+	 * Send an error code. This implementation just sets the internal error state information.
+	 * 
+	 * @param code
+	 *            The code
+	 * @throws IOException
+	 *             Not used
+	 */
+	public void sendError(final int code) throws IOException
+	{
+		this.code = code;
+		errorMessage = null;
+	}
+
+	/**
+	 * Send an error code. This implementation just sets the internal error state information.
+	 * 
+	 * @param code
+	 *            The error code
+	 * @param msg
+	 *            The error message
+	 * @throws IOException
+	 *             Not used
+	 */
+	public void sendError(final int code, final String msg) throws IOException
+	{
+		this.code = code;
+		errorMessage = msg;
+	}
+
+	/**
+	 * @return url
+	 * @see org.apache.wicket.Request#getURL()
+	 */
+	private String getURL()
+	{
+		/*
+		 * Servlet 2.3 specification :
+		 * 
+		 * Servlet Path: The path section that directly corresponds to the mapping which activated
+		 * this request. This path starts with a "/" character except in the case where the request
+		 * is matched with the "/*" pattern, in which case it is the empty string.
+		 * 
+		 * PathInfo: The part of the request path that is not part of the Context Path or the
+		 * Servlet Path. It is either null if there is no extra path, or is a string with a leading
+		 * "/".
+		 */
+		String url = servletRequest.getServletPath();
+		final String pathInfo = servletRequest.getPathInfo();
+
+		if (pathInfo != null)
+		{
+			url += pathInfo;
+		}
+
+		final String queryString = servletRequest.getQueryString();
+
+		if (queryString != null)
+		{
+			url += ("?" + queryString);
+		}
+
+		// If url is non-empty it will start with '/', which we should lose
+		if (url.length() > 0 && url.charAt(0) == '/')
+		{
+			// Remove leading '/'
+			url = url.substring(1);
+		}
+		return url;
+	}
+
+	/**
+	 * Indicate sending of a redirectLocation to a particular named resource. This implementation
+	 * just keeps hold of the redirectLocation info and makes it available for query.
+	 * 
+	 * @param location
+	 *            The location to redirectLocation to
+	 * @throws IOException
+	 *             Not used
+	 */
+	public void sendRedirect(String location) throws IOException
+	{
+		// If the location starts with ../
+		if (location.startsWith("../"))
+		{
+			// Test if the current url has a / in it. (a mount)
+			String url = getURL();
+			int index = url.lastIndexOf("/");
+			if (index != -1)
+			{
+				// Then we have to recalculate what the real redirect is for the next request
+				// which is just getContext() + getServletPath() + "/" + location;
+				url = url.substring(0, index + 1) + location;
+				url = RequestUtils.removeDoubleDots(url);
+
+				// stril the servlet path again from it.
+				index = url.indexOf("/");
+				location = url.substring(index + 1);
+			}
+		}
+		redirectLocation = location;
+	}
+
+	/**
+	 * Method ignored.
+	 * 
+	 * @param size
+	 *            The size
+	 */
+	public void setBufferSize(final int size)
+	{
+	}
+
+	/**
+	 * Set the character encoding.
+	 * 
+	 * @param characterEncoding
+	 *            The character encoding
+	 */
+	public void setCharacterEncoding(final String characterEncoding)
+	{
+		this.characterEncoding = characterEncoding;
+	}
+
+	/**
+	 * Set the content length.
+	 * 
+	 * @param length
+	 *            The length
+	 */
+	public void setContentLength(final int length)
+	{
+		setIntHeader("Content-Length", length);
+	}
+
+	/**
+	 * Set the content type.
+	 * 
+	 * @param type
+	 *            The content type
+	 */
+	public void setContentType(final String type)
+	{
+		setHeader("Content-Type", type);
+	}
+
+	/**
+	 * @return value of content-type header
+	 */
+	public String getContentType()
+	{
+		return getHeader("Content-Type");
+	}
+
+	/**
+	 * Set a date header.
+	 * 
+	 * @param name
+	 *            The header name
+	 * @param l
+	 *            The long value
+	 */
+	public void setDateHeader(final String name, final long l)
+	{
+		setHeader(name, formatDate(l));
+	}
+
+	/**
+	 * @param l
+	 * @return formatted date
+	 */
+	public static String formatDate(long l)
+	{
+		StringBuffer _dateBuffer = new StringBuffer(32);
+		Calendar _calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+		_calendar.setTimeInMillis(l);
+		formatDate(_dateBuffer, _calendar, false);
+		return _dateBuffer.toString();
+	}
+
+	/* BEGIN: This code comes from Jetty 6.1.1 */
+	private static String[] DAYS = { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+	private static String[] MONTHS = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
+			"Sep", "Oct", "Nov", "Dec", "Jan" };
+
+	/**
+	 * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'" or "EEE, dd-MMM-yy HH:mm:ss 'GMT'"for
+	 * cookies
+	 * 
+	 * @param buf
+	 * @param calendar
+	 * @param cookie
+	 */
+	public static void formatDate(StringBuffer buf, Calendar calendar, boolean cookie)
+	{
+		// "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
+		// "EEE, dd-MMM-yy HH:mm:ss 'GMT'", cookie
+
+		int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
+		int day_of_month = calendar.get(Calendar.DAY_OF_MONTH);
+		int month = calendar.get(Calendar.MONTH);
+		int year = calendar.get(Calendar.YEAR);
+		int century = year / 100;
+		year = year % 100;
+
+		int epoch = (int)((calendar.getTimeInMillis() / 1000) % (60 * 60 * 24));
+		int seconds = epoch % 60;
+		epoch = epoch / 60;
+		int minutes = epoch % 60;
+		int hours = epoch / 60;
+
+		buf.append(DAYS[day_of_week]);
+		buf.append(',');
+		buf.append(' ');
+		append2digits(buf, day_of_month);
+
+		if (cookie)
+		{
+			buf.append('-');
+			buf.append(MONTHS[month]);
+			buf.append('-');
+			append2digits(buf, year);
+		}
+		else
+		{
+			buf.append(' ');
+			buf.append(MONTHS[month]);
+			buf.append(' ');
+			append2digits(buf, century);
+			append2digits(buf, year);
+		}
+		buf.append(' ');
+		append2digits(buf, hours);
+		buf.append(':');
+		append2digits(buf, minutes);
+		buf.append(':');
+		append2digits(buf, seconds);
+		buf.append(" GMT");
+	}
+
+	/**
+	 * @param buf
+	 * @param i
+	 */
+	public static void append2digits(StringBuffer buf, int i)
+	{
+		if (i < 100)
+		{
+			buf.append((char)(i / 10 + '0'));
+			buf.append((char)(i % 10 + '0'));
+		}
+	}
+
+	/* END: This code comes from Jetty 6.1.1 */
+
+	/**
+	 * Set the given header value.
+	 * 
+	 * @param name
+	 *            The name for the header
+	 * @param value
+	 *            The value for the header
+	 */
+	public void setHeader(final String name, final String value)
+	{
+		List<String> l = new ArrayList<String>(1);
+		l.add(value);
+		headers.put(name, l);
+	}
+
+	/**
+	 * Set an int header value.
+	 * 
+	 * @param name
+	 *            The header name
+	 * @param i
+	 *            The value
+	 */
+	public void setIntHeader(final String name, final int i)
+	{
+		setHeader(name, "" + i);
+	}
+
+	/**
+	 * Set the locale in the response header.
+	 * 
+	 * @param locale
+	 *            The locale
+	 */
+	public void setLocale(final Locale locale)
+	{
+		this.locale = locale;
+	}
+
+	/**
+	 * Set the status for this response.
+	 * 
+	 * @param status
+	 *            The status
+	 */
+	public void setStatus(final int status)
+	{
+		this.status = status;
+	}
+
+	/**
+	 * Set the status for this response.
+	 * 
+	 * @param status
+	 *            The status
+	 * @param msg
+	 *            The message
+	 * @deprecated
+	 */
+	@Deprecated
+	public void setStatus(final int status, final String msg)
+	{
+		setStatus(status);
+	}
+}
\ No newline at end of file

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletResponse.java
------------------------------------------------------------------------------
    svn:executable = *

Added: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpSession.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpSession.java?rev=917331&view=auto
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpSession.java (added)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpSession.java Mon Mar  1 00:01:57 2010
@@ -0,0 +1,282 @@
+/*
+ * 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.mock;
+
+import java.io.Serializable;
+import java.rmi.server.UID;
+import java.util.Collections;
+import java.util.Enumeration;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+
+import org.apache.wicket.util.value.ValueMap;
+
+
+/**
+ * Mock implementation of the <code>WebSession</code> interface for use by the test harnesses.
+ * 
+ * @author Chris Turner
+ */
+public class MockHttpSession implements HttpSession, Serializable
+{
+	private static final long serialVersionUID = 1L;
+
+	private final ValueMap attributes = new ValueMap();
+
+	private final ServletContext context;
+
+	private final long creationTime = System.currentTimeMillis();
+
+	private final String id = (new UID()).toString().replace(':', '_').replace('-', '_');
+
+	private long lastAccessedTime = 0;
+
+	private boolean temporary = true;
+
+	/**
+	 * Create the session.
+	 * 
+	 * @param context
+	 */
+	public MockHttpSession(final ServletContext context)
+	{
+		this.context = context;
+	}
+
+	/**
+	 * Get the attribute with the given name.
+	 * 
+	 * @param name
+	 *            The attribute name
+	 * @return The value or null
+	 */
+	public Object getAttribute(final String name)
+	{
+		return attributes.get(name);
+	}
+
+	/**
+	 * Get the names of the attributes in the session.
+	 * 
+	 * @return The attribute names
+	 */
+	public Enumeration<String> getAttributeNames()
+	{
+		return Collections.enumeration(attributes.keySet());
+
+	}
+
+	/**
+	 * Get the creation time of the session.
+	 * 
+	 * @return The creation time
+	 */
+	public long getCreationTime()
+	{
+		return creationTime;
+	}
+
+	/**
+	 * Return the id of this session.
+	 * 
+	 * @return The id
+	 */
+	public String getId()
+	{
+		return id;
+	}
+
+	/**
+	 * Get the time the session was last accessed.
+	 * 
+	 * @return The last accessed time
+	 */
+	public long getLastAccessedTime()
+	{
+		return lastAccessedTime;
+	}
+
+	/**
+	 * NOT USED. Sessions never expire in the test harness.
+	 * 
+	 * @return Always returns 0
+	 */
+	public int getMaxInactiveInterval()
+	{
+		return 0;
+	}
+
+	/**
+	 * Return the servlet context for the session.
+	 * 
+	 * @return The servlet context
+	 */
+	public ServletContext getServletContext()
+	{
+		return context;
+	}
+
+	/**
+	 * NOT USED.
+	 * 
+	 * @return Always null
+	 * @deprecated
+	 */
+	@Deprecated
+	public javax.servlet.http.HttpSessionContext getSessionContext()
+	{
+		return null;
+	}
+
+	/**
+	 * Get the value for the given name.
+	 * 
+	 * @param name
+	 *            The name
+	 * @return The value or null
+	 * @deprecated use getAttribute(String) instead
+	 */
+	@Deprecated
+	public Object getValue(final String name)
+	{
+		return getAttribute(name);
+	}
+
+	/**
+	 * Get the names of the values in the session.
+	 * 
+	 * @return The names of the attributes
+	 * @deprecated use getAttributeNames() instead
+	 */
+	@Deprecated
+	public String[] getValueNames()
+	{
+		String[] result = new String[attributes.size()];
+		return attributes.keySet().toArray(result);
+	}
+
+	/**
+	 * Invalidate the session.
+	 */
+	public void invalidate()
+	{
+		attributes.clear();
+	}
+
+	/**
+	 * Check if the session is new.
+	 * 
+	 * @return Always false
+	 */
+	public boolean isNew()
+	{
+		return false;
+	}
+
+	/**
+	 * Set a value.
+	 * 
+	 * @param name
+	 *            The name of the value
+	 * @param o
+	 *            The value
+	 * @deprecated Use setAttribute(String, Object) instead
+	 */
+	@Deprecated
+	public void putValue(final String name, final Object o)
+	{
+		setAttribute(name, o);
+	}
+
+	/**
+	 * Remove an attribute.
+	 * 
+	 * @param name
+	 *            The name of the attribute
+	 */
+	public void removeAttribute(final String name)
+	{
+		attributes.remove(name);
+	}
+
+	/**
+	 * Remove a value.
+	 * 
+	 * @param name
+	 *            The name of the value
+	 * @deprecated Use removeAttribute(String) instead
+	 */
+	@Deprecated
+	public void removeValue(String name)
+	{
+		removeAttribute(name);
+	}
+
+	/**
+	 * Set an attribute.
+	 * 
+	 * @param name
+	 *            The name of the attribute to set
+	 * @param o
+	 *            The value to set
+	 */
+	public void setAttribute(final String name, final Object o)
+	{
+		attributes.put(name, o);
+	}
+
+	/**
+	 * NOT USED. Sessions never expire in the test harness.
+	 * 
+	 * @param i
+	 *            The value
+	 */
+	public void setMaxInactiveInterval(final int i)
+	{
+	}
+
+	/**
+	 * Set the last accessed time for the session.
+	 */
+	public void timestamp()
+	{
+		lastAccessedTime = System.currentTimeMillis();
+	}
+
+	/**
+	 * Indicates the state of the session. Temporary or persisted.
+	 * 
+	 * @return true if this is a temporary session, false otherwise
+	 */
+	public final boolean isTemporary()
+	{
+		return temporary;
+	}
+
+	/**
+	 * Changes the state of this session. Temporary or persisted. Uppon creation all sessions are
+	 * temporary.
+	 * 
+	 * @param temporary
+	 *            trur, for a temporary session, false for a persisted session
+	 */
+	public final void setTemporary(boolean temporary)
+	{
+		this.temporary = temporary;
+	}
+}
\ No newline at end of file

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpSession.java
------------------------------------------------------------------------------
    svn:executable = *