WICKET-6094 Find adequate ResourceReference with mount parameters
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/d0b83efb Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/d0b83efb Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/d0b83efb Branch: refs/heads/lambdas Commit: d0b83efb22997664f797ff5f1fcb7c29e852d952 Parents: ed7c997 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Thu Feb 18 22:52:06 2016 +0100 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Thu Feb 18 22:53:05 2016 +0100 ---------------------------------------------------------------------- .../mapper/AbstractBookmarkableMapper.java | 3 - .../core/request/mapper/ResourceMapper.java | 32 +++- .../MoreSpecificResourceMountPathTest.java | 173 +++++++++++++++++++ .../wicket/request/mapper/AbstractMapper.java | 16 +- 4 files changed, 211 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/d0b83efb/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractBookmarkableMapper.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractBookmarkableMapper.java b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractBookmarkableMapper.java index 420b808..4d34e8c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractBookmarkableMapper.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractBookmarkableMapper.java @@ -201,9 +201,6 @@ public abstract class AbstractBookmarkableMapper extends AbstractComponentMapper */ protected abstract boolean pageMustHaveBeenCreatedBookmarkable(); - /** - * @see IRequestMapper#getCompatibilityScore(Request) - */ @Override public int getCompatibilityScore(Request request) { http://git-wip-us.apache.org/repos/asf/wicket/blob/d0b83efb/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/ResourceMapper.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/ResourceMapper.java b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/ResourceMapper.java index c438319..d89543e 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/ResourceMapper.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/ResourceMapper.java @@ -27,7 +27,6 @@ import org.apache.wicket.request.Request; import org.apache.wicket.request.Url; import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler; import org.apache.wicket.request.http.flow.AbortWithHttpErrorCodeException; -import org.apache.wicket.request.mapper.AbstractMapper; import org.apache.wicket.request.mapper.parameter.INamedParameters; import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder; import org.apache.wicket.request.mapper.parameter.PageParameters; @@ -71,7 +70,7 @@ import org.apache.wicket.util.string.Strings; * * @author Peter Ertl */ -public class ResourceMapper extends AbstractMapper implements IRequestMapper +public class ResourceMapper extends AbstractBookmarkableMapper { // encode page parameters into url + decode page parameters from url private final IPageParametersEncoder parametersEncoder; @@ -111,9 +110,8 @@ public class ResourceMapper extends AbstractMapper implements IRequestMapper public ResourceMapper(String path, ResourceReference resourceReference, IPageParametersEncoder encoder) { - Args.notEmpty(path, "path"); + super(path, encoder); Args.notNull(resourceReference, "resourceReference"); - Args.notNull(encoder, "encoder"); this.resourceReference = resourceReference; mountSegments = getMountSegments(path); @@ -157,9 +155,33 @@ public class ResourceMapper extends AbstractMapper implements IRequestMapper } @Override + protected final UrlInfo parseRequest(final Request request) { + throw new UnsupportedOperationException(); + } + + @Override + protected final Url buildUrl(final UrlInfo info) { + throw new UnsupportedOperationException(); + } + + @Override + protected final boolean pageMustHaveBeenCreatedBookmarkable() { + throw new UnsupportedOperationException(); + } + + @Override public int getCompatibilityScore(Request request) { - return 0; // pages always have priority over resources + int score = super.getCompatibilityScore(request); + if (score > 0) + { + score--; // pages always have priority over resources + } + else + { + score = -1; + } + return score; } @Override http://git-wip-us.apache.org/repos/asf/wicket/blob/d0b83efb/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/MoreSpecificResourceMountPathTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/MoreSpecificResourceMountPathTest.java b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/MoreSpecificResourceMountPathTest.java new file mode 100644 index 0000000..9d5f582 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/MoreSpecificResourceMountPathTest.java @@ -0,0 +1,173 @@ +/* + * 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.core.request.mapper; + +import org.apache.wicket.Application; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.request.cycle.RequestCycle; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.resource.ByteArrayResource; +import org.apache.wicket.request.resource.IResource; +import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.util.string.StringValue; +import org.apache.wicket.util.tester.DummyHomePage; +import org.apache.wicket.util.tester.WicketTester; +import org.junit.Assert; +import org.junit.Test; + +import java.net.URL; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; + +/** + * https://issues.apache.org/jira/browse/WICKET-6094 + */ +public class MoreSpecificResourceMountPathTest +{ + @Test + public void can_use_resource_mounted_without_parameter() + { + WicketTester browser = new WicketTester(new WicketApplication()); + browser.executeUrl(WicketApplication.urlFor("howdy")); + Assert.assertThat(browser.getLastResponseAsString(), is(equalTo("howdy"))); + } + + @Test + public void can_use_resource_mounted_with_parameter() + { + WicketTester browser = new WicketTester(new WicketApplication()); + browser.executeUrl(WicketApplication.urlFor(1L)); + Assert.assertThat(browser.getLastResponseAsString(), is(equalTo("1"))); + } + + public static class WicketApplication extends WebApplication + { + private static final String OWNER_BY_ID_LOADER = "owner-by-id-loader"; + private static final String OWNERS_LISTER = "owners-lister"; + public static final String PARAM_ID = "id"; + public static final String PARAM_NAME = "name"; + + @Override + public Class<? extends WebPage> getHomePage() + { + return DummyHomePage.class; + } + + @Override + public void init() + { + super.init(); + + String path = "/ajax/owners"; // shared by both references + + mountResource(path, new ResourceReference(OWNERS_LISTER) + { + @Override + public IResource getResource() + { + return new DummyResource(PARAM_NAME); + } + }); + + mountResource(path + "/${" + PARAM_ID + "}", new ResourceReference(OWNER_BY_ID_LOADER) + { + @Override + public IResource getResource() + { + return new DummyResource(PARAM_ID); + } + }); + } + + public static String urlFor(String name) + { + return urlFor(name, PARAM_NAME, OWNERS_LISTER); + } + + public static String urlFor(Long id) + { + return urlFor(id, PARAM_ID, OWNER_BY_ID_LOADER); + } + + /** <Test-Helper> + * Generate an {@link URL} to access the mounted resource reference. + * @param value of dummy attribute used to have some testable response output. + * @param parameterName of dummy attribute + * @param resourceReferenceName used to mount instance + * @return {@link CharSequence} url for resource reference + */ + private static String urlFor(Object value, String parameterName, String resourceReferenceName) + { + PageParameters parameters = new PageParameters(); + if (value != null) + { + parameters.set(parameterName, value); + } + ResourceReference resourceReference = findResourceReference(resourceReferenceName); + String string = RequestCycle.get().urlFor(resourceReference, parameters).toString(); + return string; + } + + /** <Test-Helper> + * Find resource reference mounted in application. + * @param name of resource reference used to mount instance + * @return {@link ResourceReference} found + */ + private static ResourceReference findResourceReference(String name) + { + return Application.get() + .getResourceReferenceRegistry() + .getResourceReference( + new ResourceReference.Key( + Application.class.getName(), + name, + null, + null, + null + ), + false, + false + ); + } + + /** <Test-Helper> + * This is only a dummy to be referenced. It is possible to + * exchange this by a mock or whatever. + * + * @author [email protected] + */ + private static class DummyResource extends ByteArrayResource + { + private final String parameterName; + + public DummyResource(String parameterName) + { + super("application/text"); + this.parameterName = parameterName; + } + + @Override + protected byte[] getData(Attributes attributes) + { + StringValue value = attributes.getParameters().get(parameterName); + return value == null ? new byte[0] : value.toString().getBytes(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/d0b83efb/wicket-request/src/main/java/org/apache/wicket/request/mapper/AbstractMapper.java ---------------------------------------------------------------------- diff --git a/wicket-request/src/main/java/org/apache/wicket/request/mapper/AbstractMapper.java b/wicket-request/src/main/java/org/apache/wicket/request/mapper/AbstractMapper.java index 5f5060b..a9f7143 100644 --- a/wicket-request/src/main/java/org/apache/wicket/request/mapper/AbstractMapper.java +++ b/wicket-request/src/main/java/org/apache/wicket/request/mapper/AbstractMapper.java @@ -86,8 +86,7 @@ public abstract class AbstractMapper implements IRequestMapper } /** - * Returns true if the given url starts with specified segments. Segments that contain - * placeholders are not compared. + * Returns true if the given url starts with specified segments. * * @param url * @param segments @@ -105,9 +104,16 @@ public abstract class AbstractMapper implements IRequestMapper for (int i = 0; i < segments.length; ++i) { - if (!segments[i].equals(safeSegmentGetter(urlSegments, i , "")) && - (getPlaceholder(segments[i]) == null && - getOptionalPlaceholder(segments[i]) == null)) + String segment = segments[i]; + String urlSegment = safeSegmentGetter(urlSegments, i, null); + if (urlSegment == null && getOptionalPlaceholder(segment) == null) + { + // if the 'segment' has static value or is mandatory placeholder + return false; + } + else if (!segment.equals(urlSegment) && + (getPlaceholder(segment) == null && + getOptionalPlaceholder(segment) == null)) { return false; }
