Search in sources :

Example 1 with UrlMapping

use of grails.web.mapping.UrlMapping in project grails-core by grails.

the class DefaultUrlMappingEvaluatorTests method testRedirectMappings.

public void testRedirectMappings() throws Exception {
    GroovyShell shell = new GroovyShell();
    Binding binding = new Binding();
    Script script = shell.parse("mappings = {\n" + "\"/first\"(redirect:[controller: 'foo', action: 'bar'])\n" + "\"/second\"(redirect: '/bing/bang')\n" + "}");
    script.setBinding(binding);
    script.run();
    Closure closure = (Closure) binding.getVariable("mappings");
    List<UrlMapping> mappings = evaluator.evaluateMappings(closure);
    assertEquals(2, mappings.size());
    Object redirectInfo = mappings.get(0).getRedirectInfo();
    assertTrue(redirectInfo instanceof Map);
    Map redirectMap = (Map) redirectInfo;
    assertEquals(2, redirectMap.size());
    assertEquals("foo", redirectMap.get("controller"));
    assertEquals("bar", redirectMap.get("action"));
    assertEquals("/bing/bang", mappings.get(1).getRedirectInfo());
}
Also used : Binding(groovy.lang.Binding) UrlMapping(grails.web.mapping.UrlMapping) Script(groovy.lang.Script) Closure(groovy.lang.Closure) Map(java.util.Map) GroovyShell(groovy.lang.GroovyShell)

Example 2 with UrlMapping

use of grails.web.mapping.UrlMapping in project grails-core by grails.

the class RegexUrlMapping method compareTo.

/**
 * Compares this UrlMapping instance with the specified UrlMapping instance and deals with URL mapping precedence rules.
 *
 *  URL Mapping Precedence Order
 *
 *   1. Less wildcard tokens.
 *
 *       /foo          <- match
 *       /foo/(*)
 *
 *      /foo/(*)/bar/  <- match
 *      /foo/(*)/(*)
 *
 *    2. More static tokens.
 *
 *      /foo/(*)/bar   <- match
 *      /foo/(*)
 *
 * @param o An instance of the UrlMapping interface
 * @return greater than 0 if this UrlMapping should match before the specified UrlMapping. 0 if they are equal or less than 0 if this UrlMapping should match after the given UrlMapping
 */
