1 15 16 package javassist.bytecode; 17 18 import java.io.DataInputStream ; 19 import java.io.DataOutputStream ; 20 import java.io.IOException ; 21 import java.util.Map ; 22 import java.util.LinkedList ; 23 import java.util.ArrayList ; 24 import java.util.ListIterator ; 25 import java.util.List ; 26 27 import javassist.CannotCompileException; 28 29 35 public final class ClassFile { 36 int major, minor; ConstPool constPool; 38 int thisClass; 39 int accessFlags; 40 int superClass; 41 int[] interfaces; 42 ArrayList fields; 43 ArrayList methods; 44 LinkedList attributes; 45 46 String thisclassname; 48 51 public ClassFile(DataInputStream in) throws IOException { 52 read(in); 53 } 54 55 63 public ClassFile(boolean isInterface, 64 String classname, String superclass) { 65 major = 45; 66 minor = 3; constPool = new ConstPool(classname); 68 thisClass = constPool.getThisClassInfo(); 69 if (isInterface) 70 accessFlags = AccessFlag.SUPER | AccessFlag.INTERFACE 71 | AccessFlag.ABSTRACT; 72 else 73 accessFlags = AccessFlag.SUPER; 74 75 initSuperclass(superclass); 76 interfaces = null; 77 fields = new ArrayList (); 78 methods = new ArrayList (); 79 thisclassname = classname; 80 81 attributes = new LinkedList (); 82 attributes.add(new SourceFileAttribute(constPool, 83 getSourcefileName(thisclassname))); 84 } 85 86 private void initSuperclass(String superclass) { 87 if (superclass != null) 88 superClass = constPool.addClassInfo(superclass); 89 else 90 superClass = constPool.addClassInfo("java.lang.Object"); 91 } 92 93 private static String getSourcefileName(String qname) { 94 int index = qname.lastIndexOf('.'); 95 if (index >= 0) 96 qname = qname.substring(index + 1); 97 98 return qname + ".java"; 99 } 100 101 106 public void compact() { 107 ConstPool cp = compact0(); 108 ArrayList list = methods; 109 int n = list.size(); 110 for (int i = 0; i < n; ++i) { 111 MethodInfo minfo = (MethodInfo)list.get(i); 112 minfo.compact(cp); 113 } 114 115 list = fields; 116 n = list.size(); 117 for (int i = 0; i < n; ++i) { 118 FieldInfo finfo = (FieldInfo)list.get(i); 119 finfo.compact(cp); 120 } 121 122 attributes = AttributeInfo.copyAll(attributes, cp); 123 constPool = cp; 124 } 125 126 private ConstPool compact0() { 127 ConstPool cp = new ConstPool(thisclassname); 128 thisClass = cp.getThisClassInfo(); 129 superClass = cp.addClassInfo(getSuperclass()); 130 131 if (interfaces != null) { 132 int n = interfaces.length; 133 for (int i = 0; i < n; ++i) 134 interfaces[i] 135 = cp.addClassInfo(constPool.getClassInfo(interfaces[i])); 136 } 137 138 return cp; 139 } 140 141 147 public void prune() { 148 ConstPool cp = compact0(); 149 150 ArrayList list = methods; 151 int n = list.size(); 152 for (int i = 0; i < n; ++i) { 153 MethodInfo minfo = (MethodInfo)list.get(i); 154 minfo.prune(cp); 155 } 156 157 list = fields; 158 n = list.size(); 159 for (int i = 0; i < n; ++i) { 160 FieldInfo finfo = (FieldInfo)list.get(i); 161 finfo.prune(cp); 162 } 163 164 attributes = new LinkedList (); 165 cp.prune(); 166 constPool = cp; 167 } 168 169 172 public ConstPool getConstPool() { 173 return constPool; 174 } 175 176 179 public boolean isInterface() { 180 return (accessFlags & AccessFlag.INTERFACE) != 0; 181 } 182 183 186 public boolean isFinal() { 187 return (accessFlags & AccessFlag.FINAL) != 0; 188 } 189 190 193 public boolean isAbstract() { 194 return (accessFlags & AccessFlag.ABSTRACT) != 0; 195 } 196 197 202 public int getAccessFlags() { 203 return accessFlags; 204 } 205 206 211 public void setAccessFlags(int acc) { 212 accessFlags = acc | AccessFlag.SUPER; 213 } 214 215 218 public String getName() { 219 return thisclassname; 220 } 221 222 226 public void setName(String name) { 227 renameClass(thisclassname, name); 228 } 229 230 233 public String getSuperclass() { 234 return constPool.getClassInfo(superClass); 235 } 236 237 241 public int getSuperclassId() { 242 return superClass; 243 } 244 245 251 public void setSuperclass(String superclass) 252 throws CannotCompileException 253 { 254 if (superclass == null) 255 superclass = "java.lang.Object"; 256 257 try { 258 superClass = constPool.addClassInfo(superclass); 259 ArrayList list = methods; 260 int n = list.size(); 261 for (int i = 0; i < n; ++i) { 262 MethodInfo minfo = (MethodInfo)list.get(i); 263 minfo.setSuperclass(superclass); 264 } 265 } 266 catch (BadBytecode e) { 267 throw new CannotCompileException(e); 268 } 269 } 270 271 283 public final void renameClass(String oldname, String newname) { 284 ArrayList list; 285 int n; 286 287 if (oldname.equals(newname)) 288 return; 289 290 if (oldname.equals(thisclassname)) 291 thisclassname = newname; 292 293 oldname = Descriptor.toJvmName(oldname); 294 newname = Descriptor.toJvmName(newname); 295 constPool.renameClass(oldname, newname); 296 297 list = methods; 298 n = list.size(); 299 for (int i = 0; i < n; ++i) { 300 MethodInfo minfo = (MethodInfo)list.get(i); 301 String desc = minfo.getDescriptor(); 302 minfo.setDescriptor(Descriptor.rename(desc, oldname, newname)); 303 } 304 305 list = fields; 306 n = list.size(); 307 for (int i = 0; i < n; ++i) { 308 FieldInfo finfo = (FieldInfo)list.get(i); 309 String desc = finfo.getDescriptor(); 310 finfo.setDescriptor(Descriptor.rename(desc, oldname, newname)); 311 } 312 } 313 314 325 public final void renameClass(Map classnames) { 326 String jvmNewThisName 327 = (String )classnames.get(Descriptor.toJvmName(thisclassname)); 328 if (jvmNewThisName != null) 329 thisclassname = Descriptor.toJavaName(jvmNewThisName); 330 331 constPool.renameClass(classnames); 332 333 ArrayList list = methods; 334 int n = list.size(); 335 for (int i = 0; i < n; ++i) { 336 MethodInfo minfo = (MethodInfo)list.get(i); 337 String desc = minfo.getDescriptor(); 338 minfo.setDescriptor(Descriptor.rename(desc, classnames)); 339 } 340 341 list = fields; 342 n = list.size(); 343 for (int i = 0; i < n; ++i) { 344 FieldInfo finfo = (FieldInfo)list.get(i); 345 String desc = finfo.getDescriptor(); 346 finfo.setDescriptor(Descriptor.rename(desc, classnames)); 347 } 348 } 349 350 353 public String [] getInterfaces() { 354 if (interfaces == null) 355 return new String [0]; 356 else { 357 int n = interfaces.length; 358 String [] list = new String [n]; 359 for (int i = 0; i < n; ++i) 360 list[i] = constPool.getClassInfo(interfaces[i]); 361 362 return list; 363 } 364 } 365 366 371 public void setInterfaces(String [] nameList) { 372 if (nameList != null) { 373 int n = nameList.length; 374 interfaces = new int[n]; 375 for (int i = 0; i < n; ++i) 376 interfaces[i] = constPool.addClassInfo(nameList[i]); 377 } 378 } 379 380 384 public void addInterface(String name) { 385 int info = constPool.addClassInfo(name); 386 if (interfaces == null) { 387 interfaces = new int[1]; 388 interfaces[0] = info; 389 } 390 else { 391 int n = interfaces.length; 392 int[] newarray = new int[n + 1]; 393 System.arraycopy(interfaces, 0, newarray, 0, n); 394 newarray[n] = info; 395 interfaces = newarray; 396 } 397 } 398 399 405 public List getFields() { 406 return fields; 407 } 408 409 412 public void addField(FieldInfo finfo) throws CannotCompileException { 413 testExistingField(finfo.getName(), finfo.getDescriptor()); 414 fields.add(finfo); 415 } 416 417 private void addField0(FieldInfo finfo) { 418 fields.add(finfo); 419 } 420 421 private void testExistingField(String name, String descriptor) 422 throws CannotCompileException 423 { 424 ListIterator it = fields.listIterator(0); 425 while (it.hasNext()) { 426 FieldInfo minfo = (FieldInfo)it.next(); 427 if (minfo.getName().equals(name)) 428 throw new CannotCompileException("duplicate field: " + name); 429 } 430 } 431 432 438 public List getMethods() { 439 return methods; 440 } 441 442 448 public MethodInfo getMethod(String name) { 449 ArrayList list = methods; 450 int n = list.size(); 451 for (int i = 0; i < n; ++i) { 452 MethodInfo minfo = (MethodInfo)list.get(i); 453 if (minfo.getName().equals(name)) 454 return minfo; 455 } 456 457 return null; 458 } 459 460 464 public MethodInfo getStaticInitializer() { 465 return getMethod(MethodInfo.nameClinit); 466 } 467 468 471 public void addMethod(MethodInfo minfo) throws CannotCompileException { 472 testExistingMethod(minfo.getName(), minfo.getDescriptor()); 473 methods.add(minfo); 474 } 475 476 private void addMethod0(MethodInfo minfo) { 477 methods.add(minfo); 478 } 479 480 private void testExistingMethod(String name, String descriptor) 481 throws CannotCompileException 482 { 483 ListIterator it = methods.listIterator(0); 484 while (it.hasNext()) { 485 MethodInfo minfo = (MethodInfo)it.next(); 486 if (minfo.getName().equals(name) 487 && Descriptor.eqParamTypes(minfo.getDescriptor(), descriptor)) 488 throw new CannotCompileException("duplicate method: " + name); 489 } 490 } 491 492 498 public List getAttributes() { 499 return attributes; 500 } 501 502 507 public AttributeInfo getAttribute(String name) { 508 LinkedList list = attributes; 509 int n = list.size(); 510 for (int i = 0; i < n; ++i) { 511 AttributeInfo ai = (AttributeInfo)list.get(i); 512 if (ai.getName().equals(name)) 513 return ai; 514 } 515 516 return null; 517 } 518 519 523 public void addAttribute(AttributeInfo info) { 524 AttributeInfo.remove(attributes, info.getName()); 525 attributes.add(info); 526 } 527 528 533 public String getSourceFile() { 534 SourceFileAttribute sf 535 = (SourceFileAttribute)getAttribute(SourceFileAttribute.tag); 536 if (sf == null) 537 return null; 538 else 539 return sf.getFileName(); 540 } 541 542 private void read(DataInputStream in) throws IOException { 543 int i, n; 544 int magic = in.readInt(); 545 if (magic != 0xCAFEBABE) 546 throw new IOException ("non class file"); 547 548 minor = in.readUnsignedShort(); 549 major = in.readUnsignedShort(); 550 constPool = new ConstPool(in); 551 accessFlags = in.readUnsignedShort(); 552 thisClass = in.readUnsignedShort(); 553 constPool.setThisClassInfo(thisClass); 554 superClass = in.readUnsignedShort(); 555 n = in.readUnsignedShort(); 556 if (n == 0) 557 interfaces = null; 558 else { 559 interfaces = new int[n]; 560 for (i = 0; i < n; ++i) 561 interfaces[i] = in.readUnsignedShort(); 562 } 563 564 ConstPool cp = constPool; 565 n = in.readUnsignedShort(); 566 fields = new ArrayList (); 567 for (i = 0; i < n; ++i) 568 addField0(new FieldInfo(cp, in)); 569 570 n = in.readUnsignedShort(); 571 methods = new ArrayList (); 572 for (i = 0; i < n; ++i) 573 addMethod0(new MethodInfo(cp, in)); 574 575 attributes = new LinkedList (); 576 n = in.readUnsignedShort(); 577 for (i = 0; i < n; ++i) 578 addAttribute(AttributeInfo.read(cp, in)); 579 580 thisclassname = constPool.getClassInfo(thisClass); 581 } 582 583 587 public void write(DataOutputStream out) throws IOException { 588 int i, n; 589 590 out.writeInt(0xCAFEBABE); out.writeShort(minor); out.writeShort(major); constPool.write(out); out.writeShort(accessFlags); 595 out.writeShort(thisClass); 596 out.writeShort(superClass); 597 598 if (interfaces == null) 599 n = 0; 600 else 601 n = interfaces.length; 602 603 out.writeShort(n); 604 for (i = 0; i < n; ++i) 605 out.writeShort(interfaces[i]); 606 607 ArrayList list = fields; 608 n = list.size(); 609 out.writeShort(n); 610 for (i = 0; i < n; ++i) { 611 FieldInfo finfo = (FieldInfo)list.get(i); 612 finfo.write(out); 613 } 614 615 list = methods; 616 n = list.size(); 617 out.writeShort(n); 618 for (i = 0; i < n; ++i) { 619 MethodInfo minfo = (MethodInfo)list.get(i); 620 minfo.write(out); 621 } 622 623 out.writeShort(attributes.size()); 624 AttributeInfo.writeAll(attributes, out); 625 } 626 } 627 | Popular Tags |