uritemplate.java
来自「resetful样式的ws样例,一种面向资源的webservices服务」· Java 代码 · 共 796 行 · 第 1/2 页
JAVA
796 行
/* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://jersey.dev.java.net/CDDL+GPL.html * or jersey/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at jersey/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */package com.sun.jersey.api.uri;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.Set;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * A URI template. * * @author Paul.Sandoz@Sun.Com */public class UriTemplate { /** * Order the templates according to the string comparison of the * template regular expressions. * <p> * The JSR-311 specification states: * "Sort the set of matching resource classes using the number of * characters in the regular expression not resulting from template * variables as the primary key and the number of matching groups * as a secondary key" */ static public final Comparator<UriTemplate> COMPARATOR = new Comparator<UriTemplate>() { public int compare(UriTemplate o1, UriTemplate o2) { if (o1 == null && o2 == null) return 0; if (o1 == null) return 1; if (o2 == null) return -1; if (o1 == EMPTY && o2 == EMPTY) return 0; if (o1 == EMPTY) return 1; if (o2 == EMPTY) return -1; // Compare the number of explicit characters // Note that it is important that o2 is compared against o1 // so that a regular expression with say 10 explicit characters // is less than a regular expression with say 5 explicit characters. int i = o2.getNumberOfExplicitCharacters() - o1.getNumberOfExplicitCharacters(); if (i != 0) return i; // If the number of explicit characters is equal // compare the number of template variables // Note that it is important that o2 is compared against o1 // so that a regular expression with say 10 template variables // is less than a regular expression with say 5 template variables. i = o2.getNumberOfTemplateVariables() - o1.getNumberOfTemplateVariables(); if (i != 0) return i; // If the number of explicit characters and template variables // are equal then comapre the regexes // The order does not matter as long as templates with different // explicit characters are distinguishable return o2.pattern.getRegex().compareTo(o1.pattern.getRegex()); } }; /** * The regular expression for matching URI templates and names. */ private static final Pattern TEMPLATE_NAMES_PATTERN = Pattern.compile("\\{([\\w-\\._~]+?)\\}"); /** * This uses a reluctant (non-greedy qualifier) to ensure that * expresions to the right of an expression will be matched. */ private static final String TEMPLATE_VALUE_REGEX = "(.*?)"; /** * The empty URI template that matches the null or empty URI path */ public static final UriTemplate EMPTY = new UriTemplate(); /** * The URI template. */ private final String template; /** * The pattern generated from the template */ private final UriPattern pattern; /** * True if the URI template ends in a '/' character. */ private final boolean endsWithSlash; /** * The template variables in the URI template. */ private final List<String> templateVariables; /** * The number of characters in the regular expression not resulting * from conversion of template variables. */ private final int numOfCharacters; /** * Constructor for NULL template */ private UriTemplate() { this.template = ""; this.pattern = UriPattern.EMPTY; this.endsWithSlash = false; this.templateVariables = Collections.emptyList(); this.numOfCharacters = 0; } /** * Construct a new URI template. * <p> * The template will be parsed to extract template variables. * <p> * A specific regular expression will be generated from the template * to match URIs according to the template and map template variables to * template values. * <p> * @param template the template. * @throws {@link java.util.regex.PatternSyntaxException} if the specific * regular expression could not be generated * @throws {@link IllegalArgumentException} if the template is null or * an empty string. */ public UriTemplate(String template) { if (template == null || template.length() == 0) throw new IllegalArgumentException(); // TODO correctly validate template StringBuilder b = new StringBuilder(); List<String> names = new ArrayList<String>(); // Find all template variables // Create regular expression for template matching Matcher m = TEMPLATE_NAMES_PATTERN.matcher(template); int i = 0; int c = 0; while(m.find()) { c += m.start() - i; copyURITemplateCharacters(template, i, m.start(), b); b.append(TEMPLATE_VALUE_REGEX); names.add(m.group(1)); i = m.end(); } copyURITemplateCharacters(template, i, template.length(), b); c += template.length() - i; this.template = template; this.pattern = new UriPattern(b.toString()); this.numOfCharacters = c; this.endsWithSlash = template.charAt(template.length() - 1) == '/'; this.templateVariables = Collections.unmodifiableList(names); } /** * Copy characters from the URI template to a string builder. * Characters that correspond to regular expression * characters will be escaped. * <p> * TODO need to escape all regex characters present * * @param template The URI template. * @param start The start index of characters in template to copy * @param end The end index of characters in template to copy * @param b The string builder to copy the characters. */ private static void copyURITemplateCharacters(String template, int start, int end, StringBuilder b) { for (int i = start; i < end; i++) { char c = template.charAt(i); if (RESERVED_REGEX_CHARACTERS.contains(c)) b.append("\\"); b.append(c); } } private static Set<Character> RESERVED_REGEX_CHARACTERS = createReserved(); private static Set<Character> createReserved() { // TODO need to escape all regex characters present char[] reserved = { '.', '?', '(', ')'}; Set<Character> s = new HashSet<Character>(); for (char c : reserved) s.add(c); return s; } /** * Get the URI template as a String. * @return the URI template. */ public final String getTemplate() { return template; } /** * Get the URI pattern. * * @return the URI pattern. */ public final UriPattern getPattern() { return pattern; } /** * Returns true if the template end in a '/' */ public final boolean endsWithSlash() { return endsWithSlash; } /** * Get the list of template variables for the template. * @return the list of template variables. */ public final List<String> getTemplateVariables() { return templateVariables; } /** * Ascertain if a template variable is a member of this * template. * @param name name The template variable. * @return true if the template variable is a member of the template, otherwise * false. */ public final boolean isTemplateVariablePresent(String name) { for (String s : templateVariables) { if (s.equals(name)) return true; } return false; } /** * Get the number of characters in the regular expression not resulting * from conversion of template variables. * @return the number of explicit characters */ public final int getNumberOfExplicitCharacters() { return numOfCharacters; } /** * Get the number of template variables. * @return the number of template variables. */ public final int getNumberOfTemplateVariables() { return templateVariables.size(); } private int numberOfPathSegments; private Map<String, Integer> pathSegmentIndex; /** * Get the number of path segments in the template. * * @return the number of path segments */ public final int getNumberOfPathSegments() { initPathSegments(); return numberOfPathSegments; } /** * Get the path segment index of a path segment that contains a * template variable. * * @param variable the template variable * @return the path segment index, otherise -1 if the template variable is * not present */ public final int getPathSegmentIndex(String variable) { initPathSegments(); Integer i = pathSegmentIndex.get(variable); return (i != null) ? i : -1; } private final void initPathSegments() { if (pathSegmentIndex == null) { pathSegmentIndex = new HashMap<String, Integer>(); numberOfPathSegments = 0; for (String subPath : getTemplate().split("/")) { if (subPath.length() == 0) continue; for (String v : getTemplateVariables()) if (subPath.contains('{' + v + '}')) pathSegmentIndex.put(v, numberOfPathSegments); numberOfPathSegments++; } } } /** * Match a URI against the template. * <p> * If the URI matches against the pattern then the template variable to value * map will be filled with template variables as keys and template values as * values. * <p> * * @param uri the uri to match against the template. * @param templateVariableToValue the map where to put template variables (as keys) * and template values (as values). The map is cleared before any * entries are put. * @return true if the URI matches the template, otherwise false. * @throws {@link IllegalArgumentException} if the uri or * templateVariableToValue is null. */ public final boolean match(CharSequence uri, Map<String, String> templateVariableToValue) { if (templateVariableToValue == null) throw new IllegalArgumentException(); return pattern.match(uri, templateVariables, templateVariableToValue); } /** * Match a URI against the template. * <p> * If the URI matches against the pattern then the template variable to value * map will be filled with template variables as keys and template values as * values. * <p> * * @param uri the uri to match against the template. * @param groupValues the list to store the values of a pattern's * capturing groups is matching is successful. The values are stored * in the same order as the pattern's capturing groups. * @return true if the URI matches the template, otherwise false. * @throws {@link IllegalArgumentException} if the uri or * templateVariableToValue is null.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?