Skip to content

Commit 95adf1d

Browse files
committed
fixed Portlet request mapping priorities in cross-controller case
Issue: SPR-9303 Issue: SPR-9605
1 parent 049b944 commit 95adf1d

File tree

3 files changed

+91
-29
lines changed

3 files changed

+91
-29
lines changed

spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/handler/AbstractMapBasedHandlerMapping.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -76,16 +76,19 @@ protected Object getHandlerInternal(PortletRequest request) throws Exception {
7676
if (handler instanceof Map) {
7777
Map<PortletRequestMappingPredicate, Object> predicateMap =
7878
(Map<PortletRequestMappingPredicate, Object>) handler;
79-
List<PortletRequestMappingPredicate> predicates =
80-
new LinkedList<PortletRequestMappingPredicate>(predicateMap.keySet());
81-
Collections.sort(predicates);
82-
for (PortletRequestMappingPredicate predicate : predicates) {
79+
List<PortletRequestMappingPredicate> filtered = new LinkedList<PortletRequestMappingPredicate>();
80+
for (PortletRequestMappingPredicate predicate : predicateMap.keySet()) {
8381
if (predicate.match(request)) {
84-
predicate.validate(request);
85-
return predicateMap.get(predicate);
82+
filtered.add(predicate);
8683
}
8784
}
88-
return null;
85+
if (filtered.isEmpty()) {
86+
return null;
87+
}
88+
Collections.sort(filtered);
89+
PortletRequestMappingPredicate predicate = filtered.get(0);
90+
predicate.validate(request);
91+
return predicateMap.get(predicate);
8992
}
9093
return handler;
9194
}

spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/DefaultAnnotationHandlerMapping.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ private interface SpecialRequestTypePredicate {
272272

273273
private static abstract class AbstractParameterMappingPredicate implements PortletRequestMappingPredicate {
274274

275-
protected final String[] params;
275+
private final String[] params;
276276

277277
public AbstractParameterMappingPredicate(String[] params) {
278278
this.params = params;
@@ -281,6 +281,17 @@ public AbstractParameterMappingPredicate(String[] params) {
281281
public boolean match(PortletRequest request) {
282282
return PortletAnnotationMappingUtils.checkParameters(this.params, request);
283283
}
284+
285+
protected int compareParams(AbstractParameterMappingPredicate other) {
286+
return new Integer(other.params.length).compareTo(this.params.length);
287+
}
288+
289+
protected int compareParams(Object other) {
290+
if (other instanceof AbstractParameterMappingPredicate) {
291+
return compareParams((AbstractParameterMappingPredicate) other);
292+
}
293+
return 0;
294+
}
284295
}
285296

286297

@@ -318,10 +329,7 @@ public void validate(PortletRequest request) throws PortletException {
318329
}
319330

320331
public int compareTo(Object other) {
321-
if (other instanceof AbstractParameterMappingPredicate) {
322-
return new Integer(((AbstractParameterMappingPredicate) other).params.length).compareTo(this.params.length);
323-
}
324-
return (other instanceof SpecialRequestTypePredicate ? -1 : 0);
332+
return (other instanceof SpecialRequestTypePredicate ? -1 : compareParams(other));
325333
}
326334
}
327335

@@ -336,13 +344,7 @@ public void validate(PortletRequest request) throws PortletException {
336344
}
337345

338346
public int compareTo(Object other) {
339-
if (other instanceof SpecialRequestTypePredicate) {
340-
return 1;
341-
}
342-
else if (other instanceof AbstractParameterMappingPredicate) {
343-
return new Integer(((AbstractParameterMappingPredicate) other).params.length).compareTo(this.params.length);
344-
}
345-
return 0;
347+
return (other instanceof SpecialRequestTypePredicate ? 1 : compareParams(other));
346348
}
347349
}
348350

@@ -378,10 +380,10 @@ else if (other instanceof ActionMappingPredicate) {
378380
return (hasActionName ? -1 : 1);
379381
}
380382
else {
381-
return new Integer(otherAction.params.length).compareTo(this.params.length);
383+
return compareParams(otherAction);
382384
}
383385
}
384-
return (other instanceof SpecialRequestTypePredicate ? 0 : -1);
386+
return (other instanceof SpecialRequestTypePredicate ? compareParams(other) : -1);
385387
}
386388
}
387389

@@ -417,10 +419,10 @@ else if (other instanceof RenderMappingPredicate) {
417419
return (hasWindowState ? -1 : 1);
418420
}
419421
else {
420-
return new Integer(otherRender.params.length).compareTo(this.params.length);
422+
return compareParams(otherRender);
421423
}
422424
}
423-
return (other instanceof SpecialRequestTypePredicate ? 0 : -1);
425+
return (other instanceof SpecialRequestTypePredicate ? compareParams(other) : -1);
424426
}
425427
}
426428

