00001
00002
00003
00004
00005
00006
00007 package Sct;
00008
00009 import java.util.StringTokenizer;
00010 import java.util.jar.*;
00011 import java.util.zip.*;
00012 import java.util.Enumeration;
00013 import java.util.*;
00014 import java.io.*;
00015
00024 public class SearchClassLoader extends ClassLoader {
00025 private static SearchClassLoader loader = new SearchClassLoader();
00026
00027 private HashMap cache = new HashMap();
00028
00029 class CacheData {
00030 String name;
00031 Class[] prototype;
00032
00033 CacheData(String name, Class[] prototype) {
00034 this.name = name;
00035 this.prototype = prototype;
00036 }
00037 public boolean equals(Object ob) {
00038 CacheData cd = (CacheData) ob;
00039 if (cd == null) return false;
00040 boolean equal = name.equals(cd.name) && prototype.length == cd.prototype.length;
00041
00042 if (!equal) return false;
00043 for (int i=0; i<prototype.length && equal; ++i) {
00044 equal &= prototype[i].equals(cd.prototype[i]);
00045 }
00046 return equal;
00047 }
00048
00049 public int hashCode() {
00050 int hash = name.hashCode();
00051 for (int i=0; i<prototype.length; ++i) {
00052 hash += prototype[i].hashCode();
00053 }
00054 return hash;
00055 }
00056 }
00057
00058 public static SearchClassLoader instance() {
00059 return loader;
00060 }
00061
00062
00063
00064
00065
00066 public Class loadClass(String name, Class[] prototype) throws ClassNotFoundException {
00067 Class c = findInMap(name, prototype);
00068 if (c!=null) return c;
00069 c = findClassInParent(name, prototype);
00070 if (c == null) c = findClassInClassPath(name, prototype);
00071 if (c == null) c = findClassInPackages(name, prototype);
00072
00073 if (c != null) {
00074 addToMap(name, c, prototype);
00075 return c;
00076 }
00077 else throw new ClassNotFoundException("ClassLoaderIS could not find class: " + name);
00078 }
00079
00080 private void addToMap(String name, Class c, Class[] prototype) {
00081 CacheData cd = new CacheData(name, prototype);
00082 cache.put(cd, c);
00083 }
00084
00085 private Class findInMap(String name, Class[] prototype) {
00086 CacheData cd = new CacheData(name, prototype);
00087 return (Class)cache.get(cd);
00088 }
00089
00090 private boolean checkClass(Class c, Class[] prototype) {
00091
00092 try {
00093
00094 c.getConstructor(prototype);
00095 return true;
00096 } catch (NoSuchMethodException nsme) {
00097
00098 return false;
00099 }
00100 }
00101
00102 private Class findClassInParent(String name, Class[] prototype) {
00103
00104 try {
00105 Class c = loadClass(name);
00106 if (checkClass(c, prototype)) return c;
00107 } catch (ClassNotFoundException e) {}
00108 return null;
00109 }
00110
00111 private Class findClassInPackages(String name, Class[] prototype) {
00112 Class c = null;
00113 Package[] p = getPackages();
00114 int i = 0;
00115 while (c==null && i<p.length) {
00116 c = findClassInParent(p[i].getName() + "." + name, prototype);
00117 ++i;
00118 }
00119 return c;
00120 }
00121
00122
00125 private Class findClassInClassPath(String name, Class[] prototype) {
00126 Class c = null;
00127 String classPath = System.getProperty("java.class.path");
00128
00129 String classFileName = name + ".class";
00130 StringTokenizer st = new StringTokenizer(classPath, ":");
00131
00132 while (st.hasMoreTokens() && c==null) {
00133 String cpElement = st.nextToken();
00134
00135 if (cpElement.endsWith(".jar")) c = findInJarFile(classFileName, cpElement, prototype);
00136 else if (cpElement.endsWith(".zip")) c = findInZipFile(classFileName, cpElement, prototype);
00137 else c = findInDir(classFileName, cpElement, prototype);
00138
00139 }
00140
00141 return c;
00142 }
00143
00144 private Class findInDir(String fileName, String dirName, Class[] prototype) {
00145 File f = new File(dirName);
00146
00147 if (!f.isDirectory()) return null;
00148 return findInDir(fileName, f.getAbsolutePath(), f, prototype);
00149 }
00150
00151 private Class findInDir(String fileName, String parentDir, File dir, Class[] prototype) {
00152 File[] files = dir.listFiles(new MyFileNameFilter(fileName));
00153
00154 if (files.length > 0) {
00155 String className = files[0].getAbsolutePath();
00156
00157 className = className.substring(parentDir.length() + 1, className.length() - 6);
00158
00159 Class c = findClassInParent(className, prototype);
00160 if (c!=null) return c;
00161 }
00162
00163
00164 files = dir.listFiles();
00165 Class c;
00166 for (int i=0; i<files.length; ++i) {
00167 if (files[i].isDirectory()) {
00168 c = findInDir(fileName, parentDir, files[i], prototype);
00169 if (c!=null) return c;
00170 }
00171 }
00172 return null;
00173 }
00174
00175 private class MyFileNameFilter implements FilenameFilter {
00176 private String name;
00177 MyFileNameFilter(String name) {
00178 this.name = name;
00179 }
00180
00181 public boolean accept(File dir, String name) {
00182 return this.name.equals(name);
00183 }
00184 }
00185
00186
00187 private Class findInZipFile(String classFileName, String cpElement, Class[] prototype) {
00188 ZipFile f = null;
00189 try {
00190 f = new ZipFile(cpElement);
00191 return findInZipFile(f, classFileName, prototype);
00192 } catch (IOException e) {
00193 } finally {
00194 try {
00195 if (f != null) f.close();
00196 } catch (IOException e) {}
00197 }
00198 return null;
00199 }
00200
00201 private Class findInJarFile(String classFileName, String cpElement, Class[] prototype) {
00202 JarFile f = null;
00203 try {
00204 f = new JarFile(cpElement);
00205 return findInZipFile(f, classFileName, prototype);
00206 } catch (IOException e) {
00207 } finally {
00208 try {
00209 if (f != null) f.close();
00210 } catch (IOException e) {}
00211 }
00212 return null;
00213 }
00214
00215 private Class findInZipFile(ZipFile f, String classFileName, Class[] prototype) {
00216 Enumeration e = f.entries();
00217 while (e.hasMoreElements()) {
00218 String entry = ((ZipEntry)e.nextElement()).getName();
00219 if (entry.endsWith("/" + classFileName)) {
00220 String className = entry.substring(0, entry.length() - 6);
00221 className.replace('/', '.');
00222 Class c = findClassInParent(className, prototype);
00223 if (c != null) return c;
00224 }
00225 }
00226 return null;
00227 }
00228
00229
00230 public static void main(String[] args) {
00231 find("Test");
00232 find("SctControl.Test");
00233 find("SctControl/Test");
00234 find("SctControl/Test.class");
00235 }
00236
00237 public static void find(String name) {
00238 System.out.println("\n\nSearching for:" + name +"\n");
00239 SearchClassLoader cl = SearchClassLoader.instance();
00240 Class[] argTypes = {IStream.class, ObjectManager.class};
00241 try {
00242 Class c = cl.loadClass(name, argTypes);
00243 System.out.println("Success!!! : " + c.getName());
00244 } catch (ClassNotFoundException e) {
00245 System.out.println(e.getMessage());
00246 }
00247 }
00248 }