1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 */ 4 5 /* 6 * Copyright 2005 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xerces.internal.impl; 22 23 import java.io.IOException; 24 import com.sun.org.apache.xerces.internal.xni.XMLString; 25 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter; 26 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; 27 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; 28 import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl; 29 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; 30 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 31 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 32 import com.sun.org.apache.xerces.internal.xni.QName; 33 import com.sun.org.apache.xerces.internal.xni.XNIException; 34 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; 35 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 36 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; 37 import com.sun.org.apache.xerces.internal.xni.XMLAttributes; 38 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; 39 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; 40 41 import javax.xml.stream.XMLInputFactory; 42 import javax.xml.stream.XMLStreamConstants; 43 import javax.xml.stream.events.XMLEvent; 44 45 /** 46 * This class adds the functionality of namespace processing. 47 * 48 * This class has been modified as per the new design which is more suited to 49 * efficiently build pull parser. Lot of improvements have been done and 50 * the code has been added to support stax functionality/features. 51 * 52 * 53 * This class scans an XML document, checks if document has a DTD, and if 54 * DTD is not found the scanner will remove the DTD Validator from the pipeline and perform 55 * namespace binding. 56 * 57 * 58 * @author Neeraj Bajaj, Sun Microsystems 59 * @author Venugopal Rao K, Sun Microsystems 60 * @author Elena Litani, IBM 61 * @version $Id: XMLNSDocumentScannerImpl.java,v 1.11 2010-11-01 04:39:41 joehw Exp $ 62 */ 63 public class XMLNSDocumentScannerImpl 64 extends XMLDocumentScannerImpl { 65 66 /** 67 * If is true, the dtd validator is no longer in the pipeline 68 * and the scanner should bind namespaces 69 */ 70 protected boolean fBindNamespaces; 71 72 /** If validating parser, make sure we report an error in the 73 * scanner if DTD grammar is missing.*/ 74 protected boolean fPerformValidation; 75 76 77 /** Default value of this feature is false, when in Stax mode this should be true */ 78 protected boolean fNotAddNSDeclAsAttribute = false; 79 80 /** DTD validator */ 81 private XMLDTDValidatorFilter fDTDValidator; 82 83 /** xmlns, default Namespace, declared */ 84 private boolean fXmlnsDeclared = false; 85 86 /** Resets the fields of this scanner. 87 */ 88 public void reset(PropertyManager propertyManager) { 89 setPropertyManager(propertyManager); 90 super.reset(propertyManager); 91 fBindNamespaces = false; 92 fNotAddNSDeclAsAttribute = !((Boolean)propertyManager.getProperty(Constants.ADD_NAMESPACE_DECL_AS_ATTRIBUTE)).booleanValue(); 93 } 94 95 public void reset(XMLComponentManager componentManager) 96 throws XMLConfigurationException { 97 super.reset(componentManager); 98 fNotAddNSDeclAsAttribute = false ; 99 fPerformValidation = false; 100 fBindNamespaces = false; 101 } 102 103 /** return the next state on the input 104 * 105 * @return int 106 */ 107 108 public int next() throws IOException, XNIException { 109 //since namespace context should still be valid when the parser is at the end element state therefore 110 //we pop the context only when next() has been called after the end element state was encountered. - nb. 111 112 if((fScannerLastState == XMLEvent.END_ELEMENT) && fBindNamespaces){ 113 fScannerLastState = -1; 114 fNamespaceContext.popContext(); 115 } 116 117 return fScannerLastState = super.next(); 118 } 119 120 /** 121 * The scanner is responsible for removing DTD validator 122 * from the pipeline if it is not needed. 123 * 124 * @param previous The filter component before DTDValidator 125 * @param dtdValidator 126 * The DTDValidator 127 * @param next The documentHandler after the DTDValidator 128 */ 129 public void setDTDValidator(XMLDTDValidatorFilter dtd){ 130 fDTDValidator = dtd; 131 } 132 133 134 135 /** 136 * Scans a start element. This method will handle the binding of 137 * namespace information and notifying the handler of the start 138 * of the element. 139 * <p> 140 * <pre> 141 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' 142 * [40] STag ::= '<' Name (S Attribute)* S? '>' 143 * </pre> 144 * <p> 145 * <strong>Note:</strong> This method assumes that the leading 146 * '<' character has been consumed. 147 * <p> 148 * <strong>Note:</strong> This method uses the fElementQName and 149 * fAttributes variables. The contents of these variables will be 150 * destroyed. The caller should copy important information out of 151 * these variables before calling this method. 152 * 153 * @return True if element is empty. (i.e. It matches 154 * production [44]. 155 */ 156 protected boolean scanStartElement() 157 throws IOException, XNIException { 158 159 if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanStartElement()"); 160 //when skipping is true and no more elements should be added 161 if(fSkip && !fAdd){ 162 //get the stored element -- if everything goes right this should match the 163 //token in the buffer 164 165 QName name = fElementStack.getNext(); 166 167 if(DEBUG_SKIP_ALGORITHM){ 168 System.out.println("Trying to skip String = " + name.rawname); 169 } 170 171 //Be conservative -- if skipping fails -- stop. 172 fSkip = fEntityScanner.skipString(name.rawname); // skipQElement(name); 173 174 if(fSkip){ 175 if(DEBUG_SKIP_ALGORITHM){ 176 System.out.println("Element SUCESSFULLY skipped = " + name.rawname); 177 } 178 fElementStack.push(); 179 fElementQName = name; 180 }else{ 181 //if skipping fails reposition the stack or fallback to normal way of processing 182 fElementStack.reposition(); 183 if(DEBUG_SKIP_ALGORITHM){ 184 System.out.println("Element was NOT skipped, REPOSITIONING stack" ); 185 } 186 } 187 } 188 189 //we are still at the stage of adding elements 190 //the elements were not matched or 191 //fSkip is not set to true 192 if(!fSkip || fAdd){ 193 //get the next element from the stack 194 fElementQName = fElementStack.nextElement(); 195 // There are two variables,fNamespaces and fBindNamespaces 196 //StAX uses XMLNSDocumentScannerImpl so this distinction needs to be maintained 197 if (fNamespaces) { 198 fEntityScanner.scanQName(fElementQName); 199 } else { 200 String name = fEntityScanner.scanName(); 201 fElementQName.setValues(null, name, name, null); 202 } 203 204 if(DEBUG)System.out.println("Element scanned in start element is " + fElementQName.toString()); 205 if(DEBUG_SKIP_ALGORITHM){ 206 if(fAdd){ 207 System.out.println("Elements are being ADDED -- elemet added is = " + fElementQName.rawname + " at count = " + fElementStack.fCount); 208 } 209 } 210 211 } 212 213 //when the elements are being added , we need to check if we are set for skipping the elements 214 if(fAdd){ 215 //this sets the value of fAdd variable 216 fElementStack.matchElement(fElementQName); 217 } 218 219 //xxx: We dont need another pointer, fCurrentElement, we can use fElementQName 220 fCurrentElement = fElementQName; 221 222 String rawname = fElementQName.rawname; 223 if (fBindNamespaces) { 224 fNamespaceContext.pushContext(); 225 if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) { 226 if (fPerformValidation) { 227 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 228 "MSG_GRAMMAR_NOT_FOUND", 229 new Object[]{ rawname}, 230 XMLErrorReporter.SEVERITY_ERROR); 231 232 if (fDoctypeName == null || !fDoctypeName.equals(rawname)) { 233 fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN, 234 "RootElementTypeMustMatchDoctypedecl", 235 new Object[]{fDoctypeName, rawname}, 236 XMLErrorReporter.SEVERITY_ERROR); 237 } 238 } 239 } 240 } 241 242 243 fEmptyElement = false; 244 fAttributes.removeAllAttributes(); 245 246 if(!seekCloseOfStartTag()){ 247 fReadingAttributes = true; 248 fAttributeCacheUsedCount =0; 249 fStringBufferIndex =0; 250 fAddDefaultAttr = true; 251 fXmlnsDeclared = false; 252 253 do { 254 scanAttribute(fAttributes); 255 if (fSecurityManager != null && (!fSecurityManager.isNoLimit(fElementAttributeLimit)) && 256 fAttributes.getLength() > fElementAttributeLimit){ 257 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 258 "ElementAttributeLimit", 259 new Object[]{rawname, fElementAttributeLimit }, 260 XMLErrorReporter.SEVERITY_FATAL_ERROR ); 261 } 262 263 } while (!seekCloseOfStartTag()); 264 fReadingAttributes=false; 265 } 266 267 if (fBindNamespaces) { 268 // REVISIT: is it required? forbit xmlns prefix for element 269 if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) { 270 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 271 "ElementXMLNSPrefix", 272 new Object[]{fElementQName.rawname}, 273 XMLErrorReporter.SEVERITY_FATAL_ERROR); 274 } 275 276 // bind the element 277 String prefix = fElementQName.prefix != null 278 ? fElementQName.prefix : XMLSymbols.EMPTY_STRING; 279 // assign uri to the element 280 fElementQName.uri = fNamespaceContext.getURI(prefix); 281 // make sure that object in the element stack is updated as well 282 fCurrentElement.uri = fElementQName.uri; 283 284 if (fElementQName.prefix == null && fElementQName.uri != null) { 285 fElementQName.prefix = XMLSymbols.EMPTY_STRING; 286 } 287 if (fElementQName.prefix != null && fElementQName.uri == null) { 288 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 289 "ElementPrefixUnbound", 290 new Object[]{fElementQName.prefix, fElementQName.rawname}, 291 XMLErrorReporter.SEVERITY_FATAL_ERROR); 292 } 293 294 // bind attributes (xmlns are already bound bellow) 295 int length = fAttributes.getLength(); 296 // fLength = 0; //initialize structure 297 for (int i = 0; i < length; i++) { 298 fAttributes.getName(i, fAttributeQName); 299 300 String aprefix = fAttributeQName.prefix != null 301 ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING; 302 String uri = fNamespaceContext.getURI(aprefix); 303 // REVISIT: try removing the first "if" and see if it is faster. 304 // 305 if (fAttributeQName.uri != null && fAttributeQName.uri == uri) { 306 // checkDuplicates(fAttributeQName, fAttributes); 307 continue; 308 } 309 if (aprefix != XMLSymbols.EMPTY_STRING) { 310 fAttributeQName.uri = uri; 311 if (uri == null) { 312 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 313 "AttributePrefixUnbound", 314 new Object[]{fElementQName.rawname,fAttributeQName.rawname,aprefix}, 315 XMLErrorReporter.SEVERITY_FATAL_ERROR); 316 } 317 fAttributes.setURI(i, uri); 318 // checkDuplicates(fAttributeQName, fAttributes); 319 } 320 } 321 322 if (length > 1) { 323 QName name = fAttributes.checkDuplicatesNS(); 324 if (name != null) { 325 if (name.uri != null) { 326 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 327 "AttributeNSNotUnique", 328 new Object[]{fElementQName.rawname, name.localpart, name.uri}, 329 XMLErrorReporter.SEVERITY_FATAL_ERROR); 330 } else { 331 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 332 "AttributeNotUnique", 333 new Object[]{fElementQName.rawname, name.rawname}, 334 XMLErrorReporter.SEVERITY_FATAL_ERROR); 335 } 336 } 337 } 338 } 339 340 341 if (fEmptyElement) { 342 //decrease the markup depth.. 343 fMarkupDepth--; 344 345 // check that this element was opened in the same entity 346 if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) { 347 reportFatalError("ElementEntityMismatch", 348 new Object[]{fCurrentElement.rawname}); 349 } 350 // call handler 351 if (fDocumentHandler != null) { 352 if(DEBUG) 353 System.out.println("emptyElement = " + fElementQName); 354 355 fDocumentHandler.emptyElement(fElementQName, fAttributes, null); 356 } 357 358 //We should not be popping out the context here in endELement becaause the namespace context is still 359 //valid when parser is at the endElement state. 360 fScanEndElement = true; 361 //if (fBindNamespaces) { 362 // fNamespaceContext.popContext(); 363 //} 364 365 //pop the element off the stack.. 366 fElementStack.popElement(); 367 368 } else { 369 370 if(dtdGrammarUtil != null) 371 dtdGrammarUtil.startElement(fElementQName,fAttributes); 372 if(fDocumentHandler != null){ 373 //complete element and attributes are traversed in this function so we can send a callback 374 //here. 375 //<strong>we shouldn't be sending callback in scanDocument()</strong> 376 if(DEBUG) 377 System.out.println("startElement = " + fElementQName); 378 fDocumentHandler.startElement(fElementQName, fAttributes, null); 379 } 380 } 381 382 383 if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanStartElement(): "+fEmptyElement); 384 return fEmptyElement; 385 386 } // scanStartElement():boolean 387 388 389 390 /** 391 * Scans an attribute. 392 * <p> 393 * <pre> 394 * [41] Attribute ::= Name Eq AttValue 395 * </pre> 396 * <p> 397 * <strong>Note:</strong> This method assumes that the next 398 * character on the stream is the first character of the attribute 399 * name. 400 * <p> 401 * <strong>Note:</strong> This method uses the fAttributeQName and 402 * fQName variables. The contents of these variables will be 403 * destroyed. 404 * 405 * @param attributes The attributes list for the scanned attribute. 406 */ 407 protected void scanAttribute(XMLAttributesImpl attributes) 408 throws IOException, XNIException { 409 if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()"); 410 411 // name 412 fEntityScanner.scanQName(fAttributeQName); 413 414 // equals 415 fEntityScanner.skipSpaces(); 416 if (!fEntityScanner.skipChar('=')) { 417 reportFatalError("EqRequiredInAttribute", 418 new Object[]{fCurrentElement.rawname,fAttributeQName.rawname}); 419 } 420 fEntityScanner.skipSpaces(); 421 422 // content 423 int attrIndex = 0 ; 424 425 426 //REVISIT: one more case needs to be included: external PE and standalone is no 427 boolean isVC = fHasExternalDTD && !fStandalone; 428 429 // REVISIT: it seems that this function should not take attributes, and length 430 //fTempString would store attribute value 431 ///fTempString2 would store attribute non-normalized value 432 433 //this function doesn't use 'attIndex'. We are adding the attribute later 434 //after we have figured out that current attribute is not namespace declaration 435 //since scanAttributeValue doesn't use attIndex parameter therefore we 436 //can safely add the attribute later.. 437 XMLString tmpStr = getString(); 438 scanAttributeValue(tmpStr, fTempString2, 439 fAttributeQName.rawname, attributes, 440 attrIndex, isVC); 441 442 String value = null; 443 //fTempString.toString(); 444 445 // record namespace declarations if any. 446 if (fBindNamespaces) { 447 448 String localpart = fAttributeQName.localpart; 449 String prefix = fAttributeQName.prefix != null 450 ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING; 451 // when it's of form xmlns="..." or xmlns:prefix="...", 452 // it's a namespace declaration. but prefix:xmlns="..." isn't. 453 if (prefix == XMLSymbols.PREFIX_XMLNS || 454 prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) { 455 456 // get the internalized value of this attribute 457 String uri = fSymbolTable.addSymbol(tmpStr.ch,tmpStr.offset,tmpStr.length); 458 value = uri; 459 // 1. "xmlns" can't be bound to any namespace 460 if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) { 461 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 462 "CantBindXMLNS", 463 new Object[]{fAttributeQName}, 464 XMLErrorReporter.SEVERITY_FATAL_ERROR); 465 } 466 467 // 2. the namespace for "xmlns" can't be bound to any prefix 468 if (uri == NamespaceContext.XMLNS_URI) { 469 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 470 "CantBindXMLNS", 471 new Object[]{fAttributeQName}, 472 XMLErrorReporter.SEVERITY_FATAL_ERROR); 473 } 474 475 // 3. "xml" can't be bound to any other namespace than it's own 476 if (localpart == XMLSymbols.PREFIX_XML) { 477 if (uri != NamespaceContext.XML_URI) { 478 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 479 "CantBindXML", 480 new Object[]{fAttributeQName}, 481 XMLErrorReporter.SEVERITY_FATAL_ERROR); 482 } 483 } 484 // 4. the namespace for "xml" can't be bound to any other prefix 485 else { 486 if (uri ==NamespaceContext.XML_URI) { 487 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 488 "CantBindXML", 489 new Object[]{fAttributeQName}, 490 XMLErrorReporter.SEVERITY_FATAL_ERROR); 491 } 492 } 493 prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING; 494 //set it equal to XMLSymbols.PREFIX_XMLNS when namespace declaration 495 // is of type xmlns = "..", in this case prefix = "" and localname = XMLSymbols.PREFIX_XMLNS 496 //this special behavior is because of dependency on this behavior in DOM components 497 if(prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS){ 498 fAttributeQName.prefix = XMLSymbols.PREFIX_XMLNS; 499 } 500 // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix 501 // We should only report an error if there is a prefix, 502 // that is, the local part is not "xmlns". -SG 503 if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) { 504 fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, 505 "EmptyPrefixedAttName", 506 new Object[]{fAttributeQName}, 507 XMLErrorReporter.SEVERITY_FATAL_ERROR); 508 } 509 510 // check for duplicate prefix bindings 511 if (((com.sun.org.apache.xerces.internal.util.NamespaceSupport) fNamespaceContext).containsPrefixInCurrentContext(prefix)) { 512 reportFatalError("AttributeNotUnique", 513 new Object[]{fCurrentElement.rawname, 514 fAttributeQName.rawname}); 515 } 516 517 // declare prefix in context 518 boolean declared = fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null); 519 520 // check for duplicate xmlns declarations 521 if (!declared) { // by convention, prefix == "xmlns" | "xml" 522 // error if duplicate declaration 523 if (fXmlnsDeclared) { 524 reportFatalError("AttributeNotUnique", 525 new Object[]{fCurrentElement.rawname, 526 fAttributeQName.rawname}); 527 } 528 529 // xmlns declared 530 fXmlnsDeclared = true; 531 } 532 533 //xerces internals (XSAttributeChecker) has dependency on namespace declaration returned 534 //as part of XMLAttributes. 535 //addition of namespace declaration to the attribute list is controlled by fNotAddNSDeclAsAttribute 536 //feature. This is required in Stax where namespace declarations are not considered as attribute 537 538 if(fNotAddNSDeclAsAttribute){ 539 return ; 540 } 541 } 542 } 543 544 //add the attributes to the list of attributes 545 if (fBindNamespaces) { 546 attrIndex = attributes.getLength(); 547 attributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, null); 548 } else { 549 int oldLen = attributes.getLength(); 550 attrIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null); 551 552 // WFC: Unique Att Spec 553 if (oldLen == attributes.getLength()) { 554 reportFatalError("AttributeNotUnique", 555 new Object[]{fCurrentElement.rawname, 556 fAttributeQName.rawname}); 557 } 558 } 559 560 attributes.setValue(attrIndex, value,tmpStr); 561 //attributes.setNonNormalizedValue(attrIndex, fTempString2.toString()); 562 //removing as we are not using non-normalized values . -Venu 563 attributes.setSpecified(attrIndex, true); 564 565 // attempt to bind attribute 566 if (fAttributeQName.prefix != null) { 567 attributes.setURI(attrIndex, fNamespaceContext.getURI(fAttributeQName.prefix)); 568 } 569 570 if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanAttribute()"); 571 } // scanAttribute(XMLAttributes) 572 573 574 575 576 577 /** Creates a content driver. */ 578 protected Driver createContentDriver() { 579 return new NSContentDriver(); 580 } // createContentDriver():Driver 581 582 /** 583 * Driver to handle content scanning. 584 */ 585 protected final class NSContentDriver 586 extends ContentDriver { 587 /** 588 * Scan for root element hook. This method is a hook for 589 * subclasses to add code that handles scanning for the root 590 * element. This method will also attempt to remove DTD validator 591 * from the pipeline, if there is no DTD grammar. If DTD validator 592 * is no longer in the pipeline bind namespaces in the scanner. 593 * 594 * 595 * @return True if the caller should stop and return true which 596 * allows the scanner to switch to a new scanning 597 * driver. A return value of false indicates that 598 * the content driver should continue as normal. 599 */ 600 protected boolean scanRootElementHook() 601 throws IOException, XNIException { 602 603 reconfigurePipeline(); 604 if (scanStartElement()) { 605 setScannerState(SCANNER_STATE_TRAILING_MISC); 606 setDriver(fTrailingMiscDriver); 607 return true; 608 } 609 return false; 610 611 } // scanRootElementHook():boolean 612 613 /** 614 * Re-configures pipeline by removing the DTD validator 615 * if no DTD grammar exists. If no validator exists in the 616 * pipeline or there is no DTD grammar, namespace binding 617 * is performed by the scanner in the enclosing class. 618 */ 619 private void reconfigurePipeline() { 620 //fDTDValidator will be null in Stax mode 621 if (fNamespaces && fDTDValidator == null) { 622 fBindNamespaces = true; 623 } 624 else if (fNamespaces && !fDTDValidator.hasGrammar() ) { 625 fBindNamespaces = true; 626 fPerformValidation = fDTDValidator.validate(); 627 // re-configure pipeline by removing DTDValidator 628 XMLDocumentSource source = fDTDValidator.getDocumentSource(); 629 XMLDocumentHandler handler = fDTDValidator.getDocumentHandler(); 630 source.setDocumentHandler(handler); 631 if (handler != null) 632 handler.setDocumentSource(source); 633 fDTDValidator.setDocumentSource(null); 634 fDTDValidator.setDocumentHandler(null); 635 } 636 } // reconfigurePipeline() 637 } 638 639 } // class XMLNSDocumentScannerImpl