nutzam/nutz — Issue #126: 关于nutz资源读取双倍的问题 
Author: zozoh
Created: 2012-01-09 12:12:03+00:00
State: open
Labels: Dao

wendal，灰太狼，你们好！
我们正在做一个项目，是用maven构建的，分了两个模块，用到了nutz，但是
昨天在做web模块的时候，资源读取时，读了双倍
也就是说，当我们把本来只有一个自定义的sql文件，但却读取了两次，造成了读取数据库时出现了重复键的异常。
已经查找到了根源了：
问题出在 org.nutz.resource.impl.WebResourceScan中扫描资源文件，Nutz除了扫描Jar（正常），还会扫描一个/home/chao/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/work/Catalina/localhost/web/loader 文件夹 (扫描后找到的资源数量就翻倍了)。

但是异常只在第一次使用中抛出。
而且当我们用普通的项目时，把两个模块合并成一个独立的项目，也不会出现重复键的异常。
这是不是一个bug呢？对maven支持不友好？
=========以下红色字体部分就是匪夷所思的扫描代码，目前尚未知道有何特殊作用==========

public class WebResourceScan extends AbstractResourceScan {

private static final Log log = Logs.get();

private ServletContext sc;

public WebResourceScan(ServletContext servletContext) {
this.sc = servletContext;
}

public List list(final String src, String filter) {
final Pattern regex = null == filter ? null : Pattern.compile(filter);
final List list = new ArrayList();
// 获取全部jar
Set jars = sc.getResourcePaths("/WEB-INF/lib/");
if (jars != null) // 这个文件夹不一定存在,尤其是Maven的WebApp项目
for (String path : jars) {
if (!path.toLowerCase().endsWith(".jar"))
continue;
list.addAll(scanInJar(checkSrc(src), regex, sc.getRealPath(path)));
}
// 获取classes里面文件
// 对 classes 文件夹作一个深层遍历
// 忽略隐藏文件，以不能被 filter 匹配的项目
// 返回的 NutResource 对象，都是以 classes 目录为根
File dir = Files.findFile(src);
boolean flag = true;
if (null != dir && dir.exists()) {
// 获取 CLASSPATH 的基目录
String src2 = Disks.getCanonicalPath(src);
String dirPath = Disks.getCanonicalPath(dir.getAbsolutePath());
int pos = dirPath.indexOf(src2, dirPath.indexOf("classes") + 7);// TODO
// 如果不含classes,一样找不到!!
final String base = pos < 0 ? dirPath : dirPath.substring(0, pos);

// 那么很好，深层递归一下吧
if (log.isDebugEnabled())
log.debugf("Scan in web classes : %s , base = %s", dir, base);

List list2 = scanInDir(regex, dir, true);
for (NutResource nutResource : list2) {
String name = nutResource.getName();
if (name.indexOf(base) > -1) {
String tmpName = name.substring(base.length() + 1);
nutResource.setName(tmpName);
}
list.add(nutResource);
}
flag = list.isEmpty();
}
// 目录不存在,或者里面没有任何文件
if (flag && (!src.startsWith("/"))) {
try {
String base = sc.getRealPath("/WEB-INF/classes/");
String path = sc.getRealPath("/WEB-INF/classes/" + src);
if (path != null) {
List list2 = scanInDir(regex, new File(path), true);
for (NutResource nutResource : list2) {
String name = nutResource.getName();
if (name.indexOf(base) > -1)
nutResource.setName(name.substring(base.length() + 1));
list.add(nutResource);
}
flag = list.isEmpty();
}
}
catch (Throwable e) {}
}
// 还是空? 查一下classpath变量吧, Fix Issue 411
if (flag) {
String classpath = System.getProperties().getProperty("java.class.path");
if (log.isInfoEnabled())
log.info("Try to search in classpath : " + classpath);
String[] paths = classpath.split(System.getProperties().getProperty("path.separator"));
for (String pathZ : paths) {
if (pathZ.endsWith(".jar"))
list.addAll(scanInJar(checkSrc(src), regex, pathZ));
else
list.addAll(scanInDir(regex, new File(pathZ + "/" + src), true));
}
flag = list.isEmpty();
}
if (flag && log.isInfoEnabled())
log.infof( "Fail to found '%s' in /WEB-INF/classes of context [%s]",
src,
sc.getServletContextName());
return list;
}