1 15 16 package javassist; 17 18 import java.io.BufferedInputStream ; 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.io.OutputStream ; 23 import java.net.URL ; 24 import java.util.Hashtable ; 25 26 60 public class ClassPool { 61 62 73 public boolean childFirstLookup = false; 74 75 protected ClassPoolTail source; 76 protected ClassPool parent; 77 protected Hashtable classes; 79 82 private Hashtable cflow = null; 84 private static final int INIT_HASH_SIZE = 191; 85 86 89 public ClassPool() { 90 this(null); 91 } 92 93 100 public ClassPool(ClassPool parent) { 101 this.classes = new Hashtable (INIT_HASH_SIZE); 102 this.source = new ClassPoolTail(); 103 this.parent = parent; 104 if (parent == null) { 105 CtClass[] pt = CtClass.primitiveTypes; 106 for (int i = 0; i < pt.length; ++i) 107 classes.put(pt[i].getName(), pt[i]); 108 } 109 110 this.cflow = null; 111 } 112 113 137 public static synchronized ClassPool getDefault() { 138 if (defaultPool == null) { 139 defaultPool = new ClassPool(null); 140 defaultPool.appendSystemPath(); 141 } 142 143 return defaultPool; 144 } 145 146 private static ClassPool defaultPool = null; 147 148 155 protected CtClass getCached(String classname) { 156 return (CtClass)classes.get(classname); 157 } 158 159 166 protected void cacheCtClass(String classname, CtClass c) { 167 classes.put(classname, c); 168 } 169 170 177 protected CtClass removeCached(String classname) { 178 return (CtClass)classes.remove(classname); 179 } 180 181 184 public String toString() { 185 return source.toString(); 186 } 187 188 198 public void recordInvalidClassName(String name) { 199 source.recordInvalidClassName(name); 200 } 201 202 210 void recordCflow(String name, String cname, String fname) { 211 if (cflow == null) 212 cflow = new Hashtable (); 213 214 cflow.put(name, new Object [] { cname, fname }); 215 } 216 217 222 public Object [] lookupCflow(String name) { 223 if (cflow == null) 224 cflow = new Hashtable (); 225 226 return (Object [])cflow.get(name); 227 } 228 229 247 public CtClass getAndRename(String orgName, String newName) 248 throws NotFoundException 249 { 250 CtClass clazz = get0(orgName, false); 251 if (clazz == null) 252 throw new NotFoundException(orgName); 253 254 if (clazz instanceof CtClassType) 255 ((CtClassType)clazz).setClassPool(this); 256 257 clazz.setName(newName); return clazz; 260 } 261 262 267 synchronized void classNameChanged(String oldname, CtClass clazz) { 268 CtClass c = (CtClass)getCached(oldname); 269 if (c == clazz) removeCached(oldname); 272 String newName = clazz.getName(); 273 checkNotFrozen(newName); 274 cacheCtClass(newName, clazz); 275 } 276 277 293 public CtClass get(String classname) throws NotFoundException { 294 CtClass clazz; 295 if (classname == null) 296 clazz = null; 297 else 298 clazz = get0(classname, true); 299 300 if (clazz == null) 301 throw new NotFoundException(classname); 302 else { 303 clazz.incGetCounter(); 304 return clazz; 305 } 306 } 307 308 313 protected synchronized CtClass get0(String classname, boolean useCache) 314 throws NotFoundException 315 { 316 CtClass clazz = null; 317 if (useCache) { 318 clazz = getCached(classname); 319 if (clazz != null) 320 return clazz; 321 } 322 323 if (!childFirstLookup && parent != null) { 324 clazz = parent.get0(classname, useCache); 325 if (clazz != null) 326 return clazz; 327 } 328 329 clazz = createCtClass(classname, useCache); 330 if (clazz != null) { 331 if (useCache) 332 cacheCtClass(classname, clazz); 333 334 return clazz; 335 } 336 337 if (childFirstLookup && parent != null) 338 clazz = parent.get0(classname, useCache); 339 340 return clazz; 341 } 342 343 350 protected CtClass createCtClass(String classname, boolean useCache) { 351 if (classname.endsWith("[]")) { 352 String base = classname.substring(0, classname.indexOf('[')); 353 if ((!useCache || getCached(base) == null) && find(base) == null) 354 return null; 355 else 356 return new CtArray(classname, this); 357 } 358 else 359 if (find(classname) == null) 360 return null; 361 else 362 return new CtClassType(classname, this); 363 } 364 365 374 public URL find(String classname) { 375 return source.find(classname); 376 } 377 378 384 void checkNotFrozen(String classname) throws RuntimeException { 385 CtClass clazz = getCached(classname); 386 if (clazz == null) { 387 if (!childFirstLookup && parent != null) { 388 try { 389 clazz = parent.get0(classname, true); 390 } 391 catch (NotFoundException e) {} 392 if (clazz != null) 393 throw new RuntimeException (classname 394 + " is in a parent ClassPool. Use the parent."); 395 } 396 } 397 else 398 if (clazz.isFrozen()) 399 throw new RuntimeException (classname 400 + ": frozen class (cannot edit)"); 401 } 402 403 405 InputStream openClassfile(String classname) throws NotFoundException { 406 return source.openClassfile(classname); 407 } 408 409 void writeClassfile(String classname, OutputStream out) 410 throws NotFoundException, IOException , CannotCompileException 411 { 412 source.writeClassfile(classname, out); 413 } 414 415 426 public CtClass[] get(String [] classnames) throws NotFoundException { 427 if (classnames == null) 428 return new CtClass[0]; 429 430 int num = classnames.length; 431 CtClass[] result = new CtClass[num]; 432 for (int i = 0; i < num; ++i) 433 result[i] = get(classnames[i]); 434 435 return result; 436 } 437 438 445 public CtMethod getMethod(String classname, String methodname) 446 throws NotFoundException 447 { 448 CtClass c = get(classname); 449 return c.getDeclaredMethod(methodname); 450 } 451 452 466 public CtClass makeClass(InputStream classfile) 467 throws IOException , RuntimeException { 468 classfile = new BufferedInputStream (classfile); 469 CtClass clazz = new CtClassType(classfile, this); 470 clazz.checkModify(); 471 String classname = clazz.getName(); 472 checkNotFrozen(classname); 473 cacheCtClass(classname, clazz); 474 return clazz; 475 } 476 477 485 public CtClass makeClass(String classname) throws RuntimeException { 486 return makeClass(classname, null); 487 } 488 489 498 public synchronized CtClass makeClass(String classname, CtClass superclass) 499 throws RuntimeException 500 { 501 checkNotFrozen(classname); 502 CtClass clazz = new CtNewClass(classname, this, false, superclass); 503 cacheCtClass(classname, clazz); 504 return clazz; 505 } 506 507 514 synchronized CtClass makeNestedClass(String classname) { 515 checkNotFrozen(classname); 516 CtClass clazz = new CtNewNestedClass(classname, this, false, null); 517 cacheCtClass(classname, clazz); 518 return clazz; 519 } 520 521 529 public CtClass makeInterface(String name) throws RuntimeException { 530 return makeInterface(name, null); 531 } 532 533 542 public synchronized CtClass makeInterface(String name, CtClass superclass) 543 throws RuntimeException 544 { 545 checkNotFrozen(name); 546 CtClass clazz = new CtNewClass(name, this, true, superclass); 547 cacheCtClass(name, clazz); 548 return clazz; 549 } 550 551 561 public ClassPath appendSystemPath() { 562 return source.appendSystemPath(); 563 } 564 565 574 public ClassPath insertClassPath(ClassPath cp) { 575 return source.insertClassPath(cp); 576 } 577 578 587 public ClassPath appendClassPath(ClassPath cp) { 588 return source.appendClassPath(cp); 589 } 590 591 600 public ClassPath insertClassPath(String pathname) 601 throws NotFoundException 602 { 603 return source.insertClassPath(pathname); 604 } 605 606 615 public ClassPath appendClassPath(String pathname) 616 throws NotFoundException 617 { 618 return source.appendClassPath(pathname); 619 } 620 621 626 public void removeClassPath(ClassPath cp) { 627 source.removeClassPath(cp); 628 } 629 630 642 public void appendPathList(String pathlist) throws NotFoundException { 643 char sep = File.pathSeparatorChar; 644 int i = 0; 645 for (;;) { 646 int j = pathlist.indexOf(sep, i); 647 if (j < 0) { 648 appendClassPath(pathlist.substring(i)); 649 break; 650 } 651 else { 652 appendClassPath(pathlist.substring(i, j)); 653 i = j + 1; 654 } 655 } 656 } 657 658 672 public Class toClass(CtClass clazz) throws CannotCompileException { 673 return toClass(clazz, Thread.currentThread().getContextClassLoader()); 674 } 675 676 692 public Class toClass(CtClass ct, ClassLoader loader) 693 throws CannotCompileException 694 { 695 try { 696 byte[] b = ct.toBytecode(); 697 Class cl = Class.forName("java.lang.ClassLoader"); 698 java.lang.reflect.Method method = 699 cl.getDeclaredMethod("defineClass", 700 new Class [] { String .class, byte[].class, 701 int.class, int.class }); 702 method.setAccessible(true); 703 Object [] args = new Object [] { ct.getName(), b, new Integer (0), 704 new Integer (b.length)}; 705 Class clazz = (Class )method.invoke(loader, args); 706 method.setAccessible(false); 707 return clazz; 708 } 709 catch (RuntimeException e) { 710 throw e; 711 } 712 catch (java.lang.reflect.InvocationTargetException e) { 713 throw new CannotCompileException(e.getTargetException()); 714 } 715 catch (Exception e) { 716 throw new CannotCompileException(e); 717 } 718 } 719 } 720 | Popular Tags |