1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id: TransformerHandlerImpl.java 468645 2006-10-28 06:57:24Z minchau $ 20 */ 21 package org.apache.xalan.transformer; 22 23 import java.io.IOException; 24 25 import javax.xml.transform.Result; 26 import javax.xml.transform.Transformer; 27 import javax.xml.transform.sax.TransformerHandler; 28 29 import org.apache.xalan.res.XSLMessages; 30 import org.apache.xalan.res.XSLTErrorResources; 31 import org.apache.xml.dtm.DTM; 32 import org.apache.xml.dtm.DTMManager; 33 import org.apache.xml.dtm.ref.IncrementalSAXSource_Filter; 34 import org.apache.xml.dtm.ref.sax2dtm.SAX2DTM; 35 import org.apache.xpath.XPathContext; 36 37 import org.xml.sax.Attributes; 38 import org.xml.sax.ContentHandler; 39 import org.xml.sax.DTDHandler; 40 import org.xml.sax.EntityResolver; 41 import org.xml.sax.ErrorHandler; 42 import org.xml.sax.InputSource; 43 import org.xml.sax.Locator; 44 import org.xml.sax.SAXException; 45 import org.xml.sax.SAXParseException; 46 import org.xml.sax.ext.DeclHandler; 47 import org.xml.sax.ext.LexicalHandler; 48 import org.apache.xml.serializer.SerializationHandler; 49 50 51 /** 52 * A TransformerHandler 53 * listens for SAX ContentHandler parse events and transforms 54 * them to a Result. 55 */ 56 public class TransformerHandlerImpl 57 implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler, 58 LexicalHandler, TransformerHandler, DeclHandler 59 { 60 /** 61 * The flag for the setting of the optimize feature; 62 */ 63 private final boolean m_optimizer; 64 65 /** 66 * The flag for the setting of the incremental feature; 67 */ 68 private final boolean m_incremental; 69 70 /** 71 * The flag for the setting of the source_location feature; 72 */ 73 private final boolean m_source_location; 74 75 private boolean m_insideParse = false; 76 77 //////////////////////////////////////////////////////////////////// 78 // Constructors. 79 //////////////////////////////////////////////////////////////////// 80 81 /** 82 * Construct a TransformerHandlerImpl. 83 * 84 * @param transformer Non-null reference to the Xalan transformer impl. 85 * @param doFragment True if the result should be a document fragement. 86 * @param baseSystemID The system ID to use as the base for relative URLs. 87 */ TransformerHandlerImpl(TransformerImpl transformer, boolean doFragment, String baseSystemID)88 public TransformerHandlerImpl(TransformerImpl transformer, 89 boolean doFragment, String baseSystemID) 90 { 91 92 super(); 93 94 m_transformer = transformer; 95 m_baseSystemID = baseSystemID; 96 97 XPathContext xctxt = transformer.getXPathContext(); 98 DTM dtm = xctxt.getDTM(null, true, transformer, true, true); 99 100 m_dtm = dtm; 101 dtm.setDocumentBaseURI(baseSystemID); 102 103 m_contentHandler = dtm.getContentHandler(); 104 m_dtdHandler = dtm.getDTDHandler(); 105 m_entityResolver = dtm.getEntityResolver(); 106 m_errorHandler = dtm.getErrorHandler(); 107 m_lexicalHandler = dtm.getLexicalHandler(); 108 m_incremental = transformer.getIncremental(); 109 m_optimizer = transformer.getOptimize(); 110 m_source_location = transformer.getSource_location(); 111 } 112 113 /** 114 * Do what needs to be done to shut down the CoRoutine management. 115 */ clearCoRoutine()116 protected void clearCoRoutine() 117 { 118 clearCoRoutine(null); 119 } 120 121 /** 122 * Do what needs to be done to shut down the CoRoutine management. 123 */ clearCoRoutine(SAXException ex)124 protected void clearCoRoutine(SAXException ex) 125 { 126 if(null != ex) 127 m_transformer.setExceptionThrown(ex); 128 129 if(m_dtm instanceof SAX2DTM) 130 { 131 if(DEBUG) 132 System.err.println("In clearCoRoutine..."); 133 try 134 { 135 SAX2DTM sax2dtm = ((SAX2DTM)m_dtm); 136 if(null != m_contentHandler 137 && m_contentHandler instanceof IncrementalSAXSource_Filter) 138 { 139 IncrementalSAXSource_Filter sp = 140 (IncrementalSAXSource_Filter)m_contentHandler; 141 // This should now be all that's needed. 142 sp.deliverMoreNodes(false); 143 } 144 145 sax2dtm.clearCoRoutine(true); 146 m_contentHandler = null; 147 m_dtdHandler = null; 148 m_entityResolver = null; 149 m_errorHandler = null; 150 m_lexicalHandler = null; 151 } 152 catch(Throwable throwable) 153 { 154 throwable.printStackTrace(); 155 } 156 157 if(DEBUG) 158 System.err.println("...exiting clearCoRoutine"); 159 } 160 } 161 162 //////////////////////////////////////////////////////////////////// 163 // Implementation of javax.xml.transform.sax.TransformerHandler. 164 //////////////////////////////////////////////////////////////////// 165 166 /** 167 * Enables the user of the TransformerHandler to set the 168 * to set the Result for the transformation. 169 * 170 * @param result A Result instance, should not be null. 171 * 172 * @throws IllegalArgumentException if result is invalid for some reason. 173 */ setResult(Result result)174 public void setResult(Result result) throws IllegalArgumentException 175 { 176 177 if (null == result) 178 throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_RESULT_NULL, null)); //"result should not be null"); 179 180 try 181 { 182 // ContentHandler handler = 183 // m_transformer.createResultContentHandler(result); 184 // m_transformer.setContentHandler(handler); 185 SerializationHandler xoh = 186 m_transformer.createSerializationHandler(result); 187 m_transformer.setSerializationHandler(xoh); 188 } 189 catch (javax.xml.transform.TransformerException te) 190 { 191 throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_RESULT_COULD_NOT_BE_SET, null)); //"result could not be set"); 192 } 193 194 m_result = result; 195 } 196 197 /** 198 * Set the base ID (URI or system ID) from where relative 199 * URLs will be resolved. 200 * @param systemID Base URI for the source tree. 201 */ setSystemId(String systemID)202 public void setSystemId(String systemID) 203 { 204 m_baseSystemID = systemID; 205 m_dtm.setDocumentBaseURI(systemID); 206 } 207 208 /** 209 * Get the base ID (URI or system ID) from where relative 210 * URLs will be resolved. 211 * @return The systemID that was set with {@link #setSystemId}. 212 */ getSystemId()213 public String getSystemId() 214 { 215 return m_baseSystemID; 216 } 217 218 /** 219 * Get the Transformer associated with this handler, which 220 * is needed in order to set parameters and output properties. 221 * 222 * @return The Transformer associated with this handler 223 */ getTransformer()224 public Transformer getTransformer() 225 { 226 return m_transformer; 227 } 228 229 //////////////////////////////////////////////////////////////////// 230 // Implementation of org.xml.sax.EntityResolver. 231 //////////////////////////////////////////////////////////////////// 232 233 /** 234 * Filter an external entity resolution. 235 * 236 * @param publicId The entity's public identifier, or null. 237 * @param systemId The entity's system identifier. 238 * @return A new InputSource or null for the default. 239 * 240 * @throws IOException 241 * @throws SAXException The client may throw 242 * an exception during processing. 243 * @throws java.io.IOException The client may throw an 244 * I/O-related exception while obtaining the 245 * new InputSource. 246 * @see org.xml.sax.EntityResolver#resolveEntity 247 */ resolveEntity(String publicId, String systemId)248 public InputSource resolveEntity(String publicId, String systemId) 249 throws SAXException, IOException 250 { 251 252 if (m_entityResolver != null) 253 { 254 return m_entityResolver.resolveEntity(publicId, systemId); 255 } 256 else 257 { 258 return null; 259 } 260 } 261 262 //////////////////////////////////////////////////////////////////// 263 // Implementation of org.xml.sax.DTDHandler. 264 //////////////////////////////////////////////////////////////////// 265 266 /** 267 * Filter a notation declaration event. 268 * 269 * @param name The notation name. 270 * @param publicId The notation's public identifier, or null. 271 * @param systemId The notation's system identifier, or null. 272 * @throws SAXException The client may throw 273 * an exception during processing. 274 * @see org.xml.sax.DTDHandler#notationDecl 275 */ notationDecl(String name, String publicId, String systemId)276 public void notationDecl(String name, String publicId, String systemId) 277 throws SAXException 278 { 279 280 if (m_dtdHandler != null) 281 { 282 m_dtdHandler.notationDecl(name, publicId, systemId); 283 } 284 } 285 286 /** 287 * Filter an unparsed entity declaration event. 288 * 289 * @param name The entity name. 290 * @param publicId The entity's public identifier, or null. 291 * @param systemId The entity's system identifier, or null. 292 * @param notationName The name of the associated notation. 293 * @throws SAXException The client may throw 294 * an exception during processing. 295 * @see org.xml.sax.DTDHandler#unparsedEntityDecl 296 */ unparsedEntityDecl( String name, String publicId, String systemId, String notationName)297 public void unparsedEntityDecl( 298 String name, String publicId, String systemId, String notationName) 299 throws SAXException 300 { 301 302 if (m_dtdHandler != null) 303 { 304 m_dtdHandler.unparsedEntityDecl(name, publicId, systemId, notationName); 305 } 306 } 307 308 //////////////////////////////////////////////////////////////////// 309 // Implementation of org.xml.sax.ContentHandler. 310 //////////////////////////////////////////////////////////////////// 311 312 /** 313 * Filter a new document locator event. 314 * 315 * @param locator The document locator. 316 * @see org.xml.sax.ContentHandler#setDocumentLocator 317 */ setDocumentLocator(Locator locator)318 public void setDocumentLocator(Locator locator) 319 { 320 321 if (DEBUG) 322 System.out.println("TransformerHandlerImpl#setDocumentLocator: " 323 + locator.getSystemId()); 324 325 this.m_locator = locator; 326 327 if(null == m_baseSystemID) 328 { 329 setSystemId(locator.getSystemId()); 330 } 331 332 if (m_contentHandler != null) 333 { 334 m_contentHandler.setDocumentLocator(locator); 335 } 336 } 337 338 /** 339 * Filter a start document event. 340 * 341 * @throws SAXException The client may throw 342 * an exception during processing. 343 * @see org.xml.sax.ContentHandler#startDocument 344 */ startDocument()345 public void startDocument() throws SAXException 346 { 347 348 if (DEBUG) 349 System.out.println("TransformerHandlerImpl#startDocument"); 350 351 m_insideParse = true; 352 353 // Thread listener = new Thread(m_transformer); 354 355 if (m_contentHandler != null) 356 { 357 //m_transformer.setTransformThread(listener); 358 if(m_incremental) 359 { 360 m_transformer.setSourceTreeDocForThread(m_dtm.getDocument()); 361 362 int cpriority = Thread.currentThread().getPriority(); 363 364 // runTransformThread is equivalent with the 2.0.1 code, 365 // except that the Thread may come from a pool. 366 m_transformer.runTransformThread( cpriority ); 367 } 368 369 // This is now done _last_, because IncrementalSAXSource_Filter 370 // will immediately go into a "wait until events are requested" 371 // pause. I believe that will close our timing window. 372 // %REVIEW% 373 m_contentHandler.startDocument(); 374 } 375 376 //listener.setDaemon(false); 377 //listener.start(); 378 379 } 380 381 /** 382 * Filter an end document event. 383 * 384 * @throws SAXException The client may throw 385 * an exception during processing. 386 * @see org.xml.sax.ContentHandler#endDocument 387 */ endDocument()388 public void endDocument() throws SAXException 389 { 390 391 if (DEBUG) 392 System.out.println("TransformerHandlerImpl#endDocument"); 393 394 m_insideParse = false; 395 396 if (m_contentHandler != null) 397 { 398 m_contentHandler.endDocument(); 399 } 400 401 if(m_incremental) 402 { 403 m_transformer.waitTransformThread(); 404 } 405 else 406 { 407 m_transformer.setSourceTreeDocForThread(m_dtm.getDocument()); 408 m_transformer.run(); 409 } 410 /* Thread transformThread = m_transformer.getTransformThread(); 411 412 if (null != transformThread) 413 { 414 try 415 { 416 417 // This should wait until the transformThread is considered not alive. 418 transformThread.join(); 419 420 if (!m_transformer.hasTransformThreadErrorCatcher()) 421 { 422 Exception e = m_transformer.getExceptionThrown(); 423 424 if (null != e) 425 throw new org.xml.sax.SAXException(e); 426 } 427 428 m_transformer.setTransformThread(null); 429 } 430 catch (InterruptedException ie){} 431 }*/ 432 } 433 434 /** 435 * Filter a start Namespace prefix mapping event. 436 * 437 * @param prefix The Namespace prefix. 438 * @param uri The Namespace URI. 439 * @throws SAXException The client may throw 440 * an exception during processing. 441 * @see org.xml.sax.ContentHandler#startPrefixMapping 442 */ startPrefixMapping(String prefix, String uri)443 public void startPrefixMapping(String prefix, String uri) 444 throws SAXException 445 { 446 447 if (DEBUG) 448 System.out.println("TransformerHandlerImpl#startPrefixMapping: " 449 + prefix + ", " + uri); 450 451 if (m_contentHandler != null) 452 { 453 m_contentHandler.startPrefixMapping(prefix, uri); 454 } 455 } 456 457 /** 458 * Filter an end Namespace prefix mapping event. 459 * 460 * @param prefix The Namespace prefix. 461 * @throws SAXException The client may throw 462 * an exception during processing. 463 * @see org.xml.sax.ContentHandler#endPrefixMapping 464 */ endPrefixMapping(String prefix)465 public void endPrefixMapping(String prefix) throws SAXException 466 { 467 468 if (DEBUG) 469 System.out.println("TransformerHandlerImpl#endPrefixMapping: " 470 + prefix); 471 472 if (m_contentHandler != null) 473 { 474 m_contentHandler.endPrefixMapping(prefix); 475 } 476 } 477 478 /** 479 * Filter a start element event. 480 * 481 * @param uri The element's Namespace URI, or the empty string. 482 * @param localName The element's local name, or the empty string. 483 * @param qName The element's qualified (prefixed) name, or the empty 484 * string. 485 * @param atts The element's attributes. 486 * @throws SAXException The client may throw 487 * an exception during processing. 488 * @see org.xml.sax.ContentHandler#startElement 489 */ startElement( String uri, String localName, String qName, Attributes atts)490 public void startElement( 491 String uri, String localName, String qName, Attributes atts) 492 throws SAXException 493 { 494 495 if (DEBUG) 496 System.out.println("TransformerHandlerImpl#startElement: " + qName); 497 498 if (m_contentHandler != null) 499 { 500 m_contentHandler.startElement(uri, localName, qName, atts); 501 } 502 } 503 504 /** 505 * Filter an end element event. 506 * 507 * @param uri The element's Namespace URI, or the empty string. 508 * @param localName The element's local name, or the empty string. 509 * @param qName The element's qualified (prefixed) name, or the empty 510 * string. 511 * @throws SAXException The client may throw 512 * an exception during processing. 513 * @see org.xml.sax.ContentHandler#endElement 514 */ endElement(String uri, String localName, String qName)515 public void endElement(String uri, String localName, String qName) 516 throws SAXException 517 { 518 519 if (DEBUG) 520 System.out.println("TransformerHandlerImpl#endElement: " + qName); 521 522 if (m_contentHandler != null) 523 { 524 m_contentHandler.endElement(uri, localName, qName); 525 } 526 } 527 528 /** 529 * Filter a character data event. 530 * 531 * @param ch An array of characters. 532 * @param start The starting position in the array. 533 * @param length The number of characters to use from the array. 534 * @throws SAXException The client may throw 535 * an exception during processing. 536 * @see org.xml.sax.ContentHandler#characters 537 */ characters(char ch[], int start, int length)538 public void characters(char ch[], int start, int length) throws SAXException 539 { 540 541 if (DEBUG) 542 System.out.println("TransformerHandlerImpl#characters: " + start + ", " 543 + length); 544 545 if (m_contentHandler != null) 546 { 547 m_contentHandler.characters(ch, start, length); 548 } 549 } 550 551 /** 552 * Filter an ignorable whitespace event. 553 * 554 * @param ch An array of characters. 555 * @param start The starting position in the array. 556 * @param length The number of characters to use from the array. 557 * @throws SAXException The client may throw 558 * an exception during processing. 559 * @see org.xml.sax.ContentHandler#ignorableWhitespace 560 */ ignorableWhitespace(char ch[], int start, int length)561 public void ignorableWhitespace(char ch[], int start, int length) 562 throws SAXException 563 { 564 565 if (DEBUG) 566 System.out.println("TransformerHandlerImpl#ignorableWhitespace: " 567 + start + ", " + length); 568 569 if (m_contentHandler != null) 570 { 571 m_contentHandler.ignorableWhitespace(ch, start, length); 572 } 573 } 574 575 /** 576 * Filter a processing instruction event. 577 * 578 * @param target The processing instruction target. 579 * @param data The text following the target. 580 * @throws SAXException The client may throw 581 * an exception during processing. 582 * @see org.xml.sax.ContentHandler#processingInstruction 583 */ processingInstruction(String target, String data)584 public void processingInstruction(String target, String data) 585 throws SAXException 586 { 587 588 if (DEBUG) 589 System.out.println("TransformerHandlerImpl#processingInstruction: " 590 + target + ", " + data); 591 592 if (m_contentHandler != null) 593 { 594 m_contentHandler.processingInstruction(target, data); 595 } 596 } 597 598 /** 599 * Filter a skipped entity event. 600 * 601 * @param name The name of the skipped entity. 602 * @throws SAXException The client may throw 603 * an exception during processing. 604 * @see org.xml.sax.ContentHandler#skippedEntity 605 */ skippedEntity(String name)606 public void skippedEntity(String name) throws SAXException 607 { 608 609 if (DEBUG) 610 System.out.println("TransformerHandlerImpl#skippedEntity: " + name); 611 612 if (m_contentHandler != null) 613 { 614 m_contentHandler.skippedEntity(name); 615 } 616 } 617 618 //////////////////////////////////////////////////////////////////// 619 // Implementation of org.xml.sax.ErrorHandler. 620 //////////////////////////////////////////////////////////////////// 621 622 /** 623 * Filter a warning event. 624 * 625 * @param e The nwarning as an exception. 626 * @throws SAXException The client may throw 627 * an exception during processing. 628 * @see org.xml.sax.ErrorHandler#warning 629 */ warning(SAXParseException e)630 public void warning(SAXParseException e) throws SAXException 631 { 632 // This is not great, but we really would rather have the error 633 // handler be the error listener if it is a error handler. Coroutine's fatalError 634 // can't really be configured, so I think this is the best thing right now 635 // for error reporting. Possibly another JAXP 1.1 hole. -sb 636 javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener(); 637 if(errorListener instanceof ErrorHandler) 638 { 639 ((ErrorHandler)errorListener).warning(e); 640 } 641 else 642 { 643 try 644 { 645 errorListener.warning(new javax.xml.transform.TransformerException(e)); 646 } 647 catch(javax.xml.transform.TransformerException te) 648 { 649 throw e; 650 } 651 } 652 } 653 654 /** 655 * Filter an error event. 656 * 657 * @param e The error as an exception. 658 * @throws SAXException The client may throw 659 * an exception during processing. 660 * @see org.xml.sax.ErrorHandler#error 661 */ error(SAXParseException e)662 public void error(SAXParseException e) throws SAXException 663 { 664 // %REVIEW% I don't think this should be called. -sb 665 // clearCoRoutine(e); 666 667 // This is not great, but we really would rather have the error 668 // handler be the error listener if it is a error handler. Coroutine's fatalError 669 // can't really be configured, so I think this is the best thing right now 670 // for error reporting. Possibly another JAXP 1.1 hole. -sb 671 javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener(); 672 if(errorListener instanceof ErrorHandler) 673 { 674 ((ErrorHandler)errorListener).error(e); 675 if(null != m_errorHandler) 676 m_errorHandler.error(e); // may not be called. 677 } 678 else 679 { 680 try 681 { 682 errorListener.error(new javax.xml.transform.TransformerException(e)); 683 if(null != m_errorHandler) 684 m_errorHandler.error(e); // may not be called. 685 } 686 catch(javax.xml.transform.TransformerException te) 687 { 688 throw e; 689 } 690 } 691 } 692 693 /** 694 * Filter a fatal error event. 695 * 696 * @param e The error as an exception. 697 * @throws SAXException The client may throw 698 * an exception during processing. 699 * @see org.xml.sax.ErrorHandler#fatalError 700 */ fatalError(SAXParseException e)701 public void fatalError(SAXParseException e) throws SAXException 702 { 703 if(null != m_errorHandler) 704 { 705 try 706 { 707 m_errorHandler.fatalError(e); 708 } 709 catch(SAXParseException se) 710 { 711 // ignore 712 } 713 // clearCoRoutine(e); 714 } 715 716 // This is not great, but we really would rather have the error 717 // handler be the error listener if it is a error handler. Coroutine's fatalError 718 // can't really be configured, so I think this is the best thing right now 719 // for error reporting. Possibly another JAXP 1.1 hole. -sb 720 javax.xml.transform.ErrorListener errorListener = m_transformer.getErrorListener(); 721 722 if(errorListener instanceof ErrorHandler) 723 { 724 ((ErrorHandler)errorListener).fatalError(e); 725 if(null != m_errorHandler) 726 m_errorHandler.fatalError(e); // may not be called. 727 } 728 else 729 { 730 try 731 { 732 errorListener.fatalError(new javax.xml.transform.TransformerException(e)); 733 if(null != m_errorHandler) 734 m_errorHandler.fatalError(e); // may not be called. 735 } 736 catch(javax.xml.transform.TransformerException te) 737 { 738 throw e; 739 } 740 } 741 } 742 743 //////////////////////////////////////////////////////////////////// 744 // Implementation of org.xml.sax.ext.LexicalHandler. 745 //////////////////////////////////////////////////////////////////// 746 747 /** 748 * Report the start of DTD declarations, if any. 749 * 750 * <p>Any declarations are assumed to be in the internal subset 751 * unless otherwise indicated by a {@link #startEntity startEntity} 752 * event.</p> 753 * 754 * <p>Note that the start/endDTD events will appear within 755 * the start/endDocument events from ContentHandler and 756 * before the first startElement event.</p> 757 * 758 * @param name The document type name. 759 * @param publicId The declared public identifier for the 760 * external DTD subset, or null if none was declared. 761 * @param systemId The declared system identifier for the 762 * external DTD subset, or null if none was declared. 763 * @throws SAXException The application may raise an 764 * exception. 765 * @see #endDTD 766 * @see #startEntity 767 */ startDTD(String name, String publicId, String systemId)768 public void startDTD(String name, String publicId, String systemId) 769 throws SAXException 770 { 771 772 if (DEBUG) 773 System.out.println("TransformerHandlerImpl#startDTD: " + name + ", " 774 + publicId + ", " + systemId); 775 776 if (null != m_lexicalHandler) 777 { 778 m_lexicalHandler.startDTD(name, publicId, systemId); 779 } 780 } 781 782 /** 783 * Report the end of DTD declarations. 784 * 785 * @throws SAXException The application may raise an exception. 786 * @see #startDTD 787 */ endDTD()788 public void endDTD() throws SAXException 789 { 790 791 if (DEBUG) 792 System.out.println("TransformerHandlerImpl#endDTD"); 793 794 if (null != m_lexicalHandler) 795 { 796 m_lexicalHandler.endDTD(); 797 } 798 } 799 800 /** 801 * Report the beginning of an entity in content. 802 * 803 * <p><strong>NOTE:</entity> entity references in attribute 804 * values -- and the start and end of the document entity -- 805 * are never reported.</p> 806 * 807 * <p>The start and end of the external DTD subset are reported 808 * using the pseudo-name "[dtd]". All other events must be 809 * properly nested within start/end entity events.</p> 810 * 811 * <p>Note that skipped entities will be reported through the 812 * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity} 813 * event, which is part of the ContentHandler interface.</p> 814 * 815 * @param name The name of the entity. If it is a parameter 816 * entity, the name will begin with '%'. 817 * @throws SAXException The application may raise an exception. 818 * @see #endEntity 819 * @see org.xml.sax.ext.DeclHandler#internalEntityDecl 820 * @see org.xml.sax.ext.DeclHandler#externalEntityDecl 821 */ startEntity(String name)822 public void startEntity(String name) throws SAXException 823 { 824 825 if (DEBUG) 826 System.out.println("TransformerHandlerImpl#startEntity: " + name); 827 828 if (null != m_lexicalHandler) 829 { 830 m_lexicalHandler.startEntity(name); 831 } 832 } 833 834 /** 835 * Report the end of an entity. 836 * 837 * @param name The name of the entity that is ending. 838 * @throws SAXException The application may raise an exception. 839 * @see #startEntity 840 */ endEntity(String name)841 public void endEntity(String name) throws SAXException 842 { 843 844 if (DEBUG) 845 System.out.println("TransformerHandlerImpl#endEntity: " + name); 846 847 if (null != m_lexicalHandler) 848 { 849 m_lexicalHandler.endEntity(name); 850 } 851 } 852 853 /** 854 * Report the start of a CDATA section. 855 * 856 * <p>The contents of the CDATA section will be reported through 857 * the regular {@link org.xml.sax.ContentHandler#characters 858 * characters} event.</p> 859 * 860 * @throws SAXException The application may raise an exception. 861 * @see #endCDATA 862 */ startCDATA()863 public void startCDATA() throws SAXException 864 { 865 866 if (DEBUG) 867 System.out.println("TransformerHandlerImpl#startCDATA"); 868 869 if (null != m_lexicalHandler) 870 { 871 m_lexicalHandler.startCDATA(); 872 } 873 } 874 875 /** 876 * Report the end of a CDATA section. 877 * 878 * @throws SAXException The application may raise an exception. 879 * @see #startCDATA 880 */ endCDATA()881 public void endCDATA() throws SAXException 882 { 883 884 if (DEBUG) 885 System.out.println("TransformerHandlerImpl#endCDATA"); 886 887 if (null != m_lexicalHandler) 888 { 889 m_lexicalHandler.endCDATA(); 890 } 891 } 892 893 /** 894 * Report an XML comment anywhere in the document. 895 * 896 * <p>This callback will be used for comments inside or outside the 897 * document element, including comments in the external DTD 898 * subset (if read).</p> 899 * 900 * @param ch An array holding the characters in the comment. 901 * @param start The starting position in the array. 902 * @param length The number of characters to use from the array. 903 * @throws SAXException The application may raise an exception. 904 */ comment(char ch[], int start, int length)905 public void comment(char ch[], int start, int length) throws SAXException 906 { 907 908 if (DEBUG) 909 System.out.println("TransformerHandlerImpl#comment: " + start + ", " 910 + length); 911 912 if (null != m_lexicalHandler) 913 { 914 m_lexicalHandler.comment(ch, start, length); 915 } 916 } 917 918 //////////////////////////////////////////////////////////////////// 919 // Implementation of org.xml.sax.ext.DeclHandler. 920 //////////////////////////////////////////////////////////////////// 921 922 /** 923 * Report an element type declaration. 924 * 925 * <p>The content model will consist of the string "EMPTY", the 926 * string "ANY", or a parenthesised group, optionally followed 927 * by an occurrence indicator. The model will be normalized so 928 * that all whitespace is removed,and will include the enclosing 929 * parentheses.</p> 930 * 931 * @param name The element type name. 932 * @param model The content model as a normalized string. 933 * @throws SAXException The application may raise an exception. 934 */ elementDecl(String name, String model)935 public void elementDecl(String name, String model) throws SAXException 936 { 937 938 if (DEBUG) 939 System.out.println("TransformerHandlerImpl#elementDecl: " + name + ", " 940 + model); 941 942 if (null != m_declHandler) 943 { 944 m_declHandler.elementDecl(name, model); 945 } 946 } 947 948 /** 949 * Report an attribute type declaration. 950 * 951 * <p>Only the effective (first) declaration for an attribute will 952 * be reported. The type will be one of the strings "CDATA", 953 * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", 954 * "ENTITIES", or "NOTATION", or a parenthesized token group with 955 * the separator "|" and all whitespace removed.</p> 956 * 957 * @param eName The name of the associated element. 958 * @param aName The name of the attribute. 959 * @param type A string representing the attribute type. 960 * @param valueDefault A string representing the attribute default 961 * ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if 962 * none of these applies. 963 * @param value A string representing the attribute's default value, 964 * or null if there is none. 965 * @throws SAXException The application may raise an exception. 966 */ attributeDecl( String eName, String aName, String type, String valueDefault, String value)967 public void attributeDecl( 968 String eName, String aName, String type, String valueDefault, String value) 969 throws SAXException 970 { 971 972 if (DEBUG) 973 System.out.println("TransformerHandlerImpl#attributeDecl: " + eName 974 + ", " + aName + ", etc..."); 975 976 if (null != m_declHandler) 977 { 978 m_declHandler.attributeDecl(eName, aName, type, valueDefault, value); 979 } 980 } 981 982 /** 983 * Report an internal entity declaration. 984 * 985 * <p>Only the effective (first) declaration for each entity 986 * will be reported.</p> 987 * 988 * @param name The name of the entity. If it is a parameter 989 * entity, the name will begin with '%'. 990 * @param value The replacement text of the entity. 991 * @throws SAXException The application may raise an exception. 992 * @see #externalEntityDecl 993 * @see org.xml.sax.DTDHandler#unparsedEntityDecl 994 */ internalEntityDecl(String name, String value)995 public void internalEntityDecl(String name, String value) 996 throws SAXException 997 { 998 999 if (DEBUG) 1000 System.out.println("TransformerHandlerImpl#internalEntityDecl: " + name 1001 + ", " + value); 1002 1003 if (null != m_declHandler) 1004 { 1005 m_declHandler.internalEntityDecl(name, value); 1006 } 1007 } 1008 1009 /** 1010 * Report a parsed external entity declaration. 1011 * 1012 * <p>Only the effective (first) declaration for each entity 1013 * will be reported.</p> 1014 * 1015 * @param name The name of the entity. If it is a parameter 1016 * entity, the name will begin with '%'. 1017 * @param publicId The declared public identifier of the entity, or 1018 * null if none was declared. 1019 * @param systemId The declared system identifier of the entity. 1020 * @throws SAXException The application may raise an exception. 1021 * @see #internalEntityDecl 1022 * @see org.xml.sax.DTDHandler#unparsedEntityDecl 1023 */ externalEntityDecl( String name, String publicId, String systemId)1024 public void externalEntityDecl( 1025 String name, String publicId, String systemId) throws SAXException 1026 { 1027 1028 if (DEBUG) 1029 System.out.println("TransformerHandlerImpl#externalEntityDecl: " + name 1030 + ", " + publicId + ", " + systemId); 1031 1032 if (null != m_declHandler) 1033 { 1034 m_declHandler.externalEntityDecl(name, publicId, systemId); 1035 } 1036 } 1037 1038 //////////////////////////////////////////////////////////////////// 1039 // Internal state. 1040 //////////////////////////////////////////////////////////////////// 1041 1042 /** Set to true for diagnostics output. */ 1043 private static boolean DEBUG = false; 1044 1045 /** 1046 * The transformer this will use to transform a 1047 * source tree into a result tree. 1048 */ 1049 private TransformerImpl m_transformer; 1050 1051 /** The system ID to use as a base for relative URLs. */ 1052 private String m_baseSystemID; 1053 1054 /** The result for the transformation. */ 1055 private Result m_result = null; 1056 1057 /** The locator for this TransformerHandler. */ 1058 private Locator m_locator = null; 1059 1060 /** The entity resolver to aggregate to. */ 1061 private EntityResolver m_entityResolver = null; 1062 1063 /** The DTD handler to aggregate to. */ 1064 private DTDHandler m_dtdHandler = null; 1065 1066 /** The content handler to aggregate to. */ 1067 private ContentHandler m_contentHandler = null; 1068 1069 /** The error handler to aggregate to. */ 1070 private ErrorHandler m_errorHandler = null; 1071 1072 /** The lexical handler to aggregate to. */ 1073 private LexicalHandler m_lexicalHandler = null; 1074 1075 /** The decl handler to aggregate to. */ 1076 private DeclHandler m_declHandler = null; 1077 1078 /** The Document Table Instance we are transforming. */ 1079 DTM m_dtm; 1080 } 1081