/* * Copyright (C) ${year} Omry Yadan <${email}> * All rights reserved. * * See https://github.com/omry/banana/blob/master/BSD-LICENSE for licensing information */ package net.yadan.utils; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.util.regex.Pattern; /** * @author omry * @date Dec 18, 2008 */ public class GlobFilter implements FileFilter, FilenameFilter { Pattern pattern; String globPattern; private boolean m_invert; boolean m_includeDirs = true; public GlobFilter(String pattern) { this(pattern, false); } public GlobFilter(String pattern, boolean invert) { setPattern(pattern); m_invert = invert; } public GlobFilter(String pattern, boolean invert, boolean includeDirs) { setPattern(pattern); m_invert = invert; m_includeDirs = includeDirs; } public void setPattern(String globPattern) { this.globPattern = globPattern; this.pattern = globPattern(globPattern); } public static Pattern globPattern(String globPattern) { char[] gPat = globPattern.toCharArray(); char[] rPat = new char[gPat.length * 2]; boolean isWin32 = (File.separatorChar == '\\'); boolean inBrackets = false; int j = 0; if (isWin32) { // On windows, a pattern ending with *.* is equal to ending with // * int len = gPat.length; if (globPattern.endsWith("*.*")) { len -= 2; } for (int i = 0; i < len; i++) { switch (gPat[i]) { case '*': rPat[j++] = '.'; rPat[j++] = '*'; break; case '?': rPat[j++] = '.'; break; case '\\': rPat[j++] = '\\'; rPat[j++] = '\\'; break; default: if ("+()^$.{}[]".indexOf(gPat[i]) >= 0) { rPat[j++] = '\\'; } rPat[j++] = gPat[i]; break; } } } else { for (int i = 0; i < gPat.length; i++) { switch (gPat[i]) { case '*': if (!inBrackets) { rPat[j++] = '.'; } rPat[j++] = '*'; break; case '?': rPat[j++] = inBrackets ? '?' : '.'; break; case '[': inBrackets = true; rPat[j++] = gPat[i]; if (i < gPat.length - 1) { switch (gPat[i + 1]) { case '!': case '^': rPat[j++] = '^'; i++; break; case ']': rPat[j++] = gPat[++i]; break; } } break; case ']': rPat[j++] = gPat[i]; inBrackets = false; break; case '\\': if (i == 0 && gPat.length > 1 && gPat[1] == '~') { rPat[j++] = gPat[++i]; } else { rPat[j++] = '\\'; if (i < gPat.length - 1 && "*?[]".indexOf(gPat[i + 1]) >= 0) { rPat[j++] = gPat[++i]; } else { rPat[j++] = '\\'; } } break; default: // if ("+()|^$.{}<>".indexOf(gPat[i]) >= 0) { if (!Character.isLetterOrDigit(gPat[i])) { rPat[j++] = '\\'; } rPat[j++] = gPat[i]; break; } } } Pattern pat = Pattern.compile(new String(rPat, 0, j), Pattern.CASE_INSENSITIVE); return pat; } public boolean accept(File f) { return accept(f.getParentFile(), f.getName()); } public boolean matches(String name) { boolean b = pattern.matcher(name).matches(); if (m_invert) return !b; else return b; } @Override public String toString() { return "Filter: " + globPattern; } @Override public boolean accept(File dir, String name) { File f = new File(dir, name); if (m_includeDirs && f.isDirectory()) { return true; } return matches(name); } }