urlmap.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 571 行
JAVA
571 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.server.dispatch;import com.caucho.server.util.CauchoSystem;import com.caucho.util.*;import javax.servlet.ServletException;import java.util.ArrayList;import java.util.regex.Matcher;import java.util.regex.Pattern;import java.util.regex.PatternSyntaxException;/** * Maps uris to objects, using the syntax in the servlet2.2 deployment * descriptors: * * /foo/bar -- exact match * /foo/bar/* -- matches anything with the /foo/bar prefix * *.jsp -- matches anything with the .jsp suffix */public class UrlMap<E> { private static final L10N L = new L10N(UrlMap.class); // List of matching regular expressions private ArrayList<RegexpEntry<E>> _regexps; // If true, use the shortest match private boolean _bestShort; /** * Create a new map */ public UrlMap() { _regexps = new ArrayList<RegexpEntry<E>>(); } /** * Create a new map preferring a short match. * * @param bestShort if true, use the shortest match */ public UrlMap(boolean bestShort) { _regexps = new ArrayList<RegexpEntry<E>>(); _bestShort = bestShort; } /** * If set to true, this map uses the shortest match instead of the * longest. * * @param bestShort if true, use the shortest match */ void setBestShort(boolean bestShort) { _bestShort = bestShort; } int size() { return _regexps.size(); } public void addMap(String pattern, E value) throws PatternSyntaxException { addMap(pattern, null, value); } /** * Adds a new url-pattern and its corresponding value to the map * * @param pattern servlet2.2 url-pattern * @param value object stored as the value */ public void addMap(String pattern, String flags, E value) throws PatternSyntaxException { if (pattern.length() == 0 || pattern.length() == 1 && pattern.charAt(0) == '/') { addRegexp(-1, "", flags, value, true); return; } else if (pattern.equals("/*")) { addRegexp(1, "/*", "", flags, value, true); return; } int length = pattern.length(); boolean isExact = true; if (pattern.charAt(0) != '/' && pattern.charAt(0) != '*') { pattern = "/" + pattern; length++; } int prefixLength = -1; boolean isShort = false; CharBuffer cb = new CharBuffer(); cb.append("^"); for (int i = 0; i < length; i++) { char ch = pattern.charAt(i); if (ch == '*' && i + 1 == length && i > 0) { isExact = false; if (pattern.charAt(i - 1) == '/') { cb.setLength(cb.length() - 1); if (prefixLength < 0) prefixLength = i - 1; } else if (prefixLength < 0) prefixLength = i; if (prefixLength == 0) prefixLength = 1; } else if (ch == '*') { isExact = false; cb.append(".*"); if (prefixLength < 0) prefixLength = i; if (i == 0) isShort = true; } else if (ch == '.' || ch == '[' || ch == '^' || ch == '$' || ch == '{' || ch == '}' || ch == '|' || ch == '(' || ch == ')' || ch == '?') { cb.append('\\'); cb.append(ch); } else cb.append(ch); } if (isExact) cb.append("$"); else { cb.append("(?=/)|" + cb.toString() + "\\z"); } if (prefixLength < 0) prefixLength = pattern.length(); else if (prefixLength < pattern.length() && pattern.charAt(prefixLength) == '/') prefixLength--; if (cb.length() > 0 && cb.charAt(0) == '/') cb.insert(0, '^'); addRegexp(prefixLength, pattern, cb.close(), flags, value, isShort); } public static String urlPatternToRegexpPattern(String pattern) { if (pattern.length() == 0 || pattern.length() == 1 && pattern.charAt(0) == '/') { return "^.*$"; } else if (pattern.equals("/*")) return "^.*$"; int length = pattern.length(); if (pattern.charAt(0) != '/' && pattern.charAt(0) != '*') { pattern = "/" + pattern; length++; } boolean isExact = true; CharBuffer cb = new CharBuffer(); cb.append("^"); for (int i = 0; i < length; i++) { char ch = pattern.charAt(i); if (ch == '*' && i + 1 == length && i > 0) { isExact = false; if (pattern.charAt(i - 1) == '/') { cb.setLength(cb.length() - 1); } } else if (ch == '*') { isExact = false; cb.append(".*"); } else if (ch == '.' || ch == '[' || ch == '^' || ch == '$' || ch == '{' || ch == '}' || ch == '|' || ch == '(' || ch == ')' || ch == '?') { cb.append('\\'); cb.append(ch); } else cb.append(ch); } if (isExact) cb.append("\\z"); else cb.append("(?=/)|" + cb.toString() + "\\z"); if (cb.length() > 0 && cb.charAt(0) == '/') cb.insert(0, '^'); return cb.close(); } /** * Adds a new url-pattern and its corresponding value to the map * * @param pattern servlet2.2 url-pattern * @param value object stored as the value */ public void addStrictMap(String pattern, String flags, E value) throws PatternSyntaxException, ServletException { if (pattern.length() == 0 || pattern.length() == 1 && pattern.charAt(0) == '/') { addRegexp(-1, "^.*$", flags, value, true); return; } int length = pattern.length(); boolean isExact = true; if (pattern.charAt(0) != '/' && pattern.charAt(0) != '*') { pattern = "/" + pattern; length++; } if (pattern.indexOf('*') < pattern.lastIndexOf('*')) throw new ServletException("at most one '*' is allowed"); int prefixLength = -1; boolean isShort = false; CharBuffer cb = new CharBuffer(); cb.append('^'); for (int i = 0; i < length; i++) { char ch = pattern.charAt(i); switch (ch) { case '*': if (i > 0 && i + 1 == length && pattern.charAt(i - 1) == '/') { cb.append(".*"); } else if (i == 0 && length > 1 && pattern.charAt(1) == '.' && pattern.lastIndexOf('/') < 0) { cb.append(".*"); } else throw new ServletException(L.l("illegal url-pattern '{0}'", pattern)); break; case '.': case '[': case '^': case '$': case '{': case '}': case '|': case '(': case '?': cb.append('\\'); cb.append(ch); break; default: cb.append(ch); } } cb.append("$"); addRegexp(prefixLength, pattern, cb.close(), flags, value, isShort); } public void addRegexp(String regexp, String flags, E value) throws PatternSyntaxException { addRegexp(0, regexp, flags, value, false); } public void addRegexp(String regexp, E value) throws PatternSyntaxException { addRegexp(0, regexp, null, value, false); } /** * Adds a regular expression to the map. * * @param prefixLength the length of the pattern's mandatory prefix * @param regexp the regexp pattern to add * @param flags regexp flags, like "i" for case insensitive * @param value the value for matching the pattern * @param isShort if true, this regexp expects to be shorter than others */ public void addRegexp(int prefixLength, String regexp, String flags, E value, boolean isShort) throws PatternSyntaxException { RegexpEntry<E> entry = new RegexpEntry<E>(prefixLength, regexp, flags, value); for (int i = 0; i < _regexps.size(); i++) { RegexpEntry<E> re = _regexps.get(i); if (re.equals(entry)) { _regexps.remove(i); break; } } if (isShort) entry.setShortMatch(); _regexps.add(entry); } /** * Adds a regular expression to the map. * * @param prefixLength the length of the pattern's mandatory prefix * @param pattern the regexp pattern to add * @param regexp the regexp pattern to add * @param flags regexp flags, like "i" for case insensitive * @param value the value for matching the pattern * @param isShort if true, this regexp expects to be shorter than others */ public void addRegexp(int prefixLength, String pattern, String regexp, String flags, E value, boolean isShort) throws PatternSyntaxException { RegexpEntry<E> entry = new RegexpEntry<E>(prefixLength, pattern, regexp, flags, value); for (int i = _regexps.size() - 1; i >= 0; i--) { RegexpEntry<E> re = _regexps.get(i); if (re.equals(entry)) { _regexps.remove(i); } } if (isShort) entry.setShortMatch(); _regexps.add(entry); } /** * Finds the best match for the uri. In the case of a servlet dispatch, * match is servletPath and replacement is pathInfo. * * @param uri uri to match * * @return matching object */ public E map(String uri) { return map(uri, null); } /** * Finds the best match for the uri. In the case of a servlet dispatch, * match is servletPath and replacement is pathInfo. * * @param uri uri to match * @param vars a list of the regexp variables. * * @return matching object */ public E map(String uri, ArrayList<String> vars) { E best = null; if (vars != null) vars.add(uri); int bestPrefixLength = -2; int bestMinLength = -2; int bestMaxLength = Integer.MAX_VALUE; for (int i = 0; i < _regexps.size(); i++) { RegexpEntry<E> entry = _regexps.get(i); if ("plugin_match".equals(entry._value) || "plugin-match".equals(entry._value)) continue; if ("plugin_ignore".equals(entry._value) || "plugin-ignore".equals(entry._value)) continue; if (entry._prefixLength < bestPrefixLength) continue; Matcher matcher = entry._regexp.matcher(uri); if (! matcher.find()) continue; int begin = matcher.start(); int end = matcher.end(); int length = end - begin; boolean bestShort = entry.isShortMatch(); // Earlier matches override later ones if (bestPrefixLength < entry._prefixLength || bestMinLength < length) { if (vars != null) { vars.clear(); vars.add(uri.substring(0, end)); for (int j = 1; j <= matcher.groupCount(); j++) vars.add(matcher.group(j)); } best = entry._value; bestPrefixLength = entry._prefixLength; bestMaxLength = length; if (! entry.isShortMatch()) bestMinLength = length; if (bestMinLength < entry._prefixLength) bestMinLength = entry._prefixLength; } } return best; } /** * Return the matching url patterns. */ public ArrayList<String> getURLPatterns() { ArrayList<String> patterns = new ArrayList<String>(); for (int i = 0; i < _regexps.size(); i++) { RegexpEntry<E> entry = _regexps.get(i); String urlPattern = entry.getURLPattern(); if (urlPattern != null) patterns.add(urlPattern); } return patterns; } static class RegexpEntry<E> { String _urlPattern; String _pattern; int _flags; Pattern _regexp; E _value; int _prefixLength; boolean _shortMatch; RegexpEntry(int prefixLength, String pattern, String flags, E value) throws PatternSyntaxException { this(prefixLength, pattern, pattern, flags, value); } RegexpEntry(int prefixLength, String urlPattern, String pattern, String flags, E value) throws PatternSyntaxException { _urlPattern = urlPattern; _prefixLength = prefixLength; _pattern = pattern; if (flags == null && CauchoSystem.isCaseInsensitive()) _flags = Pattern.CASE_INSENSITIVE; else if (flags != null && flags.equals("i")) _flags = Pattern.CASE_INSENSITIVE; _regexp = Pattern.compile(pattern, _flags); _value = value; } void setShortMatch() { _shortMatch = true; } boolean isShortMatch() { return _shortMatch; } String getURLPattern() { return _urlPattern; } String getPattern() { return _pattern; } public int hashCode() { if (_urlPattern != null) return _urlPattern.hashCode(); else if (_pattern != null) return _pattern.hashCode(); else return 17; } public boolean equals(Object o) { if (! (o instanceof RegexpEntry)) return false; RegexpEntry re = (RegexpEntry) o; if (_urlPattern != null) return _urlPattern.equals(re._urlPattern); else if (_pattern != null) return _pattern.equals(re._pattern); else return false; } public String toString() { if (_urlPattern != null) return "RegexpEntry[" + _urlPattern + "]"; else if (_pattern != null) return "RegexpEntry[" + _pattern + "]"; else return super.toString(); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?