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

aQute.lib.fileset.FileSet Maven / Gradle / Ivy

The newest version!
package aQute.lib.fileset;

import java.io.File;
import java.net.URI;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import aQute.lib.io.IO;
import aQute.libg.glob.Glob;

/**
 * Implements a FileSet a la Ant/Gradle. A file set is a specification of a set
 * of files. A file set specification contains a number of '/' separated
 * segments. The last segment is Glob expression and the preceding segments
 * specify either a directory, a wildcard directory ('*'), or a set of wildcard
 * directories ('**').
 *
 * 
 * filesets ::= fileset ( ',' fileset )*
 * fileset  ::= ( segment '/' )* filematch
 * segment  ::= any | glob
 * glob     ::= 
 * any      ::= '**'
 * filematch::= allfile | anyfile | glob
 * anyfile  ::= '**' glob
 * allfile  ::= '**'
 * 
*/ public class FileSet { private final File base; private DFA dfa; private String source; public FileSet(File base, String filesetSpec) { this.source = filesetSpec; this.dfa = compile(base, filesetSpec); this.base = base; } public FileSet(File base, String filematch, Collection allsourcepath) { StringBuilder sb = new StringBuilder(); String del = ""; for (String f : allsourcepath) { if (f.endsWith("/")) f = f.substring(0, f.length() - 1); sb.append(del) .append(f) .append("/**/" + filematch); del = ","; } this.source = sb.toString(); this.dfa = compile(base, this.source); this.base = base; } /* * Compile the file set specification to a DFA */ private static DFA compile(File base, String filesetSpec) { String parts[] = filesetSpec.trim() .split("\\s*,\\s*"); DFA result = null; for (String part : parts) { if (part.startsWith("/")) throw new IllegalArgumentException("FileSet must not start with a /"); // if we end in allfile (**), turn it in to any/all if (part.endsWith("**")) part = part + "/*"; if (part.endsWith("/")) part = part + "**/*"; else { File dirq = IO.getFile(base, part); if (dirq.isDirectory()) part += "/**/*"; } String[] segments = part.split("/"); String lastSegment = segments[segments.length - 1]; // anyfile (**.ts) DFA prev; if (lastSegment.startsWith("**")) { prev = new AnyDir(new FileMatch(lastSegment.substring(1))); } else prev = new FileMatch(lastSegment); for (int i = segments.length - 2; i >= 0; i--) { String segment = segments[i]; if (segment.equals("**")) prev = new AnyDir(prev); else prev = new DirMatch(prev, segment); } if (result == null) result = prev; else { result = new OrDFA(result, prev); } } return result; } public Set getFiles() { Set files = new HashSet<>(); if (base.isDirectory()) { for (File sub : IO.listFiles(base)) { dfa.match(files, sub); } } return files; } public boolean isIncluded(File file) { URI target = file.toURI(); URI source = base.toURI(); URI relative = source.relativize(target); if (relative.equals(target) || relative.equals(source)) return false; String[] segments = relative.getPath() .split("/"); if (dfa.isIncluded(segments, 0)) return true; return false; } public boolean isIncluded(String relativePath) { if (relativePath.startsWith("/")) throw new IllegalArgumentException("FileSet must not start with a /"); String[] segments = relativePath.split("/"); if (dfa.isIncluded(segments, 0)) return true; return false; } public boolean hasOverlap(Collection files) { for (File f : files) { if (isIncluded(f)) return true; } return false; } public File findFirst(String file) { for (File f : getFiles()) { if (f.getName() .equals(file)) return f; } return null; } /* * Deterministic Finite Automata */ static abstract class DFA { abstract void match(Collection files, File input); abstract boolean isIncluded(String segments[], int n); } /* * Implements an Or state, both paths are executed in parallel */ static class OrDFA extends DFA { private DFA a; private DFA b; public OrDFA(DFA a, DFA b) { this.a = a; this.b = b; } @Override void match(Collection files, File input) { a.match(files, input); b.match(files, input); } @Override boolean isIncluded(String[] segments, int n) { return a.isIncluded(segments, n) || b.isIncluded(segments, n); } } /* * Must match a directory with a glob expression */ static class DirMatch extends DFA { final Glob glob; final DFA next; DirMatch(DFA next, String segment) { this.next = next; this.glob = new Glob(segment); } @Override void match(Collection files, File input) { if (input.isDirectory()) { if (glob.matcher(input.getName()) .matches()) { for (File sub : IO.listFiles(input)) { next.match(files, sub); } } } } @Override boolean isIncluded(String segments[], int n) { if (n >= segments.length - 1) return false; if (!glob.matcher(segments[n]) .matches()) return false; return next.isIncluded(segments, n + 1); } } /* * Matches ANY depth of directories, including zero. */ static class AnyDir extends DFA { final DFA next; AnyDir(DFA next) { this.next = next; } @Override void match(Collection files, File input) { if (input.isDirectory()) { for (File sub : IO.listFiles(input)) { next.match(files, sub); this.match(files, sub); } } else next.match(files, input); } @Override boolean isIncluded(String segments[], int n) { if (n >= segments.length - 1) return false; return next.isIncluded(segments, n + 1) || this.isIncluded(segments, n + 1); } } /* * Match a file name with a glob */ static class FileMatch extends DFA { final Glob glob; FileMatch(String string) { this.glob = new Glob(string); } @Override void match(Collection files, File input) { if (input.isFile()) { if (glob.matcher(input.getName()) .matches()) files.add(input); } } @Override boolean isIncluded(String segments[], int n) { if (n != segments.length - 1) return false; return glob.matcher(segments[n]) .matches(); } } @Override public String toString() { return source; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy