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 <[email protected]>
Authored: Mon Sep 29 23:31:22 2014 +0200
Committer: Jesse Long <[email protected]>
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)}.
         */

Reply via email to