public int compareTo(Object o) {
    if (!(o instanceof UrlMapping)) {
        throw new IllegalArgumentException("Cannot compare with Object [" + o + "]. It is not an instance of UrlMapping!");
    }
    if (equals(o))
        return 0;
    UrlMapping other = (UrlMapping) o;
    // this wild card count
    final int thisStaticTokenCount = getStaticTokenCount(this);
    final int thisSingleWildcardCount = getSingleWildcardCount(this);
    final int thisDoubleWildcardCount = getDoubleWildcardCount(this);
    // the other wild card count
    final int otherStaticTokenCount = getStaticTokenCount(other);
    final int otherSingleWildcardCount = getSingleWildcardCount(other);
    final int otherDoubleWildcardCount = getDoubleWildcardCount(other);
    final boolean hasWildCards = thisDoubleWildcardCount > 0 || thisSingleWildcardCount > 0;
    final boolean otherHasWildCards = otherDoubleWildcardCount > 0 || otherSingleWildcardCount > 0;
    // Always prioritise the / root mapping
    boolean isThisRoot = thisStaticTokenCount == 0 && thisSingleWildcardCount == 0 && thisDoubleWildcardCount == 0;
    boolean isThatRoot = otherStaticTokenCount == 0 && otherDoubleWildcardCount == 0 && otherSingleWildcardCount == 0;
    if (isThisRoot && isThatRoot) {
        return evaluatePluginOrder(other);
    } else if (isThisRoot) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a higher precedence than [{}] because it is the root", this.toString(), other.toString());
        }
        return 1;
    } else if (isThatRoot) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter is the root", this.toString(), other.toString());
        }
        return -1;
    }
    if (otherStaticTokenCount == 0 && thisStaticTokenCount > 0) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more path tokens", this.toString(), other.toString());
        }
        return 1;
    }
    if (thisStaticTokenCount == 0 && otherStaticTokenCount > 0) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a lower precedence than [{}] because it has fewer path tokens", this.toString(), other.toString());
        }
        return -1;
    }
    final int thisStaticAndWildcardTokenCount = getStaticAndWildcardTokenCount(this);
    final int otherStaticAndWildcardTokenCount = getStaticAndWildcardTokenCount(other);
    if (otherStaticAndWildcardTokenCount == 0 && thisStaticAndWildcardTokenCount > 0) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticAndWildcardTokenCount, otherStaticAndWildcardTokenCount);
        }
        return 1;
    }
    if (thisStaticAndWildcardTokenCount == 0 && otherStaticAndWildcardTokenCount > 0) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a higher precedence than [{}] because the latter has more path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticAndWildcardTokenCount, otherStaticAndWildcardTokenCount);
        }
        return -1;
    }
    final int staticDiff = thisStaticTokenCount - otherStaticTokenCount;
    if (staticDiff < 0 && !otherHasWildCards) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter has more concrete path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticTokenCount, otherStaticTokenCount);
        }
        return -1;
    } else if (staticDiff > 0 && !hasWildCards) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a higher precedence than [{}] because it has more concrete path tokens [{} vs {}]", this.toString(), other.toString(), thisStaticTokenCount, otherStaticTokenCount);
        }
        return 1;
    }
    String[] thisTokens = getUrlData().getTokens();
    String[] otherTokens = other.getUrlData().getTokens();
    final int thisTokensLength = thisTokens.length;
    final int otherTokensLength = otherTokens.length;
    int greaterLength = thisTokensLength > otherTokensLength ? thisTokensLength : otherTokensLength;
    for (int i = 0; i < greaterLength; i++) {
        final boolean thisHasMoreTokens = i < thisTokensLength;
        final boolean otherHasMoreTokens = i < otherTokensLength;
        boolean thisTokenIsWildcard = !thisHasMoreTokens || isSingleWildcard(thisTokens[i]);
        boolean otherTokenIsWildcard = !otherHasMoreTokens || isSingleWildcard(otherTokens[i]);
        if (thisTokenIsWildcard && !otherTokenIsWildcard) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Mapping [{}] has a lower precedence than [{}] because the latter contains more concrete tokens", this.toString(), other.toString());
            }
            return -1;
        }
        if (!thisTokenIsWildcard && otherTokenIsWildcard) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Mapping [{}] has a higher precedence than [{}] because it contains more concrete tokens", this.toString(), other.toString());
            }
            return 1;
        }
    }
    final int doubleWildcardDiff = otherDoubleWildcardCount - thisDoubleWildcardCount;
    if (doubleWildcardDiff != 0) {
        if (LOG.isDebugEnabled()) {
            if (doubleWildcardDiff > 0) {
                LOG.debug("Mapping [{}] has a higher precedence than [{}] due containing more double wild cards [{} vs. {}]", this.toString(), other.toString(), thisDoubleWildcardCount, otherDoubleWildcardCount);
            } else if (doubleWildcardDiff < 0) {
                LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the latter containing more double wild cards [{} vs. {}]", this.toString(), other.toString(), thisDoubleWildcardCount, otherDoubleWildcardCount);
            }
        }
        return doubleWildcardDiff;
    }
    final int singleWildcardDiff = otherSingleWildcardCount - thisSingleWildcardCount;
    if (singleWildcardDiff != 0) {
        if (LOG.isDebugEnabled()) {
            if (singleWildcardDiff > 0) {
                LOG.debug("Mapping [{}] has a higher precedence than [{}] because it contains more single wild card matches [{} vs. {}]", this.toString(), other.toString(), thisSingleWildcardCount, otherSingleWildcardCount);
            } else if (singleWildcardDiff < 0) {
                LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the latter containing more single wild card matches[{} vs. {}]", this.toString(), other.toString(), thisSingleWildcardCount, otherSingleWildcardCount);
            }
        }
        return singleWildcardDiff;
    }
    int thisConstraintCount = getAppliedConstraintsCount(this);
    int thatConstraintCount = getAppliedConstraintsCount(other);
    int constraintDiff = thisConstraintCount - thatConstraintCount;
    if (constraintDiff != 0) {
        if (LOG.isDebugEnabled()) {
            if (constraintDiff > 0) {
                LOG.debug("Mapping [{}] has a higher precedence than [{}] since it defines more constraints [{} vs. {}]", this.toString(), other.toString(), thisConstraintCount, thatConstraintCount);
            } else if (constraintDiff < 0) {
                LOG.debug("Mapping [{}] has a lower precedence than [{}] since the latter defines more constraints [{} vs. {}]", this.toString(), other.toString(), thisConstraintCount, thatConstraintCount);
            }
        }
        return constraintDiff;
    }
    int allDiff = (thisStaticTokenCount - otherStaticTokenCount) + (thisSingleWildcardCount - otherSingleWildcardCount) + (thisDoubleWildcardCount - otherDoubleWildcardCount);
    if (allDiff != 0) {
        if (LOG.isDebugEnabled()) {
            if (allDiff > 0) {
                LOG.debug("Mapping [{}] has a higher precedence than [{}] due to the overall diff", this.toString(), other.toString());
            } else if (allDiff < 0) {
                LOG.debug("Mapping [{}] has a lower precedence than [{}] due to the overall diff", this.toString(), other.toString());
            }
        }
        return allDiff;
    }
    String thisVersion = getVersion();
    String thatVersion = other.getVersion();
    if ((thisVersion.equals(thatVersion))) {
        return evaluatePluginOrder(other);
    } else if (thisVersion.equals(ANY_VERSION) && !thatVersion.equals(ANY_VERSION)) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a lower precedence than [{}] due to version precedence [{} vs {}]", this.toString(), other.toString(), thisVersion, thatVersion);
        }
        return -1;
    } else if (!thisVersion.equals(ANY_VERSION) && thatVersion.equals(ANY_VERSION)) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Mapping [{}] has a higher precedence than [{}] due to version precedence [{} vs {}]", this.toString(), other.toString(), thisVersion, thatVersion);
        }
        return 1;
    } else {
        int i = new VersionComparator().compare(thisVersion, thatVersion);
        if (i > 0) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Mapping [{}] has a higher precedence than [{}] due to version precedence [{} vs. {}]", this.toString(), other.toString(), thisVersion, thatVersion);
            }
            return 1;
        } else if (i < 0) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Mapping [{}] has a lower precedence than [{}] due to version precedence [{} vs. {}]", this.toString(), other.toString(), thisVersion, thatVersion);
            }
            return -1;
        } else {
            return evaluatePluginOrder(other);
        }
    }
}
Also used : UrlMapping(grails.web.mapping.UrlMapping) VersionComparator(grails.plugins.VersionComparator)

