All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.anarsoft.trace.agent.runtime.util.AntPatternMatcher Maven / Gradle / Ivy

There is a newer version: 1.1.5
Show newest version
package com.anarsoft.trace.agent.runtime.util;



/**
 * 
 * see https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/AntPathMatcher.html
 * 
 * from https://github.com/stoicflame/enunciate/blob/master/core/src/main/java/com/webcohesion/enunciate/util/AntPatternMatcher.java
 * 
 * 
 * @author thomas
 *
 */


public class AntPatternMatcher {

	  public static final AntPatternMatcher INSTANCE = new AntPatternMatcher();

	  /** Default path separator: "." */
	  public static final String DEFAULT_PATH_SEPARATOR = ".";

	  private String pathSeparator = DEFAULT_PATH_SEPARATOR;

	  public static boolean isValidPattern(String pattern) {
	    return INSTANCE.isPattern(pattern);
	  }

	  /**
	   * Set the path separator to use for pattern parsing.
	   * Default is "/", as in Ant.
	   *
	   * @param pathSeparator The path separator.
	   */
	  public void setPathSeparator(String pathSeparator) {
	    this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
	  }

	  /**
	   * Whether this is a pattern.
	   *
	   * @param path The pattern.
	   * @return Whether the path is a pattern.
	   */
	  public boolean isPattern(String path) {
	    return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
	  }

	  public boolean match(String pattern, String path) {
	    return doMatch(pattern, path, true);
	  }

	  /**
	   * Actually match the given path against the given pattern.
	   * @param pattern the pattern to match against
	   * @param path the path String to test
	   * @param fullMatch whether a full pattern match is required
	   * (else a pattern match as far as the given base path goes is sufficient)
	   * @return true if the supplied path matched,
	   * false if it didn't
	   */
	  protected boolean doMatch(String pattern, String path, boolean fullMatch) {
	    if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
	      return false;
	    }

	    String pathSeparatorSplitPattern = ".".equals(this.pathSeparator) ? "\\." : this.pathSeparator; //escape the special '.' for regexp splitting.
	    pathSeparatorSplitPattern = "\\".equals(pathSeparatorSplitPattern) ? "\\\\" : pathSeparatorSplitPattern; //escape the special '\' for regexp splitting.
	    String[] pattDirs = pattern.split(pathSeparatorSplitPattern);
	    String[] pathDirs = path.split(pathSeparatorSplitPattern);

	    int pattIdxStart = 0;
	    int pattIdxEnd = pattDirs.length - 1;
	    int pathIdxStart = 0;
	    int pathIdxEnd = pathDirs.length - 1;

