1 /* 2 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 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 if (fEventType == XMLStreamConstants.CHARACTERS || 614 fEventType == XMLStreamConstants.ENTITY_REFERENCE || 615 fEventType == XMLStreamConstants.PROCESSING_INSTRUCTION || 616 fEventType == XMLStreamConstants.COMMENT || 617 fEventType == XMLStreamConstants.CDATA) { 618 fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity); 619 } 620 621 return fEventType; 622 } catch (IOException ex) { 623 // if this error occured trying to resolve the external DTD subset 624 // and IS_VALIDATING == false, then this is not an XML error 625 if (fScanner.fScannerState == XMLDocumentScannerImpl.SCANNER_STATE_DTD_EXTERNAL) { 626 Boolean isValidating = (Boolean) fPropertyManager.getProperty( 627 XMLInputFactory.IS_VALIDATING); 628 if (isValidating != null 629 && !isValidating.booleanValue()) { 630 // ignore the error, set scanner to known state 631 fEventType = XMLEvent.DTD; 632 fScanner.setScannerState(XMLDocumentScannerImpl.SCANNER_STATE_PROLOG); 633 fScanner.setDriver(fScanner.fPrologDriver); 634 if (fDTDDecl == null 635 || fDTDDecl.length() == 0) { 636 fDTDDecl = "<!-- " 637 + "Exception scanning External DTD Subset. " 638 + "True contents of DTD cannot be determined. " 639 + "Processing will continue as XMLInputFactory.IS_VALIDATING == false." 640 + " -->"; 641 } 642 return XMLEvent.DTD; 643 } 644 } 645 646 // else real error 647 throw new XMLStreamException(ex.getMessage(), getLocation(), ex); 648 } catch (XNIException ex) { 649 throw new XMLStreamException( 650 ex.getMessage(), 651 getLocation(), 652 ex.getException()); 653 } 654 } //next() 655 656 private void switchToXML11Scanner() throws IOException { 657 658 int oldEntityDepth = fScanner.fEntityDepth; 659 com.sun.org.apache.xerces.internal.xni.NamespaceContext oldNamespaceContext 660 = fScanner.fNamespaceContext; 661 662 fScanner = new XML11NSDocumentScannerImpl(); 663 664 //get the new scanner state to old scanner's previous state 665 fScanner.reset(fPropertyManager); 666 fScanner.setPropertyManager(fPropertyManager); 667 fEntityScanner = fEntityManager.getEntityScanner(); 668 fEntityScanner.registerListener(fScanner); 669 fEntityManager.fCurrentEntity.mayReadChunks = true; 670 fScanner.setScannerState(XMLEvent.START_DOCUMENT); 671 672 fScanner.fEntityDepth = oldEntityDepth; 673 fScanner.fNamespaceContext = oldNamespaceContext; 674 fEventType = fScanner.next(); 675 } 676 677 final static String getEventTypeString(int eventType) { 678 switch (eventType) { 679 case XMLEvent.START_ELEMENT: 680 return "START_ELEMENT"; 681 case XMLEvent.END_ELEMENT: 682 return "END_ELEMENT"; 683 case XMLEvent.PROCESSING_INSTRUCTION: 684 return "PROCESSING_INSTRUCTION"; 685 case XMLEvent.CHARACTERS: 686 return "CHARACTERS"; 687 case XMLEvent.COMMENT: 688 return "COMMENT"; 689 case XMLEvent.START_DOCUMENT: 690 return "START_DOCUMENT"; 691 case XMLEvent.END_DOCUMENT: 692 return "END_DOCUMENT"; 693 case XMLEvent.ENTITY_REFERENCE: 694 return "ENTITY_REFERENCE"; 695 case XMLEvent.ATTRIBUTE: 696 return "ATTRIBUTE"; 697 case XMLEvent.DTD: 698 return "DTD"; 699 case XMLEvent.CDATA: 700 return "CDATA"; 701 case XMLEvent.SPACE: 702 return "SPACE"; 703 } 704 return "UNKNOWN_EVENT_TYPE, " + String.valueOf(eventType); 705 } 706 707 /** 708 * Returns the count of attributes on this START_ELEMENT, this method is 709 * only valid on a START_ELEMENT or ATTRIBUTE. This count excludes namespace 710 * definitions. Attribute indices are zero-based. 711 * 712 * @return returns the number of attributes 713 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 714 */ 715 public int getAttributeCount() { 716 //xxx: recognize SAX properties namespace, namespace-prefix to get XML Namespace declarations 717 //does length includes namespace declarations ? 718 719 //State should be either START_ELEMENT or ATTRIBUTE 720 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 721 return fScanner.getAttributeIterator().getLength(); 722 } else { 723 throw new java.lang.IllegalStateException("Current state is not among the states " 724 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 725 + getEventTypeString(XMLEvent.ATTRIBUTE) 726 + "valid for getAttributeCount()"); 727 } 728 }//getAttributeCount 729 730 /** 731 * Returns the localName of the attribute at the provided index 732 * 733 * @param index the position of the attribute 734 * @return the localName of the attribute 735 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 736 */ 737 public QName getAttributeName(int index) { 738 //State should be either START_ELEMENT or ATTRIBUTE 739 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 740 return convertXNIQNametoJavaxQName(fScanner.getAttributeIterator().getQualifiedName(index)); 741 } else { 742 throw new java.lang.IllegalStateException("Current state is not among the states " 743 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 744 + getEventTypeString(XMLEvent.ATTRIBUTE) 745 + "valid for getAttributeName()"); 746 } 747 }//getAttributeName 748 749 /** 750 * @param index 751 * @return 752 */ 753 public String getAttributeLocalName(int index) { 754 //State should be either START_ELEMENT or ATTRIBUTE 755 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 756 return fScanner.getAttributeIterator().getLocalName(index); 757 } else { 758 throw new java.lang.IllegalStateException(); 759 } 760 }//getAttributeName 761 762 /** 763 * Returns the namespace of the attribute at the provided index 764 * 765 * @param index the position of the attribute 766 * @return the namespace URI (can be null) 767 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 768 */ 769 public String getAttributeNamespace(int index) { 770 //State should be either START_ELEMENT or ATTRIBUTE 771 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 772 return fScanner.getAttributeIterator().getURI(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 getAttributeNamespace()"); 778 } 779 780 }//getAttributeNamespace 781 782 /** 783 * Returns the prefix of this attribute at the provided index 784 * 785 * @param index the position of the attribute 786 * @return the prefix of the attribute 787 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 788 */ 789 public String getAttributePrefix(int index) { 790 //State should be either START_ELEMENT or ATTRIBUTE 791 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 792 return fScanner.getAttributeIterator().getPrefix(index); 793 } else { 794 throw new java.lang.IllegalStateException("Current state is not among the states " 795 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 796 + getEventTypeString(XMLEvent.ATTRIBUTE) 797 + "valid for getAttributePrefix()"); 798 } 799 }//getAttributePrefix 800 801 /** 802 * Returns the qname of the attribute at the provided index 803 * 804 * @param index the position of the attribute 805 * @return the QName of the attribute 806 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 807 */ 808 public javax.xml.namespace.QName getAttributeQName(int index) { 809 //State should be either START_ELEMENT or ATTRIBUTE 810 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 811 // create new object at runtime.. 812 String localName = fScanner.getAttributeIterator().getLocalName(index); 813 String uri = fScanner.getAttributeIterator().getURI(index); 814 return new javax.xml.namespace.QName(uri, localName); 815 } else { 816 throw new java.lang.IllegalStateException("Current state is not among the states " 817 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 818 + getEventTypeString(XMLEvent.ATTRIBUTE) 819 + "valid for getAttributeQName()"); 820 } 821 }//getAttributeQName 822 823 /** 824 * Returns the XML type of the attribute at the provided index 825 * 826 * @param index the position of the attribute 827 * @return the XML type of the attribute 828 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 829 */ 830 public String getAttributeType(int index) { 831 //State should be either START_ELEMENT or ATTRIBUTE 832 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 833 return fScanner.getAttributeIterator().getType(index); 834 } else { 835 throw new java.lang.IllegalStateException("Current state is not among the states " 836 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 837 + getEventTypeString(XMLEvent.ATTRIBUTE) 838 + "valid for getAttributeType()"); 839 } 840 841 }//getAttributeType 842 843 /** 844 * Returns the value of the attribute at the index 845 * 846 * @param index the position of the attribute 847 * @return the attribute value 848 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 849 */ 850 public String getAttributeValue(int index) { 851 //State should be either START_ELEMENT or ATTRIBUTE 852 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 853 return fScanner.getAttributeIterator().getValue(index); 854 } else { 855 throw new java.lang.IllegalStateException("Current state is not among the states " 856 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 857 + getEventTypeString(XMLEvent.ATTRIBUTE) 858 + "valid for getAttributeValue()"); 859 } 860 861 }//getAttributeValue 862 863 /** 864 * @param namespaceURI 865 * @param localName 866 * @return 867 */ 868 public String getAttributeValue(String namespaceURI, String localName) { 869 //State should be either START_ELEMENT or ATTRIBUTE 870 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.ATTRIBUTE) { 871 XMLAttributesImpl attributes = fScanner.getAttributeIterator(); 872 if (namespaceURI == null) { //sjsxp issue 70 873 return attributes.getValue(attributes.getIndexByLocalName(localName)); 874 } else { 875 return fScanner.getAttributeIterator().getValue( 876 namespaceURI.length() == 0 ? null : namespaceURI, localName); 877 } 878 879 } else { 880 throw new java.lang.IllegalStateException("Current state is not among the states " 881 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 882 + getEventTypeString(XMLEvent.ATTRIBUTE) 883 + "valid for getAttributeValue()"); 884 } 885 886 } 887 888 /** 889 * Reads the content of a text-only element. Precondition: the current event 890 * is START_ELEMENT. Postcondition: The current event is the corresponding 891 * END_ELEMENT. 892 * 893 * @throws XMLStreamException if the current event is not a START_ELEMENT or 894 * if a non text element is encountered 895 */ 896 public String getElementText() throws XMLStreamException { 897 898 if (getEventType() != XMLStreamConstants.START_ELEMENT) { 899 throw new XMLStreamException( 900 "parser must be on START_ELEMENT to read next text", getLocation()); 901 } 902 int eventType = next(); 903 StringBuilder content = new StringBuilder(); 904 while (eventType != XMLStreamConstants.END_ELEMENT) { 905 if (eventType == XMLStreamConstants.CHARACTERS 906 || eventType == XMLStreamConstants.CDATA 907 || eventType == XMLStreamConstants.SPACE 908 || eventType == XMLStreamConstants.ENTITY_REFERENCE) { 909 content.append(getText()); 910 } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 911 || eventType == XMLStreamConstants.COMMENT) { 912 // skipping 913 } else if (eventType == XMLStreamConstants.END_DOCUMENT) { 914 throw new XMLStreamException( 915 "unexpected end of document when reading element text content"); 916 } else if (eventType == XMLStreamConstants.START_ELEMENT) { 917 throw new XMLStreamException("elementGetText() function expects text " 918 + "only elment but START_ELEMENT was encountered.", getLocation()); 919 } else { 920 throw new XMLStreamException( 921 "Unexpected event type " + eventType, getLocation()); 922 } 923 eventType = next(); 924 } 925 return content.toString(); 926 } 927 928 /** 929 * Return the current location of the processor. If the Location is unknown 930 * the processor should return an implementation of Location that returns -1 931 * for the location and null for the publicId and systemId. The location 932 * information is only valid until next() is called. 933 */ 934 public Location getLocation() { 935 return new Location() { 936 String _systemId = fEntityScanner.getExpandedSystemId(); 937 String _publicId = fEntityScanner.getPublicId(); 938 int _offset = fEntityScanner.getCharacterOffset(); 939 int _columnNumber = fEntityScanner.getColumnNumber(); 940 int _lineNumber = fEntityScanner.getLineNumber(); 941 942 public String getLocationURI() { 943 return _systemId; 944 } 945 946 public int getCharacterOffset() { 947 return _offset; 948 } 949 950 public int getColumnNumber() { 951 return _columnNumber; 952 } 953 954 public int getLineNumber() { 955 return _lineNumber; 956 } 957 958 public String getPublicId() { 959 return _publicId; 960 } 961 962 public String getSystemId() { 963 return _systemId; 964 } 965 966 public String toString() { 967 StringBuilder sbuffer = new StringBuilder(); 968 sbuffer.append("Line number = " + getLineNumber()); 969 sbuffer.append("\n"); 970 sbuffer.append("Column number = " + getColumnNumber()); 971 sbuffer.append("\n"); 972 sbuffer.append("System Id = " + getSystemId()); 973 sbuffer.append("\n"); 974 sbuffer.append("Public Id = " + getPublicId()); 975 sbuffer.append("\n"); 976 sbuffer.append("Location Uri= " + getLocationURI()); 977 sbuffer.append("\n"); 978 sbuffer.append("CharacterOffset = " + getCharacterOffset()); 979 sbuffer.append("\n"); 980 return sbuffer.toString(); 981 } 982 }; 983 984 } 985 986 /** 987 * Returns a QName for the current START_ELEMENT or END_ELEMENT event 988 * 989 * @return the QName for the current START_ELEMENT or END_ELEMENT event 990 */ 991 public javax.xml.namespace.QName getName() { 992 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT) { 993 return convertXNIQNametoJavaxQName(fScanner.getElementQName()); 994 } else { 995 throw new java.lang.IllegalStateException("Illegal to call getName() " 996 + "when event type is " + getEventTypeString(fEventType) + "." 997 + " Valid states are " + getEventTypeString(XMLEvent.START_ELEMENT) + ", " 998 + getEventTypeString(XMLEvent.END_ELEMENT)); 999 } 1000 } 1001 1002 /** 1003 * Returns a read only namespace context for the current position. The 1004 * context is transient and only valid until a call to next() changes the 1005 * state of the reader. 1006 * 1007 * @return return a namespace context 1008 */ 1009 public NamespaceContext getNamespaceContext() { 1010 return fNamespaceContextWrapper; 1011 } 1012 1013 /** 1014 * Returns the count of namespaces declared on this START_ELEMENT or 1015 * END_ELEMENT, this method is only valid on a START_ELEMENT, END_ELEMENT or 1016 * NAMESPACE. On an END_ELEMENT the count is of the namespaces that are 1017 * about to go out of scope. This is the equivalent of the information 1018 * reported by SAX callback for an end element event. 1019 * 1020 * @return returns the number of namespace declarations on this specific 1021 * element 1022 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT 1023 * or NAMESPACE 1024 */ 1025 public int getNamespaceCount() { 1026 //namespaceContext is dynamic object. 1027 //REVISIT: check if it specifies all conditions mentioned in the javadoc 1028 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 1029 || fEventType == XMLEvent.NAMESPACE) { 1030 return fScanner.getNamespaceContext().getDeclaredPrefixCount(); 1031 } else { 1032 throw new IllegalStateException("Current event state is " + getEventTypeString(fEventType) 1033 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 1034 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 1035 + getEventTypeString(XMLEvent.NAMESPACE) 1036 + " valid for getNamespaceCount()."); 1037 } 1038 } 1039 1040 /** 1041 * Returns the prefix for the namespace declared at the index. Returns null 1042 * if this is the default namespace declaration 1043 * 1044 * @param index the position of the namespace declaration 1045 * @return returns the namespace prefix 1046 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT 1047 * or NAMESPACE 1048 */ 1049 public String getNamespacePrefix(int index) { 1050 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 1051 || fEventType == XMLEvent.NAMESPACE) { 1052 //namespaceContext is dynamic object. 1053 String prefix = fScanner.getNamespaceContext().getDeclaredPrefixAt(index); 1054 return prefix.isEmpty() ? null : prefix; 1055 } else { 1056 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1057 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 1058 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 1059 + getEventTypeString(XMLEvent.NAMESPACE) 1060 + " valid for getNamespacePrefix()."); 1061 } 1062 } 1063 1064 /** 1065 * Returns the uri for the namespace declared at the index. 1066 * 1067 * @param index the position of the namespace declaration 1068 * @return returns the namespace uri 1069 * @throws IllegalStateException if this is not a START_ELEMENT, END_ELEMENT 1070 * or NAMESPACE 1071 */ 1072 public String getNamespaceURI(int index) { 1073 if (fEventType == XMLEvent.START_ELEMENT || fEventType == XMLEvent.END_ELEMENT 1074 || fEventType == XMLEvent.NAMESPACE) { 1075 //namespaceContext is dynamic object. 1076 return fScanner.getNamespaceContext().getURI(fScanner.getNamespaceContext() 1077 .getDeclaredPrefixAt(index)); 1078 } else { 1079 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1080 + " is not among the states " + getEventTypeString(XMLEvent.START_ELEMENT) 1081 + ", " + getEventTypeString(XMLEvent.END_ELEMENT) + ", " 1082 + getEventTypeString(XMLEvent.NAMESPACE) 1083 + " valid for getNamespaceURI()."); 1084 } 1085 1086 } 1087 1088 /** 1089 * Get the value of a feature/property from the underlying implementation 1090 * 1091 * @param name The name of the property, may not be null 1092 * @return The value of the property 1093 * @throws IllegalArgumentException if name is null 1094 */ 1095 public Object getProperty(java.lang.String name) throws java.lang.IllegalArgumentException { 1096 if (name == null) { 1097 throw new java.lang.IllegalArgumentException(); 1098 } 1099 if (fPropertyManager != null) { 1100 if (name.equals(PropertyManager.STAX_NOTATIONS)) { 1101 return getNotationDecls(); 1102 } else if (name.equals(PropertyManager.STAX_ENTITIES)) { 1103 return getEntityDecls(); 1104 } else { 1105 return fPropertyManager.getProperty(name); 1106 } 1107 } 1108 return null; 1109 } 1110 1111 /** 1112 * Returns the current value of the parse event as a string, this returns 1113 * the string value of a CHARACTERS event, returns the value of a COMMENT, 1114 * the replacement value for an ENTITY_REFERENCE, or the String value of the 1115 * DTD 1116 * 1117 * @return the current text or null 1118 * @throws java.lang.IllegalStateException if this state is not a valid text 1119 * state. 1120 */ 1121 public String getText() { 1122 if (fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 1123 || fEventType == XMLEvent.CDATA || fEventType == XMLEvent.SPACE) { 1124 //this requires creation of new string 1125 //fEventType == XMLEvent.ENTITY_REFERENCE 1126 return fScanner.getCharacterData().toString(); 1127 } else if (fEventType == XMLEvent.ENTITY_REFERENCE) { 1128 String name = fScanner.getEntityName(); 1129 if (name != null) { 1130 if (fScanner.foundBuiltInRefs) { 1131 return fScanner.getCharacterData().toString(); 1132 } 1133 1134 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1135 Entity en = entityStore.getEntity(name); 1136 if (en == null) { 1137 return null; 1138 } 1139 if (en.isExternal()) { 1140 return ((Entity.ExternalEntity) en).entityLocation.getExpandedSystemId(); 1141 } else { 1142 return ((Entity.InternalEntity) en).text; 1143 } 1144 } else { 1145 return null; 1146 } 1147 } else if (fEventType == XMLEvent.DTD) { 1148 if (fDTDDecl != null) { 1149 return fDTDDecl; 1150 } 1151 XMLStringBuffer tmpBuffer = fScanner.getDTDDecl(); 1152 fDTDDecl = tmpBuffer.toString(); 1153 return fDTDDecl; 1154 } else { 1155 throw new IllegalStateException("Current state " + getEventTypeString(fEventType) 1156 + " is not among the states" + getEventTypeString(XMLEvent.CHARACTERS) + ", " 1157 + getEventTypeString(XMLEvent.COMMENT) + ", " 1158 + getEventTypeString(XMLEvent.CDATA) + ", " 1159 + getEventTypeString(XMLEvent.SPACE) + ", " 1160 + getEventTypeString(XMLEvent.ENTITY_REFERENCE) + ", " 1161 + getEventTypeString(XMLEvent.DTD) + " valid for getText() "); 1162 } 1163 }//getText 1164 1165 /** 1166 * Test if the current event is of the given type and if the namespace and 1167 * name match the current namespace and name of the current event. If the 1168 * namespaceURI is null it is not checked for equality, if the localName is 1169 * null it is not checked for equality. 1170 * 1171 * @param type the event type 1172 * @param namespaceURI the uri of the event, may be null 1173 * @param localName the localName of the event, may be null 1174 * @throws XMLStreamException if the required values are not matched. 1175 */ 1176 public void require(int type, String namespaceURI, String localName) throws XMLStreamException { 1177 if (type != fEventType) { 1178 throw new XMLStreamException("Event type " + getEventTypeString(type) + " specified did " 1179 + "not match with current parser event " + getEventTypeString(fEventType)); 1180 } 1181 if (namespaceURI != null && !namespaceURI.equals(getNamespaceURI())) { 1182 throw new XMLStreamException("Namespace URI " + namespaceURI + " specified did not match " 1183 + "with current namespace URI"); 1184 } 1185 if (localName != null && !localName.equals(getLocalName())) { 1186 throw new XMLStreamException("LocalName " + localName + " specified did not match with " 1187 + "current local name"); 1188 } 1189 return; 1190 } 1191 1192 /** 1193 * Gets the the text associated with a CHARACTERS, SPACE or CDATA event. 1194 * Text starting a "sourceStart" is copied into "destination" starting at 1195 * "targetStart". Up to "length" characters are copied. The number of 1196 * characters actually copied is returned. 1197 * 1198 * The "sourceStart" argument must be greater or equal to 0 and less than or 1199 * equal to the number of characters associated with the event. Usually, one 1200 * requests text starting at a "sourceStart" of 0. If the number of 1201 * characters actually copied is less than the "length", then there is no 1202 * more text. Otherwise, subsequent calls need to be made until all text has 1203 * been retrieved. For example: 1204 * 1205 * <code> 1206 * int length = 1024; 1207 * char[] myBuffer = new char[ length ]; 1208 * 1209 * for ( int sourceStart = 0 ; ; sourceStart += length ) 1210 * { 1211 * int nCopied = stream.getTextCharacters( sourceStart, myBuffer, 0, length ); 1212 * 1213 * if (nCopied < length) 1214 * break; 1215 * } 1216 * </code> XMLStreamException may be thrown if there are any XML errors in 1217 * the underlying source. The "targetStart" argument must be greater than or 1218 * equal to 0 and less than the length of "target", Length must be greater 1219 * than 0 and "targetStart + length" must be less than or equal to length of 1220 * "target". 1221 * 1222 * @param sourceStart the index of the first character in the source array 1223 * to copy 1224 * @param target the destination array 1225 * @param targetStart the start offset in the target array 1226 * @param length the number of characters to copy 1227 * @return the number of characters actually copied 1228 * @throws XMLStreamException if the underlying XML source is not 1229 * well-formed 1230 * @throws IndexOutOfBoundsException if targetStart < 0 or > than the length 1231 * of target 1232 * @throws IndexOutOfBoundwhile(isCharacters()) ;sException if length < 0 or targetStart + length 1233 * > length of target 1234 * @throws UnsupportedOperationException if this method is not supported 1235 * @throws NullPointerException is if target is null 1236 */ 1237 public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) 1238 throws XMLStreamException { 1239 1240 if (target == null) { 1241 throw new NullPointerException("target char array can't be null"); 1242 } 1243 1244 if (targetStart < 0 || length < 0 || sourceStart < 0 || targetStart >= target.length 1245 || (targetStart + length) > target.length) { 1246 throw new IndexOutOfBoundsException(); 1247 } 1248 1249 //getTextStart() + sourceStart should not be greater than the lenght of number of characters 1250 //present 1251 int copiedLength = 0; 1252 //int presentDataLen = getTextLength() - (getTextStart()+sourceStart); 1253 int available = getTextLength() - sourceStart; 1254 if (available < 0) { 1255 throw new IndexOutOfBoundsException("sourceStart is greater than" 1256 + "number of characters associated with this event"); 1257 } 1258 if (available < length) { 1259 copiedLength = available; 1260 } else { 1261 copiedLength = length; 1262 } 1263 1264 System.arraycopy(getTextCharacters(), getTextStart() + sourceStart, target, targetStart, copiedLength); 1265 return copiedLength; 1266 } 1267 1268 /** 1269 * Return true if the current event has text, false otherwise The following 1270 * events have text: CHARACTERS,DTD ,ENTITY_REFERENCE, COMMENT 1271 */ 1272 public boolean hasText() { 1273 if (DEBUG) { 1274 pr("XMLReaderImpl#EVENT TYPE = " + fEventType); 1275 } 1276 if (fEventType == XMLEvent.CHARACTERS || fEventType == XMLEvent.COMMENT 1277 || fEventType == XMLEvent.CDATA) { 1278 return fScanner.getCharacterData().length > 0; 1279 } else if (fEventType == XMLEvent.ENTITY_REFERENCE) { 1280 String name = fScanner.getEntityName(); 1281 if (name != null) { 1282 if (fScanner.foundBuiltInRefs) { 1283 return true; 1284 } 1285 1286 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1287 Entity en = entityStore.getEntity(name); 1288 if (en == null) { 1289 return false; 1290 } 1291 if (en.isExternal()) { 1292 return ((Entity.ExternalEntity) en).entityLocation.getExpandedSystemId() != null; 1293 } else { 1294 return ((Entity.InternalEntity) en).text != null; 1295 } 1296 } else { 1297 return false; 1298 } 1299 } else if (fEventType == XMLEvent.DTD) { 1300 return fScanner.fSeenDoctypeDecl; 1301 } 1302 return false; 1303 } 1304 1305 /** 1306 * Returns a boolean which indicates if this attribute was created by 1307 * default 1308 * 1309 * @param index the position of the attribute 1310 * @return true if this is a default attribute 1311 * @throws IllegalStateException if this is not a START_ELEMENT or ATTRIBUTE 1312 */ 1313 public boolean isAttributeSpecified(int index) { 1314 //check that current state should be either START_ELEMENT or ATTRIBUTE 1315 if ((fEventType == XMLEvent.START_ELEMENT) || (fEventType == XMLEvent.ATTRIBUTE)) { 1316 return fScanner.getAttributeIterator().isSpecified(index); 1317 } else { 1318 throw new IllegalStateException("Current state is not among the states " 1319 + getEventTypeString(XMLEvent.START_ELEMENT) + " , " 1320 + getEventTypeString(XMLEvent.ATTRIBUTE) 1321 + "valid for isAttributeSpecified()"); 1322 } 1323 } 1324 1325 /** 1326 * Returns true if the cursor points to a character data event 1327 * 1328 * @return true if the cursor points to character data, false otherwise 1329 */ 1330 public boolean isCharacters() { 1331 return fEventType == XMLEvent.CHARACTERS; 1332 } 1333 1334 /** 1335 * Skips any insignificant events (COMMENT and PROCESSING_INSTRUCTION) until 1336 * a START_ELEMENT or END_ELEMENT is reached. If other than space characters 1337 * are encountered, an exception is thrown. This method should be used when 1338 * processing element-only content because the parser is not able to 1339 * recognize ignorable whitespace if then DTD is missing or not interpreted. 1340 * 1341 * @return the event type of the element read 1342 * @throws XMLStreamException if the current event is not white space 1343 */ 1344 public int nextTag() throws XMLStreamException { 1345 1346 int eventType = next(); 1347 while ((eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace()) // skip whitespace 1348 || (eventType == XMLStreamConstants.CDATA && isWhiteSpace()) 1349 // skip whitespace 1350 || eventType == XMLStreamConstants.SPACE 1351 || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION 1352 || eventType == XMLStreamConstants.COMMENT) { 1353 eventType = next(); 1354 } 1355 1356 if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) { 1357 throw new XMLStreamException( 1358 "found: " + getEventTypeString(eventType) 1359 + ", expected " + getEventTypeString(XMLStreamConstants.START_ELEMENT) 1360 + " or " + getEventTypeString(XMLStreamConstants.END_ELEMENT), 1361 getLocation()); 1362 } 1363 1364 return eventType; 1365 } 1366 1367 /** 1368 * Checks if standalone was set in the document 1369 * 1370 * @return true if standalone was set in the document, or false otherwise 1371 */ 1372 public boolean standaloneSet() { 1373 //xxx: it requires if the standalone was set in the document ? This is different that if the document 1374 // is standalone 1375 return fScanner.standaloneSet(); 1376 } 1377 1378 /** 1379 * @param qname 1380 * @return 1381 */ 1382 public javax.xml.namespace.QName convertXNIQNametoJavaxQName( 1383 com.sun.org.apache.xerces.internal.xni.QName qname) { 1384 if (qname == null) { 1385 return null; 1386 } 1387 //xxx: prefix definition ? 1388 if (qname.prefix == null) { 1389 return new javax.xml.namespace.QName(qname.uri, qname.localpart); 1390 } else { 1391 return new javax.xml.namespace.QName(qname.uri, qname.localpart, qname.prefix); 1392 } 1393 } 1394 1395 /** 1396 * Return the uri for the given prefix. The uri returned depends on the 1397 * current state of the processor. 1398 * 1399 * <p> 1400 * <strong>NOTE:</strong>The 'xml' prefix is bound as defined in 1401 * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in 1402 * XML</a> 1403 * specification to "http://www.w3.org/XML/1998/namespace". 1404 * 1405 * <p> 1406 * <strong>NOTE:</strong> The 'xmlns' prefix must be resolved to following 1407 * namespace 1408 * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a> 1409 * 1410 * @return the uri bound to the given prefix or null if it is not bound 1411 * @param prefix The prefix to lookup, may not be null 1412 * @throws IllegalStateException - if the prefix is null 1413 */ 1414 public String getNamespaceURI(String prefix) { 1415 if (prefix == null) { 1416 throw new java.lang.IllegalArgumentException("prefix cannot be null."); 1417 } 1418 1419 //first add the string to symbol table.. since internally identity comparisons are done. 1420 return fScanner.getNamespaceContext().getURI(fSymbolTable.addSymbol(prefix)); 1421 } 1422 1423 //xxx: this function is not being used. 1424 protected void setPropertyManager(PropertyManager propertyManager) { 1425 fPropertyManager = propertyManager; 1426 //REVISIT: we were supplying hashmap ealier 1427 fScanner.setProperty("stax-properties", propertyManager); 1428 fScanner.setPropertyManager(propertyManager); 1429 } 1430 1431 /** 1432 * @return returns the reference to property manager. 1433 */ 1434 protected PropertyManager getPropertyManager() { 1435 return fPropertyManager; 1436 } 1437 1438 static void pr(String str) { 1439 System.out.println(str); 1440 } 1441 1442 protected List<EntityDeclaration> getEntityDecls() { 1443 if (fEventType == XMLStreamConstants.DTD) { 1444 XMLEntityStorage entityStore = fEntityManager.getEntityStore(); 1445 ArrayList<EntityDeclaration> list = null; 1446 Map<String, Entity> entities = entityStore.getEntities(); 1447 if (entities.size() > 0) { 1448 EntityDeclarationImpl decl = null; 1449 list = new ArrayList<>(entities.size()); 1450 for (Map.Entry<String, Entity> entry : entities.entrySet()) { 1451 String key = entry.getKey(); 1452 Entity en = entry.getValue(); 1453 decl = new EntityDeclarationImpl(); 1454 decl.setEntityName(key); 1455 if (en.isExternal()) { 1456 decl.setXMLResourceIdentifier(((Entity.ExternalEntity) en).entityLocation); 1457 decl.setNotationName(((Entity.ExternalEntity) en).notation); 1458 } else { 1459 decl.setEntityReplacementText(((Entity.InternalEntity) en).text); 1460 } 1461 list.add(decl); 1462 } 1463 } 1464 return list; 1465 } 1466 return null; 1467 } 1468 1469 protected List<NotationDeclaration> getNotationDecls() { 1470 if (fEventType == XMLStreamConstants.DTD) { 1471 if (fScanner.fDTDScanner == null) { 1472 return null; 1473 } 1474 DTDGrammar grammar = ((XMLDTDScannerImpl) (fScanner.fDTDScanner)).getGrammar(); 1475 if (grammar == null) { 1476 return null; 1477 } 1478 List<XMLNotationDecl> notations = grammar.getNotationDecls(); 1479 ArrayList<NotationDeclaration> list = new ArrayList<>(); 1480 for (XMLNotationDecl notation : notations) { 1481 if (notation != null) { 1482 list.add(new NotationDeclarationImpl(notation)); 1483 } 1484 } 1485 return list; 1486 } 1487 return null; 1488 } 1489 1490 }//XMLReaderImpl