| 1 22 package org.jboss.util; 23 24 import org.jboss.logging.Logger; 25 26 73 public class Base64 74 { 75 private static final Logger log = Logger.getLogger(Base64.class); 77 78 79 80 81 public final static int NO_OPTIONS = 0; 82 83 84 public final static int ENCODE = 1; 85 86 87 public final static int DECODE = 0; 88 89 90 public final static int GZIP = 2; 91 92 93 public final static int DONT_BREAK_LINES = 8; 94 95 96 97 98 private final static int MAX_LINE_LENGTH = 76; 99 100 101 private final static byte EQUALS_SIGN = (byte)'='; 102 103 104 private final static byte NEW_LINE = (byte)'\n'; 105 106 107 private final static String PREFERRED_ENCODING = "UTF-8"; 108 109 110 private final static byte[] ALPHABET; 111 private final static byte[] _NATIVE_ALPHABET = 112 { (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', 113 (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b', 114 (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', (byte)'o', (byte)'p', 115 (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', (byte)'0', (byte)'1', (byte)'2', (byte)'3', 116 (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' }; 117 118 119 static 120 { 121 byte[] __bytes; 122 try 123 { 124 __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(PREFERRED_ENCODING); 125 } catch (java.io.UnsupportedEncodingException use) 127 { 128 __bytes = _NATIVE_ALPHABET; } ALPHABET = __bytes; 131 } 133 137 private final static byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, -5, -5, -9, -9, -5, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -5, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 62, -9, -9, -9, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -9, -9, -9, -1, -9, -9, -9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -9, -9, -9, -9, -9, -9, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -9, -9, -9, -9 168 }; 169 170 private final static byte WHITE_SPACE_ENC = -5; private final static byte EQUALS_SIGN_ENC = -1; 175 176 private Base64() 177 { 178 } 179 180 181 182 197 private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes) 198 { 199 encode3to4(threeBytes, 0, numSigBytes, b4, 0); 200 return b4; 201 } 203 224 private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset) 225 { 226 233 int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) 238 | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); 239 240 switch (numSigBytes) 241 { 242 case 3: 243 destination[destOffset] = ALPHABET[(inBuff >>> 18)]; 244 destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; 245 destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; 246 destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f]; 247 return destination; 248 249 case 2: 250 destination[destOffset] = ALPHABET[(inBuff >>> 18)]; 251 destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; 252 destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; 253 destination[destOffset + 3] = EQUALS_SIGN; 254 return destination; 255 256 case 1: 257 destination[destOffset] = ALPHABET[(inBuff >>> 18)]; 258 destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; 259 destination[destOffset + 2] = EQUALS_SIGN; 260 destination[destOffset + 3] = EQUALS_SIGN; 261 return destination; 262 263 default: 264 return destination; 265 } } 268 279 public static String encodeObject(java.io.Serializable serializableObject) 280 { 281 return encodeObject(serializableObject, NO_OPTIONS); 282 } 284 307 public static String encodeObject(java.io.Serializable serializableObject, int options) 308 { 309 java.io.ByteArrayOutputStream baos = null; 311 java.io.OutputStream b64os = null; 312 java.io.ObjectOutputStream oos = null; 313 java.util.zip.GZIPOutputStream gzos = null; 314 315 int gzip = (options & GZIP); 317 int dontBreakLines = (options & DONT_BREAK_LINES); 318 319 try 320 { 321 baos = new java.io.ByteArrayOutputStream (); 323 b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines); 324 325 if (gzip == GZIP) 327 { 328 gzos = new java.util.zip.GZIPOutputStream (b64os); 329 oos = new java.io.ObjectOutputStream (gzos); 330 } else oos = new java.io.ObjectOutputStream (b64os); 332 333 oos.writeObject(serializableObject); 334 } catch (java.io.IOException e) 336 { 337 e.printStackTrace(); 338 return null; 339 } finally 341 { 342 try 343 { 344 oos.close(); 345 } 346 catch (Exception e) 347 { 348 } 349 try 350 { 351 gzos.close(); 352 } 353 catch (Exception e) 354 { 355 } 356 try 357 { 358 b64os.close(); 359 } 360 catch (Exception e) 361 { 362 } 363 try 364 { 365 baos.close(); 366 } 367 catch (Exception e) 368 { 369 } 370 } 372 try 374 { 375 return new String (baos.toByteArray(), PREFERRED_ENCODING); 376 } catch (java.io.UnsupportedEncodingException uue) 378 { 379 return new String (baos.toByteArray()); 380 } 382 } 384 391 public static String encodeBytes(byte[] source) 392 { 393 return encodeBytes(source, 0, source.length, NO_OPTIONS); 394 } 396 416 public static String encodeBytes(byte[] source, int options) 417 { 418 return encodeBytes(source, 0, source.length, options); 419 } 421 430 public static String encodeBytes(byte[] source, int off, int len) 431 { 432 return encodeBytes(source, off, len, NO_OPTIONS); 433 } 435 457 public static String encodeBytes(byte[] source, int off, int len, int options) 458 { 459 int dontBreakLines = (options & DONT_BREAK_LINES); 461 int gzip = (options & GZIP); 462 463 if (gzip == GZIP) 465 { 466 java.io.ByteArrayOutputStream baos = null; 467 java.util.zip.GZIPOutputStream gzos = null; 468 Base64.OutputStream b64os = null; 469 470 try 471 { 472 baos = new java.io.ByteArrayOutputStream (); 474 b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines); 475 gzos = new java.util.zip.GZIPOutputStream (b64os); 476 477 gzos.write(source, off, len); 478 gzos.close(); 479 } catch (java.io.IOException e) 481 { 482 e.printStackTrace(); 483 return null; 484 } finally 486 { 487 try 488 { 489 gzos.close(); 490 } 491 catch (Exception e) 492 { 493 } 494 try 495 { 496 b64os.close(); 497 } 498 catch (Exception e) 499 { 500 } 501 try 502 { 503 baos.close(); 504 } 505 catch (Exception e) 506 { 507 } 508 } 510 try 512 { 513 return new String (baos.toByteArray(), PREFERRED_ENCODING); 514 } catch (java.io.UnsupportedEncodingException uue) 516 { 517 return new String (baos.toByteArray()); 518 } } 521 else 523 { 524 boolean breakLines = dontBreakLines == 0; 526 527 int len43 = len * 4 / 3; 528 byte[] outBuff = new byte[(len43) + ((len % 3) > 0 ? 4 : 0) + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; int d = 0; 532 int e = 0; 533 int len2 = len - 2; 534 int lineLength = 0; 535 for (; d < len2; d += 3, e += 4) 536 { 537 encode3to4(source, d + off, 3, outBuff, e); 538 539 lineLength += 4; 540 if (breakLines && lineLength == MAX_LINE_LENGTH) 541 { 542 outBuff[e + 4] = NEW_LINE; 543 e++; 544 lineLength = 0; 545 } } 548 if (d < len) 549 { 550 encode3to4(source, d + off, len - d, outBuff, e); 551 e += 4; 552 } 554 try 556 { 557 return new String (outBuff, 0, e, PREFERRED_ENCODING); 558 } catch (java.io.UnsupportedEncodingException uue) 560 { 561 return new String (outBuff, 0, e); 562 } 564 } 566 } 568 569 570 592 private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset) 593 { 594 if (source[srcOffset + 2] == EQUALS_SIGN) 596 { 597 int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12); 601 602 destination[destOffset] = (byte)(outBuff >>> 16); 603 return 1; 604 } 605 606 else if (source[srcOffset + 3] == EQUALS_SIGN) 608 { 609 int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) 614 | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6); 615 616 destination[destOffset] = (byte)(outBuff >>> 16); 617 destination[destOffset + 1] = (byte)(outBuff >>> 8); 618 return 2; 619 } 620 621 else 623 { 624 try 625 { 626 int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) 632 | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) | ((DECODABET[source[srcOffset + 3]] & 0xFF)); 633 634 destination[destOffset] = (byte)(outBuff >> 16); 635 destination[destOffset + 1] = (byte)(outBuff >> 8); 636 destination[destOffset + 2] = (byte)(outBuff); 637 638 return 3; 639 } 640 catch (Exception e) 641 { 642 log.error("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]])); 643 log.error("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]])); 644 log.error("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]])); 645 log.error("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]])); 646 return -1; 647 } } 649 } 651 662 public static byte[] decode(byte[] source, int off, int len) 663 { 664 int len34 = len * 3 / 4; 665 byte[] outBuff = new byte[len34]; int outBuffPosn = 0; 667 668 byte[] b4 = new byte[4]; 669 int b4Posn = 0; 670 int i = 0; 671 byte sbiCrop = 0; 672 byte sbiDecode = 0; 673 for (i = off; i < off + len; i++) 674 { 675 sbiCrop = (byte)(source[i] & 0x7f); sbiDecode = DECODABET[sbiCrop]; 677 678 if (sbiDecode >= WHITE_SPACE_ENC) { 680 if (sbiDecode >= EQUALS_SIGN_ENC) 681 { 682 b4[b4Posn++] = sbiCrop; 683 if (b4Posn > 3) 684 { 685 outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn); 686 b4Posn = 0; 687 688 if (sbiCrop == EQUALS_SIGN) 690 break; 691 } 693 } 695 } else 697 { 698 throw new IllegalStateException ("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)"); 699 } } 702 byte[] out = new byte[outBuffPosn]; 703 System.arraycopy(outBuff, 0, out, 0, outBuffPosn); 704 return out; 705 } 707 715 public static byte[] decode(String s) 716 { 717 byte[] bytes; 718 try 719 { 720 bytes = s.getBytes(PREFERRED_ENCODING); 721 } catch (java.io.UnsupportedEncodingException uee) 723 { 724 bytes = s.getBytes(); 725 } 728 bytes = decode(bytes, 0, bytes.length); 730 731 if (bytes != null && bytes.length >= 4) 734 { 735 736 int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); 737 if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) 738 { 739 java.io.ByteArrayInputStream bais = null; 740 java.util.zip.GZIPInputStream gzis = null; 741 java.io.ByteArrayOutputStream baos = null; 742 byte[] buffer = new byte[2048]; 743 int length = 0; 744 745 try 746 { 747 baos = new java.io.ByteArrayOutputStream (); 748 bais = new java.io.ByteArrayInputStream (bytes); 749 gzis = new java.util.zip.GZIPInputStream (bais); 750 751 while ((length = gzis.read(buffer)) >= 0) 752 { 753 baos.write(buffer, 0, length); 754 } 756 bytes = baos.toByteArray(); 758 759 } catch (java.io.IOException e) 761 { 762 } finally 765 { 766 try 767 { 768 baos.close(); 769 } 770 catch (Exception e) 771 { 772 } 773 try 774 { 775 gzis.close(); 776 } 777 catch (Exception e) 778 { 779 } 780 try 781 { 782 bais.close(); 783 } 784 catch (Exception e) 785 { 786 } 787 } 789 } } 792 return bytes; 793 } 795 803 public static Object decodeToObject(String encodedObject) 804 { 805 byte[] objBytes = decode(encodedObject); 807 808 java.io.ByteArrayInputStream bais = null; 809 java.io.ObjectInputStream ois = null; 810 Object obj = null; 811 812 try 813 { 814 bais = new java.io.ByteArrayInputStream (objBytes); 815 ois = new java.io.ObjectInputStream (bais); 816 817 obj = ois.readObject(); 818 } catch (java.io.IOException e) 820 { 821 e.printStackTrace(); 822 obj = null; 823 } catch (java.lang.ClassNotFoundException e) 825 { 826 e.printStackTrace(); 827 obj = null; 828 } finally 830 { 831 try 832 { 833 bais.close(); 834 } 835 |