1 21 22 package org.apache.derby.iapi.services.classfile; 23 24 25 import java.io.InputStream ; 26 import java.util.Enumeration ; 27 28 import java.io.IOException ; 29 import java.util.Vector ; 30 31 import org.apache.derby.iapi.services.classfile.VMDescriptor; 32 import org.apache.derby.iapi.services.classfile.VMDescriptor; 33 import java.util.HashSet ; 34 35 import java.util.Hashtable ; 36 import java.util.Vector ; 37 import java.util.Enumeration ; 38 import java.util.Collections ; 39 40 41 43 44 public class ClassInvestigator extends ClassHolder { 45 46 public static ClassInvestigator load(InputStream is) 47 throws IOException { 48 49 ClassInput classInput = new ClassInput(is); 50 51 checkHeader(classInput); 53 54 int constantPoolCount = classInput.getU2(); 56 57 ClassInvestigator ci = new ClassInvestigator(constantPoolCount); 58 for (int i = 1; i < constantPoolCount; ) { 61 ConstantPoolEntry item = ClassInvestigator.getConstant(classInput); 62 i += ci.addEntry(item.getKey(), item); 63 } 64 65 ci.access_flags = classInput.getU2(); 67 ci.this_class = classInput.getU2(); 68 ci.super_class = classInput.getU2(); 69 70 int interfaceCount = classInput.getU2(); 72 if (interfaceCount != 0) { 73 ci.interfaces = new int[interfaceCount]; 74 for (int i = 0; i < interfaceCount; i++) 75 ci.interfaces[i] = classInput.getU2(); 76 } 77 78 int fieldCount = classInput.getU2(); 79 if (fieldCount != 0) { 80 ci.field_info = new MemberTable(fieldCount); 81 for (int i = 0; i < fieldCount; i++) 82 { 83 ci.field_info.addEntry(readClassMember(ci, classInput)); 84 } 85 } 86 87 int methodCount = classInput.getU2(); 88 if (methodCount != 0) { 89 ci.method_info = new MemberTable(methodCount); 90 for (int i = 0; i < methodCount; i++) 91 { 92 ci.method_info.addEntry(readClassMember(ci, classInput)); 93 } 94 } 95 96 int attributeCount = classInput.getU2(); 97 if (attributeCount != 0) { 98 ci.attribute_info = new Attributes(attributeCount); 99 100 for (int i = 0; i < attributeCount; i++) 101 ci.attribute_info.addEntry(new AttributeEntry(classInput)); 102 } 103 return ci; 104 105 } 106 107 private static ClassMember readClassMember(ClassInvestigator ci, ClassInput in) 108 throws IOException { 109 110 ClassMember member = new ClassMember(ci, in.getU2(), in.getU2(), in.getU2()); 111 112 int attributeCount = in.getU2(); 113 if (attributeCount != 0) { 114 member.attribute_info = new Attributes(attributeCount); 115 for (int i = 0; i < attributeCount; i++) 116 member.attribute_info.addEntry(new AttributeEntry(in)); 117 } 118 119 return member; 120 } 121 122 125 126 private ClassInvestigator(int constantPoolCount) { 127 super(constantPoolCount); 128 } 129 130 133 134 135 public Enumeration implementedInterfaces() 136 { 137 int interfaceCount = interfaces == null ? 0 : interfaces.length; 138 Vector implemented = new Vector (interfaceCount); 139 140 for (int i = 0; i < interfaceCount; i++) 141 { 142 implemented.addElement(className(interfaces[i])); 143 } 144 return implemented.elements(); 145 } 146 public Enumeration getFields() { 147 if (field_info == null) 148 return Collections.enumeration(Collections.EMPTY_LIST); 149 150 return field_info.entries.elements(); 151 } 152 153 public Enumeration getMethods() { 154 if (method_info == null) 155 return Collections.enumeration(Collections.EMPTY_LIST); 156 return method_info.entries.elements(); 157 } 158 159 public Enumeration referencedClasses() { 160 return getClasses(getMethods(), getFields() ); 161 } 162 163 166 167 private Enumeration getClasses(Enumeration methods, Enumeration fields) 168 { 169 return new ClassEnumeration(this, cptEntries.elements(), methods, fields); 170 } 171 172 public Enumeration getStrings() { 173 HashSet strings = new HashSet (30, 0.8f); 174 175 int size = cptEntries.size(); 176 for (int i = 1; i < size; i++) { 177 ConstantPoolEntry cpe = getEntry(i); 178 179 if ((cpe == null) || (cpe.getTag() != VMDescriptor.CONSTANT_String)) 180 continue; 181 182 CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe; 183 184 strings.add(nameIndexToString(cii.getI1())); 185 } 186 187 return java.util.Collections.enumeration(strings); 188 } 189 190 public ClassMember getMember(String simpleName, String descriptor) { 191 192 if (descriptor.startsWith("(")) { 193 if (method_info == null) 194 return null; 195 return method_info.find(simpleName, descriptor); 196 } 197 else { 198 if (field_info == null) 199 return null; 200 return field_info.find(simpleName, descriptor); 201 } 202 } 203 204 207 212 213 216 public void removeAttributes() throws IOException { 218 219 if (attribute_info != null) { 221 for (int i = attribute_info.size() - 1; i >= 0 ; i--) { 222 223 AttributeEntry ae = (AttributeEntry) attribute_info.elementAt(i); 224 String name = nameIndexToString(ae.getNameIndex()); 225 if (name.equals("SourceFile")) 226 attribute_info.removeElementAt(i); 227 else if (name.equals("InnerClasses")) 228 ; else 230 System.err.println("WARNING - Unknown Class File attribute " + name); 231 } 232 233 if (attribute_info.size() == 0) 234 attribute_info = null; 235 } 236 attribute_info = null; 237 238 for (Enumeration e = getFields(); e.hasMoreElements(); ) { 240 ClassMember member = (ClassMember) e.nextElement(); 241 242 Attributes attrs = member.attribute_info; 243 244 if (attrs != null) { 245 246 for (int i = attrs.size() - 1; i >= 0 ; i--) { 247 248 AttributeEntry ae = (AttributeEntry) attrs.elementAt(i); 249 String name = nameIndexToString(ae.getNameIndex()); 250 if (name.equals("ConstantValue")) 251 ; else if (name.equals("Synthetic")) 253 ; else 255 System.err.println("WARNING - Unknown Field attribute " + name); 256 } 257 258 if (attrs.size() == 0) 259 member.attribute_info = null; 260 } 261 262 } 263 264 for (Enumeration e = getMethods(); e.hasMoreElements(); ) { 266 ClassMember member = (ClassMember) e.nextElement(); 267 268 Attributes attrs = member.attribute_info; 269 270 if (attrs != null) { 271 272 for (int i = attrs.size() - 1; i >= 0 ; i--) { 273 274 AttributeEntry ae = (AttributeEntry) attrs.elementAt(i); 275 String name = nameIndexToString(ae.getNameIndex()); 276 if (name.equals("Code")) 277 processCodeAttribute(member, ae); 278 else if (name.equals("Exceptions")) 279 ; else if (name.equals("Deprecated")) 281 ; else if (name.equals("Synthetic")) 283 ; else 285 System.err.println("WARNING - Unknown method attribute " + name); 286 } 287 288 if (attrs.size() == 0) 289 member.attribute_info = null; 290 } 291 292 } 293 } 294 295 private void processCodeAttribute(ClassMember member, AttributeEntry ae) throws IOException { 296 297 ClassInput ci = new ClassInput(new java.io.ByteArrayInputStream (ae.infoIn)); 298 299 300 ci.skipBytes(4); int len = ci.getU4(); 302 ci.skipBytes(len); int count = ci.getU2(); 304 if (count != 0) 305 ci.skipBytes(8 * count); 306 307 int nonAttrLength = 4 + 4 + len + 2 + (8 * count); 308 309 311 count = ci.getU2(); 312 if (count == 0) 313 return; 314 315 int newCount = count; 316 for (int i = 0; i < count; i++) { 317 318 int nameIndex = ci.getU2(); 319 String name = nameIndexToString(nameIndex); 320 if (name.equals("LineNumberTable") || name.equals("LocalVariableTable")) 321 newCount--; 322 else 323 System.err.println("ERROR - Unknown code attribute " + name); 324 325 len = ci.getU4(); 326 ci.skipBytes(len); 327 } 328 329 if (newCount != 0) { 330 System.err.println("ERROR - expecting all code attributes to be removed"); 331 System.exit(1); 332 } 333 334 336 byte[] newInfo = new byte[nonAttrLength + 2]; 337 System.arraycopy(ae.infoIn, 0, newInfo, 0, nonAttrLength); 338 ae.infoIn = newInfo; 340 } 341 342 public void renameClassElements(Hashtable classNameMap, Hashtable memberNameMap) { 343 344 renameString(classNameMap, (CONSTANT_Index_info) getEntry(this_class)); 346 renameString(classNameMap, (CONSTANT_Index_info) getEntry(super_class)); 347 348 351 int size = cptEntries.size(); 354 for (int i = 1; i < size; i++) { 355 ConstantPoolEntry cpe = getEntry(i); 356 357 if (cpe == null) 358 continue; 359 360 switch (cpe.getTag()) { 361 case VMDescriptor.CONSTANT_String: 362 case VMDescriptor.CONSTANT_Class: 363 { 364 CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe; 365 renameString(classNameMap, cii); 366 break; 367 } 368 case VMDescriptor.CONSTANT_NameAndType: 369 { 370 CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe; 371 String newDescriptor = newDescriptor(classNameMap, nameIndexToString(cii.getI2())); 372 if (newDescriptor != null) { 373 doRenameString(cii.getI2(), newDescriptor); 374 } 375 break; 376 } 377 378 default: 379 continue; 380 } 381 382 } 383 384 386 renameMembers(getFields(), classNameMap, memberNameMap); 388 389 renameMembers(getMethods(), classNameMap, memberNameMap); 390 } 391 392 private void renameMembers(Enumeration e, Hashtable classNameMap, Hashtable memberNameMap) { 393 394 for (; e.hasMoreElements(); ) { 395 ClassMember member = (ClassMember) e.nextElement(); 396 397 String oldMemberName = nameIndexToString(member.name_index); 398 String newMemberName = (String ) memberNameMap.get(oldMemberName); 399 if (newMemberName != null) 400 doRenameString(member.name_index, newMemberName); 401 402 String newDescriptor = newDescriptor(classNameMap, nameIndexToString(member.descriptor_index)); 403 if (newDescriptor != null) { 404 doRenameString(member.descriptor_index, newDescriptor); 405 } 406 } 407 408 } 409 410 private void renameString(Hashtable classNameMap, CONSTANT_Index_info cii) { 411 412 int index = cii.getI1(); 413 414 String name = nameIndexToString(index); 415 String newName = (String ) classNameMap.get(name); 416 if (newName != null) { 417 418 doRenameString(index, newName); 419 420 return; 421 } 422 423 if (cii.getTag() == VMDescriptor.CONSTANT_Class) { 425 426 if (name.charAt(0) == '[') { 427 int classOffset = name.indexOf('L') + 1; 428 429 String baseClassName = name.substring(classOffset, name.length() - 1); 430 431 432 newName = (String ) classNameMap.get(baseClassName); 433 434 if (newName != null) { 435 436 String newArrayClassName = name.substring(0, classOffset) + newName + ";"; 437 438 doRenameString(index, newArrayClassName); 439 440 } 441 442 } 443 } 444 } 445 446 private void doRenameString(int index, String newName) { 447 ConstantPoolEntry cpe = getEntry(index); 448 if (cpe.getTag() != VMDescriptor.CONSTANT_Utf8) 449 throw new RuntimeException ("unexpected type " + cpe); 450 451 CONSTANT_Utf8_info newCpe = new CONSTANT_Utf8_info(newName); 452 453 cptHashTable.remove(cpe.getKey()); 454 cptHashTable.put(cpe.getKey(), cpe); 455 456 newCpe.index = index; 457 458 cptEntries.setElementAt(newCpe, index); 459 } 460 461 464 static private void checkHeader(ClassInput in) throws IOException { 465 int magic = in.getU4(); 466 int minor_version = in.getU2(); 467 int major_version = in.getU2(); 468 469 470 if (magic != VMDescriptor.JAVA_CLASS_FORMAT_MAGIC) 471 throw new ClassFormatError (); 472 } 473 private static ConstantPoolEntry getConstant(ClassInput in) 474 throws IOException { 475 476 ConstantPoolEntry item; 477 int tag; 478 tag = in.readUnsignedByte(); 479 480 switch (tag) { 481 case VMDescriptor.CONSTANT_Class: 482 case VMDescriptor.CONSTANT_String: 483 item = new CONSTANT_Index_info(tag, in.getU2(), 0); 484 break; 485 486 case VMDescriptor.CONSTANT_NameAndType: 487 case VMDescriptor.CONSTANT_Fieldref: 488 case VMDescriptor.CONSTANT_Methodref: 489 case VMDescriptor.CONSTANT_InterfaceMethodref: 490 item = new CONSTANT_Index_info(tag, in.getU2(), in.getU2()); 491 break; 492 493 case VMDescriptor.CONSTANT_Integer: 494 item = new CONSTANT_Integer_info(in.getU4()); 495 break; 496 497 case VMDescriptor.CONSTANT_Float: 498 item = new CONSTANT_Float_info(in.readFloat()); 499 break; 500 501 case VMDescriptor.CONSTANT_Long: 502 item = new CONSTANT_Long_info(in.readLong()); 503 break; 504 505 case VMDescriptor.CONSTANT_Double: 506 item = new CONSTANT_Double_info(in.readDouble()); 507 break; 508 509 case VMDescriptor.CONSTANT_Utf8: 510 item = new CONSTANT_Utf8_info(in.readUTF()); 511 break; 512 default: 513 throw new ClassFormatError (); 514 } 515 516 return item; 517 } 518 public static String newDescriptor(Hashtable classNameMap, String descriptor) { 519 520 String newDescriptor = null; 521 522 int dlen = descriptor.length(); 523 for (int offset = 0; offset < dlen; ) { 524 char c = descriptor.charAt(offset); 525 switch (c) { 526 case VMDescriptor.C_VOID : 527 case VMDescriptor.C_BOOLEAN: 528 case VMDescriptor.C_BYTE: 529 case VMDescriptor.C_CHAR: 530 case VMDescriptor.C_SHORT: 531 case VMDescriptor.C_INT: 532 case VMDescriptor.C_LONG: 533 case VMDescriptor.C_FLOAT: 534 case VMDescriptor.C_DOUBLE: 535 case VMDescriptor.C_ARRAY: 536 case VMDescriptor.C_METHOD: 537 case VMDescriptor.C_ENDMETHOD: 538 default: 539 offset++; 540 continue; 541 542 case VMDescriptor.C_CLASS: 543 { 544 int startOffset = offset; 545 while (descriptor.charAt(offset++) != VMDescriptor.C_ENDCLASS) 546 ; 547 int endOffset = offset; 548 549 String name = descriptor.substring(startOffset, endOffset); 551 String newName = (String ) classNameMap.get(name); 552 if (newName != null) { 553 if (newDescriptor == null) 554 newDescriptor = descriptor; 555 556 int startPos = newDescriptor.indexOf(name); 559 560 String tmp; 561 if (startPos == 0) 562 tmp = newName; 563 else 564 tmp = newDescriptor.substring(0, startPos) + 565 newName; 566 567 int endPos = startPos + name.length(); 568 569 if (endPos < newDescriptor.length()) { 570 571 tmp += newDescriptor.substring(endPos , newDescriptor.length()); 572 } 573 574 575 newDescriptor = tmp; 576 } 577 } 578 } 579 580 581 } 582 return newDescriptor; 587 } 588 } 589 | Popular Tags |