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