1/* 2 * Copyright (c) 2005, 2013, 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 26package com.sun.xml.internal.stream.buffer.sax; 27 28import com.sun.xml.internal.stream.buffer.AbstractProcessor; 29import com.sun.xml.internal.stream.buffer.AttributesHolder; 30import com.sun.xml.internal.stream.buffer.XMLStreamBuffer; 31import org.xml.sax.ContentHandler; 32import org.xml.sax.DTDHandler; 33import org.xml.sax.EntityResolver; 34import org.xml.sax.ErrorHandler; 35import org.xml.sax.InputSource; 36import org.xml.sax.SAXException; 37import org.xml.sax.SAXNotRecognizedException; 38import org.xml.sax.SAXNotSupportedException; 39import org.xml.sax.SAXParseException; 40import org.xml.sax.XMLReader; 41import org.xml.sax.ext.LexicalHandler; 42import org.xml.sax.helpers.LocatorImpl; 43 44import javax.xml.XMLConstants; 45import java.io.IOException; 46import java.util.Collections; 47import java.util.HashSet; 48import java.util.Map; 49import java.util.Set; 50 51/** 52 * A processor of a {@link XMLStreamBuffer} that that reads the XML infoset as 53 * {@link XMLReader}. 54 */ 55public class SAXBufferProcessor extends AbstractProcessor implements XMLReader { 56 /** 57 * Reference to entity resolver. 58 */ 59 protected EntityResolver _entityResolver = DEFAULT_LEXICAL_HANDLER; 60 61 /** 62 * Reference to dtd handler. 63 */ 64 protected DTDHandler _dtdHandler = DEFAULT_LEXICAL_HANDLER; 65 66 /** 67 * Reference to content handler. 68 */ 69 protected ContentHandler _contentHandler = DEFAULT_LEXICAL_HANDLER; 70 71 /** 72 * Reference to error handler. 73 */ 74 protected ErrorHandler _errorHandler = DEFAULT_LEXICAL_HANDLER; 75 76 /** 77 * Reference to lexical handler. 78 */ 79 protected LexicalHandler _lexicalHandler = DEFAULT_LEXICAL_HANDLER; 80 81 /** 82 * SAX Namespace attributes features 83 */ 84 protected boolean _namespacePrefixesFeature = false; 85 86 protected AttributesHolder _attributes = new AttributesHolder(); 87 88 protected String[] _namespacePrefixes = new String[16]; 89 protected int _namespacePrefixesIndex; 90 91 protected int[] _namespaceAttributesStartingStack = new int[16]; 92 protected int[] _namespaceAttributesStack = new int[16]; 93 protected int _namespaceAttributesStackIndex; 94 95 public SAXBufferProcessor() { 96 } 97 98 /** 99 * @deprecated 100 * Use {@link #SAXBufferProcessor(XMLStreamBuffer, boolean)} 101 */ 102 public SAXBufferProcessor(XMLStreamBuffer buffer) { 103 setXMLStreamBuffer(buffer); 104 } 105 106 /** 107 * @param produceFragmentEvent 108 * True to generate fragment SAX events without start/endDocument. 109 * False to generate a full document SAX events. 110 */ 111 public SAXBufferProcessor(XMLStreamBuffer buffer, boolean produceFragmentEvent) { 112 setXMLStreamBuffer(buffer,produceFragmentEvent); 113 } 114 115 public boolean getFeature(String name) 116 throws SAXNotRecognizedException, SAXNotSupportedException { 117 if (name.equals(Features.NAMESPACES_FEATURE)) { 118 return true; 119 } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { 120 return _namespacePrefixesFeature; 121 } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { 122 return true; 123 } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { 124 return true; 125 } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { 126 return _stringInterningFeature; 127 } else { 128 throw new SAXNotRecognizedException( 129 "Feature not supported: " + name); 130 } 131 } 132 133 public void setFeature(String name, boolean value) 134 throws SAXNotRecognizedException, SAXNotSupportedException { 135 if (name.equals(Features.NAMESPACES_FEATURE)) { 136 if (!value) { 137 throw new SAXNotSupportedException(name + ":" + value); 138 } 139 } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { 140 _namespacePrefixesFeature = value; 141 } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { 142 // ignore 143 } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { 144 // ignore 145 } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { 146 if (value != _stringInterningFeature) { 147 throw new SAXNotSupportedException(name + ":" + value); 148 } 149 } else { 150 throw new SAXNotRecognizedException( 151 "Feature not supported: " + name); 152 } 153 } 154 155 public Object getProperty(String name) 156 throws SAXNotRecognizedException, SAXNotSupportedException { 157 if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { 158 return getLexicalHandler(); 159 } else { 160 throw new SAXNotRecognizedException("Property not recognized: " + name); 161 } 162 } 163 164 public void setProperty(String name, Object value) 165 throws SAXNotRecognizedException, SAXNotSupportedException { 166 if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { 167 if (value instanceof LexicalHandler) { 168 setLexicalHandler((LexicalHandler)value); 169 } else { 170 throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY); 171 } 172 } else { 173 throw new SAXNotRecognizedException("Property not recognized: " + name); 174 } 175 } 176 177 public void setEntityResolver(EntityResolver resolver) { 178 _entityResolver = resolver; 179 } 180 181 public EntityResolver getEntityResolver() { 182 return _entityResolver; 183 } 184 185 public void setDTDHandler(DTDHandler handler) { 186 _dtdHandler = handler; 187 } 188 189 public DTDHandler getDTDHandler() { 190 return _dtdHandler; 191 } 192 193 public void setContentHandler(ContentHandler handler) { 194 _contentHandler = handler; 195 } 196 197 public ContentHandler getContentHandler() { 198 return _contentHandler; 199 } 200 201 public void setErrorHandler(ErrorHandler handler) { 202 _errorHandler = handler; 203 } 204 205 public ErrorHandler getErrorHandler() { 206 return _errorHandler; 207 } 208 209 public void setLexicalHandler(LexicalHandler handler) { 210 _lexicalHandler = handler; 211 } 212 213 public LexicalHandler getLexicalHandler() { 214 return _lexicalHandler; 215 } 216 217 public void parse(InputSource input) throws IOException, SAXException { 218 // InputSource is ignored 219 process(); 220 } 221 222 public void parse(String systemId) throws IOException, SAXException { 223 // systemId is ignored 224 process(); 225 } 226 227 /** 228 * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer)} then {@link #process()}. 229 * 230 * @deprecated 231 * Use {@link #process(XMLStreamBuffer, boolean)} 232 */ 233 public final void process(XMLStreamBuffer buffer) throws SAXException { 234 setXMLStreamBuffer(buffer); 235 process(); 236 } 237 238 /** 239 * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer,boolean)} then {@link #process()}. 240 * 241 * @param produceFragmentEvent 242 * True to generate fragment SAX events without start/endDocument. 243 * False to generate a full document SAX events. 244 */ 245 public final void process(XMLStreamBuffer buffer, boolean produceFragmentEvent) throws SAXException { 246 setXMLStreamBuffer(buffer); 247 process(); 248 } 249 250 /** 251 * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. 252 * 253 * @deprecated 254 * Use {@link #setXMLStreamBuffer(XMLStreamBuffer, boolean)}. 255 */ 256 public void setXMLStreamBuffer(XMLStreamBuffer buffer) { 257 setBuffer(buffer); 258 } 259 260 /** 261 * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. 262 * 263 * @param produceFragmentEvent 264 * True to generate fragment SAX events without start/endDocument. 265 * False to generate a full document SAX events. 266 */ 267 public void setXMLStreamBuffer(XMLStreamBuffer buffer, boolean produceFragmentEvent) { 268 if(!produceFragmentEvent && _treeCount>1) 269 throw new IllegalStateException("Can't write a forest to a full XML infoset"); 270 setBuffer(buffer,produceFragmentEvent); 271 } 272 273 /** 274 * Parse the sub-tree (or a whole document) that {@link XMLStreamBuffer} 275 * points to, and sends events to handlers. 276 * 277 * <p> 278 * TODO: 279 * We probably need two modes for a sub-tree event generation. One for 280 * firing a sub-tree as if it's a whole document (in which case start/endDocument 281 * and appropriate additional namespace bindings are necessary), and the other 282 * mode for firing a subtree as a subtree, like it does today. 283 * A stream buffer SAX feature could be used to specify this. 284 * 285 * @throws SAXException 286 * Follow the same semantics as {@link XMLReader#parse(InputSource)}. 287 */ 288 public final void process() throws SAXException { 289 if(!_fragmentMode) { 290 LocatorImpl nullLocator = new LocatorImpl(); 291 nullLocator.setSystemId(_buffer.getSystemId()); 292 nullLocator.setLineNumber(-1); 293 nullLocator.setColumnNumber(-1); 294 _contentHandler.setDocumentLocator(nullLocator); 295 296 _contentHandler.startDocument(); 297 // TODO: if we are writing a fragment stream buffer as a full XML document, 298 // we need to declare in-scope namespaces as if they are on the root element. 299 } 300 301 while (_treeCount>0) { 302 final int item = readEiiState(); 303 switch(item) { 304 case STATE_DOCUMENT: 305 processDocument(); 306 _treeCount--; 307 break; 308 case STATE_END: 309 // Empty buffer 310 return; 311 case STATE_ELEMENT_U_LN_QN: 312 processElement(readStructureString(), readStructureString(), readStructureString(), isInscope()); 313 _treeCount--; 314 break; 315 case STATE_ELEMENT_P_U_LN: 316 { 317 final String prefix = readStructureString(); 318 final String uri = readStructureString(); 319 final String localName = readStructureString(); 320 processElement(uri, localName, getQName(prefix, localName),isInscope()); 321 _treeCount--; 322 break; 323 } 324 case STATE_ELEMENT_U_LN: { 325 final String uri = readStructureString(); 326 final String localName = readStructureString(); 327 processElement(uri, localName, localName,isInscope()); 328 _treeCount--; 329 break; 330 } 331 case STATE_ELEMENT_LN: 332 { 333 final String localName = readStructureString(); 334 processElement("", localName, localName,isInscope()); 335 _treeCount--; 336 break; 337 } 338 case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: 339 processCommentAsCharArraySmall(); 340 break; 341 case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: 342 processCommentAsCharArrayMedium(); 343 break; 344 case STATE_COMMENT_AS_CHAR_ARRAY_COPY: 345 processCommentAsCharArrayCopy(); 346 break; 347 case STATE_COMMENT_AS_STRING: 348 processComment(readContentString()); 349 break; 350 case STATE_PROCESSING_INSTRUCTION: 351 processProcessingInstruction(readStructureString(), readStructureString()); 352 break; 353 default: 354 throw reportFatalError("Illegal state for DIIs: "+item); 355 } 356 } 357 358 if(!_fragmentMode) 359 _contentHandler.endDocument(); 360 } 361 362 private void processCommentAsCharArraySmall() throws SAXException { 363 final int length = readStructure(); 364 final int start = readContentCharactersBuffer(length); 365 processComment(_contentCharactersBuffer, start, length); 366 } 367 368 /** 369 * Report a fatal error and abort. 370 * 371 * This is necessary to follow the SAX semantics of error handling. 372 */ 373 private SAXParseException reportFatalError(String msg) throws SAXException { 374 SAXParseException spe = new SAXParseException(msg, null); 375 if(_errorHandler!=null) 376 _errorHandler.fatalError(spe); 377 return spe; 378 } 379 380 private boolean isInscope() { 381 return _buffer.getInscopeNamespaces().size() > 0; 382 } 383 384 private void processDocument() throws SAXException { 385 while(true) { 386 int item = readEiiState(); 387 switch(item) { 388 case STATE_ELEMENT_U_LN_QN: 389 processElement(readStructureString(), readStructureString(), readStructureString(),isInscope()); 390 break; 391 case STATE_ELEMENT_P_U_LN: 392 { 393 final String prefix = readStructureString(); 394 final String uri = readStructureString(); 395 final String localName = readStructureString(); 396 processElement(uri, localName, getQName(prefix, localName),isInscope()); 397 break; 398 } 399 case STATE_ELEMENT_U_LN: { 400 final String uri = readStructureString(); 401 final String localName = readStructureString(); 402 processElement(uri, localName, localName,isInscope()); 403 break; 404 } 405 case STATE_ELEMENT_LN: 406 { 407 final String localName = readStructureString(); 408 processElement("", localName, localName,isInscope()); 409 break; 410 } 411 case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: 412 processCommentAsCharArraySmall(); 413 break; 414 case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: 415 processCommentAsCharArrayMedium(); 416 break; 417 case STATE_COMMENT_AS_CHAR_ARRAY_COPY: 418 processCommentAsCharArrayCopy(); 419 break; 420 case STATE_COMMENT_AS_STRING: 421 processComment(readContentString()); 422 break; 423 case STATE_PROCESSING_INSTRUCTION: 424 processProcessingInstruction(readStructureString(), readStructureString()); 425 break; 426 case STATE_END: 427 return; 428 default: 429 throw reportFatalError("Illegal state for child of DII: "+item); 430 } 431 } 432 } 433 434 protected void processElement(String uri, String localName, String qName, boolean inscope) throws SAXException { 435 boolean hasAttributes = false; 436 boolean hasNamespaceAttributes = false; 437 int item = peekStructure(); 438 Set<String> prefixSet = inscope ? new HashSet<String>() : Collections.<String>emptySet(); 439 if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) { 440 cacheNamespacePrefixStartingIndex(); 441 hasNamespaceAttributes = true; 442 item = processNamespaceAttributes(item, inscope, prefixSet); 443 } 444 if (inscope) { 445 readInscopeNamespaces(prefixSet); 446 } 447 448 if ((item & TYPE_MASK) == T_ATTRIBUTE) { 449 hasAttributes = true; 450 processAttributes(item); 451 } 452 453 _contentHandler.startElement(uri, localName, qName, _attributes); 454 455 if (hasAttributes) { 456 _attributes.clear(); 457 } 458 459 do { 460 item = readEiiState(); 461 switch(item) { 462 case STATE_ELEMENT_U_LN_QN: 463 processElement(readStructureString(), readStructureString(), readStructureString(), false); 464 break; 465 case STATE_ELEMENT_P_U_LN: 466 { 467 final String p = readStructureString(); 468 final String u = readStructureString(); 469 final String ln = readStructureString(); 470 processElement(u, ln, getQName(p, ln),false); 471 break; 472 } 473 case STATE_ELEMENT_U_LN: { 474 final String u = readStructureString(); 475 final String ln = readStructureString(); 476 processElement(u, ln, ln,false); 477 break; 478 } 479 case STATE_ELEMENT_LN: { 480 final String ln = readStructureString(); 481 processElement("", ln, ln,false); 482 break; 483 } 484 case STATE_TEXT_AS_CHAR_ARRAY_SMALL: 485 { 486 final int length = readStructure(); 487 int start = readContentCharactersBuffer(length); 488 _contentHandler.characters(_contentCharactersBuffer, start, length); 489 break; 490 } 491 case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: 492 { 493 final int length = readStructure16(); 494 int start = readContentCharactersBuffer(length); 495 _contentHandler.characters(_contentCharactersBuffer, start, length); 496 break; 497 } 498 case STATE_TEXT_AS_CHAR_ARRAY_COPY: 499 { 500 final char[] ch = readContentCharactersCopy(); 501 502 _contentHandler.characters(ch, 0, ch.length); 503 break; 504 } 505 case STATE_TEXT_AS_STRING: 506 { 507 final String s = readContentString(); 508 _contentHandler.characters(s.toCharArray(), 0, s.length()); 509 break; 510 } 511 case STATE_TEXT_AS_OBJECT: 512 { 513 final CharSequence c = (CharSequence)readContentObject(); 514 final String s = c.toString(); 515 _contentHandler.characters(s.toCharArray(), 0, s.length()); 516 break; 517 } 518 case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: 519 processCommentAsCharArraySmall(); 520 break; 521 case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: 522 processCommentAsCharArrayMedium(); 523 break; 524 case STATE_COMMENT_AS_CHAR_ARRAY_COPY: 525 processCommentAsCharArrayCopy(); 526 break; 527 case T_COMMENT_AS_STRING: 528 processComment(readContentString()); 529 break; 530 case STATE_PROCESSING_INSTRUCTION: 531 processProcessingInstruction(readStructureString(), readStructureString()); 532 break; 533 case STATE_END: 534 break; 535 default: 536 throw reportFatalError("Illegal state for child of EII: "+item); 537 } 538 } while(item != STATE_END); 539 540 _contentHandler.endElement(uri, localName, qName); 541 542 if (hasNamespaceAttributes) { 543 processEndPrefixMapping(); 544 } 545 } 546 547 private void readInscopeNamespaces(Set<String> prefixSet) throws SAXException { 548 for (Map.Entry<String, String> e : _buffer.getInscopeNamespaces().entrySet()) { 549 String key = fixNull(e.getKey()); 550 // If the prefix is already written, do not write the prefix 551 if (!prefixSet.contains(key)) { 552 processNamespaceAttribute(key,e.getValue()); 553 } 554 } 555 556 } 557 558 private static String fixNull(String s) { 559 if (s == null) return ""; 560 else return s; 561 } 562 private void processCommentAsCharArrayCopy() throws SAXException { 563 final char[] ch = readContentCharactersCopy(); 564 processComment(ch, 0, ch.length); 565 } 566 567 private void processCommentAsCharArrayMedium() throws SAXException { 568 final int length = readStructure16(); 569 final int start = readContentCharactersBuffer(length); 570 processComment(_contentCharactersBuffer, start, length); 571 } 572 573 private void processEndPrefixMapping() throws SAXException { 574 final int end = _namespaceAttributesStack[--_namespaceAttributesStackIndex]; 575// final int start = (_namespaceAttributesStackIndex > 0) ? _namespaceAttributesStack[_namespaceAttributesStackIndex] : 0; 576 final int start = (_namespaceAttributesStackIndex >= 0) ? _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] : 0; 577 578 for (int i = end - 1; i >= start; i--) { 579 _contentHandler.endPrefixMapping(_namespacePrefixes[i]); 580 } 581 _namespacePrefixesIndex = start; 582 } 583 584 private int processNamespaceAttributes(int item,boolean collectPrefixes, Set<String> prefixSet) throws SAXException { 585 do { 586 String prefix; 587 switch(getNIIState(item)) { 588 case STATE_NAMESPACE_ATTRIBUTE: 589 // Undeclaration of default namespace 590 processNamespaceAttribute("", ""); 591 if(collectPrefixes) { 592 prefixSet.add(""); 593 } 594 break; 595 case STATE_NAMESPACE_ATTRIBUTE_P: 596 // Undeclaration of namespace 597 prefix = readStructureString(); 598 processNamespaceAttribute(prefix, ""); 599 if(collectPrefixes) { 600 prefixSet.add(prefix); 601 } 602 break; 603 case STATE_NAMESPACE_ATTRIBUTE_P_U: 604 // Declaration with prefix 605 prefix = readStructureString(); 606 processNamespaceAttribute(prefix, readStructureString()); 607 if(collectPrefixes) { 608 prefixSet.add(prefix); 609 } 610 break; 611 case STATE_NAMESPACE_ATTRIBUTE_U: 612 // Default declaration 613 processNamespaceAttribute("", readStructureString()); 614 if(collectPrefixes) { 615 prefixSet.add(""); 616 } 617 break; 618 default: 619 throw reportFatalError("Illegal state: "+item); 620 } 621 readStructure(); 622 623 item = peekStructure(); 624 } while((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE); 625 626 627 cacheNamespacePrefixIndex(); 628 629 return item; 630 } 631 632 private void processAttributes(int item) throws SAXException { 633 do { 634 switch(getAIIState(item)) { 635 case STATE_ATTRIBUTE_U_LN_QN: 636 _attributes.addAttributeWithQName(readStructureString(), readStructureString(), readStructureString(), readStructureString(), readContentString()); 637 break; 638 case STATE_ATTRIBUTE_P_U_LN: 639 { 640 final String p = readStructureString(); 641 final String u = readStructureString(); 642 final String ln = readStructureString(); 643 _attributes.addAttributeWithQName(u, ln, getQName(p, ln), readStructureString(), readContentString()); 644 break; 645 } 646 case STATE_ATTRIBUTE_U_LN: { 647 final String u = readStructureString(); 648 final String ln = readStructureString(); 649 _attributes.addAttributeWithQName(u, ln, ln, readStructureString(), readContentString()); 650 break; 651 } 652 case STATE_ATTRIBUTE_LN: { 653 final String ln = readStructureString(); 654 _attributes.addAttributeWithQName("", ln, ln, readStructureString(), readContentString()); 655 break; 656 } 657 default: 658 throw reportFatalError("Illegal state: "+item); 659 } 660 readStructure(); 661 662 item = peekStructure(); 663 } while((item & TYPE_MASK) == T_ATTRIBUTE); 664 } 665 666 private void processNamespaceAttribute(String prefix, String uri) throws SAXException { 667 _contentHandler.startPrefixMapping(prefix, uri); 668 669 if (_namespacePrefixesFeature) { 670 // Add the namespace delcaration as an attribute 671 if (prefix != "") { 672 _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix, 673 getQName(XMLConstants.XMLNS_ATTRIBUTE, prefix), 674 "CDATA", uri); 675 } else { 676 _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE, 677 XMLConstants.XMLNS_ATTRIBUTE, 678 "CDATA", uri); 679 } 680 } 681 682 cacheNamespacePrefix(prefix); 683 } 684 685 private void cacheNamespacePrefix(String prefix) { 686 if (_namespacePrefixesIndex == _namespacePrefixes.length) { 687 final String[] namespaceAttributes = new String[_namespacePrefixesIndex * 3 / 2 + 1]; 688 System.arraycopy(_namespacePrefixes, 0, namespaceAttributes, 0, _namespacePrefixesIndex); 689 _namespacePrefixes = namespaceAttributes; 690 } 691 692 _namespacePrefixes[_namespacePrefixesIndex++] = prefix; 693 } 694 695 private void cacheNamespacePrefixIndex() { 696 if (_namespaceAttributesStackIndex == _namespaceAttributesStack.length) { 697 final int[] namespaceAttributesStack = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; 698 System.arraycopy(_namespaceAttributesStack, 0, namespaceAttributesStack, 0, _namespaceAttributesStackIndex); 699 _namespaceAttributesStack = namespaceAttributesStack; 700 } 701 702 _namespaceAttributesStack[_namespaceAttributesStackIndex++] = _namespacePrefixesIndex; 703 } 704 705 private void cacheNamespacePrefixStartingIndex() { 706 if (_namespaceAttributesStackIndex == _namespaceAttributesStartingStack.length) { 707 final int[] namespaceAttributesStart = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; 708 System.arraycopy(_namespaceAttributesStartingStack, 0, namespaceAttributesStart, 0, _namespaceAttributesStackIndex); 709 _namespaceAttributesStartingStack = namespaceAttributesStart; 710 } 711 _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] = _namespacePrefixesIndex; 712 } 713 714 private void processComment(String s) throws SAXException { 715 processComment(s.toCharArray(), 0, s.length()); 716 } 717 718 private void processComment(char[] ch, int start, int length) throws SAXException { 719 _lexicalHandler.comment(ch, start, length); 720 } 721 722 private void processProcessingInstruction(String target, String data) throws SAXException { 723 _contentHandler.processingInstruction(target, data); 724 } 725 726 private static final DefaultWithLexicalHandler DEFAULT_LEXICAL_HANDLER = new DefaultWithLexicalHandler(); 727} 728