Skip to content

Commit d893a80

Browse files
committed
Merge branch '3.1.x' into 3.2.x
2 parents 3a1dd85 + 938f961 commit d893a80

File tree

5 files changed

+113
-14
lines changed

5 files changed

+113
-14
lines changed

grails-plugin-testing/src/main/groovy/grails/test/mixin/web/UrlMappingsUnitTestMixin.groovy

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import org.grails.gsp.GroovyPagesTemplateEngine
3939
*/
4040
class UrlMappingsUnitTestMixin extends ControllerUnitTestMixin {
4141

42+
public static final String KEY_EXCEPTION = 'exception'
4243
private assertionKeys = ["controller", "action", "view"]
4344

4445
/**
@@ -193,7 +194,12 @@ class UrlMappingsUnitTestMixin extends ControllerUnitTestMixin {
193194
def mappingInfos
194195
if (url instanceof Integer) {
195196
mappingInfos = []
196-
def mapping = mappingsHolder.matchStatusCode(url)
197+
def mapping
198+
if (assertions."$KEY_EXCEPTION") {
199+
mapping = mappingsHolder.matchStatusCode(url, assertions."$KEY_EXCEPTION" as Throwable)
200+
} else {
201+
mapping = mappingsHolder.matchStatusCode(url)
202+
}
197203
if (mapping) mappingInfos << mapping
198204
}
199205
else {

grails-test-suite-uber/src/test/groovy/grails/test/mixin/UrlMappingsTestMixinTests.groovy

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,17 @@ class UrlMappingsTestMixinTests {
166166
assertUrlMapping('/users/timmy', controller: 'user', action: 'update', method: 'put') { name = 'timmy' }
167167
}
168168

169+
@Test
170+
@Issue('https://github.com/grails/grails-core/issues/10226')
171+
void testExceptionUrlMapping() {
172+
mockController(ExceptionTestErrorsController)
173+
mockUrlMappings(ExceptionTestUrlMappings)
174+
175+
assertForwardUrlMapping(500, controller: 'exceptionTestErrors', action: 'handleNullPointer', exception: new NullPointerException())
176+
assertForwardUrlMapping(500, controller: 'exceptionTestErrors', action: 'handleIllegalArgument', exception: new IllegalArgumentException())
177+
assertForwardUrlMapping(500, controller: 'exceptionTestErrors', action: 'handleDefault')
178+
}
179+
169180
@Test
170181
@Issue('https://github.com/grails/grails-core/issues/9065')
171182
void testResourcesUrlMapping() {
@@ -282,3 +293,18 @@ class ResourceTestUrlMappings {
282293
'/person'(resources: 'person')
283294
}
284295
}
296+
297+
@Artefact("Controller")
298+
class ExceptionTestErrorsController {
299+
def handleNullPointer() {}
300+
def handleIllegalArgument() {}
301+
def handleDefault() {}
302+
}
303+
304+
class ExceptionTestUrlMappings {
305+
static mappings = {
306+
'500'(controller: 'exceptionTestErrors', action: 'handleNullPointer', exception: NullPointerException)
307+
'500'(controller: 'exceptionTestErrors', action: 'handleIllegalArgument', exception: IllegalArgumentException)
308+
'500'(controller: 'exceptionTestErrors', action: 'handleDefault')
309+
}
310+
}

grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/DefaultUrlMappingsHolder.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import org.apache.commons.logging.LogFactory;
4747
import org.springframework.core.style.ToStringCreator;
4848
import org.springframework.http.HttpMethod;
49+
import org.springframework.util.AntPathMatcher;
50+
import org.springframework.util.PathMatcher;
4951
import org.springframework.web.context.WebApplicationContext;
5052

5153
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
@@ -66,6 +68,7 @@ public class DefaultUrlMappingsHolder implements UrlMappings {
6668

6769
private static final transient Log LOG = LogFactory.getLog(DefaultUrlMappingsHolder.class);
6870
private static final int DEFAULT_MAX_WEIGHTED_CAPACITY = 5000;
71+
public static final UrlMappingInfo[] EMPTY_RESULTS = new UrlMappingInfo[0];
6972

7073
private int maxWeightedCacheCapacity = DEFAULT_MAX_WEIGHTED_CAPACITY;
7174
private Map<String, UrlMappingInfo> cachedMatches;
@@ -79,20 +82,21 @@ public int weightOf(List<UrlMappingInfo> values) {
7982
}
8083
}
8184

82-
private List<UrlMapping> urlMappings = new ArrayList<UrlMapping>();
85+
private List<UrlMapping> urlMappings = new ArrayList<>();
8386
private UrlMapping[] mappings;
84-
private List excludePatterns;
85-
private Map<UrlMappingKey, UrlMapping> mappingsLookup = new HashMap<UrlMappingKey, UrlMapping>();
86-
private Map<String, UrlMapping> namedMappings = new HashMap<String, UrlMapping>();
87-
private UrlMappingsList mappingsListLookup = new UrlMappingsList();
88-
private Set<String> DEFAULT_NAMESPACE_PARAMS = CollectionUtils.newSet(
89-
UrlMapping.NAMESPACE, UrlMapping.CONTROLLER, UrlMapping.ACTION);
90-
private Set<String> DEFAULT_CONTROLLER_PARAMS = CollectionUtils.newSet(
91-
UrlMapping.CONTROLLER, UrlMapping.ACTION);
92-
private Set<String> DEFAULT_ACTION_PARAMS = CollectionUtils.newSet(UrlMapping.ACTION);
9387
private UrlCreatorCache urlCreatorCache;
9488
// capacity of the UrlCreatoreCache is the estimated number of char's stored in cached objects
9589
private int urlCreatorMaxWeightedCacheCapacity = 160000;
90+
private final List excludePatterns;
91+
private final Map<UrlMappingKey, UrlMapping> mappingsLookup = new HashMap<>();
92+
private final Map<String, UrlMapping> namedMappings = new HashMap<>();
93+
private final UrlMappingsList mappingsListLookup = new UrlMappingsList();
94+
private final Set<String> DEFAULT_NAMESPACE_PARAMS = CollectionUtils.newSet(
95+
UrlMapping.NAMESPACE, UrlMapping.CONTROLLER, UrlMapping.ACTION);
96+
private final Set<String> DEFAULT_CONTROLLER_PARAMS = CollectionUtils.newSet(
97+
UrlMapping.CONTROLLER, UrlMapping.ACTION);
98+
private final Set<String> DEFAULT_ACTION_PARAMS = CollectionUtils.newSet(UrlMapping.ACTION);
99+
private final PathMatcher pathMatcher = new AntPathMatcher();
96100

97101
public DefaultUrlMappingsHolder(List<UrlMapping> mappings) {
98102
this(mappings, null, false);
@@ -359,7 +363,7 @@ private UrlCreator resolveUrlCreator(final String controller,
359363
}
360364
}
361365
if (mapping == null || (mapping instanceof ResponseCodeUrlMapping)) {
362-
Set<String> lookupParams = new HashSet<String>(DEFAULT_NAMESPACE_PARAMS);
366+
Set<String> lookupParams = new HashSet<>(DEFAULT_NAMESPACE_PARAMS);
363367
Set<String> paramKeys = new HashSet<String>(params.keySet());
364368
paramKeys.removeAll(lookupParams);
365369
lookupParams.addAll(paramKeys);
@@ -478,6 +482,8 @@ public UrlMappingInfo[] matchAll(String uri) {
478482
}
479483

480484
public UrlMappingInfo[] matchAll(String uri, String httpMethod) {
485+
if (isExcluded(uri)) return EMPTY_RESULTS;
486+
481487
boolean anyHttpMethod = httpMethod != null && httpMethod.equalsIgnoreCase(UrlMapping.ANY_HTTP_METHOD);
482488
List<UrlMappingInfo> matchingUrls = new ArrayList<UrlMappingInfo>();
483489
UriToUrlMappingKey cacheKey = new UriToUrlMappingKey(uri, httpMethod, UrlMapping.ANY_VERSION);
@@ -506,7 +512,20 @@ public UrlMappingInfo[] matchAll(String uri, String httpMethod) {
506512
return matchingUrls.toArray(new UrlMappingInfo[matchingUrls.size()]);
507513
}
508514

515+
private boolean isExcluded(String uri) {
516+
if(excludePatterns != null) {
517+
for (Object excludePattern : excludePatterns) {
518+
if(pathMatcher.match(excludePattern.toString(), uri)) {
519+
return true;
520+
}
521+
}
522+
}
523+
return false;
524+
}
525+
509526
public UrlMappingInfo[] matchAll(String uri, String httpMethod, String version) {
527+
if (isExcluded(uri)) return EMPTY_RESULTS;
528+
510529
List<UrlMappingInfo> matchingUrls;
511530
UriToUrlMappingKey cacheKey = new UriToUrlMappingKey(uri, httpMethod, version);
512531
if (cachedListMatches.containsKey(cacheKey)) {

grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/mvc/AbstractGrailsControllerUrlMappings.groovy

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,10 @@ abstract class AbstractGrailsControllerUrlMappings implements UrlMappings{
179179
if(info.redirectInfo) {
180180
return info
181181
}
182-
webRequest.resetParams()
183-
info.configure(webRequest)
182+
if(webRequest != null) {
183+
webRequest.resetParams()
184+
info.configure(webRequest)
185+
}
184186
def controllerKey = new ControllerKey(info.namespace, info.controllerName, info.actionName, info.pluginName)
185187
GrailsControllerClass controllerClass = info ? mappingsToGrailsControllerMap.get(controllerKey) : null
186188
if(controllerClass) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.grails.web.mapping
2+
3+
import grails.core.DefaultGrailsApplication
4+
import grails.core.GrailsApplication
5+
import grails.plugins.DefaultGrailsPluginManager
6+
import grails.plugins.GrailsPluginManager
7+
import grails.web.mapping.UrlMappingsHolder
8+
import org.springframework.context.support.GenericApplicationContext
9+
import spock.lang.Specification
10+
11+
/**
12+
* Created by graemerocher on 17/10/16.
13+
*/
14+
class UrlMappingsHolderFactoryBeanSpec extends Specification {
15+
16+
void "test url mappings holder factory bean excludes"() {
17+
given:
18+
UrlMappingsHolderFactoryBean factoryBean = new UrlMappingsHolderFactoryBean()
19+
def context = new GenericApplicationContext()
20+
context.refresh()
21+
def app = new DefaultGrailsApplication(ExcludeUrlMappings)
22+
def pm = new DefaultGrailsPluginManager(app)
23+
context.beanFactory.registerSingleton(GrailsApplication.APPLICATION_ID, app)
24+
context.beanFactory.registerSingleton(GrailsPluginManager.BEAN_NAME, pm)
25+
app.initialise()
26+
factoryBean.setApplicationContext(context)
27+
28+
when:"The URL mappings holder is created"
29+
factoryBean.afterPropertiesSet()
30+
UrlMappingsHolder holder = factoryBean.getObject()
31+
32+
then:"The excludes are correct"
33+
holder.excludePatterns == ["/stomp/", "/stomp/*", "/topic/*"]
34+
holder.matchAll("/stomp/foo").size() == 0
35+
}
36+
}
37+
class ExcludeUrlMappings {
38+
39+
static excludes = ["/stomp/", "/stomp/*", "/topic/*"]
40+
41+
static mappings = {
42+
'/**'(controller:"index")
43+
"500"(view:'/error')
44+
"404"(view:'/notFound')
45+
}
46+
}

0 commit comments

Comments
 (0)