1 28 29 package org.jibx.runtime; 30 31 import java.sql.Time ; 32 import java.sql.Timestamp ; 33 import java.util.*; 34 35 45 46 public abstract class Utility 47 { 48 49 private static final int MSPERMINUTE = 60000; 50 51 52 private static final int MSPERHOUR = MSPERMINUTE*60; 53 54 55 private static final int MSPERDAY = MSPERHOUR*24; 56 57 58 private static final long LMSPERDAY = (long)MSPERDAY; 59 60 61 private static final long MSPERYEAR = LMSPERDAY*365; 62 63 64 private static final long MSPERAVGYEAR = (long)(MSPERDAY*365.25); 65 66 67 private static final long MSPERCENTURY = (long)(MSPERDAY*36524.25); 68 69 71 private static final long TIME_BASE = 1969*MSPERYEAR + 72 (1969/4 - 19 + 4)*LMSPERDAY; 73 74 75 private static final int[] MONTHS_NONLEAP = 76 { 77 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 78 }; 79 80 81 private static final int[] MONTHS_LEAP = 82 { 83 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 84 }; 85 86 87 private static final long[] BIAS_MONTHMS = 88 { 89 0*LMSPERDAY, 0*LMSPERDAY, 0*LMSPERDAY, 0*LMSPERDAY, 90 31*LMSPERDAY, 61*LMSPERDAY, 92*LMSPERDAY, 122*LMSPERDAY, 91 153*LMSPERDAY, 184*LMSPERDAY, 214*LMSPERDAY, 245*LMSPERDAY, 92 275*LMSPERDAY, 306*LMSPERDAY, 337*LMSPERDAY 93 }; 94 95 96 private static final char PAD_CHAR = '='; 97 98 99 private static final char[] s_base64Chars = { 100 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 101 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 102 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 103 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 104 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 105 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', 106 '8', '9', '+', '/' 107 }; 108 109 110 private static final byte[] s_base64Values = new byte[128]; 111 static { 112 for (int i = 0; i < s_base64Values.length; i++) { 113 s_base64Values[i] = -1; 114 } 115 s_base64Values[PAD_CHAR] = 0; 116 for (int i = 0; i < s_base64Chars.length; i++) { 117 s_base64Values[s_base64Chars[i]] = (byte)i; 118 } 119 } 120 121 132 133 private static int parseDigits(String text, int offset, int length) 134 throws JiBXException { 135 136 int value = 0; 138 if (length > 9) { 139 140 try { 142 value = Integer.parseInt(text.substring(offset, offset+length)); 143 } catch (NumberFormatException ex) { 144 throw new JiBXException(ex.getMessage()); 145 } 146 147 } else { 148 149 int limit = offset + length; 151 while (offset < limit) { 152 char chr = text.charAt(offset++); 153 if (chr >= '0' && chr <= '9') { 154 value = value * 10 + (chr - '0'); 155 } else { 156 throw new JiBXException("Non-digit in number value"); 157 } 158 } 159 160 } 161 return value; 162 } 163 164 172 173 public static int parseInt(String text) throws JiBXException { 174 175 text = text.trim(); 177 int offset = 0; 178 int limit = text.length(); 179 if (limit == 0) { 180 throw new JiBXException("Empty number value"); 181 } 182 183 boolean negate = false; 185 char chr = text.charAt(0); 186 if (chr == '-') { 187 if (limit > 9) { 188 189 try { 191 return Integer.parseInt(text); 192 } catch (NumberFormatException ex) { 193 throw new JiBXException(ex.getMessage()); 194 } 195 196 } else { 197 negate = true; 198 offset++; 199 } 200 } else if (chr == '+') { 201 offset++; 202 } 203 if (offset >= limit) { 204 throw new JiBXException("Invalid number format"); 205 } 206 207 int value = parseDigits(text, offset, limit-offset); 209 if (negate) { 210 return -value; 211 } else { 212 return value; 213 } 214 } 215 216 222 223 public static String serializeInt(int value) { 224 return Integer.toString(value); 225 } 226 227 235 236 public static long parseLong(String text) throws JiBXException { 237 238 text = text.trim(); 240 int offset = 0; 241 int limit = text.length(); 242 if (limit == 0) { 243 throw new JiBXException("Empty number value"); 244 } 245 246 boolean negate = false; 248 char chr = text.charAt(0); 249 if (chr == '-') { 250 negate = true; 251 offset++; 252 } else if (chr == '+') { 253 offset++; 254 } 255 if (offset >= limit) { 256 throw new JiBXException("Invalid number format"); 257 } 258 259 long value = 0; 261 if (limit-offset > 18) { 262 263 if (chr == '+') { 265 text = text.substring(1); 266 } 267 try { 268 value = Long.parseLong(text); 269 } catch (NumberFormatException ex) { 270 throw new JiBXException(ex.getMessage()); 271 } 272 273 } else { 274 275 while (offset < limit) { 277 chr = text.charAt(offset++); 278 if (chr >= '0' && chr <= '9') { 279 value = value * 10 + (chr - '0'); 280 } else { 281 throw new JiBXException("Non-digit in number value"); 282 } 283 } 284 if (negate) { 285 value = -value; 286 } 287 288 } 289 return value; 290 } 291 292 298 299 public static String serializeLong(long value) { 300 return Long.toString(value); 301 } 302 303 311 312 public static short parseShort(String text) throws JiBXException { 313 int value = parseInt(text); 314 if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { 315 throw new JiBXException("Value out of range"); 316 } 317 return (short)value; 318 } 319 320 326 327 public static String serializeShort(short value) { 328 return Short.toString(value); 329 } 330 331 339 340 public static byte parseByte(String text) throws JiBXException { 341 int value = parseInt(text); 342 if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { 343 throw new JiBXException("Value out of range"); 344 } 345 return (byte)value; 346 } 347 348 354 355 public static String serializeByte(byte value) { 356 return Byte.toString(value); 357 } 358 359 367 368 public static boolean parseBoolean(String text) throws JiBXException { 369 text = text.trim(); 370 if ("true".equals(text) || "1".equals(text)) { 371 return true; 372 } else if ("false".equals(text) || "0".equals(text)) { 373 return false; 374 } else { 375 throw new JiBXException("Invalid boolean value"); 376 } 377 } 378 379 386 387 public static String serializeBoolean(boolean value) { 388 return value ? "true" : "false"; 389 } 390 391 399 400 public static char parseChar(String text) throws JiBXException { 401 int value = parseInt(text); 402 if (value < Character.MIN_VALUE || value > Character.MAX_VALUE) { 403 throw new JiBXException("Value out of range"); 404 } 405 return (char)value; 406 } 407 408 414 415 public static String serializeChar(char value) { 416 return Integer.toString(value); 417 } 418 419 427 428 public static char parseCharString(String text) throws JiBXException { 429 if (text.length() == 1) { 430 return text.charAt(0); 431 } else { 432 throw new JiBXException("Input must be a single character"); 433 } 434 } 435 436 444 445 public static char deserializeCharString(String text) throws JiBXException { 446 if (text == null) { 447 return 0; 448 } else { 449 return parseCharString(text); 450 } 451 } 452 453 459 460 public static String serializeCharString(char value) { 461 return String.valueOf(value); 462 } 463 464 474 475 public static float parseFloat(String text) throws JiBXException { 476 text = text.trim(); 477 if ("-INF".equals(text)) { 478 return Float.NEGATIVE_INFINITY; 479 } else if ("INF".equals(text)) { 480 return Float.POSITIVE_INFINITY; 481 } else { 482 try { 483 return Float.parseFloat(text); 484 } catch (NumberFormatException ex) { 485 throw new JiBXException(ex.getMessage()); 486 } 487 } 488 } 489 490 496 497 public static String serializeFloat(float value) { 498 if (Float.isInfinite(value)) { 499 return (value < 0.0f) ? "-INF" : "INF"; 500 } else { 501 return Float.toString(value); 502 } 503 } 504 505 515 516 public static double parseDouble(String text) throws JiBXException { 517 text = text.trim(); 518 if ("-INF".equals(text)) { 519 return Double.NEGATIVE_INFINITY; 520 } else if ("INF".equals(text)) { 521 return Double.POSITIVE_INFINITY; 522 } else { 523 try { 524 return Double.parseDouble(text); 525 } catch (NumberFormatException ex) { 526 throw new JiBXException(ex.getMessage()); 527 } 528 } 529 } 530 531 537 538 public static String serializeDouble(double value) { 539 if (Double.isInfinite(value)) { 540 return (value < 0.0f) ? "-INF" : "INF"; 541 } else { 542 return Double.toString(value); 543 } 544 } 545 546 554 555 public static long parseYear(String text) throws JiBXException { 556 557 text = text.trim(); 559 boolean valid = true; 560 int minc = 4; 561 char chr = text.charAt(0); 562 if (chr == '-') { 563 minc = 5; 564 } else if (chr == '+') { 565 valid = false; 566 } 567 if (text.length() < minc) { 568 valid = false; 569 } 570 if (!valid) { 571 throw new JiBXException("Invalid year format"); 572 } 573 574 int year = parseInt(text); 576 if (year == 0) { 577 throw new JiBXException("Year value 0 is not allowed"); 578 } 579 if (year > 0) { 580 year--; 581 } 582 long day = ((long)year)*365 + year/4 - year/100 + year/400; 583 return day*MSPERDAY - TIME_BASE; 584 } 585 586 595 596 public static long parseYearMonth(String text) throws JiBXException { 597 598 text = text.trim(); 600 boolean valid = true; 601 int minc = 7; 602 char chr = text.charAt(0); 603 if (chr == '-') { 604 minc = 8; 605 } else if (chr == '+') { 606 valid = false; 607 } 608 int split = text.length() - 3; 609 if (text.length() < minc) { 610 valid = false; 611 } else { 612 if (text.charAt(split) != '-') { 613 valid = false; 614 } 615 } 616 if (!valid) { 617 throw new JiBXException("Invalid date format"); 618 } 619 620 int year = parseInt(text.substring(0, split)); 622 if (year == 0) { 623 throw new JiBXException("Year value 0 is not allowed"); 624 } 625 int month = parseDigits(text, split+1, 2) - 1; 626 if (month < 0 || month > 11) { 627 throw new JiBXException("Month value out of range"); 628 } 629 boolean leap = (year%4 == 0) && !((year%100 == 0) && (year%400 != 0)); 630 if (year > 0) { 631 year--; 632 } 633 long day = ((long)year)*365 + year/4 - year/100 + year/400 + 634 (leap ? MONTHS_LEAP : MONTHS_NONLEAP)[month]; 635 return day*MSPERDAY - TIME_BASE; 636 } 637 638 648 649 public static long parseDate(String text) throws JiBXException { 650 651 boolean valid = true; 653 int minc = 10; 654 char chr = text.charAt(0); 655 if (chr == '-') { 656 minc = 11; 657 } else if (chr == '+') { 658 valid = false; 659 } 660 int split = text.length() - 6; 661 if (text.length() < minc) { 662 valid = false; 663 } else { 664 if (text.charAt(split) != '-' || text.charAt(split+3) != '-') { 665 valid = false; 666 } 667 } 668 if (!valid) { 669 throw new JiBXException("Invalid date format"); 670 } 671 672 int year = parseInt(text.substring(0, split)); 674 if (year == 0) { 675 throw new JiBXException("Year value 0 is not allowed"); 676 } 677 int month = parseDigits(text, split+1, 2) - 1; 678 if (month < 0 || month > 11) { 679 throw new JiBXException("Month value out of range"); 680 } 681 long day = parseDigits(text, split+4, 2) - 1; 682 boolean leap = (year%4 == 0) && !((year%100 == 0) && (year%400 != 0)); 683 int[] starts = leap ? MONTHS_LEAP : MONTHS_NONLEAP; 684 if (day < 0 || day >= (starts[month+1]-starts[month])) { 685 throw new JiBXException("Day value out of range"); 686 } 687 if (year > 0) { 688 year--; 689 } 690 day += ((long)year)*365 + year/4 - year/100 + year/400 + starts[month]; 691 return day*MSPERDAY - TIME_BASE; 692 } 693 694 705 706 public static Date deserializeDate(String text) throws JiBXException { 707 if (text == null) { 708 return null; 709 } else { 710 return new Date(parseDate(text)); 711 } 712 } 713 714 725 726 public static java.sql.Date deserializeSqlDate(String text) 727 throws JiBXException { 728 if (text == null) { 729 return null; 730 } else { 731 732 long time = parseDate(text); 734 time += TimeZone.getDefault().getRawOffset() + MSPERHOUR*2; 735 return new java.sql.Date (time); 736 } 737 } 738 739 750 751 public static long parseTime(String text, int start, int length) 752 throws JiBXException { 753 754 long milli = 0; 756 boolean valid = length > (start+7) && 757 (text.charAt(start+2) == ':') && 758 (text.charAt(start+5) == ':'); 759 if (valid) { 760 int hour = parseDigits(text, start, 2); 761 int minute = parseDigits(text, start+3, 2); 762 int second = parseDigits(text, start+6, 2); 763 if (hour > 23 || minute > 59 || second > 60) { 764 valid = false; 765 } else { 766 767 milli = (((hour*60)+minute)*60+second)*1000; 769 start += 8; 770 if (length > start) { 771 772 if (text.charAt(length-1) == 'Z') { 774 length--; 775 } else { 776 char chr = text.charAt(length-6); 777 if (chr == '-' || chr == '+') { 778 hour = parseDigits(text, length-5, 2); 779 minute = parseDigits(text, length-2, 2); 780 if (hour > 23 || minute > 59) { 781 valid = false; 782 } else { 783 int offset = ((hour*60)+minute)*60*1000; 784 if (chr == '-') { 785 milli += offset; 786 } else { 787 milli -= offset; 788 } 789 } 790 length -= 6; 791 } 792 } 793 794 if (text.charAt(start) == '.') { 796 double fraction = Double.parseDouble 797 (text.substring(start, length)); 798 milli += fraction*1000.0; 799 } else if (length > start) { 800 valid = false; 801 } 802 } 803 } 804 } 805 806 if (valid) { 808 return milli; 809 } else { 810 throw new JiBXException("Invalid dateTime format"); 811 } 812 } 813 814 823 824 public static long parseDateTime(String text) throws JiBXException { 825 826 int split = text.indexOf('T'); 828 if (split < 0) { 829 throw new JiBXException("Missing 'T' separator in dateTime"); 830 } 831 return parseDate(text.substring(0, split)) + 832 parseTime(text, split+1, text.length()); 833 } 834 835 847 848 public static Date deserializeDateTime(String text) throws JiBXException { 849 if (text == null) { 850 return null; 851 } else { 852 return new Date(parseDateTime(text)); 853 } 854 } 855 856 868 869 public static Timestamp deserializeTimestamp(String text) 870 throws JiBXException { 871 if (text == null) { 872 return null; 873 } else { 874 875 int split = text.indexOf('.'); 877 int nano = 0; 878 if (split > 0) { 879 880 if (text.indexOf('.', split) > 0) { 882 throw new JiBXException("Not a valid dateTime value"); 883 } 884 885 int limit = text.length(); 887 int scan = split; 888 while (++scan < limit) { 889 char chr = text.charAt(scan); 890 if (chr < '0' || chr > '9') { 891 break; 892 } 893 } 894 895 int length = scan - split - 1; 897 if (length > 9) { 898 length = 9; 899 } 900 nano = parseDigits(text, split+1, length); 901 902 while (length < 9) { 904 nano *= 10; 905 length++; 906 } 907 908 if (scan < limit) { 910 text = text.substring(0, split) + text.substring(scan); 911 } else { 912 text = text.substring(0, split); 913 } 914 } 915 916 Timestamp stamp = new Timestamp (parseDateTime(text)); 918 stamp.setNanos(nano); 919 return stamp; 920 } 921 } 922 923 933 934 public static Time deserializeSqlTime(String text) 935 throws JiBXException { 936 if (text == null) { 937 return null; 938 } else { 939 return new Time (parseTime(text, 0, text.length())); 940 } 941 } 942 943 951 952 protected static void formatYearNumber(long year, StringBuffer buff) { 953 954 if (year <= 0) { 956 buff.append('-'); 957 year = -(year-1); 958 } 959 960 if (year < 1000) { 962 buff.append('0'); 963 if (year < 100) { 964 buff.append('0'); 965 if (year < 10) { 966 buff.append('0'); 967 } 968 } 969 } 970 971 buff.append(year); 973 } 974 975 982 983 protected static void formatTwoDigits(int value, StringBuffer buff) { 984 if (value < 10) { 985 buff.append('0'); 986 } 987 buff.append(value); 988 } 989 990 1000 1001 protected static void formatYear(long value, StringBuffer buff) { 1002 1003 long time = value + 306*LMSPERDAY + LMSPERDAY*3/4; 1009 long century = time / MSPERCENTURY; long adjusted = time + (century - (century/4)) * MSPERDAY; 1011 int year = (int)(adjusted / MSPERAVGYEAR); if (adjusted < 0) { 1013 year--; 1014 } 1015 long yms = adjusted + LMSPERDAY/4 - (year * 365 + year/4) * LMSPERDAY; 1016 int yday = (int)(yms / LMSPERDAY); int month = (5*yday + 456) / 153; if (month > 12) { year++; 1020 } 1021 1022 formatYearNumber(year, buff); 1024 } 1025 1026 1036 1037 protected static long formatYearMonth(long value, StringBuffer buff) { 1038 1039 long time = value + 306*LMSPERDAY + LMSPERDAY*3/4; 1045 long century = time / MSPERCENTURY; long adjusted = time + (century - (century/4)) * MSPERDAY; 1047 int year = (int)(adjusted / MSPERAVGYEAR); if (adjusted < 0) { 1049 year--; 1050 } 1051 long yms = adjusted + LMSPERDAY/4 - (year * 365 + year/4) * LMSPERDAY; 1052 int yday = (int)(yms / LMSPERDAY); if (yday == 0) { boolean bce = year < 0; 1055 if (bce) { 1056 year--; 1057 } 1058 int dcnt = year % 4 == 0 ? 366 : 365; 1059 if (!bce) { 1060 year--; 1061 } 1062 yms += dcnt * LMSPERDAY; 1063 yday += dcnt; 1064 } 1065 int month = (5*yday + 456) / 153; long rem = yms - BIAS_MONTHMS[month] - LMSPERDAY; if (month > 12) { year++; 1069 month -= 12; 1070 } 1071 1072 formatYearNumber(year, buff); 1074 buff.append('-'); 1075 formatTwoDigits(month, buff); 1076 1077 return rem; 1079 } 1080 1081 1091 1092 protected static int formatYearMonthDay(long value, StringBuffer buff) { 1093 1094 long extra = formatYearMonth(value, buff); 1096 1097 int day = (int)(extra / MSPERDAY) + 1; 1099 buff.append('-'); 1100 formatTwoDigits(day, buff); 1101 1102 return (int)(extra % MSPERDAY); 1104 } 1105 1106 1115 1116 public static String serializeYear(long time) throws JiBXException { 1117 StringBuffer buff = new StringBuffer (6); 1118 formatYear(time + TIME_BASE, buff); 1119 return buff.toString(); 1120 } 1121 1122 1131 1132 public static String serializeYear(Date date) throws JiBXException { 1133 return serializeYear(date.getTime()); 1134 } 1135 1136 1145 1146 public static String serializeYearMonth(long time) throws JiBXException { 1147 StringBuffer buff = new StringBuffer (12); 1148 formatYearMonth(time + TIME_BASE, buff); 1149 return buff.toString(); 1150 } 1151 1152 1161 1162 public static String serializeYearMonth(Date date) throws JiBXException { 1163 return serializeYearMonth(date.getTime()); 1164 } 1165 1166 1175 1176 public static String serializeDate(long time) throws JiBXException { 1177 StringBuffer buff = new StringBuffer (12); 1178 formatYearMonthDay(time + TIME_BASE, buff); 1179 return buff.toString(); 1180 } 1181 1182 1191 1192 public static String serializeDate(Date date) throws JiBXException { 1193 return serializeDate(date.getTime()); 1194 } 1195 1196 1205 1206 public static String serializeSqlDate(java.sql.Date date) 1207 throws JiBXException { 1208 1209 long time = date.getTime(); 1211 time -= TimeZone.getDefault().getRawOffset() - MSPERHOUR*2; 1212 return serializeDate(time); 1213 } 1214 1215 1225 1226 public static void serializeTime(int time, StringBuffer buff) 1227 throws JiBXException { 1228 1229 formatTwoDigits(time/MSPERHOUR, buff); 1231 time = time % MSPERHOUR; 1232 buff.append(':'); 1233 formatTwoDigits(time/MSPERMINUTE, buff); 1234 time = time % MSPERMINUTE; 1235 buff.append(':'); 1236 formatTwoDigits(time/1000, buff); 1237 time = time % 1000; 1238 1239 if (time > 0) { 1241 buff.append('.'); 1242 buff.append(time / 100); 1243 time = time % 100; 1244 if (time > 0) { 1245 buff.append(time / 10); 1246 time = time % 10; 1247 if (time > 0) { 1248 buff.append(time); 1249 } 1250 } 1251 } 1252 } 1253 1254 1264 1265 public static String serializeDateTime(long time, boolean zone) 1266 throws JiBXException { 1267 1268 StringBuffer buff = new StringBuffer (25); 1270 int extra = formatYearMonthDay(time + TIME_BASE, buff); 1271 1272 buff.append('T'); 1274 serializeTime(extra, buff); 1275 1276 if (zone) { 1278 buff.append('Z'); 1279 } 1280 return buff.toString(); 1281 } 1282 1283 1292 1293 public static String serializeDateTime(long time) throws JiBXException { 1294 return serializeDateTime(time, false); 1295 } 1296 1297 1306 1307 public static String serializeDateTime(Date date) throws JiBXException { 1308 return serializeDateTime(date.getTime(), false); 1309 } 1310 1311 1320 1321 public static String serializeTimestamp(Timestamp stamp) 1322 throws JiBXException { 1323 1324 int nano = stamp.getNanos(); 1326 if (nano > 0) { 1327 1328 String value = serializeInt(nano); 1330 1331 StringBuffer digits = new StringBuffer (9); 1333 if (value.length() < 9) { 1334 int lead = 9 - value.length(); 1335 for (int i = 0; i < lead; i++) { 1336 digits.append('0'); 1337 } 1338 } 1339 digits.append(value); 1340 1341 int last = 9; 1343 while (--last > 0) { 1344 if (digits.charAt(last) != '0') { 1345 break; 1346 } 1347 } 1348 digits.setLength(last); 1349 1350 return serializeDateTime(stamp.getTime(), false) + '.' + 1352 digits + 'Z'; 1353 1354 } else { 1355 return serializeDateTime(stamp.getTime(), true); 1356 } 1357 } 1358 1359 1369 1370 public static String serializeSqlTime(Time time) throws JiBXException { 1371 StringBuffer buff = new StringBuffer (12); 1372 serializeTime((int)time.getTime(), buff); 1373 return buff.toString(); 1374 } 1375 1376 1386 1387 public static boolean isEqual(Object a, Object b) { 1388 return (a == null) ? b == null : a.equals(b); 1389 } 1390 1391 1404 1405 public static int enumValue(String target, String [] enums, int[] vals) 1406 throws JiBXException { 1407 int base = 0; 1408 int limit = enums.length - 1; 1409 while (base <= limit) { 1410 int cur = (base + limit) >> 1; 1411 int diff = target.compareTo(enums[cur]); 1412 if (diff < 0) { 1413 limit = cur - 1; 1414 } else if (diff > 0) { 1415 base = cur + 1; 1416 } else if (vals != null) { 1417 return vals[cur]; 1418 } else { 1419 return cur; 1420 } 1421 } 1422 throw new JiBXException("Target value \"" + target + 1423 "\" not found in enumeration"); 1424 } 1425 1426 1439 1440 private static int decodeChunk(int base, char[] chrs, int fill, 1441 byte[] byts) throws JiBXException { 1442 1443 int length = 3; 1445 if (chrs[base+3] == PAD_CHAR) { 1446 length = 2; 1447 if (chrs[base+2] == PAD_CHAR) { 1448 length = 1; 1449 } 1450 } 1451 1452 int v0 = s_base64Values[chrs[base+0]]; 1454 int v1 = s_base64Values[chrs[base+1]]; 1455 int v2 = s_base64Values[chrs[base+2]]; 1456 int v3 = s_base64Values[chrs[base+3]]; 1457 1458 switch (length) { 1460 case 3: 1461 byts[fill+2] = (byte)(v2 << 6 | v3); 1462 case 2: 1463 byts[fill+1] = (byte)(v1 << 4 | v2 >> 2); 1464 case 1: 1465 byts[fill] = (byte)(v0 << 2 | v1 >> 4); 1466 break; 1467 } 1468 return length; 1469 } 1470 1471 1479 1480 public static byte[] parseBase64(String text) throws JiBXException { 1481 1482 char[] chrs = new char[text.length()]; 1484 int length = 0; 1485 for (int i = 0; i < text.length(); i++) { 1486 char chr = text.charAt(i); 1487 if (chr < 128 && s_base64Values[chr] >= 0) { 1488 chrs[length++] = chr; 1489 } 1490 } 1491 1492 if (length % 4 != 0) { 1494 throw new JiBXException 1495 ("Text length for base64 must be a multiple of 4"); 1496 } else if (length == 0) { 1497 return new byte[0]; 1498 } 1499 1500 int blength = length / 4 * 3; 1502 if (chrs[length-1] == PAD_CHAR) { 1503 blength--; 1504 if (chrs[length-2] == PAD_CHAR) { 1505 blength--; 1506 } 1507 } 1508 1509 byte[] byts = new byte[blength]; 1511 int fill = 0; 1512 for (int i = 0; i < length; i += 4) { 1513 fill += decodeChunk(i, chrs, fill, byts); 1514 } 1515 if (fill != blength) { 1516 throw new JiBXException 1517 ("Embedded padding characters in byte64 text"); 1518 } 1519 return byts; 1520 } 1521 1522 1530 1531 public static byte[] deserializeBase64(String text) throws JiBXException { 1532 if (text == null) { 1533 return null; 1534 } else { 1535 return parseBase64(text); 1536 } 1537 } 1538 1539 1548 1549 public static void encodeChunk(int base, byte[] byts, StringBuffer buff) { 1550 1551 int length = 3; 1553 if (base + length > byts.length) { 1554 length = byts.length - base; 1555 } 1556 1557 int b0 = byts[base]; 1559 int value = (b0 >> 2) & 0x3F; 1560 buff.append(s_base64Chars[value]); 1561 if (length > 1) { 1562 int b1 = byts[base+1]; 1563 value = ((b0 & 3) << 4) + ((b1 >> 4) & 0x0F); 1564 buff.append(s_base64Chars[value]); 1565 if (length > 2) { 1566 int b2 = byts[base+2]; 1567 value = ((b1 & 0x0F) << 2) + ((b2 >> 6) & 3); 1568 buff.append(s_base64Chars[value]); 1569 value = b2 & 0x3F; 1570 buff.append(s_base64Chars[value]); 1571 } else { 1572 value = (b1 & 0x0F) << 2; 1573 buff.append(s_base64Chars[value]); 1574 buff.append(PAD_CHAR); 1575 } 1576 } else { 1577 value = (b0 & 3) << 4; 1578 buff.append(s_base64Chars[value]); 1579 buff.append(PAD_CHAR); 1580 buff.append(PAD_CHAR); 1581 } 1582 } 1583 1584 1591 1592 public static String serializeBase64(byte[] byts) { 1593 StringBuffer buff = new StringBuffer ((byts.length + 2) / 3 * 4); 1594 for (int i = 0; i < byts.length; i += 3) { 1595 encodeChunk(i, byts, buff); 1596 if (i > 0 && i % 57 == 0 && (i + 3) < byts.length) { 1597 buff.append("\r\n"); 1598 } 1599 } 1600 return buff.toString(); 1601 } 1602 1603 1609 1610 public static List arrayListFactory() { 1611 return new ArrayList(); 1612 } 1613} 1614 | Popular Tags |