Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,28 @@ mappings {
}
'''

def mappingWithNamespace = '''
mappings {
"/$namespace/$controller/$action?/$id?" ()
}
'''

@Test
void testGetReverseMappingWithNamespace() {
def res = new ByteArrayResource(mappingWithNamespace.bytes)

def evaluator = new DefaultUrlMappingEvaluator(mainContext)
def mappings = evaluator.evaluateMappings(res)

def holder = new DefaultUrlMappingsHolder(mappings)

def m = holder.getReverseMapping("product", "show", "foo", null, [:])
assertNotNull "getReverseMapping returned null", m

assertEquals "/foo/product/show", m.createURL("product", "show", "foo", null, [:], "utf-8")
}


@Test
void testGetReverseMappingWithNamedArgsAndClosure() {
def res = new ByteArrayResource(mappingWithNamedArgsAndClosure.bytes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ private String getControllerNameInternal(GrailsWebRequest req) {
return null;
}

public String getControllerNamespace() {
final GrailsWebRequest req = getWebRequest();
if (req != null) {
return req.getControllerNamespace();
}
return null;
}

public String getActionName() {
final GrailsWebRequest req = getWebRequest();
if (req != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ public interface GrailsRequestStateLookupStrategy {
*/
public String getControllerName();

/**
* The controller namespace
*
* @return The controller namespace or null if not known
*/
public String getControllerNamespace();

/**
* The action name for the given controller name
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Map;

import grails.util.GrailsStringUtils;
import grails.web.mapping.LinkGenerator;
import grails.web.mapping.UrlMapping;
import grails.util.GrailsMetaClassUtils;
Expand Down Expand Up @@ -120,6 +121,13 @@ private void appendMapKey(StringBuilder buffer, Map map) {
}
appendKeyValue(buffer, map, key, value);
}
if (map.get(UrlMapping.NAMESPACE) == null) {
String namespace = getRequestStateLookupStrategy().getControllerNamespace();
if (GrailsStringUtils.isNotEmpty(namespace)) {
appendCommaIfNotFirst(buffer, first);
appendKeyValue(buffer, map, UrlMapping.NAMESPACE, namespace);
}
}
buffer.append(CLOSING_BRACKET);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,19 +243,19 @@ class DefaultLinkGenerator implements LinkGenerator, org.codehaus.groovy.grails.
params.put(ATTRIBUTE_ID, id)
}
def pluginName = attrs.get(UrlMapping.PLUGIN)?.toString()
def namespace = attrs.get(UrlMapping.NAMESPACE)?.toString()
def namespace = attrs.get(UrlMapping.NAMESPACE)?.toString() ?: requestStateLookupStrategy.controllerNamespace
UrlCreator mapping = urlMappingsHolder.getReverseMappingNoDefault(controller,action,namespace,pluginName,httpMethod,params)
if (mapping == null && isDefaultAction) {
mapping = urlMappingsHolder.getReverseMappingNoDefault(controller,null,namespace,pluginName,httpMethod,params)
}
if (mapping == null) {
mapping = urlMappingsHolder.getReverseMapping(controller,action,pluginName,httpMethod,params)
mapping = urlMappingsHolder.getReverseMapping(controller,action,namespace,pluginName,httpMethod,params)
}

boolean absolute = isAbsolute(attrs)

if (!absolute) {
url = mapping.createRelativeURL(convertedControllerName, convertedActionName, params, encoding, frag)
url = mapping.createRelativeURL(convertedControllerName, convertedActionName, namespace, pluginName, params, encoding, frag)
final contextPathAttribute = attrs.get(ATTRIBUTE_CONTEXT_PATH)
final cp = contextPathAttribute == null ? getContextPath() : contextPathAttribute
if (attrs.get(ATTRIBUTE_BASE) || cp == null) {
Expand All @@ -268,7 +268,7 @@ class DefaultLinkGenerator implements LinkGenerator, org.codehaus.groovy.grails.
writer.append url
}
else {
url = mapping.createRelativeURL(convertedControllerName, convertedActionName, params, encoding, frag)
url = mapping.createRelativeURL(convertedControllerName, convertedActionName, namespace, pluginName, params, encoding, frag)
writer.append handleAbsolute(attrs)
writer.append url
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public int weightOf(List<UrlMappingInfo> values) {
private Map<UrlMappingKey, UrlMapping> mappingsLookup = new HashMap<UrlMappingKey, UrlMapping>();
private Map<String, UrlMapping> namedMappings = new HashMap<String, UrlMapping>();
private UrlMappingsList mappingsListLookup = new UrlMappingsList();
private Set<String> DEFAULT_NAMESPACE_PARAMS = CollectionUtils.newSet(
UrlMapping.NAMESPACE, UrlMapping.CONTROLLER, UrlMapping.ACTION);
private Set<String> DEFAULT_CONTROLLER_PARAMS = CollectionUtils.newSet(
UrlMapping.CONTROLLER, UrlMapping.ACTION);
private Set<String> DEFAULT_ACTION_PARAMS = CollectionUtils.newSet(UrlMapping.ACTION);
Expand Down Expand Up @@ -356,6 +358,27 @@ private UrlCreator resolveUrlCreator(final String controller,
}
}
}
if (mapping == null || (mapping instanceof ResponseCodeUrlMapping)) {
Set<String> lookupParams = new HashSet<String>(DEFAULT_NAMESPACE_PARAMS);
Set<String> paramKeys = new HashSet<String>(params.keySet());
paramKeys.removeAll(lookupParams);
lookupParams.addAll(paramKeys);
UrlMappingKey lookupKey = new UrlMappingKey(null, null, null, pluginName, httpMethod, version,lookupParams);
mapping = mappingsLookup.get(lookupKey);
if (mapping == null) {
lookupKey.httpMethod = UrlMapping.ANY_HTTP_METHOD;
mapping = mappingsLookup.get(lookupKey);
}
if (mapping == null) {
lookupParams.removeAll(paramKeys);
UrlMappingKey lookupKeyModifiedParams = new UrlMappingKey(null, null, null, pluginName, httpMethod, version,lookupParams);
mapping = mappingsLookup.get(lookupKeyModifiedParams);
if (mapping == null) {
lookupKeyModifiedParams.httpMethod = UrlMapping.ANY_HTTP_METHOD;
mapping = mappingsLookup.get(lookupKeyModifiedParams);
}
}
}
UrlCreator creator = null;
if (mapping == null || (mapping instanceof ResponseCodeUrlMapping)) {
if (useDefault) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ private void populateParameterList(Map paramValues, String encoding, StringBuild
usedParams.add("controller");
usedParams.add("action");
usedParams.add("namespace");
usedParams.add("plugin");

// A 'null' encoding will cause an exception, so default to 'UTF-8'.
if (encoding == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.codehaus.groovy.grails.web.mapping

import grails.util.GrailsWebMockUtil
import org.grails.web.mapping.CachingLinkGenerator
import org.grails.web.servlet.mvc.DefaultRequestStateLookupStrategy
import org.grails.web.servlet.mvc.GrailsWebRequest
import org.springframework.web.context.request.RequestContextHolder
import spock.lang.Shared
import spock.lang.Specification

/**
* Tests for the {@link org.grails.web.mapping.CachingLinkGenerator} class
*/
class CachingLinkGeneratorSpec extends Specification {

@Shared
MyCachingLinkGenerator linkGenerator

@Shared
GrailsWebRequest request

void setup() {
linkGenerator = new MyCachingLinkGenerator("http://grails.org/")
request = GrailsWebMockUtil.bindMockWebRequest()
linkGenerator.requestStateLookupStrategy = new DefaultRequestStateLookupStrategy(request)
}

void cleanup() {
RequestContextHolder.resetRequestAttributes()
}

void "test namespace"() {
given:
String key

when: "not in the request or params"
key = linkGenerator.makeKey([controller: "foo", action: "bar"])

then: "its not in the key"
key == "link[controller:foo, action:bar]"

when: "its in the params"
key = linkGenerator.makeKey([controller: "foo", action: "bar", namespace: "foo"])

then: "its in the key"
key == "link[controller:foo, action:bar, namespace:foo]"

when: "its in the request"
request.setControllerNamespace("fooReq")
key = linkGenerator.makeKey([controller: "foo", action: "bar"])

then: "its in the key"
key == "link[controller:foo, action:bar, namespace:fooReq]"

when: "its in the request and the params"
request.setControllerNamespace("fooReq")
key = linkGenerator.makeKey([controller: "foo", action: "bar", namespace: "fooParam"])

then: "params wins"
key == "link[controller:foo, action:bar, namespace:fooParam]"
}


class MyCachingLinkGenerator extends CachingLinkGenerator {
public MyCachingLinkGenerator(String serverBaseURL) {
super(serverBaseURL)
}

String makeKey(Map attrs) {
super.makeKey(LINK_PREFIX, attrs)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,39 @@ class LinkGeneratorSpec extends Specification {
then:
cacheKey == "somePrefix[resource:org.codehaus.groovy.grails.web.mapping.Widget->2]"
}


def 'link should take into affect namespace'() {
given:
final webRequest = GrailsWebMockUtil.bindMockWebRequest()
MockHttpServletRequest request = webRequest.currentRequest
linkParams.contextPath = ''

when: "A namespace is specified"
linkParams.namespace = 'fooBar'
linkParams.controller = 'one'
linkParams.action = 'two'

then: "it exists in the url"
link == '/fooBar/one/two'

when: "The namespace is in the request params"
webRequest.setControllerNamespace("fooBarReq")
linkParams.remove('namespace')
linkParams.controller = 'one'
linkParams.action = 'two'

then: "it exists in the url"
link == '/fooBarReq/one/two'

when: "Params and the request attribute exist"
webRequest.setControllerNamespace("fooBarReq")
linkParams.namespace = 'fooBarParam'
linkParams.controller = 'one'
linkParams.action = 'two'

then: "params wins"
link == '/fooBarParam/one/two'
}

void cleanup() {
RequestContextHolder.resetRequestAttributes()
Expand All @@ -294,8 +326,8 @@ class LinkGeneratorSpec extends Specification {
protected getGenerator(boolean cache=false) {
def generator = cache ? new CachingLinkGenerator(baseUrl, context) : new DefaultLinkGenerator(baseUrl, context)
final callable = { String controller, String action, String namespace, String pluginName, String httpMethod, Map params ->
[createRelativeURL: { String c, String a, Map parameterValues, String encoding, String fragment ->
"/$controller/$action".toString()
[createRelativeURL: { String c, String a, String n, String p, Map parameterValues, String encoding, String fragment ->
"${namespace ? '/' + namespace : ''}/$controller/$action".toString()
}] as UrlCreator
}
generator.grailsUrlConverter = new CamelCaseUrlConverter()
Expand Down
5 changes: 5 additions & 0 deletions trigger-dependent-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then
exit 0
fi

# Only run for master branch
if [ "${TRAVIS_BRANCH}" != "master" ]; then
exit 0
fi

# Don't run for tagged releases
if [[ $TRAVIS_TAG =~ ^v[[:digit:]] ]]; then
exit 0
Expand Down