@@ -443,8 +445,8 @@ public void validate(PortletRequest request) {
443445

444446
public int compareTo(Object other) {
445447
if (other instanceof ResourceMappingPredicate) {
446-
boolean hasResourceId = "".equals(this.resourceId);
447-
boolean otherHasResourceId = "".equals(((ResourceMappingPredicate) other).resourceId);
448+
boolean hasResourceId = !"".equals(this.resourceId);
449+
boolean otherHasResourceId = !"".equals(((ResourceMappingPredicate) other).resourceId);
448450
if (hasResourceId != otherHasResourceId) {
449451
return (hasResourceId ? -1 : 1);
450452
}
@@ -478,8 +480,8 @@ public void validate(PortletRequest request) {
478480

479481
public int compareTo(Object other) {
480482
if (other instanceof EventMappingPredicate) {
481-
boolean hasEventName = "".equals(this.eventName);
482-
boolean otherHasEventName = "".equals(((EventMappingPredicate) other).eventName);
483+
boolean hasEventName = !"".equals(this.eventName);
484+
boolean otherHasEventName = !"".equals(((EventMappingPredicate) other).eventName);
483485
if (hasEventName != otherHasEventName) {
484486
return (hasEventName ? -1 : 1);
485487
}

spring-webmvc-portlet/src/test/java/org/springframework/web/portlet/mvc/annotation/Portlet20AnnotationControllerTests.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
import javax.portlet.PortletSession;
3434
import javax.portlet.RenderRequest;
3535
import javax.portlet.RenderResponse;
36+
import javax.portlet.ResourceRequest;
3637
import javax.portlet.ResourceResponse;
3738
import javax.portlet.StateAwareResponse;
3839
import javax.portlet.WindowState;
@@ -694,6 +695,32 @@ protected ApplicationContext createPortletApplicationContext(ApplicationContext
694695
assertEquals("myDefaultResource", resourceResponse.getContentAsString());
695696
}
696697

698+
@Test
699+
public void testPredicatePriorityComparisonAcrossControllers() throws Exception {
700+
DispatcherPortlet portlet = new DispatcherPortlet() {
701+
protected ApplicationContext createPortletApplicationContext(ApplicationContext parent) throws BeansException {
702+
StaticPortletApplicationContext wac = new StaticPortletApplicationContext();
703+
// The order of handler registration is important to get
704+
// the collection with [Render,Action,Render] predicates
705+
wac.registerSingleton("firstController", FirstController.class);
706+
wac.registerSingleton("secondController", SecondController.class);
707+
wac.registerSingleton("handlerMapping", DefaultAnnotationHandlerMapping.class);
708+
wac.registerSingleton("handlerAdapter", AnnotationMethodHandlerAdapter.class);
709+
wac.setPortletContext(new MockPortletContext());
710+
AnnotationConfigUtils.registerAnnotationConfigProcessors(wac);
711+
wac.refresh();
712+
return wac;
713+
}
714+
};
715+
portlet.init(new MockPortletConfig());
716+
717+
// Prepare render request with 'page=baz' parameters
718+
MockRenderRequest request = new MockRenderRequest(PortletMode.VIEW);
719+
MockRenderResponse response = new MockRenderResponse();
720+
request.addParameter("page", "baz");
721+
portlet.render(request, response);
722+
}
723+
697724

698725
/*
699726
* Controllers
@@ -1169,4 +1196,34 @@ public void render(String viewName, Map model, PortletRequest request, MimeRespo
11691196
}
11701197
}
11711198

1199+
1200+
@RequestMapping(value="view")
1201+
public static class FirstController {
1202+
1203+
@RenderMapping
1204+
public String renderBar() {
1205+
throw new UnsupportedOperationException("Should not be called");
1206+
}
1207+
1208+
@ActionMapping("xyz")
1209+
public void processXyz() {
1210+
throw new UnsupportedOperationException("Should not be called");
1211+
}
1212+
}
1213+
1214+
1215+
@RequestMapping(value="view")
1216+
public static class SecondController {
1217+
1218+
@ResourceMapping
1219+
public void processResource(ResourceRequest request, ResourceResponse response) {
1220+
throw new UnsupportedOperationException("Should not be called");
1221+
}
1222+
1223+
@RenderMapping(params="page=baz")
1224+
public String renderBaz() {
1225+
return "SUCCESS";
1226+
}
1227+
}
1228+
11721229
}

0 commit comments

Comments
 (0)