1 29 30 package com.caucho.bytecode; 31 32 import com.caucho.log.Log; 33 import com.caucho.util.CharBuffer; 34 import com.caucho.util.L10N; 35 36 import java.util.logging.Level ; 37 import java.util.logging.Logger ; 38 39 42 public class ByteCodeClassScanner { 43 static private final Logger log = Log.open(ByteCodeClassScanner.class); 44 static private final L10N L = new L10N(ByteCodeClassScanner.class); 45 46 private final String _className; 47 48 private final byte []_buffer; 49 private final int _length; 50 51 private final ByteCodeClassMatcher _matcher; 52 53 private int []_cpOffset = new int[256]; 54 private int _index; 55 56 private CharBuffer _cb = new CharBuffer(); 57 58 public ByteCodeClassScanner(String className, 59 byte []buffer, int offset, int length, 60 ByteCodeClassMatcher matcher) 61 { 62 _className = className; 63 64 _buffer = buffer; 65 _index = offset; 66 _length = length; 67 68 _matcher = matcher; 69 } 70 71 public boolean scan() 72 { 73 try { 74 int magic = readInt(); 75 76 if (magic != JavaClass.MAGIC) 77 throw error(L.l("bad magic number in class file")); 78 79 int minor = readShort(); 80 int major = readShort(); 81 82 parseConstantPool(); 83 84 int accessFlags = readShort(); 85 int thisClassIndex = readShort(); 86 87 String thisName = parseClass(thisClassIndex).toString(); 88 89 if (_matcher.isClassMatch(thisName)) 90 return true; 91 92 int superClassIndex = readShort(); 93 94 int interfaceCount = readShort(); 95 for (int i = 0; i < interfaceCount; i++) { 96 int classIndex = readShort(); 97 } 98 99 int fieldCount = readShort(); 100 for (int i = 0; i < fieldCount; i++) { 101 if (parseField()) 102 return true; 103 } 104 105 int methodCount = readShort(); 106 for (int i = 0; i < methodCount; i++) { 107 if (parseMethod()) 108 return true; 109 } 110 111 int attrCount = readShort(); 112 for (int i = 0; i < attrCount; i++) { 113 if (parseAttribute()) 114 return true; 115 } 116 117 return false; 118 } catch (Exception e) { 119 log.warning("failed scanning class " + _className); 120 log.log(Level.WARNING, e.toString(), e); 121 122 return false; 123 } 124 } 125 126 129 public boolean parseConstantPool() 130 { 131 int count = readShort(); 132 133 int i = 1; 134 while (i < count) { 135 int code = read(); 136 137 parseConstantPoolEntry(code, i); 138 139 if (code == ByteCodeParser.CP_LONG || code == ByteCodeParser.CP_DOUBLE) 140 i += 2; 141 else 142 i += 1; 143 } 144 145 165 166 return false; 167 } 168 169 172 private boolean parseConstantPoolEntry(int tag, int i) 173 { 174 switch (tag) { 175 case ByteCodeParser.CP_CLASS: 176 { 177 if (_cpOffset.length <= i) { 178 int []offset = new int[2 * i]; 179 System.arraycopy(_cpOffset, 0, offset, 0, _cpOffset.length); 180 _cpOffset = offset; 181 } 182 183 _cpOffset[i] = _index - 1; 184 185 _index += 2; 186 187 return false; 188 } 189 190 case ByteCodeParser.CP_FIELD_REF: 191 { 192 195 _index += 4; 196 197 return false; 198 } 199 200 case ByteCodeParser.CP_METHOD_REF: 201 { 202 205 _index += 4; 206 207 return false; 208 } 209 210 case ByteCodeParser.CP_INTERFACE_METHOD_REF: 211 { 212 215 _index += 4; 216 217 return false; 218 } 219 220 case ByteCodeParser.CP_STRING: 221 { 222 224 _index += 2; 225 226 return false; 227 } 228 229 case ByteCodeParser.CP_INTEGER: 230 { 231 _index += 4; 232 233 return false; 234 } 235 236 case ByteCodeParser.CP_FLOAT: 237 { 238 _index += 4; 239 240 return false; 241 } 242 243 case ByteCodeParser.CP_LONG: 244 { 245 _index += 8; 246 247 return false; 248 } 249 250 case ByteCodeParser.CP_DOUBLE: 251 { 252 _index += 8; 253 254 return false; 255 } 256 257 case ByteCodeParser.CP_NAME_AND_TYPE: 258 { 259 262 _index += 4; 263 264 return false; 265 } 266 267 case ByteCodeParser.CP_UTF8: 268 { 269 if (_cpOffset.length <= i) { 270 int []offset = new int[2 * i + 1]; 271 System.arraycopy(_cpOffset, 0, offset, 0, _cpOffset.length); 272 _cpOffset = offset; 273 } 274 275 _cpOffset[i] = _index - 1; 276 277 int length = readShort(); 278 279 _index += length; 280 281 return false; 282 } 283 284 default: 285 throw error(L.l("'{0}' is an unknown constant pool type.", 286 tag)); 287 } 288 } 289 290 293 private boolean parseField() 294 { 295 int accessFlags = readShort(); 296 int nameIndex = readShort(); 297 int descriptorIndex = readShort(); 298 299 int attributesCount = readShort(); 300 301 for (int i = 0; i < attributesCount; i++) { 302 if (parseAttribute()) 303 return true; 304 } 305 306 return false; 307 } 308 309 312 private boolean parseMethod() 313 { 314 int accessFlags = readShort(); 315 int nameIndex = readShort(); 316 int descriptorIndex = readShort(); 317 318 int attributesCount = readShort(); 319 for (int i = 0; i < attributesCount; i++) { 320 if (parseAttribute()) 321 return true; 322 } 323 324 return false; 325 } 326 327 330 boolean parseAttribute() 331 { 332 int nameIndex = readShort(); 333 334 int length = readInt(); 335 int start = _index; 336 337 CharBuffer name = parseUTF8(nameIndex, 0); 338 339 if (name != null && name.matches("RuntimeVisibleAnnotations")) { 340 int n = readShort(); 341 342 for (int i = 0; i < n; i++) { 343 if (parseAttributeImpl()) 344 return true; 345 } 346 } 347 348 _index = start + length; 349 350 return false; 351 352 366 367 } 368 369 372 private boolean parseAttributeImpl() 373 { 374 int type = readShort(); 375 376 CharBuffer name = name = parseUTF8(type, 1); 377 name.setLength(name.length() - 1); 378 379 if (_matcher.isMatch(name)) 380 return true; 381 382 int nPairs = readShort(); 383 for (int j = 0; j < nPairs; j++) { 384 int valueName = readShort(); 385 386 parseElementValue(); 387 } 388 389 return false; 390 } 391 392 private void parseElementValue() 393 { 394 int tag = read(); 395 396 switch (tag) { 397 case 's': 398 _index += 2; 399 break; 400 case 'e': 401 _index += 4; 402 break; 403 case 'c': 404 _index += 2; 405 break; 406 case 'Z': 407 case 'B': 408 case 'S': 409 case 'I': 410 case 'J': 411 case 'C': 412 case 'F': 413 case 'D': 414 _index += 2; 415 break; 416 case '@': 417 parseAttributeImpl(); 419 break; 420 case '[': 421 { 422 int n = readShort(); 423 for (int i = 0; i < n; i++) 424 parseElementValue(); 425 } 426 break; 427 default: 428 System.out.println("UNKNOWN: " + (char) tag); 429 throw new IllegalStateException (); 430 } 431 } 432 433 436 private CharBuffer parseClass(int index) 437 { 438 int offset = _cpOffset[index] + 1; 439 440 return parseUTF8((_buffer[offset] & 0xff) * 256 + 441 (_buffer[offset + 1] & 0xff), 442 0); 443 } 444 445 448 private CharBuffer parseUTF8(int index, int skip) 449 { 450 int offset = _cpOffset[index] + 1; 451 452 byte []bBuf = _buffer; 453 454 int len = ((bBuf[offset] & 0xff) << 8) + (bBuf[offset + 1] & 0xff); 455 456 _cb.ensureCapacity(len); 457 458 offset += 2; 459 int end = offset + len; 460 461 char []cBuf = _cb.getBuffer(); 462 int cLen = -skip; 463 464 while (offset < end) { 465 int d1 = bBuf[offset] & 0xff; 466 467 if (d1 < 0x80) { 468 if (d1 == '/') 469 d1 = '.'; 470 471 if (cLen < 0) 472 cLen++; 473 else 474 cBuf[cLen++] = (char) d1; 475 476 offset++; 477 } 478 else if (d1 < 0xe0) { 479 int d2 = bBuf[offset + 1] & 0x3f; 480 481 if (cLen < 0) 482 cLen++; 483 else 484 cBuf[cLen++] = (char) (((d1 & 0x1f) << 6) + 485 ((d2))); 486 487 offset += 2; 488 } 489 else if (d1 < 0xf0) { 490 int d2 = bBuf[offset + 1] & 0x3f; 491 int d3 = bBuf[offset + 1] & 0x3f; 492 493 if (cLen < 0) 494 cLen++; 495 else 496 cBuf[cLen++] = (char) (((d1 & 0xf) << 12) + 497 ((d2 << 6)) + 498 ((d3))); 499 500 offset += 2; 501 } 502 else 503 throw new IllegalStateException (); 504 } 505 506 _cb.setLength(cLen); 507 508 return _cb; 509 } 510 511 514 private long readLong() 515 { 516 return (((long) read() << 56) | 517 ((long) read() << 48) | 518 ((long) read() << 40) | 519 ((long) read() << 32) | 520 ((long) read() << 24) | 521 ((long) read() << 16) | 522 ((long) read() << 8) | 523 ((long) read())); 524 } 525 526 529 private int readInt() 530 { 531 return ((read() << 24) | 532 (read() << 16) | 533 (read() << 8) | 534 (read())); 535 } 536 537 540 private int readShort() 541 { 542 int c1 = read(); 543 int c2 = read(); 544 545 return ((c1 << 8) | c2); 546 } 547 548 551 private int read() 552 { 553 if (_index < _length) 554 return _buffer[_index++] & 0xff; 555 else 556 return -1; 557 } 558 559 562 private IllegalStateException error(String message) 563 { 564 return new IllegalStateException (message); 565 } 566 } 567 | Popular Tags |