You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by jl...@apache.org on 2014/09/29 23:34:19 UTC

[1/2] git commit: Ignore Netbeans formatting config

Repository: wicket
Updated Branches:
  refs/heads/wicket-6.x 734ecfbe1 -> ed07f6b38


Ignore Netbeans formatting config


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/1597703b
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/1597703b
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/1597703b

Branch: refs/heads/wicket-6.x
Commit: 1597703bbc75003f3ec67c34df522de898ee4ed5
Parents: 734ecfb
Author: Jesse Long <jl...@apache.org>
Authored: Mon Sep 29 23:26:44 2014 +0200
Committer: Jesse Long <jl...@apache.org>
Committed: Mon Sep 29 23:26:44 2014 +0200

----------------------------------------------------------------------
 .gitignore | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/1597703b/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index c0d1544..d2f286c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ velocity.log
 *.idea/
 *.iml
 *~
+nb-configuration.xml


[2/2] git commit: WICKET-5698 WebApplication#unmount() unmounts the whole compound mapper if some of its inner ones matches

Posted by jl...@apache.org.
WICKET-5698 WebApplication#unmount() unmounts the whole compound mapper if some of its inner ones matches


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/ed07f6b3
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/ed07f6b3
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/ed07f6b3

Branch: refs/heads/wicket-6.x
Commit: ed07f6b38ff29d3ff46357db8252656ca2cc2b97
Parents: 1597703
Author: Jesse Long <jl...@apache.org>
Authored: Mon Sep 29 23:31:22 2014 +0200
Committer: Jesse Long <jl...@apache.org>
Committed: Mon Sep 29 23:31:22 2014 +0200

----------------------------------------------------------------------
 .../core/request/mapper/CryptoMapper.java       |  17 +-
 .../wicket/protocol/http/WebApplication.java    |  99 +++++++-
 .../wicket/protocol/https/HttpsMapper.java      |  12 +-
 .../wicket/util/tester/BaseWicketTester.java    |   9 +-
 .../protocol/http/WebApplicationTest.java       | 244 +++++++++++++++++++
 .../request/mapper/CompoundRequestMapper.java   |  62 +----
 .../request/mapper/ICompoundRequestMapper.java  |   2 +
 .../request/mapper/IRequestMapperDelegate.java  |  36 +++
 .../mapper/ParentPathReferenceRewriter.java     |   9 +-
 .../mapper/CompoundRequestMapperTest.java       |  64 -----
 10 files changed, 428 insertions(+), 126 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
index 06a10ed..58fc6b6 100755
--- a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/CryptoMapper.java
@@ -24,6 +24,7 @@ import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.IRequestMapper;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.Url;
+import org.apache.wicket.request.mapper.IRequestMapperDelegate;
 import org.apache.wicket.settings.ISecuritySettings;
 import org.apache.wicket.util.IProvider;
 import org.apache.wicket.util.crypt.ICrypt;
@@ -49,7 +50,7 @@ import org.slf4j.LoggerFactory;
  * @author Jesse Long
  * @author svenmeier
  */
-public class CryptoMapper implements IRequestMapper
+public class CryptoMapper implements IRequestMapperDelegate
 {
 	private static final Logger log = LoggerFactory.getLogger(CryptoMapper.class);
 
@@ -145,9 +146,21 @@ public class CryptoMapper implements IRequestMapper
 
 	/**
 	 * @return the wrapped root request mapper
+	 *
+	 * @deprecated Since 6.18.0, to be removed in 7.0.0. Use {@link #getDelegateMapper()} instead.
 	 */
+	@Deprecated
 	protected final IRequestMapper getWrappedMapper()
 	{
+		return getDelegateMapper();
+	}
+
+	/**
+	 * @return the wrapped root request mapper
+	 */
+	@Override
+	public final IRequestMapper getDelegateMapper()
+	{
 		return wrappedMapper;
 	}
 
@@ -321,4 +334,4 @@ public class CryptoMapper implements IRequestMapper
 			return hash;
 		}
 	}
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
index 494e3e8..8d1a79e 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
@@ -17,6 +17,10 @@
 package org.apache.wicket.protocol.http;
 
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Locale;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -62,6 +66,8 @@ import org.apache.wicket.request.handler.render.PageRenderer;
 import org.apache.wicket.request.handler.render.WebPageRenderer;
 import org.apache.wicket.request.http.WebRequest;
 import org.apache.wicket.request.http.WebResponse;
