Embedded esoteric wildcard project to provide access to internal fields and rename methods to follow a more "standard" naming scheme
This commit is contained in:
parent
b98d9b1c53
commit
4cee6c1d34
|
@ -16,6 +16,8 @@
|
|||
<orderEntry type="library" name="logging slf4j-api" level="application" />
|
||||
<orderEntry type="library" name="dorkbox minlog_slf4j" level="application" />
|
||||
<orderEntry type="library" name="dorkbox annotations" level="application" />
|
||||
<orderEntry type="library" name="dorkbox console" level="application" />
|
||||
<orderEntry type="library" name="dorkbox shell_executor" level="application" />
|
||||
<orderEntry type="library" name="bouncyCastle bcpg-jdk15on" level="application" />
|
||||
<orderEntry type="library" name="bouncyCastle bcpkix-jdk15on" level="application" />
|
||||
<orderEntry type="library" name="bouncyCastle bcprov-jdk15on" level="application" />
|
||||
|
@ -30,7 +32,6 @@
|
|||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="wildcard" level="application" />
|
||||
<orderEntry type="library" name="javaparser" level="application" />
|
||||
<orderEntry type="library" name="javatar" level="application" />
|
||||
<orderEntry type="library" name="async-http-client" level="application" />
|
||||
|
@ -39,4 +40,4 @@
|
|||
<orderEntry type="library" name="yamlbeans" level="application" />
|
||||
<orderEntry type="library" name="kryo" level="application" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
|
@ -42,53 +42,6 @@ class Build {
|
|||
} catch (Exception ignored) {
|
||||
System.err.println("CRITICAL:: Can't load javaFX to the classpath URLS");
|
||||
}
|
||||
|
||||
|
||||
File runLocation = get();
|
||||
if (runLocation != null) {
|
||||
// we want to look for the libraries, because they are OFTEN going to be in the incorrect path.
|
||||
// this is only necessary if they aren't correctly loaded.
|
||||
try {
|
||||
Class.forName("com.esotericsoftware.wildcard.Paths");
|
||||
} catch (Exception e) {
|
||||
// whoops. can't find it on the path
|
||||
|
||||
File parent = runLocation.getParentFile();
|
||||
File libDir = new File(parent, "libs");
|
||||
|
||||
if (!libDir.isDirectory()) {
|
||||
libDir = new File(parent.getParentFile(), "libs");
|
||||
}
|
||||
|
||||
if (!libDir.isDirectory()) {
|
||||
throw new RuntimeException("Unable to find the libs directory for execution: " + runLocation);
|
||||
}
|
||||
|
||||
Class<?>[] parameters = new Class[] {URL.class};
|
||||
Class<URLClassLoader> sysclass = URLClassLoader.class;
|
||||
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||
|
||||
try {
|
||||
Method method = sysclass.getDeclaredMethod("addURL", parameters);
|
||||
method.setAccessible(true);
|
||||
|
||||
// add lib dir jars
|
||||
for (File f : libDir.listFiles()) {
|
||||
final String name = f.getName();
|
||||
if (!f.isDirectory() && f.canRead() && name.endsWith(".jar") && !name.contains("source") && !name.contains("src")) {
|
||||
// System.err.println("adding url " + f.getAbsolutePath());
|
||||
method.invoke(sysloader, new Object[] {f.toURI().toURL()});
|
||||
}
|
||||
}
|
||||
|
||||
// try to load the library again to make sure the libs loaded
|
||||
Class.forName("com.esotericsoftware.wildcard.Paths");
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
throw new RuntimeException("Unable to load the libs directory for execution: " + libDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static
|
||||
|
|
|
@ -10,9 +10,8 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
|
||||
import dorkbox.build.util.BuildLog;
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
import dorkbox.util.FileUtil;
|
||||
import dorkbox.util.IO;
|
||||
import dorkbox.util.OS;
|
||||
|
|
|
@ -37,8 +37,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
|
||||
import dorkbox.annotation.AnnotationDefaults;
|
||||
import dorkbox.annotation.AnnotationDetector;
|
||||
import dorkbox.build.Project;
|
||||
|
@ -50,6 +48,7 @@ import dorkbox.build.util.FileNotFoundRuntimeException;
|
|||
import dorkbox.build.util.classloader.ByteClassloader;
|
||||
import dorkbox.build.util.classloader.ClassByteIterator;
|
||||
import dorkbox.build.util.jar.Pack200Util;
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
import dorkbox.util.FileUtil;
|
||||
import dorkbox.util.IO;
|
||||
import dorkbox.util.LZMA;
|
||||
|
|
|
@ -3,13 +3,12 @@ package dorkbox.build;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
|
||||
import dorkbox.build.util.BuildLog;
|
||||
import dorkbox.build.util.PreJarAction;
|
||||
import dorkbox.build.util.jar.JarOptions;
|
||||
import dorkbox.build.util.jar.JarSigner;
|
||||
import dorkbox.build.util.jar.JarUtil;
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package dorkbox.build.util;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
|
||||
public
|
||||
class CrossCompileClass {
|
||||
|
|
|
@ -28,11 +28,10 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
|
||||
import dorkbox.BuildOptions;
|
||||
import dorkbox.Builder;
|
||||
import dorkbox.build.Project;
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
import dorkbox.util.Base64Fast;
|
||||
import dorkbox.util.IO;
|
||||
|
||||
|
|
|
@ -17,9 +17,8 @@ package dorkbox.build.util;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
|
||||
import dorkbox.Builder;
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
|
||||
public
|
||||
class ShutdownHook implements Runnable {
|
||||
|
|
|
@ -15,14 +15,7 @@
|
|||
*/
|
||||
package dorkbox.build.util.classloader;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -31,6 +24,15 @@ import java.net.URI;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
|
||||
public class JavaMemFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
|
||||
|
||||
static class ClassMemFileObject extends SimpleJavaFileObject {
|
||||
|
|
|
@ -20,8 +20,7 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
import dorkbox.license.License;
|
||||
|
||||
public class JarOptions {
|
||||
|
|
|
@ -55,7 +55,6 @@ import java.util.zip.ZipOutputStream;
|
|||
|
||||
import org.bouncycastle.crypto.digests.SHA512Digest;
|
||||
|
||||
import com.esotericsoftware.wildcard.Paths;
|
||||
import com.ice.tar.TarEntry;
|
||||
import com.ice.tar.TarInputStream;
|
||||
|
||||
|
@ -63,6 +62,7 @@ import dorkbox.BuildOptions;
|
|||
import dorkbox.Builder;
|
||||
import dorkbox.build.Project;
|
||||
import dorkbox.build.util.BuildLog;
|
||||
import dorkbox.build.util.wildcard.Paths;
|
||||
import dorkbox.license.License;
|
||||
import dorkbox.util.Base64Fast;
|
||||
import dorkbox.util.FileUtil;
|
||||
|
@ -386,6 +386,40 @@ class JarUtil {
|
|||
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputFile file to get the contents from (excluding manifest info and directory names)
|
||||
*
|
||||
* @return list of files, null if there are problems
|
||||
*/
|
||||
public static
|
||||
List<String> getJarContents(File inputFile) {
|
||||
// by default, this will not have access to the manifest! (not that we care...)
|
||||
// we will ALSO lose entry comments!
|
||||
try {
|
||||
JarInputStream jarInputStream = new JarInputStream(new FileInputStream(inputFile), false);
|
||||
|
||||
ArrayList<String> contents = new ArrayList<>();
|
||||
|
||||
JarEntry entry;
|
||||
while ((entry = jarInputStream.getNextJarEntry()) != null) {
|
||||
if (!entry.isDirectory()) {
|
||||
String name = entry.getName();
|
||||
|
||||
contents.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
// finish the stream that we have been writing to
|
||||
IO.close(jarInputStream);
|
||||
|
||||
return contents;
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This will also install the specified licenses, and for JARs, this will ALSO normalize (pack+unpack) the jar
|
||||
* <p/>
|
||||
|
@ -475,15 +509,15 @@ class JarUtil {
|
|||
|
||||
int totalEntries = 0;
|
||||
if (options.inputPaths != null) {
|
||||
totalEntries += options.inputPaths.count();
|
||||
totalEntries += options.inputPaths.size();
|
||||
}
|
||||
|
||||
if (options.extraPaths != null) {
|
||||
totalEntries += options.extraPaths.count();
|
||||
totalEntries += options.extraPaths.size();
|
||||
}
|
||||
|
||||
if (options.sourcePaths != null) {
|
||||
totalEntries += options.sourcePaths.count();
|
||||
totalEntries += options.sourcePaths.size();
|
||||
}
|
||||
|
||||
BuildLog.println();
|
||||
|
@ -697,7 +731,7 @@ class JarUtil {
|
|||
// These files will MATCH the path hierarchy in the jar
|
||||
///////////////////////////////////////////////
|
||||
if (options.extraPaths != null) {
|
||||
final int count = options.extraPaths.count();
|
||||
final int count = options.extraPaths.size();
|
||||
List<SortedFiles> sortList = new ArrayList<SortedFiles>(count);
|
||||
|
||||
if (count > 0) {
|
||||
|
@ -728,9 +762,9 @@ class JarUtil {
|
|||
// include the source code if possible
|
||||
///////////////////////////////////////////////
|
||||
if (options.sourcePaths != null && !options.sourcePaths.isEmpty()) {
|
||||
List<SortedFiles> sortList = new ArrayList<SortedFiles>(options.sourcePaths.count());
|
||||
List<SortedFiles> sortList = new ArrayList<SortedFiles>(options.sourcePaths.size());
|
||||
|
||||
BuildLog.println("\tAdding sources (" + options.sourcePaths.count() + " entries)...");
|
||||
BuildLog.println("\tAdding sources (" + options.sourcePaths.size() + " entries)...");
|
||||
|
||||
fullPaths = options.sourcePaths.getPaths();
|
||||
relativePaths = options.sourcePaths.getRelativePaths();
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Nathan Sweet
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Modified by dorkbox, llc
|
||||
*/
|
||||
package dorkbox.build.util.wildcard;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
class GlobScanner {
|
||||
private final File rootDir;
|
||||
private final List<String> matches = new ArrayList(128);
|
||||
|
||||
public GlobScanner (File rootDir, List<String> includes, List<String> excludes) {
|
||||
if (rootDir == null) throw new IllegalArgumentException("rootDir cannot be null.");
|
||||
if (!rootDir.exists()) throw new IllegalArgumentException("Directory does not exist: " + rootDir);
|
||||
if (!rootDir.isDirectory()) throw new IllegalArgumentException("File must be a directory: " + rootDir);
|
||||
try {
|
||||
rootDir = rootDir.getCanonicalFile();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("OS error determining canonical path: " + rootDir, ex);
|
||||
}
|
||||
this.rootDir = rootDir;
|
||||
|
||||
if (includes == null) throw new IllegalArgumentException("includes cannot be null.");
|
||||
if (excludes == null) throw new IllegalArgumentException("excludes cannot be null.");
|
||||
|
||||
if (includes.isEmpty()) includes.add("**");
|
||||
List<Pattern> includePatterns = new ArrayList(includes.size());
|
||||
for (String include : includes)
|
||||
includePatterns.add(new Pattern(include));
|
||||
|
||||
List<Pattern> allExcludePatterns = new ArrayList(excludes.size());
|
||||
for (String exclude : excludes)
|
||||
allExcludePatterns.add(new Pattern(exclude));
|
||||
|
||||
scanDir(rootDir, includePatterns);
|
||||
|
||||
if (!allExcludePatterns.isEmpty()) {
|
||||
// For each file, see if any exclude patterns match.
|
||||
outerLoop:
|
||||
//
|
||||
for (Iterator matchIter = matches.iterator(); matchIter.hasNext();) {
|
||||
String filePath = (String)matchIter.next();
|
||||
List<Pattern> excludePatterns = new ArrayList(allExcludePatterns);
|
||||
try {
|
||||
// Shortcut for excludes that are "**/XXX", just check file name.
|
||||
for (Iterator excludeIter = excludePatterns.iterator(); excludeIter.hasNext();) {
|
||||
Pattern exclude = (Pattern)excludeIter.next();
|
||||
if (exclude.values.length == 2 && exclude.values[0].equals("**")) {
|
||||
exclude.incr();
|
||||
String fileName = filePath.substring(filePath.lastIndexOf(File.separatorChar) + 1);
|
||||
if (exclude.matches(fileName)) {
|
||||
matchIter.remove();
|
||||
continue outerLoop;
|
||||
}
|
||||
excludeIter.remove();
|
||||
}
|
||||
}
|
||||
// Get the file names after the root dir.
|
||||
String[] fileNames = filePath.split("\\" + File.separator);
|
||||
for (String fileName : fileNames) {
|
||||
for (Iterator excludeIter = excludePatterns.iterator(); excludeIter.hasNext();) {
|
||||
Pattern exclude = (Pattern)excludeIter.next();
|
||||
if (!exclude.matches(fileName)) {
|
||||
excludeIter.remove();
|
||||
continue;
|
||||
}
|
||||
exclude.incr(fileName);
|
||||
if (exclude.wasFinalMatch()) {
|
||||
// Exclude pattern matched.
|
||||
matchIter.remove();
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
// Stop processing the file if none of the exclude patterns matched.
|
||||
if (excludePatterns.isEmpty()) continue outerLoop;
|
||||
}
|
||||
} finally {
|
||||
for (Pattern exclude : allExcludePatterns)
|
||||
exclude.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanDir (File dir, List<Pattern> includes) {
|
||||
if (!dir.canRead()) return;
|
||||
|
||||
// See if patterns are specific enough to avoid scanning every file in the directory.
|
||||
boolean scanAll = false;
|
||||
for (Pattern include : includes) {
|
||||
if (include.value.indexOf('*') != -1 || include.value.indexOf('?') != -1) {
|
||||
scanAll = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scanAll) {
|
||||
// If not scanning all the files, we know exactly which ones to include.
|
||||
List matchingIncludes = new ArrayList(1);
|
||||
for (Pattern include : includes) {
|
||||
if (matchingIncludes.isEmpty())
|
||||
matchingIncludes.add(include);
|
||||
else
|
||||
matchingIncludes.set(0, include);
|
||||
process(dir, include.value, matchingIncludes);
|
||||
}
|
||||
} else {
|
||||
// Scan every file.
|
||||
for (String fileName : dir.list()) {
|
||||
// Get all include patterns that match.
|
||||
List<Pattern> matchingIncludes = new ArrayList(includes.size());
|
||||
for (Pattern include : includes)
|
||||
if (include.matches(fileName)) matchingIncludes.add(include);
|
||||
if (matchingIncludes.isEmpty()) continue;
|
||||
process(dir, fileName, matchingIncludes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void process (File dir, String fileName, List<Pattern> matchingIncludes) {
|
||||
// Increment patterns that need to move to the next token.
|
||||
boolean isFinalMatch = false;
|
||||
List<Pattern> incrementedPatterns = new ArrayList();
|
||||
for (Iterator iter = matchingIncludes.iterator(); iter.hasNext();) {
|
||||
Pattern include = (Pattern)iter.next();
|
||||
if (include.incr(fileName)) {
|
||||
incrementedPatterns.add(include);
|
||||
if (include.isExhausted()) iter.remove();
|
||||
}
|
||||
if (include.wasFinalMatch()) isFinalMatch = true;
|
||||
}
|
||||
|
||||
File file = new File(dir, fileName);
|
||||
if (isFinalMatch) {
|
||||
int length = rootDir.getPath().length();
|
||||
if (!rootDir.getPath().endsWith(File.separator)) length++; // Lose starting slash.
|
||||
matches.add(file.getPath().substring(length));
|
||||
}
|
||||
if (!matchingIncludes.isEmpty() && file.isDirectory()) scanDir(file, matchingIncludes);
|
||||
|
||||
// Decrement patterns.
|
||||
for (Pattern include : incrementedPatterns)
|
||||
include.decr();
|
||||
}
|
||||
|
||||
public List<String> matches () {
|
||||
return matches;
|
||||
}
|
||||
|
||||
public File rootDir () {
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
static class Pattern {
|
||||
String value;
|
||||
final String[] values;
|
||||
|
||||
private int index;
|
||||
|
||||
Pattern (String pattern) {
|
||||
pattern = pattern.replace('\\', '/');
|
||||
pattern = pattern.replaceAll("\\*\\*[^/]", "**/*");
|
||||
pattern = pattern.replaceAll("[^/]\\*\\*", "*/**");
|
||||
// pattern = pattern.toLowerCase();
|
||||
values = pattern.split("/");
|
||||
value = values[0];
|
||||
}
|
||||
|
||||
boolean matches (String fileName) {
|
||||
if (value.equals("**")) return true;
|
||||
|
||||
// fileName = fileName.toLowerCase();
|
||||
|
||||
// Shortcut if no wildcards.
|
||||
if (value.indexOf('*') == -1 && value.indexOf('?') == -1) return fileName.equals(value);
|
||||
|
||||
int i = 0, j = 0;
|
||||
while (i < fileName.length() && j < value.length() && value.charAt(j) != '*') {
|
||||
if (value.charAt(j) != fileName.charAt(i) && value.charAt(j) != '?') return false;
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
// If reached end of pattern without finding a * wildcard, the match has to fail if not same length.
|
||||
if (j == value.length()) return fileName.length() == value.length();
|
||||
|
||||
int cp = 0;
|
||||
int mp = 0;
|
||||
while (i < fileName.length()) {
|
||||
if (j < value.length() && value.charAt(j) == '*') {
|
||||
if (j++ >= value.length()) return true;
|
||||
mp = j;
|
||||
cp = i + 1;
|
||||
} else if (j < value.length() && (value.charAt(j) == fileName.charAt(i) || value.charAt(j) == '?')) {
|
||||
j++;
|
||||
i++;
|
||||
} else {
|
||||
j = mp;
|
||||
i = cp++;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle trailing asterisks.
|
||||
while (j < value.length() && value.charAt(j) == '*')
|
||||
j++;
|
||||
|
||||
return j >= value.length();
|
||||
}
|
||||
|
||||
String nextValue () {
|
||||
if (index + 1 == values.length) return null;
|
||||
return values[index + 1];
|
||||
}
|
||||
|
||||
boolean incr (String fileName) {
|
||||
if (value.equals("**")) {
|
||||
if (index == values.length - 1) return false;
|
||||
incr();
|
||||
if (matches(fileName))
|
||||
incr();
|
||||
else {
|
||||
decr();
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
incr();
|
||||
return true;
|
||||
}
|
||||
|
||||
void incr () {
|
||||
index++;
|
||||
if (index >= values.length)
|
||||
value = null;
|
||||
else
|
||||
value = values[index];
|
||||
}
|
||||
|
||||
void decr () {
|
||||
index--;
|
||||
if (index > 0 && values[index - 1].equals("**")) index--;
|
||||
value = values[index];
|
||||
}
|
||||
|
||||
void reset () {
|
||||
index = 0;
|
||||
value = values[0];
|
||||
}
|
||||
|
||||
boolean isExhausted () {
|
||||
return index >= values.length;
|
||||
}
|
||||
|
||||
boolean isLast () {
|
||||
return index >= values.length - 1;
|
||||
}
|
||||
|
||||
boolean wasFinalMatch () {
|
||||
return isExhausted() || (isLast() && value.equals("**"));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args) {
|
||||
// System.out.println(new Paths("C:\\Java\\ls", "**"));
|
||||
List<String> includes = new ArrayList();
|
||||
includes.add("website/in*");
|
||||
// includes.add("**/lavaserver/**");
|
||||
List<String> excludes = new ArrayList();
|
||||
// excludes.add("**/*.php");
|
||||
// excludes.add("website/**/doc**");
|
||||
long start = System.nanoTime();
|
||||
List<String> files = new GlobScanner(new File(".."), includes, excludes).matches();
|
||||
long end = System.nanoTime();
|
||||
System.out.println(files.toString().replaceAll(", ", "\n").replaceAll("[\\[\\]]", ""));
|
||||
System.out.println((end - start) / 1000000f);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Nathan Sweet
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Modified by dorkbox, llc
|
||||
*/
|
||||
package dorkbox.build.util.wildcard;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public final
|
||||
class Path {
|
||||
public final String dir;
|
||||
public final String name;
|
||||
|
||||
public
|
||||
Path(String dir, String name) {
|
||||
this.dir = dir;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public
|
||||
String absolute() {
|
||||
return dir + name;
|
||||
}
|
||||
|
||||
public
|
||||
File file() {
|
||||
return new File(dir, name);
|
||||
}
|
||||
|
||||
public
|
||||
int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((dir == null) ? 0 : dir.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
public
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Path other = (Path) obj;
|
||||
if (dir == null) {
|
||||
if (other.dir != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!dir.equals(other.dir)) {
|
||||
return false;
|
||||
}
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,604 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Nathan Sweet
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Modified by dorkbox, llc
|
||||
*/
|
||||
package dorkbox.build.util.wildcard;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* Collects filesystem paths using wildcards, preserving the directory structure. Copies, deletes, and zips paths.
|
||||
*/
|
||||
@SuppressWarnings({"Duplicates", "WeakerAccess"})
|
||||
public
|
||||
class Paths implements Iterable<Path> {
|
||||
static private final Comparator<Path> LONGEST_TO_SHORTEST = new Comparator<Path>() {
|
||||
public
|
||||
int compare(Path s1, Path s2) {
|
||||
return s2.absolute()
|
||||
.length() - s1.absolute()
|
||||
.length();
|
||||
}
|
||||
};
|
||||
|
||||
static private List<String> defaultGlobExcludes;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the exclude patterns that will be used in addition to the excludes specified for all glob searches.
|
||||
*/
|
||||
static public
|
||||
void setDefaultGlobExcludes(String... defaultGlobExcludes) {
|
||||
Paths.defaultGlobExcludes = Arrays.asList(defaultGlobExcludes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a directory and all files and directories it contains.
|
||||
*/
|
||||
static private
|
||||
boolean deleteDirectory(File file) {
|
||||
if (file.exists()) {
|
||||
File[] files = file.listFiles();
|
||||
for (int i = 0, n = files.length; i < n; i++) {
|
||||
if (files[i].isDirectory()) {
|
||||
deleteDirectory(files[i]);
|
||||
}
|
||||
else {
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
return file.delete();
|
||||
}
|
||||
|
||||
final HashSet<Path> paths = new HashSet<Path>(32);
|
||||
|
||||
/**
|
||||
* Creates an empty Paths object.
|
||||
*/
|
||||
public
|
||||
Paths() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Paths object and calls {@link #glob(String, String[])} with the specified arguments.
|
||||
*/
|
||||
public
|
||||
Paths(File dir, String... patterns) {
|
||||
glob(dir.getAbsolutePath(), patterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Paths object and calls {@link #glob(String, String[])} with the specified arguments.
|
||||
*/
|
||||
public
|
||||
Paths(String dir, String... patterns) {
|
||||
glob(dir, patterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all files and directories in the specified directory matching the wildcard patterns.
|
||||
*
|
||||
* @param dir The directory containing the paths to collect. If it does not exist, no paths are collected. If null, "." is
|
||||
* assumed.
|
||||
* @param patterns The wildcard patterns of the paths to collect or exclude. Patterns may optionally contain wildcards
|
||||
* represented by asterisks and question marks. If empty or omitted then the dir parameter is split on the "|"
|
||||
* character, the first element is used as the directory and remaining are used as the patterns. If null, ** is
|
||||
* assumed (collects all paths).<br>
|
||||
* <br>
|
||||
* A single question mark (?) matches any single character. Eg, something? collects any path that is named
|
||||
* "something" plus any character.<br>
|
||||
* <br>
|
||||
* A single asterisk (*) matches any characters up to the next slash (/). Eg, *\*\something* collects any path that
|
||||
* has two directories of any name, then a file or directory that starts with the name "something".<br>
|
||||
* <br>
|
||||
* A double asterisk (**) matches any characters. Eg, **\something\** collects any path that contains a directory
|
||||
* named "something".<br>
|
||||
* <br>
|
||||
* A pattern starting with an exclamation point (!) causes paths matched by the pattern to be excluded, even if other
|
||||
* patterns would select the paths.
|
||||
*/
|
||||
public
|
||||
Paths glob(File dir, String... patterns) {
|
||||
return glob(dir.getAbsolutePath(), patterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all files and directories in the specified directory matching the wildcard patterns.
|
||||
*
|
||||
* @param dir The directory containing the paths to collect. If it does not exist, no paths are collected. If null, "." is
|
||||
* assumed.
|
||||
* @param patterns The wildcard patterns of the paths to collect or exclude. Patterns may optionally contain wildcards
|
||||
* represented by asterisks and question marks. If empty or omitted then the dir parameter is split on the "|"
|
||||
* character, the first element is used as the directory and remaining are used as the patterns. If null, ** is
|
||||
* assumed (collects all paths).<br>
|
||||
* <br>
|
||||
* A single question mark (?) matches any single character. Eg, something? collects any path that is named
|
||||
* "something" plus any character.<br>
|
||||
* <br>
|
||||
* A single asterisk (*) matches any characters up to the next slash (/). Eg, *\*\something* collects any path that
|
||||
* has two directories of any name, then a file or directory that starts with the name "something".<br>
|
||||
* <br>
|
||||
* A double asterisk (**) matches any characters. Eg, **\something\** collects any path that contains a directory
|
||||
* named "something".<br>
|
||||
* <br>
|
||||
* A pattern starting with an exclamation point (!) causes paths matched by the pattern to be excluded, even if other
|
||||
* patterns would select the paths.
|
||||
*/
|
||||
public
|
||||
Paths glob(String dir, String... patterns) {
|
||||
if (dir == null) {
|
||||
dir = ".";
|
||||
}
|
||||
if (patterns != null && patterns.length == 0) {
|
||||
String[] split = dir.split("\\|");
|
||||
if (split.length > 1) {
|
||||
dir = split[0];
|
||||
patterns = new String[split.length - 1];
|
||||
for (int i = 1, n = split.length; i < n; i++) {
|
||||
patterns[i - 1] = split[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
File dirFile = new File(dir);
|
||||
if (!dirFile.exists()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
List<String> includes = new ArrayList<String>();
|
||||
List<String> excludes = new ArrayList<String>();
|
||||
if (patterns != null) {
|
||||
for (String pattern : patterns) {
|
||||
if (pattern.charAt(0) == '!') {
|
||||
excludes.add(pattern.substring(1));
|
||||
}
|
||||
else {
|
||||
includes.add(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (includes.isEmpty()) {
|
||||
includes.add("**");
|
||||
}
|
||||
|
||||
if (defaultGlobExcludes != null) {
|
||||
excludes.addAll(defaultGlobExcludes);
|
||||
}
|
||||
|
||||
GlobScanner scanner = new GlobScanner(dirFile, includes, excludes);
|
||||
String rootDir = scanner.rootDir()
|
||||
.getPath()
|
||||
.replace('\\', '/');
|
||||
if (!rootDir.endsWith("/")) {
|
||||
rootDir += '/';
|
||||
}
|
||||
for (String filePath : scanner.matches()) {
|
||||
paths.add(new Path(rootDir, filePath));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Paths object and calls {@link #glob(String, List)} with the specified arguments.
|
||||
*/
|
||||
public
|
||||
Paths(String dir, List<String> patterns) {
|
||||
glob(dir, patterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #glob(String, String...)}.
|
||||
*/
|
||||
public
|
||||
Paths glob(String dir, List<String> patterns) {
|
||||
if (patterns == null) {
|
||||
throw new IllegalArgumentException("patterns cannot be null.");
|
||||
}
|
||||
glob(dir, patterns.toArray(new String[patterns.size()]));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all files and directories in the specified directory matching the regular expression patterns. This method is much
|
||||
* slower than {@link #glob(String, String...)} because every file and directory under the specified directory must be
|
||||
* inspected.
|
||||
*
|
||||
* @param dir The directory containing the paths to collect. If it does not exist, no paths are collected.
|
||||
* @param patterns The regular expression patterns of the paths to collect or exclude. If empty or omitted then the dir
|
||||
* parameter is split on the "|" character, the first element is used as the directory and remaining are used as the
|
||||
* patterns. If null, ** is assumed (collects all paths).<br>
|
||||
* <br>
|
||||
* A pattern starting with an exclamation point (!) causes paths matched by the pattern to be excluded, even if other
|
||||
* patterns would select the paths.
|
||||
*/
|
||||
public
|
||||
Paths regex(String dir, String... patterns) {
|
||||
if (dir == null) {
|
||||
dir = ".";
|
||||
}
|
||||
if (patterns != null && patterns.length == 0) {
|
||||
String[] split = dir.split("\\|");
|
||||
if (split.length > 1) {
|
||||
dir = split[0];
|
||||
patterns = new String[split.length - 1];
|
||||
for (int i = 1, n = split.length; i < n; i++) {
|
||||
patterns[i - 1] = split[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
File dirFile = new File(dir);
|
||||
if (!dirFile.exists()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
List<String> includes = new ArrayList<String>();
|
||||
List<String> excludes = new ArrayList<String>();
|
||||
if (patterns != null) {
|
||||
for (String pattern : patterns) {
|
||||
if (pattern.charAt(0) == '!') {
|
||||
excludes.add(pattern.substring(1));
|
||||
}
|
||||
else {
|
||||
includes.add(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (includes.isEmpty()) {
|
||||
includes.add(".*");
|
||||
}
|
||||
|
||||
RegexScanner scanner = new RegexScanner(dirFile, includes, excludes);
|
||||
String rootDir = scanner.rootDir()
|
||||
.getPath()
|
||||
.replace('\\', '/');
|
||||
if (!rootDir.endsWith("/")) {
|
||||
rootDir += '/';
|
||||
}
|
||||
for (String filePath : scanner.matches()) {
|
||||
paths.add(new Path(rootDir, filePath));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the files and directories to the specified directory.
|
||||
*
|
||||
* @return A paths object containing the paths of the new files.
|
||||
*/
|
||||
public
|
||||
Paths copyTo(String destDir) throws IOException {
|
||||
Paths newPaths = new Paths();
|
||||
for (Path path : paths) {
|
||||
File destFile = new File(destDir, path.name);
|
||||
File srcFile = path.file();
|
||||
if (srcFile.isDirectory()) {
|
||||
destFile.mkdirs();
|
||||
}
|
||||
else {
|
||||
destFile.getParentFile()
|
||||
.mkdirs();
|
||||
copyFile(srcFile, destFile);
|
||||
}
|
||||
newPaths.paths.add(new Path(destDir, path.name));
|
||||
}
|
||||
return newPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies one file to another.
|
||||
*/
|
||||
static private
|
||||
void copyFile(File in, File out) throws IOException {
|
||||
FileInputStream sourceStream = new FileInputStream(in);
|
||||
FileOutputStream destinationStream = new FileOutputStream(out);
|
||||
FileChannel sourceChannel = sourceStream.getChannel();
|
||||
FileChannel destinationChannel = destinationStream.getChannel();
|
||||
sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel);
|
||||
sourceChannel.close();
|
||||
sourceStream.close();
|
||||
destinationChannel.close();
|
||||
destinationStream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all the files, directories, and any files in the directories.
|
||||
*
|
||||
* @return False if any file could not be deleted.
|
||||
*/
|
||||
public
|
||||
boolean delete() {
|
||||
boolean success = true;
|
||||
List<Path> pathsCopy = new ArrayList<Path>(paths);
|
||||
Collections.sort(pathsCopy, LONGEST_TO_SHORTEST);
|
||||
for (File file : getFiles(pathsCopy)) {
|
||||
if (file.isDirectory()) {
|
||||
if (!deleteDirectory(file)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!file.delete()) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute paths delimited by commas.
|
||||
*/
|
||||
public
|
||||
String toString() {
|
||||
return toString(", ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute paths delimited by the specified character.
|
||||
*/
|
||||
public
|
||||
String toString(String delimiter) {
|
||||
StringBuilder buffer = new StringBuilder(256);
|
||||
for (String path : getPaths()) {
|
||||
if (buffer.length() > 0) {
|
||||
buffer.append(delimiter);
|
||||
}
|
||||
buffer.append(path);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full paths.
|
||||
*/
|
||||
public
|
||||
List<String> getPaths() {
|
||||
ArrayList<String> stringPaths = new ArrayList<String>(paths.size());
|
||||
for (File file : getFiles()) {
|
||||
stringPaths.add(file.getPath());
|
||||
}
|
||||
return stringPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the paths as File objects.
|
||||
*/
|
||||
public
|
||||
List<File> getFiles() {
|
||||
return getFiles(new ArrayList<Path>(paths));
|
||||
}
|
||||
|
||||
private
|
||||
ArrayList<File> getFiles(List<Path> paths) {
|
||||
ArrayList<File> files = new ArrayList<File>(paths.size());
|
||||
int i = 0;
|
||||
for (Path path : paths) {
|
||||
files.add(path.file());
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses the files and directories specified by the paths into a new zip file at the specified location. If there are no
|
||||
* paths or all the paths are directories, no zip file will be created.
|
||||
*/
|
||||
public
|
||||
void zip(String destFile) throws IOException {
|
||||
Paths zipPaths = filesOnly();
|
||||
if (zipPaths.paths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
byte[] buf = new byte[1024];
|
||||
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(destFile));
|
||||
try {
|
||||
for (Path path : zipPaths.paths) {
|
||||
File file = path.file();
|
||||
out.putNextEntry(new ZipEntry(path.name.replace('\\', '/')));
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.closeEntry();
|
||||
}
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Paths object containing the paths that are files.
|
||||
*/
|
||||
public
|
||||
Paths filesOnly() {
|
||||
Paths newPaths = new Paths();
|
||||
for (Path path : paths) {
|
||||
if (path.file()
|
||||
.isFile()) {
|
||||
newPaths.paths.add(path);
|
||||
}
|
||||
}
|
||||
return newPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of paths.
|
||||
*
|
||||
* @return the number of paths
|
||||
*/
|
||||
public
|
||||
int size() {
|
||||
return paths.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if there are no paths
|
||||
*
|
||||
* @return <tt>true</tt> if there are no paths
|
||||
*/
|
||||
public
|
||||
boolean isEmpty() {
|
||||
return paths.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Paths object containing the paths that are files, as if each file were selected from its parent directory.
|
||||
*/
|
||||
public
|
||||
Paths flatten() {
|
||||
Paths newPaths = new Paths();
|
||||
for (Path path : paths) {
|
||||
File file = path.file();
|
||||
if (file.isFile()) {
|
||||
newPaths.paths.add(new Path(file.getParent(), file.getName()));
|
||||
}
|
||||
}
|
||||
return newPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Paths object containing the paths that are directories.
|
||||
*/
|
||||
public
|
||||
Paths dirsOnly() {
|
||||
Paths newPaths = new Paths();
|
||||
for (Path path : paths) {
|
||||
if (path.file()
|
||||
.isDirectory()) {
|
||||
newPaths.paths.add(path);
|
||||
}
|
||||
}
|
||||
return newPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the portion of the path after the root directory where the path was collected.
|
||||
*/
|
||||
public
|
||||
List<String> getRelativePaths() {
|
||||
ArrayList<String> stringPaths = new ArrayList<String>(paths.size());
|
||||
for (Path path : paths) {
|
||||
stringPaths.add(path.name);
|
||||
}
|
||||
return stringPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the paths' filenames.
|
||||
*/
|
||||
public
|
||||
List<String> getNames() {
|
||||
ArrayList<String> stringPaths = new ArrayList<String>(paths.size());
|
||||
for (File file : getFiles()) {
|
||||
stringPaths.add(file.getName());
|
||||
}
|
||||
return stringPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single path to this Paths object.
|
||||
*/
|
||||
public
|
||||
Paths addFile(String fullPath) {
|
||||
File file = new File(fullPath);
|
||||
paths.add(new Path(file.getParent(), file.getName()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single path to this Paths object.
|
||||
*/
|
||||
public
|
||||
Paths add(String dir, String name) {
|
||||
paths.add(new Path(dir, name));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all paths from the specified Paths object to this Paths object.
|
||||
*/
|
||||
public
|
||||
void add(Paths paths) {
|
||||
this.paths.addAll(paths.paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the absolute paths. The iterator supports the remove method.
|
||||
*/
|
||||
public
|
||||
Iterator<Path> iterator() {
|
||||
return new Iterator<Path>() {
|
||||
private Iterator<Path> iter = paths.iterator();
|
||||
|
||||
public
|
||||
boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
public
|
||||
void remove() {
|
||||
iter.remove();
|
||||
}
|
||||
|
||||
public
|
||||
Path next() {
|
||||
return iter.next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the paths as File objects. The iterator supports the remove method.
|
||||
*/
|
||||
public
|
||||
Iterator<File> fileIterator() {
|
||||
return new Iterator<File>() {
|
||||
private Iterator<Path> iter = paths.iterator();
|
||||
|
||||
public
|
||||
void remove() {
|
||||
iter.remove();
|
||||
}
|
||||
|
||||
public
|
||||
File next() {
|
||||
return iter.next()
|
||||
.file();
|
||||
}
|
||||
|
||||
public
|
||||
boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Nathan Sweet
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Modified by dorkbox, llc
|
||||
*/
|
||||
package dorkbox.build.util.wildcard;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class RegexScanner {
|
||||
public static
|
||||
void main(String[] args) {
|
||||
// System.out.println(new Paths("C:\\Java\\ls", "**"));
|
||||
List<String> includes = new ArrayList();
|
||||
includes.add("core[^T]+php");
|
||||
// includes.add(".*/lavaserver/.*");
|
||||
List<String> excludes = new ArrayList();
|
||||
// excludes.add("website/**/doc**");
|
||||
long start = System.nanoTime();
|
||||
List<String> files = new RegexScanner(new File("..\\website\\includes"), includes, excludes).matches();
|
||||
long end = System.nanoTime();
|
||||
System.out.println(files.toString()
|
||||
.replaceAll(", ", "\n")
|
||||
.replaceAll("[\\[\\]]", ""));
|
||||
System.out.println((end - start) / 1000000f);
|
||||
}
|
||||
|
||||
public
|
||||
List<String> matches() {
|
||||
return matches;
|
||||
}
|
||||
private final File rootDir;
|
||||
private final List<Pattern> includePatterns;
|
||||
private final List<String> matches = new ArrayList(128);
|
||||
|
||||
public
|
||||
RegexScanner(File rootDir, List<String> includes, List<String> excludes) {
|
||||
if (rootDir == null) {
|
||||
throw new IllegalArgumentException("rootDir cannot be null.");
|
||||
}
|
||||
if (!rootDir.exists()) {
|
||||
throw new IllegalArgumentException("Directory does not exist: " + rootDir);
|
||||
}
|
||||
if (!rootDir.isDirectory()) {
|
||||
throw new IllegalArgumentException("File must be a directory: " + rootDir);
|
||||
}
|
||||
try {
|
||||
rootDir = rootDir.getCanonicalFile();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("OS error determining canonical path: " + rootDir, ex);
|
||||
}
|
||||
this.rootDir = rootDir;
|
||||
|
||||
if (includes == null) {
|
||||
throw new IllegalArgumentException("includes cannot be null.");
|
||||
}
|
||||
if (excludes == null) {
|
||||
throw new IllegalArgumentException("excludes cannot be null.");
|
||||
}
|
||||
|
||||
includePatterns = new ArrayList();
|
||||
for (String include : includes) {
|
||||
includePatterns.add(Pattern.compile(include, Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
|
||||
List<Pattern> excludePatterns = new ArrayList();
|
||||
for (String exclude : excludes) {
|
||||
excludePatterns.add(Pattern.compile(exclude, Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
|
||||
scanDir(rootDir);
|
||||
|
||||
for (Iterator matchIter = matches.iterator(); matchIter.hasNext(); ) {
|
||||
String filePath = (String) matchIter.next();
|
||||
for (Pattern exclude : excludePatterns) {
|
||||
if (exclude.matcher(filePath)
|
||||
.matches()) {
|
||||
matchIter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
void scanDir(File dir) {
|
||||
for (File file : dir.listFiles()) {
|
||||
for (Pattern include : includePatterns) {
|
||||
int length = rootDir.getPath()
|
||||
.length();
|
||||
if (!rootDir.getPath()
|
||||
.endsWith(File.separator)) {
|
||||
length++; // Lose starting slash.
|
||||
}
|
||||
String filePath = file.getPath()
|
||||
.substring(length);
|
||||
if (include.matcher(filePath)
|
||||
.matches()) {
|
||||
matches.add(filePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
scanDir(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public
|
||||
File rootDir() {
|
||||
return rootDir;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue