📄 urlpattern.java
字号:
package dev.trade.common.securityfilter.filter;
import org.apache.oro.text.regex.*;
import dev.trade.common.securityfilter.config.*;
/**
* URLPattern - Contains matchable URL pattern and the associated
* SecurityConstraint and WebResourceCollection objects for the pattern.
* Also supports sorting according to the Servlet Spec v2.3.
*/
public class URLPattern implements Comparable {
/**
* Pattern type for patterns that do not meet the specifications for the
* other pattern types.
*/
public static final int EXACT_TYPE = 1;
/**
* Pattern type for PATH_TYPE mappings. Starts with '/' and ends with '/*'.
*/
public static final int PATH_TYPE = 2;
/**
* Pattern type for EXTENSION_TYPE mappings. Starts with '*.'
*/
public static final int EXTENSION_TYPE = 3;
/**
* Pattern type for EXTENSION_TYPE mappings. Starts with '*.'
*/
public static final int DEFAULT_TYPE = 4;
protected String pattern;
protected String convertedPattern;
protected Pattern compiledPattern;
protected SecurityConstraint constraint;
protected WebResourceCollection resourceCollection;
protected int order;
protected int patternType;
protected int pathLength;
/**
* Construct a new URLPattern object.
*
* @param pattern the url pattern to match
* @param constraint the SecurityConstraint associated with this pattern
* @param resourceCollection the WebResourceCollection associated with this pattern
* @param order the order in which this pattern occurred in the configuration file
* @param compiler a PatternCompiler to use to compile this url pattern
*
* @see URLPatternFactory
*/
public URLPattern(
String pattern,
SecurityConstraint constraint,
WebResourceCollection resourceCollection,
int order,
PatternCompiler compiler
) throws Exception {
this.pattern = pattern;
this.constraint = constraint;
this.resourceCollection = resourceCollection;
this.order = order;
initPatternType();
initPathLength();
initConvertedPattern();
initCompiledPattern(compiler);
}
/**
* Get the url pattern to match.
*/
public String getPattern() {
return pattern;
}
/**
* Get the compiled version of this pattern.
*
* @return compiled version of this pattern
*/
public Pattern getCompiledPattern() {
return compiledPattern;
}
/**
* Get the pattern type. The pattern type will be determined on the first call to this method.
*
* @return EXACT, PATH, or EXTENSION
*/
public int getPatternType() {
return patternType;
}
/**
* Get the path length of the pattern. This is only valid when getPatternType() = PATH.<p>
* Examples:
* <ul>
* <li>/* = 0</li>
* <li>/path/* = 1</li>
* <li>/really/long/path/* = 3</li>
* </ul>
*
* @return path length of this pattern
*/
public int getPathLength() {
return pathLength;
}
/**
* Get the SecurityConstraint object associated with this pattern.
*/
public SecurityConstraint getSecurityConstraint() {
return constraint;
}
/**
* Get the order value for this pattern (the order in which it appeared in the config file).
*/
public int getOrder() {
return order;
}
/**
* Get the WebResourceCollection associated with this pattern.
*/
public WebResourceCollection getWebResourceCollection() {
return resourceCollection;
}
/**
* Initialize the patternType protected member.
*/
protected void initPatternType() {
if ("/".equals(pattern)) {
patternType = DEFAULT_TYPE;
} else if (pattern.startsWith("*.")) {
patternType = EXTENSION_TYPE;
} else if (pattern.startsWith("/") && pattern.endsWith("/*")) {
patternType = PATH_TYPE;
} else {
patternType = EXACT_TYPE;
}
}
/**
* Initialize the pathLength protected member.
*/
protected void initPathLength() {
pathLength = -1;
int pos = pattern.indexOf('/');
while (pos != -1) {
pathLength++;
pos = pattern.indexOf('/', pos + 1);
}
}
/**
* Initialize the convertedPattern protected member.
*/
protected void initConvertedPattern() {
if (patternType == DEFAULT_TYPE) {
// match anything for default pattern
convertedPattern = ".*";
} else {
StringBuffer buf = new StringBuffer(pattern);
int pos;
// escape '.' characters
pos = buf.toString().indexOf('.');
while (pos != -1) {
buf.insert(pos, "\\");
pos = buf.toString().indexOf('.', pos + 2);
}
// replace '*' chars in the compiledPattern with '.*'
pos = buf.toString().indexOf('*');
while (pos != -1) {
buf.replace(pos, pos + 1, ".*");
pos = buf.toString().indexOf('*', pos + 2);
}
// replace '/' chars with '/+' to match one or more consecutive slashes
// the spec hints that containers are supposed to normalize the extra slashes out,
// but testing revealed that sometimes the extra slashes are not normalized out
pos = buf.toString().indexOf('/');
while (pos != -1) {
buf.replace(pos, pos + 1, "/+");
pos = buf.toString().indexOf('/', pos + 2);
}
// adjustments for the different expression types
switch (patternType) {
case PATH_TYPE:
// make sure it matches from the start of the string
buf.insert(0, '^');
// make sure /foo/* matches /foo and /foo/morestuff, but not /foobar
buf.insert(buf.length()-4, "(");
buf.append(")?$");
break;
case EXTENSION_TYPE:
buf.append('$');
break;
case EXACT_TYPE:
buf.insert(0, '^');
buf.append('$');
break;
}
convertedPattern = buf.toString();
}
}
/**
* Initialize the compiledPattern protected member.
*
* @param compiler
* @throws Exception
*/
protected void initCompiledPattern(PatternCompiler compiler) throws Exception {
compiledPattern = compiler.compile(convertedPattern, Perl5Compiler.READ_ONLY_MASK);
}
/**
* Test if this pattern is equivalent to another pattern.
* This is implemented so that consistency with the compareTo method results can be maintained.
*
* @param obj the value to test equivalence with
* @return true if the passed object is an equivalent URLPattern, false if it is not a URLPattern
* or if it is not equivalent.
*/
public boolean equals(Object obj) {
if (obj instanceof URLPattern) {
URLPattern otherPattern = (URLPattern) obj;
return (
constraint.equals(otherPattern.getSecurityConstraint())
&& resourceCollection.equals(otherPattern.getWebResourceCollection())
&& pattern.equals(otherPattern.getPattern())
);
}
return false;
}
/**
* Compares this URLPattern to obj to support sorting.<p>
*
* The sort order is dictated by the servlet spec. The ordering by type is:
* EXACT_TYPE
* PATH_TYPE
* EXTENTION_TYPE
* DEFAULT_TYPE
* Ordering among PATH_TYPE patterns is determined by path length, with the
* longer path coming first. If the path lengths are the same, or both patterns
* are of the same type other than PATH_TYPE, ordering is determined by the order
* in which the pattern appeared in the config file.
*
* Thanks to Chris Nokleberg for contributing code for this method.
*
* @param obj another URLPattern to compare to
*
* @return a negative integer, zero, or a positive integer as this object is
* less than, equal to, or greater than the specified object.
*
* @exception ClassCastException thrown if obj is not a URLPattern instance
*/
public int compareTo(Object obj) throws ClassCastException {
URLPattern other = (URLPattern) obj;
// return 0 if the other pattern is equivalent to this one
if (this.equals(other)) {
return 0;
}
int c = patternType - other.patternType;
if (c == 0) {
switch (patternType) {
case PATH_TYPE:
c = other.pathLength - pathLength;
if (c != 0) {
break;
}
/* fall through */
case EXACT_TYPE:
/* fall through */
case EXTENSION_TYPE:
/* fall through */
case DEFAULT_TYPE:
c = order - other.order;
}
}
return c;
}
}
// ----------------------------------------------------------------------------
// EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -