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