Skip to content

Instantly share code, notes, and snippets.

@danieldietrich
Last active December 14, 2015 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danieldietrich/5130596 to your computer and use it in GitHub Desktop.
Save danieldietrich/5130596 to your computer and use it in GitHub Desktop.
Classpath Resources
package net.danieldietrich;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Based on the Java classpath specification
*
* http://docs.oracle.com/javase/1.5.0/docs/tooldocs/solaris/classpath.html
* http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/classpath.html
*
* the classpath is scanned for resources, which match a given regex pattern.
*
* Results are passed to a Visitor.
*
* @author Daniel Dietrich
*/
public class Classpath {
private final Pattern pattern;
public Classpath(final Pattern pattern) {
this.pattern = pattern;
}
public void getResources(final Visitor visitor) throws Exception {
final String classpath = System.getProperty("java.class.path", ".");
final String[] classpathElements = classpath.split(File.pathSeparator);
for (final String element : classpathElements) {
getResources(element, visitor);
}
}
private void getResources(final String element, final Visitor visitor) throws Exception {
final File file = new File(element);
if (file.isDirectory()) {
getResourcesFromDirectory("", file, visitor);
} else if (isJarOrZip(file)) {
getResourcesFromJarFile(file, visitor);
} else {
// TODO: LOGGER.info("Ignoring classpath element {}. It is no directory and not a jar/zip file.", element);
}
}
private void getResourcesFromJarFile(final File file, final Visitor visitor) throws Exception {
final ZipFile zipFile = new ZipFile(file);
for(final ZipEntry zipEntry : Collections.list(zipFile.entries())) {
if(!zipEntry.isDirectory()) {
final String resource = zipEntry.getName();
final boolean accept = pattern.matcher(resource).matches();
if(accept) {
final String path = file.getCanonicalPath().replaceAll("\\\\", "/");
final String escaped = "jar:file:" + escape(path) + "!/" + escape(resource);
final URL url = new URI(escaped).toURL();
visitor.visit(resource, url);
}
}
}
zipFile.close();
}
private void getResourcesFromDirectory(final String path, final File directory,
final Visitor visitor) throws Exception {
final File[] fileList = directory.listFiles();
for(final File file : fileList) {
if(file.isDirectory()) {
getResourcesFromDirectory(path + file.getName() + "/", file, visitor);
} else {
final String fileName = file.getCanonicalPath();
final boolean accept = pattern.matcher(fileName).matches();
if(accept) {
final URL url = file.toURI().toURL();
visitor.visit(path + file.getName(), url);
}
}
}
}
private boolean isJarOrZip(final File file) {
// TODO(nice2have): ensure that file content is zip
final String name = file.getName().toLowerCase();
return name.endsWith(".jar") || name.endsWith(".zip");
}
private String escape(final String s) {
// TODO(nice2have): escape all characters accordingly to RFC 2396
return s.replaceAll(" ", "%20");
}
public static interface Visitor {
void visit(String resource, URL url) throws Exception;
}
}
package net.danieldietrich;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Search the classpath for resources which match a specific pattern.
*
* Arguments:
* -Dpattern=<search pattern> (optional, default: .*)
* -Dregex=[true|false] (optional, default: false)
*
* Example:
* -Dpattern=*\xml\*.xsd
* is the same as
* -Dpattern=.*\\xml\\.*\.xsd -Dregex=true
*
* @author Daniel Dietrich
*/
public class Main {
public void run(final Pattern pattern) throws Exception {
new Classpath(pattern).getResources(
new Classpath.Visitor() {
private Map<String, URL> visited = new HashMap<String, URL>();
@Override
public void visit(final String resource, final URL url) throws Exception {
if (!visited.containsKey(resource)) {
visited.put(resource, url);
/*DELME*/System.out.println("found " + resource + " (" + url + ")");
// TODO: LOGGER.info("found {} ({})", resource, url);
// TODO: copy resource to a specific place via url.openStream()
} else {
/*DELME*/System.out.println("skipping " + resource + " (" + url + " overwritten by " + visited.get(resource) + ")");
// TODO: LOGGER.info("skipping {} ({} overwritten by {})", resource, url, visited.get(resource));
}
}
}
);
}
public static void main(final String[] args) throws Exception {
new Main().run(getPattern());
}
private static Pattern getPattern() {
final String arg = System.getProperty("pattern");
if (arg == null) {
return Pattern.compile(".*");
} else {
final boolean isRegex = Boolean.getBoolean("regex");
final String pattern = isRegex ? arg : arg
// escape escape-character
.replaceAll("\\\\", "\\\\\\\\")
// escape wildcard-character
.replaceAll("\\.", "\\\\.")
// substitute asterisk '*' with wildcard-character '.*'
.replaceAll("\\*", ".*");
return Pattern.compile(pattern);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment