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

org.metricssampler.config.loader.FileGlob Maven / Gradle / Ivy

The newest version!
package org.metricssampler.config.loader;

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Matches relative paths to files against a glob expression. The supported glob expressions are:
 * 
    *
  • '*' - any number of characters different from the path separator
  • *
  • '**' - any number of directories (including none)
  • *
* Both '/' and '\' are recognized as path separators not just the system's path separator */ public class FileGlob { private final PathSegmentPattern[] patterns; public static String[] tokenize(final String path) { if (path == null) { throw new IllegalArgumentException("Parameter path may not be null"); } final int len = path.length(); int prev = 0; final List result = new LinkedList(); for (int i = 0; i < len; i++) { final char c = path.charAt(i); if (c == '/' || c == '\\') { result.add(path.substring(prev, i)); prev = i + 1; } } if (prev < len) { result.add(path.substring(prev)); } return result.toArray(new String[result.size()]); } /** * @param file the file * @param basedir the base directory * @return The path of file relative to basedir. Note that the file must be a descendant * of basedir. * * @throws IllegalArgumentException if file is not a descendant of basedir */ public static String relativePath(final File file, final File basedir) { final String filePath = file.getPath(); final String basePath = basedir.getPath(); final String shouldBeBasePath = filePath.substring(0, basePath.length()); if (!shouldBeBasePath.equals(basePath)) { throw new IllegalArgumentException(file + " is not a descendant of " + basedir); } final String path = filePath.substring(basePath.length(), filePath.length()); if (path.length() > 0) { final char firstChar = path.charAt(0); if ((firstChar == '/') || (firstChar == '\\')) { return path.substring(1, path.length()); } } return path; } public static abstract class PathSegmentPattern { private final boolean reusable; private final boolean optional; public PathSegmentPattern(final boolean reusable, final boolean optional) { this.reusable = reusable; this.optional = optional; } public abstract boolean matches(String name, boolean directory); public boolean isReusable() { return reusable; } public boolean isOptional() { return optional; } } public static class AnyPathSegmentPattern extends PathSegmentPattern { private final boolean directory; public AnyPathSegmentPattern(final boolean directory) { super(true, true); this.directory = directory; } @Override public boolean matches(final String name, final boolean directory) { return this.directory == directory; } @Override public String toString() { return "**"; } } public static class NamePathSegmentPattern extends PathSegmentPattern { private final String name; private final boolean directory; public NamePathSegmentPattern(final String name, final boolean directory) { super(false, false); this.name = name; this.directory = directory; } @Override public boolean matches(final String name, final boolean directory) { if (this.directory == directory) { return this.name.equals(name); } return false; } @Override public String toString() { return name; } } public static class NameExpressionPathSegmentPattern extends PathSegmentPattern { private final String expression; private final boolean directory; private final Pattern pattern; public NameExpressionPathSegmentPattern(final String expression, final boolean directory) { super(false, false); this.expression = expression; this.directory = directory; this.pattern = Pattern.compile(expression.replaceAll("\\*", ".*")); } @Override public boolean matches(final String name, final boolean directory) { if (this.directory == directory) { return pattern.matcher(name).matches(); } return false; } @Override public String toString() { return expression; } } public FileGlob(final String expression) { patterns = compileExpression(expression); } public boolean matches(final File file, final File basedir) { final String relativePath = relativePath(file, basedir); final String[] pathItems = tokenize(relativePath); return internalMatches(pathItems, 0, 0); } protected boolean internalMatches(final String[] paths, final int patternIndex, final int pathIndex) { if (pathIndex == paths.length) { return true; } if (patternIndex == patterns.length) { return false; } final String path = paths[pathIndex]; final PathSegmentPattern pattern = patterns[patternIndex]; final boolean isDirectory = pathIndex != paths.length - 1; if (pattern.matches(path, isDirectory)) { if (pattern.isReusable()) { // try reusing it final boolean result = internalMatches(paths, patternIndex, pathIndex + 1); if (result) { return true; } } return internalMatches(paths, patternIndex + 1, pathIndex + 1); } else { if (pattern.isOptional()) { return internalMatches(paths, patternIndex + 1, pathIndex); } else { return false; } } } public static PathSegmentPattern[] compileExpression(final String expression) { final String[] tokens = tokenize(expression); final PathSegmentPattern[] patterns = new PathSegmentPattern[tokens.length]; int i = 0; for (final String token : tokens) { if ("**".equals(token)) { patterns[i] = new AnyPathSegmentPattern(true); } else { final boolean isDirectoryToken = i != tokens.length - 1; if (token.contains("*")) { patterns[i] = new NameExpressionPathSegmentPattern(token, isDirectoryToken); } else { patterns[i] = new NamePathSegmentPattern(token, isDirectoryToken); } } i++; } return patterns; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy