OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / xalan / transformer / TransformerHandlerImpl.java
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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 }