1 package javax.xml.bind; 2 3 import javax.xml.namespace.QName ; 4 import javax.xml.namespace.NamespaceContext ; 5 import javax.xml.datatype.DatatypeFactory ; 6 import javax.xml.datatype.DatatypeConfigurationException ; 7 import java.math.BigInteger ; 8 import java.math.BigDecimal ; 9 import java.util.Calendar ; 10 import java.util.GregorianCalendar ; 11 import java.util.TimeZone ; 12 13 29 final class DatatypeConverterImpl implements DatatypeConverterInterface { 30 31 34 public static final DatatypeConverterInterface theInstance = new DatatypeConverterImpl(); 35 36 protected DatatypeConverterImpl() { 37 } 38 39 public String parseString(String lexicalXSDString) { 40 return lexicalXSDString; 41 } 42 43 public BigInteger parseInteger(String lexicalXSDInteger) { 44 return _parseInteger(lexicalXSDInteger); 45 } 46 47 public static BigInteger _parseInteger(CharSequence s) { 48 return new BigInteger (removeOptionalPlus(WhiteSpaceProcessor.trim(s)).toString()); 49 } 50 51 public String printInteger(BigInteger val) { 52 return _printInteger(val); 53 } 54 55 public static String _printInteger(BigInteger val) { 56 return val.toString(); 57 } 58 59 public int parseInt(String s) { 60 return _parseInt(s); 61 } 62 63 73 public static int _parseInt(CharSequence s) { 74 int len = s.length(); 75 int sign = 1; 76 77 int r = 0; 78 79 for( int i=0; i<len; i++ ) { 80 char ch = s.charAt(i); 81 if(WhiteSpaceProcessor.isWhiteSpace(ch)) { 82 } else 84 if('0'<=ch && ch<='9') { 85 r = r*10 + (ch-'0'); 86 } else 87 if(ch=='-') { 88 sign = -1; 89 } else 90 if(ch=='+') { 91 } else 93 throw new NumberFormatException ("Not a number: "+s); 94 } 95 96 return r*sign; 97 } 98 99 public long parseLong(String lexicalXSLong) { 100 return _parseLong(lexicalXSLong); 101 } 102 103 public static long _parseLong(CharSequence s) { 104 return Long.valueOf(removeOptionalPlus(WhiteSpaceProcessor.trim(s)).toString()); 105 } 106 107 public short parseShort(String lexicalXSDShort) { 108 return _parseShort(lexicalXSDShort); 109 } 110 111 public static short _parseShort(CharSequence s) { 112 return (short)_parseInt(s); 113 } 114 115 public String printShort(short val) { 116 return _printShort(val); 117 } 118 119 public static String _printShort(short val) { 120 return String.valueOf(val); 121 } 122 123 public BigDecimal parseDecimal(String content) { 124 return _parseDecimal(content); 125 } 126 public static BigDecimal _parseDecimal(CharSequence content) { 127 content = WhiteSpaceProcessor.trim(content); 128 129 return new BigDecimal (content.toString()); 130 131 } 143 144 public float parseFloat(String lexicalXSDFloat) { 145 return _parseFloat(lexicalXSDFloat); 146 } 147 148 public static float _parseFloat( CharSequence _val ) { 149 String s = WhiteSpaceProcessor.trim(_val).toString(); 150 164 165 if(s.equals("NaN")) return Float.NaN; 166 if(s.equals("INF")) return Float.POSITIVE_INFINITY; 167 if(s.equals("-INF")) return Float.NEGATIVE_INFINITY; 168 169 if(s.length()==0 170 || !isDigitOrPeriodOrSign(s.charAt(0)) 171 || !isDigitOrPeriodOrSign(s.charAt(s.length()-1)) ) 172 throw new NumberFormatException (); 173 174 return Float.parseFloat(s); 176 } 177 178 public String printFloat(float v) { 179 return _printFloat(v); 180 } 181 182 public static String _printFloat(float v) { 183 if( v==Float.NaN ) return "NaN"; 184 if( v==Float.POSITIVE_INFINITY ) return "INF"; 185 if( v==Float.NEGATIVE_INFINITY ) return "-INF"; 186 return String.valueOf(v); 187 } 188 189 190 191 public double parseDouble(String lexicalXSDDouble) { 192 return _parseDouble(lexicalXSDDouble); 193 } 194 195 public static double _parseDouble( CharSequence _val ) { 196 String val = WhiteSpaceProcessor.trim(_val).toString(); 197 198 if(val.equals("NaN")) return Double.NaN; 199 if(val.equals("INF")) return Double.POSITIVE_INFINITY; 200 if(val.equals("-INF")) return Double.NEGATIVE_INFINITY; 201 202 if(val.length()==0 203 || !isDigitOrPeriodOrSign(val.charAt(0)) 204 || !isDigitOrPeriodOrSign(val.charAt(val.length()-1)) ) 205 throw new NumberFormatException (val); 206 207 208 return Double.parseDouble(val); 210 } 211 212 public boolean parseBoolean(String lexicalXSDBoolean) { 213 return _parseBoolean(lexicalXSDBoolean); 214 } 215 216 public static boolean _parseBoolean(CharSequence literal) { 217 int i=0; 218 int len = literal.length(); 219 char ch; 220 do { 221 ch = literal.charAt(i++); 222 } while(WhiteSpaceProcessor.isWhiteSpace(ch) && i<len); 223 224 226 if( ch=='t' || ch=='1' ) return true; 227 if( ch=='f' || ch=='0' ) return false; 228 return false; 229 } 230 231 public String printBoolean(boolean val) { 232 return val?"true":"false"; 233 } 234 public static String _printBoolean(boolean val) { 235 return val?"true":"false"; 236 } 237 238 public byte parseByte(String lexicalXSDByte) { 239 return _parseByte(lexicalXSDByte); 240 } 241 242 public static byte _parseByte(CharSequence literal) { 243 return (byte)_parseInt(literal); 244 } 245 246 public String printByte(byte val) { 247 return _printByte(val); 248 } 249 250 public static String _printByte(byte val) { 251 return String.valueOf(val); 252 } 253 254 public QName parseQName(String lexicalXSDQName, NamespaceContext nsc) { 255 return _parseQName(lexicalXSDQName,nsc); 256 } 257 258 261 public static QName _parseQName(CharSequence text, NamespaceContext nsc) { 262 int length = text.length(); 263 264 int start=0; 266 while(start<length && WhiteSpaceProcessor.isWhiteSpace(text.charAt(start))) 267 start++; 268 269 int end = length; 270 while(end>start && WhiteSpaceProcessor.isWhiteSpace(text.charAt(end-1))) 271 end--; 272 273 if(end==start) 274 throw new IllegalArgumentException ("input is empty"); 275 276 277 String uri; 278 String localPart; 279 String prefix; 280 281 int idx=start+1; while(idx<end && text.charAt(idx)!=':' ) 284 idx++; 285 286 if( idx==end ) { 287 uri = nsc.getNamespaceURI(""); 288 localPart = text.subSequence(start,end).toString(); 289 prefix = ""; 290 } else { 291 prefix = text.subSequence(start,idx).toString(); 293 localPart = text.subSequence(idx+1,end).toString(); 294 uri = nsc.getNamespaceURI(prefix); 295 if(uri==null || uri.length()==0) throw new IllegalArgumentException ("prefix "+prefix+" is not bound to a namespace"); 300 } 301 302 return new QName (uri,localPart,prefix); 303 } 304 305 public Calendar parseDateTime(String lexicalXSDDateTime) { 306 return _parseDateTime(lexicalXSDDateTime); 307 } 308 309 public static GregorianCalendar _parseDateTime(CharSequence s) { 310 String val = WhiteSpaceProcessor.trim(s).toString(); 311 return datatypeFactory.newXMLGregorianCalendar(val).toGregorianCalendar(); 312 } 313 314 public String printDateTime(Calendar val) { 315 return _printDateTime(val); 316 } 317 318 public static String _printDateTime(Calendar val) { 319 return CalendarFormatter.doFormat("%Y-%M-%DT%h:%m:%s%z",val); 320 } 321 322 public byte[] parseBase64Binary(String lexicalXSDBase64Binary) { 323 return _parseBase64Binary(lexicalXSDBase64Binary); 324 } 325 326 327 public byte[] parseHexBinary(String s) { 328 final int len = s.length(); 329 330 if( len%2 != 0 ) 332 throw new IllegalArgumentException ("hexBinary needs to be even-length: "+s); 333 334 byte[] out = new byte[len/2]; 335 336 for( int i=0; i<len; i+=2 ) { 337 int h = hexToBin(s.charAt(i )); 338 int l = hexToBin(s.charAt(i+1)); 339 if( h==-1 || l==-1 ) 340 throw new IllegalArgumentException ("contains illegal character for hexBinary: "+s); 341 342 out[i/2] = (byte)(h*16+l); 343 } 344 345 return out; 346 } 347 348 private static int hexToBin( char ch ) { 349 if( '0'<=ch && ch<='9' ) return ch-'0'; 350 if( 'A'<=ch && ch<='F' ) return ch-'A'+10; 351 if( 'a'<=ch && ch<='f' ) return ch-'a'+10; 352 return -1; 353 } 354 355 private static final char[] hexCode = "0123456789ABCDEF".toCharArray(); 356 357 public String printHexBinary(byte[] data) { 358 StringBuilder r = new StringBuilder (data.length*2); 359 for ( byte b : data) { 360 r.append(hexCode[(b >> 4) & 0xF]); 361 r.append(hexCode[(b & 0xF)]); 362 } 363 return r.toString(); 364 } 365 366 367 public long parseUnsignedInt(String lexicalXSDUnsignedInt) { 368 return _parseLong(lexicalXSDUnsignedInt); 369 } 370 371 public String printUnsignedInt(long val) { 372 return _printLong(val); 373 } 374 375 public int parseUnsignedShort(String lexicalXSDUnsignedShort) { 376 return _parseInt(lexicalXSDUnsignedShort); 377 } 378 379 public Calendar parseTime(String lexicalXSDTime) { 380 return datatypeFactory.newXMLGregorianCalendar(lexicalXSDTime).toGregorianCalendar(); 381 } 382 383 public String printTime(Calendar val) { 384 return CalendarFormatter.doFormat("%h:%m:%s%z",val); 385 } 386 387 public Calendar parseDate(String lexicalXSDDate) { 388 return datatypeFactory.newXMLGregorianCalendar(lexicalXSDDate).toGregorianCalendar(); 389 } 390 391 public String printDate(Calendar val) { 392 393 return CalendarFormatter.doFormat((new StringBuilder ("%Y-%M-%D").append("%z")).toString(),val); 394 } 395 396 public String parseAnySimpleType(String lexicalXSDAnySimpleType) { 397 return lexicalXSDAnySimpleType; 398 } 400 401 public String printString(String val) { 402 return val; 404 } 405 406 407 public String printInt(int val) { 408 return _printInt(val); 409 } 410 411 public static String _printInt(int val) { 412 return String.valueOf(val); 413 } 414 415 public String printLong(long val) { 416 return _printLong(val); 417 } 418 419 public static String _printLong(long val) { 420 return String.valueOf(val); 421 } 422 423 public String printDecimal(BigDecimal val) { 424 return _printDecimal(val); 425 } 426 427 public static String _printDecimal(BigDecimal val) { 428 return val.toPlainString(); 429 } 430 431 public String printDouble(double v) { 432 return _printDouble(v); 433 } 434 435 public static String _printDouble(double v) { 436 if( v==Double.NaN ) return "NaN"; 437 if( v==Double.POSITIVE_INFINITY ) return "INF"; 438 if( v==Double.NEGATIVE_INFINITY ) return "-INF"; 439 return String.valueOf(v); 440 } 441 442 public String printQName(QName val, NamespaceContext nsc) { 443 return _printQName(val,nsc); 444 } 445 446 public static String _printQName(QName val, NamespaceContext nsc) { 447 String qname; 449 String prefix = nsc.getPrefix( val.getNamespaceURI() ); 450 String localPart = val.getLocalPart(); 451 452 if( prefix == null || prefix.length()==0 ) { qname = localPart; 454 } else { 455 qname = prefix + ':' + localPart; 456 } 457 458 return qname; 459 } 460 461 public String printBase64Binary(byte[] val) { 462 return _printBase64Binary(val); 463 } 464 465 public String printUnsignedShort(int val) { 466 return String.valueOf(val); 467 } 468 469 public String printAnySimpleType(String val) { 470 return val; 471 } 472 473 474 479 public static String installHook( String s ) { 480 DatatypeConverter.setDatatypeConverter(theInstance); 481 return s; 482 } 483 484 485 486 487 490 private static final byte[] decodeMap = initDecodeMap(); 491 private static final byte PADDING = 127; 492 493 private static byte[] initDecodeMap() { 494 byte[] map = new byte[128]; 495 int i; 496 for( i=0; i<128; i++ ) map[i] = -1; 497 498 for( i='A'; i<='Z'; i++ ) map[i] = (byte)(i-'A'); 499 for( i='a'; i<='z'; i++ ) map[i] = (byte)(i-'a'+26); 500 for( i='0'; i<='9'; i++ ) map[i] = (byte)(i-'0'+52); 501 map['+'] = 62; 502 map['/'] = 63; 503 map['='] = PADDING; 504 505 return map; 506 } 507 508 528 private static int guessLength( String text ) { 529 final int len = text.length(); 530 531 int j=len-1; 533 for(; j>=0; j-- ) { 534 byte code = decodeMap[text.charAt(j)]; 535 if(code==PADDING) 536 continue; 537 if(code==-1) 538 return text.length()/4*3; 540 break; 541 } 542 543 j++; int padSize = len-j; 545 if(padSize >2) return text.length()/4*3; 547 548 return text.length()/4*3-padSize; 551 } 552 553 562 public static byte[] _parseBase64Binary(String text) { 563 final int buflen = guessLength(text); 564 final byte[] out = new byte[buflen]; 565 int o=0; 566 567 final int len = text.length(); 568 int i; 569 570 final byte[] quadruplet = new byte[4]; 571 int q=0; 572 573 for( i=0; i<len; i++ ) { 575 char ch = text.charAt(i); 576 byte v = decodeMap[ch]; 577 578 if( v!=-1 ) 579 quadruplet[q++] = v; 580 581 if(q==4) { 582 out[o++] = (byte)((quadruplet[0]<<2)|(quadruplet[1]>>4)); 584 if( quadruplet[2]!=PADDING ) 585 out[o++] = (byte)((quadruplet[1]<<4)|(quadruplet[2]>>2)); 586 if( quadruplet[3]!=PADDING ) 587 out[o++] = (byte)((quadruplet[2]<<6)|(quadruplet[3])); 588 q=0; 589 } 590 } 591 592 if(buflen==o) return out; 594 595 byte[] nb = new byte[o]; 597 System.arraycopy(out,0,nb,0,o); 598 return nb; 599 } 600 601 private static final char[] encodeMap = initEncodeMap(); 602 603 private static char[] initEncodeMap() { 604 char[] map = new char[64]; 605 int i; 606 for( i= 0; i<26; i++ ) map[i] = (char)('A'+i); 607 for( i=26; i<52; i++ ) map[i] = (char)('a'+(i-26)); 608 for( i=52; i<62; i++ ) map[i] = (char)('0'+(i-52)); 609 map[62] = '+'; 610 map[63] = '/'; 611 612 return map; 613 } 614 615 public static char encode( int i ) { 616 return encodeMap[i&0x3F]; 617 } 618 619 public static byte encodeByte( int i ) { 620 return (byte)encodeMap[i&0x3F]; 621 } 622 623 public static String _printBase64Binary(byte[] input) { 624 return _printBase64Binary(input, 0, input.length); 625 } 626 public static String _printBase64Binary(byte[] input, int offset, int len) { 627 char[] buf = new char[((len+2)/3)*4]; 628 int ptr = _printBase64Binary(input,offset,len,buf,0); 629 assert ptr==buf.length; 630 return new String (buf); 631 } 632 633 642 public static int _printBase64Binary(byte[] input, int offset, int len, char[] buf, int ptr) { 643 for( int i=offset; i<len; i+=3 ) { 644 switch( len-i ) { 645 case 1: 646 buf[ptr++] = encode(input[i]>>2); 647 buf[ptr++] = encode(((input[i])&0x3)<<4); 648 buf[ptr++] = '='; 649 buf[ptr++] = '='; 650 break; 651 case 2: 652 buf[ptr++] = encode(input[i]>>2); 653 buf[ptr++] = encode( 654 ((input[i]&0x3)<<4) | 655 ((input[i+1]>>4)&0xF)); 656 buf[ptr++] = encode((input[i+1]&0xF)<<2); 657 buf[ptr++] = '='; 658 break; 659 default: 660 buf[ptr++] = encode(input[i]>>2); 661 buf[ptr++] = encode( 662 ((input[i]&0x3)<<4) | 663 ((input[i+1]>>4)&0xF)); 664 buf[ptr++] = encode( 665 ((input[i+1]&0xF)<<2)| 666 ((input[i+2]>>6)&0x3)); 667 buf[ptr++] = encode(input[i+2]&0x3F); 668 break; 669 } 670 } 671 return ptr; 672 } 673 674 684 public static int _printBase64Binary(byte[] input, int offset, int len, byte[] out, int ptr) { 685 byte[] buf = out; 686 int max = len+offset; 687 for( int i=offset; i<max; i+=3 ) { 688 switch( max-i ) { 689 case 1: 690 buf[ptr++] = encodeByte(input[i]>>2); 691 buf[ptr++] = encodeByte(((input[i])&0x3)<<4); 692 buf[ptr++] = '='; 693 buf[ptr++] = '='; 694 break; 695 case 2: 696 buf[ptr++] = encodeByte(input[i]>>2); 697 buf[ptr++] = encodeByte( 698 ((input[i]&0x3)<<4) | 699 ((input[i+1]>>4)&0xF)); 700 buf[ptr++] = encodeByte((input[i+1]&0xF)<<2); 701 buf[ptr++] = '='; 702 break; 703 default: 704 buf[ptr++] = encodeByte(input[i]>>2); 705 buf[ptr++] = encodeByte( 706 ((input[i]&0x3)<<4) | 707 ((input[i+1]>>4)&0xF)); 708 buf[ptr++] = encodeByte( 709 ((input[i+1]&0xF)<<2)| 710 ((input[i+2]>>6)&0x3)); 711 buf[ptr++] = encodeByte(input[i+2]&0x3F); 712 break; 713 } 714 } 715 716 return ptr; 717 } 718 719 private static CharSequence removeOptionalPlus(CharSequence s) { 720 int len = s.length(); 721 722 if(len<=1 || s.charAt(0)!='+') return s; 723 724 s = s.subSequence(1,len); 725 char ch = s.charAt(0); 726 if('0'<=ch && ch<='9') return s; 727 if('.'==ch ) return s; 728 729 throw new NumberFormatException (); 730 } 731 732 private static boolean isDigitOrPeriodOrSign( char ch ) { 733 if( '0'<=ch && ch<='9' ) return true; 734 if( ch=='+' || ch=='-' || ch=='.' ) return true; 735 return false; 736 } 737 738 private static final DatatypeFactory datatypeFactory; 739 740 static { 741 try { 742 datatypeFactory = DatatypeFactory.newInstance(); 743 } catch (DatatypeConfigurationException e) { 744 throw new Error (e); 745 } 746 } 747 748 749 private static final class CalendarFormatter { 750 public static String doFormat( String format, Calendar cal ) throws IllegalArgumentException { 751 int fidx = 0; 752 int flen = format.length(); 753 StringBuilder buf = new StringBuilder (); 754 755 while(fidx<flen) { 756 char fch = format.charAt(fidx++); 757 758 if(fch!='%') { buf.append(fch); 760 continue; 761 } 762 763 switch (format.charAt(fidx++)) { 765 case 'Y' : formatYear(cal, buf); 767 break; 768 769 case 'M' : formatMonth(cal, buf); 771 break; 772 773 case 'D' : formatDays(cal, buf); 775 break; 776 777 case 'h' : formatHours(cal, buf); 779 break; 780 781 case 'm' : formatMinutes(cal, buf); 783 break; 784 785 case 's' : formatSeconds(cal, buf); 787 break; 788 789 case 'z' : formatTimeZone(cal,buf); 791 break; 792 793 default : 794 throw new InternalError (); 796 } 797 } 798 799 return buf.toString(); 800 } 801 802 803 private static void formatYear(Calendar cal, StringBuilder buf) { 804 int year = cal.get(Calendar.YEAR); 805 806 String s; 807 if (year <= 0) s = Integer.toString(1 - year); 809 else s = Integer.toString(year); 811 812 while (s.length() < 4) 813 s = '0' + s; 814 if (year <= 0) 815 s = '-' + s; 816 817 buf.append(s); 818 } 819 820 private static void formatMonth(Calendar cal, StringBuilder buf) { 821 formatTwoDigits(cal.get(Calendar.MONTH)+1,buf); 822 } 823 824 private static void formatDays(Calendar cal, StringBuilder buf) { 825 formatTwoDigits(cal.get(Calendar.DAY_OF_MONTH),buf); 826 } 827 828 private static void formatHours(Calendar cal, StringBuilder buf) { 829 formatTwoDigits(cal.get(Calendar.HOUR_OF_DAY),buf); 830 } 831 832 private static void formatMinutes(Calendar cal, StringBuilder buf) { 833 formatTwoDigits(cal.get(Calendar.MINUTE),buf); 834 } 835 836 private static void formatSeconds(Calendar cal, StringBuilder buf) { 837 formatTwoDigits(cal.get(Calendar.SECOND),buf); 838 if (cal.isSet(Calendar.MILLISECOND)) { int n = cal.get(Calendar.MILLISECOND); 840 if(n!=0) { 841 String ms = Integer.toString(n); 842 while (ms.length() < 3) 843 ms = '0' + ms; 845 buf.append('.'); 846 buf.append(ms); 847 } 848 } 849 } 850 851 852 private static void formatTimeZone(Calendar cal,StringBuilder buf) { 853 TimeZone tz = cal.getTimeZone(); 854 855 if (tz == null) return; 856 857 int offset; 859 if (tz.inDaylightTime(cal.getTime())) { 860 offset = tz.getRawOffset() + (tz.useDaylightTime()?3600000:0); 861 } else { 862 offset = tz.getRawOffset(); 863 } 864 865 if(offset==0) { 866 buf.append('Z'); 867 return; 868 } 869 870 if (offset >= 0) 871 buf.append('+'); 872 else { 873 buf.append('-'); 874 offset *= -1; 875 } 876 877 offset /= 60 * 1000; 879 formatTwoDigits(offset / 60, buf); 880 buf.append(':'); 881 formatTwoDigits(offset % 60, buf); 882 } 883 884 885 private static void formatTwoDigits(int n,StringBuilder buf) { 886 if (n < 10) buf.append('0'); 888 buf.append(n); 889 } 890 } 891 } 892 | Popular Tags |