1 17 package org.apache.bcel.classfile; 18 19 import java.io.ByteArrayInputStream ; 20 import java.io.ByteArrayOutputStream ; 21 import java.io.CharArrayReader ; 22 import java.io.CharArrayWriter ; 23 import java.io.FilterReader ; 24 import java.io.FilterWriter ; 25 import java.io.IOException ; 26 import java.io.PrintStream ; 27 import java.io.PrintWriter ; 28 import java.io.Reader ; 29 import java.io.Writer ; 30 import java.util.ArrayList ; 31 import java.util.List ; 32 import java.util.Locale ; 33 import java.util.zip.GZIPInputStream ; 34 import java.util.zip.GZIPOutputStream ; 35 import org.apache.bcel.Constants; 36 import org.apache.bcel.util.ByteSequence; 37 38 44 public abstract class Utility { 45 46 private static int unwrap( ThreadLocal tl ) { 47 return ((Integer ) tl.get()).intValue(); 48 } 49 50 51 private static void wrap( ThreadLocal tl, int value ) { 52 tl.set(new Integer (value)); 53 } 54 55 private static ThreadLocal consumed_chars = new ThreadLocal () { 56 57 protected Object initialValue() { 58 return new Integer (0); 59 } 60 }; 65 private static boolean wide = false; 74 75 76 82 public static final String accessToString( int access_flags ) { 83 return accessToString(access_flags, false); 84 } 85 86 87 99 public static final String accessToString( int access_flags, boolean for_class ) { 100 StringBuffer buf = new StringBuffer (); 101 int p = 0; 102 for (int i = 0; p < Constants.MAX_ACC_FLAG; i++) { p = pow2(i); 104 if ((access_flags & p) != 0) { 105 110 if (for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE))) { 111 continue; 112 } 113 buf.append(Constants.ACCESS_NAMES[i]).append(" "); 114 } 115 } 116 return buf.toString().trim(); 117 } 118 119 120 123 public static final String classOrInterface( int access_flags ) { 124 return ((access_flags & Constants.ACC_INTERFACE) != 0) ? "interface" : "class"; 125 } 126 127 128 142 public static final String codeToString( byte[] code, ConstantPool constant_pool, int index, 143 int length, boolean verbose ) { 144 StringBuffer buf = new StringBuffer (code.length * 20); ByteSequence stream = new ByteSequence(code); 146 try { 147 for (int i = 0; i < index; i++) { 148 codeToString(stream, constant_pool, verbose); 149 } 150 for (int i = 0; stream.available() > 0; i++) { 151 if ((length < 0) || (i < length)) { 152 String indices = fillup(stream.getIndex() + ":", 6, true, ' '); 153 buf.append(indices).append(codeToString(stream, constant_pool, verbose)) 154 .append('\n'); 155 } 156 } 157 } catch (IOException e) { 158 System.out.println(buf.toString()); 159 e.printStackTrace(); 160 throw new ClassFormatException("Byte code error: " + e); 161 } 162 return buf.toString(); 163 } 164 165 166 public static final String codeToString( byte[] code, ConstantPool constant_pool, int index, 167 int length ) { 168 return codeToString(code, constant_pool, index, length, true); 169 } 170 171 172 181 public static final String codeToString( ByteSequence bytes, ConstantPool constant_pool, 182 boolean verbose ) throws IOException { 183 short opcode = (short) bytes.readUnsignedByte(); 184 int default_offset = 0, low, high, npairs; 185 int index, vindex, constant; 186 int[] match, jump_table; 187 int no_pad_bytes = 0, offset; 188 StringBuffer buf = new StringBuffer (Constants.OPCODE_NAMES[opcode]); 189 192 if ((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) { 193 int remainder = bytes.getIndex() % 4; 194 no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder; 195 for (int i = 0; i < no_pad_bytes; i++) { 196 byte b; 197 if ((b = bytes.readByte()) != 0) { 198 System.err.println("Warning: Padding byte != 0 in " 199 + Constants.OPCODE_NAMES[opcode] + ":" + b); 200 } 201 } 202 default_offset = bytes.readInt(); 204 } 205 switch (opcode) { 206 208 case Constants.TABLESWITCH: 209 low = bytes.readInt(); 210 high = bytes.readInt(); 211 offset = bytes.getIndex() - 12 - no_pad_bytes - 1; 212 default_offset += offset; 213 buf.append("\tdefault = ").append(default_offset).append(", low = ").append(low) 214 .append(", high = ").append(high).append("("); 215 jump_table = new int[high - low + 1]; 216 for (int i = 0; i < jump_table.length; i++) { 217 jump_table[i] = offset + bytes.readInt(); 218 buf.append(jump_table[i]); 219 if (i < jump_table.length - 1) { 220 buf.append(", "); 221 } 222 } 223 buf.append(")"); 224 break; 225 227 case Constants.LOOKUPSWITCH: { 228 npairs = bytes.readInt(); 229 offset = bytes.getIndex() - 8 - no_pad_bytes - 1; 230 match = new int[npairs]; 231 jump_table = new int[npairs]; 232 default_offset += offset; 233 buf.append("\tdefault = ").append(default_offset).append(", npairs = ").append( 234 npairs).append(" ("); 235 for (int i = 0; i < npairs; i++) { 236 match[i] = bytes.readInt(); 237 jump_table[i] = offset + bytes.readInt(); 238 buf.append("(").append(match[i]).append(", ").append(jump_table[i]).append(")"); 239 if (i < npairs - 1) { 240 buf.append(", "); 241 } 242 } 243 buf.append(")"); 244 } 245 break; 246 249 case Constants.GOTO: 250 case Constants.IFEQ: 251 case Constants.IFGE: 252 case Constants.IFGT: 253 case Constants.IFLE: 254 case Constants.IFLT: 255 case Constants.JSR: 256 case Constants.IFNE: 257 case Constants.IFNONNULL: 258 case Constants.IFNULL: 259 case Constants.IF_ACMPEQ: 260 case Constants.IF_ACMPNE: 261 case Constants.IF_ICMPEQ: 262 case Constants.IF_ICMPGE: 263 case Constants.IF_ICMPGT: 264 case Constants.IF_ICMPLE: 265 case Constants.IF_ICMPLT: 266 case Constants.IF_ICMPNE: 267 buf.append("\t\t#").append((bytes.getIndex() - 1) + bytes.readShort()); 268 break; 269 271 case Constants.GOTO_W: 272 case Constants.JSR_W: 273 buf.append("\t\t#").append(((bytes.getIndex() - 1) + bytes.readInt())); 274 break; 275 277 case Constants.ALOAD: 278 case Constants.ASTORE: 279 case Constants.DLOAD: 280 case Constants.DSTORE: 281 case Constants.FLOAD: 282 case Constants.FSTORE: 283 case Constants.ILOAD: 284 case Constants.ISTORE: 285 case Constants.LLOAD: 286 case Constants.LSTORE: 287 case Constants.RET: 288 if (wide) { 289 vindex = bytes.readUnsignedShort(); 290 wide = false; } else { 292 vindex = bytes.readUnsignedByte(); 293 } 294 buf.append("\t\t%").append(vindex); 295 break; 296 301 case Constants.WIDE: 302 wide = true; 303 buf.append("\t(wide)"); 304 break; 305 307 case Constants.NEWARRAY: 308 buf.append("\t\t<").append(Constants.TYPE_NAMES[bytes.readByte()]).append(">"); 309 break; 310 312 case Constants.GETFIELD: 313 case Constants.GETSTATIC: 314 case Constants.PUTFIELD: 315 case Constants.PUTSTATIC: 316 index = bytes.readUnsignedShort(); 317 buf.append("\t\t").append( 318 constant_pool.constantToString(index, Constants.CONSTANT_Fieldref)).append( 319 (verbose ? " (" + index + ")" : "")); 320 break; 321 323 case Constants.NEW: 324 case Constants.CHECKCAST: 325 buf.append("\t"); 326 case Constants.INSTANCEOF: 327 index = bytes.readUnsignedShort(); 328 buf.append("\t<").append( 329 constant_pool.constantToString(index, Constants.CONSTANT_Class)) 330 .append(">").append((verbose ? " (" + index + ")" : "")); 331 break; 332 334 case Constants.INVOKESPECIAL: 335 case Constants.INVOKESTATIC: 336 case Constants.INVOKEVIRTUAL: 337 index = bytes.readUnsignedShort(); 338 buf.append("\t").append( 339 constant_pool.constantToString(index, Constants.CONSTANT_Methodref)) 340 .append((verbose ? " (" + index + ")" : "")); 341 break; 342 case Constants.INVOKEINTERFACE: 343 index = bytes.readUnsignedShort(); 344 int nargs = bytes.readUnsignedByte(); buf.append("\t").append( 346 constant_pool 347 .constantToString(index, Constants.CONSTANT_InterfaceMethodref)) 348 .append(verbose ? " (" + index + ")\t" : "").append(nargs).append("\t") 349 .append(bytes.readUnsignedByte()); break; 351 353 case Constants.LDC_W: 354 case Constants.LDC2_W: 355 index = bytes.readUnsignedShort(); 356 buf.append("\t\t").append( 357 constant_pool.constantToString(index, constant_pool.getConstant(index) 358 .getTag())).append((verbose ? " (" + index + ")" : "")); 359 break; 360 case Constants.LDC: 361 index = bytes.readUnsignedByte(); 362 buf.append("\t\t").append( 363 constant_pool.constantToString(index, constant_pool.getConstant(index) 364 .getTag())).append((verbose ? " (" + index + ")" : "")); 365 break; 366 368 case Constants.ANEWARRAY: 369 index = bytes.readUnsignedShort(); 370 buf.append("\t\t<").append( 371 compactClassName(constant_pool.getConstantString(index, 372 Constants.CONSTANT_Class), false)).append(">").append( 373 (verbose ? " (" + index + ")" : "")); 374 break; 375 377 case Constants.MULTIANEWARRAY: { 378 index = bytes.readUnsignedShort(); 379 int dimensions = bytes.readUnsignedByte(); 380 buf.append("\t<").append( 381 compactClassName(constant_pool.getConstantString(index, 382 Constants.CONSTANT_Class), false)).append(">\t").append(dimensions) 383 .append((verbose ? " (" + index + ")" : "")); 384 } 385 break; 386 388 case Constants.IINC: 389 if (wide) { 390 vindex = bytes.readUnsignedShort(); 391 constant = bytes.readShort(); 392 wide = false; 393 } else { 394 vindex = bytes.readUnsignedByte(); 395 constant = bytes.readByte(); 396 } 397 buf.append("\t\t%").append(vindex).append("\t").append(constant); 398 break; 399 default: 400 if (Constants.NO_OF_OPERANDS[opcode] > 0) { 401 for (int i = 0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) { 402 buf.append("\t\t"); 403 switch (Constants.TYPE_OF_OPERANDS[opcode][i]) { 404 case Constants.T_BYTE: 405 buf.append(bytes.readByte()); 406 break; 407 case Constants.T_SHORT: 408 buf.append(bytes.readShort()); 409 break; 410 case Constants.T_INT: 411 buf.append(bytes.readInt()); 412 break; 413 default: System.err.println("Unreachable default case reached!"); 415 System.exit(-1); 416 } 417 } 418 } 419 } 420 return buf.toString(); 421 } 422 423 424 public static final String codeToString( ByteSequence bytes, ConstantPool constant_pool ) 425 throws IOException { 426 return codeToString(bytes, constant_pool, true); 427 } 428 429 430 437 public static final String compactClassName( String str ) { 438 return compactClassName(str, true); 439 } 440 441 442 453 public static final String compactClassName( String str, String prefix, boolean chopit ) { 454 int len = prefix.length(); 455 str = str.replace('/', '.'); if (chopit) { 457 if (str.startsWith(prefix) && (str.substring(len).indexOf('.') == -1)) { 459 str = str.substring(len); 460 } 461 } 462 return str; 463 } 464 465 466 476 public static final String compactClassName( String str, boolean chopit ) { 477 return compactClassName(str, "java.lang.", chopit); 478 } 479 480 481 484 public static final int setBit( int flag, int i ) { 485 return flag | pow2(i); 486 } 487 488 489 492 public static final int clearBit( int flag, int i ) { 493 int bit = pow2(i); 494 return (flag & bit) == 0 ? flag : flag ^ bit; 495 } 496 497 498 501 public static final boolean isSet( int flag, int i ) { 502 return (flag & pow2(i)) != 0; 503 } 504 505 506 514 public final static String methodTypeToSignature( String ret, String [] argv ) 515 throws ClassFormatException { 516 StringBuffer buf = new StringBuffer ("("); 517 String str; 518 if (argv != null) { 519 for (int i = 0; i < argv.length; i++) { 520 str = getSignature(argv[i]); 521 if (str.endsWith("V")) { 522 throw new ClassFormatException("Invalid type: " + argv[i]); 523 } 524 buf.append(str); 525 } 526 } 527 str = getSignature(ret); 528 buf.append(")").append(str); 529 return buf.toString(); 530 } 531 532 533 538 public static final String [] methodSignatureArgumentTypes( String signature ) 539 throws ClassFormatException { 540 return methodSignatureArgumentTypes(signature, true); 541 } 542 543 544 550 public static final String [] methodSignatureArgumentTypes( String signature, boolean chopit ) 551 throws ClassFormatException { 552 List vec = new ArrayList (); 553 int index; 554 try { if (signature.charAt(0) != '(') { 556 throw new ClassFormatException("Invalid method signature: " + signature); 557 } 558 index = 1; while (signature.charAt(index) != ')') { 560 vec.add(signatureToString(signature.substring(index), chopit)); 561 index += unwrap(consumed_chars); } 564 } catch (StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid method signature: " + signature); 566 } 567 return (String []) vec.toArray(new String [vec.size()]); 568 } 569 570 571 576 public static final String methodSignatureReturnType( String signature ) 577 throws ClassFormatException { 578 return methodSignatureReturnType(signature, true); 579 } 580 581 582 588 public static final String methodSignatureReturnType( String signature, boolean chopit ) 589 throws ClassFormatException { 590 int index; 591 String type; 592 try { 593 index = signature.lastIndexOf(')') + 1; 595 type = signatureToString(signature.substring(index), chopit); 596 } catch (StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid method signature: " + signature); 598 } 599 return type; 600 } 601 602 603 611 public static final String methodSignatureToString( String signature, String name, String access ) { 612 return methodSignatureToString(signature, name, access, true); 613 } 614 615 616 public static final String methodSignatureToString( String signature, String name, 617 String access, boolean chopit ) { 618 return methodSignatureToString(signature, name, access, chopit, null); 619 } 620 621 622 649 public static final String methodSignatureToString( String signature, String name, 650 String access, boolean chopit, LocalVariableTable vars ) throws ClassFormatException { 651 StringBuffer buf = new StringBuffer ("("); 652 String type; 653 int index; 654 int var_index = (access.indexOf("static") >= 0) ? 0 : 1; 655 try { if (signature.charAt(0) != '(') { 657 throw new ClassFormatException("Invalid method signature: " + signature); 658 } 659 index = 1; while (signature.charAt(index) != ')') { 661 String param_type = signatureToString(signature.substring(index), chopit); 662 buf.append(param_type); 663 if (vars != null) { 664 LocalVariable l = vars.getLocalVariable(var_index); 665 if (l != null) { 666 buf.append(" ").append(l.getName()); 667 } 668 } else { 669 buf.append(" arg").append(var_index); 670 } 671 if ("double".equals(param_type) || "long".equals(param_type)) { 672 var_index += 2; 673 } else { 674 var_index++; 675 } 676 buf.append(", "); 677 index += unwrap(consumed_chars); } 680 index++; type = signatureToString(signature.substring(index), chopit); 683 } catch (StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid method signature: " + signature); 685 } 686 if (buf.length() > 1) { 687 buf.setLength(buf.length() - 2); 688 } 689 buf.append(")"); 690 return access + ((access.length() > 0) ? " " : "") + type + " " + name + buf.toString(); 692 } 693 694 695 private static final int pow2( int n ) { 697 return 1 << n; 698 } 699 700 701 709 public static final String replace( String str, String old, String new_ ) { 710 int index, old_index; 711 StringBuffer buf = new StringBuffer (); 712 try { 713 if ((index = str.indexOf(old)) != -1) { old_index = 0; while ((index = str.indexOf(old, old_index)) != -1) { 717 buf.append(str.substring(old_index, index)); buf.append(new_); old_index = index + old.length(); } 721 buf.append(str.substring(old_index)); str = buf.toString(); 723 } 724 } catch (StringIndexOutOfBoundsException e) { System.err.println(e); 726 } 727 return str; 728 } 729 730 731 737 public static final String signatureToString( String signature ) { 738 return signatureToString(signature, true); 739 } 740 741 742 776 public static final String signatureToString( String signature, boolean chopit ) { 777 wrap(consumed_chars, 1); try { 780 switch (signature.charAt(0)) { 781 case 'B': 782 return "byte"; 783 case 'C': 784 return "char"; 785 case 'D': 786 return "double"; 787 case 'F': 788 return "float"; 789 case 'I': 790 return "int"; 791 case 'J': 792 return "long"; 793 case 'L': { int index = signature.indexOf(';'); if (index < 0) { 796 throw new ClassFormatException("Invalid signature: " + signature); 797 } 798 wrap(consumed_chars, index + 1); return compactClassName(signature.substring(1, index), chopit); 801 } 802 case 'S': 803 return "short"; 804 case 'Z': 805 return "boolean"; 806 case '[': { int n; 808 StringBuffer brackets; 809 String type; 810 int consumed_chars; brackets = new StringBuffer (); for (n = 0; signature.charAt(n) == '['; n++) { 814 brackets.append("[]"); 815 } 816 consumed_chars = n; type = signatureToString(signature.substring(n), chopit); 819 int _temp = unwrap(Utility.consumed_chars) + consumed_chars; 822 wrap(Utility.consumed_chars, _temp); 823 return type + brackets.toString(); 824 } 825 case 'V': 826 return "void"; 827 default: 828 throw new ClassFormatException("Invalid signature: `" + signature + "'"); 829 } 830 } catch (StringIndexOutOfBoundsException e) { throw new ClassFormatException("Invalid signature: " + e + ":" + signature); 832 } 833 } 834 835 836 842 public static String getSignature( String type ) { 843 StringBuffer buf = new StringBuffer (); 844 char[] chars = type.toCharArray(); 845 boolean char_found = false, delim = false; 846 int index = -1; 847 loop: for (int i = 0; i < chars.length; i++) { 848 switch (chars[i]) { 849 case ' ': 850 case '\t': 851 case '\n': 852 case '\r': 853 case '\f': 854 if (char_found) { 855 delim = true; 856 } 857 break; 858 case '[': 859 if (!char_found) { 860 throw new RuntimeException ("Illegal type: " + type); 861 } 862 index = i; 863 break loop; 864 default: 865 char_found = true; 866 if (!delim) { 867 buf.append(chars[i]); 868 } 869 } 870 } 871 int brackets = 0; 872 if (index > 0) { 873 brackets = countBrackets(type.substring(index)); 874 } 875 type = buf.toString(); 876 buf.setLength(0); 877 for (int i = 0; i < brackets; i++) { 878 buf.append('['); 879 } 880 boolean found = false; 881 for (int i = Constants.T_BOOLEAN; (i <= Constants.T_VOID) && !found; i++) { 882 if (Constants.TYPE_NAMES[i].equals(type)) { 883 found = true; 884 buf.append(Constants.SHORT_TYPE_NAMES[i]); 885 } 886 } 887 if (!found) { 888 buf.append('L').append(type.replace('.', '/')).append(';'); 889 } 890 return buf.toString(); 891 } 892 893 894 private static int countBrackets( String brackets ) { 895 char[] chars = brackets.toCharArray(); 896 int count = 0; 897 boolean open = false; 898 for (int i = 0; i < chars.length; i++) { 899 switch (chars[i]) { 900 case '[': 901 if (open) { 902 throw new RuntimeException ("Illegally nested brackets:" + brackets); 903 } 904 open = true; 905 break; 906 case ']': 907 if (!open) { 908 throw new RuntimeException ("Illegally nested brackets:" + brackets); 909 } 910 open = false; 911 count++; 912 break; 913 default: 914 } 916 } 917 if (open) { 918 throw new RuntimeException ("Illegally nested brackets:" + brackets); 919 } 920 return count; 921 } 922 923 924 931 public static final byte typeOfMethodSignature( String signature ) throws ClassFormatException { 932 int index; 933 try { 934 if (signature.charAt(0) != '(') { 935 throw new ClassFormatException("Invalid method signature: " + signature); 936 } 937 index = signature.lastIndexOf(')') + 1; 938 return typeOfSignature(signature.substring(index)); 939 } catch (StringIndexOutOfBoundsException e) { 940 throw new ClassFormatException("Invalid method signature: " + signature); 941 } 942 } 943 944 945 952 public static final byte typeOfSignature( String signature ) throws ClassFormatException { 953 try { 954 switch (signature.charAt(0)) { 955 case 'B': 956 return Constants.T_BYTE; 957 case 'C': 958 return Constants.T_CHAR; 959 case 'D': 960 return Constants.T_DOUBLE; 961 case 'F': 962 return Constants.T_FLOAT; 963 case 'I': 964 return Constants.T_INT; 965 case 'J': 966 return Constants.T_LONG; 967 case 'L': 968 return Constants.T_REFERENCE; 969 case '[': 970 return Constants.T_ARRAY; 971 case 'V': 972 return Constants.T_VOID; 973 case 'Z': 974 return Constants.T_BOOLEAN; 975 case 'S': 976 return Constants.T_SHORT; 977 default: 978 throw new ClassFormatException("Invalid method signature: " + signature); 979 } 980 } catch (StringIndexOutOfBoundsException e) { 981 throw new ClassFormatException("Invalid method signature: " + signature); 982 } 983 } 984 985 986 988 public static short searchOpcode( String name ) { 989 name = name.toLowerCase(Locale.ENGLISH); 990 for (short i = 0; i < Constants.OPCODE_NAMES.length; i++) { 991 if (Constants.OPCODE_NAMES[i].equals(name)) { 992 return i; 993 } 994 } 995 return -1; 996 } 997 998 999 1003 private static final short byteToShort( byte b ) { 1004 return (b < 0) ? (short) (256 + b) : (short) b; 1005 } 1006 1007 1008 1012 public static final String toHexString( byte[] bytes ) { 1013 StringBuffer buf = new StringBuffer (); 1014 for (int i = 0; i < bytes.length; i++) { 1015 short b = byteToShort(bytes[i]); 1016 String hex = Integer.toString(b, 0x10); 1017 if (b < 0x10) { 1018 buf.append('0'); 1019 } 1020 buf.append(hex); 1021 if (i < bytes.length - 1) { 1022 buf.append(' '); 1023 } 1024 } 1025 return buf.toString(); 1026 } 1027 1028 1029 1039 public static final String format( int i, int length, boolean left_justify, char fill ) { 1040 return fillup(Integer.toString(i), length, left_justify, fill); 1041 } 1042 1043 1044 1053 public static final String fillup( String str, int length, boolean left_justify, char fill ) { 1054 int len = length - str.length(); 1055 char[] buf = new char[(len < 0) ? 0 : len]; 1056 for (int j = 0; j < buf.length; j++) { 1057 buf[j] = fill; 1058 } 1059 if (left_justify) { 1060 return str + new String (buf); 1061 } 1062 return new String (buf) + str; 1063 } 1064 1065 1066 static final boolean equals( byte[] a, byte[] b ) { 1067 int size; 1068 if ((size = a.length) != b.length) { 1069 return false; 1070 } 1071 for (int i = 0; i < size; i++) { 1072 if (a[i] != b[i]) { 1073 return false; 1074 } 1075 } 1076 return true; 1077 } 1078 1079 1080 public static final void printArray( PrintStream out, Object [] obj ) { 1081 out.println(printArray(obj, true)); 1082 } 1083 1084 1085 public static final void printArray( PrintWriter out, Object [] obj ) { 1086 out.println(printArray(obj, true)); 1087 } 1088 1089 1090 public static final String printArray( Object [] obj ) { 1091 return printArray(obj, true); 1092 } 1093 1094 1095 public static final String printArray( Object [] obj, boolean braces ) { 1096 return printArray(obj, braces, false); 1097 } 1098 1099 1100 public static final String printArray( Object [] obj, boolean braces, boolean quote ) { 1101 if (obj == null) { 1102 return null; 1103 } 1104 StringBuffer buf = new StringBuffer (); 1105 if (braces) { 1106 buf.append('{'); 1107 } 1108 for (int i = 0; i < obj.length; i++) { 1109 if (obj[i] != null) { 1110 buf.append((quote ? "\"" : "")).append(obj[i].toString()).append( 1111 (quote ? "\"" : "")); 1112 } else { 1113 buf.append("null"); 1114 } 1115 if (i < obj.length - 1) { 1116 buf.append(", "); 1117 } 1118 } 1119 if (braces) { 1120 buf.append('}'); 1121 } 1122 return buf.toString(); 1123 } 1124 1125 1126 1128 public static boolean isJavaIdentifierPart( char ch ) { 1129 return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) 1130 || ((ch >= '0') && (ch <= '9')) || (ch == '_'); 1131 } 1132 1133 1134 1150 public static String encode( byte[] bytes, boolean compress ) throws IOException { 1151 if (compress) { 1152 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 1153 GZIPOutputStream gos = new GZIPOutputStream (baos); 1154 gos.write(bytes, 0, bytes.length); 1155 gos.close(); 1156 baos.close(); 1157 bytes = baos.toByteArray(); 1158 } 1159 CharArrayWriter caw = new CharArrayWriter (); 1160 JavaWriter jw = new JavaWriter(caw); 1161 for (int i = 0; i < bytes.length; i++) { 1162 int in = bytes[i] & 0x000000ff; jw.write(in); 1164 } 1165 return caw.toString(); 1166 } 1167 1168 1169 1174 public static byte[] decode( String s, boolean uncompress ) throws IOException { 1175 char[] chars = s.toCharArray(); 1176 CharArrayReader car = new CharArrayReader (chars); 1177 JavaReader jr = new JavaReader(car); 1178 ByteArrayOutputStream bos = new ByteArrayOutputStream (); 1179 int ch; 1180 while ((ch = jr.read()) >= 0) { 1181 bos.write(ch); 1182 } 1183 bos.close(); 1184 car.close(); 1185 jr.close(); 1186 byte[] bytes = bos.toByteArray(); 1187 if (uncompress) { 1188 GZIPInputStream gis = new GZIPInputStream (new ByteArrayInputStream (bytes)); 1189 byte[] tmp = new byte[bytes.length * 3]; int count = 0; 1191 int b; 1192 while ((b = gis.read()) >= 0) { 1193 tmp[count++] = (byte) b; 1194 } 1195 bytes = new byte[count]; 1196 System.arraycopy(tmp, 0, bytes, 0, count); 1197 } 1198 return bytes; 1199 } 1200 1201 private static final int FREE_CHARS = 48; 1203 static int[] CHAR_MAP = new int[FREE_CHARS]; 1204 static int[] MAP_CHAR = new int[256]; private static final char ESCAPE_CHAR = '$'; 1206 static { 1207 int j = 0; 1208 for (int i = 'A'; i <= 'Z'; i++) { 1209 CHAR_MAP[j] = i; 1210 MAP_CHAR[i] = j; 1211 j++; 1212 } 1213 for (int i = 'g'; i <= 'z'; i++) { 1214 CHAR_MAP[j] = i; 1215 MAP_CHAR[i] = j; 1216 j++; 1217 } 1218 CHAR_MAP[j] = '$'; 1219 MAP_CHAR['$'] = j; 1220 j++; 1221 CHAR_MAP[j] = '_'; 1222 MAP_CHAR['_'] = j; 1223 } 1224 1225 1228 private static class JavaReader extends FilterReader { 1229 1230 public JavaReader(Reader in) { 1231 super(in); 1232 } 1233 1234 1235 public int read() throws IOException { 1236 int b = in.read(); 1237 if (b != ESCAPE_CHAR) { 1238 return b; 1239 } 1240 int i = in.read(); 1241 if (i < 0) { 1242 return -1; 1243 } 1244 if (((i >= '0') && (i <= '9')) || ((i >= 'a') && (i <= 'f'))) { int j = in.read(); 1246 if (j < 0) { 1247 return -1; 1248 } 1249 char[] tmp = { 1250 (char) i, (char) j 1251 }; 1252 int s = Integer.parseInt(new String (tmp), 16); 1253 return s; 1254 } 1255 return MAP_CHAR[i]; 1256 } 1257 1258 1259 public int read( char[] cbuf, int off, int len ) throws IOException { 1260 for (int i = 0; i < len; i++) { 1261 cbuf[off + i] = (char) read(); 1262 } 1263 return len; 1264 } 1265 } 1266 1267 1270 private static class JavaWriter extends FilterWriter { 1271 1272 public JavaWriter(Writer out) { 1273 super(out); 1274 } 1275 1276 1277 public void write( int b ) throws IOException { 1278 if (isJavaIdentifierPart((char) b) && (b != ESCAPE_CHAR)) { 1279 out.write(b); 1280 } else { 1281 out.write(ESCAPE_CHAR); if (b >= 0 && b < FREE_CHARS) { 1284 out.write(CHAR_MAP[b]); 1285 } else { char[] tmp = Integer.toHexString(b).toCharArray(); 1287 if (tmp.length == 1) { 1288 out.write('0'); 1289 out.write(tmp[0]); 1290 } else { 1291 out.write(tmp[0]); 1292 out.write(tmp[1]); 1293 } 1294 } 1295 } 1296 } 1297 1298 1299 public void write( char[] cbuf, int off, int len ) throws IOException { 1300 for (int i = 0; i < len; i++) { 1301 write(cbuf[off + i]); 1302 } 1303 } 1304 1305 1306 public void write( String str, int off, int len ) throws IOException { 1307 write(str.toCharArray(), off, len); 1308 } 1309 } 1310 1311 1312 1315 public static final String convertString( String label ) { 1316 char[] ch = label.toCharArray(); 1317 StringBuffer buf = new StringBuffer (); 1318 for (int i = 0; i < ch.length; i++) { 1319 switch (ch[i]) { 1320 case '\n': 1321 buf.append("\\n"); 1322 break; 1323 case '\r': 1324 buf.append("\\r"); 1325 break; 1326 case '\"': 1327 buf.append("\\\""); 1328 break; 1329 case '\'': 1330 buf.append("\\'"); 1331 break; 1332 case '\\': 1333 buf.append("\\\\"); 1334 break; 1335 default: 1336 buf.append(ch[i]); 1337 break; 1338 } 1339 } 1340 return buf.toString(); 1341 } 1342} 1343 | Popular Tags |