Example 3 with UrlMapping

use of grails.web.mapping.UrlMapping in project grails-core by grails.

the class DefaultUrlMappingsHolder method addMappings.

@Override
public Collection<UrlMapping> addMappings(Closure mappings) {
    WebApplicationContext applicationContext = (WebApplicationContext) Holders.findApplicationContext();
    UrlMappingEvaluator evaluator = new DefaultUrlMappingEvaluator(applicationContext);
    List<UrlMapping> newMappings = evaluator.evaluateMappings(mappings);
    this.urlMappings.addAll(newMappings);
    initialize();
    return newMappings;
}
Also used : UrlMapping(grails.web.mapping.UrlMapping) UrlMappingEvaluator(grails.web.mapping.UrlMappingEvaluator) WebApplicationContext(org.springframework.web.context.WebApplicationContext)

Example 4 with UrlMapping

use of grails.web.mapping.UrlMapping in project grails-core by grails.

the class DefaultUrlMappingsHolder method matchAll.

public UrlMappingInfo[] matchAll(String uri, String httpMethod, String version) {
    if (isExcluded(uri))
        return EMPTY_RESULTS;
    UriToUrlMappingKey cacheKey = new UriToUrlMappingKey(uri, httpMethod, version);
    List<UrlMappingInfo> matchingUrls = cachedListMatches.getIfPresent(cacheKey);
    if (matchingUrls == null) {
        matchingUrls = new ArrayList<>();
        boolean anyHttpMethod = httpMethod != null && httpMethod.equals(UrlMapping.ANY_HTTP_METHOD);
        boolean anyVersion = version != null && version.equals(UrlMapping.ANY_VERSION);
        for (UrlMapping mapping : mappings) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Attempting to match URI [" + uri + "] with pattern [" + mapping.getUrlData().getUrlPattern() + "]");
            }
            UrlMappingInfo current = mapping.match(uri);
            if (current != null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Matched URI [" + uri + "] with pattern [" + mapping.getUrlData().getUrlPattern() + "], adding to posibilities");
                }
                String mappingHttpMethod = current.getHttpMethod();
                String mappingVersion = current.getVersion();
                boolean isValidHttpMethod = mappingHttpMethod == null || anyHttpMethod || mappingHttpMethod.equalsIgnoreCase(UrlMapping.ANY_HTTP_METHOD) || mappingHttpMethod.equalsIgnoreCase(httpMethod);
                boolean isValidVersion = mappingVersion == null || anyVersion || mappingVersion.equals(UrlMapping.ANY_VERSION) || mappingVersion.equals(version);
                if (isValidHttpMethod && isValidVersion) {
                    matchingUrls.add(current);
                }
            }
        }
        cachedListMatches.put(cacheKey, matchingUrls);
    }
    return matchingUrls.toArray(new UrlMappingInfo[matchingUrls.size()]);
}
Also used : UrlMapping(grails.web.mapping.UrlMapping) UrlMappingInfo(grails.web.mapping.UrlMappingInfo)

Example 5 with UrlMapping

use of grails.web.mapping.UrlMapping in project grails-core by grails.

the class DefaultUrlMappingsHolder method matchStatusCode.

public UrlMappingInfo matchStatusCode(int responseCode) {
    for (UrlMapping mapping : mappings) {
        if (mapping instanceof ResponseCodeUrlMapping) {
            ResponseCodeUrlMapping responseCodeUrlMapping = (ResponseCodeUrlMapping) mapping;
            if (responseCodeUrlMapping.getExceptionType() != null)
                continue;
            final UrlMappingInfo current = responseCodeUrlMapping.match(responseCode);
            if (current != null)
                return current;
        }
    }
    return null;
}
Also used : UrlMapping(grails.web.mapping.UrlMapping) UrlMappingInfo(grails.web.mapping.UrlMappingInfo)

Aggregations

UrlMapping (grails.web.mapping.UrlMapping)14 UrlMappingInfo (grails.web.mapping.UrlMappingInfo)4 Binding (groovy.lang.Binding)3 Closure (groovy.lang.Closure)3 GroovyShell (groovy.lang.GroovyShell)3 Script (groovy.lang.Script)3 HashSet (java.util.HashSet)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Config (grails.config.Config)1 GrailsClass (grails.core.GrailsClass)1 GrailsControllerClass (grails.core.GrailsControllerClass)1 GrailsUrlMappingsClass (grails.core.GrailsUrlMappingsClass)1 ArtefactAdditionEvent (grails.core.events.ArtefactAdditionEvent)1 Constrained (grails.gorm.validation.Constrained)1 ConstrainedProperty (grails.gorm.validation.ConstrainedProperty)1 VersionComparator (grails.plugins.VersionComparator)1 UrlConverter (grails.web.UrlConverter)1 UrlCreator (grails.web.mapping.UrlCreator)1 UrlMappingEvaluator (grails.web.mapping.UrlMappingEvaluator)1