// // ======================================================================== // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // 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.regex.Matcher; import java.util.regex.Pattern; public class RegexPathSpec extends PathSpec { protected Pattern pattern; protected RegexPathSpec() { super(); } public RegexPathSpec(String regex) { super.pathSpec = regex; if (regex.startsWith("regex|")) super.pathSpec = regex.substring("regex|".length()); this.pathDepth = 0; this.specLength = pathSpec.length(); // build up a simple signature we can use to identify the grouping boolean inGrouping = false; StringBuilder signature = new StringBuilder(); for (char c : pathSpec.toCharArray()) { switch (c) { case '[': inGrouping = true; break; case ']': inGrouping = false; signature.append('g'); // glob break; case '*': signature.append('g'); // glob break; case '/': if (!inGrouping) { this.pathDepth++; } break; default: if (!inGrouping) { if (Character.isLetterOrDigit(c)) { signature.append('l'); // literal (exact) } } break; } } this.pattern = Pattern.compile(pathSpec); // Figure out the grouping based on the signature String sig = signature.toString(); if (Pattern.matches("^l*$",sig)) { this.group = PathSpecGroup.EXACT; } else if (Pattern.matches("^l*g+",sig)) { this.group = PathSpecGroup.PREFIX_GLOB; } else if (Pattern.matches("^g+l+$",sig)) { this.group = PathSpecGroup.SUFFIX_GLOB; } else { this.group = PathSpecGroup.MIDDLE_GLOB; } } public Matcher getMatcher(String path) { return this.pattern.matcher(path); } @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 (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; } public Pattern getPattern() { return this.pattern; } @Override public String getRelativePath(String base, String path) { // TODO Auto-generated method stub return null; } @Override public boolean matches(final String path) { int idx = path.indexOf('?'); if (idx >= 0) { // match only non-query part return getMatcher(path.substring(0,idx)).matches(); } else { // match entire path return getMatcher(path).matches(); } } }