This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
BWMirror-Generator/manual-bwapi/ResourceList.java
gered 2bff907f93 more robust way of extracting dlls / bwta data from classpath resources
this is important, as if you want to run the TestBot in the bwmirror project
directly from an IDE, the dlls and bwta data files are not being extracted
from a JAR file and the extraction would fail. this method is a fair bit more
robust and will automatically handle those differences.

in addition, using System.load instead of System.loadLibrary to load
the bwapi_bridge native library. this allows us to stop doing that hacky
reflection thing to reset the java.library.path property and just pass in
an absolute path to bwapi_bridge.dll
2017-04-11 18:37:30 -04:00

144 lines
5.9 KiB
Java

package bwapi;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
/**
* Get a list of all resources that exist on the classpath that match
* a given java.util.regex.Pattern.
*
* All elements listed in the system property "java.class.path" will be searched
* and whether it is a JAR file or directory will be handled automatically.
*
* Resources that are listed with this class can be loaded using a ClassLoader.
* e.g. Thread.currentThread().getContextClassLoader().getResourceAsStream(...)
*/
public class ResourceList {
/**
* Returns a list of all resources within the classpath matching the given pattern.
*
* NOTE: If your pattern includes paths, you should use forward slashes between
* directory and filenames instead of backslashes, even when running on Windows.
* Internally, paths will be converted to forward slashes before the pattern is
* matched for consistency reasons.
*
* @param pattern the pattern to match
* @return the resources in the order they are found
*/
public static Collection<String> getResources(final Pattern pattern) {
final ArrayList<String> retval = new ArrayList<>();
final String classPath = System.getProperty("java.class.path", ".");
final String[] classPathElements = classPath.split(File.pathSeparator);
for (final String element : classPathElements) {
retval.addAll(getResources(element, pattern));
}
return retval;
}
private static Collection<String> getResources(final String element,
final Pattern pattern) {
final ArrayList<String> retval = new ArrayList<>();
final File file = new File(element);
if (file.isDirectory()) {
String baseDirectory;
try {
baseDirectory = file.getCanonicalPath() + File.separator;
} catch (final IOException e) {
throw new java.lang.Error(e);
}
retval.addAll(getResourcesFromDirectory(file, baseDirectory, pattern));
} else {
retval.addAll(getResourcesFromJarFile(file, pattern));
}
return retval;
}
private static Collection<String> getResourcesFromJarFile(final File file, final Pattern pattern) {
final ArrayList<String> retval = new ArrayList<>();
ZipFile zf;
try {
zf = new ZipFile(file);
} catch (final ZipException e) {
throw new java.lang.Error(e);
} catch (final IOException e) {
throw new java.lang.Error(e);
}
final Enumeration e = zf.entries();
while (e.hasMoreElements()) {
final ZipEntry ze = (ZipEntry) e.nextElement();
final String fileName = ze.getName();
final boolean accept = pattern.matcher(fileName).matches();
if (accept) {
retval.add(fileName);
}
}
try {
zf.close();
} catch (final IOException e1) {
throw new java.lang.Error(e1);
}
return retval;
}
private static Collection<String> getResourcesFromDirectory(final File directory, final String baseDirectory, final Pattern pattern) {
final ArrayList<String> retval = new ArrayList<>();
final File[] fileList = directory.listFiles();
for (final File file : fileList) {
if (file.isDirectory()) {
retval.addAll(getResourcesFromDirectory(file, baseDirectory, pattern));
} else {
try {
// the below call to file.getCanonicalPath will return an absolute path.
// since JAR file paths will all be relative, we trim off the absolute path's
// base directory prefix before doing the regex match.
//
// also convert the remaining sub-path to use forward slashes. this is a convenience thing
// as the _ONLY_ time a path being matched in this entire class will have backslashes
// is in this method (when checking local directories only) and ONLY on Windows.
// checking JAR file paths (getResourcesFromJarFile) will have forward slashes, even
// on Windows...
// so let's just force forward slashes everywhere to be consistent, shall we?
final String fileName = file.getCanonicalPath().substring(baseDirectory.length()).replaceAll("\\\\", "/");
final boolean accept = pattern.matcher(fileName).matches();
if (accept) {
// also note that we are adding the slash-converted sub-path to the list of files, NOT
// the absolute path initially obtained! this is so that this path can be passed
// directly into a call to getResourceAsStream() or similar
retval.add(fileName);
}
} catch (final IOException e) {
throw new java.lang.Error(e);
}
}
}
return retval;
}
/**
* list the resources that match args[0]
*
* @param args args[0] is the pattern to match, or list all resources if
* there are no args
*/
public static void main(final String[] args) {
Pattern pattern;
if (args.length < 1) {
pattern = Pattern.compile(".*");
} else {
pattern = Pattern.compile(args[0]);
}
final Collection<String> list = ResourceList.getResources(pattern);
for (final String name : list) {
System.out.println(name);
}
}
}