
org.unidal.helper.Scanners Maven / Gradle / Ivy
The newest version!
package org.unidal.helper;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.unidal.helper.Scanners.IMatcher.Direction;
public class Scanners {
public static DirScanner forDir() {
return DirScanner.INSTANCE;
}
public static JarScanner forJar() {
return JarScanner.INSTANCE;
}
public static ResourceScanner forResource() {
return ResourceScanner.INSTANCE;
}
public static abstract class DirMatcher implements IMatcher {
@Override
public boolean isDirEligible() {
return true;
}
@Override
public boolean isFileElegible() {
return false;
}
}
public enum DirScanner {
INSTANCE;
public List scan(File base, IMatcher matcher) {
List files = new ArrayList();
StringBuilder relativePath = new StringBuilder();
scanForFiles(base, relativePath, matcher, false, files);
return files;
}
private void scanForFiles(File base, StringBuilder relativePath, IMatcher matcher, boolean foundFirst,
List files) {
int len = relativePath.length();
File dir = len == 0 ? base : new File(base, relativePath.toString());
String[] list = dir.list();
if (list != null) {
for (String item : list) {
File child = new File(dir, item);
if (len > 0) {
relativePath.append('/');
}
relativePath.append(item);
IMatcher.Direction direction = matcher.matches(base, relativePath.toString());
if (direction == null) {
direction = Direction.NEXT;
}
switch (direction) {
case MATCHED:
if (matcher.isDirEligible() && child.isDirectory()) {
files.add(child);
}
if (matcher.isFileElegible() && child.isFile()) {
files.add(child);
}
break;
case DOWN:
// for sub-folders
scanForFiles(base, relativePath, matcher, foundFirst, files);
break;
default:
break;
}
relativePath.setLength(len); // reset
if (foundFirst && files.size() > 0) {
break;
}
}
}
}
public File scanForOne(File base, IMatcher matcher) {
List files = new ArrayList(1);
StringBuilder relativePath = new StringBuilder();
scanForFiles(base, relativePath, matcher, true, files);
if (files.isEmpty()) {
return null;
} else {
return files.get(0);
}
}
}
public static abstract class FileMatcher implements IMatcher {
@Override
public boolean isDirEligible() {
return false;
}
@Override
public boolean isFileElegible() {
return true;
}
}
public static interface IMatcher {
public boolean isDirEligible();
public boolean isFileElegible();
public Direction matches(T base, String path);
public enum Direction {
MATCHED,
DOWN,
NEXT;
public boolean isDown() {
return this == DOWN;
}
public boolean isMatched() {
return this == MATCHED;
}
public boolean isNext() {
return this == NEXT;
}
}
}
public enum JarScanner {
INSTANCE;
public ZipEntry getEntry(String jarFileName, String name) {
ZipFile zipFile = null;
try {
zipFile = new ZipFile(jarFileName);
ZipEntry entry = zipFile.getEntry(name);
return entry;
} catch (IOException e1) {
// ignore
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException e) {
// ignore it
}
}
}
return null;
}
public byte[] getEntryContent(String jarFileName, String entryPath) {
byte[] bytes = null;
ZipFile zipFile = null;
try {
zipFile = new ZipFile(jarFileName);
ZipEntry entry = zipFile.getEntry(entryPath);
if (entry != null) {
InputStream inputStream = zipFile.getInputStream(entry);
bytes = Files.forIO().readFrom(inputStream);
}
} catch (Exception e) {
// ignore
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (Exception e) {
}
}
}
return bytes;
}
public boolean hasEntry(String jarFileName, String name) {
return getEntry(jarFileName, name) != null;
}
public List scan(File jarFile, IMatcher matcher) throws ZipException, IOException {
return scan(new ZipFile(jarFile), matcher);
}
public List scan(ZipFile zipFile, IMatcher matcher) {
List files = new ArrayList();
scanZipFile(zipFile, matcher, false, files);
return files;
}
public String scanForOne(File jarFile, IMatcher matcher) throws ZipException, IOException {
List files = new ArrayList(1);
scanZipFile(new ZipFile(jarFile), matcher, false, files);
if (files.isEmpty()) {
return null;
} else {
return files.get(0);
}
}
private void scanZipFile(ZipFile zipFile, IMatcher matcher, boolean foundFirst, List names) {
Enumeration extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
if (matcher.isDirEligible() && entry.isDirectory()) {
IMatcher.Direction direction = matcher.matches(entry, name);
if (direction.isMatched()) {
names.add(name);
}
} else if (matcher.isFileElegible() && !entry.isDirectory()) {
IMatcher.Direction direction = matcher.matches(entry, name);
if (direction.isMatched()) {
names.add(name);
}
}
if (foundFirst && names.size() > 0) {
break;
}
}
}
}
public static abstract class ResourceMatcher implements IMatcher {
@Override
public boolean isDirEligible() {
return false;
}
@Override
public boolean isFileElegible() {
return true;
}
}
public enum ResourceScanner {
INSTANCE;
@SuppressWarnings("deprecation")
private String decode(String url) {
try {
return URLDecoder.decode(url, "utf-8");
} catch (UnsupportedEncodingException e) {
return URLDecoder.decode(url);
}
}
private void scan(Set done, final List urls, final URL base, String resourceBase, final ResourceMatcher matcher)
throws IOException {
if (done.contains(base)) {
return;
} else {
done.add(base);
}
String protocol = base.getProtocol();
if ("file".equals(protocol)) { // local file folder
scanFile(urls, base, matcher);
} else if ("jar".equals(protocol)) { // normal jar
scanJar(urls, base, resourceBase, matcher);
} else if ("wsjar".equals(protocol)) { // websphere jar, zip file
scanWsjar(urls, base, resourceBase, matcher);
}
}
public List scan(String resourceBase, final ResourceMatcher matcher) throws IOException {
List urls = new ArrayList();
Set done = new HashSet();
// try to load from current class's classloader
Enumeration e1 = getClass().getClassLoader().getResources(resourceBase);
while (e1.hasMoreElements()) {
scan(done, urls, e1.nextElement(), resourceBase, matcher);
}
// try to load from current context's classloader
Enumeration e2 = Thread.currentThread().getContextClassLoader().getResources(resourceBase);
while (e2.hasMoreElements()) {
scan(done, urls, e2.nextElement(), resourceBase, matcher);
}
return urls;
}
private void scanFile(final List urls, final URL base, final ResourceMatcher matcher) {
File baseDir = new File(decode(base.getPath()));
DirScanner.INSTANCE.scan(baseDir, new FileMatcher() {
@Override
public Direction matches(File dir, String path) {
try {
Direction d = matcher.matches(base, path);
if (d.isMatched()) {
String baseUrl = base.toExternalForm();
String url;
if (baseUrl.endsWith("/")) {
url = baseUrl + path;
} else {
url = baseUrl + "/" + path;
}
urls.add(new URL(url));
}
return d;
} catch (MalformedURLException e) {
// ignore it
}
return Direction.DOWN;
}
});
}
private void scanJar(final List urls, final URL base, String resourceBase, final ResourceMatcher matcher)
throws IOException {
String url = base.toExternalForm();
int pos = url.lastIndexOf("!/");
final URL u = new URL(url.substring(0, pos + 2));
URLConnection conn = u.openConnection();
if (conn instanceof JarURLConnection) {
JarFile jarFile = ((JarURLConnection) conn).getJarFile();
final String prefix = resourceBase + "/";
try {
JarScanner.INSTANCE.scan(jarFile, new ZipEntryMatcher() {
@Override
public Direction matches(ZipEntry entry, String path) {
if (path.startsWith(prefix)) {
try {
String p = path.substring(prefix.length());
Direction d = matcher.matches(base, p);
if (d.isMatched()) {
URL url = new URL(base.toExternalForm() + "/" + p);
urls.add(url);
}
return d;
} catch (MalformedURLException e) {
// ignore it
}
}
return Direction.DOWN;
}
});
} finally {
try {
jarFile.close();
} catch (Throwable e) {
// ignore it
}
}
}
}
private void scanWsjar(final List urls, final URL base, final String resourceBase, final ResourceMatcher matcher)
throws IOException {
String path = base.getPath();
int pos = path.lastIndexOf("!/");
File jarFile = new File(path.substring("file:".length(), pos));
final String prefix = resourceBase + "/";
JarScanner.INSTANCE.scan(jarFile, new ZipEntryMatcher() {
@Override
public Direction matches(ZipEntry entry, String path) {
if (path.startsWith(prefix)) {
try {
String p = path.substring(prefix.length());
Direction d = matcher.matches(base, p);
if (d.isMatched()) {
URL url = new URL(base.toExternalForm() + "/" + p);
urls.add(url);
}
return d;
} catch (MalformedURLException e) {
// ignore it
}
}
return Direction.DOWN;
}
});
}
}
public static abstract class ZipEntryMatcher implements IMatcher {
@Override
public boolean isDirEligible() {
return false;
}
@Override
public boolean isFileElegible() {
return true;
}
public abstract Direction matches(ZipEntry entry, String path);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy