/* * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.nio.fs; import java.util.regex.PatternSyntaxException; public class Globs { private Globs() { } private static final String regexMetaChars = ".^$+{[]|()"; private static final String globMetaChars = "\\*?[{"; private static boolean isRegexMeta(char c) { return regexMetaChars.indexOf(c) != -1; } private static boolean isGlobMeta(char c) { return globMetaChars.indexOf(c) != -1; } private static char EOL = 0; //TBD private static char next(String glob, int i) { if (i < glob.length()) { return glob.charAt(i); } return EOL; } /** * Creates a regex pattern from the given glob expression. * * @throws PatternSyntaxException */ private static String toRegexPattern(String globPattern, boolean isDos) { boolean inGroup = false; StringBuilder regex = new StringBuilder("^"); int i = 0; while (i < globPattern.length()) { char c = globPattern.charAt(i++); switch (c) { case '\\': // escape special characters if (i == globPattern.length()) { throw new PatternSyntaxException("No character to escape", globPattern, i - 1); } char next = globPattern.charAt(i++); if (isGlobMeta(next) || isRegexMeta(next)) { regex.append('\\'); } regex.append(next); break; case '/': if (isDos) { regex.append("\\\\"); } else { regex.append(c); } break; case '[': // don't match name separator in class if (isDos) { regex.append("[[^\\\\]&&["); } else { regex.append("[[^/]&&["); } if (next(globPattern, i) == '^') { // escape the regex negation char if it appears regex.append("\\^"); i++; } else { // negation if (next(globPattern, i) == '!') { regex.append('^'); i++; } // hyphen allowed at start if (next(globPattern, i) == '-') { regex.append('-'); i++; } } boolean hasRangeStart = false; char last = 0; while (i < globPattern.length()) { c = globPattern.charAt(i++); if (c == ']') { break; } if (c == '/' || (isDos && c == '\\')) { throw new PatternSyntaxException("Explicit 'name separator' in class", globPattern, i - 1); } // TBD: how to specify ']' in a class? if (c == '\\' || c == '[' || c == '&' && next(globPattern, i) == '&') { // escape '\', '[' or "&&" for regex class regex.append('\\'); } regex.append(c); if (c == '-') { if (!hasRangeStart) { throw new PatternSyntaxException("Invalid range", globPattern, i - 1); } if ((c = next(globPattern, i++)) == EOL || c == ']') { break; } if (c < last) { throw new PatternSyntaxException("Invalid range", globPattern, i - 3); } regex.append(c); hasRangeStart = false; } else { hasRangeStart = true; last = c; } } if (c != ']') { throw new PatternSyntaxException("Missing ']", globPattern, i - 1); } regex.append("]]"); break; case '{': if (inGroup) { throw new PatternSyntaxException("Cannot nest groups", globPattern, i - 1); } regex.append("(?:(?:"); inGroup = true; break; case '}': if (inGroup) { regex.append("))"); inGroup = false; } else { regex.append('}'); } break; case ',': if (inGroup) { regex.append(")|(?:"); } else { regex.append(','); } break; case '*': if (next(globPattern, i) == '*') { // crosses directory boundaries regex.append(".*"); i++; } else { // within directory boundary if (isDos) { regex.append("[^\\\\]*"); } else { regex.append("[^/]*"); } } break; case '?': if (isDos) { regex.append("[^\\\\]"); } else { regex.append("[^/]"); } break; default: if (isRegexMeta(c)) { regex.append('\\'); } regex.append(c); } } if (inGroup) { throw new PatternSyntaxException("Missing '}", globPattern, i - 1); } return regex.append('$').toString(); } static String toUnixRegexPattern(String globPattern) { return toRegexPattern(globPattern, false); } static String toWindowsRegexPattern(String globPattern) { return toRegexPattern(globPattern, true); } }