1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /*
6  * Licensed to the Apache Software Foundation (ASF) under one or more
7  * contributor license agreements.  See the NOTICE file distributed with
8  * this work for additional information regarding copyright ownership.
9  * The ASF licenses this file to You under the Apache License, Version 2.0
10  * (the "License"); you may not use this file except in compliance with
11  * the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 package com.sun.org.apache.xalan.internal.xsltc.trax;
23 
24 import javax.xml.transform.Result;
25 import javax.xml.transform.Transformer;
26 import javax.xml.transform.TransformerException;
27 import javax.xml.transform.sax.TransformerHandler;
28 import javax.xml.transform.dom.DOMResult;
29 
30 import com.sun.org.apache.xalan.internal.xsltc.StripFilter;
31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
32 import com.sun.org.apache.xalan.internal.xsltc.dom.DOMWSFilter;
33 import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl;
34 import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager;
35 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
36 import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
37 import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
38 
39 import org.xml.sax.Attributes;
40 import org.xml.sax.ContentHandler;
41 import org.xml.sax.DTDHandler;
42 import org.xml.sax.Locator;
43 import org.xml.sax.SAXException;
44 import org.xml.sax.ext.DeclHandler;
45 import org.xml.sax.ext.LexicalHandler;
46 import org.xml.sax.helpers.DefaultHandler;
47 
48 /**
49  * Implementation of a JAXP1.1 TransformerHandler
50  * @author Morten Jorgensen
51  */
52 public class TransformerHandlerImpl implements TransformerHandler, DeclHandler {
53 
54     private TransformerImpl  _transformer;
55     private AbstractTranslet _translet = null;
56     private String           _systemId;
57     private SAXImpl          _dom = null;
58     private ContentHandler   _handler = null;
59     private LexicalHandler   _lexHandler = null;
60     private DTDHandler       _dtdHandler = null;
61     private DeclHandler      _declHandler = null;
62     private Result           _result = null;
63     private Locator          _locator = null;
64 
65     private boolean          _done = false; // Set in endDocument()
66 
67     /**
68      * A flag indicating whether this transformer handler implements the
69      * identity transform.
70      */
71     private boolean _isIdentity = false;
72 
73     /**
74      * Cosntructor - pass in reference to a TransformerImpl object
75      */
TransformerHandlerImpl(TransformerImpl transformer)76     public TransformerHandlerImpl(TransformerImpl transformer) {
77         // Save the reference to the transformer
78         _transformer = transformer;
79 
80         if (transformer.isIdentity()) {
81             // Set initial handler to the empty handler
82             _handler = new DefaultHandler();
83             _isIdentity = true;
84         }
85         else {
86             // Get a reference to the translet wrapped inside the transformer
87             _translet = _transformer.getTranslet();
88         }
89     }
90 
91     /**
92      * Implements javax.xml.transform.sax.TransformerHandler.getSystemId()
93      * Get the base ID (URI or system ID) from where relative URLs will be
94      * resolved.
95      * @return The systemID that was set with setSystemId(String id)
96      */
97     @Override
getSystemId()98     public String getSystemId() {
99         return _systemId;
100     }
101 
102     /**
103      * Implements javax.xml.transform.sax.TransformerHandler.setSystemId()
104      * Get the base ID (URI or system ID) from where relative URLs will be
105      * resolved.
106      * @param id Base URI for this stylesheet
107      */
108     @Override
setSystemId(String id)109     public void setSystemId(String id) {
110         _systemId = id;
111     }
112 
113     /**
114      * Implements javax.xml.transform.sax.TransformerHandler.getTransformer()
115      * Get the Transformer associated with this handler, which is needed in
116      * order to set parameters and output properties.
117      * @return The Transformer object
118      */
119     @Override
getTransformer()120     public Transformer getTransformer() {
121         return _transformer;
122     }
123 
124     /**
125      * Implements javax.xml.transform.sax.TransformerHandler.setResult()
126      * Enables the user of the TransformerHandler to set the to set the Result
127      * for the transformation.
128      * @param result A Result instance, should not be null
129      * @throws IllegalArgumentException if result is invalid for some reason
130      */
131     @Override
setResult(Result result)132     public void setResult(Result result) throws IllegalArgumentException {
133         _result = result;
134 
135     if (null == result) {
136        ErrorMsg err = new ErrorMsg(ErrorMsg.ER_RESULT_NULL);
137        throw new IllegalArgumentException(err.toString()); //"result should not be null");
138     }
139 
140         if (_isIdentity) {
141             try {
142                 // Connect this object with output system directly
143                 SerializationHandler outputHandler =
144                     _transformer.getOutputHandler(result);
145                 _transformer.transferOutputProperties(outputHandler);
146 
147                 _handler = outputHandler;
148                 _lexHandler = outputHandler;
149             }
150             catch (TransformerException e) {
151                 _result = null;
152             }
153         }
154         else if (_done) {
155             // Run the transformation now, if not already done
156             try {
157                 _transformer.setDOM(_dom);
158                 _transformer.transform(null, _result);
159             }
160             catch (TransformerException e) {
161                 // What the hell are we supposed to do with this???
162                 throw new IllegalArgumentException(e.getMessage());
163             }
164         }
165     }
166 
167     /**
168      * Implements org.xml.sax.ContentHandler.characters()
169      * Receive notification of character data.
170      */
171     @Override
characters(char[] ch, int start, int length)172     public void characters(char[] ch, int start, int length)
173         throws SAXException
174     {
175         _handler.characters(ch, start, length);
176     }
177 
178     /**
179      * Implements org.xml.sax.ContentHandler.startDocument()
180      * Receive notification of the beginning of a document.
181      */
182     @Override
startDocument()183     public void startDocument() throws SAXException {
184         // Make sure setResult() was called before the first SAX event
185         if (_result == null) {
186             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_RESULT_ERR);
187             throw new SAXException(err.toString());
188         }
189 
190         if (!_isIdentity) {
191             boolean hasIdCall = (_translet != null) ? _translet.hasIdCall() : false;
192             XSLTCDTMManager dtmManager = null;
193 
194             // Create an internal DOM (not W3C) and get SAX2 input handler
195             try {
196                 dtmManager = _transformer.getTransformerFactory()
197                                          .createNewDTMManagerInstance();
198             } catch (Exception e) {
199                 throw new SAXException(e);
200             }
201 
202             DTMWSFilter wsFilter;
203             if (_translet != null && _translet instanceof StripFilter) {
204                 wsFilter = new DOMWSFilter(_translet);
205             } else {
206                 wsFilter = null;
207             }
208 
209             // Construct the DTM using the SAX events that come through
210             _dom = (SAXImpl)dtmManager.getDTM(null, false, wsFilter, true,
211                                               false, hasIdCall);
212 
213             _handler = _dom.getBuilder();
214             _lexHandler = (LexicalHandler) _handler;
215             _dtdHandler = (DTDHandler) _handler;
216             _declHandler = (DeclHandler) _handler;
217 
218 
219             // Set document URI
220             _dom.setDocumentURI(_systemId);
221 
222             if (_locator != null) {
223                 _handler.setDocumentLocator(_locator);
224             }
225         }
226 
227         // Proxy call
228         _handler.startDocument();
229     }
230 
231     /**
232      * Implements org.xml.sax.ContentHandler.endDocument()
233      * Receive notification of the end of a document.
234      */
235     @Override
endDocument()236     public void endDocument() throws SAXException {
237         // Signal to the DOMBuilder that the document is complete
238         _handler.endDocument();
239 
240         if (!_isIdentity) {
241             // Run the transformation now if we have a reference to a Result object
242             if (_result != null) {
243                 try {
244                     _transformer.setDOM(_dom);
245                     _transformer.transform(null, _result);
246                 }
247                 catch (TransformerException e) {
248                     throw new SAXException(e);
249                 }
250             }
251             // Signal that the internal DOM is built (see 'setResult()').
252             _done = true;
253 
254             // Set this DOM as the transformer's DOM
255             _transformer.setDOM(_dom);
256         }
257         if (_isIdentity && _result instanceof DOMResult) {
258             ((DOMResult)_result).setNode(_transformer.getTransletOutputHandlerFactory().getNode());
259         }
260     }
261 
262     /**
263      * Implements org.xml.sax.ContentHandler.startElement()
264      * Receive notification of the beginning of an element.
265      */
266     @Override
startElement(String uri, String localName, String qname, Attributes attributes)267     public void startElement(String uri, String localName,
268                              String qname, Attributes attributes)
269         throws SAXException
270     {
271         _handler.startElement(uri, localName, qname, attributes);
272     }
273 
274     /**
275      * Implements org.xml.sax.ContentHandler.endElement()
276      * Receive notification of the end of an element.
277      */
278     @Override
endElement(String namespaceURI, String localName, String qname)279     public void endElement(String namespaceURI, String localName, String qname)
280         throws SAXException
281     {
282         _handler.endElement(namespaceURI, localName, qname);
283     }
284 
285     /**
286      * Implements org.xml.sax.ContentHandler.processingInstruction()
287      * Receive notification of a processing instruction.
288      */
289     @Override
processingInstruction(String target, String data)290     public void processingInstruction(String target, String data)
291         throws SAXException
292     {
293         _handler.processingInstruction(target, data);
294     }
295 
296     /**
297      * Implements org.xml.sax.ext.LexicalHandler.startCDATA()
298      */
299     @Override
startCDATA()300     public void startCDATA() throws SAXException {
301         if (_lexHandler != null) {
302             _lexHandler.startCDATA();
303         }
304     }
305 
306     /**
307      * Implements org.xml.sax.ext.LexicalHandler.endCDATA()
308      */
309     @Override
endCDATA()310     public void endCDATA() throws SAXException {
311         if (_lexHandler != null) {
312             _lexHandler.endCDATA();
313         }
314     }
315 
316     /**
317      * Implements org.xml.sax.ext.LexicalHandler.comment()
318      * Receieve notification of a comment
319      */
320     @Override
comment(char[] ch, int start, int length)321     public void comment(char[] ch, int start, int length)
322         throws SAXException
323     {
324         if (_lexHandler != null) {
325             _lexHandler.comment(ch, start, length);
326         }
327     }
328 
329     /**
330      * Implements org.xml.sax.ContentHandler.ignorableWhitespace()
331      * Receive notification of ignorable whitespace in element
332      * content. Similar to characters(char[], int, int).
333      */
334     @Override
ignorableWhitespace(char[] ch, int start, int length)335     public void ignorableWhitespace(char[] ch, int start, int length)
336         throws SAXException
337     {
338         _handler.ignorableWhitespace(ch, start, length);
339     }
340 
341     /**
342      * Implements org.xml.sax.ContentHandler.setDocumentLocator()
343      * Receive an object for locating the origin of SAX document events.
344      */
345     @Override
setDocumentLocator(Locator locator)346     public void setDocumentLocator(Locator locator) {
347         _locator = locator;
348 
349         if (_handler != null) {
350             _handler.setDocumentLocator(locator);
351         }
352     }
353 
354     /**
355      * Implements org.xml.sax.ContentHandler.skippedEntity()
356      * Receive notification of a skipped entity.
357      */
358     @Override
skippedEntity(String name)359     public void skippedEntity(String name) throws SAXException {
360         _handler.skippedEntity(name);
361     }
362 
363     /**
364      * Implements org.xml.sax.ContentHandler.startPrefixMapping()
365      * Begin the scope of a prefix-URI Namespace mapping.
366      */
367     @Override
startPrefixMapping(String prefix, String uri)368     public void startPrefixMapping(String prefix, String uri)
369         throws SAXException {
370         _handler.startPrefixMapping(prefix, uri);
371     }
372 
373     /**
374      * Implements org.xml.sax.ContentHandler.endPrefixMapping()
375      * End the scope of a prefix-URI Namespace mapping.
376      */
377     @Override
endPrefixMapping(String prefix)378     public void endPrefixMapping(String prefix) throws SAXException {
379         _handler.endPrefixMapping(prefix);
380     }
381 
382     /**
383      * Implements org.xml.sax.ext.LexicalHandler.startDTD()
384      */
385     @Override
startDTD(String name, String publicId, String systemId)386     public void startDTD(String name, String publicId, String systemId)
387         throws SAXException
388     {
389         if (_lexHandler != null) {
390             _lexHandler.startDTD(name, publicId, systemId);
391         }
392     }
393 
394     /**
395      * Implements org.xml.sax.ext.LexicalHandler.endDTD()
396      */
397     @Override
endDTD()398     public void endDTD() throws SAXException {
399         if (_lexHandler != null) {
400             _lexHandler.endDTD();
401         }
402     }
403 
404     /**
405      * Implements org.xml.sax.ext.LexicalHandler.startEntity()
406      */
407     @Override
startEntity(String name)408     public void startEntity(String name) throws SAXException {
409         if (_lexHandler != null) {
410             _lexHandler.startEntity(name);
411         }
412     }
413 
414     /**
415      * Implements org.xml.sax.ext.LexicalHandler.endEntity()
416      */
417     @Override
endEntity(String name)418     public void endEntity(String name) throws SAXException {
419         if (_lexHandler != null) {
420             _lexHandler.endEntity(name);
421         }
422     }
423 
424     /**
425      * Implements org.xml.sax.DTDHandler.unparsedEntityDecl()
426      */
427     @Override
unparsedEntityDecl(String name, String publicId, String systemId, String notationName)428     public void unparsedEntityDecl(String name, String publicId,
429         String systemId, String notationName) throws SAXException
430     {
431         if (_dtdHandler != null) {
432             _dtdHandler.unparsedEntityDecl(name, publicId, systemId,
433                                            notationName);
434         }
435     }
436 
437     /**
438      * Implements org.xml.sax.DTDHandler.notationDecl()
439      */
440     @Override
notationDecl(String name, String publicId, String systemId)441     public void notationDecl(String name, String publicId, String systemId)
442         throws SAXException
443     {
444         if (_dtdHandler != null) {
445             _dtdHandler.notationDecl(name, publicId, systemId);
446         }
447     }
448 
449     /**
450      * Implements org.xml.sax.ext.DeclHandler.attributeDecl()
451      */
452     @Override
attributeDecl(String eName, String aName, String type, String valueDefault, String value)453     public void attributeDecl(String eName, String aName, String type,
454         String valueDefault, String value) throws SAXException
455     {
456         if (_declHandler != null) {
457             _declHandler.attributeDecl(eName, aName, type, valueDefault, value);
458         }
459     }
460 
461     /**
462      * Implements org.xml.sax.ext.DeclHandler.elementDecl()
463      */
464     @Override
elementDecl(String name, String model)465     public void elementDecl(String name, String model)
466         throws SAXException
467     {
468         if (_declHandler != null) {
469             _declHandler.elementDecl(name, model);
470         }
471     }
472 
473     /**
474      * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
475      */
476     @Override
externalEntityDecl(String name, String publicId, String systemId)477     public void externalEntityDecl(String name, String publicId, String systemId)
478         throws SAXException
479     {
480         if (_declHandler != null) {
481             _declHandler.externalEntityDecl(name, publicId, systemId);
482         }
483     }
484 
485     /**
486      * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
487      */
488     @Override
internalEntityDecl(String name, String value)489     public void internalEntityDecl(String name, String value)
490         throws SAXException
491     {
492         if (_declHandler != null) {
493             _declHandler.internalEntityDecl(name, value);
494         }
495     }
496 
497 
498    /** Implementation of the reset() method
499     *
500     */
reset()501    public void reset() {
502        _systemId = null;
503        _dom = null;
504        _handler = null;
505        _lexHandler = null;
506        _dtdHandler = null;
507        _declHandler = null;
508        _result = null;
509        _locator = null;
510    }
511 }
512