1 9 package javolution.xml.stream; 10 11 import java.io.IOException ; 12 import java.io.InputStream ; 13 import java.io.InputStreamReader ; 14 import java.io.Reader ; 15 import java.io.UnsupportedEncodingException ; 16 17 import javolution.context.ObjectFactory; 18 import javolution.io.UTF8StreamReader; 19 import javolution.lang.Reusable; 20 import javolution.text.CharArray; 21 import javolution.xml.sax.Attributes; 22 import j2me.lang.CharSequence; 23 import j2me.lang.IllegalStateException; 24 import j2me.util.Map; 25 import j2mex.realtime.MemoryArea; 26 27 72 public final class XMLStreamReaderImpl implements XMLStreamReader, Reusable { 73 74 77 static final String [] NAMES_OF_EVENTS = new String [] { "UNDEFINED", 78 "START_ELEMENT", "END_ELEMENT", "PROCESSING_INSTRUCTIONS", 79 "CHARACTERS", "COMMENT", "SPACE", "START_DOCUMENT", "END_DOCUMENT", 80 "ENTITY_REFERENCE", "ATTRIBUTE", "DTD", "CDATA", "NAMESPACE", 81 "NOTATION_DECLARATION", "ENTITY_DECLARATION" }; 82 83 86 static final int READER_BUFFER_CAPACITY = 4096; 87 88 91 CharArray _prolog; 92 93 96 ObjectFactory _objectFactory; 97 98 101 private int _readIndex; 102 103 106 private int _readCount; 107 108 111 private char[] _data = new char[READER_BUFFER_CAPACITY * 2]; 112 113 116 private int _index; 117 118 121 private int _nesting; 122 123 126 private CharArray _qName; 127 128 131 private int _prefixSep; 132 133 136 private CharArray _attrQName; 137 138 141 private int _attrPrefixSep; 142 143 146 private CharArray _attrValue; 147 148 151 private int _eventType = START_DOCUMENT; 152 153 156 private boolean _isEmpty; 157 158 161 boolean _charactersPending = false; 162 163 166 private int _start; 167 168 171 private int _state = STATE_CHARACTERS; 172 173 176 private CharArray _text; 177 178 181 private Reader _reader; 182 183 186 private final char[] _readBuffer = new char[READER_BUFFER_CAPACITY]; 187 188 192 private int _startOffset; 194 197 private final LocationImpl _location = new LocationImpl(); 198 199 202 private final NamespacesImpl _namespaces = new NamespacesImpl(); 203 204 207 private final AttributesImpl _attributes = new AttributesImpl(_namespaces); 208 209 212 private CharArray[] _elemStack = new CharArray[16]; 213 214 217 private String _encoding; 218 219 222 private final EntitiesImpl _entities = new EntitiesImpl(); 223 224 227 private final UTF8StreamReader _utf8StreamReader = new UTF8StreamReader(); 228 229 232 public XMLStreamReaderImpl() { 233 } 234 235 241 public void setInput(InputStream in) throws XMLStreamException { 242 setInput(in, detectEncoding(in)); 243 CharArray prologEncoding = getCharacterEncodingScheme(); 244 245 if ((prologEncoding != null) && !prologEncoding.equals(_encoding) 247 && !(isUTF8(prologEncoding) && isUTF8(_encoding))) { 248 int startOffset = _readCount; 250 reset(); 251 _startOffset = startOffset; 252 setInput(in, prologEncoding.toString()); 253 } 254 } 255 256 private static boolean isUTF8(Object encoding) { 257 return encoding.equals("utf-8") || encoding.equals("UTF-8") 258 || encoding.equals("ASCII") || encoding.equals("utf8") 259 || encoding.equals("UTF8"); 260 } 261 262 268 public void setInput(InputStream in, String encoding) 269 throws XMLStreamException { 270 _encoding = encoding; 271 if (isUTF8(encoding)) { setInput(_utf8StreamReader.setInput(in)); 273 } else { 274 try { 275 setInput(new InputStreamReader (in, encoding)); 276 } catch (UnsupportedEncodingException e) { 277 throw new XMLStreamException(e); 278 } 279 } 280 } 281 282 291 public void setInput(Reader reader) throws XMLStreamException { 292 if (_reader != null) 293 throw new IllegalStateException ("Reader not closed or reset"); 294 _reader = reader; 295 try { int readCount = reader.read(_readBuffer, _startOffset, 297 _readBuffer.length - _startOffset); 298 _readCount = (readCount >= 0) ? readCount + _startOffset 299 : _startOffset; 300 if ((_readCount >= 5) && (_readBuffer[0] == '<') 301 && (_readBuffer[1] == '?') && (_readBuffer[2] == 'x') 302 && (_readBuffer[3] == 'm') && (_readBuffer[4] == 'l') 303 && (_readBuffer[5] == ' ')) { next(); _prolog = this.getPIData(); 306 _index = _prolog.offset() + _prolog.length(); _start = _index; _eventType = START_DOCUMENT; } 310 } catch (IOException e) { 311 throw new XMLStreamException(e); 312 } 313 } 314 315 321 public CharArray getQName() { 322 if ((_eventType != XMLStreamConstants.START_ELEMENT) 323 && (_eventType != XMLStreamConstants.END_ELEMENT)) 324 throw new IllegalStateException ( 325 "Not a start element or an end element"); 326 return _qName; 327 } 328 329 335 public Attributes getAttributes() { 336 if (_eventType != XMLStreamConstants.START_ELEMENT) 337 throw new IllegalStateException ("Not a start element"); 338 return _attributes; 339 } 340 341 358 public void setEntities(Map entities) { 359 _entities.setEntitiesMapping(entities); 360 } 361 362 367 public String toString() { 368 return "XMLStreamReader - State: " + NAMES_OF_EVENTS[_eventType] 369 + ", Location: " + _location.toString(); 370 } 371 372 public int next() throws XMLStreamException { 374 375 if (_eventType == START_ELEMENT) { 377 _attributes.reset(); 378 if (_isEmpty) { _isEmpty = false; 380 return _eventType = END_ELEMENT; 381 } 382 } else if (_eventType == END_ELEMENT) { 383 _namespaces.pop(); 384 CharArray startElem = _elemStack[_nesting--]; 385 _start = _index = startElem.offset(); 386 while (_seqs[--_seqsIndex] != startElem) { } 388 } 389 while (true) { 391 392 if ((_readIndex >= _readCount) && isEndOfStream()) 394 return _eventType; char c = _readBuffer[_readIndex++]; 396 if (c <= '&') 397 c = (c == '&') ? replaceEntity() 398 : (c < ' ') ? handleEndOfLine(c) : c; 399 _data[_index++] = c; 400 401 switch (_state) { 404 405 case STATE_CHARACTERS: 406 while (true) { 408 if (c == '<') { 409 int length = _index - _start - 1; 410 if (length > 0) { 411 if (_charactersPending) { 412 _text.setArray(_data, _text.offset(), _text 413 .length() 414 + length); } else { 416 _text = newSeq(_start, length); 417 _charactersPending = true; 418 } 419 _start = _index - 1; } 421 _state = STATE_MARKUP; 422 break; 423 } 424 425 if ((_readIndex >= _readCount) && isEndOfStream()) 427 return _eventType; 428 c = _readBuffer[_readIndex++]; 429 if (c <= '&') 430 c = (c == '&') ? replaceEntity() 431 : (c < ' ') ? handleEndOfLine(c) : c; 432 _data[_index++] = c; 433 } 434 break; 435 436 case STATE_CDATA: 437 while (true) { 439 if ((c == '>') && (_index - _start >= 3) 440 && (_data[_index - 2] == ']') 441 && (_data[_index - 3] == ']')) { 442 _index -= 3; 443 int length = _index - _start; 444 if (length > 0) { if (_charactersPending) { 446 _text.setArray(_data, _text.offset(), _text 447 .length() 448 + length); } else { 450 _text = newSeq(_start, length); 451 _charactersPending = true; 452 } 453 } 454 _start = _index; 455 _state = STATE_CHARACTERS; 456 break; 457 } 458 459 if (_readIndex >= _readCount) 461 reloadBuffer(); 462 c = _readBuffer[_readIndex++]; 463 if (c < ' ') 464 c = handleEndOfLine(c); 465 _data[_index++] = c; 466 } 467 break; 468 469 case STATE_DTD: 470 if (c == '>') { 471 _text = newSeq(_start, _index - _start); 472 _index = _start; _state = STATE_CHARACTERS; 474 return _eventType = DTD; 475 } else if (c == '[') { 476 _state = STATE_DTD_INTERNAL; 477 } 478 break; 479 480 case STATE_DTD_INTERNAL: 481 if (c == ']') { 482 _state = STATE_DTD; 483 } 484 break; 485 486 case STATE_MARKUP: if (_index - _start == 2) { 488 if (c == '/') { 489 _start = _index = _index - 2; 490 _state = STATE_CLOSE_TAGxREAD_ELEM_NAME; 491 _prefixSep = -1; 492 if (_charactersPending) { _charactersPending = false; 494 return _eventType = CHARACTERS; 495 } 496 } else if (c == '?') { 497 _start = _index = _index - 2; 498 _state = STATE_PI; 499 if (_charactersPending) { _charactersPending = false; 501 return _eventType = CHARACTERS; 502 } 503 } else if (c != '!') { _data[_start] = c; 505 _index = _start + 1; 506 _state = STATE_OPEN_TAGxREAD_ELEM_NAME; 507 _prefixSep = -1; 508 if (_charactersPending) { _charactersPending = false; 510 return _eventType = CHARACTERS; 511 } 512 } 513 } else if ((_index - _start == 4) && (_data[_start + 1] == '!') 514 && (_data[_start + 2] == '-') 515 && (_data[_start + 3] == '-')) { 516 _start = _index = _index - 4; _state = STATE_COMMENT; 518 if (_charactersPending) { _charactersPending = false; 520 return _eventType = CHARACTERS; 521 } 522 523 } else if ((_index - _start == 9) && (_data[_start + 1] == '!') 524 && (_data[_start + 2] == '[') 525 && (_data[_start + 3] == 'C') 526 && (_data[_start + 4] == 'D') 527 && (_data[_start + 5] == 'A') 528 && (_data[_start + 6] == 'T') 529 && (_data[_start + 7] == 'A') 530 && (_data[_start + 8] == '[')) { 531 _start = _index = _index - 9; _state = STATE_CDATA; 533 534 } else if ((_index - _start == 9) && (_data[_start + 1] == '!') 535 && (_data[_start + 2] == 'D') 536 && (_data[_start + 3] == 'O') 537 && (_data[_start + 4] == 'C') 538 && (_data[_start + 5] == 'T') 539 && (_data[_start + 6] == 'Y') 540 && (_data[_start + 7] == 'P') 541 && (_data[_start + 8] == 'E')) { 542 _state = STATE_DTD; 544 } else { 545 } 547 break; 548 549 case STATE_COMMENT: 550 while (true) { 552 if ((c == '>') && (_index - _start >= 3) 553 && (_data[_index - 2] == '-') 554 && (_data[_index - 3] == '-')) { 555 _index -= 3; _text = newSeq(_start, _index - _start); 557 _state = STATE_CHARACTERS; 558 _index = _start; return _eventType = COMMENT; 560 } 561 562 if (_readIndex >= _readCount) 564 reloadBuffer(); 565 c = _readBuffer[_readIndex++]; 566 if (c < ' ') 567 c = handleEndOfLine(c); 568 _data[_index++] = c; 569 } 570 571 case STATE_PI: 572 if ((c == '>') && (_index - _start >= 2) 573 && (_data[_index - 2] == '?')) { 574 _index -= 2; _text = newSeq(_start, _index - _start); 576 _state = STATE_CHARACTERS; 577 _index = _start; return _eventType = PROCESSING_INSTRUCTION; 579 } 580 break; 581 582 case STATE_OPEN_TAGxREAD_ELEM_NAME: 584 while (true) { 586 if (c < '@') { if (c == '>') { 588 _qName = newSeq(_start, --_index - _start); 589 _start = _index; 590 _state = STATE_CHARACTERS; 591 processStartTag(); 592 _isEmpty = false; 593 return _eventType = START_ELEMENT; 594 } else if (c == '/') { 595 _qName = newSeq(_start, --_index - _start); 596 _start = _index; 597 _state = STATE_OPEN_TAGxEMPTY_TAG; 598 break; 599 } else if (c == ':') { 600 _prefixSep = _index - 1; 601 } else if (c <= ' ') { 602 _qName = newSeq(_start, --_index - _start); 603 _state = STATE_OPEN_TAGxELEM_NAME_READ; 604 break; 605 } 606 } 607 608 if (_readIndex >= _readCount) 609 reloadBuffer(); 610 c = _data[_index++] = _readBuffer[_readIndex++]; 611 } 612 break; 613 614 case STATE_OPEN_TAGxELEM_NAME_READ: 615 if (c == '>') { 616 _start = --_index; 617 _state = STATE_CHARACTERS; 618 processStartTag(); 619 _isEmpty = false; 620 return _eventType = START_ELEMENT; 621 } else if (c == '/') { 622 _state = STATE_OPEN_TAGxEMPTY_TAG; 623 } else if (c > ' ') { 624 _start = _index - 1; _attrPrefixSep = -1; 626 _state = STATE_OPEN_TAGxREAD_ATTR_NAME; 627 } 628 break; 629 630 case STATE_OPEN_TAGxREAD_ATTR_NAME: 631 while (true) { 633 if (c < '@') { if (c <= ' ') { 635 _attrQName = newSeq(_start, --_index - _start); 636 _state = STATE_OPEN_TAGxATTR_NAME_READ; 637 break; 638 } else if (c == '=') { 639 _attrQName = newSeq(_start, --_index - _start); 640 _state = STATE_OPEN_TAGxEQUAL_READ; 641 break; 642 } else if (c == ':') { 643 _attrPrefixSep = _index - 1; 644 } 645 } 646 647 if (_readIndex >= _readCount) 648 reloadBuffer(); 649 _data[_index++] = c = _readBuffer[_readIndex++]; 650 } 651 break; 652 653 case STATE_OPEN_TAGxATTR_NAME_READ: 654 if (c == '=') { 655 --_index; 656 _state = STATE_OPEN_TAGxEQUAL_READ; 657 } else if (c > ' ') { 658 throw new XMLStreamException("'=' expected", _location); 659 } 660 break; 661 662 case STATE_OPEN_TAGxEQUAL_READ: 663 if (c == '\'') { 664 _start = --_index; 665 _state = STATE_OPEN_TAGxREAD_ATTR_VALUE_SIMPLE_QUOTE; 666 } else if (c == '\"') { 667 _start = --_index; 668 _state = STATE_OPEN_TAGxREAD_ATTR_VALUE_DOUBLE_QUOTE; 669 } else if (c > ' ') { 670 throw new XMLStreamException("Quotes expected", _location); 671 } 672 break; 673 674 case STATE_OPEN_TAGxREAD_ATTR_VALUE_SIMPLE_QUOTE: 675 while (true) { 677 if (c == '\'') { 678 _attrValue = newSeq(_start, --_index - _start); 679 processAttribute(); 680 _state = STATE_OPEN_TAGxELEM_NAME_READ; 681 break; 682 } 683 684 if (_readIndex >= _readCount) 686 reloadBuffer(); 687 c = _readBuffer[_readIndex++]; 688 if (c == '&') 689 c = replaceEntity(); 690 _data[_index++] = c; 691 } 692 break; 693 694 case STATE_OPEN_TAGxREAD_ATTR_VALUE_DOUBLE_QUOTE: 695 while (true) { 697 if (c == '\"') { 698 _attrValue = newSeq(_start, --_index - _start); 699 processAttribute(); 700 _state = STATE_OPEN_TAGxELEM_NAME_READ; 701 break; 702 } 703 704 if (_readIndex >= _readCount) 706 reloadBuffer(); 707 c = _readBuffer[_readIndex++]; 708 if (c == '&') 709 c = replaceEntity(); 710 _data[_index++] = c; 711 } 712 break; 713 714 case STATE_OPEN_TAGxEMPTY_TAG: 715 if (c == '>') { 716 _start = --_index; 717 _state = STATE_CHARACTERS; 718 processStartTag(); 719 _isEmpty = true; 720 return _eventType = START_ELEMENT; 721 } else { 722 throw new XMLStreamException("'>' expected", _location); 723 } 724 725 case STATE_CLOSE_TAGxREAD_ELEM_NAME: 727 while (true) { 729 if (c < '@') { if (c == '>') { 731 _qName = newSeq(_start, --_index - _start); 732 _start = _index; 733 _state = STATE_CHARACTERS; 734 processEndTag(); 735 return _eventType = END_ELEMENT; 736 } else if (c == ':') { 737 _prefixSep = _index - 1; 738 } else if (c <= ' ') { 739 _qName = newSeq(_start, --_index - _start); 740 _state = STATE_CLOSE_TAGxELEM_NAME_READ; 741 break; 742 } 743 } 744 745 if (_readIndex >= _readCount) 746 reloadBuffer(); 747 c = _data[_index++] = _readBuffer[_readIndex++]; 748 } 749 break; 750 751 case STATE_CLOSE_TAGxELEM_NAME_READ: 752 if (c == '>') { 753 _start = --_index; 754 _state = STATE_CHARACTERS; 755 processEndTag(); 756 return _eventType = END_ELEMENT; 757 } else if (c > ' ') { 758 throw new XMLStreamException("'>' expected", _location); 759 } 760 break; 761 762 default: 763 throw new XMLStreamException("State unknown: " + _state, 764 _location); 765 } 766 } 767 } 768 769 private static final int STATE_CHARACTERS = 1; 771 772 private static final int STATE_MARKUP = 2; 773 774 private static final int STATE_COMMENT = 3; 775 776 private static final int STATE_PI = 4; 777 778 private static final int STATE_CDATA = 5; 779 780 private static final int STATE_OPEN_TAGxREAD_ELEM_NAME = 6; 781 782 private static final int STATE_OPEN_TAGxELEM_NAME_READ = 7; 783 784 private static final int STATE_OPEN_TAGxREAD_ATTR_NAME = 8; 785 786 private static final int STATE_OPEN_TAGxATTR_NAME_READ = 9; 787 788 private static final int STATE_OPEN_TAGxEQUAL_READ = 10; 789 790 private static final int STATE_OPEN_TAGxREAD_ATTR_VALUE_SIMPLE_QUOTE = 11; 791 792 private static final int STATE_OPEN_TAGxREAD_ATTR_VALUE_DOUBLE_QUOTE = 12; 793 794 private static final int STATE_OPEN_TAGxEMPTY_TAG = 13; 795 796 private static final int STATE_CLOSE_TAGxREAD_ELEM_NAME = 14; 797 798 private static final int STATE_CLOSE_TAGxELEM_NAME_READ = 15; 799 800 private static final int STATE_DTD = 16; 801 802 private static final int STATE_DTD_INTERNAL = 17; 803 804 812 private void reloadBuffer() throws XMLStreamException { 813 _location._column += _readIndex; 814 _location._charactersRead += _readIndex; 815 _readIndex = 0; 816 try { 817 _readCount = _reader.read(_readBuffer, 0, _readBuffer.length); 818 if ((_readCount <= 0) 819 && ((_nesting != 0) || (_state != STATE_CHARACTERS))) 820 throw new XMLStreamException("Unexpected end of document", 821 _location); 822 } catch (IOException e) { 823 throw new XMLStreamException(e); 824 } 825 while ((_index + _readCount) >= _data.length) { increaseDataBuffer(); 827 } 828 } 829 830 837 private boolean isEndOfStream() throws XMLStreamException { 838 if (_readIndex >= _readCount) 839 reloadBuffer(); 840 if (_readCount <= 0) { 841 if (_eventType == END_DOCUMENT) 842 throw new XMLStreamException( 843 "End document has already been reached"); 844 int length = _index - _start - 1; 845 if ((_state == STATE_CHARACTERS) && (length > 0)) { if (_charactersPending) { 847 _text.setArray(_data, _text.offset(), _text.length() 848 + length); } else { 850 _text = newSeq(_start, length); 851 } 852 _eventType = CHARACTERS; 853 _state = STATE_CHARACTERS; 854 } else { 855 _eventType = END_DOCUMENT; 856 _state = STATE_CHARACTERS; 857 } 858 return true; 859 } 860 return false; 861 } 862 863 869 private char handleEndOfLine(char c) throws XMLStreamException { 870 if (c == 0xD) { if (_readIndex >= _readCount) 874 reloadBuffer(); 875 if ((_readIndex < _readCount) && (_readBuffer[_readIndex] == 0xA)) 876 _readIndex++; c = (char) 0xA; 878 } 879 if (c == 0xA) { 880 _location._line++; 881 _location._column = -_readIndex; } else if (c == 0x0) { 883 throw new XMLStreamException("Illegal XML character U+0000", 884 _location); 885 } 886 return c; 887 } 888 889 895 private char replaceEntity() throws XMLStreamException { 896 if ((_state == STATE_COMMENT) || (_state == STATE_PI) 897 || (_state == STATE_CDATA)) 898 return '&'; 900 int start = _index; _data[_index++] = '&'; 902 while (true) { 903 if (_readIndex >= _readCount) 904 reloadBuffer(); 905 char c = _data[_index++] = _readBuffer[_readIndex++]; 906 if (c == ';') 907 break; 908 if (c <= ' ') 909 throw new XMLStreamException("';' expected", _location); 910 } 911 while (start + _entities.getMaxLength() >= _data.length) 913 increaseDataBuffer(); 914 915 int length = _entities.replaceEntity(_data, start, _index - start); 917 918 _index = start + length; 920 921 if (_readIndex >= _readCount) 923 reloadBuffer(); 924 char c = _readBuffer[_readIndex++]; 925 return (c == '&') ? (c = replaceEntity()) : c; 926 } 927 928 931 private void processAttribute() throws XMLStreamException { 932 if (_attrPrefixSep < 0) { if (isXMLNS(_attrQName)) { _namespaces.setPrefix(_namespaces._defaultNsPrefix, _attrValue); 935 } else { 936 _attributes.addAttribute(_attrQName, null, _attrQName, 937 _attrValue); 938 } 939 } else { final int offset = _attrQName.offset(); 941 final int length = _attrQName.length(); 942 943 CharArray prefix = newSeq(offset, _attrPrefixSep - offset); 944 945 CharArray localName = newSeq(_attrPrefixSep + 1, offset + length 946 - _attrPrefixSep - 1); 947 948 if (isXMLNS(prefix)) { _namespaces.setPrefix(localName, _attrValue); 950 } else { 951 _attributes.addAttribute(localName, prefix, _attrQName, 952 _attrValue); 953 } 954 } 955 } 956 957 private static boolean isXMLNS(CharArray chars) { 958 return (chars.length() == 5) && (chars.charAt(0) == 'x') 959 && (chars.charAt(1) == 'm') && (chars.charAt(2) == 'l') 960 && (chars.charAt(3) == 'n') && (chars.charAt(4) == 's'); 961 } 962 963 private void processEndTag() throws XMLStreamException { 964 if (!_qName.equals(_elemStack[_nesting])) 965 throw new XMLStreamException("Unexpected end tag for " + _qName, 966 _location); 967 } 968 969 private void processStartTag() throws XMLStreamException { 970 if (++_nesting >= _elemStack.length) { 971 increaseStack(); 972 } 973 _elemStack[_nesting] = _qName; 974 _namespaces.push(); 975 } 976 977 public void reset() { 979 _attributes.reset(); 981 _attrPrefixSep = 0; 982 _attrQName = null; 983 _attrValue = null; 984 _attrQName = null; 985 _charactersPending = false; 986 _encoding = null; 987 _entities.reset(); 988 _eventType = START_DOCUMENT; 989 _index = 0; 990 _isEmpty = false; 991 _location.reset(); 992 _namespaces.reset(); 993 _objectFactory = null; 994 _prolog = null; 995 _readCount = 0; 996 _reader = null; 997 _nesting = 0; 998 _readIndex = 0; 999 _seqsIndex = 0; 1000 _start = 0; 1001 _startOffset = 0; 1002 _state = STATE_CHARACTERS; 1003 _utf8StreamReader.reset(); 1004 } 1005 1006 private CharArray newSeq(int offset, int length) { 1008 CharArray seq = (_seqsIndex < _seqsCapacity) ? _seqs[_seqsIndex++] 1009 : newSeq2(); 1010 return seq.setArray(_data, offset, length); 1011 } 1012 1013 private CharArray newSeq2() { 1014 MemoryArea.getMemoryArea(this).executeInArea(_createSeqLogic); 1015 return _seqs[_seqsIndex++]; 1016 } 1017 1018 private final Runnable _createSeqLogic = new Runnable () { 1019 public void run() { 1020 if (_seqsCapacity >= _seqs.length) { CharArray[] tmp = new CharArray[_seqs.length * 2]; 1022 System.arraycopy(_seqs, 0, tmp, 0, _seqs.length); 1023 _seqs = tmp; 1024 } 1025 CharArray seq = new CharArray(); 1026 _seqs[_seqsCapacity++] = seq; 1027 } 1028 }; 1029 1030 private CharArray[] _seqs = new CharArray[256]; 1031 1032 private int _seqsIndex; 1033 1034 private int _seqsCapacity; 1035 1036 private void increaseDataBuffer() { 1038 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 1044 public void run() { 1045 char[] tmp = new char[_data.length * 2]; 1046 javolution.context.LogContext.info(new CharArray( 1047 "XMLStreamReaderImpl: Data buffer increased to " 1048 + tmp.length)); 1049 System.arraycopy(_data, 0, tmp, 0, _data.length); 1050 _data = tmp; 1051 } 1052 }); 1053 } 1054 1055 private void increaseStack() { 1057 MemoryArea.getMemoryArea(this).executeInArea(new Runnable () { 1058 public void run() { 1059 CharArray[] tmp = new CharArray[_elemStack.length * 2]; 1060 javolution.context.LogContext.info(new CharArray( 1061 "XMLStreamReaderImpl: CharArray stack increased to " 1062 + tmp.length)); 1063 System.arraycopy(_elemStack, 0, tmp, 0, _elemStack.length); 1064 _elemStack = tmp; 1065 } 1066 }); 1067 } 1068 1069 1072 private final class LocationImpl implements Location, Reusable { 1073 1074 int _column; 1075 1076 int _line; 1077 1078 int _charactersRead; 1079 1080 public int getLineNumber() { 1081 return _line + 1; 1082 } 1083 1084 public int getColumnNumber() { 1085 return _column + _readIndex; 1086 } 1087 1088 public int getCharacterOffset() { 1089 return _charactersRead + _readIndex; 1090 } 1091 1092 public String getPublicId() { 1093 return null; } 1095 1096 public String getSystemId() { 1097 return null; } 1099 1100 public String toString() { 1101 return "Line " + getLineNumber() + ", Column " + getColumnNumber(); 1102 } 1103 1104 public void reset() { 1105 _line = 0; 1106 _column = 0; 1107 _charactersRead = 0; 1108 } 1109 } 1110 1111 1115 public void require(int type, CharSequence namespaceURI, 1117 CharSequence localName) throws XMLStreamException { 1118 if (_eventType != type) 1119 throw new XMLStreamException("Expected event: " 1120 + NAMES_OF_EVENTS[type] + ", found event: " 1121 + NAMES_OF_EVENTS[_eventType]); 1122 if ((namespaceURI != null) && !getNamespaceURI().equals(namespaceURI)) 1123 throw new XMLStreamException("Expected namespace URI: " 1124 + namespaceURI + ", found: " + getNamespaceURI()); 1125 if ((localName != null) && !getLocalName().equals(localName)) 1126 throw new XMLStreamException("Expected local name: " + localName 1127 + ", found: " + getLocalName()); 1128 } 1129 1130 public CharArray getElementText() throws XMLStreamException { 1132 if (getEventType() != XMLStreamConstants.START_ELEMENT) { 1134 throw new XMLStreamException( 1135 "Parser must be on START_ELEMENT to read next text", 1136 getLocation()); 1137 } 1138 CharArray text = null; 1139 int eventType = next(); 1140 while (eventType != XMLStreamConstants.END_ELEMENT) { 1141 if (eventType == XMLStreamConstants.CHARACTERS) { 1142 if (text == null) { 1143 text = getText(); 1144 } else { text.setArray(_data, text.offset(), text.length() 1146 + getText().length()); 1147 } 1148 } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 1149 || eventType == XMLStreamConstants.COMMENT) { 1150 } else if (eventType == XMLStreamConstants.END_DOCUMENT) { 1152 throw new XMLStreamException( 1153 "Unexpected end of document when reading element text content", 1154 getLocation()); 1155 } else if (eventType == XMLStreamConstants.START_ELEMENT) { 1156 throw new XMLStreamException( 1157 "Element text content may not contain START_ELEMENT", 1158 getLocation()); 1159 } else { 1160 throw new XMLStreamException("Unexpected event type " 1161 + NAMES_OF_EVENTS[eventType], getLocation()); 1162 } 1163 eventType = next(); 1164 } 1165 return (text != null) ? text : newSeq(0, 0); 1166 } 1167 1168 public Object getProperty(String name) throws IllegalArgumentException { 1170 if (name.equals(XMLInputFactory.IS_COALESCING)) { 1171 return new Boolean (true); 1172 } else if (name.equals(XMLInputFactory.ENTITIES)) { 1173 return _entities.getEntitiesMapping(); 1174 } else { 1175 throw new IllegalArgumentException ("Property: " + name 1176 + " not supported"); 1177 } 1178 } 1179 1180 public void close() throws XMLStreamException { 1182 if (_objectFactory != null) { 1183 _objectFactory.recycle(this); } else { 1185 reset(); 1186 } 1187 } 1188 1189 public int getAttributeCount() { 1190 if (_eventType != XMLStreamConstants.START_ELEMENT) 1191 throw illegalState("Not a start element"); 1192 return _attributes.getLength(); 1193 } 1194 1195 public CharArray getAttributeLocalName(int index) { 1196 if (_eventType != XMLStreamConstants.START_ELEMENT) 1197 throw illegalState("Not a start element"); 1198 return _attributes.getLocalName(index); 1199 } 1200 1201 public CharArray getAttributeNamespace(int index) { 1202 if (_eventType != XMLStreamConstants.START_ELEMENT) 1203 throw illegalState("Not a start element"); 1204 CharArray prefix = _attributes.getPrefix(index); 1205 return (prefix == null) ? null : _namespaces.getNamespaceURI(prefix); 1206 } 1207 1208 public CharArray getAttributePrefix(int index) { 1209 if (_eventType != XMLStreamConstants.START_ELEMENT) 1210 throw illegalState("Not a start element"); 1211 return _attributes.getPrefix(index); 1212 } 1213 1214 public CharArray getAttributeType(int index) { 1215 if (_eventType != XMLStreamConstants.START_ELEMENT) 1216 throw illegalState("Not a start element"); 1217 return _attributes.getType(index); 1218 } 1219 1220 public CharArray getAttributeValue(CharSequence uri, CharSequence localName) { 1221 if (_eventType != XMLStreamConstants.START_ELEMENT) 1222 throw illegalState("Not a start element"); 1223 return (uri == null) ? _attributes.getValue(localName) : _attributes 1224 .getValue(uri, localName); 1225 } 1226 1227 public CharArray getAttributeValue(int index) { 1228 if (_eventType != XMLStreamConstants.START_ELEMENT) 1229 throw illegalState("Not a start element"); 1230 return _attributes.getValue(index); 1231 } 1232 1233 public CharArray getCharacterEncodingScheme() { 1234 return readPrologAttribute(ENCODING); 1235 } 1236 1237 private static final CharArray ENCODING = new CharArray("encoding"); 1238 1239 public String getEncoding() { 1240 return _encoding; 1241 } 1242 1243 public int getEventType() { 1244 return _eventType; 1245 } 1246 1247 public CharArray getLocalName() { 1248 if ((_eventType != XMLStreamConstants.START_ELEMENT) 1249 && (_eventType != XMLStreamConstants.END_ELEMENT)) 1250 throw illegalState("Not a start or end element"); 1251 if (_prefixSep < 0) 1252 return _qName; 1253 CharArray localName = newSeq(_prefixSep + 1, _qName.offset() 1254 + _qName.length() - _prefixSep - 1); 1255 return localName; 1256 } 1257 1258 public Location getLocation() { 1259 return _location; 1260 } 1261 1262 public int getNamespaceCount() { 1263 if ((_eventType != XMLStreamConstants.START_ELEMENT) 1264 && (_eventType != XMLStreamConstants.END_ELEMENT)) 1265 throw illegalState("Not a start or end element"); 1266 return _namespaces._namespacesCount[_nesting]; 1267 } 1268 1269 public CharArray getNamespacePrefix(int index) { 1270 if ((_eventType != XMLStreamConstants.START_ELEMENT) 1271 && (_eventType != XMLStreamConstants.END_ELEMENT)) 1272 throw illegalState("Not a start or end element"); 1273 return _namespaces._prefixes[index]; 1274 } 1275 1276 public CharArray getNamespaceURI(CharSequence prefix) { 1277 if ((_eventType != XMLStreamConstants.START_ELEMENT) 1278 && (_eventType != XMLStreamConstants.END_ELEMENT)) 1279 throw illegalState("Not a start or end element"); 1280 return _namespaces.getNamespaceURI(prefix); 1281 } 1282 1283 public CharArray getNamespaceURI(int index) { 1284 if ((_eventType != XMLStreamConstants.START_ELEMENT) 1285 && (_eventType != XMLStreamConstants.END_ELEMENT)) 1286 throw illegalState("Not a start or end element"); 1287 return _namespaces._namespaces[index]; 1288 } 1289 1290 public NamespaceContext getNamespaceContext() { 1291 return _namespaces; 1292 } 1293 1294 public CharArray getNamespaceURI() { 1295 if ((_eventType != XMLStreamConstants.START_ELEMENT) 1296 && (_eventType != XMLStreamConstants.END_ELEMENT)) 1297 throw illegalState("Not a start or end element"); 1298 CharArray prefix = getPrefix(); 1299 return (prefix != null) ? getNamespaceURI(prefix) : null; 1300 } 1301 1302 public CharArray getPrefix() { 1303 if ((_eventType != XMLStreamConstants.START_ELEMENT) 1304 && (_eventType != XMLStreamConstants.END_ELEMENT)) 1305 throw illegalState("Not a start or end element"); 1306 if (_prefixSep < 0) 1307 return null; 1308 int offset = _qName.offset(); 1309 CharArray prefix = newSeq(offset, _prefixSep - offset); 1310 return prefix; 1311 } 1312 1313 public CharArray getPIData() { 1314 if (_eventType != XMLStreamConstants.PROCESSING_INSTRUCTION) 1315 throw illegalState("Not a processing instruction"); 1316 int offset = _text.offsetOf(' ') + 1; 1317 CharArray piData = newSeq(offset, _text.length() - offset); 1318 return piData; 1319 } 1320 1321 public CharArray getPITarget() { 1322 if (_eventType != XMLStreamConstants.PROCESSING_INSTRUCTION) 1323 throw illegalState("Not a processing instruction"); 1324 CharArray piTarget = newSeq(_text.offset(), _text.offsetOf(' ')); 1325 return piTarget; 1326 } 1327 1328 public CharArray getText() { 1329 if ((_eventType != XMLStreamConstants.CHARACTERS) 1330 && (_eventType != XMLStreamConstants.COMMENT) 1331 && (_eventType != XMLStreamConstants.DTD)) 1332 throw illegalState("Not a text event"); 1333 return _text; 1334 } 1335 1336 public char[] getTextCharacters() { 1337 return getText().array(); 1338 } 1339 1340 public int getTextCharacters(int sourceStart, char[] target, 1341 int targetStart, int length) throws XMLStreamException { 1342 CharArray text = getText(); 1343 int copyLength = Math.min(length, text.length()); 1344 System.arraycopy(text.array(), sourceStart + text.offset(), target, 1345 targetStart, copyLength); 1346 return copyLength; 1347 } 1348 1349 public int getTextLength() { 1350 return getText().length(); 1351 } 1352 1353 public int getTextStart() { 1354 return getText().offset(); 1355 } 1356 1357 public CharArray getVersion() { 1358 return readPrologAttribute(VERSION); 1359 } 1360 1361 private static final CharArray VERSION = new CharArray("version"); 1362 1363 public boolean isStandalone() { 1364 CharArray standalone = readPrologAttribute(STANDALONE); 1365 return (standalone != null) ? standalone.equals("no") : true; 1366 } 1367 1368 public boolean standaloneSet() { 1369 return readPrologAttribute(STANDALONE) != null; 1370 } 1371 1372 private static final CharArray STANDALONE = new CharArray("standalone"); 1373 1374 public boolean hasName() { 1375 return (_eventType == XMLStreamConstants.START_ELEMENT) 1376 || (_eventType == XMLStreamConstants.END_ELEMENT); 1377 } 1378 1379 public boolean hasNext() throws XMLStreamException { 1380 return _eventType != XMLStreamConstants.END_DOCUMENT; 1381 } 1382 1383 public boolean hasText() { 1384 return ((_eventType == XMLStreamConstants.CHARACTERS) 1385 || (_eventType == XMLStreamConstants.COMMENT) || (_eventType == XMLStreamConstants.DTD)) 1386 && (_text.length() > 0); 1387 } 1388 1389 public boolean isAttributeSpecified(int index) { 1390 if (_eventType != XMLStreamConstants.START_ELEMENT) 1391 throw new IllegalStateException ("Not a start element"); 1392 return _attributes.getValue(index) != null; 1393 } 1394 1395 public boolean isCharacters() { 1396 return _eventType == XMLStreamConstants.CHARACTERS; 1397 } 1398 1399 public boolean isEndElement() { 1400 return _eventType == XMLStreamConstants.END_ELEMENT; 1401 } 1402 1403 public boolean isStartElement() { 1404 return _eventType == XMLStreamConstants.START_ELEMENT; 1405 } 1406 1407 public boolean isWhiteSpace() { 1408 if (isCharacters()) { 1409 char[] chars = _text.array(); 1410 for (int i = _text.offset(), end = _text.offset() + _text.length(); i < end;) { 1411 if (!isWhiteSpace(chars[i++])) 1412 return false; 1413 } 1414 return true; 1415 } 1416 return false; 1417 } 1418 1419 private static boolean isWhiteSpace(char c) { 1421 return (c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA); 1422 } 1423 1424 public int nextTag() throws XMLStreamException { 1425 int eventType = next(); 1426 while (eventType == XMLStreamConstants.COMMENT 1427 || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 1428 || (eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace())) { 1429 eventType = next(); 1430 } 1431 if (eventType != XMLStreamConstants.START_ELEMENT 1432 && eventType != XMLStreamConstants.END_ELEMENT) 1433 throw new XMLStreamException("Tag expected (but found " 1434 + NAMES_OF_EVENTS[_eventType] + ")"); 1435 return eventType; 1436 } 1437 1438 private IllegalStateException illegalState(String msg) { 1439 return new IllegalStateException (msg + " (" 1440 + NAMES_OF_EVENTS[_eventType] + ")"); 1441 } 1442 1443 private String detectEncoding(InputStream input) throws XMLStreamException { 1444 int byte0; 1446 try { 1447 byte0 = input.read(); 1448 } catch (IOException e) { 1449 throw new XMLStreamException(e); 1450 } 1451 if (byte0 == -1) 1452 throw new XMLStreamException("Premature End-Of-File"); 1453 if (byte0 == '<') { _readBuffer[_startOffset++] = '<'; 1455 return "UTF-8"; 1456 } else { 1457 int byte1; 1458 try { 1459 byte1 = input.read(); 1460 } catch (IOException e) { 1461 throw new XMLStreamException(e); 1462 } 1463 if (byte1 == -1) 1464 throw new XMLStreamException("Premature End-Of-File"); 1465 if ((byte0 == 0) && (byte1 == '<')) { _readBuffer[_startOffset++] = '<'; 1467 return "UTF-16BE"; 1468 } else if ((byte0 == '<') && (byte1 == 0)) { _readBuffer[_startOffset++] = '<'; 1470 return "UTF-16LE"; 1471 } else if ((byte0 == 0xFF) && (byte1 == 0xFE)) { return "UTF-16"; 1473 } else if ((byte0 == 0xFE) && (byte1 == 0xFF)) { return "UTF-16"; 1475 } else { _readBuffer[_startOffset++] = (char) byte0; 1477 _readBuffer[_startOffset++] = (char) byte1; 1478 return "UTF-8"; 1479 } 1480 } 1481 } 1482 1483 private final CharArray readPrologAttribute(CharSequence name) { 1484 if (_prolog == null) 1485 return null; 1486 final int READ_EQUAL = 0; 1487 final int READ_QUOTE = 1; 1488 final int VALUE_SIMPLE_QUOTE = 2; 1489 final int VALUE_DOUBLE_QUOTE = 3; 1490 1491 int i = _prolog.offsetOf(name); 1492 if (i >= 0) { 1493 int maxIndex = _prolog.offset() + _prolog.length(); 1494 i += name.length(); 1495 int state = READ_EQUAL; 1496 int valueOffset = 0; 1497 while (i < maxIndex) { 1498 char c = _prolog.array()[i++]; 1499 switch (state) { 1500 case READ_EQUAL: 1501 if (c == '=') { 1502 state = READ_QUOTE; 1503 } 1504 break; 1505 case READ_QUOTE: 1506 if (c == '"') { 1507 state = VALUE_DOUBLE_QUOTE; 1508 valueOffset = i; 1509 } else if (c == '\'') { 1510 state = VALUE_SIMPLE_QUOTE; 1511 valueOffset = i; 1512 } 1513 break; 1514 case VALUE_SIMPLE_QUOTE: 1515 if (c == '\'') 1516 return newSeq(valueOffset, i - valueOffset - 1); 1517 break; 1518 case VALUE_DOUBLE_QUOTE: 1519 if (c == '"') 1520 return newSeq(valueOffset, i - valueOffset - 1); 1521 break; 1522 } 1523 } 1524 } 1525 return null; 1526 } 1527} | Popular Tags |