![JAR search and dependency download from the Maven repository](/logo.png)
org.beangle.commons.regex.AntPathPattern.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of beangle-commons Show documentation
Show all versions of beangle-commons Show documentation
The Beangle Commons Library
The newest version!
/*
* Copyright (C) 2005, The Beangle Software.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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.See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
package org.beangle.commons.regex
import org.beangle.commons.collection.Collections
import org.beangle.commons.lang.Strings
import org.beangle.commons.regex.AntPathPattern.DefaultPattern
import java.util.regex.Pattern
object AntPathPattern {
def matches(pattern: String, path: String): Boolean = new AntPathPattern(pattern).matches(path)
def matchStart(pattern: String, path: String): Boolean = new AntPathPattern(pattern).matchStart(path)
def isPattern(path: String): Boolean = {
(path.indexOf('*') != -1 || path.indexOf('?') != -1)
}
//? or /** or **/ or * or { (?: {[^/]+?} | [^/{}] | \\[{}] )+? }
private val DefaultPattern = Pattern.compile("""\?|/\*\*|\*\*/|\*|\{((?:\{[^/]+?\}|[^/{}]|\\[{}])+?)\}""")
}
/** AntPattern implementation for Ant-style path patterns. Examples are provided below.
*
* Part of this mapping code has been kindly borrowed from Apache
* Ant.
*
* The mapping matches URLs using the following rules:
*
* - ? matches one character
* - * matches zero or more characters
* - ** matches zero or more 'directories' in a path
*
*
* Some examples:
*
* com/t?st.jsp
- matches com/test.jsp
but also
* com/tast.jsp
or com/txst.jsp
* com/*sp
- matches all .jsp
files in the com
directory
* org/beangle/**/*.jsp
- matches all .jsp
files underneath
* com/**/test.jsp
- matches all test.jsp
files underneath the com
path
* the org/beangle
path
* org/**/servlet/bla.jsp
- matches
* org/beangle/servlet/bla.jsp
but also
* org/beangle/testing/servlet/bla.jsp
and org/servlet/bla.jsp
*
*
* @author chaostone
* @since 3.1.0
*/
class AntPathPattern(val text: String) {
private var pattern: Pattern = _
private var exactMatch: Boolean = _
var variables: List[String] = List.empty
preprocess(text, false)
/** translate ant string to regex string
*/
def preprocess(pattern: String, caseSensitive: Boolean): Unit = {
val builder = new StringBuilder()
val matcher = DefaultPattern.matcher(pattern)
var end = 0
val vars = Collections.newBuffer[String]
while (matcher.find()) {
builder.append(quote(pattern, end, matcher.start()))
val matched = matcher.group()
if ("?" == matched) {
builder.append('.')
} else if ("**/" == matched || "/**" == matched) {
builder.append(".*")
} else if ("*" == matched) {
builder.append("[^/]*")
} else if (matched.startsWith("{") && matched.endsWith("}")) {
val colonIdx = matched.indexOf(':')
if (colonIdx == -1) {
if isRegex(matched) then
builder.append(s"(${matched.substring(1, matched.length - 1)})")
else
builder.append("((?s).*)")
vars.addOne(matcher.group(1))
} else {
val variablePattern = matched.substring(colonIdx + 1, matched.length() - 1)
builder.append('(').append(variablePattern).append(')')
val variableName = matched.substring(1, colonIdx)
vars.addOne(variableName)
}
}
end = matcher.end();
}
this.variables = vars.toList
if (end == 0) {
this.exactMatch = true
this.pattern = null
} else {
this.exactMatch = false
builder.append(quote(pattern, end, pattern.length()))
this.pattern = Pattern.compile(builder.toString(),
Pattern.DOTALL | (if caseSensitive then 0 else Pattern.CASE_INSENSITIVE))
}
}
private def isRegex(p: String): Boolean = {
p.indexOf('*') > 0 || p.indexOf('.') > 0 || p.indexOf('+') > 0 || p.indexOf('[') > 0
}
override def hashCode(): Int = text.hashCode
override def equals(obj: Any): Boolean = obj match {
case obj: AntPathPattern => text == obj.text
case _ => false
}
def matches(path: String): Boolean = {
if exactMatch then text == path else pattern.matcher(path).matches()
}
def matchStart(path: String): Boolean = {
if exactMatch then path.startsWith(text)
else
val m = pattern.matcher(path)
m.matches()
m.hitEnd()
}
private def quote(s: String, start: Int, end: Int): String = {
if start == end then ""
else Pattern.quote(s.substring(start, end));
}
override def toString: String = {
if null == pattern then s"ant:[${text}]"
else Strings.concat("ant:[", text, "] regex:[", pattern.toString, "]")
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy