001: /*
002: * JFox - The most lightweight Java EE Application Server!
003: * more details please visit http://www.huihoo.org/jfox or http://www.jfox.org.cn.
004: *
005: * JFox is licenced and re-distributable under GNU LGPL.
006: */
007: package org.jfox.framework;
008:
009: import java.io.File;
010: import java.net.URL;
011: import java.net.URLClassLoader;
012: import java.net.MalformedURLException;
013: import java.util.HashMap;
014: import java.util.List;
015: import java.util.Map;
016:
017: import org.apache.log4j.Logger;
018: import org.jfox.util.FileFilterUtils;
019: import org.jfox.util.FileUtils;
020:
021: /**
022: * Class Loader Repository
023: * <p/>
024: * 负责管�所有Module Export 的 Class
025: *
026: * @author <a href="mailto:jfox.young@gmail.com">Yang Yong</a>
027: */
028: public class ClassLoaderRepository extends URLClassLoader {
029:
030: private Logger logger = Logger
031: .getLogger(ClassLoaderRepository.class);
032:
033: /**
034: * classname => ClassEntry
035: */
036: private Map<String, ClassEntry> exportClassRepo = new HashMap<String, ClassEntry>();
037:
038: public ClassLoaderRepository(URL[] urls) {
039: super (urls, ClassLoaderRepository.class.getClassLoader());
040: loadExternalLibs();
041: }
042:
043: public ClassLoaderRepository(URL[] urls, ClassLoader parent) {
044: super (urls, parent);
045: loadExternalLibs();
046: }
047:
048: /**
049: * 装载 common 目录下的 jar
050: */
051: private void loadExternalLibs() {
052: File libDir = new File(Constants.getCommonLibPath());
053: if (libDir.exists() && libDir.isDirectory()) {
054:
055: List<File> jarFiles = FileUtils.listFiles(libDir,
056: FileFilterUtils.suffixFileFilter(new String[] {
057: "jar", "zip" }));
058: for (File file : jarFiles) {
059: try {
060: addURL(file.toURI().toURL());
061: } catch (MalformedURLException e) {
062: logger.warn(e);
063: }
064: }
065: }
066: }
067:
068: /**
069: * å°† exported class 交给 ClassLoaderRepository 缓å˜
070: *
071: * @param module module name
072: * @param clz clz
073: */
074: public synchronized void addExportedClass(String module, Class clz) {
075: logger
076: .debug("Exportping Class: " + clz + ", Module: "
077: + module);
078: if (exportClassRepo.containsKey(clz.getName())) {
079: logger.warn("Class: " + clz.getName()
080: + " to be exported has been exist, overwrite!");
081: }
082: ClassEntry classEntry = new ClassEntry(module, clz);
083: exportClassRepo.put(clz.getName(), classEntry);
084: }
085:
086: /**
087: * 装载 export 类
088: * 在 ModuleClassLoader loadImportClass 时调用
089: *
090: * @param className �装载的 class
091: * @return Class
092: * @throws ClassNotFoundException if class not found
093: */
094: Class loadExportClass(String className)
095: throws ClassNotFoundException {
096: if (className == null || className.trim().length() == 0) {
097: throw new IllegalArgumentException("Class name: "
098: + className + " is invalid.");
099: }
100: if (exportClassRepo.containsKey(className)) {
101: ClassEntry classEntry = exportClassRepo.get(className);
102: //å?ªæœ‰è¢«å¤–部模å?—饮用æ‰?ä¼šå¢žåŠ å¼•ç”¨æ¬¡æ•°,如果是被本模å?—load,ModuleClassLoader会调用decreaseReference
103: //如果是本模å?—的类,将在 findLoadedClass ä¸è¿”回,ä¸?会ç»?过 ClassLoaderRepository
104: classEntry.setReferenced();
105: return classEntry.getClazz();
106: }
107: throw new ClassNotFoundException("Can not found class: "
108: + className + ", it was not exported.");
109: }
110:
111: boolean isExportClassLoaded(String className) {
112: return exportClassRepo.containsKey(className);
113: }
114:
115: /**
116: * 判æ–一个 Export Class 是å?¦å·²ç»?被引用,如果已ç»?被引用,å°†ä¸?能销æ¯?
117: * 如果一定�销�,那么也需�引用它的类
118: *
119: * @param clz Class
120: * @return true if referenced
121: */
122: boolean isExportedClassReferenced(Class clz) {
123: if (exportClassRepo.containsKey(clz.getName())) {
124: return exportClassRepo.get(clz.getName()).isReferenced();
125: } else {
126: return false;
127: }
128: }
129:
130: /**
131: * æ·»åŠ URL 到 Classpath æ?œç´¢è·¯å¾„
132: *
133: * @param url jar url
134: */
135: protected void addURL(URL url) {
136: logger.debug("Add URL " + url.toString()
137: + " to ClassLoaderRepository.");
138: super .addURL(url);
139: }
140:
141: /**
142: * å› ä¸º ClassLoaderRepository 是 LocalClassLoader çš„ parent ClassLoader
143: * LocalClassLoader 会直接调这个方法,所以必须�覆盖
144: * 首先从 ClassLoaderRepository çš„classpath路径ä¸è£…载类,如果失败, 装载缓å˜çš„ LocalClassLoader
145: * 已�装载的类
146: *
147: * @param name class name
148: * @param resolve need resole
149: * @return class
150: * @throws ClassNotFoundException
151: */
152: protected synchronized Class<?> loadClass(String name,
153: boolean resolve) throws ClassNotFoundException {
154: try {
155: return super .loadClass(name, resolve);
156: } catch (ClassNotFoundException e) {
157: try {
158: Class clz = loadExportClass(name);
159: if (resolve) {
160: resolveClass(clz);
161: }
162: return clz;
163: } catch (ClassNotFoundException e1) {
164: // e.printStackTrace();
165: }
166: }
167: throw new ClassNotFoundException(name);
168: }
169:
170: /**
171: * 一个Module export 的类,这些类一旦装载,çƒéƒ¨ç½²çš„时候,也ä¸?会é‡?新装载
172: * è¿™ç§?类一旦装载,就被缓å˜åœ¨Repositoryä¸ï¼Œä»¥å?Žload的时候,将首先检查缓å˜
173: * <p/>
174: * export的类一般是一些接�或者工具类。
175: * 如果export的类�生的改�,那么就需��新部署已�引用了export类的模�,
176: * å?¦åˆ™å¼•ç”¨æ¨¡å?—å¾—ä¸?到新的Classï¼Œä¼šé€ æˆ? ClassCastException 错误
177: */
178: class ClassEntry {
179: private String module;
180: private Class clz;
181: private boolean referenced = false;
182:
183: public ClassEntry(String module, Class clz) {
184: this .module = module;
185: this .clz = clz;
186: }
187:
188: public Class getClazz() {
189: return clz;
190: }
191:
192: public String getModule() {
193: return module;
194: }
195:
196: public boolean isReferenced() {
197: return referenced;
198: }
199:
200: public void setReferenced() {
201: this .referenced = true;
202: }
203: }
204:
205: public static void main(String[] args) {
206:
207: }
208: }
|