package jef.tools.resource;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import jef.tools.reflect.ClassLoaderUtil;
/**
* 根据指定的class来定位资源。
* 如果用/开头表示从该class的根目录加载,否则认为从该class的相对路径加载。
*
*
* 下面两个属性是可以自行修改的
* <li>directoryOnly</li>
* 跳过jar包
* <li>onlySamePathOfClz</li>
* 必须从指定class所在的classpath加载,不允许使用classloader中的其他位置(无论是否设置此属性,都优先从指定class的cp中加载)
*
*
* @author jiyi
*
*/
public class ClassRelativeLoader extends AResourceLoader {
private Class<?> clz;
private boolean directoryOnly=false;
private boolean noOtherUrlOfClassLoader=true;
public ClassRelativeLoader(Class<?> clz) {
while (clz.isArray()) {
clz = clz.getComponentType();
}
this.clz = clz;
}
/**
* 和JDK class.getResource()的默认实现不同,这个实现是优先从指定class的加载路径去寻找资源的。
*/
public URL getResource(String name) {
URL path = ClassLoaderUtil.getCodeSource(clz);
name=resolveName(name,clz);
if (path != null) {
if(!(directoryOnly && toFile(path).isFile())){
java.net.URLClassLoader ul=new java.net.URLClassLoader(new URL[]{path});
URL url=ul.findResource(name);
if(url!=null)return url;
}
}
if(noOtherUrlOfClassLoader){
return null;
}
if(directoryOnly)name="./"+name;
return clz.getClassLoader().getResource(name);
}
private static final String resolveName(String name,Class<?> clz) {
if (name == null) {
return name;
}
if (!name.startsWith("/")) {
String baseName = clz.getName();
int index = baseName.lastIndexOf('.');
if (index != -1) {
name = baseName.substring(0, index).replace('.', '/') + "/"+ name;
}
} else {
name = name.substring(1);
}
int n=name.indexOf("../");
while(n>-1){
int front=name.lastIndexOf('/', n-2);
if(front==-1){
name=name.substring(n+3);
}else{
name=name.substring(0,front)+name.substring(n+2);
}
n=name.indexOf("../");
}
return name;
}
public List<URL> getResources(String name) {
List<URL> result = new ArrayList<URL>();
//如果限定只允许从指定class所在的classpath查找——
if(noOtherUrlOfClassLoader){
URL u=getResource(name);
if(u!=null)result.add(u);
return result;
}
//通用查找
name = resolveName(name,clz);
if(directoryOnly)name="./"+name;
try {
for (Enumeration<URL> e = clz.getClassLoader().getResources(name); e
.hasMoreElements();) {
result.add(e.nextElement());
}
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
return result;
}
public boolean isDirectoryOnly() {
return directoryOnly;
}
public void setDirectoryOnly(boolean directoryOnly) {
this.directoryOnly = directoryOnly;
}
public boolean isOnlySamePathOfClz() {
return noOtherUrlOfClassLoader;
}
public void setOnlySamePathOfClz(boolean onlySamePathOfClz) {
this.noOtherUrlOfClassLoader = onlySamePathOfClz;
}
}