package com.isti.traceview.common;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.log4j.Logger;
import com.isti.traceview.TraceView;
import com.isti.traceview.TraceViewException;
/**
* this class realize unix command line wildcard syntax
*
* @author Max Kokoulin
*/
public class Wildcard {
private static final Logger logger = Logger.getLogger(Wildcard.class);
List<String> path = null;
List<File> lst = new ArrayList<File>();
/**
* @param pattern
* wildcard expression
* @param text
* text to test
* @return flag if text matches pattern
*/
public static boolean matches(String pattern, String text) {
boolean ret = text.matches(wildcardToRegex(pattern));
logger.debug("Match " + text + " with pattern " + wildcardToRegex(pattern) + ": " + ret);
return ret;
}
/**
* Finds files by mask
*
* @param mask
* wildcard expression to find file
* @return list of found files
* @throws TraceViewException if the mask is not parseable
*/
public List<File> getFilesByMask(String mask) throws TraceViewException {
lst.clear();
try {
if (TraceView.osNameString.contains("Windows")) {
String[] as = mask.replaceFirst(":\\\\\\\\", ":\\\\").split("\\\\");
path = new ArrayList<String>(Arrays.asList(as));
if (path.get(0).contains(":")) {
// absolute path
explore(path.get(0) + "\\\\", 0);
} else if (path.get(0).equals(".") || path.get(0).equals("..") || path.get(0).equals("~")) {
// relative path
explore(path.get(0), 0);
} else {
// relative path without point
path.add(0, ".");
explore(path.get(0), 0);
}
} else {
String[] as = mask.split(File.separator);
path = new ArrayList<String>(Arrays.asList(as));
if (path.get(0).equals(".") || path.get(0).equals("..") || path.get(0).equals("~")) {
// relative path
explore(path.get(0), 0);
} else if (path.get(0).equals("")) {
// absolute path
explore("/", 0);
} else {
// relative path without point
path.add(0, ".");
explore(path.get(0), 0);
}
}
} catch (Exception e) {
StringBuilder message = new StringBuilder();
message.append(String.format("Can't parse wildcarded path: '" + mask + "'" + e.toString()));
throw new TraceViewException(message.toString());
}
return lst;
}
/**
* Recursive searching
*
* @param partPath - currently exploring point of path
* @param i - current depth
*/
private void explore(String partPath, int i) {
File f = new File(partPath);
File[] dir = f.listFiles();
//System.out.format("== explore(partPath=%s i=%d) File f=%s path=%s (dir.length=%d)\n", partPath, i, f.getName(), f.getPath(), dir.length);
if (dir.length > 0) {
for (int j = 0; j < dir.length; j++) {
if (path.size() > i + 1) {
if (Wildcard.matches(path.get(i + 1), dir[j].getName())) {
if (dir[j].isDirectory()) {
explore(partPath + File.separator + dir[j].getName(), i + 1);
} else {
//lst.add(dir[j]);
// MTH: This was adding matches *along* the path, not just at the terminus, e.g.,
// -d 'xs0/seed/*/2012/2012_160*/*seed' was matching xs0/seed/jts.seed
// Added if statement to make sure we only match at the end of the path
// This has not been tested on Windows!
if ((path.size() - i) == 2) {
//System.out.format("== +++ Found matching file=[%s] [path.size()=%d i=%d]\n", dir[j], path.size(), i);
lst.add(dir[j]);
}
}
}
} else {
if (dir[j].isDirectory()) {
explore(partPath + File.separator + dir[j].getName(), i + 1);
} else {
lst.add(dir[j]);
}
}
}
}
}
public static String wildcardToRegex(String wild) {
if (wild == null)
return null;
StringBuffer buffer = new StringBuffer();
char[] chars = wild.toCharArray();
for (int i = 0; i < chars.length; ++i) {
if (chars[i] == '*')
buffer.append(".*");
else if (chars[i] == '?')
buffer.append(".");
else if (chars[i] == '!')
buffer.append("^");
else if (chars[i] == '{')
buffer.append("(");
else if (chars[i] == '}')
buffer.append(")");
else if (chars[i] == ',')
buffer.append("|");
else if ("+()^$.|\\".indexOf(chars[i]) != -1)
buffer.append('\\').append(chars[i]); // prefix all unused metacharacters with
// backslash
else
buffer.append(chars[i]);
}
return buffer.toString();
}
}