1 /* 2 * Copyright (c) 2005, 2006, 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 javax.xml.stream.XMLStreamReader; 29 import javax.xml.stream.StreamFilter; 30 import javax.xml.stream.XMLStreamException; 31 import javax.xml.namespace.QName; 32 import javax.xml.stream.events.XMLEvent; 33 34 35 /** 36 * 37 * @author Joe Wang: 38 * This is a rewrite of the original class. The focus is on removing caching, and make the filtered 39 * stream reader more compatible with those in other implementations. Note however, that this version 40 * will not solve all the issues related to the undefined condition in the spec. The priority is 41 * to pass the TCK. Issues arising due to the requirement, that is, (1) should it initiate at BEGIN_DOCUMENT 42 * or an accepted event; (2) should hasNext() advance the underlining stream in order to find an acceptable 43 * event, would have to wait until 1.1 of StAX in which the filtered stream reader would be defined more clearly. 44 */ 45 46 public class XMLStreamFilterImpl implements javax.xml.stream.XMLStreamReader { 47 48 private StreamFilter fStreamFilter = null; 49 private XMLStreamReader fStreamReader = null; 50 private int fCurrentEvent; 51 private boolean fEventAccepted = false; 52 53 /**the very issue around a long discussion. but since we must pass the TCK, we have to allow 54 * hasNext() to advance the underlining stream in order to find the next acceptable event 55 */ 56 private boolean fStreamAdvancedByHasNext = false; 57 58 /** 59 * Creates a new instance of XMLStreamFilterImpl, advancing the reader to 60 * the next event accepted by the filter, if not already positioned on an 61 * accepted event. 62 * 63 * @param reader 64 * the reader to filter 65 * @param filter 66 * the filter to apply to the reader 67 * @throws XMLStreamException 68 * when an {@code XMLStreamException} is thrown when 69 * advancing the reader to an accepted event. 70 **/ XMLStreamFilterImpl(XMLStreamReader reader,StreamFilter filter)71 public XMLStreamFilterImpl(XMLStreamReader reader,StreamFilter filter) throws XMLStreamException { 72 fStreamReader = reader; 73 this.fStreamFilter = filter; 74 75 //this is debatable to initiate at an acceptable event, 76 //but it's neccessary in order to pass the TCK and yet avoid skipping element 77 if (fStreamFilter.accept(fStreamReader)) { 78 fEventAccepted = true; 79 } else { 80 findNextEvent(); 81 } 82 } 83 84 /** 85 * 86 * @param sf 87 */ setStreamFilter(StreamFilter sf)88 protected void setStreamFilter(StreamFilter sf){ 89 this.fStreamFilter = sf; 90 } 91 92 /** 93 * 94 * @return 95 * @throws XMLStreamException 96 */ next()97 public int next() throws XMLStreamException { 98 if (fStreamAdvancedByHasNext && fEventAccepted) { 99 fStreamAdvancedByHasNext = false; 100 return fCurrentEvent; 101 } 102 int event = findNextEvent(); 103 if (event != -1) { 104 return event; 105 } 106 107 throw new IllegalStateException("The stream reader has reached the end of the document, or there are no more "+ 108 " items to return"); 109 } 110 /** 111 * 112 * @throws XMLStreamException 113 * @return 114 */ nextTag()115 public int nextTag() throws XMLStreamException { 116 if (fStreamAdvancedByHasNext && fEventAccepted && 117 (fCurrentEvent == XMLEvent.START_ELEMENT || fCurrentEvent == XMLEvent.START_ELEMENT)) { 118 fStreamAdvancedByHasNext = false; 119 return fCurrentEvent; 120 } 121 122 int event = findNextTag(); 123 if (event != -1) { 124 return event; 125 } 126 throw new IllegalStateException("The stream reader has reached the end of the document, or there are no more "+ 127 " items to return"); 128 } 129 130 /** 131 * 132 * @throws XMLStreamException 133 * @return 134 */ hasNext()135 public boolean hasNext() throws XMLStreamException { 136 if (fStreamReader.hasNext()) { 137 if (!fEventAccepted) { 138 if ((fCurrentEvent = findNextEvent()) == -1) { 139 return false; 140 } else { 141 fStreamAdvancedByHasNext = true; 142 } 143 } 144 return true; 145 } 146 return false; 147 } 148 findNextEvent()149 private int findNextEvent() throws XMLStreamException { 150 fStreamAdvancedByHasNext = false; 151 while(fStreamReader.hasNext()){ 152 fCurrentEvent = fStreamReader.next(); 153 if(fStreamFilter.accept(fStreamReader)){ 154 fEventAccepted = true; 155 return fCurrentEvent; 156 } 157 } 158 //although it seems that IllegalStateException should be thrown when next() is called 159 //on a stream that has no more items, we have to assume END_DOCUMENT is always accepted 160 //in order to pass the TCK 161 if (fCurrentEvent == XMLEvent.END_DOCUMENT) 162 return fCurrentEvent; 163 else 164 return -1; 165 } findNextTag()166 private int findNextTag() throws XMLStreamException { 167 fStreamAdvancedByHasNext = false; 168 while(fStreamReader.hasNext()){ 169 fCurrentEvent = fStreamReader.nextTag(); 170 if(fStreamFilter.accept(fStreamReader)){ 171 fEventAccepted = true; 172 return fCurrentEvent; 173 } 174 } 175 if (fCurrentEvent == XMLEvent.END_DOCUMENT) 176 return fCurrentEvent; 177 else 178 return -1; 179 } 180 /** 181 * 182 * @throws XMLStreamException 183 */ close()184 public void close() throws XMLStreamException { 185 fStreamReader.close(); 186 } 187 188 /** 189 * 190 * @return 191 */ getAttributeCount()192 public int getAttributeCount() { 193 return fStreamReader.getAttributeCount(); 194 } 195 196 /** 197 * 198 * @param index 199 * @return 200 */ getAttributeName(int index)201 public QName getAttributeName(int index) { 202 return fStreamReader.getAttributeName(index); 203 } 204 205 /** 206 * 207 * @param index 208 * @return 209 */ getAttributeNamespace(int index)210 public String getAttributeNamespace(int index) { 211 return fStreamReader.getAttributeNamespace(index); 212 } 213 214 /** 215 * 216 * @param index 217 * @return 218 */ getAttributePrefix(int index)219 public String getAttributePrefix(int index) { 220 return fStreamReader.getAttributePrefix(index); 221 } 222 223 /** 224 * 225 * @param index 226 * @return 227 */ getAttributeType(int index)228 public String getAttributeType(int index) { 229 return fStreamReader.getAttributeType(index); 230 } 231 232 /** 233 * 234 * @param index 235 * @return 236 */ getAttributeValue(int index)237 public String getAttributeValue(int index) { 238 return fStreamReader.getAttributeValue(index); 239 } 240 241 /** 242 * 243 * @param namespaceURI 244 * @param localName 245 * @return 246 */ getAttributeValue(String namespaceURI, String localName)247 public String getAttributeValue(String namespaceURI, String localName) { 248 return fStreamReader.getAttributeValue(namespaceURI,localName); 249 } 250 251 /** 252 * 253 * @return 254 */ getCharacterEncodingScheme()255 public String getCharacterEncodingScheme() { 256 return fStreamReader.getCharacterEncodingScheme(); 257 } 258 259 /** 260 * 261 * @throws XMLStreamException 262 * @return 263 */ getElementText()264 public String getElementText() throws XMLStreamException { 265 return fStreamReader.getElementText(); 266 } 267 268 /** 269 * 270 * @return 271 */ getEncoding()272 public String getEncoding() { 273 return fStreamReader.getEncoding(); 274 } 275 276 /** 277 * 278 * @return 279 */ getEventType()280 public int getEventType() { 281 return fStreamReader.getEventType(); 282 } 283 284 /** 285 * 286 * @return 287 */ getLocalName()288 public String getLocalName() { 289 return fStreamReader.getLocalName(); 290 } 291 292 /** 293 * 294 * @return 295 */ getLocation()296 public javax.xml.stream.Location getLocation() { 297 return fStreamReader.getLocation(); 298 } 299 300 /** 301 * 302 * @return 303 */ getName()304 public javax.xml.namespace.QName getName() { 305 return fStreamReader.getName(); 306 } 307 308 /** 309 * 310 * @return 311 */ getNamespaceContext()312 public javax.xml.namespace.NamespaceContext getNamespaceContext() { 313 return fStreamReader.getNamespaceContext(); 314 } 315 316 /** 317 * 318 * @return 319 */ getNamespaceCount()320 public int getNamespaceCount() { 321 return fStreamReader.getNamespaceCount(); 322 } 323 324 /** 325 * 326 * @param index 327 * @return 328 */ getNamespacePrefix(int index)329 public String getNamespacePrefix(int index) { 330 return fStreamReader.getNamespacePrefix(index); 331 } 332 333 /** 334 * 335 * @return 336 */ getNamespaceURI()337 public String getNamespaceURI() { 338 return fStreamReader.getNamespaceURI(); 339 } 340 341 /** 342 * 343 * @param index 344 * @return 345 */ getNamespaceURI(int index)346 public String getNamespaceURI(int index) { 347 return fStreamReader.getNamespaceURI(index); 348 } 349 350 /** 351 * 352 * @param prefix 353 * @return 354 */ getNamespaceURI(String prefix)355 public String getNamespaceURI(String prefix) { 356 return fStreamReader.getNamespaceURI(prefix); 357 } 358 359 /** 360 * 361 * @return 362 */ getPIData()363 public String getPIData() { 364 return fStreamReader.getPIData(); 365 } 366 367 /** 368 * 369 * @return 370 */ getPITarget()371 public String getPITarget() { 372 return fStreamReader.getPITarget(); 373 } 374 375 /** 376 * 377 * @return 378 */ getPrefix()379 public String getPrefix() { 380 return fStreamReader.getPrefix(); 381 } 382 383 /** 384 * 385 * @param name 386 * @throws IllegalArgumentException 387 * @return 388 */ getProperty(java.lang.String name)389 public Object getProperty(java.lang.String name) throws java.lang.IllegalArgumentException { 390 return fStreamReader.getProperty(name); 391 } 392 393 /** 394 * 395 * @return 396 */ getText()397 public String getText() { 398 return fStreamReader.getText(); 399 } 400 401 /** 402 * 403 * @return 404 */ getTextCharacters()405 public char[] getTextCharacters() { 406 return fStreamReader.getTextCharacters(); 407 } 408 409 /** 410 * 411 * @param sourceStart 412 * @param target 413 * @param targetStart 414 * @param length 415 * @throws XMLStreamException 416 * @return 417 */ getTextCharacters(int sourceStart, char[] target, int targetStart, int length)418 public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) throws XMLStreamException { 419 return fStreamReader.getTextCharacters(sourceStart, target,targetStart,length); 420 } 421 422 /** 423 * 424 * @return 425 */ getTextLength()426 public int getTextLength() { 427 return fStreamReader.getTextLength(); 428 } 429 430 /** 431 * 432 * @return 433 */ getTextStart()434 public int getTextStart() { 435 return fStreamReader.getTextStart(); 436 } 437 438 /** 439 * 440 * @return 441 */ getVersion()442 public String getVersion() { 443 return fStreamReader.getVersion(); 444 } 445 446 /** 447 * 448 * @return 449 */ hasName()450 public boolean hasName() { 451 return fStreamReader.hasName(); 452 } 453 454 /** 455 * 456 * @return 457 */ hasText()458 public boolean hasText() { 459 return fStreamReader.hasText(); 460 } 461 462 /** 463 * 464 * @return 465 * @param index 466 */ isAttributeSpecified(int index)467 public boolean isAttributeSpecified(int index) { 468 return fStreamReader.isAttributeSpecified(index); 469 } 470 471 /** 472 * 473 * @return 474 */ isCharacters()475 public boolean isCharacters() { 476 return fStreamReader.isCharacters(); 477 } 478 479 /** 480 * 481 * @return 482 */ isEndElement()483 public boolean isEndElement() { 484 return fStreamReader.isEndElement(); 485 } 486 487 /** 488 * 489 * @return 490 */ isStandalone()491 public boolean isStandalone() { 492 return fStreamReader.isStandalone(); 493 } 494 495 /** 496 * 497 * @return 498 */ isStartElement()499 public boolean isStartElement() { 500 return fStreamReader.isStartElement(); 501 } 502 503 /** 504 * 505 * @return 506 */ isWhiteSpace()507 public boolean isWhiteSpace() { 508 return fStreamReader.isWhiteSpace(); 509 } 510 511 512 /** 513 * 514 * @param type 515 * @param namespaceURI 516 * @param localName 517 * @throws XMLStreamException 518 */ require(int type, String namespaceURI, String localName)519 public void require(int type, String namespaceURI, String localName) throws XMLStreamException { 520 fStreamReader.require(type,namespaceURI,localName); 521 } 522 523 /** 524 * 525 * @return 526 */ standaloneSet()527 public boolean standaloneSet() { 528 return fStreamReader.standaloneSet(); 529 } 530 531 /** 532 * 533 * @param index 534 * @return 535 */ getAttributeLocalName(int index)536 public String getAttributeLocalName(int index){ 537 return fStreamReader.getAttributeLocalName(index); 538 } 539 } 540