1 9 package com.vladium.jcd.lib; 10 11 import java.io.IOException ; 12 import java.lang.reflect.*; 13 14 import com.vladium.jcd.cls.IAccessFlags; 15 16 24 public abstract class Types 25 { 26 28 32 public static String getClassPackageName (final Class c) 33 { 34 36 final String className = c.getName (); 37 final int lastDot = className.lastIndexOf ('.'); 38 return lastDot >= 0 ? className.substring (0, lastDot) : ""; 39 } 40 41 42 public static String accessFlagsToString (final int flags, final boolean isClass) 43 { 44 final StringBuffer result = new StringBuffer (); 45 46 boolean first = true; 47 48 if (isClass) 49 { 50 for (int f = 0; f < IAccessFlags.ALL_ACC.length; ++ f) 51 { 52 final int bit = IAccessFlags.ALL_ACC [f]; 53 54 if ((flags & bit) != 0) 55 { 56 if (first) 57 first = false; 58 else 59 result.append (" "); 60 61 if (bit == IAccessFlags.ACC_SUPER) 62 result.append ("super"); 63 else 64 result.append (IAccessFlags.ALL_ACC_NAMES [f]); 65 } 66 } 67 } 68 else 69 { 70 for (int f = 0; f < IAccessFlags.ALL_ACC.length; ++ f) 71 { 72 final int bit = IAccessFlags.ALL_ACC [f]; 73 74 if ((flags & bit) != 0) 75 { 76 if (first) 77 first = false; 78 else 79 result.append (" "); 80 81 result.append (IAccessFlags.ALL_ACC_NAMES [f]); 82 } 83 } 84 } 85 86 return result.toString (); 87 } 88 89 90 99 public static String javaNameToVMName (final String javaName) 100 { 101 if (javaName == null) return null; 102 return javaName.replace ('.', '/'); 103 } 104 105 106 115 public static String vmNameToJavaName (final String vmName) 116 { 117 if (vmName == null) return null; 118 return vmName.replace ('/', '.'); 119 } 120 121 122 133 public static String signatureToDescriptor (Method method) 134 { 135 if (method == null) throw new IllegalArgumentException ("null input: method"); 136 return signatureToDescriptor (method.getParameterTypes (), method.getReturnType ()); 137 } 138 139 140 144 public static String signatureToDescriptor (Class [] parameterTypes, Class returnType) 145 { 146 return new signatureCompiler ().signatureDescriptor (parameterTypes, returnType); 147 } 148 149 150 161 public static String typeToDescriptor (Class type) 162 { 163 return new signatureCompiler ().typeDescriptor (type); 164 } 165 166 167 178 public static Class descriptorToType (String typedescriptor) throws ClassNotFoundException 179 { 180 return new typeDescriptorCompiler ().descriptorToClass (typedescriptor); 181 } 182 183 184 185 public static String descriptorToReturnType (String methoddescriptor) 186 { 187 final int i1 = methoddescriptor.indexOf ('('); 188 final int i2 = methoddescriptor.lastIndexOf (')'); 189 190 if ((i1 < 0) || (i2 <= 0) || (i1 >= i2) || (i2 >= methoddescriptor.length () - 1)) 191 throw new IllegalArgumentException ("malformed method descriptor: [" + methoddescriptor + "]"); 192 193 return methoddescriptor.substring (i2 + 1); 194 } 195 196 197 public static String [] descriptorToParameterTypes (String methoddescriptor) 198 { 199 201 try 202 { 203 final methodDescriptorCompiler compiler = new methodDescriptorCompiler (methoddescriptor); 204 compiler.methodDescriptor (); 205 return compiler.getResult (); 206 } 207 catch (IOException e) 208 { 209 throw new IllegalArgumentException ("error parsing [" + methoddescriptor + "]: " + e.toString ()); 210 } 211 212 314 } 315 316 317 public static String signatureToMethodDescriptor (final String [] parameterTypeDescriptors, final String returnTypeDescriptor) 318 { 319 final StringBuffer result = new StringBuffer ("("); 320 321 for (int p = 0; p < parameterTypeDescriptors.length; p++) 322 { 323 result.append (parameterTypeDescriptors [p]); 324 } 325 326 result.append (')'); 327 result.append (returnTypeDescriptor); 328 329 return result.toString (); 330 } 331 332 333 public static String typeDescriptorToUserName (final String typedescriptor) 334 { 335 return new typeDescriptorCompiler2 ().descriptorToClass (typedescriptor); 336 } 337 338 public static String methodDescriptorToUserName (final String methoddescriptor) 339 { 340 final String [] parameterTypes = descriptorToParameterTypes (methoddescriptor); 341 342 final StringBuffer result = new StringBuffer ("("); 343 344 for (int p = 0; p < parameterTypes.length; p++) 345 { 346 348 if (p > 0) result.append (", "); 349 350 final String typeUserName = typeDescriptorToUserName (parameterTypes [p]); 351 int lastDot = typeUserName.lastIndexOf ('.'); 352 353 if ((lastDot < 0) || ! "java.lang.".equals (typeUserName.substring (0, lastDot + 1))) 354 result.append (typeUserName); 355 else 356 result.append (typeUserName.substring (lastDot + 1)); 357 } 358 359 result.append (')'); 360 return result.toString (); 361 } 362 363 public static String fullMethodDescriptorToUserName (final String classJavaName, String methodName, final String methoddescriptor) 364 { 365 if ("<init>".equals (methodName)) 366 methodName = simpleClassName (classJavaName); 367 if ("<clinit>".equals (methodName)) 368 methodName = "<static class initializer>"; 369 370 return methodName + ' ' + methodDescriptorToUserName (methoddescriptor); 371 } 372 373 public static String fullMethodDescriptorToFullUserName (final String classJavaName, String methodName, final String methoddescriptor) 375 { 376 if ("<init>".equals (methodName)) 377 methodName = simpleClassName (classJavaName); 378 if ("<clinit>".equals (methodName)) 379 methodName = "<static class initializer>"; 380 381 return classJavaName + '.' + methodName + ' ' + methodDescriptorToUserName (methoddescriptor); 382 } 383 384 386 388 390 391 private static String simpleClassName (final String classJavaName) 392 { 393 int lastDot = classJavaName.lastIndexOf ('.'); 394 395 if (lastDot < 0) 396 return classJavaName; 397 else 398 return classJavaName.substring (lastDot + 1); 399 } 400 401 402 403 private static final class signatureCompiler 404 { 405 String signatureDescriptor (Class [] _parameterTypes, Class _returnType) 406 { 407 emit ('('); parameterTypes (_parameterTypes); emit (')'); returnType (_returnType); 408 409 return m_desc.toString (); 410 } 411 412 String typeDescriptor (Class type) 413 { 414 parameterType (type); 415 416 return m_desc.toString (); 417 } 418 419 420 private void parameterTypes (Class [] _parameterTypes) 421 { 422 if (_parameterTypes != null) 423 { 424 for (int p = 0; p < _parameterTypes.length; p++) 425 { 426 parameterType (_parameterTypes [p]); 427 } 428 } 429 } 430 431 432 private void returnType (Class _returnType) 433 { 434 if ((_returnType == null) || (_returnType == Void.TYPE)) 435 emit ('V'); 436 else 437 parameterType (_returnType); 438 } 439 440 441 private void parameterType (Class _parameterType) 442 { 443 if (_parameterType != null) 444 { 445 if (_parameterType.isPrimitive ()) { 447 if (byte.class == _parameterType) emit ('B'); 448 else if (char.class == _parameterType) emit ('C'); 449 else if (double.class == _parameterType) emit ('D'); 450 else if (float.class == _parameterType) emit ('F'); 451 else if (int.class == _parameterType) emit ('I'); 452 else if (long.class == _parameterType) emit ('J'); 453 else if (short.class == _parameterType) emit ('S'); 454 else if (boolean.class == _parameterType) emit ('Z'); 455 } 456 else if (_parameterType.isArray ()) { 458 emit ('['); parameterType (_parameterType.getComponentType ()); 459 } 460 else { 462 emit ('L'); emit (javaNameToVMName (_parameterType.getName ())); emit (';'); 463 } 464 } 465 } 466 467 468 private void emit (String s) 469 { 470 m_desc.append (s); 471 } 472 473 private void emit (char c) 474 { 475 m_desc.append (c); 476 } 477 478 479 private StringBuffer m_desc = new StringBuffer (); 480 481 } 483 484 485 private static class typeDescriptorCompiler 486 { 487 494 495 Class descriptorToClass (String typedescriptor) throws ClassNotFoundException 496 { 497 char first = typedescriptor.charAt (0); 498 499 if (first == '[') 500 return arrayOf (typedescriptor.substring (1)); 502 else if (first == 'L') 503 return Class.forName (vmNameToJavaName (typedescriptor.substring (1, typedescriptor.length() - 1))); 505 else { 507 return primitive (first); 508 } 509 } 510 511 512 Class arrayOf (String typedescriptor) throws ClassNotFoundException 513 { 514 char first = typedescriptor.charAt (0); 515 Class component; 516 517 if (first == '[') 518 component = arrayOf (typedescriptor.substring (1)); 520 else if (first == 'L') 521 component = Class.forName (vmNameToJavaName (typedescriptor.substring (1, typedescriptor.length() - 1))); 523 else { 525 component = primitive (first); 526 } 527 528 Object array = Array.newInstance (component, 0); 529 return array.getClass (); 530 } 531 532 533 Class primitive (char c) throws ClassNotFoundException 534 { 535 if (c == 'B') return byte.class; 536 else if (c == 'C') return char.class; 537 else if (c == 'D') return double.class; 538 else if (c == 'F') return float.class; 539 else if (c == 'I') return int.class; 540 else if (c == 'J') return long.class; 541 else if (c == 'S') return short.class; 542 else if (c == 'Z') return boolean.class; 543 else throw new ClassNotFoundException ("unknown base type: " + c); 544 } 545 546 } 548 549 private static class typeDescriptorCompiler2 550 { 551 String descriptorToClass (String typedescriptor) 552 { 553 555 char first = typedescriptor.charAt (0); 556 557 if (first == '[') 558 return arrayOf (typedescriptor.substring (1)); 560 else if (first == 'L') 561 return vmNameToJavaName (typedescriptor.substring (1, typedescriptor.length() - 1)); 563 else return primitive (first); 565 } 566 567 568 String arrayOf (String typedescriptor) 569 { 570 572 char first = typedescriptor.charAt (0); 573 String component; 574 575 if (first == '[') 576 component = arrayOf (typedescriptor.substring (1)); 578 else if (first == 'L') 579 component = vmNameToJavaName (typedescriptor.substring (1, typedescriptor.length() - 1)); 581 else component = primitive (first); 583 584 String array = component + " []"; 585 return array; 586 } 587 588 589 String primitive (char c) 590 { 591 switch (c) 592 { 593 case 'B': return "byte"; 594 case 'C': return "char"; 595 case 'D': return "double"; 596 case 'F': return "float"; 597 case 'I': return "int"; 598 case 'J': return "long"; 599 case 'S': return "short"; 600 case 'Z': return "boolean"; 601 default: 602 throw new IllegalArgumentException ("unknown primitive: " + c); 603 } 604 } 605 606 } 608 609 private static class methodDescriptorCompiler 610 { 611 methodDescriptorCompiler (String methoddescriptor) 612 { 613 m_in = new java.io.PushbackReader (new java.io.StringReader (methoddescriptor)); 614 } 615 616 String [] getResult () 617 { 618 final String [] result = new String [m_result.size ()]; 619 m_result.toArray (result); 620 621 return result; 622 } 623 624 void methodDescriptor () throws IOException 625 { 626 consume ('('); 627 628 char c; 629 while ((c = (char) m_in.read ()) != ')') 630 { 631 m_in.unread (c); 632 parameterDescriptor (); 633 } 634 returnDescriptor (); 635 } 636 637 void parameterDescriptor () throws IOException 638 { 639 fieldType (); 640 newToken (); 641 } 642 643 void returnDescriptor () throws IOException 644 { 645 char c = (char) m_in.read (); 646 647 switch (c) 648 { 649 case 'V': 650 m_token.append (c); 651 break; 652 653 default: 654 m_in.unread (c); 655 fieldType (); 656 657 } 658 } 660 661 void componentType () throws IOException 662 { 663 fieldType (); 664 } 665 666 void objectType () throws IOException 667 { 668 consume ('L'); 669 m_token.append ('L'); 670 671 char c; 672 while ((c = (char) m_in.read ()) != ';') 673 { 674 m_token.append (c); 675 } 676 m_token.append (';'); 677 } 678 679 void arrayType () throws IOException 680 { 681 consume ('['); 682 m_token.append ('['); 683 684 componentType (); 685 } 686 687 void fieldType () throws IOException 688 { 689 char c = (char) m_in.read (); 690 m_in.unread (c); 691 692 switch (c) 693 { 694 case 'L': 695 objectType (); 696 break; 697 698 case '[': 699 arrayType (); 700 break; 701 702 default: 703 baseType (); 704 break; 705 } 706 } 707 708 709 void baseType () throws IOException 710 { 711 char c = (char) m_in.read (); 712 713 switch (c) 714 { 715 case 'B': 716 case 'C': 717 case 'D': 718 case 'F': 719 case 'I': 720 case 'J': 721 case 'S': 722 case 'Z': 723 m_token.append (c); 724 break; 725 726 default: 727 throw new IllegalArgumentException ("unknown base type: " + c); 728 } 729 } 730 731 732 private void consume (char expected) throws IOException 733 { 734 char c = (char) m_in.read (); 735 736 if (c != expected) 737 throw new IllegalArgumentException ("consumed '" + c + "' while expecting '" + expected + "'"); 738 } 739 740 741 742 private void newToken () 743 { 744 746 m_result.add (m_token.toString ()); 747 m_token.setLength (0); 748 } 749 750 final java.util.List m_result = new java.util.ArrayList (); 751 private StringBuffer m_token = new StringBuffer (); 752 private java.io.PushbackReader m_in; 753 } 755 } | Popular Tags |