001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: TransformerHandlerImpl.java 468645 2006-10-28 06:57:24Z minchau $
020 */
021 package org.apache.xalan.transformer;
022
023 import java.io.IOException;
024
025 import javax.xml.transform.Result;
026 import javax.xml.transform.Transformer;
027 import javax.xml.transform.sax.TransformerHandler;
028
029 import org.apache.xalan.res.XSLMessages;
030 import org.apache.xalan.res.XSLTErrorResources;
031 import org.apache.xml.dtm.DTM;
032 import org.apache.xml.dtm.DTMManager;
033 import org.apache.xml.dtm.ref.IncrementalSAXSource_Filter;
034 import org.apache.xml.dtm.ref.sax2dtm.SAX2DTM;
035 import org.apache.xpath.XPathContext;
036
037 import org.xml.sax.Attributes;
038 import org.xml.sax.ContentHandler;
039 import org.xml.sax.DTDHandler;
040 import org.xml.sax.EntityResolver;
041 import org.xml.sax.ErrorHandler;
042 import org.xml.sax.InputSource;
043 import org.xml.sax.Locator;
044 import org.xml.sax.SAXException;
045 import org.xml.sax.SAXParseException;
046 import org.xml.sax.ext.DeclHandler;
047 import org.xml.sax.ext.LexicalHandler;
048 import org.apache.xml.serializer.SerializationHandler;
049
050
051 /**
052 * A TransformerHandler
053 * listens for SAX ContentHandler parse events and transforms
054 * them to a Result.
055 */
056 public class TransformerHandlerImpl
057 implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler,
058 LexicalHandler, TransformerHandler, DeclHandler
059 {
060 /**
061 * The flag for the setting of the optimize feature;
062 */
063 private final boolean m_optimizer;
064
065 /**
066 * The flag for the setting of the incremental feature;
067 */
068 private final boolean m_incremental;
069
070 /**
071 * The flag for the setting of the source_location feature;
072 */
073 private final boolean m_source_location;
074
075 private boolean m_insideParse = false;
076
077 ////////////////////////////////////////////////////////////////////
078 // Constructors.
079 ////////////////////////////////////////////////////////////////////
080
081 /**
082 * Construct a TransformerHandlerImpl.
083 *
084 * @param transformer Non-null reference to the Xalan transformer impl.
085 * @param doFragment True if the result should be a document fragement.
086 * @param baseSystemID The system ID to use as the base for relative URLs.
087 */
088 public TransformerHandlerImpl(TransformerImpl transformer,
089 boolean doFragment, String baseSystemID)
090 {
091
092 super();
093
094 m_transformer = transformer;
095 m_baseSystemID = baseSystemID;
096
097 XPathContext xctxt = transformer.getXPathContext();
098 DTM dtm = xctxt.getDTM(null, true, transformer, true, true);
099
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 }