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 + -
显示快捷键?