+import org.apache.wicket.request.mapper.ICompoundRequestMapper;
+import org.apache.wicket.request.mapper.IRequestMapperDelegate;
 import org.apache.wicket.request.mapper.mount.MountMapper;
 import org.apache.wicket.request.resource.CssResourceReference;
 import org.apache.wicket.request.resource.JavaScriptResourceReference;
@@ -388,7 +394,98 @@ public abstract class WebApplication extends Application
 		{
 			path = path.substring(1);
 		}
-		getRootRequestMapperAsCompound().unmount(path);
+
+		IRequestMapper mapper = getRootRequestMapper();
+
+		while (mapper instanceof IRequestMapperDelegate)
+		{
+			mapper = ((IRequestMapperDelegate) mapper).getDelegateMapper();
+		}
+
+		/*
+		 * Only attempt to unmount if root request mapper is either a compound, or wraps a compound to avoid leaving the
+		 * application with no mappers installed.
+		 */
+		if (mapper instanceof ICompoundRequestMapper)
+		{
+			final Url url = Url.parse(path);
+
+			Request request = new Request()
+			{
+				@Override
+				public Url getUrl()
+				{
+					return url;
+				}
+
+				@Override
+				public Url getClientUrl()
+				{
+					return url;
+				}
+
+				@Override
+				public Locale getLocale()
+				{
+					return null;
+				}
+
+				@Override
+				public Charset getCharset()
+				{
+					return null;
+				}
+
+				@Override
+				public Object getContainerRequest()
+				{
+					return null;
+				}
+			};
+
+			unmountFromCompound((ICompoundRequestMapper) mapper, request);
+		}
+	}
+
+	/**
+	 * Descends the tree of {@link ICompoundRequestMapper}s and {@link IRequestMapperDelegate}s to find the correct descendant
+	 * to remove.
+	 *
+	 * @param parent
+	 *		The {@link ICompoundRequestMapper} from which to unmount the matching mapper.
+	 * @param request
+	 *		The request used to find the mapper to remove.
+	 */
+	private void unmountFromCompound(ICompoundRequestMapper parent, Request request)
+	{
+		Collection<IRequestMapper> toRemove = new LinkedList<IRequestMapper>();
+
+		for (IRequestMapper mapper : parent)
+		{
+			if (mapper.mapRequest(request) != null)
+			{
+				IRequestMapper actualMapper = mapper;
+
+				while (actualMapper instanceof IRequestMapperDelegate)
+				{
+					actualMapper = ((IRequestMapperDelegate) actualMapper).getDelegateMapper();
+				}
+
+				if (actualMapper instanceof ICompoundRequestMapper)
+				{
+					unmountFromCompound((ICompoundRequestMapper) actualMapper, request);
+				}
+				else
+				{
+					toRemove.add(mapper);
+				}
+			}
+		}
+
+		for (IRequestMapper mapper : toRemove)
+		{
+			parent.remove(mapper);
+		}
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java b/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
index aaa1a3e..391aab0 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/https/HttpsMapper.java
@@ -29,6 +29,7 @@ import org.apache.wicket.request.component.IRequestablePage;
 import org.apache.wicket.request.cycle.RequestCycle;
 import org.apache.wicket.request.http.WebRequest;
 import org.apache.wicket.request.http.WebResponse;
+import org.apache.wicket.request.mapper.IRequestMapperDelegate;
 import org.apache.wicket.util.collections.ClassMetaCache;
 import org.apache.wicket.util.lang.Args;
 
@@ -61,7 +62,7 @@ import org.apache.wicket.util.lang.Args;
  * 
  * @author igor
  */
-public class HttpsMapper implements IRequestMapper
+public class HttpsMapper implements IRequestMapperDelegate
 {
 	private final HttpsConfig config;
 	private final IRequestMapper delegate;
@@ -79,6 +80,15 @@ public class HttpsMapper implements IRequestMapper
 		this.config = config;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public IRequestMapper getDelegateMapper()
+	{
+		return delegate;
+	}
+
 	@Override
 	public final int getCompatibilityScore(Request request)
 	{

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java b/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
index 83c0c4a..4661607 100644
--- a/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
+++ b/wicket-core/src/main/java/org/apache/wicket/util/tester/BaseWicketTester.java
@@ -116,6 +116,7 @@ import org.apache.wicket.request.cycle.RequestCycleContext;
 import org.apache.wicket.request.handler.render.PageRenderer;
 import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
 import org.apache.wicket.request.http.WebResponse;
+import org.apache.wicket.request.mapper.IRequestMapperDelegate;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.request.resource.IResource;
 import org.apache.wicket.request.resource.ResourceReference;
@@ -2758,7 +2759,7 @@ public class BaseWicketTester
 	/**
 	 *
 	 */
-	private class TestRequestMapper implements IRequestMapper
+	private class TestRequestMapper implements IRequestMapperDelegate
 	{
 		private final IRequestMapper delegate;
 
@@ -2768,6 +2769,12 @@ public class BaseWicketTester
 		}
 
 		@Override
+		public IRequestMapper getDelegateMapper()
+		{
+			return delegate;
+		}
+
+		@Override
 		public int getCompatibilityScore(Request request)
 		{
 			return delegate.getCompatibilityScore(request);

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebApplicationTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebApplicationTest.java b/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebApplicationTest.java
new file mode 100644
index 0000000..4371c72
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/protocol/http/WebApplicationTest.java
@@ -0,0 +1,244 @@
+/*
+ * 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 java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.Locale;
+import org.apache.wicket.WicketTestCase;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.IRequestMapper;
+import org.apache.wicket.request.Request;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.handler.EmptyRequestHandler;
+import org.apache.wicket.request.mapper.CompoundRequestMapper;
+import org.apache.wicket.request.mapper.ICompoundRequestMapper;
+import org.apache.wicket.request.mapper.IRequestMapperDelegate;
+import org.junit.Test;
+
+/**
+ * Test WebApplication
+ */
+public class WebApplicationTest extends WicketTestCase
+{
+	private static final String MOUNT_PATH_1 = "mount/path/1";
+	private static final String MOUNT_PATH_2 = "mount/path/2";
+	private static final String MOUNT_PATH_3 = "mount/path/3";
+	private static final String MOUNT_PATH_4 = "mount/path/4";
+
+	/**
+	 * Test basic unmounting from a compound mapper.
+	 */
+	@Test
+	public void testUnmountSimple()
+	{
+		CompoundRequestMapper compound = new CompoundRequestMapper();
+
+		compound.add(tester.getApplication().getRootRequestMapper());
+
+		compound.add(new MountMapper(MOUNT_PATH_1, new EmptyRequestHandler()));
+		compound.add(new MountMapper(MOUNT_PATH_2, new EmptyRequestHandler()));
+		compound.add(new MountMapper(MOUNT_PATH_3, new EmptyRequestHandler()));
+
+		tester.getApplication().setRootRequestMapper(compound);
+
+		tester.getApplication().unmount(MOUNT_PATH_1);
+
+		assertEquals("Compound size should be 3", 3, getCompoundRequestMapperSize(compound));
+
+		assertNull("Mount path 1 should not be mounted",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_1)));
+
+		assertTrue("Mount path 2 should match",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_2)) instanceof EmptyRequestHandler);
+
+		assertTrue("Mount path 3 should match",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_3)) instanceof EmptyRequestHandler);
+	}
+
+	/**
+	 * See https://issues.apache.org/jira/browse/WICKET-5698
+	 */
+	@Test
+	public void testUnmountComplex()
+	{
+		CompoundRequestMapper nestedCompound = new CompoundRequestMapper();
+
+		nestedCompound.add(tester.getApplication().getRootRequestMapper());
+
+		nestedCompound.add(new MountMapper(MOUNT_PATH_1, new EmptyRequestHandler()));
+		nestedCompound.add(new MountMapper(MOUNT_PATH_2, new EmptyRequestHandler()));
+
+		CompoundRequestMapper rootCompound = new CompoundRequestMapper();
+
+		rootCompound.add(new SimpleRequestMapperDelegate(nestedCompound));
+
+		rootCompound.add(new MountMapper(MOUNT_PATH_3, new EmptyRequestHandler()));
+		rootCompound.add(new MountMapper(MOUNT_PATH_4, new EmptyRequestHandler()));
+
+		tester.getApplication().setRootRequestMapper(new SimpleRequestMapperDelegate(rootCompound));
+
+		tester.getApplication().unmount(MOUNT_PATH_1);
+
+		assertEquals("Compound size should be 2", 2, getCompoundRequestMapperSize(nestedCompound));
+
+		assertNull("Mount path 1 should not be mounted",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_1)));
+
+		assertTrue("Mount path 2 should match",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_2)) instanceof EmptyRequestHandler);
+
+		assertTrue("Mount path 3 should match",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_3)) instanceof EmptyRequestHandler);
+
+		assertTrue("Mount path 4 should match",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_4)) instanceof EmptyRequestHandler);
+
+		tester.getApplication().unmount(MOUNT_PATH_3);
+
+		assertNull("Mount path 1 should not be mounted",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_1)));
+
+		assertTrue("Mount path 2 should match",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_2)) instanceof EmptyRequestHandler);
+
+		assertNull("Mount path 3 should not be mounted",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_3)));
+
+		assertTrue("Mount path 4 should match",
+			tester.getApplication().getRootRequestMapper().mapRequest(createMockRequest(MOUNT_PATH_4)) instanceof EmptyRequestHandler);
+	}
+
+	private static Request createMockRequest(String path)
+	{
+		final Url url = Url.parse(path);
+
+		return new Request()
+		{
+			@Override
+			public Url getUrl()
+			{
+				return url;
+			}
+
+			@Override
+			public Url getClientUrl()
+			{
+				return url;
+			}
+
+			@Override
+			public Locale getLocale()
+			{
+				return null;
+			}
+
+			@Override
+			public Charset getCharset()
+			{
+				return null;
+			}
+
+			@Override
+			public Object getContainerRequest()
+			{
+				return null;
+			}
+		};
+	}
+
+	private static int getCompoundRequestMapperSize(ICompoundRequestMapper compound)
+	{
+		int retv = 0;
+
+		for (Iterator<IRequestMapper> it = compound.iterator(); it.hasNext();)
+		{
+			it.next();
+			retv++;
+		}
+
+		return retv;
+	}
+
+	private static class MountMapper implements IRequestMapper
+	{
+		private final String path;
+		private final IRequestHandler handler;
+
+		public MountMapper(String path, EmptyRequestHandler handler)
+		{
+			this.path = path;
+			this.handler = handler;
+		}
+
+		@Override
+		public IRequestHandler mapRequest(Request request)
+		{
+			if (request.getUrl().toString().equals(path))
+			{
+				return handler;
+			}
+			return null;
+		}
+
+		@Override
+		public int getCompatibilityScore(Request request)
+		{
+			return 0;
+		}
+
+		@Override
+		public Url mapHandler(IRequestHandler requestHandler)
+		{
+			return null;
+		}
+	}
+
+	private static class SimpleRequestMapperDelegate implements IRequestMapperDelegate
+	{
+		private final IRequestMapper delegate;
+
+		public SimpleRequestMapperDelegate(IRequestMapper delegate)
+		{
+			this.delegate = delegate;
+		}
+
+		@Override
+		public IRequestMapper getDelegateMapper()
+		{
+			return delegate;
+		}
+
+		@Override
+		public IRequestHandler mapRequest(Request request)
+		{
+			return delegate.mapRequest(request);
+		}
+
+		@Override
+		public int getCompatibilityScore(Request request)
+		{
+			return delegate.getCompatibilityScore(request);
+		}
+
+		@Override
+		public Url mapHandler(IRequestHandler requestHandler)
+		{
+			return delegate.mapHandler(requestHandler);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-request/src/main/java/org/apache/wicket/request/mapper/CompoundRequestMapper.java
----------------------------------------------------------------------
diff --git a/wicket-request/src/main/java/org/apache/wicket/request/mapper/CompoundRequestMapper.java b/wicket-request/src/main/java/org/apache/wicket/request/mapper/CompoundRequestMapper.java
index c950279..fa81329 100644
--- a/wicket-request/src/main/java/org/apache/wicket/request/mapper/CompoundRequestMapper.java
+++ b/wicket-request/src/main/java/org/apache/wicket/request/mapper/CompoundRequestMapper.java
@@ -243,64 +243,14 @@ public class CompoundRequestMapper implements ICompoundRequestMapper
 		return mappers.iterator();
 	}
 
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @deprecated since 6.18.0. To be removed in Wicket 7.0.0. See {@code WebApplication.unmount()}.
+	 */
+	@Deprecated
 	@Override
 	public void unmount(String path)
 	{
-		final Url url = Url.parse(path);
-		final Request request = createRequest(url);
-
-		for (IRequestMapper mapper : this)
-		{
-			if (mapper instanceof ICompoundRequestMapper)
-			{
-				ICompoundRequestMapper inner = (ICompoundRequestMapper) mapper;
-				inner.unmount(path);
-			}
-			else if (mapper.mapRequest(request) != null)
-			{
-				remove(mapper);
-			}
-		}
-	}
-
-	int size()
-	{
-		return mappers.size();
-	}
-
-	Request createRequest(final Url url)
-	{
-		return new Request()
-		{
-			@Override
-			public Url getUrl()
-			{
-				return url;
-			}
-
-			@Override
-			public Locale getLocale()
-			{
-				return null;
-			}
-
-			@Override
-			public Object getContainerRequest()
-			{
-				return null;
-			}
-
-			@Override
-			public Url getClientUrl()
-			{
-				return url;
-			}
-
-			@Override
-			public Charset getCharset()
-			{
-				return null;
-			}
-		};
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-request/src/main/java/org/apache/wicket/request/mapper/ICompoundRequestMapper.java
----------------------------------------------------------------------
diff --git a/wicket-request/src/main/java/org/apache/wicket/request/mapper/ICompoundRequestMapper.java b/wicket-request/src/main/java/org/apache/wicket/request/mapper/ICompoundRequestMapper.java
index 0bb235c..bf98577 100755
--- a/wicket-request/src/main/java/org/apache/wicket/request/mapper/ICompoundRequestMapper.java
+++ b/wicket-request/src/main/java/org/apache/wicket/request/mapper/ICompoundRequestMapper.java
@@ -47,6 +47,8 @@ public interface ICompoundRequestMapper extends IRequestMapper, Iterable<IReques
 	 * 
 	 * @param path
 	 *            the path to unmount
+	 * @deprecated since 6.18.0. To be removed in Wicket 7.0.0. See {@code WebApplication.unmount()}.
 	 */
+	@Deprecated
 	void unmount(String path);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-request/src/main/java/org/apache/wicket/request/mapper/IRequestMapperDelegate.java
----------------------------------------------------------------------
diff --git a/wicket-request/src/main/java/org/apache/wicket/request/mapper/IRequestMapperDelegate.java b/wicket-request/src/main/java/org/apache/wicket/request/mapper/IRequestMapperDelegate.java
new file mode 100644
index 0000000..175deca
--- /dev/null
+++ b/wicket-request/src/main/java/org/apache/wicket/request/mapper/IRequestMapperDelegate.java
@@ -0,0 +1,36 @@
+/*
+ * 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.mapper;
+
+import org.apache.wicket.request.IRequestMapper;
+
+/**
+ * A interface to be implemented by {@link IRequestMapper}s that delegate to other {@link IRequestMapper}s.
+ * This allows the application to traverse the tree of request mappers to find a mounted mapper to remove
+ * when unmounting mounted mappers.
+ *
+ * @author Jesse Long
+ */
+public interface IRequestMapperDelegate extends IRequestMapper
+{
+	/**
+	 * Returns the delegate {@link IRequestMapper}.
+	 *
+	 * @return The delegate {@link IRequestMapper}.
+	 */
+	IRequestMapper getDelegateMapper();
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-request/src/main/java/org/apache/wicket/request/mapper/ParentPathReferenceRewriter.java
----------------------------------------------------------------------
diff --git a/wicket-request/src/main/java/org/apache/wicket/request/mapper/ParentPathReferenceRewriter.java b/wicket-request/src/main/java/org/apache/wicket/request/mapper/ParentPathReferenceRewriter.java
index c786685..5f569e4 100755
--- a/wicket-request/src/main/java/org/apache/wicket/request/mapper/ParentPathReferenceRewriter.java
+++ b/wicket-request/src/main/java/org/apache/wicket/request/mapper/ParentPathReferenceRewriter.java
@@ -29,7 +29,7 @@ import org.apache.wicket.util.lang.Args;
  * 
  * @author igor.vaynberg
  */
-public class ParentPathReferenceRewriter implements IRequestMapper
+public class ParentPathReferenceRewriter implements IRequestMapperDelegate
 {
 	private final IProvider<String> escapeSequence;
 	private final IRequestMapper chain;
@@ -108,4 +108,11 @@ public class ParentPathReferenceRewriter implements IRequestMapper
 	{
 		return chain.getCompatibilityScore(request);
 	}
+
+	/** {@inheritDoc} */
+	@Override
+	public IRequestMapper getDelegateMapper()
+	{
+		return chain;
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/ed07f6b3/wicket-request/src/test/java/org/apache/wicket/request/mapper/CompoundRequestMapperTest.java
----------------------------------------------------------------------
diff --git a/wicket-request/src/test/java/org/apache/wicket/request/mapper/CompoundRequestMapperTest.java b/wicket-request/src/test/java/org/apache/wicket/request/mapper/CompoundRequestMapperTest.java
index e449362..977edf7 100644
--- a/wicket-request/src/test/java/org/apache/wicket/request/mapper/CompoundRequestMapperTest.java
+++ b/wicket-request/src/test/java/org/apache/wicket/request/mapper/CompoundRequestMapperTest.java
@@ -16,10 +16,7 @@
  */
 package org.apache.wicket.request.mapper;
 
-import org.apache.wicket.request.Url;
-import org.apache.wicket.request.handler.EmptyRequestHandler;
 import org.apache.wicket.request.mapper.CompoundRequestMapper.MapperWithScore;
-import org.apache.wicket.request.mapper.mount.MountMapper;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -28,67 +25,6 @@ import org.junit.Test;
  */
 public class CompoundRequestMapperTest extends Assert
 {
-
-	private static final String MOUNT_PATH_3 = "mount/path/3";
-	private static final String MOUNT_PATH_2 = "mount/path/2";
-	private static final String MOUNT_PATH_1 = "mount/path/1";
-
-	@Test
-	public void unmount()
-	{
-		CompoundRequestMapper compound = new CompoundRequestMapper();
-
-		compound.add(new MountMapper(MOUNT_PATH_1, new EmptyRequestHandler()));
-		compound.add(new MountMapper(MOUNT_PATH_2, new EmptyRequestHandler()));
-		compound.add(new MountMapper(MOUNT_PATH_3, new EmptyRequestHandler()));
-
-		assertEquals(3, compound.size());
-
-		compound.unmount(MOUNT_PATH_2);
-		assertEquals(2, compound.size());
-
-		assertTrue(
-			"Mount path 1 should match",
-			compound.mapRequest(compound.createRequest(Url.parse(MOUNT_PATH_1))) instanceof EmptyRequestHandler);
-		assertNull("Mount path 2 should not match",
-			compound.mapRequest(compound.createRequest(Url.parse(MOUNT_PATH_2))));
-		assertTrue(
-			"Mount path 3 should match",
-			compound.mapRequest(compound.createRequest(Url.parse(MOUNT_PATH_3))) instanceof EmptyRequestHandler);
-	}
-
-	/**
-	 * https://issues.apache.org/jira/browse/WICKET-5698
-	 */
-	@Test
-	public void unmountNested()
-	{
-		CompoundRequestMapper compound = new CompoundRequestMapper();
-
-		CompoundRequestMapper nestedCompound = new CompoundRequestMapper();
-		compound.add(nestedCompound);
-
-		nestedCompound.add(new MountMapper(MOUNT_PATH_1, new EmptyRequestHandler()));
-		nestedCompound.add(new MountMapper(MOUNT_PATH_2, new EmptyRequestHandler()));
-		nestedCompound.add(new MountMapper(MOUNT_PATH_3, new EmptyRequestHandler()));
-
-		assertEquals(1, compound.size());
-		assertEquals(3, nestedCompound.size());
-
-		compound.unmount(MOUNT_PATH_2);
-		assertEquals(1, compound.size());
-		assertEquals(2, nestedCompound.size());
-
-		assertTrue(
-				"Mount path 1 should match",
-				compound.mapRequest(compound.createRequest(Url.parse(MOUNT_PATH_1))) instanceof EmptyRequestHandler);
-		assertNull("Mount path 2 should not match",
-				compound.mapRequest(compound.createRequest(Url.parse(MOUNT_PATH_2))));
-		assertTrue(
-				"Mount path 3 should match",
-				compound.mapRequest(compound.createRequest(Url.parse(MOUNT_PATH_3))) instanceof EmptyRequestHandler);
-	}
-
 	/**
 	 * Test {@link MapperWithScore#compareTo(MapperWithScore)}.
 	 */