org.eclipse.jetty.http.pathmap.RegexPathSpec Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
//
// ========================================================================
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.http.pathmap;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
// @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported.
@Deprecated(since = "2021-05-27")
public class RegexPathSpec extends AbstractPathSpec {
private static final Logger LOG = Log.getLogger(UriTemplatePathSpec.class);
private static final Map FORBIDDEN_ESCAPED = new HashMap<>();
static {
FORBIDDEN_ESCAPED.put('s', "any whitespace");
FORBIDDEN_ESCAPED.put('n', "newline");
FORBIDDEN_ESCAPED.put('r', "carriage return");
FORBIDDEN_ESCAPED.put('t', "tab");
FORBIDDEN_ESCAPED.put('f', "form-feed");
FORBIDDEN_ESCAPED.put('b', "bell");
FORBIDDEN_ESCAPED.put('e', "escape");
FORBIDDEN_ESCAPED.put('c', "control char");
}
private final String _declaration;
private final PathSpecGroup _group;
private final int _pathDepth;
private final int _specLength;
private final Pattern _pattern;
public RegexPathSpec(String regex) {
String declaration;
if (regex.startsWith("regex|"))
declaration = regex.substring("regex|".length());
else
declaration = regex;
int specLength = declaration.length();
// build up a simple signature we can use to identify the grouping
boolean inTextList = false;
boolean inQuantifier = false;
StringBuilder signature = new StringBuilder();
int pathDepth = 0;
char last = 0;
for (int i = 0; i < declaration.length(); i++) {
char c = declaration.charAt(i);
switch(c) {
// ignore anchors
case '^':
// ignore anchors
case '$':
// ignore escaping
case '\'':
// ignore grouping
case '(':
case // ignore grouping
')':
break;
// single char quantifier
case '+':
// single char quantifier
case '?':
// single char quantifier
case '*':
// alternate match token
case '|':
case // any char token
'.':
// glob
signature.append('g');
break;
case '{':
inQuantifier = true;
break;
case '}':
inQuantifier = false;
break;
case '[':
inTextList = true;
break;
case ']':
inTextList = false;
// glob
signature.append('g');
break;
case '/':
if (!inTextList && !inQuantifier)
pathDepth++;
break;
default:
if (!inTextList && !inQuantifier && Character.isLetterOrDigit(c)) {
if (// escaped
last == '\\') {
String forbiddenReason = FORBIDDEN_ESCAPED.get(c);
if (forbiddenReason != null) {
throw new IllegalArgumentException(String.format("%s does not support \\%c (%s) for \"%s\"", this.getClass().getSimpleName(), c, forbiddenReason, declaration));
}
switch(c) {
// any non-whitespace
case 'S':
// any digits
case 'd':
// any non-digits
case 'D':
// any word
case 'w':
case // any non-word
'W':
// glob
signature.append('g');
break;
default:
// literal (exact)
signature.append('l');
break;
}
} else // not escaped
{
// literal (exact)
signature.append('l');
}
}
break;
}
last = c;
}
Pattern pattern = Pattern.compile(declaration);
// Figure out the grouping based on the signature
String sig = signature.toString();
PathSpecGroup group;
if (Pattern.matches("^l*$", sig))
group = PathSpecGroup.EXACT;
else if (Pattern.matches("^l*g+", sig))
group = PathSpecGroup.PREFIX_GLOB;
else if (Pattern.matches("^g+l+.*", sig))
group = PathSpecGroup.SUFFIX_GLOB;
else
group = PathSpecGroup.MIDDLE_GLOB;
_declaration = declaration;
_group = group;
_pathDepth = pathDepth;
_specLength = specLength;
_pattern = pattern;
if (LOG.isDebugEnabled()) {
LOG.debug("Creating RegexPathSpec[{}] (signature: [{}], group: {})", _declaration, sig, _group);
}
}
protected Matcher getMatcher(String path) {
int idx = path.indexOf('?');
if (idx >= 0) {
// match only non-query part
return _pattern.matcher(path.substring(0, idx));
} else {
// match entire path
return _pattern.matcher(path);
}
}
@Override
public int getSpecLength() {
return _specLength;
}
@Override
public PathSpecGroup getGroup() {
return _group;
}
@Override
public int getPathDepth() {
return _pathDepth;
}
@Override
public String getPathInfo(String path) {
// Path Info only valid for PREFIX_GLOB types
if (_group == PathSpecGroup.PREFIX_GLOB) {
Matcher matcher = getMatcher(path);
if (matcher.matches()) {
if (matcher.groupCount() >= 1) {
String pathInfo = matcher.group(1);
if ("".equals(pathInfo))
return "/";
else
return pathInfo;
}
}
}
return null;
}
@Override
public String getPathMatch(String path) {
Matcher matcher = getMatcher(path);
if (matcher.matches()) {
if (_group == PathSpecGroup.PREFIX_GLOB && matcher.groupCount() >= 1) {
int idx = matcher.start(1);
if (idx > 0) {
if (path.charAt(idx - 1) == '/')
idx--;
return path.substring(0, idx);
}
}
return path;
}
return null;
}
@Override
public String getDeclaration() {
return _declaration;
}
@Override
public String getPrefix() {
return null;
}
@Override
public String getSuffix() {
return null;
}
public Pattern getPattern() {
return _pattern;
}
@Override
public boolean matches(final String path) {
return getMatcher(path).matches();
}
@Override
public MatchedPath matched(String path) {
Matcher matcher = getMatcher(path);
if (matcher.matches()) {
return new RegexMatchedPath(this, path, matcher);
}
return null;
}
// @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported.
@Deprecated(since = "2021-05-27")
private class RegexMatchedPath implements MatchedPath {
private final RegexPathSpec pathSpec;
private final String path;
private final Matcher matcher;
public RegexMatchedPath(RegexPathSpec regexPathSpec, String path, Matcher matcher) {
this.pathSpec = regexPathSpec;
this.path = path;
this.matcher = matcher;
}
@Override
public String getPathMatch() {
try {
String p = matcher.group("name");
if (p != null) {
return p;
}
} catch (IllegalArgumentException ignore) {
// ignore if group name not found.
}
if (pathSpec.getGroup() == PathSpecGroup.PREFIX_GLOB && matcher.groupCount() >= 1) {
int idx = matcher.start(1);
if (idx > 0) {
if (this.path.charAt(idx - 1) == '/')
idx--;
return this.path.substring(0, idx);
}
}
// default is the full path
return this.path;
}
@Override
public String getPathInfo() {
try {
String p = matcher.group("info");
if (p != null) {
return p;
}
} catch (IllegalArgumentException ignore) {
// ignore if group info not found.
}
// Path Info only valid for PREFIX_GLOB
if (pathSpec.getGroup() == PathSpecGroup.PREFIX_GLOB && matcher.groupCount() >= 1) {
String pathInfo = matcher.group(1);
if ("".equals(pathInfo))
return "/";
else
return pathInfo;
}
// default is null
return null;
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + "pathSpec=" + pathSpec + ", path=\"" + path + "\"" + ", matcher=" + matcher + ']';
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy