package com.aggrepoint.utils; import java.io.InputStream; import java.net.URL; import java.util.StringTokenizer; /** * 用于定位资源 * * Class.getResource()方法沿CLASSPATH中指定的各个目录和JAR寻找指定的资源。而 * ResourceLocator.getResource()方法可以指定一个参照类,寻找资源时先查找该参 * 照类所处的目录或JAR,若查找不到,再沿CLASSPATH各个目录查找。 * * 假设在同一个JVM的CLASSPATH中存在两个JAR,这两个JAR分别有目录/prop/conf.xml * 用于存放各自的配置。如果这两个JAR中的代码都用Class.getResource(“/prop/conf.xml”) * 方法去获取配置资源,那么在运行时两个JAR中代码所访问到的将会是同一个conf.xml * 文件。那个JAR文件先出现在CLASSPATH中,那个JAR里包含的conf.xml就会被访问。若 * 使用ResourceLocator.getResource()方法去访问conf.xml文件,则两个JAR可以各自 访问各自的conf.xml,互不影响。 * * Creation date: (2002-6-8) * * @author: Yang Jiang Ming */ public class ResourceLocator { /** * 构造函数,不能被实例化 */ ResourceLocator() { } /** * 将指定类的类名中所有.替换为/,并在后面补上.class */ static String getClassPathName(Class<?> c) { String strClassFullName = c.getName(); StringTokenizer st = new StringTokenizer(strClassFullName, "."); StringBuffer sb = new StringBuffer(); sb.append(st.nextToken()); while (st.hasMoreTokens()) { sb.append("/"); sb.append(st.nextToken()); } sb.append(".class"); return sb.toString(); } /** * 返回指定类的Class Loader用于加载该类的Class Path。返回的字符串以/结尾 */ public static String getClassRootPath(Class<?> c) { String strClassPathName = getClassPathName(c); ClassLoader cl = c.getClassLoader(); if (cl == null) return null; URL urlClass = cl.getResource(strClassPathName); if (urlClass == null) return null; String strUrl = urlClass.toString(); return strUrl.substring(0, strUrl.lastIndexOf(strClassPathName)); } /** * 返回指定类的文件所在的路径。返回的字符串以/结尾 */ public static String getClassPath(Class<?> c) { String strClassFullName = c.getName(); String strClassName = strClassFullName.substring(strClassFullName .lastIndexOf(".") + 1); String strClassPathName = getClassPathName(c); ClassLoader cl = c.getClassLoader(); if (cl == null) { cl = ClassLoader.getSystemClassLoader(); return null; } URL urlClass = cl.getResource(strClassPathName); if (urlClass == null) return null; String strUrl = urlClass.toString(); return strUrl.substring(0, strUrl.lastIndexOf(strClassName)); } /** * 根据加载类的路径,构造资源URL。不检查资源是否存在返回的URL处。 */ public static URL constructResourceURL(Class<?> c, String resName) { String strUrl = ""; if (resName.startsWith("/")) // 资源名称以"/"开头,从类所在的Class Path根目录开始定位资源 strUrl = getClassRootPath(c) + resName.substring(1); else // 资源名称不以"/"开头,从类所在的目录开始定位资源 strUrl = getClassPath(c) + resName; try { return new URL(strUrl); } catch (Exception e) { return null; } } /** * 定位资源。 首先查找指定类的加载路径,如果找不到,再由指定类的Class Loader从其CLASSPATH路径中查找。 */ public static URL getResource(Class<?> c, String resName) { URL url = constructResourceURL(c, resName); if (url == null) return c.getResource(resName); InputStream is = null; try { is = url.openStream(); is.read(); } catch (Exception e) { return c.getResource(resName); } finally { try { if (is != null) is.close(); } catch (Exception e) { } } return url; } }