8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.org.apache.xerces.internal.impl; 27 28 import com.sun.xml.internal.stream.Entity; 29 import com.sun.xml.internal.stream.StaxErrorReporter; 30 import com.sun.xml.internal.stream.XMLEntityStorage; 31 import com.sun.xml.internal.stream.events.EntityDeclarationImpl; 32 import com.sun.xml.internal.stream.events.NotationDeclarationImpl; 33 import javax.xml.namespace.NamespaceContext; 34 import com.sun.org.apache.xerces.internal.xni.XNIException; 35 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 36 import javax.xml.XMLConstants; 37 import javax.xml.namespace.QName; 38 import javax.xml.stream.Location; 39 import javax.xml.stream.events.XMLEvent; 40 import com.sun.org.apache.xerces.internal.util.NamespaceContextWrapper; 41 import com.sun.org.apache.xerces.internal.util.SymbolTable; 42 import com.sun.xml.internal.stream.dtd.nonvalidating.XMLNotationDecl; 43 import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; 44 import java.io.BufferedInputStream; 45 import java.io.BufferedReader; 46 import java.io.IOException; 47 import java.io.InputStream; 48 import java.io.Reader; 49 import java.util.ArrayList; 50 import java.util.Enumeration; 51 import java.util.Iterator; 52 import java.util.List; 53 import javax.xml.stream.XMLInputFactory; 54 import javax.xml.stream.XMLStreamConstants; 55 import javax.xml.stream.XMLStreamException; 56 import com.sun.org.apache.xerces.internal.util.XMLChar; 57 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; 58 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 59 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; 60 61 /** This class implements javax.xml.stream.XMLStreamReader. It makes use of XML*Scanner classes to 62 * derive most of its functionality. If desired, Application can reuse this instance by calling 63 * reset() and setInputSource(). 64 * 65 * @author Neeraj Bajaj Sun Microsystems,Inc. 66 * @author K.Venugopal Sun Microsystems,Inc. 67 * @author Sunitha Reddy Sun Microsystems,Inc. 68 */ 69 public class XMLStreamReaderImpl implements javax.xml.stream.XMLStreamReader { 70 71 /** Property identifier: entity manager. */ 72 protected static final String ENTITY_MANAGER = 73 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; 74 75 /** Property identifier: Error Reporter. */ 76 protected static final String ERROR_REPORTER = 77 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 78 79 /** Property identifier: Symbol table. */ 80 protected static final String SYMBOL_TABLE = 81 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 82 83 protected static final String READER_IN_DEFINED_STATE = 84 Constants.READER_IN_DEFINED_STATE; 85 86 private SymbolTable fSymbolTable = new SymbolTable(); 87 88 /** Document scanner. */ 89 protected XMLDocumentScannerImpl fScanner = new XMLNSDocumentScannerImpl(); 90 91 //make Global NamespaceContextWrapper object, fScanner.getNamespaceContext() is dynamic object and ita value changes 92 //as per the state of the parser. 93 protected NamespaceContextWrapper fNamespaceContextWrapper = new NamespaceContextWrapper((NamespaceSupport)fScanner.getNamespaceContext()) ; 94 protected XMLEntityManager fEntityManager = new XMLEntityManager(); 95 protected StaxErrorReporter fErrorReporter = new StaxErrorReporter(); 96 97 98 /** Entity scanner, this alwasy works on last entity that was opened. */ 99 protected XMLEntityScanner fEntityScanner = null; 100 101 /** Input Source */ 102 protected XMLInputSource fInputSource = null; 103 /** Store properties*/ 104 protected PropertyManager fPropertyManager = null ; 105 106 /** current event type */ 107 private int fEventType ; 108 /** debug flag*/ 109 static final boolean DEBUG = false ; 110 /** more to scan */ 111 private boolean fReuse = true; 112 private boolean fReaderInDefinedState = true ; 113 private boolean fBindNamespaces = true; 114 private String fDTDDecl = null; 115 private String versionStr = null; 116 117 /** 118 * @param inputStream 119 * @param props 120 * @throws XMLStreamException 121 */ 122 public XMLStreamReaderImpl(InputStream inputStream, PropertyManager props) throws XMLStreamException { 123 init(props); 124 //publicId, systemid, baseSystemId, inputStream, enocding 125 XMLInputSource inputSource = new XMLInputSource(null,null,null,inputStream,null); 126 //pass the input source to document scanner impl. 127 setInputSource(inputSource); 128 } 129 130 public XMLDocumentScannerImpl getScanner(){ 131 System.out.println("returning scanner"); 132 return fScanner; 133 } 134 /** 135 * @param systemid 136 * @param props 137 * @throws XMLStreamException 138 */ 139 public XMLStreamReaderImpl(String systemid, PropertyManager props) throws XMLStreamException { 140 init(props); 141 //publicId, systemid, baseSystemId, inputStream, enocding 142 XMLInputSource inputSource = new XMLInputSource(null, systemid, null, false); 143 //pass the input source to document scanner impl. 144 setInputSource(inputSource); 145 } 146 147 148 /** 149 * @param inputStream 150 * @param encoding 151 * @param props 152 * @throws XMLStreamException 153 */ 154 public XMLStreamReaderImpl(InputStream inputStream, String encoding, PropertyManager props ) throws XMLStreamException { 155 init(props); 156 //publicId, systemid, baseSystemId, inputStream, enocding 157 XMLInputSource inputSource = new XMLInputSource(null,null,null, new BufferedInputStream(inputStream),encoding ); 158 //pass the input source to document scanner impl. 159 setInputSource(inputSource); 160 } 161 162 /** 163 * @param reader 164 * @param props 165 * @throws XMLStreamException 166 */ 167 public XMLStreamReaderImpl(Reader reader, PropertyManager props) throws XMLStreamException { 168 init(props); 169 //publicId, systemid, baseSystemId, inputStream, enocding 170 //xxx: Using buffered reader 171 XMLInputSource inputSource = new XMLInputSource(null,null,null,new BufferedReader(reader),null); 172 //pass the input source to document scanner impl. 173 setInputSource(inputSource); 174 } 175 176 /** 177 * @param inputSource 178 * @param props 179 * @throws XMLStreamException 180 */ 181 public XMLStreamReaderImpl(XMLInputSource inputSource, PropertyManager props) throws XMLStreamException { 182 init(props); 183 //pass the input source to document scanner impl. 184 setInputSource(inputSource); 185 } 186 187 /** 188 * @param inputSource 189 * @throws XMLStreamException 190 */ 191 public void setInputSource(XMLInputSource inputSource ) throws XMLStreamException { 192 //once setInputSource() is called this instance is busy parsing the inputsource supplied 193 //this instances is free for reuse if parser has reached END_DOCUMENT state or application has 194 //called close() 195 fReuse = false; 196 197 try{ 198 199 fScanner.setInputSource(inputSource) ; 200 //XMLStreamReader should be in defined state 201 if(fReaderInDefinedState){ 202 fEventType = fScanner.next(); 203 if (versionStr == null) 204 versionStr = getVersion(); 205 206 if (fEventType == XMLStreamConstants.START_DOCUMENT && versionStr != null && versionStr.equals("1.1")){ 207 switchToXML11Scanner(); 208 } 209 210 } 211 }catch(java.io.IOException ex){ 212 throw new XMLStreamException(ex); 213 } catch(XNIException ex){ //Issue 56 XNIException not caught 214 throw new XMLStreamException(ex.getMessage(), getLocation(), ex.getException()); 215 } 216 }//setInputSource 217 218 void init(PropertyManager propertyManager) throws XMLStreamException { 219 fPropertyManager = propertyManager; 220 //set Stax internal properties -- Note that these instances are being created in XMLReaderImpl. 221 //1.SymbolTable 222 //2.XMLMessageFormatter 223 //3.XMLEntityManager 224 //4. call reset() 225 //1. 226 propertyManager.setProperty(SYMBOL_TABLE, fSymbolTable ) ; 227 //2. 228 propertyManager.setProperty(ERROR_REPORTER, fErrorReporter ) ; 229 //3. 230 propertyManager.setProperty(ENTITY_MANAGER, fEntityManager); 231 //4. 232 reset(); 233 } 234 235 /** This function tells if this instances is available for reuse. 236 * One must call reset() and setInputSource() to be able to reuse 237 * this instance. 238 */ 239 public boolean canReuse(){ 240 if(DEBUG){ 241 System.out.println("fReuse = " + fReuse); 242 System.out.println("fEventType = " + getEventTypeString(fEventType) ); 243 } 244 //when parsing begins, fReuse is set to false 245 //fReuse is set to 'true' when application calls close() 246 return fReuse; 247 } 248 249 /** 250 * Resets this instance so that this instance is ready for reuse. 251 */ 252 public void reset(){ 253 fReuse = true; 254 fEventType = 0 ; 255 //reset entity manager 256 fEntityManager.reset(fPropertyManager); 257 //reset the scanner 258 fScanner.reset(fPropertyManager); 259 //REVISIT:this is too ugly -- we are getting XMLEntityManager and XMLEntityReader from 260 //property manager, it should be only XMLEntityManager 261 fDTDDecl = null; 262 fEntityScanner = (XMLEntityScanner)fEntityManager.getEntityScanner() ; 263 //default value for this property is true. However, this should be false when using XMLEventReader... Ugh.. 264 //because XMLEventReader should not have defined state. 265 fReaderInDefinedState = ((Boolean)fPropertyManager.getProperty(READER_IN_DEFINED_STATE)).booleanValue(); 266 fBindNamespaces = ((Boolean)fPropertyManager.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue(); 267 versionStr = null; 268 } 269 270 271 /** Frees any resources associated with this Reader. This method does not close the underlying input source. 272 * @throws XMLStreamException if there are errors freeing associated resources 273 */ 274 public void close() throws XMLStreamException { 275 //xxx: Check what this function is intended to do. 276 //reset(); 277 fReuse = true ; 278 } 279 280 281 /** Returns the character encoding declared on the xml declaration Returns null if none was declared 282 * @return the encoding declared in the document or null 283 */ 284 public String getCharacterEncodingScheme() { 285 return fScanner.getCharacterEncodingScheme(); 286 287 } 288 289 290 /** 291 * @return 292 */ 293 public int getColumnNumber() { 294 return fEntityScanner.getColumnNumber(); 295 }//getColumnNumber 296 297 /** Return input encoding if known or null if unknown. 298 * @return the encoding of this instance or null 299 */ 300 public String getEncoding() { 301 return fEntityScanner.getEncoding(); 302 }//getEncoding 303 304 /** Returns the current value of the parse event as a string, this returns the string value of a CHARACTERS event, returns the value of a COMMENT, the replacement value for an ENTITY_REFERENCE, the string value of a CDATA section, the string value for a SPACE event, or the String value of the internal subset of the DTD. If an ENTITY_REFERENCE has been resolved, any character data will be reported as CHARACTERS events. 305 * @return the current text or null 306 */ 307 public int getEventType() { 308 return fEventType ; 309 }//getEventType 310 311 /** 312 * @return 313 */ 314 public int getLineNumber() { 315 return fEntityScanner.getLineNumber() ; 316 }//getLineNumber 317 318 public String getLocalName() { 319 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT){ 320 //xxx check whats the value of fCurrentElement 321 return fScanner.getElementQName().localpart ; 322 } 323 else if(fEventType == XMLEvent.ENTITY_REFERENCE){ 324 return fScanner.getEntityName(); 325 } 326 throw new IllegalStateException("Method getLocalName() cannot be called for " + 327 getEventTypeString(fEventType) + " event."); 328 }//getLocalName() 329 330 /** 331 * @return 332 */ 333 public String getNamespaceURI() { 334 //doesn't take care of Attribute as separte event 335 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT){ 336 return fScanner.getElementQName().uri ; 337 } 338 return null ; 339 }//getNamespaceURI 340 341 /** Get the data section of a processing instruction 342 * @return the data or null 343 */ 344 345 public String getPIData() { 346 if( fEventType == XMLEvent.PROCESSING_INSTRUCTION){ 347 return fScanner.getPIData().toString(); 348 } 349 else throw new java.lang.IllegalStateException("Current state of the parser is " + getEventTypeString(fEventType) + 350 " But Expected state is " + XMLEvent.PROCESSING_INSTRUCTION ) ; 351 }//getPIData 352 353 354 /** Get the target of a processing instruction 355 * @return the target or null 356 */ 357 public String getPITarget() { 358 if( fEventType == XMLEvent.PROCESSING_INSTRUCTION){ 359 return fScanner.getPITarget(); 360 } 361 else throw new java.lang.IllegalStateException("Current state of the parser is " + getEventTypeString(fEventType) + 362 " But Expected state is " + XMLEvent.PROCESSING_INSTRUCTION ) ; 363 364 }//getPITarget 365 366 367 /** 368 * @return the prefix of the current event, or null if the event does 369 * not have a prefix. For START_ELEMENT and END_ELEMENT, return 370 * XMLConstants.DEFAULT_NS_PREFIX when no prefix is available. 371 */ 372 public String getPrefix() { 373 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT){ 374 String prefix = fScanner.getElementQName().prefix; 375 return prefix == null ? XMLConstants.DEFAULT_NS_PREFIX : prefix; 376 } 377 return null ; 378 }//getPrefix() 379 380 381 382 /** 383 * @return 384 */ 385 public char[] getTextCharacters() { 386 if( fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 387 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE){ 388 return fScanner.getCharacterData().ch; 389 } else{ 390 throw new IllegalStateException("Current state = " + getEventTypeString(fEventType) 391 + " is not among the states " + getEventTypeString(XMLEvent.CHARACTERS) + " , " 392 + getEventTypeString(XMLEvent.COMMENT) + " , " + getEventTypeString(XMLEvent.CDATA) 393 + " , " + getEventTypeString(XMLEvent.SPACE) +" valid for getTextCharacters() " ) ; 394 } 395 } 396 397 /** 398 * @return 399 */ 400 public int getTextLength() { 401 if( fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 402 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE){ 403 return fScanner.getCharacterData().length; 404 } else{ 405 throw new IllegalStateException("Current state = " + getEventTypeString(fEventType) 406 + " is not among the states " + getEventTypeString(XMLEvent.CHARACTERS) + " , " 407 + getEventTypeString(XMLEvent.COMMENT) + " , " + getEventTypeString(XMLEvent.CDATA) 408 + " , " + getEventTypeString(XMLEvent.SPACE) +" valid for getTextLength() " ) ; 409 } 410 411 } 412 413 /** 414 * @return 415 */ 416 public int getTextStart() { 417 if( fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE){ 418 return fScanner.getCharacterData().offset; 419 } else{ 420 throw new IllegalStateException("Current state = " + getEventTypeString(fEventType) 421 + " is not among the states " + getEventTypeString(XMLEvent.CHARACTERS) + " , " 422 + getEventTypeString(XMLEvent.COMMENT) + " , " + getEventTypeString(XMLEvent.CDATA) 423 + " , " + getEventTypeString(XMLEvent.SPACE) +" valid for getTextStart() " ) ; 424 } 425 } 426 427 /** 428 * @return 429 */ 430 public String getValue() { 431 if(fEventType == XMLEvent.PROCESSING_INSTRUCTION){ 432 return fScanner.getPIData().toString(); 433 } else if(fEventType == XMLEvent.COMMENT){ 434 return fScanner.getComment(); 435 } else if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT){ 436 return fScanner.getElementQName().localpart ; 437 } else if(fEventType == XMLEvent.CHARACTERS){ 438 return fScanner.getCharacterData().toString(); 439 } 440 return null; 441 }//getValue() 442 443 /** Get the XML language version of the current document being parsed */ 444 public String getVersion() { 445 //apply SAP's patch: the default version in the scanner was set to 1.0 because of DOM and SAX 446 //so this patch is a workaround of the difference between StAX and DOM 447 // SAPJVM: Return null if the XML version has not been declared (as specified in the JavaDoc). 448 449 String version = fEntityScanner.getXMLVersion(); 450 451 return "1.0".equals(version) && !fEntityScanner.xmlVersionSetExplicitly ? null : version; 452 } 453 454 /** 455 * @return 456 */ 457 public boolean hasAttributes() { 458 return fScanner.getAttributeIterator().getLength() > 0 ? true : false ; 459 } 460 461 /** this Funtion returns true if the current event has name */ 462 public boolean hasName() { 463 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 464 return true; 465 } else { 466 return false; 467 } 468 }//hasName() 469 470 /** 471 * @throws XMLStreamException 472 * @return 473 */ 474 public boolean hasNext() throws XMLStreamException { 475 //the scanner returns -1 when it detects a broken stream 476 if (fEventType == -1) return false; 477 //we can check in scanners if the scanner state is not set to 478 //terminating, we still have more events. 479 return fEventType != XMLEvent.END_DOCUMENT; 480 } 481 482 /** 483 * @return 484 */ 485 public boolean hasValue() { 486 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 487 || fEventType == XMLEvent.ENTITY_REFERENCE || fEventType == XMLEvent.PROCESSING_INSTRUCTION 488 || fEventType == XMLEvent.COMMENT || fEventType == XMLEvent.CHARACTERS) { 489 return true; 490 } else { 491 return false; 492 } 493 494 } 495 496 /** 497 * @return 498 */ 499 public boolean isEndElement() { 500 return fEventType == XMLEvent.END_ELEMENT; 501 } 502 503 /** 504 * @return 505 */ 506 public boolean isStandalone() { 507 return fScanner.isStandAlone(); 508 } 509 510 /** 511 * @return 512 */ 513 public boolean isStartElement() { 514 return fEventType == XMLEvent.START_ELEMENT; 515 } 516 517 /** 518 * Returns true if the cursor points to a character data event that consists of all whitespace 519 * Application calling this method needs to cache the value and avoid calling this method again 520 * for the same event. 521 * @return 522 */ 523 public boolean isWhiteSpace() { 524 if(isCharacters() || (fEventType == XMLStreamConstants.CDATA)){ 525 char [] ch = this.getTextCharacters(); 526 final int start = this.getTextStart(); 527 final int end = start + this.getTextLength(); 528 for (int i = start; i < end; i++){ 529 if(!XMLChar.isSpace(ch[i])){ 530 return false; 531 } 532 } 533 return true; 534 } 535 return false; 536 } 537 538 539 540 /** 541 * @throws XMLStreamException 542 * @return 543 */ 544 public int next() throws XMLStreamException { 545 if( !hasNext() ) { 546 if (fEventType != -1) { 547 throw new java.util.NoSuchElementException( "END_DOCUMENT reached: no more elements on the stream." ); 548 } else { 549 throw new XMLStreamException( "Error processing input source. The input stream is not complete." ); 550 } 551 } 552 try { 553 fEventType = fScanner.next(); 554 555 if (versionStr == null) { 556 versionStr = getVersion(); 557 } 558 559 if (fEventType == XMLStreamConstants.START_DOCUMENT 560 && versionStr != null 561 && versionStr.equals("1.1")) { 562 switchToXML11Scanner(); 563 } 564 565 return fEventType; 566 } catch (IOException ex) { 567 // if this error occured trying to resolve the external DTD subset 568 // and IS_VALIDATING == false, then this is not an XML error 569 if (fScanner.fScannerState == fScanner.SCANNER_STATE_DTD_EXTERNAL) { 570 Boolean isValidating = (Boolean) fPropertyManager.getProperty( 571 XMLInputFactory.IS_VALIDATING); 572 if (isValidating != null 573 && !isValidating.booleanValue()) { 574 // ignore the error, set scanner to known state 575 fEventType = XMLEvent.DTD; 576 fScanner.setScannerState(fScanner.SCANNER_STATE_PROLOG); 577 fScanner.setDriver(fScanner.fPrologDriver); 578 if (fDTDDecl == null 579 || fDTDDecl.length() == 0) { 580 fDTDDecl = "<!-- " 581 + "Exception scanning External DTD Subset. " 582 + "True contents of DTD cannot be determined. " 583 + "Processing will continue as XMLInputFactory.IS_VALIDATING == false." 584 + " -->"; 585 } 586 return XMLEvent.DTD; 587 } 588 } 589 590 // else real error 591 throw new XMLStreamException(ex.getMessage(), getLocation(), ex); 592 } catch (XNIException ex) { 593 throw new XMLStreamException( 594 ex.getMessage(), 595 getLocation(), 596 ex.getException()); 597 } 598 } //next() 599 600 private void switchToXML11Scanner() throws IOException{ 601 602 int oldEntityDepth = fScanner.fEntityDepth; 603 com.sun.org.apache.xerces.internal.xni.NamespaceContext oldNamespaceContext = fScanner.fNamespaceContext; 604 605 fScanner = new XML11NSDocumentScannerImpl(); 606 607 //get the new scanner state to old scanner's previous state 608 fScanner.reset(fPropertyManager); 609 fScanner.setPropertyManager(fPropertyManager); 610 fEntityScanner = fEntityManager.getEntityScanner(); 611 fEntityScanner.registerListener(fScanner); 612 fEntityManager.fCurrentEntity.mayReadChunks = true; 613 fScanner.setScannerState(XMLEvent.START_DOCUMENT); 614 615 fScanner.fEntityDepth = oldEntityDepth; 616 fScanner.fNamespaceContext = oldNamespaceContext; 617 fEventType = fScanner.next(); 618 } 619 620 621 622 final static String getEventTypeString(int eventType) { 623 switch (eventType){ 624 case XMLEvent.START_ELEMENT: 625 return "START_ELEMENT"; 626 case XMLEvent.END_ELEMENT: 627 return "END_ELEMENT"; 628 case XMLEvent.PROCESSING_INSTRUCTION: 629 return "PROCESSING_INSTRUCTION"; 630 case XMLEvent.CHARACTERS: 631 return "CHARACTERS"; 632 case XMLEvent.COMMENT: 633 return "COMMENT"; 634 case XMLEvent.START_DOCUMENT: 635 return "START_DOCUMENT"; 636 case XMLEvent.END_DOCUMENT: 637 return "END_DOCUMENT"; 638 case XMLEvent.ENTITY_REFERENCE: 639 return "ENTITY_REFERENCE"; 640 case XMLEvent.ATTRIBUTE: 641 return "ATTRIBUTE"; 642 case XMLEvent.DTD: 643 return "DTD"; 644 case XMLEvent.CDATA: 645 return "CDATA"; 646 case XMLEvent.SPACE: 647 return "SPACE"; 648 } 649 return "UNKNOWN_EVENT_TYPE, " + String.valueOf(eventType); 650 } 651 652 /** Returns the count of attributes on this START_ELEMENT, 653 * this method is only valid on a START_ELEMENT or ATTRIBUTE. This 654 * count excludes namespace definitions. Attribute indices are 655 * zero-based. 656 * @return returns the number of attributes 657 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 658 */ 659 public int getAttributeCount() { 660 //xxx: recognize SAX properties namespace, namespace-prefix to get XML Namespace declarations 661 //does length includes namespace declarations ? 662 663 //State should be either START_ELEMENT or ATTRIBUTE 664 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 665 return fScanner.getAttributeIterator().getLength() ; 666 } else{ 667 throw new java.lang.IllegalStateException( "Current state is not among the states " 668 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 669 + getEventTypeString(XMLEvent.ATTRIBUTE) 670 + "valid for getAttributeCount()") ; 671 } 672 }//getAttributeCount 673 674 /** Returns the localName of the attribute at the provided 675 * index 676 * @param index the position of the attribute 677 * @return the localName of the attribute 678 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 679 */ 680 public QName getAttributeName(int index) { 681 //State should be either START_ELEMENT or ATTRIBUTE 682 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 683 return convertXNIQNametoJavaxQName(fScanner.getAttributeIterator().getQualifiedName(index)) ; 684 } else{ 685 throw new java.lang.IllegalStateException("Current state is not among the states " 686 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 687 + getEventTypeString(XMLEvent.ATTRIBUTE) 688 + "valid for getAttributeName()") ; 689 } 690 }//getAttributeName 691 692 /** 693 * @param index 694 * @return 695 */ 696 public String getAttributeLocalName(int index) { 697 //State should be either START_ELEMENT or ATTRIBUTE 698 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 699 return fScanner.getAttributeIterator().getLocalName(index) ; 700 } else{ 701 throw new java.lang.IllegalStateException() ; 702 } 703 }//getAttributeName 704 705 /** Returns the namespace of the attribute at the provided 706 * index 707 * @param index the position of the attribute 708 * @return the namespace URI (can be null) 709 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 710 */ 711 public String getAttributeNamespace(int index) { 712 //State should be either START_ELEMENT or ATTRIBUTE 713 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 714 return fScanner.getAttributeIterator().getURI(index); 715 } else{ 716 throw new java.lang.IllegalStateException("Current state is not among the states " 717 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 718 + getEventTypeString(XMLEvent.ATTRIBUTE) 719 + "valid for getAttributeNamespace()") ; 720 } 721 722 }//getAttributeNamespace 723 724 /** Returns the prefix of this attribute at the 725 * provided index 726 * @param index the position of the attribute 727 * @return the prefix of the attribute 728 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 729 */ 730 public String getAttributePrefix(int index) { 731 //State should be either START_ELEMENT or ATTRIBUTE 732 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 733 return fScanner.getAttributeIterator().getPrefix(index); 734 } else{ 735 throw new java.lang.IllegalStateException("Current state is not among the states " 736 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 737 + getEventTypeString(XMLEvent.ATTRIBUTE) 738 + "valid for getAttributePrefix()") ; 739 } 740 }//getAttributePrefix 741 742 /** Returns the qname of the attribute at the provided index 743 * 744 * @param index the position of the attribute 745 * @return the QName of the attribute 746 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 747 */ 748 public javax.xml.namespace.QName getAttributeQName(int index) { 749 //State should be either START_ELEMENT or ATTRIBUTE 750 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 751 // create new object at runtime.. 752 String localName = fScanner.getAttributeIterator().getLocalName(index) ; 753 String uri = fScanner.getAttributeIterator().getURI(index) ; 754 return new javax.xml.namespace.QName(uri, localName) ; 755 } else{ 756 throw new java.lang.IllegalStateException("Current state is not among the states " 757 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 758 + getEventTypeString(XMLEvent.ATTRIBUTE) 759 + "valid for getAttributeQName()") ; 760 } 761 }//getAttributeQName 762 763 /** Returns the XML type of the attribute at the provided 764 * index 765 * @param index the position of the attribute 766 * @return the XML type of the attribute 767 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 768 */ 769 public String getAttributeType(int index) { 770 //State should be either START_ELEMENT or ATTRIBUTE 771 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 772 return fScanner.getAttributeIterator().getType(index) ; 773 } else{ 774 throw new java.lang.IllegalStateException("Current state is not among the states " 775 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 776 + getEventTypeString(XMLEvent.ATTRIBUTE) 777 + "valid for getAttributeType()") ; 778 } 779 780 }//getAttributeType 781 782 /** Returns the value of the attribute at the 783 * index 784 * @param index the position of the attribute 785 * @return the attribute value 786 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 787 */ 788 public String getAttributeValue(int index) { 789 //State should be either START_ELEMENT or ATTRIBUTE 790 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 791 return fScanner.getAttributeIterator().getValue(index) ; 792 } else{ 793 throw new java.lang.IllegalStateException("Current state is not among the states " 794 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 795 + getEventTypeString(XMLEvent.ATTRIBUTE) 796 + "valid for getAttributeValue()") ; 797 } 798 799 }//getAttributeValue 800 801 /** 802 * @param namespaceURI 803 * @param localName 804 * @return 805 */ 806 public String getAttributeValue(String namespaceURI, String localName) { 807 //State should be either START_ELEMENT or ATTRIBUTE 808 if( fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 809 XMLAttributesImpl attributes = fScanner.getAttributeIterator(); 810 if (namespaceURI == null) { //sjsxp issue 70 811 return attributes.getValue(attributes.getIndexByLocalName(localName)) ; 812 } else { 813 return fScanner.getAttributeIterator().getValue( 814 namespaceURI.length() == 0 ? null : namespaceURI, localName) ; 815 } 816 817 } else{ 818 throw new java.lang.IllegalStateException("Current state is not among the states " 819 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 820 + getEventTypeString(XMLEvent.ATTRIBUTE) 821 + "valid for getAttributeValue()") ; 822 } 823 824 } 825 826 /** Reads the content of a text-only element. Precondition: 827 * the current event is START_ELEMENT. Postcondition: 828 * The current event is the corresponding END_ELEMENT. 829 * @throws XMLStreamException if the current event is not a START_ELEMENT or if 830 * a non text element is encountered 831 */ 832 public String getElementText() throws XMLStreamException { 833 834 if(getEventType() != XMLStreamConstants.START_ELEMENT) { 835 throw new XMLStreamException( 836 "parser must be on START_ELEMENT to read next text", getLocation()); 837 } 838 int eventType = next(); 839 StringBuffer content = new StringBuffer(); 840 while(eventType != XMLStreamConstants.END_ELEMENT ) { 841 if(eventType == XMLStreamConstants.CHARACTERS 842 || eventType == XMLStreamConstants.CDATA 843 || eventType == XMLStreamConstants.SPACE 844 || eventType == XMLStreamConstants.ENTITY_REFERENCE) { 845 content.append(getText()); 846 } else if(eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 847 || eventType == XMLStreamConstants.COMMENT) { 848 // skipping 849 } else if(eventType == XMLStreamConstants.END_DOCUMENT) { 850 throw new XMLStreamException("unexpected end of document when reading element text content"); 851 } else if(eventType == XMLStreamConstants.START_ELEMENT) { 852 throw new XMLStreamException( 853 "elementGetText() function expects text only elment but START_ELEMENT was encountered.", getLocation()); 854 } else { 855 throw new XMLStreamException( 856 "Unexpected event type "+ eventType, getLocation()); 857 } 858 eventType = next(); 859 } 860 return content.toString(); 861 } 862 863 /** Return the current location of the processor. 864 * If the Location is unknown the processor should return 865 * an implementation of Location that returns -1 for the 866 * location and null for the publicId and systemId. 867 * The location information is only valid until next() is 868 * called. 869 */ 870 public Location getLocation() { 871 return new Location() { 872 String _systemId = fEntityScanner.getExpandedSystemId(); 873 String _publicId = fEntityScanner.getPublicId(); 874 int _offset = fEntityScanner.getCharacterOffset(); 875 int _columnNumber = fEntityScanner.getColumnNumber(); 876 int _lineNumber = fEntityScanner.getLineNumber(); 877 public String getLocationURI(){ 878 return _systemId; 879 } 880 881 public int getCharacterOffset(){ 882 return _offset; 883 } 884 885 public int getColumnNumber() { 886 return _columnNumber; 887 } 888 889 public int getLineNumber(){ 890 return _lineNumber; 891 } 892 893 public String getPublicId(){ 894 return _publicId; 895 } 896 897 public String getSystemId(){ 898 return _systemId; 899 } 900 901 public String toString(){ 902 StringBuffer sbuffer = new StringBuffer() ; 903 sbuffer.append("Line number = " + getLineNumber()); 904 sbuffer.append("\n") ; 905 sbuffer.append("Column number = " + getColumnNumber()); 906 sbuffer.append("\n") ; 907 sbuffer.append("System Id = " + getSystemId()); 908 sbuffer.append("\n") ; 909 sbuffer.append("Public Id = " + getPublicId()); 910 sbuffer.append("\n") ; 911 sbuffer.append("Location Uri= " + getLocationURI()); 912 sbuffer.append("\n") ; 913 sbuffer.append("CharacterOffset = " + getCharacterOffset()); 914 sbuffer.append("\n") ; 915 return sbuffer.toString(); 916 } 917 } ; 918 919 } 920 921 /** Returns a QName for the current START_ELEMENT or END_ELEMENT event 922 * @return the QName for the current START_ELEMENT or END_ELEMENT event 923 */ 924 public javax.xml.namespace.QName getName() { 925 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) 926 return convertXNIQNametoJavaxQName(fScanner.getElementQName()); 927 else 928 throw new java.lang.IllegalStateException("Illegal to call getName() "+ 929 "when event type is "+ getEventTypeString(fEventType) + "." 930 + " Valid states are " + getEventTypeString(XMLEvent.START_ELEMENT) + ", " 931 + getEventTypeString(XMLEvent.END_ELEMENT)); 932 } 933 934 /** Returns a read only namespace context for the current 935 * position. The context is transient and only valid until 936 * a call to next() changes the state of the reader. 937 * @return return a namespace context 938 */ 939 public NamespaceContext getNamespaceContext() { 940 return fNamespaceContextWrapper ; 941 } 942 943 /** Returns the count of namespaces declared on this START_ELEMENT or END_ELEMENT, 944 * this method is only valid on a START_ELEMENT, END_ELEMENT or NAMESPACE. On 945 * an END_ELEMENT the count is of the namespaces that are about to go 946 * out of scope. This is the equivalent of the information reported 947 * by SAX callback for an end element event. 948 * @return returns the number of namespace declarations on this specific element 949 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT or NAMESPACE 950 */ 951 public int getNamespaceCount() { 952 //namespaceContext is dynamic object. 953 //REVISIT: check if it specifies all conditions mentioned in the javadoc 954 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT || fEventType == XMLEvent.NAMESPACE){ 955 return fScanner.getNamespaceContext().getDeclaredPrefixCount() ; 956 } else{ 957 throw new IllegalStateException("Current event state is " + getEventTypeString(fEventType) 958 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 959 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 960 + getEventTypeString(XMLEvent.NAMESPACE) 961 + " valid for getNamespaceCount()." ); 962 } 963 } 964 965 /** Returns the prefix for the namespace declared at the 966 * index. Returns null if this is the default namespace 967 * declaration 968 * 969 * @param index the position of the namespace declaration 970 * @return returns the namespace prefix 971 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT or NAMESPACE 972 */ 973 public String getNamespacePrefix(int index) { 974 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT || fEventType == XMLEvent.NAMESPACE){ 975 //namespaceContext is dynamic object. 976 String prefix = fScanner.getNamespaceContext().getDeclaredPrefixAt(index) ; 977 return prefix.equals("") ? null : prefix ; 978 } 979 else{ 980 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 981 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 982 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 983 + getEventTypeString(XMLEvent.NAMESPACE) 984 + " valid for getNamespacePrefix()." ); 985 } 986 } 987 988 /** Returns the uri for the namespace declared at the 989 * index. 990 * 991 * @param index the position of the namespace declaration 992 * @return returns the namespace uri 993 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT or NAMESPACE 994 */ 995 public String getNamespaceURI(int index) { 996 if(fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT || fEventType == XMLEvent.NAMESPACE){ 997 //namespaceContext is dynamic object. 998 return fScanner.getNamespaceContext().getURI(fScanner.getNamespaceContext().getDeclaredPrefixAt(index)); 999 } 1000 else{ 1001 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1002 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 1003 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 1004 + getEventTypeString(XMLEvent.NAMESPACE) 1005 + " valid for getNamespaceURI()." ); 1006 } 1007 1008 } 1009 1010 /** Get the value of a feature/property from the underlying implementation 1011 * @param name The name of the property, may not be null 1012 * @return The value of the property 1013 * @throws IllegalArgumentException if name is null 1014 */ 1015 public Object getProperty(java.lang.String name) throws java.lang.IllegalArgumentException { 1016 if(name == null) throw new java.lang.IllegalArgumentException() ; 1017 if (fPropertyManager != null ){ 1018 if(name.equals(fPropertyManager.STAX_NOTATIONS)){ 1019 return getNotationDecls(); 1020 }else if(name.equals(fPropertyManager.STAX_ENTITIES)){ 1021 return getEntityDecls(); 1022 }else 1023 return fPropertyManager.getProperty(name); 1024 } 1025 return null; 1026 } 1027 1028 /** Returns the current value of the parse event as a string, 1029 * this returns the string value of a CHARACTERS event, 1030 * returns the value of a COMMENT, the replacement value 1031 * for an ENTITY_REFERENCE, 1032 * or the String value of the DTD 1033 * @return the current text or null 1034 * @throws java.lang.IllegalStateException if this state is not 1035 * a valid text state. 1036 */ 1037 public String getText() { 1038 if( fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 1039 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE){ 1040 //this requires creation of new string 1041 //fEventType == XMLEvent.ENTITY_REFERENCE 1042 return fScanner.getCharacterData().toString() ; 1043 } else if(fEventType == XMLEvent.ENTITY_REFERENCE){ 1044 String name = fScanner.getEntityName(); 1045 if(name != null){ 1046 if(fScanner.foundBuiltInRefs) 1047 return fScanner.getCharacterData().toString(); 1048 1049 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1050 Entity en = entityStore.getEntity(name); 1051 if(en == null) 1052 return null; 1053 if(en.isExternal()) 1054 return ((Entity.ExternalEntity)en).entityLocation.getExpandedSystemId(); 1055 else 1056 return ((Entity.InternalEntity)en).text; 1057 }else 1058 return null; 1059 } 1060 else if(fEventType == XMLEvent.DTD){ 1061 if(fDTDDecl != null){ 1062 return fDTDDecl; 1063 } 1064 XMLStringBuffer tmpBuffer = fScanner.getDTDDecl(); 1065 fDTDDecl = tmpBuffer.toString(); 1066 return fDTDDecl; 1067 } else{ 1068 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1069 + " is not among the states" + getEventTypeString(XMLEvent.CHARACTERS) + ", " 1070 + getEventTypeString(XMLEvent.COMMENT) + ", " 1071 + getEventTypeString(XMLEvent.CDATA) + ", " 1072 + getEventTypeString(XMLEvent.SPACE) + ", " 1073 + getEventTypeString(XMLEvent.ENTITY_REFERENCE) + ", " 1074 + getEventTypeString(XMLEvent.DTD) + " valid for getText() " ) ; 1075 } 1076 }//getText 1077 1078 1079 /** Test if the current event is of the given type and if the namespace and name match the current namespace and name of the current event. 1080 * If the namespaceURI is null it is not checked for equality, if the localName is null it is not checked for equality. 1081 * @param type the event type 1082 * @param namespaceURI the uri of the event, may be null 1083 * @param localName the localName of the event, may be null 1084 * @throws XMLStreamException if the required values are not matched. 1085 */ 1086 public void require(int type, String namespaceURI, String localName) throws XMLStreamException { 1087 if( type != fEventType) 1088 throw new XMLStreamException("Event type " + getEventTypeString(type) + " specified did " + 1089 "not match with current parser event " + getEventTypeString(fEventType)); 1090 if( namespaceURI != null && !namespaceURI.equals(getNamespaceURI()) ) 1091 throw new XMLStreamException("Namespace URI " + namespaceURI +" specified did not match " + 1092 "with current namespace URI"); 1093 if(localName != null && !localName.equals(getLocalName())) 1094 throw new XMLStreamException("LocalName " + localName +" specified did not match with " + 1095 "current local name"); 1096 return; 1097 } 1098 1099 /** Gets the the text associated with a CHARACTERS, SPACE or CDATA event. 1100 * Text starting a "sourceStart" is copied into "destination" starting at "targetStart". 1101 * Up to "length" characters are copied. The number of characters actually copied is returned. 1102 * 1103 * The "sourceStart" argument must be greater or equal to 0 and less than or equal to 1104 * the number of characters associated with the event. Usually, one requests text starting at a "sourceStart" of 0. 1105 * If the number of characters actually copied is less than the "length", then there is no more text. 1106 * Otherwise, subsequent calls need to be made until all text has been retrieved. For example: 1107 * 1108 * <code> 1109 * int length = 1024; 1110 * char[] myBuffer = new char[ length ]; 1111 * 1112 * for ( int sourceStart = 0 ; ; sourceStart += length ) 1113 * { 1114 * int nCopied = stream.getTextCharacters( sourceStart, myBuffer, 0, length ); 1115 * 1116 * if (nCopied < length) 1117 * break; 1118 * } 1119 * </code> 1120 * XMLStreamException may be thrown if there are any XML errors in the underlying source. 1121 * The "targetStart" argument must be greater than or equal to 0 and less than the length of "target", 1122 * Length must be greater than 0 and "targetStart + length" must be less than or equal to length of "target". 1123 * 1124 * @param sourceStart the index of the first character in the source array to copy 1125 * @param target the destination array 1126 * @param targetStart the start offset in the target array 1127 * @param length the number of characters to copy 1128 * @return the number of characters actually copied 1129 * @throws XMLStreamException if the underlying XML source is not well-formed 1130 * @throws IndexOutOfBoundsException if targetStart < 0 or > than the length of target 1131 * @throws IndexOutOfBoundwhile(isCharacters()) ;sException if length < 0 or targetStart + length > length of target 1132 * @throws UnsupportedOperationException if this method is not supported 1133 * @throws NullPointerException is if target is null 1134 */ 1135 public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) throws XMLStreamException { 1136 1137 if(target == null){ 1138 throw new NullPointerException("target char array can't be null") ; 1139 } 1140 1141 if(targetStart < 0 || length < 0 || sourceStart < 0 || targetStart >= target.length || 1142 (targetStart + length ) > target.length) { 1143 throw new IndexOutOfBoundsException(); 1144 } 1145 1146 //getTextStart() + sourceStart should not be greater than the lenght of number of characters 1147 //present 1148 int copiedLength = 0; 1149 //int presentDataLen = getTextLength() - (getTextStart()+sourceStart); 1150 int available = getTextLength() - sourceStart; 1151 if(available < 0){ 1152 throw new IndexOutOfBoundsException("sourceStart is greater than" + 1153 "number of characters associated with this event"); 1154 } 1155 if(available < length){ 1156 copiedLength = available; 1157 } else{ 1158 copiedLength = length; 1159 } 1160 1161 System.arraycopy(getTextCharacters(), getTextStart() + sourceStart , target, targetStart, copiedLength); 1162 return copiedLength; 1163 } 1164 1165 /** Return true if the current event has text, false otherwise 1166 * The following events have text: 1167 * CHARACTERS,DTD ,ENTITY_REFERENCE, COMMENT 1168 */ 1169 public boolean hasText() { 1170 if(DEBUG) pr("XMLReaderImpl#EVENT TYPE = " + fEventType ) ; 1171 if( fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT || fEventType == XMLEvent.CDATA) { 1172 return fScanner.getCharacterData().length > 0; 1173 } else if(fEventType == XMLEvent.ENTITY_REFERENCE) { 1174 String name = fScanner.getEntityName(); 1175 if(name != null){ 1176 if(fScanner.foundBuiltInRefs) 1177 return true; 1178 1179 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1180 Entity en = entityStore.getEntity(name); 1181 if(en == null) 1182 return false; 1183 if(en.isExternal()){ 1184 return ((Entity.ExternalEntity)en).entityLocation.getExpandedSystemId() != null; 1185 } else{ 1186 return ((Entity.InternalEntity)en).text != null ; 1187 } 1188 }else 1189 return false; 1190 } else { 1191 if(fEventType == XMLEvent.DTD) 1192 return fScanner.fSeenDoctypeDecl; 1193 } 1194 return false; 1195 } 1196 1197 /** Returns a boolean which indicates if this 1198 * attribute was created by default 1199 * @param index the position of the attribute 1200 * @return true if this is a default attribute 1201 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 1202 */ 1203 public boolean isAttributeSpecified(int index) { 1204 //check that current state should be either START_ELEMENT or ATTRIBUTE 1205 if( (fEventType == XMLEvent.START_ELEMENT) || (fEventType == XMLEvent.ATTRIBUTE)){ 1206 return fScanner.getAttributeIterator().isSpecified(index) ; 1207 } else{ 1208 throw new IllegalStateException("Current state is not among the states " 1209 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 1210 + getEventTypeString(XMLEvent.ATTRIBUTE) 1211 + "valid for isAttributeSpecified()") ; 1212 } 1213 } 1214 1215 /** Returns true if the cursor points to a character data event 1216 * @return true if the cursor points to character data, false otherwise 1217 */ 1218 public boolean isCharacters() { 1219 return fEventType == XMLEvent.CHARACTERS ; 1220 } 1221 1222 /** Skips any insignificant events (COMMENT and PROCESSING_INSTRUCTION) 1223 * until a START_ELEMENT or 1224 * END_ELEMENT is reached. If other than space characters are 1225 * encountered, an exception is thrown. This method should 1226 * be used when processing element-only content because 1227 * the parser is not able to recognize ignorable whitespace if 1228 * then DTD is missing or not interpreted. 1229 * @return the event type of the element read 1230 * @throws XMLStreamException if the current event is not white space 1231 */ 1232 public int nextTag() throws XMLStreamException { 1233 1234 int eventType = next(); 1235 while((eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace()) // skip whitespace 1236 || (eventType == XMLStreamConstants.CDATA && isWhiteSpace()) 1237 // skip whitespace 1238 || eventType == XMLStreamConstants.SPACE 1239 || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 1240 || eventType == XMLStreamConstants.COMMENT 1241 ) { 1242 eventType = next(); 1243 } 1244 1245 if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) { 1246 throw new XMLStreamException( 1247 "found: " + getEventTypeString(eventType) 1248 + ", expected " + getEventTypeString(XMLStreamConstants.START_ELEMENT) 1249 + " or " + getEventTypeString(XMLStreamConstants.END_ELEMENT), 1250 getLocation()); 1251 } 1252 1253 return eventType; 1254 } 1255 1256 /** Checks if standalone was set in the document 1257 * @return true if standalone was set in the document, or false otherwise 1258 */ 1259 public boolean standaloneSet() { 1260 //xxx: it requires if the standalone was set in the document ? This is different that if the document 1261 // is standalone 1262 return fScanner.standaloneSet() ; 1263 } 1264 1265 /** 1266 * @param qname 1267 * @return 1268 */ 1269 public javax.xml.namespace.QName convertXNIQNametoJavaxQName(com.sun.org.apache.xerces.internal.xni.QName qname){ 1270 if (qname == null) return null; 1271 //xxx: prefix definition ? 1272 if(qname.prefix == null){ 1273 return new javax.xml.namespace.QName(qname.uri, qname.localpart) ; 1274 } else{ 1275 return new javax.xml.namespace.QName(qname.uri, qname.localpart, qname.prefix) ; 1276 } 1277 } 1278 1279 /** Return the uri for the given prefix. 1280 * The uri returned depends on the current state of the processor. 1281 * 1282 * <p><strong>NOTE:</strong>The 'xml' prefix is bound as defined in 1283 * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a> 1284 * specification to "http://www.w3.org/XML/1998/namespace". 1285 * 1286 * <p><strong>NOTE:</strong> The 'xmlns' prefix must be resolved to following namespace 1287 * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a> 1288 * @return the uri bound to the given prefix or null if it is not bound 1289 * @param prefix The prefix to lookup, may not be null 1290 * @throws IllegalStateException - if the prefix is null 1291 */ 1292 public String getNamespaceURI(String prefix) { 1293 if(prefix == null) throw new java.lang.IllegalArgumentException("prefix cannot be null.") ; 1294 1295 //first add the string to symbol table.. since internally identity comparisons are done. 1296 return fScanner.getNamespaceContext().getURI(fSymbolTable.addSymbol(prefix)) ; 1297 } 1298 1299 //xxx: this function is not being used. 1300 protected void setPropertyManager(PropertyManager propertyManager){ 1301 fPropertyManager = propertyManager ; 1302 //REVISIT: we were supplying hashmap ealier 1303 fScanner.setProperty("stax-properties",propertyManager); 1304 fScanner.setPropertyManager(propertyManager) ; 1305 } 1306 1307 /** 1308 * @return returns the reference to property manager. 1309 */ 1310 protected PropertyManager getPropertyManager(){ 1311 return fPropertyManager ; 1312 } 1313 1314 static void pr(String str) { 1315 System.out.println(str) ; 1316 } 1317 1318 protected List getEntityDecls(){ 1319 if(fEventType == XMLStreamConstants.DTD){ 1320 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1321 ArrayList list = null; 1322 if(entityStore.hasEntities()){ 1323 EntityDeclarationImpl decl = null; 1324 list = new ArrayList(entityStore.getEntitySize()); 1325 Enumeration enu = entityStore.getEntityKeys(); 1326 while(enu.hasMoreElements()){ 1327 String key = (String)enu.nextElement(); 1328 Entity en = (Entity)entityStore.getEntity(key); 1329 decl = new EntityDeclarationImpl(); 1330 decl.setEntityName(key); 1331 if(en.isExternal()){ 1332 decl.setXMLResourceIdentifier(((Entity.ExternalEntity)en).entityLocation); 1333 decl.setNotationName(((Entity.ExternalEntity)en).notation); 1334 } 1335 else 1336 decl.setEntityReplacementText(((Entity.InternalEntity)en).text); 1337 list.add(decl); 1338 } 1339 } 1340 return list; 1341 } 1342 return null; 1343 } 1344 1345 protected List getNotationDecls(){ 1346 if(fEventType == XMLStreamConstants.DTD){ 1347 if(fScanner.fDTDScanner == null) return null; 1348 DTDGrammar grammar = ((XMLDTDScannerImpl)(fScanner.fDTDScanner)).getGrammar(); 1349 if(grammar == null) return null; 1350 List notations = grammar.getNotationDecls(); 1351 1352 Iterator it = notations.iterator(); 1353 ArrayList list = new ArrayList(); 1354 while(it.hasNext()){ 1355 XMLNotationDecl ni = (XMLNotationDecl)it.next(); 1356 if(ni!= null){ 1357 list.add(new NotationDeclarationImpl(ni)); 1358 } 1359 } 1360 return list; 1361 } 1362 return null; 1363 } 1364 1365 1366 1367 }//XMLReaderImpl | 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.org.apache.xerces.internal.impl; 27 28 import com.sun.org.apache.xerces.internal.util.NamespaceContextWrapper; 29 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 30 import com.sun.org.apache.xerces.internal.util.SymbolTable; 31 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; 32 import com.sun.org.apache.xerces.internal.util.XMLChar; 33 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; 34 import com.sun.org.apache.xerces.internal.xni.XNIException; 35 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 36 import com.sun.xml.internal.stream.Entity; 37 import com.sun.xml.internal.stream.StaxErrorReporter; 38 import com.sun.xml.internal.stream.XMLEntityStorage; 39 import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; 40 import com.sun.xml.internal.stream.dtd.nonvalidating.XMLNotationDecl; 41 import com.sun.xml.internal.stream.events.EntityDeclarationImpl; 42 import com.sun.xml.internal.stream.events.NotationDeclarationImpl; 43 import java.io.BufferedInputStream; 44 import java.io.BufferedReader; 45 import java.io.IOException; 46 import java.io.InputStream; 47 import java.io.Reader; 48 import java.util.ArrayList; 49 import java.util.List; 50 import java.util.Map; 51 import javax.xml.XMLConstants; 52 import javax.xml.namespace.NamespaceContext; 53 import javax.xml.namespace.QName; 54 import javax.xml.stream.Location; 55 import javax.xml.stream.XMLInputFactory; 56 import javax.xml.stream.XMLStreamConstants; 57 import javax.xml.stream.XMLStreamException; 58 import javax.xml.stream.events.EntityDeclaration; 59 import javax.xml.stream.events.NotationDeclaration; 60 import javax.xml.stream.events.XMLEvent; 61 62 /** 63 * This class implements javax.xml.stream.XMLStreamReader. It makes use of 64 * XML*Scanner classes to derive most of its functionality. If desired, 65 * Application can reuse this instance by calling reset() and setInputSource(). 66 * 67 * @author Neeraj Bajaj Sun Microsystems,Inc. 68 * @author K.Venugopal Sun Microsystems,Inc. 69 * @author Sunitha Reddy Sun Microsystems,Inc. 70 */ 71 public class XMLStreamReaderImpl implements javax.xml.stream.XMLStreamReader { 72 73 /** 74 * Property identifier: entity manager. 75 */ 76 protected static final String ENTITY_MANAGER 77 = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; 78 79 /** 80 * Property identifier: Error Reporter. 81 */ 82 protected static final String ERROR_REPORTER 83 = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 84 85 /** 86 * Property identifier: Symbol table. 87 */ 88 protected static final String SYMBOL_TABLE 89 = Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 90 91 protected static final String READER_IN_DEFINED_STATE 92 = Constants.READER_IN_DEFINED_STATE; 93 94 private SymbolTable fSymbolTable = new SymbolTable(); 95 96 /** 97 * Document scanner. 98 */ 99 protected XMLDocumentScannerImpl fScanner = new XMLNSDocumentScannerImpl(); 100 101 //make Global NamespaceContextWrapper object, fScanner.getNamespaceContext() 102 //is dynamic object and ita value changes as per the state of the parser. 103 protected NamespaceContextWrapper fNamespaceContextWrapper = 104 new NamespaceContextWrapper((NamespaceSupport) fScanner.getNamespaceContext()); 105 protected XMLEntityManager fEntityManager = new XMLEntityManager(); 106 protected StaxErrorReporter fErrorReporter = new StaxErrorReporter(); 107 108 /** 109 * Entity scanner, this alwasy works on last entity that was opened. 110 */ 111 protected XMLEntityScanner fEntityScanner = null; 112 113 /** 114 * Input Source 115 */ 116 protected XMLInputSource fInputSource = null; 117 /** 118 * Store properties 119 */ 120 protected PropertyManager fPropertyManager = null; 121 122 /** 123 * current event type 124 */ 125 private int fEventType; 126 /** 127 * debug flag 128 */ 129 static final boolean DEBUG = false; 130 /** 131 * more to scan 132 */ 133 private boolean fReuse = true; 134 private boolean fReaderInDefinedState = true; 135 private String fDTDDecl = null; 136 private String versionStr = null; 137 138 /** 139 * @param inputStream 140 * @param props 141 * @throws XMLStreamException 142 */ 143 public XMLStreamReaderImpl(InputStream inputStream, PropertyManager props) throws XMLStreamException { 144 init(props); 145 //publicId, systemid, baseSystemId, inputStream, enocding 146 XMLInputSource inputSource = new XMLInputSource(null, null, null, inputStream, null); 147 //pass the input source to document scanner impl. 148 setInputSource(inputSource); 149 } 150 151 public XMLDocumentScannerImpl getScanner() { 152 System.out.println("returning scanner"); 153 return fScanner; 154 } 155 156 /** 157 * @param systemid 158 * @param props 159 * @throws XMLStreamException 160 */ 161 public XMLStreamReaderImpl(String systemid, PropertyManager props) throws XMLStreamException { 162 init(props); 163 //publicId, systemid, baseSystemId, inputStream, enocding 164 XMLInputSource inputSource = new XMLInputSource(null, systemid, null, false); 165 //pass the input source to document scanner impl. 166 setInputSource(inputSource); 167 } 168 169 /** 170 * @param inputStream 171 * @param encoding 172 * @param props 173 * @throws XMLStreamException 174 */ 175 public XMLStreamReaderImpl(InputStream inputStream, String encoding, PropertyManager props) 176 throws XMLStreamException { 177 init(props); 178 //publicId, systemid, baseSystemId, inputStream, enocding 179 XMLInputSource inputSource = new XMLInputSource(null, null, null, 180 new BufferedInputStream(inputStream), encoding); 181 //pass the input source to document scanner impl. 182 setInputSource(inputSource); 183 } 184 185 /** 186 * @param reader 187 * @param props 188 * @throws XMLStreamException 189 */ 190 public XMLStreamReaderImpl(Reader reader, PropertyManager props) 191 throws XMLStreamException { 192 init(props); 193 //publicId, systemid, baseSystemId, inputStream, enocding 194 //xxx: Using buffered reader 195 XMLInputSource inputSource = new XMLInputSource(null, null, null, 196 new BufferedReader(reader), null); 197 //pass the input source to document scanner impl. 198 setInputSource(inputSource); 199 } 200 201 /** 202 * @param inputSource 203 * @param props 204 * @throws XMLStreamException 205 */ 206 public XMLStreamReaderImpl(XMLInputSource inputSource, PropertyManager props) 207 throws XMLStreamException { 208 init(props); 209 //pass the input source to document scanner impl. 210 setInputSource(inputSource); 211 } 212 213 /** 214 * @param inputSource 215 * @throws XMLStreamException 216 */ 217 public final void setInputSource(XMLInputSource inputSource) throws XMLStreamException { 218 //once setInputSource() is called this instance is busy parsing the inputsource supplied 219 //this instances is free for reuse if parser has reached END_DOCUMENT state or application has 220 //called close() 221 fReuse = false; 222 223 try { 224 225 fScanner.setInputSource(inputSource); 226 //XMLStreamReader should be in defined state 227 if (fReaderInDefinedState) { 228 fEventType = fScanner.next(); 229 if (versionStr == null) { 230 versionStr = getVersion(); 231 } 232 233 if (fEventType == XMLStreamConstants.START_DOCUMENT && versionStr != null 234 && versionStr.equals("1.1")) { 235 switchToXML11Scanner(); 236 } 237 238 } 239 } catch (java.io.IOException ex) { 240 throw new XMLStreamException(ex); 241 } catch (XNIException ex) { //Issue 56 XNIException not caught 242 throw new XMLStreamException(ex.getMessage(), getLocation(), ex.getException()); 243 } 244 }//setInputSource 245 246 final void init(PropertyManager propertyManager) throws XMLStreamException { 247 fPropertyManager = propertyManager; 248 //set Stax internal properties -- Note that these instances are being created in XMLReaderImpl. 249 //1.SymbolTable 250 //2.XMLMessageFormatter 251 //3.XMLEntityManager 252 //4. call reset() 253 //1. 254 propertyManager.setProperty(SYMBOL_TABLE, fSymbolTable); 255 //2. 256 propertyManager.setProperty(ERROR_REPORTER, fErrorReporter); 257 //3. 258 propertyManager.setProperty(ENTITY_MANAGER, fEntityManager); 259 //4. 260 reset(); 261 } 262 263 /** 264 * This function tells if this instances is available for reuse. One must 265 * call reset() and setInputSource() to be able to reuse this instance. 266 */ 267 public boolean canReuse() { 268 if (DEBUG) { 269 System.out.println("fReuse = " + fReuse); 270 System.out.println("fEventType = " + getEventTypeString(fEventType)); 271 } 272 //when parsing begins, fReuse is set to false 273 //fReuse is set to 'true' when application calls close() 274 return fReuse; 275 } 276 277 /** 278 * Resets this instance so that this instance is ready for reuse. 279 */ 280 public void reset() { 281 fReuse = true; 282 fEventType = 0; 283 //reset entity manager 284 fEntityManager.reset(fPropertyManager); 285 //reset the scanner 286 fScanner.reset(fPropertyManager); 287 //REVISIT:this is too ugly -- we are getting XMLEntityManager and XMLEntityReader from 288 //property manager, it should be only XMLEntityManager 289 fDTDDecl = null; 290 fEntityScanner = fEntityManager.getEntityScanner(); 291 //default value for this property is true. However, this should be false 292 //when using XMLEventReader, because XMLEventReader should not have defined state. 293 fReaderInDefinedState = ((Boolean) fPropertyManager.getProperty(READER_IN_DEFINED_STATE)); 294 versionStr = null; 295 } 296 297 /** 298 * Frees any resources associated with this Reader. This method does not 299 * close the underlying input source. 300 * 301 * @throws XMLStreamException if there are errors freeing associated 302 * resources 303 */ 304 public void close() throws XMLStreamException { 305 //xxx: Check what this function is intended to do. 306 //reset(); 307 fReuse = true; 308 } 309 310 /** 311 * Returns the character encoding declared on the xml declaration Returns 312 * null if none was declared 313 * 314 * @return the encoding declared in the document or null 315 */ 316 public String getCharacterEncodingScheme() { 317 return fScanner.getCharacterEncodingScheme(); 318 319 } 320 321 /** 322 * @return 323 */ 324 public int getColumnNumber() { 325 return fEntityScanner.getColumnNumber(); 326 }//getColumnNumber 327 328 /** 329 * Return input encoding if known or null if unknown. 330 * 331 * @return the encoding of this instance or null 332 */ 333 public String getEncoding() { 334 return fEntityScanner.getEncoding(); 335 }//getEncoding 336 337 /** 338 * Returns the current value of the parse event as a string, this returns 339 * the string value of a CHARACTERS event, returns the value of a COMMENT, 340 * the replacement value for an ENTITY_REFERENCE, the string value of a 341 * CDATA section, the string value for a SPACE event, or the String value of 342 * the internal subset of the DTD. If an ENTITY_REFERENCE has been resolved, 343 * any character data will be reported as CHARACTERS events. 344 * 345 * @return the current text or null 346 */ 347 public int getEventType() { 348 return fEventType; 349 }//getEventType 350 351 /** 352 * @return 353 */ 354 public int getLineNumber() { 355 return fEntityScanner.getLineNumber(); 356 }//getLineNumber 357 358 public String getLocalName() { 359 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 360 //xxx check whats the value of fCurrentElement 361 return fScanner.getElementQName().localpart; 362 } else if (fEventType == XMLEvent.ENTITY_REFERENCE) { 363 return fScanner.getEntityName(); 364 } 365 throw new IllegalStateException("Method getLocalName() cannot be called for " 366 + getEventTypeString(fEventType) + " event."); 367 }//getLocalName() 368 369 /** 370 * @return 371 */ 372 public String getNamespaceURI() { 373 //doesn't take care of Attribute as separte event 374 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 375 return fScanner.getElementQName().uri; 376 } 377 return null; 378 }//getNamespaceURI 379 380 /** 381 * Get the data section of a processing instruction 382 * 383 * @return the data or null 384 */ 385 public String getPIData() { 386 if (fEventType == XMLEvent.PROCESSING_INSTRUCTION) { 387 return fScanner.getPIData().toString(); 388 } else { 389 throw new java.lang.IllegalStateException("Current state of the parser is " + getEventTypeString(fEventType) 390 + " But Expected state is " + XMLEvent.PROCESSING_INSTRUCTION); 391 } 392 }//getPIData 393 394 /** 395 * Get the target of a processing instruction 396 * 397 * @return the target or null 398 */ 399 public String getPITarget() { 400 if (fEventType == XMLEvent.PROCESSING_INSTRUCTION) { 401 return fScanner.getPITarget(); 402 } else { 403 throw new java.lang.IllegalStateException("Current state of the parser is " + getEventTypeString(fEventType) 404 + " But Expected state is " + XMLEvent.PROCESSING_INSTRUCTION); 405 } 406 407 }//getPITarget 408 409 /** 410 * @return the prefix of the current event, or null if the event does not 411 * have a prefix. For START_ELEMENT and END_ELEMENT, return 412 * XMLConstants.DEFAULT_NS_PREFIX when no prefix is available. 413 */ 414 public String getPrefix() { 415 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 416 String prefix = fScanner.getElementQName().prefix; 417 return prefix == null ? XMLConstants.DEFAULT_NS_PREFIX : prefix; 418 } 419 return null; 420 }//getPrefix() 421 422 /** 423 * @return 424 */ 425 public char[] getTextCharacters() { 426 if (fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 427 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE) { 428 return fScanner.getCharacterData().ch; 429 } else { 430 throw new IllegalStateException("Current state = " + getEventTypeString(fEventType) 431 + " is not among the states " + getEventTypeString(XMLEvent.CHARACTERS) + " , " 432 + getEventTypeString(XMLEvent.COMMENT) + " , " + getEventTypeString(XMLEvent.CDATA) 433 + " , " + getEventTypeString(XMLEvent.SPACE) + " valid for getTextCharacters() "); 434 } 435 } 436 437 /** 438 * @return 439 */ 440 public int getTextLength() { 441 if (fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 442 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE) { 443 return fScanner.getCharacterData().length; 444 } else { 445 throw new IllegalStateException("Current state = " + getEventTypeString(fEventType) 446 + " is not among the states " + getEventTypeString(XMLEvent.CHARACTERS) + " , " 447 + getEventTypeString(XMLEvent.COMMENT) + " , " + getEventTypeString(XMLEvent.CDATA) 448 + " , " + getEventTypeString(XMLEvent.SPACE) + " valid for getTextLength() "); 449 } 450 451 } 452 453 /** 454 * @return 455 */ 456 public int getTextStart() { 457 if (fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 458 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE) { 459 return fScanner.getCharacterData().offset; 460 } else { 461 throw new IllegalStateException("Current state = " + getEventTypeString(fEventType) 462 + " is not among the states " + getEventTypeString(XMLEvent.CHARACTERS) + " , " 463 + getEventTypeString(XMLEvent.COMMENT) + " , " + getEventTypeString(XMLEvent.CDATA) 464 + " , " + getEventTypeString(XMLEvent.SPACE) + " valid for getTextStart() "); 465 } 466 } 467 468 /** 469 * @return 470 */ 471 public String getValue() { 472 if (fEventType == XMLEvent.PROCESSING_INSTRUCTION) { 473 return fScanner.getPIData().toString(); 474 } else if (fEventType == XMLEvent.COMMENT) { 475 return fScanner.getComment(); 476 } else if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 477 return fScanner.getElementQName().localpart; 478 } else if (fEventType == XMLEvent.CHARACTERS) { 479 return fScanner.getCharacterData().toString(); 480 } 481 return null; 482 }//getValue() 483 484 /** 485 * Get the XML language version of the current document being parsed 486 */ 487 public String getVersion() { 488 //apply SAP's patch: the default version in the scanner was set to 1.0 because of DOM and SAX 489 //so this patch is a workaround of the difference between StAX and DOM 490 // SAPJVM: Return null if the XML version has not been declared (as specified in the JavaDoc). 491 492 String version = fEntityScanner.getXMLVersion(); 493 494 return "1.0".equals(version) && !fEntityScanner.xmlVersionSetExplicitly ? null : version; 495 } 496 497 /** 498 * @return 499 */ 500 public boolean hasAttributes() { 501 return fScanner.getAttributeIterator().getLength() > 0 ? true : false; 502 } 503 504 /** 505 * this Funtion returns true if the current event has name 506 */ 507 public boolean hasName() { 508 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 509 return true; 510 } else { 511 return false; 512 } 513 }//hasName() 514 515 /** 516 * @throws XMLStreamException 517 * @return 518 */ 519 public boolean hasNext() throws XMLStreamException { 520 //the scanner returns -1 when it detects a broken stream 521 if (fEventType == -1) { 522 return false; 523 } 524 //we can check in scanners if the scanner state is not set to 525 //terminating, we still have more events. 526 return fEventType != XMLEvent.END_DOCUMENT; 527 } 528 529 /** 530 * @return 531 */ 532 public boolean hasValue() { 533 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 534 || fEventType == XMLEvent.ENTITY_REFERENCE || fEventType == XMLEvent.PROCESSING_INSTRUCTION 535 || fEventType == XMLEvent.COMMENT || fEventType == XMLEvent.CHARACTERS) { 536 return true; 537 } else { 538 return false; 539 } 540 541 } 542 543 /** 544 * @return 545 */ 546 public boolean isEndElement() { 547 return fEventType == XMLEvent.END_ELEMENT; 548 } 549 550 /** 551 * @return 552 */ 553 public boolean isStandalone() { 554 return fScanner.isStandAlone(); 555 } 556 557 /** 558 * @return 559 */ 560 public boolean isStartElement() { 561 return fEventType == XMLEvent.START_ELEMENT; 562 } 563 564 /** 565 * Returns true if the cursor points to a character data event that consists 566 * of all whitespace Application calling this method needs to cache the 567 * value and avoid calling this method again for the same event. 568 * 569 * @return 570 */ 571 public boolean isWhiteSpace() { 572 if (isCharacters() || (fEventType == XMLStreamConstants.CDATA)) { 573 char[] ch = this.getTextCharacters(); 574 final int start = this.getTextStart(); 575 final int end = start + this.getTextLength(); 576 for (int i = start; i < end; i++) { 577 if (!XMLChar.isSpace(ch[i])) { 578 return false; 579 } 580 } 581 return true; 582 } 583 return false; 584 } 585 586 /** 587 * @throws XMLStreamException 588 * @return 589 */ 590 public int next() throws XMLStreamException { 591 if (!hasNext()) { 592 if (fEventType != -1) { 593 throw new java.util.NoSuchElementException( 594 "END_DOCUMENT reached: no more elements on the stream."); 595 } else { 596 throw new XMLStreamException( 597 "Error processing input source. The input stream is not complete."); 598 } 599 } 600 try { 601 fEventType = fScanner.next(); 602 603 if (versionStr == null) { 604 versionStr = getVersion(); 605 } 606 607 if (fEventType == XMLStreamConstants.START_DOCUMENT 608 && versionStr != null 609 && versionStr.equals("1.1")) { 610 switchToXML11Scanner(); 611 } 612 613 return fEventType; 614 } catch (IOException ex) { 615 // if this error occured trying to resolve the external DTD subset 616 // and IS_VALIDATING == false, then this is not an XML error 617 if (fScanner.fScannerState == XMLDocumentScannerImpl.SCANNER_STATE_DTD_EXTERNAL) { 618 Boolean isValidating = (Boolean) fPropertyManager.getProperty( 619 XMLInputFactory.IS_VALIDATING); 620 if (isValidating != null 621 && !isValidating.booleanValue()) { 622 // ignore the error, set scanner to known state 623 fEventType = XMLEvent.DTD; 624 fScanner.setScannerState(XMLDocumentScannerImpl.SCANNER_STATE_PROLOG); 625 fScanner.setDriver(fScanner.fPrologDriver); 626 if (fDTDDecl == null 627 || fDTDDecl.length() == 0) { 628 fDTDDecl = "<!-- " 629 + "Exception scanning External DTD Subset. " 630 + "True contents of DTD cannot be determined. " 631 + "Processing will continue as XMLInputFactory.IS_VALIDATING == false." 632 + " -->"; 633 } 634 return XMLEvent.DTD; 635 } 636 } 637 638 // else real error 639 throw new XMLStreamException(ex.getMessage(), getLocation(), ex); 640 } catch (XNIException ex) { 641 throw new XMLStreamException( 642 ex.getMessage(), 643 getLocation(), 644 ex.getException()); 645 } 646 } //next() 647 648 private void switchToXML11Scanner() throws IOException { 649 650 int oldEntityDepth = fScanner.fEntityDepth; 651 com.sun.org.apache.xerces.internal.xni.NamespaceContext oldNamespaceContext 652 = fScanner.fNamespaceContext; 653 654 fScanner = new XML11NSDocumentScannerImpl(); 655 656 //get the new scanner state to old scanner's previous state 657 fScanner.reset(fPropertyManager); 658 fScanner.setPropertyManager(fPropertyManager); 659 fEntityScanner = fEntityManager.getEntityScanner(); 660 fEntityScanner.registerListener(fScanner); 661 fEntityManager.fCurrentEntity.mayReadChunks = true; 662 fScanner.setScannerState(XMLEvent.START_DOCUMENT); 663 664 fScanner.fEntityDepth = oldEntityDepth; 665 fScanner.fNamespaceContext = oldNamespaceContext; 666 fEventType = fScanner.next(); 667 } 668 669 final static String getEventTypeString(int eventType) { 670 switch (eventType) { 671 case XMLEvent.START_ELEMENT: 672 return "START_ELEMENT"; 673 case XMLEvent.END_ELEMENT: 674 return "END_ELEMENT"; 675 case XMLEvent.PROCESSING_INSTRUCTION: 676 return "PROCESSING_INSTRUCTION"; 677 case XMLEvent.CHARACTERS: 678 return "CHARACTERS"; 679 case XMLEvent.COMMENT: 680 return "COMMENT"; 681 case XMLEvent.START_DOCUMENT: 682 return "START_DOCUMENT"; 683 case XMLEvent.END_DOCUMENT: 684 return "END_DOCUMENT"; 685 case XMLEvent.ENTITY_REFERENCE: 686 return "ENTITY_REFERENCE"; 687 case XMLEvent.ATTRIBUTE: 688 return "ATTRIBUTE"; 689 case XMLEvent.DTD: 690 return "DTD"; 691 case XMLEvent.CDATA: 692 return "CDATA"; 693 case XMLEvent.SPACE: 694 return "SPACE"; 695 } 696 return "UNKNOWN_EVENT_TYPE, " + String.valueOf(eventType); 697 } 698 699 /** 700 * Returns the count of attributes on this START_ELEMENT, this method is 701 * only valid on a START_ELEMENT or ATTRIBUTE. This count excludes namespace 702 * definitions. Attribute indices are zero-based. 703 * 704 * @return returns the number of attributes 705 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 706 */ 707 public int getAttributeCount() { 708 //xxx: recognize SAX properties namespace, namespace-prefix to get XML Namespace declarations 709 //does length includes namespace declarations ? 710 711 //State should be either START_ELEMENT or ATTRIBUTE 712 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 713 return fScanner.getAttributeIterator().getLength(); 714 } else { 715 throw new java.lang.IllegalStateException("Current state is not among the states " 716 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 717 + getEventTypeString(XMLEvent.ATTRIBUTE) 718 + "valid for getAttributeCount()"); 719 } 720 }//getAttributeCount 721 722 /** 723 * Returns the localName of the attribute at the provided index 724 * 725 * @param index the position of the attribute 726 * @return the localName of the attribute 727 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 728 */ 729 public QName getAttributeName(int index) { 730 //State should be either START_ELEMENT or ATTRIBUTE 731 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 732 return convertXNIQNametoJavaxQName(fScanner.getAttributeIterator().getQualifiedName(index)); 733 } else { 734 throw new java.lang.IllegalStateException("Current state is not among the states " 735 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 736 + getEventTypeString(XMLEvent.ATTRIBUTE) 737 + "valid for getAttributeName()"); 738 } 739 }//getAttributeName 740 741 /** 742 * @param index 743 * @return 744 */ 745 public String getAttributeLocalName(int index) { 746 //State should be either START_ELEMENT or ATTRIBUTE 747 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 748 return fScanner.getAttributeIterator().getLocalName(index); 749 } else { 750 throw new java.lang.IllegalStateException(); 751 } 752 }//getAttributeName 753 754 /** 755 * Returns the namespace of the attribute at the provided index 756 * 757 * @param index the position of the attribute 758 * @return the namespace URI (can be null) 759 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 760 */ 761 public String getAttributeNamespace(int index) { 762 //State should be either START_ELEMENT or ATTRIBUTE 763 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 764 return fScanner.getAttributeIterator().getURI(index); 765 } else { 766 throw new java.lang.IllegalStateException("Current state is not among the states " 767 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 768 + getEventTypeString(XMLEvent.ATTRIBUTE) 769 + "valid for getAttributeNamespace()"); 770 } 771 772 }//getAttributeNamespace 773 774 /** 775 * Returns the prefix of this attribute at the provided index 776 * 777 * @param index the position of the attribute 778 * @return the prefix of the attribute 779 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 780 */ 781 public String getAttributePrefix(int index) { 782 //State should be either START_ELEMENT or ATTRIBUTE 783 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 784 return fScanner.getAttributeIterator().getPrefix(index); 785 } else { 786 throw new java.lang.IllegalStateException("Current state is not among the states " 787 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 788 + getEventTypeString(XMLEvent.ATTRIBUTE) 789 + "valid for getAttributePrefix()"); 790 } 791 }//getAttributePrefix 792 793 /** 794 * Returns the qname of the attribute at the provided index 795 * 796 * @param index the position of the attribute 797 * @return the QName of the attribute 798 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 799 */ 800 public javax.xml.namespace.QName getAttributeQName(int index) { 801 //State should be either START_ELEMENT or ATTRIBUTE 802 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 803 // create new object at runtime.. 804 String localName = fScanner.getAttributeIterator().getLocalName(index); 805 String uri = fScanner.getAttributeIterator().getURI(index); 806 return new javax.xml.namespace.QName(uri, localName); 807 } else { 808 throw new java.lang.IllegalStateException("Current state is not among the states " 809 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 810 + getEventTypeString(XMLEvent.ATTRIBUTE) 811 + "valid for getAttributeQName()"); 812 } 813 }//getAttributeQName 814 815 /** 816 * Returns the XML type of the attribute at the provided index 817 * 818 * @param index the position of the attribute 819 * @return the XML type of the attribute 820 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 821 */ 822 public String getAttributeType(int index) { 823 //State should be either START_ELEMENT or ATTRIBUTE 824 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 825 return fScanner.getAttributeIterator().getType(index); 826 } else { 827 throw new java.lang.IllegalStateException("Current state is not among the states " 828 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 829 + getEventTypeString(XMLEvent.ATTRIBUTE) 830 + "valid for getAttributeType()"); 831 } 832 833 }//getAttributeType 834 835 /** 836 * Returns the value of the attribute at the index 837 * 838 * @param index the position of the attribute 839 * @return the attribute value 840 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 841 */ 842 public String getAttributeValue(int index) { 843 //State should be either START_ELEMENT or ATTRIBUTE 844 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 845 return fScanner.getAttributeIterator().getValue(index); 846 } else { 847 throw new java.lang.IllegalStateException("Current state is not among the states " 848 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 849 + getEventTypeString(XMLEvent.ATTRIBUTE) 850 + "valid for getAttributeValue()"); 851 } 852 853 }//getAttributeValue 854 855 /** 856 * @param namespaceURI 857 * @param localName 858 * @return 859 */ 860 public String getAttributeValue(String namespaceURI, String localName) { 861 //State should be either START_ELEMENT or ATTRIBUTE 862 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 863 XMLAttributesImpl attributes = fScanner.getAttributeIterator(); 864 if (namespaceURI == null) { //sjsxp issue 70 865 return attributes.getValue(attributes.getIndexByLocalName(localName)); 866 } else { 867 return fScanner.getAttributeIterator().getValue( 868 namespaceURI.length() == 0 ? null : namespaceURI, localName); 869 } 870 871 } else { 872 throw new java.lang.IllegalStateException("Current state is not among the states " 873 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 874 + getEventTypeString(XMLEvent.ATTRIBUTE) 875 + "valid for getAttributeValue()"); 876 } 877 878 } 879 880 /** 881 * Reads the content of a text-only element. Precondition: the current event 882 * is START_ELEMENT. Postcondition: The current event is the corresponding 883 * END_ELEMENT. 884 * 885 * @throws XMLStreamException if the current event is not a START_ELEMENT or 886 * if a non text element is encountered 887 */ 888 public String getElementText() throws XMLStreamException { 889 890 if (getEventType() != XMLStreamConstants.START_ELEMENT) { 891 throw new XMLStreamException( 892 "parser must be on START_ELEMENT to read next text", getLocation()); 893 } 894 int eventType = next(); 895 StringBuilder content = new StringBuilder(); 896 while (eventType != XMLStreamConstants.END_ELEMENT) { 897 if (eventType == XMLStreamConstants.CHARACTERS 898 || eventType == XMLStreamConstants.CDATA 899 || eventType == XMLStreamConstants.SPACE 900 || eventType == XMLStreamConstants.ENTITY_REFERENCE) { 901 content.append(getText()); 902 } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 903 || eventType == XMLStreamConstants.COMMENT) { 904 // skipping 905 } else if (eventType == XMLStreamConstants.END_DOCUMENT) { 906 throw new XMLStreamException( 907 "unexpected end of document when reading element text content"); 908 } else if (eventType == XMLStreamConstants.START_ELEMENT) { 909 throw new XMLStreamException("elementGetText() function expects text " 910 + "only elment but START_ELEMENT was encountered.", getLocation()); 911 } else { 912 throw new XMLStreamException( 913 "Unexpected event type " + eventType, getLocation()); 914 } 915 eventType = next(); 916 } 917 return content.toString(); 918 } 919 920 /** 921 * Return the current location of the processor. If the Location is unknown 922 * the processor should return an implementation of Location that returns -1 923 * for the location and null for the publicId and systemId. The location 924 * information is only valid until next() is called. 925 */ 926 public Location getLocation() { 927 return new Location() { 928 String _systemId = fEntityScanner.getExpandedSystemId(); 929 String _publicId = fEntityScanner.getPublicId(); 930 int _offset = fEntityScanner.getCharacterOffset(); 931 int _columnNumber = fEntityScanner.getColumnNumber(); 932 int _lineNumber = fEntityScanner.getLineNumber(); 933 934 public String getLocationURI() { 935 return _systemId; 936 } 937 938 public int getCharacterOffset() { 939 return _offset; 940 } 941 942 public int getColumnNumber() { 943 return _columnNumber; 944 } 945 946 public int getLineNumber() { 947 return _lineNumber; 948 } 949 950 public String getPublicId() { 951 return _publicId; 952 } 953 954 public String getSystemId() { 955 return _systemId; 956 } 957 958 public String toString() { 959 StringBuilder sbuffer = new StringBuilder(); 960 sbuffer.append("Line number = " + getLineNumber()); 961 sbuffer.append("\n"); 962 sbuffer.append("Column number = " + getColumnNumber()); 963 sbuffer.append("\n"); 964 sbuffer.append("System Id = " + getSystemId()); 965 sbuffer.append("\n"); 966 sbuffer.append("Public Id = " + getPublicId()); 967 sbuffer.append("\n"); 968 sbuffer.append("Location Uri= " + getLocationURI()); 969 sbuffer.append("\n"); 970 sbuffer.append("CharacterOffset = " + getCharacterOffset()); 971 sbuffer.append("\n"); 972 return sbuffer.toString(); 973 } 974 }; 975 976 } 977 978 /** 979 * Returns a QName for the current START_ELEMENT or END_ELEMENT event 980 * 981 * @return the QName for the current START_ELEMENT or END_ELEMENT event 982 */ 983 public javax.xml.namespace.QName getName() { 984 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 985 return convertXNIQNametoJavaxQName(fScanner.getElementQName()); 986 } else { 987 throw new java.lang.IllegalStateException("Illegal to call getName() " 988 + "when event type is " + getEventTypeString(fEventType) + "." 989 + " Valid states are " + getEventTypeString(XMLEvent.START_ELEMENT) + ", " 990 + getEventTypeString(XMLEvent.END_ELEMENT)); 991 } 992 } 993 994 /** 995 * Returns a read only namespace context for the current position. The 996 * context is transient and only valid until a call to next() changes the 997 * state of the reader. 998 * 999 * @return return a namespace context 1000 */ 1001 public NamespaceContext getNamespaceContext() { 1002 return fNamespaceContextWrapper; 1003 } 1004 1005 /** 1006 * Returns the count of namespaces declared on this START_ELEMENT or 1007 * END_ELEMENT, this method is only valid on a START_ELEMENT, END_ELEMENT or 1008 * NAMESPACE. On an END_ELEMENT the count is of the namespaces that are 1009 * about to go out of scope. This is the equivalent of the information 1010 * reported by SAX callback for an end element event. 1011 * 1012 * @return returns the number of namespace declarations on this specific 1013 * element 1014 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT 1015 * or NAMESPACE 1016 */ 1017 public int getNamespaceCount() { 1018 //namespaceContext is dynamic object. 1019 //REVISIT: check if it specifies all conditions mentioned in the javadoc 1020 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 1021 || fEventType == XMLEvent.NAMESPACE) { 1022 return fScanner.getNamespaceContext().getDeclaredPrefixCount(); 1023 } else { 1024 throw new IllegalStateException("Current event state is " + getEventTypeString(fEventType) 1025 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 1026 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 1027 + getEventTypeString(XMLEvent.NAMESPACE) 1028 + " valid for getNamespaceCount()."); 1029 } 1030 } 1031 1032 /** 1033 * Returns the prefix for the namespace declared at the index. Returns null 1034 * if this is the default namespace declaration 1035 * 1036 * @param index the position of the namespace declaration 1037 * @return returns the namespace prefix 1038 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT 1039 * or NAMESPACE 1040 */ 1041 public String getNamespacePrefix(int index) { 1042 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 1043 || fEventType == XMLEvent.NAMESPACE) { 1044 //namespaceContext is dynamic object. 1045 String prefix = fScanner.getNamespaceContext().getDeclaredPrefixAt(index); 1046 return prefix.equals("") ? null : prefix; 1047 } else { 1048 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1049 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 1050 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 1051 + getEventTypeString(XMLEvent.NAMESPACE) 1052 + " valid for getNamespacePrefix()."); 1053 } 1054 } 1055 1056 /** 1057 * Returns the uri for the namespace declared at the index. 1058 * 1059 * @param index the position of the namespace declaration 1060 * @return returns the namespace uri 1061 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT 1062 * or NAMESPACE 1063 */ 1064 public String getNamespaceURI(int index) { 1065 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 1066 || fEventType == XMLEvent.NAMESPACE) { 1067 //namespaceContext is dynamic object. 1068 return fScanner.getNamespaceContext().getURI(fScanner.getNamespaceContext() 1069 .getDeclaredPrefixAt(index)); 1070 } else { 1071 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1072 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 1073 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 1074 + getEventTypeString(XMLEvent.NAMESPACE) 1075 + " valid for getNamespaceURI()."); 1076 } 1077 1078 } 1079 1080 /** 1081 * Get the value of a feature/property from the underlying implementation 1082 * 1083 * @param name The name of the property, may not be null 1084 * @return The value of the property 1085 * @throws IllegalArgumentException if name is null 1086 */ 1087 public Object getProperty(java.lang.String name) throws java.lang.IllegalArgumentException { 1088 if (name == null) { 1089 throw new java.lang.IllegalArgumentException(); 1090 } 1091 if (fPropertyManager != null) { 1092 if (name.equals(PropertyManager.STAX_NOTATIONS)) { 1093 return getNotationDecls(); 1094 } else if (name.equals(PropertyManager.STAX_ENTITIES)) { 1095 return getEntityDecls(); 1096 } else { 1097 return fPropertyManager.getProperty(name); 1098 } 1099 } 1100 return null; 1101 } 1102 1103 /** 1104 * Returns the current value of the parse event as a string, this returns 1105 * the string value of a CHARACTERS event, returns the value of a COMMENT, 1106 * the replacement value for an ENTITY_REFERENCE, or the String value of the 1107 * DTD 1108 * 1109 * @return the current text or null 1110 * @throws java.lang.IllegalStateException if this state is not a valid text 1111 * state. 1112 */ 1113 public String getText() { 1114 if (fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 1115 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE) { 1116 //this requires creation of new string 1117 //fEventType == XMLEvent.ENTITY_REFERENCE 1118 return fScanner.getCharacterData().toString(); 1119 } else if (fEventType == XMLEvent.ENTITY_REFERENCE) { 1120 String name = fScanner.getEntityName(); 1121 if (name != null) { 1122 if (fScanner.foundBuiltInRefs) { 1123 return fScanner.getCharacterData().toString(); 1124 } 1125 1126 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1127 Entity en = entityStore.getEntity(name); 1128 if (en == null) { 1129 return null; 1130 } 1131 if (en.isExternal()) { 1132 return ((Entity.ExternalEntity) en).entityLocation.getExpandedSystemId(); 1133 } else { 1134 return ((Entity.InternalEntity) en).text; 1135 } 1136 } else { 1137 return null; 1138 } 1139 } else if (fEventType == XMLEvent.DTD) { 1140 if (fDTDDecl != null) { 1141 return fDTDDecl; 1142 } 1143 XMLStringBuffer tmpBuffer = fScanner.getDTDDecl(); 1144 fDTDDecl = tmpBuffer.toString(); 1145 return fDTDDecl; 1146 } else { 1147 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1148 + " is not among the states" + getEventTypeString(XMLEvent.CHARACTERS) + ", " 1149 + getEventTypeString(XMLEvent.COMMENT) + ", " 1150 + getEventTypeString(XMLEvent.CDATA) + ", " 1151 + getEventTypeString(XMLEvent.SPACE) + ", " 1152 + getEventTypeString(XMLEvent.ENTITY_REFERENCE) + ", " 1153 + getEventTypeString(XMLEvent.DTD) + " valid for getText() "); 1154 } 1155 }//getText 1156 1157 /** 1158 * Test if the current event is of the given type and if the namespace and 1159 * name match the current namespace and name of the current event. If the 1160 * namespaceURI is null it is not checked for equality, if the localName is 1161 * null it is not checked for equality. 1162 * 1163 * @param type the event type 1164 * @param namespaceURI the uri of the event, may be null 1165 * @param localName the localName of the event, may be null 1166 * @throws XMLStreamException if the required values are not matched. 1167 */ 1168 public void require(int type, String namespaceURI, String localName) throws XMLStreamException { 1169 if (type != fEventType) { 1170 throw new XMLStreamException("Event type " + getEventTypeString(type) + " specified did " 1171 + "not match with current parser event " + getEventTypeString(fEventType)); 1172 } 1173 if (namespaceURI != null && !namespaceURI.equals(getNamespaceURI())) { 1174 throw new XMLStreamException("Namespace URI " + namespaceURI + " specified did not match " 1175 + "with current namespace URI"); 1176 } 1177 if (localName != null && !localName.equals(getLocalName())) { 1178 throw new XMLStreamException("LocalName " + localName + " specified did not match with " 1179 + "current local name"); 1180 } 1181 return; 1182 } 1183 1184 /** 1185 * Gets the the text associated with a CHARACTERS, SPACE or CDATA event. 1186 * Text starting a "sourceStart" is copied into "destination" starting at 1187 * "targetStart". Up to "length" characters are copied. The number of 1188 * characters actually copied is returned. 1189 * 1190 * The "sourceStart" argument must be greater or equal to 0 and less than or 1191 * equal to the number of characters associated with the event. Usually, one 1192 * requests text starting at a "sourceStart" of 0. If the number of 1193 * characters actually copied is less than the "length", then there is no 1194 * more text. Otherwise, subsequent calls need to be made until all text has 1195 * been retrieved. For example: 1196 * 1197 * <code> 1198 * int length = 1024; 1199 * char[] myBuffer = new char[ length ]; 1200 * 1201 * for ( int sourceStart = 0 ; ; sourceStart += length ) 1202 * { 1203 * int nCopied = stream.getTextCharacters( sourceStart, myBuffer, 0, length ); 1204 * 1205 * if (nCopied < length) 1206 * break; 1207 * } 1208 * </code> XMLStreamException may be thrown if there are any XML errors in 1209 * the underlying source. The "targetStart" argument must be greater than or 1210 * equal to 0 and less than the length of "target", Length must be greater 1211 * than 0 and "targetStart + length" must be less than or equal to length of 1212 * "target". 1213 * 1214 * @param sourceStart the index of the first character in the source array 1215 * to copy 1216 * @param target the destination array 1217 * @param targetStart the start offset in the target array 1218 * @param length the number of characters to copy 1219 * @return the number of characters actually copied 1220 * @throws XMLStreamException if the underlying XML source is not 1221 * well-formed 1222 * @throws IndexOutOfBoundsException if targetStart < 0 or > than the length 1223 * of target 1224 * @throws IndexOutOfBoundwhile(isCharacters()) ;sException if length < 0 or targetStart + length 1225 * > length of target 1226 * @throws UnsupportedOperationException if this method is not supported 1227 * @throws NullPointerException is if target is null 1228 */ 1229 public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) 1230 throws XMLStreamException { 1231 1232 if (target == null) { 1233 throw new NullPointerException("target char array can't be null"); 1234 } 1235 1236 if (targetStart < 0 || length < 0 || sourceStart < 0 || targetStart >= target.length 1237 || (targetStart + length) > target.length) { 1238 throw new IndexOutOfBoundsException(); 1239 } 1240 1241 //getTextStart() + sourceStart should not be greater than the lenght of number of characters 1242 //present 1243 int copiedLength = 0; 1244 //int presentDataLen = getTextLength() - (getTextStart()+sourceStart); 1245 int available = getTextLength() - sourceStart; 1246 if (available < 0) { 1247 throw new IndexOutOfBoundsException("sourceStart is greater than" 1248 + "number of characters associated with this event"); 1249 } 1250 if (available < length) { 1251 copiedLength = available; 1252 } else { 1253 copiedLength = length; 1254 } 1255 1256 System.arraycopy(getTextCharacters(), getTextStart() + sourceStart, target, targetStart, copiedLength); 1257 return copiedLength; 1258 } 1259 1260 /** 1261 * Return true if the current event has text, false otherwise The following 1262 * events have text: CHARACTERS,DTD ,ENTITY_REFERENCE, COMMENT 1263 */ 1264 public boolean hasText() { 1265 if (DEBUG) { 1266 pr("XMLReaderImpl#EVENT TYPE = " + fEventType); 1267 } 1268 if (fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 1269 || fEventType == XMLEvent.CDATA) { 1270 return fScanner.getCharacterData().length > 0; 1271 } else if (fEventType == XMLEvent.ENTITY_REFERENCE) { 1272 String name = fScanner.getEntityName(); 1273 if (name != null) { 1274 if (fScanner.foundBuiltInRefs) { 1275 return true; 1276 } 1277 1278 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1279 Entity en = entityStore.getEntity(name); 1280 if (en == null) { 1281 return false; 1282 } 1283 if (en.isExternal()) { 1284 return ((Entity.ExternalEntity) en).entityLocation.getExpandedSystemId() != null; 1285 } else { 1286 return ((Entity.InternalEntity) en).text != null; 1287 } 1288 } else { 1289 return false; 1290 } 1291 } else if (fEventType == XMLEvent.DTD) { 1292 return fScanner.fSeenDoctypeDecl; 1293 } 1294 return false; 1295 } 1296 1297 /** 1298 * Returns a boolean which indicates if this attribute was created by 1299 * default 1300 * 1301 * @param index the position of the attribute 1302 * @return true if this is a default attribute 1303 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 1304 */ 1305 public boolean isAttributeSpecified(int index) { 1306 //check that current state should be either START_ELEMENT or ATTRIBUTE 1307 if ((fEventType == XMLEvent.START_ELEMENT) || (fEventType == XMLEvent.ATTRIBUTE)) { 1308 return fScanner.getAttributeIterator().isSpecified(index); 1309 } else { 1310 throw new IllegalStateException("Current state is not among the states " 1311 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 1312 + getEventTypeString(XMLEvent.ATTRIBUTE) 1313 + "valid for isAttributeSpecified()"); 1314 } 1315 } 1316 1317 /** 1318 * Returns true if the cursor points to a character data event 1319 * 1320 * @return true if the cursor points to character data, false otherwise 1321 */ 1322 public boolean isCharacters() { 1323 return fEventType == XMLEvent.CHARACTERS; 1324 } 1325 1326 /** 1327 * Skips any insignificant events (COMMENT and PROCESSING_INSTRUCTION) until 1328 * a START_ELEMENT or END_ELEMENT is reached. If other than space characters 1329 * are encountered, an exception is thrown. This method should be used when 1330 * processing element-only content because the parser is not able to 1331 * recognize ignorable whitespace if then DTD is missing or not interpreted. 1332 * 1333 * @return the event type of the element read 1334 * @throws XMLStreamException if the current event is not white space 1335 */ 1336 public int nextTag() throws XMLStreamException { 1337 1338 int eventType = next(); 1339 while ((eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace()) // skip whitespace 1340 || (eventType == XMLStreamConstants.CDATA && isWhiteSpace()) 1341 // skip whitespace 1342 || eventType == XMLStreamConstants.SPACE 1343 || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 1344 || eventType == XMLStreamConstants.COMMENT) { 1345 eventType = next(); 1346 } 1347 1348 if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) { 1349 throw new XMLStreamException( 1350 "found: " + getEventTypeString(eventType) 1351 + ", expected " + getEventTypeString(XMLStreamConstants.START_ELEMENT) 1352 + " or " + getEventTypeString(XMLStreamConstants.END_ELEMENT), 1353 getLocation()); 1354 } 1355 1356 return eventType; 1357 } 1358 1359 /** 1360 * Checks if standalone was set in the document 1361 * 1362 * @return true if standalone was set in the document, or false otherwise 1363 */ 1364 public boolean standaloneSet() { 1365 //xxx: it requires if the standalone was set in the document ? This is different that if the document 1366 // is standalone 1367 return fScanner.standaloneSet(); 1368 } 1369 1370 /** 1371 * @param qname 1372 * @return 1373 */ 1374 public javax.xml.namespace.QName convertXNIQNametoJavaxQName( 1375 com.sun.org.apache.xerces.internal.xni.QName qname) { 1376 if (qname == null) { 1377 return null; 1378 } 1379 //xxx: prefix definition ? 1380 if (qname.prefix == null) { 1381 return new javax.xml.namespace.QName(qname.uri, qname.localpart); 1382 } else { 1383 return new javax.xml.namespace.QName(qname.uri, qname.localpart, qname.prefix); 1384 } 1385 } 1386 1387 /** 1388 * Return the uri for the given prefix. The uri returned depends on the 1389 * current state of the processor. 1390 * 1391 * <p> 1392 * <strong>NOTE:</strong>The 'xml' prefix is bound as defined in 1393 * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in 1394 * XML</a> 1395 * specification to "http://www.w3.org/XML/1998/namespace". 1396 * 1397 * <p> 1398 * <strong>NOTE:</strong> The 'xmlns' prefix must be resolved to following 1399 * namespace 1400 * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a> 1401 * 1402 * @return the uri bound to the given prefix or null if it is not bound 1403 * @param prefix The prefix to lookup, may not be null 1404 * @throws IllegalStateException - if the prefix is null 1405 */ 1406 public String getNamespaceURI(String prefix) { 1407 if (prefix == null) { 1408 throw new java.lang.IllegalArgumentException("prefix cannot be null."); 1409 } 1410 1411 //first add the string to symbol table.. since internally identity comparisons are done. 1412 return fScanner.getNamespaceContext().getURI(fSymbolTable.addSymbol(prefix)); 1413 } 1414 1415 //xxx: this function is not being used. 1416 protected void setPropertyManager(PropertyManager propertyManager) { 1417 fPropertyManager = propertyManager; 1418 //REVISIT: we were supplying hashmap ealier 1419 fScanner.setProperty("stax-properties", propertyManager); 1420 fScanner.setPropertyManager(propertyManager); 1421 } 1422 1423 /** 1424 * @return returns the reference to property manager. 1425 */ 1426 protected PropertyManager getPropertyManager() { 1427 return fPropertyManager; 1428 } 1429 1430 static void pr(String str) { 1431 System.out.println(str); 1432 } 1433 1434 protected List<EntityDeclaration> getEntityDecls() { 1435 if (fEventType == XMLStreamConstants.DTD) { 1436 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1437 ArrayList<EntityDeclaration> list = null; 1438 Map<String, Entity> entities = entityStore.getEntities(); 1439 if (entities.size() > 0) { 1440 EntityDeclarationImpl decl = null; 1441 list = new ArrayList<>(entities.size()); 1442 for (Map.Entry<String, Entity> entry : entities.entrySet()) { 1443 String key = entry.getKey(); 1444 Entity en = entry.getValue(); 1445 decl = new EntityDeclarationImpl(); 1446 decl.setEntityName(key); 1447 if (en.isExternal()) { 1448 decl.setXMLResourceIdentifier(((Entity.ExternalEntity) en).entityLocation); 1449 decl.setNotationName(((Entity.ExternalEntity) en).notation); 1450 } else { 1451 decl.setEntityReplacementText(((Entity.InternalEntity) en).text); 1452 } 1453 list.add(decl); 1454 } 1455 } 1456 return list; 1457 } 1458 return null; 1459 } 1460 1461 protected List<NotationDeclaration> getNotationDecls() { 1462 if (fEventType == XMLStreamConstants.DTD) { 1463 if (fScanner.fDTDScanner == null) { 1464 return null; 1465 } 1466 DTDGrammar grammar = ((XMLDTDScannerImpl) (fScanner.fDTDScanner)).getGrammar(); 1467 if (grammar == null) { 1468 return null; 1469 } 1470 List<XMLNotationDecl> notations = grammar.getNotationDecls(); 1471 ArrayList<NotationDeclaration> list = new ArrayList<>(); 1472 for (XMLNotationDecl notation : notations) { 1473 if (notation != null) { 1474 list.add(new NotationDeclarationImpl(notation)); 1475 } 1476 } 1477 return list; 1478 } 1479 return null; 1480 } 1481 1482 }//XMLReaderImpl |