package com.github.axet.lookup.common;
import java.io.File;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.lang.StringUtils;
/**
* it worth to be a separate project
*
* c = ClassResources(YourClass.class, "fonts") c.names();
*
* fonts is a resources directory:
*
* com/example/project/YourClass.class
*
* com/example/project/fonts
*
* TODO make it separate project
*
* @author axet
*
*/
public class ClassResources {
Class<?> c;
File path;
public ClassResources(Class<?> c) {
this.c = c;
}
public ClassResources(Class<?> c, File path) {
this.c = c;
this.path = path;
}
/**
*
* @param path
* @return
*/
public List<String> names() {
return getResourceListing(c, path);
}
/**
* enter sub directory
*
* @param path
* @return
*/
public ClassResources dir(File path) {
return new ClassResources(c, new File(this.path, path.getPath()));
}
// 1) under debugger, /Users/axet/source/mircle/play/target/classes/
//
// 2) app packed as one jar, mac osx wihtout debugger path -
// /Users/axet/source/mircle/mircle/macosx/Mircle.app/Contents/Resources/Java/mircle.jar
// case above 1) works prefectly
//
// 3) if it is a separate library packed with maven under debugger
// /Users/axet/.m2/repository/com/github/axet/play/0.0.3/play-0.0.3.jar
File getPath(Class<?> cls) {
CodeSource src = cls.getProtectionDomain().getCodeSource();
if (src == null)
return null;
return new File(src.getLocation().getPath());
}
String getClassPath(Class<?> c) {
return new File(c.getCanonicalName().replace('.', File.separatorChar)).getParent();
}
String getClassPath(Class<?> c, String path) {
return new File(c.getCanonicalName().replace('.', File.separatorChar)).getParent() + File.separator + path;
}
List<String> getResourceListing(Class<?> clazz, File path) {
try {
// clazz.getClassLoader().getResource(pp) may return system library
// if path is common (Like "/com")
File pp = getPath(clazz);
String strPath = path.getPath();
if (pp.isDirectory()) {
if (strPath.startsWith(File.separator))
pp = new File(pp, strPath);
else
pp = new File(pp, getClassPath(clazz, strPath));
File r = new File(pp.toURI());
if (!r.exists())
throw new RuntimeException("File not found: " + r);
String[] ss = r.list();
if (ss == null)
return new ArrayList<String>();
if (ss.length == 0)
throw new RuntimeException("Font directory is empy: " + r);
return Arrays.asList(ss);
}
if (pp.isFile()) {
String p;
if (strPath.startsWith(File.separator))
p = StringUtils.removeStart(strPath, File.separator);
else
p = getClassPath(clazz, strPath);
JarFile jar = new JarFile(pp);
Enumeration<JarEntry> entries = jar.entries();
Set<String> result = new HashSet<String>();
boolean f = false;
while (entries.hasMoreElements()) {
String name = entries.nextElement().getName();
if (name.startsWith(p)) {
f = true;
String a = StringUtils.removeStart(name, p);
a = StringUtils.removeStart(a, File.separator);
a = a.trim();
int e = StringUtils.indexOfAny(a, new char[] { '/', '\\' });
if (e != -1)
a = a.substring(0, e);
if (!a.isEmpty())
result.add(a);
}
}
if (!f)
throw new RuntimeException("Jar file: " + pp + " has no entry: " + p);
if (result.isEmpty())
throw new RuntimeException("Jar file: " + pp + " has empty folder: " + p);
return new ArrayList<String>(result);
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}