![JAR search and dependency download from the Maven repository](/logo.png)
com.strategicgains.restexpress.url.UrlPattern Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of RestExpress Show documentation
Show all versions of RestExpress Show documentation
Internet scale, high-performance RESTful Services in Java
/*
Copyright 2010, Strategic Gains, Inc.
Licensed 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 com.strategicgains.restexpress.url;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* UrlPattern leverages Regex Pattern to represent a parameterized URL. Parameters within the URL are
* denoted by curly braces '{}' with the parameter name contained within (e.g. '{userid}').
*
* Parameter names must be formed of word characters (e.g. A-Z, a-z, 0-9, '_').
* An optional format parameter following a dot ('.') may be added to the end. While it could be named any valid parameter name,
* RestExpress offers special handling (e.g. within the Request, etc.) if it's named 'format'.
*
* Note that the format specifier allows only word characters and percent-encoded characters.
*
* URL Pattern examples:
*
* - /api/search.{format}
* - /api/search/users/{userid}.{format}
* - /api/{version}/search/users/{userid}
*
*
* RestExpress accepts URIs with the following BNF values taken from the URI Generic Syntax IETF RFC 3986 as follows:
*
* pct-encoded = "%" HEXDIG HEXDIG
*
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* reserved = gen-delims / sub-delims
* gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" *
*
*
* @author toddf
* @since Apr 28, 2010
* @see http://www.ietf.org/rfc/rfc3986.txt
*/
public class UrlPattern
implements UrlMatcher
{
// SECTION: CONSTANTS
// Finds parameters in the URL pattern string.
private static final String URL_PARAM_REGEX = "\\{(\\w*?)\\}";
// Replaces parameter names in the URL pattern string to match parameters in URLs.
private static final String URL_PARAM_MATCH_REGEX = "\\([%\\\\w-.\\\\~!\\$&'\\\\(\\\\)\\\\*\\\\+,;=:\\\\?#\\\\[\\\\]@]+?\\)";
// Pattern to match URL pattern parameter names.
private static final Pattern URL_PARAM_PATTERN = Pattern.compile(URL_PARAM_REGEX);
// Finds the format portion of the URL pattern string.
private static final String URL_FORMAT_REGEX = "(?:\\.\\{(\\w+)\\})$";
// Replaces the format parameter name in the URL pattern string to match the format specifier in URLs. Appended to the end of the regex string
// when a URL pattern contains a format parameter.
private static final String URL_FORMAT_MATCH_REGEX = "(?:\\\\.\\([\\\\w%]+?\\))?";
// Finds the query string portion within a URL. Appended to the end of the built-up regex string.
private static final String URL_QUERY_STRING_REGEX = "(?:\\?.+?)?$";
/**
* The URL pattern describing the URL layout and any parameters.
*/
private String urlPattern;
/**
* A compiled regex created from the urlPattern, above.
*/
private Pattern compiledUrl;
/**
* An ordered list of parameter names found in the urlPattern, above.
*/
private List parameterNames = new ArrayList();
// SECTION: CONSTRUCTOR
/**
* @param pattern
*/
public UrlPattern(String pattern)
{
super();
setUrlPattern(pattern);
compile();
}
// SECTION: ACCESSORS/MUTATORS - PRIVATE
/**
* @return the pattern
*/
private String getUrlPattern()
{
return urlPattern;
}
public String getPattern()
{
return getUrlPattern().replaceFirst(URL_FORMAT_REGEX, "");
}
/**
* @param pattern the pattern to set
*/
private void setUrlPattern(String pattern)
{
this.urlPattern = pattern;
}
public List getParameterNames()
{
return Collections.unmodifiableList(parameterNames);
}
// SECTION: URL MATCHING
/**
* Test the given URL against the underlying pattern to determine if it matches, returning the
* results in a UrlMatch instance. If the URL matches, parse any applicable parameters from it,
* placing those also in the UrlMatch instance accessible by their parameter names.
*
* @param url an URL string with or without query string.
* @return a UrlMatch instance reflecting the outcome of the comparison, if matched. Otherwise, null.
*/
@Override
public UrlMatch match(String url)
{
Matcher matcher = compiledUrl.matcher(url);
if (matcher.matches())
{
return new UrlMatch(extractParameters(matcher));
}
return null;
}
/**
* Test the given URL against the underlying pattern to determine if it matches, returning a boolean
* to reflect the outcome.
*
* @param url an URL string with or without query string.
* @return true if the given URL matches the underlying pattern. Otherwise false.
*/
@Override
public boolean matches(String url)
{
return (match(url) != null);
}
// SECTION: UTILITY - PRIVATE
/**
* Processes the incoming URL pattern string to create a java.util.regex Pattern out of it and
* parse out the parameter names, if applicable.
*/
public void compile()
{
acquireParameterNames();
String parsedPattern = getUrlPattern().replaceFirst(URL_FORMAT_REGEX, URL_FORMAT_MATCH_REGEX);
parsedPattern = parsedPattern.replaceAll(URL_PARAM_REGEX, URL_PARAM_MATCH_REGEX);
@SuppressWarnings("unused")
String completePattern = parsedPattern + URL_QUERY_STRING_REGEX;
compiledUrl = Pattern.compile(parsedPattern + URL_QUERY_STRING_REGEX);
}
/**
* Parses the parameter names from the URL pattern string provided to the constructor, building
* the ordered list, parameterNames.
*/
private void acquireParameterNames()
{
Matcher m = URL_PARAM_PATTERN.matcher(getUrlPattern());
while (m.find())
{
parameterNames.add(m.group(1));
}
}
/**
* Extracts parameter values from a Matcher instance.
*
* @param matcher
* @return a Map containing parameter values indexed by their corresponding parameter name.
*/
private Map extractParameters(Matcher matcher)
{
Map values = new HashMap();
for (int i = 0; i < matcher.groupCount(); i++)
{
String value = matcher.group(i + 1);
if (value != null)
{
values.put(parameterNames.get(i), value);
}
}
return values;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy