1 30 31 package jbet; 32 import java.util.*; 33 import java.util.zip.*; 34 import java.io.*; 35 import java.lang.*; 36 37 54 55 public class ClassInfoLoader implements ClassFinder { 56 Vector classPath; 57 private Hashtable classes; 58 private Hashtable files; 59 60 public static char colon = java.io.File.pathSeparatorChar; 61 public static char slash = java.io.File.separatorChar; 62 63 public static String JbetLogFacility = "classloader"; 64 65 73 74 public static class DirectoryCPE extends ClassPathElement { 75 String prefix; 76 String dirname; 77 public DirectoryCPE (String dirname) { 78 this.prefix = ""; 79 this.dirname = dirname; 80 } 81 public DirectoryCPE (String prefix, String dirname) { 82 this.prefix = prefix; 83 this.dirname = dirname; 84 } 85 public InputStream get(String filename) throws IOException { 86 try { 87 File f = new File(dirname + slash + filename); 88 if (f.exists()) 89 return new FileInputStream(f); 90 else 91 return null; 92 } catch (FileNotFoundException e) { 93 return null; 94 } 95 } 96 public OutputStream put(String filename) throws IOException { 97 return put (new File(dirname), filename); 98 } 99 private OutputStream put(File f, String filename) throws IOException { 100 if (filename.startsWith("./")) 101 filename = filename.substring(2); 102 if (filename.startsWith("/")) throw new IOException 103 ("requested an absolute path from a DirectoryCPE"); 104 int pos = filename.lastIndexOf( '/' ); 105 if (pos == -1) { 106 return new FileOutputStream(f + "/" + filename); 107 } 108 File d = new File (f + "/" + filename.substring(0,pos)); 109 if (!d.exists()) { 110 d.mkdirs(); 111 } 112 return put(d, filename.substring(pos+1)); 113 } 114 public Iterator classes() { 115 File dirfile = new File(dirname); 116 final File[] list = dirfile.listFiles(); 117 Vector out = new Vector(); 118 for (int i = 0; i < list.length; i++) { 119 if (! list[i].isFile()) continue; 120 String filename = list[i].getName(); 121 if (! filename.endsWith(".class")) continue; 122 filename = filename.substring (0, filename.lastIndexOf ('.')); 123 out.addElement(prefix + filename); 124 } 125 return out.iterator(); 126 } 127 public boolean subdir_exists(String filename) { 128 File f = new File (dirname + slash + filename); 129 return f.exists() && f.isDirectory(); 130 } 131 public boolean class_exists(String filename) { 132 File f = new File (dirname + slash + filename + ".class"); 133 return f.exists(); 134 } 135 public String toString() { 136 return dirname; 137 } 138 public Iterator subdirs() { 139 File dirfile = new File(dirname); 140 final File[] list = dirfile.listFiles(); 141 Vector out = new Vector(); 142 for (int i = 0; i < list.length; i++) { 143 if (list[i].isDirectory()) 144 out.add(list[i].getName()); 145 } 146 return out.iterator(); 147 } 148 public ClassPathElement subdir (String subdirname) throws IOException { 149 return new DirectoryCPE (prefix + subdirname + "/", 150 dirname + "/" + subdirname); 151 } 152 public boolean supports_subdir() { return true; } 153 } 154 155 156 public static ClassPathElement directory(String name) { 157 final String s = ((name.length()!=0) 158 && (name.charAt(name.length()-1) == slash)) 159 ? name.substring(0, name.length()-1) 160 : name; 161 return new DirectoryCPE(s); 162 } 163 164 172 173 public static class ZipFileCPE extends ClassPathElement { 174 ZipFile zf; 175 String zfname; 176 public ZipFileCPE(String zfname) throws IOException { 177 zf = new ZipFile(zfname); 178 this.zfname = zfname; 179 } 180 public InputStream get(String filename) throws IOException { 181 ZipEntry ze = zf.getEntry(filename); 182 if (ze == null) return null; 183 return zf.getInputStream(ze); 184 } 185 public OutputStream put(String filename) throws IOException { 186 throw new RuntimeException 187 ("Writing to zip files not supported"); 188 } 189 public Iterator classes() { 190 Vector out = new Vector(); 192 for (Enumeration e = zf.entries(); e.hasMoreElements(); ) { 193 ZipEntry entry = (ZipEntry) e.nextElement(); 194 if (entry.isDirectory()) continue; 195 String s = entry.getName(); 196 if (! s.endsWith(".class")) continue; 197 s = s.substring (0, s.lastIndexOf ('.')); 198 out.addElement(s); 199 } 200 return out.iterator(); 201 } 202 public Iterator subdirs() { 203 return null; 204 } 205 public boolean class_exists(String name) { 206 return zf.getEntry(name + ".class") != null; 207 } 208 public boolean subdir_exists(String name) { 209 return false; 210 } 211 public String toString() { 212 return zfname; 213 } 214 215 public ClassPathElement subdir (String dirname) throws IOException { 216 throw new 217 IllegalStateException ("don't put zipfiles on the command path"); 218 } 219 public boolean supports_subdir() { return false; } 220 } 221 222 public static ClassPathElement zipfile(String zfname) throws IOException { 223 return new ZipFileCPE(zfname); 224 } 225 226 static ClassPathElement resolveCPElement (String s) throws IOException { 227 ClassPathElement cpe; 228 if (( s.endsWith(".jar") || s.endsWith(".zip")) ) 229 cpe = zipfile(s); 230 else 231 cpe = directory(s); 232 return cpe; 233 } 234 235 236 242 ClassPathElement getCPElement(int i) throws IOException { 243 Object o = classPath.elementAt(i); 244 if (o instanceof ClassPathElement) 245 return (ClassPathElement) o; 246 String s = (String ) o; 247 ClassPathElement cpe = resolveCPElement (s); 248 classPath.setElementAt(cpe, i); 249 return cpe; 250 } 251 252 259 public void parseClassPath(String cpString) { 260 parseClassPath(cpString, true); 261 } 262 263 269 public void parseClassPath(String cpString, boolean insertAtFront) { 270 for (int i = 0; i < cpString.length();) { 271 int io = cpString.indexOf(colon, i); 272 String s; 273 if (io == -1) { 274 s = cpString.substring(i); 275 i = cpString.length(); 276 } else { 277 s = cpString.substring(i, io); 278 i = io + 1; 279 } 280 if (insertAtFront) 281 classPath.insertElementAt(s, 0); 282 else 283 classPath.addElement(s); 284 } 285 } 286 287 289 public void clearPath() { 290 classPath.removeAllElements(); 291 } 292 293 295 public ClassInfoLoader() { 296 classPath = new Vector(); 297 classes = new Hashtable(); 298 files = new Hashtable(); 299 } 300 301 303 public Enumeration getClasses() { 304 final Enumeration e1f = classes.elements(); 305 final Enumeration e2f = files.elements(); 306 return new Enumeration() { 307 Enumeration e1 = e1f, e2 = e2f; 308 public boolean hasMoreElements() { 309 return (e1 != null && e1.hasMoreElements()) || 310 (e2 != null && e2.hasMoreElements()); 311 } 312 public Object nextElement() { 313 if (e1 != null) { 314 if (e1.hasMoreElements()) 315 return e1.nextElement(); 316 else 317 e1 = null; 318 } 319 if (e2 != null) 320 return e2.nextElement(); 321 throw new IllegalStateException ("can't get here"); 322 } 323 }; 324 } 325 326 327 public ClassInfo findClass(String name) throws ClassFileException { 328 return getClass(name); 329 } 330 331 332 333 339 340 public ClassInfo lookupClass(String name) { 341 if (name.startsWith("@")) { 342 String filename = name.substring(1, name.length()); 343 return (ClassInfo) files.get(filename); 344 } else { 345 return (ClassInfo) classes.get(name); 346 } 347 } 348 349 public ClassInfo getClass(String name) throws ClassFileException { 350 ClassInfo cr = lookupClass(name); 351 if (cr != null) 352 return cr; 353 cr = loadClass(name); 354 putClass(name, cr); 355 return cr; 356 } 357 358 public ClassInfo getCopy(String name) throws ClassFileException { 359 ClassInfo cr = lookupClass(name); 360 if (cr != null) 361 return new ClassInfo(cr); 362 else 363 return loadClass(name); 364 } 365 366 public ClassFinder getCopyFinder = new ClassFinder() { 367 public ClassInfo findClass(String name) throws ClassFileException { 368 return getCopy(name); 369 } 370 }; 371 372 378 public MethodInfo getMethod(String cname, String name, Descriptor type) throws ClassFileException, ElementNotFoundException 379 { 380 ClassInfo cr = getClass(cname); 381 MethodInfo ret = null; 382 for (int i = 0; i < cr.methods.size(); i++) { 383 MethodInfo mi = (MethodInfo) cr.methods.elementAt(i); 384 if (mi.name.equals(name) && 385 (type==null || type.equals(mi.descriptor))) 386 if (ret == null) 387 ret = mi; 388 else 389 throw new ElementNotFoundException 390 (cname, name, type, "Can not disambiguate"); 391 } 392 if (ret == null) { 393 throw new ElementNotFoundException (cname, name, type); 394 } 395 return ret; 396 } 397 398 403 public FieldInfo getField(String cname, String name) throws ClassFileException, ElementNotFoundException 404 { 405 ClassInfo cr = getClass(cname); 406 return cr.getField(name); 407 } 408 409 416 public Object getThing(String cname, String name, Descriptor d) throws ClassFileException, ElementNotFoundException { 417 if (name == null) return getClass(cname); 418 if (d == null) { 419 try { 420 return getField(cname, name); 421 } catch (ElementNotFoundException e) { 422 return getMethod(cname, name, null); 423 } 424 } else 425 return getMethod(cname, name, d); 426 } 427 428 429 public void removeClass (ClassInfo cr) { 430 Object z = classes.get (cr.name()); 431 if (z == cr) 432 classes.remove (cr.name()); 433 } 434 435 438 public void putClass(ClassInfo cr) { 439 classes.put( cr.name(), cr ); 440 } 441 442 public void putClass(String name, ClassInfo cr) { 443 if (name.startsWith("@")) 444 files.put(name.substring(1), cr); 445 else 446 classes.put(name, cr); 447 } 448 449 453 public boolean exists (String name) throws ClassFileException { 454 if (lookupClass(name) != null) 455 return true; 456 try { 457 if (name.startsWith("@")) { 458 File f = new File(name.substring(1)); 459 return f.exists(); 460 } else { 461 for (int i = 0; i < classPath.size(); i++) 462 if (getCPElement(i).class_exists(name)) return true; 463 return false; 464 } 465 } catch (IOException e) { 466 throw new ClassFileException("IOException caught " 467 + name, e); 468 } 469 } 470 471 478 private ClassInfo loadClass(String name) throws ClassFileException { 479 ClassInfo cr; 480 try { 481 if (name.startsWith("@")) { 482 String filename = name.substring(1, name.length()); 483 String dirname = Util.basename(filename); 484 InputStream in = new FileInputStream(filename); 485 cr = new ClassInfo(in); 486 String pakname = Util.basename(cr.name()); 487 if ( name.endsWith(".class") && dirname.endsWith(pakname) ) { 488 cr.classPathElement = directory 489 (dirname.substring(0, dirname.length()-pakname.length())); 490 cr.filename = null; 491 } else { 492 cr.classPathElement = directory(dirname); 493 cr.filename = Util.unqualify(filename); 494 } 495 return cr; 496 } else { 497 for (int i = 0; i < classPath.size(); i++) { 498 ClassPathElement cpe; 499 try { 500 cpe = getCPElement(i); 501 } catch (IOException e) { 502 continue; 503 } 505 InputStream in = cpe.get(name + ".class"); 506 if (in == null) continue; 507 return new ClassInfo(in, cpe); 508 } 509 throw new ClassFileNotFoundException(name + ".class"); 510 } 511 } catch (IOException e) { 512 throw new ClassFileException("IOException caught trying to read " 513 + name, e); 514 } 515 } 516 517 public void findPackageClasses (String packname, Collection out, boolean sense) 518 throws ClassFileException { 519 String prefix; 520 if (packname.equals("")) 521 prefix = ""; 522 else 523 prefix = packname + "/"; 524 try { 525 HashSet outset = new HashSet(); 526 for (Enumeration e = classes.elements(); e.hasMoreElements();) { 527 ClassInfo cr = (ClassInfo) e.nextElement(); 528 if (cr.name().startsWith(prefix)) { 529 outset.add(cr.name()); 530 } 531 } 532 for (int i = 0; i < classPath.size(); i++) { 533 Iterator j = null; 534 ClassPathElement cpe; 535 try { 536 cpe = getCPElement(i); 537 } catch (IOException e) { 538 continue; 539 } 540 if (!packname.equals("") && cpe.supports_subdir()) { 541 if (!cpe.subdir_exists(packname)) continue; 542 j = cpe.subdir(packname).allclasses(); 543 } else 544 j = cpe.allclasses(); 545 while (j.hasNext()) { 546 String name = (String ) j.next(); 547 if (name.startsWith(prefix)) { 548 outset.add(name); 549 } 550 } 551 } 552 if (sense) 553 out.addAll(outset); 554 else 555 out.removeAll(outset); 556 } catch (IOException e) { 557 throw new ClassFileException("IOException caught ", e); 558 } 559 } 560 561 562 565 void print(LineWriter out) { 566 for (int i = 0; i < classPath.size(); i++) 567 out.println( classPath.elementAt(i).toString() ); 568 } 569 570 public String getClassPath () { 571 StringBuffer S = new StringBuffer (); 572 573 for (int i = 0; i < classPath.size(); i++) { 574 if (S.length() > 0) 575 S.append (":"); 576 S.append (classPath.elementAt(i).toString()); 577 } 578 579 return S.toString(); 580 } 581 } 582 | Popular Tags |