1 23 24 25 package com.sun.jdo.api.persistence.enhancer.classfile; 26 27 import java.util.ArrayList ; 28 import java.util.List ; 29 import java.util.Vector ; 30 import java.util.Enumeration ; 31 import java.io.*; 32 import java.io.DataOutputStream ; 33 34 35 39 40 final public class ClassFile implements VMConstants, Serializable { 41 42 43 public static final int magic = 0xcafebabe; 44 45 public static final short[][] jdkMajorMinorVersions = new short[][]{ 47 new short[]{45, 3}, new short[]{46, 0}, new short[]{47, 0}, new short[]{48, 0}, new short[]{49, 0} }; 53 public static final List jdkVersions = 54 convertMajorMinorVersions(jdkMajorMinorVersions); 55 public static final String supportedVersions = printSupportedVersions(); 56 57 private int majorVersion = 0; 58 private int minorVersion = 0; 59 60 61 private ConstantPool constantPool = new ConstantPool(); 62 63 64 private int accessFlags = 0; 65 66 67 private ConstClass thisClassName; 68 69 70 private ConstClass superClassName; 71 72 75 private Vector classInterfaces = new Vector (); 76 77 80 private Vector classFields = new Vector (); 81 82 85 private Vector classMethods = new Vector (); 86 87 88 private AttributeVector classAttributes = new AttributeVector(); 89 90 91 92 93 94 95 96 99 public ConstantPool pool() { 100 return constantPool; 101 } 102 103 106 public int access() { 107 return accessFlags; 108 } 109 110 113 final public boolean isFinal() { 114 return (accessFlags & ACCFinal) != 0; 115 } 116 117 120 final public boolean isInterface() { 121 return (accessFlags & ACCInterface) != 0; 122 } 123 124 127 final public boolean isPublic() { 128 return (accessFlags & ACCPublic) != 0; 129 } 130 131 134 final public boolean isAbstract() { 135 return (accessFlags & ACCAbstract) != 0; 136 } 137 138 139 142 public void setAccessFlags (int flags) { 143 accessFlags = flags; 144 } 145 146 149 public ConstClass className() { 150 return thisClassName; 151 } 152 153 156 public ConstClass superName() { 157 return superClassName; 158 } 159 160 163 public String superNameString() { 164 return (superClassName == null) ? null : superClassName.asString(); 165 } 166 167 170 public void setSuperName(ConstClass superCl) { 171 superClassName = superCl; 172 } 173 174 178 public Vector interfaces() { 179 return classInterfaces; 180 } 181 182 185 public void addInterface (ConstClass iface) { 186 classInterfaces.addElement(iface); 187 } 188 189 193 public Vector fields() { 194 return classFields; 195 } 196 197 200 public void addField (ClassField field) { 201 classFields.addElement(field); 202 } 203 204 208 public void addField(ClassField field, int index) { 209 classFields.insertElementAt(field, index); 210 } 211 212 216 public Vector methods() { 217 return classMethods; 218 } 219 220 223 public ClassMethod findMethod(String methodName, String methodSig) { 224 for (Enumeration e = methods().elements(); e.hasMoreElements();) { 225 ClassMethod method = (ClassMethod) e.nextElement(); 226 if (method.name().asString().equals(methodName) && 227 method.signature().asString().equals(methodSig)) 228 return method; 229 } 230 return null; 231 } 232 233 236 public void addMethod(ClassMethod method) { 237 classMethods.addElement(method); 238 } 239 240 243 public ClassField findField(String fieldName) { 244 for (Enumeration e = fields().elements(); e.hasMoreElements();) { 245 ClassField field = (ClassField) e.nextElement(); 246 if (field.name().asString().equals(fieldName)) 247 return field; 248 } 249 return null; 250 } 251 252 255 public AttributeVector attributes() { 256 return classAttributes; 257 } 258 259 262 public ClassFile(DataInputStream data) throws ClassFormatError { 263 try { 264 int thisMagic = data.readInt(); 265 if (thisMagic != magic) 266 throw new ClassFormatError ("Bad magic value for input"); 268 short thisMinorVersion = data.readShort(); 269 short thisMajorVersion = data.readShort(); 270 273 if (isSupportedVersion(thisMajorVersion, thisMinorVersion)) { 274 minorVersion = thisMinorVersion; 275 majorVersion = thisMajorVersion; 276 } else { 277 throw new ClassFormatError ("Bad version number: {" + thisMajorVersion + "," + thisMinorVersion + 280 "} expected one of: " + supportedVersions); 282 } 283 readConstants(data); 284 accessFlags = data.readUnsignedShort(); 285 thisClassName = (ConstClass) 286 constantPool.constantAt(data.readUnsignedShort()); 287 superClassName = (ConstClass) 288 constantPool.constantAt(data.readUnsignedShort()); 289 readInterfaces(data); 290 readFields(data); 291 readMethods(data); 292 classAttributes = AttributeVector.readAttributes(data, constantPool); 293 } catch (IOException e) { 294 ClassFormatError cfe = new ClassFormatError ("IOException during reading"); cfe.initCause(e); 296 throw cfe; 297 } 298 } 301 302 305 public ClassFile(String cname, String supername) { 306 thisClassName = constantPool.addClass(cname); 307 superClassName = constantPool.addClass(supername); 308 } 311 312 315 public 316 void write (DataOutputStream buff) throws IOException { 317 buff.writeInt(magic); 318 buff.writeShort(minorVersion); 319 buff.writeShort(majorVersion); 320 constantPool.write(buff); 321 buff.writeShort(accessFlags); 322 buff.writeShort(thisClassName.getIndex()); 323 buff.writeShort(superClassName == null ? 0 : superClassName.getIndex()); 325 writeInterfaces(buff); 327 writeFields(buff); 328 writeMethods(buff); 329 classAttributes.write(buff); 330 } 331 332 335 public byte[] getBytes() throws java.io.IOException { 336 337 338 String writeClassToDirectory = 339 System.getProperty("filter.writeClassToDirectory"); 340 if (writeClassToDirectory != null) { 341 String filename = writeClassToDirectory + java.io.File.separator + 342 thisClassName.asString() + ".class"; System.err.println("Writing class to file " + filename); 344 DataOutputStream stream = new DataOutputStream ( 345 new java.io.FileOutputStream (filename)); 346 write(stream); 347 stream.close(); 348 } 349 350 351 352 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 353 write(new DataOutputStream (byteStream)); 354 355 return byteStream.toByteArray(); 356 } 357 358 359 360 361 362 public void print (PrintStream out) { 363 constantPool.print(out); 364 out.println(); 365 366 out.println("majorVersion = " + Integer.toString(majorVersion)); out.println("minorVersion = " + Integer.toString(minorVersion)); out.println("accessFlags = " + Integer.toString(accessFlags)); out.println("className = " + thisClassName.asString()); out.println("superClassName = " + superClassName.asString()); out.print("Interfaces ="); for (int i=0; i<classInterfaces.size(); i++) { 373 out.print(" " + ((ConstClass) classInterfaces.elementAt(i)).asString()); } 375 out.println(); 376 377 out.println("fields ="); for (int i=0; i<classFields.size(); i++) { 379 ((ClassField) classFields.elementAt(i)).print(out, 3); 380 } 381 382 out.println("methods ="); for (int i=0; i<classMethods.size(); i++) { 384 ((ClassMethod) classMethods.elementAt(i)).print(out, 3); 385 } 386 387 out.println("attributes ="); classAttributes.print(out, 3); 389 390 } 391 392 public void summarize () { 393 PrintStream os = System.out; 394 395 constantPool.summarize(); 396 int codeSize = 0; 397 for (int i=0; i<classMethods.size(); i++) { 398 codeSize += ((ClassMethod) classMethods.elementAt(i)).codeSize(); 399 } 400 System.out.println(classMethods.size() + " methods in " + codeSize + " bytes"); } 402 403 406 private void readConstants (DataInputStream data) throws IOException { 407 constantPool = new ConstantPool(data); 408 } 409 410 private void readInterfaces(DataInputStream data) throws IOException { 411 int nInterfaces = data.readUnsignedShort(); 412 while (nInterfaces-- > 0) { 413 int interfaceIndex = data.readUnsignedShort(); 414 ConstClass ci = null; 415 if (interfaceIndex != 0) 416 ci = (ConstClass) constantPool.constantAt(interfaceIndex); 417 classInterfaces.addElement(ci); 418 } 419 } 420 421 private void writeInterfaces(DataOutputStream data) throws IOException { 422 data.writeShort(classInterfaces.size()); 423 for (int i=0; i<classInterfaces.size(); i++) { 424 ConstClass ci = (ConstClass) classInterfaces.elementAt(i); 425 int interfaceIndex = 0; 426 if (ci != null) 427 interfaceIndex = ci.getIndex(); 428 data.writeShort(interfaceIndex); 429 } 430 } 431 432 private void readFields(DataInputStream data) throws IOException { 433 int nFields = data.readUnsignedShort(); 434 while (nFields-- > 0) { 435 classFields.addElement (ClassField.read(data, constantPool)); 436 } 437 } 438 439 private void writeFields (DataOutputStream data) throws IOException { 440 data.writeShort(classFields.size()); 441 for (int i=0; i<classFields.size(); i++) 442 ((ClassField)classFields.elementAt(i)).write(data); 443 } 444 445 private void readMethods (DataInputStream data) throws IOException { 446 int nMethods = data.readUnsignedShort(); 447 while (nMethods-- > 0) { 448 classMethods.addElement (ClassMethod.read(data, constantPool)); 449 } 450 } 451 452 private void writeMethods (DataOutputStream data) throws IOException { 453 data.writeShort(classMethods.size()); 454 for (int i=0; i<classMethods.size(); i++) 455 ((ClassMethod)classMethods.elementAt(i)).write(data); 456 } 457 458 459 private static List convertMajorMinorVersions(short[][] majorMinor) { 461 int length = majorMinor.length; 462 List result = new ArrayList (length); 463 for (int i = 0; i < length; i++) { 464 result.add(getVersionInt(majorMinor[i][0], majorMinor[i][1])); 465 } 466 return result; 467 } 468 469 private static boolean isSupportedVersion(short major, short minor) { 470 Integer version = getVersionInt(major, minor); 471 return jdkVersions.contains(version); 472 } 473 474 private static Integer getVersionInt(short major, short minor) { 475 return new Integer (major * 65536 + minor); 476 } 477 478 public static final String printSupportedVersions() { 479 StringBuffer buf = new StringBuffer ("{"); int length = jdkMajorMinorVersions.length; 481 for (int i = 0; i < length; i++) { 482 int major = jdkMajorMinorVersions[i][0]; 483 int minor = jdkMajorMinorVersions[i][1]; 484 buf.append("{"); buf.append(major); 486 buf.append(","); buf.append(minor); 488 buf.append("}"); } 490 buf.append("}"); return buf.toString(); 492 } 493 494 } 495 496 abstract class ArraySorter { 497 protected ArraySorter() {} 498 499 500 abstract int size(); 501 502 503 abstract int compare(int o1Index, int o2Index); 504 505 506 abstract void swap(int o1Index, int o2Index); 507 508 void sortArray() { 509 sortArray(0, size()-1); 510 } 511 512 private void sortArray(int start, int end) { 513 if (end > start) { 514 swap(start, (start+end)/2); 515 int last = start; 516 for (int i = start+1; i<=end; i++) { 517 if (compare(i, start) < 0) 518 swap (++last, i); 519 } 520 swap(start, last); 521 sortArray(start, last-1); 522 sortArray(last+1, end); 523 } 524 } 525 } 526 527 class InterfaceArraySorter extends ArraySorter { 528 private ConstClass theArray[]; 529 530 InterfaceArraySorter(ConstClass[] interfaces) { 531 theArray = interfaces; 532 } 533 534 535 int size() { return theArray.length; } 536 537 538 int compare(int o1Index, int o2Index) { 539 return theArray[o1Index].asString().compareTo( 540 theArray[o2Index].asString()); 541 } 542 543 544 void swap(int o1Index, int o2Index) { 545 ConstClass tmp = theArray[o1Index]; 546 theArray[o1Index] = theArray[o2Index]; 547 theArray[o2Index] = tmp; 548 } 549 } 550 551 class FieldArraySorter extends ArraySorter { 552 private ClassField theArray[]; 553 554 FieldArraySorter(ClassField[] fields) { 555 theArray = fields; 556 } 557 558 559 int size() { return theArray.length; } 560 561 562 int compare(int o1Index, int o2Index) { 563 return theArray[o1Index].name().asString().compareTo( 564 theArray[o2Index].name().asString()); 565 } 566 567 568 void swap(int o1Index, int o2Index) { 569 ClassField tmp = theArray[o1Index]; 570 theArray[o1Index] = theArray[o2Index]; 571 theArray[o2Index] = tmp; 572 } 573 } 574 575 class MethodArraySorter extends ArraySorter { 576 private ClassMethod theArray[]; 577 578 MethodArraySorter(ClassMethod[] methods) { 579 theArray = methods; 580 } 581 582 583 int size() { return theArray.length; } 584 585 586 int compare(int o1Index, int o2Index) { 587 int cmp = theArray[o1Index].name().asString().compareTo( 588 theArray[o2Index].name().asString()); 589 if (cmp == 0) { 590 cmp = theArray[o1Index].signature().asString().compareTo( 591 theArray[o2Index].signature().asString()); 592 } 593 return cmp; 594 } 595 596 597 void swap(int o1Index, int o2Index) { 598 ClassMethod tmp = theArray[o1Index]; 599 theArray[o1Index] = theArray[o2Index]; 600 theArray[o2Index] = tmp; 601 } 602 603 604 } 605 606 | Popular Tags |