	    // Match all elements up to the first **
	    while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
	      String patDir = pattDirs[pattIdxStart];
	      if ("**".equals(patDir)) {
	        break;
	      }
	      if (!matchStrings(patDir, pathDirs[pathIdxStart])) {
	        return false;
	      }
	      pattIdxStart++;
	      pathIdxStart++;
	    }

	    if (pathIdxStart > pathIdxEnd) {
	      // Path is exhausted, only match if rest of pattern is * or **'s
	      if (pattIdxStart > pattIdxEnd) {
	        return (pattern.endsWith(this.pathSeparator) ?
	            path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator));
	      }
	      if (!fullMatch) {
	        return true;
	      }
	      if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") &&
	          path.endsWith(this.pathSeparator)) {
	        return true;
	      }
	      for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
	        if (!pattDirs[i].equals("**")) {
	          return false;
	        }
	      }
	      return true;
	    }
	    else if (pattIdxStart > pattIdxEnd) {
	      // String not exhausted, but pattern is. Failure.
	      return false;
	    }
	    else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {
	      // Path start definitely matches due to "**" part in pattern.
	      return true;
	    }

	    // up to last '**'
	    while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
	      String patDir = pattDirs[pattIdxEnd];
	      if (patDir.equals("**")) {
	        break;
	      }
	      if (!matchStrings(patDir, pathDirs[pathIdxEnd])) {
	        return false;
	      }
	      pattIdxEnd--;
	      pathIdxEnd--;
	    }
	    if (pathIdxStart > pathIdxEnd) {
	      // String is exhausted
	      for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
	        if (!pattDirs[i].equals("**")) {
	          return false;
	        }
	      }
	      return true;
	    }

	    while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
	      int patIdxTmp = -1;
	      for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
	        if (pattDirs[i].equals("**")) {
	          patIdxTmp = i;
	          break;
	        }
	      }
	      if (patIdxTmp == pattIdxStart + 1) {
	        // '**/**' situation, so skip one
	        pattIdxStart++;
	        continue;
	      }
	      // Find the pattern between padIdxStart & padIdxTmp in str between
	      // strIdxStart & strIdxEnd
	      int patLength = (patIdxTmp - pattIdxStart - 1);
	      int strLength = (pathIdxEnd - pathIdxStart + 1);
	      int foundIdx = -1;

	      strLoop:
	          for (int i = 0; i <= strLength - patLength; i++) {
	            for (int j = 0; j < patLength; j++) {
	              String subPat = (String) pattDirs[pattIdxStart + j + 1];
	              String subStr = (String) pathDirs[pathIdxStart + i + j];
	              if (!matchStrings(subPat, subStr)) {
	                continue strLoop;
	              }
	            }
	            foundIdx = pathIdxStart + i;
	            break;
	          }

	      if (foundIdx == -1) {
	        return false;
	      }

	      pattIdxStart = patIdxTmp;
	      pathIdxStart = foundIdx + patLength;
	    }

	    for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
	      if (!pattDirs[i].equals("**")) {
	        return false;
	      }
	    }

	    return true;
	  }

	  /**
	   * Tests whether or not a string matches against a pattern.
	   * The pattern may contain two special characters:
* '*' means zero or more characters
* '?' means one and only one character * @param pattern pattern to match against. * Must not be null. * @param str string which must be matched against the pattern. * Must not be null. * @return true if the string matches against the * pattern, or false otherwise. */ private boolean matchStrings(String pattern, String str) { char[] patArr = pattern.toCharArray(); char[] strArr = str.toCharArray(); int patIdxStart = 0; int patIdxEnd = patArr.length - 1; int strIdxStart = 0; int strIdxEnd = strArr.length - 1; char ch; boolean containsStar = false; for (int i = 0; i < patArr.length; i++) { if (patArr[i] == '*') { containsStar = true; break; } } if (!containsStar) { // No '*'s, so we make a shortcut if (patIdxEnd != strIdxEnd) { return false; // Pattern and string do not have the same size } for (int i = 0; i <= patIdxEnd; i++) { ch = patArr[i]; if (ch != '?') { if (ch != strArr[i]) { return false;// Character mismatch } } } return true; // String matches against pattern } if (patIdxEnd == 0) { return true; // Pattern contains only '*', which matches anything } // Process characters before first star while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { if (ch != '?') { if (ch != strArr[strIdxStart]) { return false;// Character mismatch } } patIdxStart++; strIdxStart++; } if (strIdxStart > strIdxEnd) { // All characters in the string are used. Check if only '*'s are // left in the pattern. If so, we succeeded. Otherwise failure. for (int i = patIdxStart; i <= patIdxEnd; i++) { if (patArr[i] != '*') { return false; } } return true; } // Process characters after last star while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { if (ch != '?') { if (ch != strArr[strIdxEnd]) { return false;// Character mismatch } } patIdxEnd--; strIdxEnd--; } if (strIdxStart > strIdxEnd) { // All characters in the string are used. Check if only '*'s are // left in the pattern. If so, we succeeded. Otherwise failure. for (int i = patIdxStart; i <= patIdxEnd; i++) { if (patArr[i] != '*') { return false; } } return true; } // process pattern between stars. padIdxStart and patIdxEnd point // always to a '*'. while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { int patIdxTmp = -1; for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { if (patArr[i] == '*') { patIdxTmp = i; break; } } if (patIdxTmp == patIdxStart + 1) { // Two stars next to each other, skip the first one. patIdxStart++; continue; } // Find the pattern between padIdxStart & padIdxTmp in str between // strIdxStart & strIdxEnd int patLength = (patIdxTmp - patIdxStart - 1); int strLength = (strIdxEnd - strIdxStart + 1); int foundIdx = -1; strLoop: for (int i = 0; i <= strLength - patLength; i++) { for (int j = 0; j < patLength; j++) { ch = patArr[patIdxStart + j + 1]; if (ch != '?') { if (ch != strArr[strIdxStart + i + j]) { continue strLoop; } } } foundIdx = strIdxStart + i; break; } if (foundIdx == -1) { return false; } patIdxStart = patIdxTmp; strIdxStart = foundIdx + patLength; } // All characters in the string are used. Check if only '*'s are left // in the pattern. If so, we succeeded. Otherwise failure. for (int i = patIdxStart; i <= patIdxEnd; i++) { if (patArr[i] != '*') { return false; } } return true; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy