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 468653 2006-10-28 07:07:05Z minchau $
020 */
021
022 package org.apache.xalan.xsltc.trax;
023
024 import javax.xml.transform.Result;
025 import javax.xml.transform.Transformer;
026 import javax.xml.transform.TransformerException;
027 import javax.xml.transform.sax.TransformerHandler;
028 import javax.xml.transform.dom.DOMResult;
029
030 import org.apache.xalan.xsltc.StripFilter;
031 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
032 import org.apache.xalan.xsltc.dom.DOMWSFilter;
033 import org.apache.xalan.xsltc.dom.SAXImpl;
034 import org.apache.xalan.xsltc.dom.XSLTCDTMManager;
035 import org.apache.xalan.xsltc.runtime.AbstractTranslet;
036 import org.apache.xml.dtm.DTMWSFilter;
037 import org.apache.xml.serializer.SerializationHandler;
038
039 import org.xml.sax.Attributes;
040 import org.xml.sax.ContentHandler;
041 import org.xml.sax.DTDHandler;
042 import org.xml.sax.Locator;
043 import org.xml.sax.SAXException;
044 import org.xml.sax.ext.DeclHandler;
045 import org.xml.sax.ext.LexicalHandler;
046 import org.xml.sax.helpers.DefaultHandler;
047
048 /**
049 * Implementation of a JAXP1.1 TransformerHandler
050 * @author Morten Jorgensen
051 */
052 public class TransformerHandlerImpl implements TransformerHandler, DeclHandler {
053
054 private TransformerImpl _transformer;
055 private AbstractTranslet _translet = null;
056 private String _systemId;
057 private SAXImpl _dom = null;
058 private ContentHandler _handler = null;
059 private LexicalHandler _lexHandler = null;
060 private DTDHandler _dtdHandler = null;
061 private DeclHandler _declHandler = null;
062 private Result _result = null;
063 private Locator _locator = null;
064
065 private boolean _done = false; // Set in endDocument()
066
067 /**
068 * A flag indicating whether this transformer handler implements the
069 * identity transform.
070 */
071 private boolean _isIdentity = false;
072
073 /**
074 * Cosntructor - pass in reference to a TransformerImpl object
075 */
076 public TransformerHandlerImpl(TransformerImpl transformer) {
077 // Save the reference to the transformer
078 _transformer = transformer;
079
080 if (transformer.isIdentity()) {
081 // Set initial handler to the empty handler
082 _handler = new DefaultHandler();
083 _isIdentity = true;
084 }
085 else {
086 // Get a reference to the translet wrapped inside the transformer
087 _translet = _transformer.getTranslet();
088 }
089 }
090
091 /**
092 * Implements javax.xml.transform.sax.TransformerHandler.getSystemId()
093 * Get the base ID (URI or system ID) from where relative URLs will be
094 * resolved.
095 * @return The systemID that was set with setSystemId(String id)
096 */
097 public String getSystemId() {
098 return _systemId;
099 }
100
101 /**
102 * Implements javax.xml.transform.sax.TransformerHandler.setSystemId()
103 * Get the base ID (URI or system ID) from where relative URLs will be
104 * resolved.
105 * @param id Base URI for this stylesheet
106 */
107 public void setSystemId(String id) {
108 _systemId = id;
109 }
110
111 /**
112 * Implements javax.xml.transform.sax.TransformerHandler.getTransformer()
113 * Get the Transformer associated with this handler, which is needed in
114 * order to set parameters and output properties.
115 * @return The Transformer object
116 */
117 public Transformer getTransformer() {
118 return _transformer;
119 }
120
121 /**
122 * Implements javax.xml.transform.sax.TransformerHandler.setResult()
123 * Enables the user of the TransformerHandler to set the to set the Result
124 * for the transformation.
125 * @param result A Result instance, should not be null
126 * @throws IllegalArgumentException if result is invalid for some reason
127 */
128 public void setResult(Result result) throws IllegalArgumentException {
129 _result = result;
130
131 if (null == result) {
132 ErrorMsg err = new ErrorMsg(ErrorMsg.ER_RESULT_NULL);
133 throw new IllegalArgumentException(err.toString()); //"result should not be null");
134 }
135
136 if (_isIdentity) {
137 try {
138 // Connect this object with output system directly
139 SerializationHandler outputHandler =
140 _transformer.getOutputHandler(result);
141 _transformer.transferOutputProperties(outputHandler);
142
143 _handler = outputHandler;
144 _lexHandler = outputHandler;
145 }
146 catch (TransformerException e) {
147 _result = null;
148 }
149 }
150 else if (_done) {
151 // Run the transformation now, if not already done
152 try {
153 _transformer.setDOM(_dom);
154 _transformer.transform(null, _result);
155 }
156 catch (TransformerException e) {
157 // What the hell are we supposed to do with this???
158 throw new IllegalArgumentException(e.getMessage());
159 }
160 }
161 }
162
163 /**
164 * Implements org.xml.sax.ContentHandler.characters()
165 * Receive notification of character data.
166 */
167 public void characters(char[] ch, int start, int length)
168 throws SAXException
169 {
170 _handler.characters(ch, start, length);
171 }
172
173 /**
174 * Implements org.xml.sax.ContentHandler.startDocument()
175 * Receive notification of the beginning of a document.
176 */
177 public void startDocument() throws SAXException {
178 // Make sure setResult() was called before the first SAX event
179 if (_result == null) {
180 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_RESULT_ERR);
181 throw new SAXException(err.toString());
182 }
183
184 if (!_isIdentity) {
185 boolean hasIdCall = (_translet != null) ? _translet.hasIdCall() : false;
186 XSLTCDTMManager dtmManager = null;
187
188 // Create an internal DOM (not W3C) and get SAX2 input handler
189 try {
190 dtmManager =
191 (XSLTCDTMManager)_transformer.getTransformerFactory()
192 .getDTMManagerClass()
193 .newInstance();
194 } catch (Exception e) {
195 throw new SAXException(e);
196 }
197
198 DTMWSFilter wsFilter;
199 if (_translet != null && _translet instanceof StripFilter) {
200 wsFilter = new DOMWSFilter(_translet);
201 } else {
202 wsFilter = null;
203 }
204
205 // Construct the DTM using the SAX events that come through
206 _dom = (SAXImpl)dtmManager.getDTM(null, false, wsFilter, true,
207 false, hasIdCall);
208
209 _handler = _dom.getBuilder();
210 _lexHandler = (LexicalHandler) _handler;
211 _dtdHandler = (DTDHandler) _handler;
212 _declHandler = (DeclHandler) _handler;
213
214
215 // Set document URI
216 _dom.setDocumentURI(_systemId);
217
218 if (_locator != null) {
219 _handler.setDocumentLocator(_locator);
220 }
221 }
222
223 // Proxy call
224 _handler.startDocument();
225 }
226
227 /**
228 * Implements org.xml.sax.ContentHandler.endDocument()
229 * Receive notification of the end of a document.
230 */
231 public void endDocument() throws SAXException {
232 // Signal to the DOMBuilder that the document is complete
233 _handler.endDocument();
234
235 if (!_isIdentity) {
236 // Run the transformation now if we have a reference to a Result object
237 if (_result != null) {
238 try {
239 _transformer.setDOM(_dom);
240 _transformer.transform(null, _result);
241 }
242 catch (TransformerException e) {
243 throw new SAXException(e);
244 }
245 }
246 // Signal that the internal DOM is built (see 'setResult()').
247 _done = true;
248
249 // Set this DOM as the transformer's DOM
250 _transformer.setDOM(_dom);
251 }
252 if (_isIdentity && _result instanceof DOMResult) {
253 ((DOMResult)_result).setNode(_transformer.getTransletOutputHandlerFactory().getNode());
254 }
255 }
256
257 /**
258 * Implements org.xml.sax.ContentHandler.startElement()
259 * Receive notification of the beginning of an element.
260 */
261 public void startElement(String uri, String localName,
262 String qname, Attributes attributes)
263 throws SAXException
264 {
265 _handler.startElement(uri, localName, qname, attributes);
266 }
267
268 /**
269 * Implements org.xml.sax.ContentHandler.endElement()
270 * Receive notification of the end of an element.
271 */
272 public void endElement(String namespaceURI, String localName, String qname)
273 throws SAXException
274 {
275 _handler.endElement(namespaceURI, localName, qname);
276 }
277
278 /**
279 * Implements org.xml.sax.ContentHandler.processingInstruction()
280 * Receive notification of a processing instruction.
281 */
282 public void processingInstruction(String target, String data)
283 throws SAXException
284 {
285 _handler.processingInstruction(target, data);
286 }
287
288 /**
289 * Implements org.xml.sax.ext.LexicalHandler.startCDATA()
290 */
291 public void startCDATA() throws SAXException {
292 if (_lexHandler != null) {
293 _lexHandler.startCDATA();
294 }
295 }
296
297 /**
298 * Implements org.xml.sax.ext.LexicalHandler.endCDATA()
299 */
300 public void endCDATA() throws SAXException {
301 if (_lexHandler != null) {
302 _lexHandler.endCDATA();
303 }
304 }
305
306 /**
307 * Implements org.xml.sax.ext.LexicalHandler.comment()
308 * Receieve notification of a comment
309 */
310 public void comment(char[] ch, int start, int length)
311 throws SAXException
312 {
313 if (_lexHandler != null) {
314 _lexHandler.comment(ch, start, length);
315 }
316 }
317
318 /**
319 * Implements org.xml.sax.ContentHandler.ignorableWhitespace()
320 * Receive notification of ignorable whitespace in element
321 * content. Similar to characters(char[], int, int).
322 */
323 public void ignorableWhitespace(char[] ch, int start, int length)
324 throws SAXException
325 {
326 _handler.ignorableWhitespace(ch, start, length);
327 }
328
329 /**
330 * Implements org.xml.sax.ContentHandler.setDocumentLocator()
331 * Receive an object for locating the origin of SAX document events.
332 */
333 public void setDocumentLocator(Locator locator) {
334 _locator = locator;
335
336 if (_handler != null) {
337 _handler.setDocumentLocator(locator);
338 }
339 }
340
341 /**
342 * Implements org.xml.sax.ContentHandler.skippedEntity()
343 * Receive notification of a skipped entity.
344 */
345 public void skippedEntity(String name) throws SAXException {
346 _handler.skippedEntity(name);
347 }
348
349 /**
350 * Implements org.xml.sax.ContentHandler.startPrefixMapping()
351 * Begin the scope of a prefix-URI Namespace mapping.
352 */
353 public void startPrefixMapping(String prefix, String uri)
354 throws SAXException {
355 _handler.startPrefixMapping(prefix, uri);
356 }
357
358 /**
359 * Implements org.xml.sax.ContentHandler.endPrefixMapping()
360 * End the scope of a prefix-URI Namespace mapping.
361 */
362 public void endPrefixMapping(String prefix) throws SAXException {
363 _handler.endPrefixMapping(prefix);
364 }
365
366 /**
367 * Implements org.xml.sax.ext.LexicalHandler.startDTD()
368 */
369 public void startDTD(String name, String publicId, String systemId)
370 throws SAXException
371 {
372 if (_lexHandler != null) {
373 _lexHandler.startDTD(name, publicId, systemId);
374 }
375 }
376
377 /**
378 * Implements org.xml.sax.ext.LexicalHandler.endDTD()
379 */
380 public void endDTD() throws SAXException {
381 if (_lexHandler != null) {
382 _lexHandler.endDTD();
383 }
384 }
385
386 /**
387 * Implements org.xml.sax.ext.LexicalHandler.startEntity()
388 */
389 public void startEntity(String name) throws SAXException {
390 if (_lexHandler != null) {
391 _lexHandler.startEntity(name);
392 }
393 }
394
395 /**
396 * Implements org.xml.sax.ext.LexicalHandler.endEntity()
397 */
398 public void endEntity(String name) throws SAXException {
399 if (_lexHandler != null) {
400 _lexHandler.endEntity(name);
401 }
402 }
403
404 /**
405 * Implements org.xml.sax.DTDHandler.unparsedEntityDecl()
406 */
407 public void unparsedEntityDecl(String name, String publicId,
408 String systemId, String notationName) throws SAXException
409 {
410 if (_dtdHandler != null) {
411 _dtdHandler.unparsedEntityDecl(name, publicId, systemId,
412 notationName);
413 }
414 }
415
416 /**
417 * Implements org.xml.sax.DTDHandler.notationDecl()
418 */
419 public void notationDecl(String name, String publicId, String systemId)
420 throws SAXException
421 {
422 if (_dtdHandler != null) {
423 _dtdHandler.notationDecl(name, publicId, systemId);
424 }
425 }
426
427 /**
428 * Implements org.xml.sax.ext.DeclHandler.attributeDecl()
429 */
430 public void attributeDecl(String eName, String aName, String type,
431 String valueDefault, String value) throws SAXException
432 {
433 if (_declHandler != null) {
434 _declHandler.attributeDecl(eName, aName, type, valueDefault, value);
435 }
436 }
437
438 /**
439 * Implements org.xml.sax.ext.DeclHandler.elementDecl()
440 */
441 public void elementDecl(String name, String model)
442 throws SAXException
443 {
444 if (_declHandler != null) {
445 _declHandler.elementDecl(name, model);
446 }
447 }
448
449 /**
450 * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
451 */
452 public void externalEntityDecl(String name, String publicId, String systemId)
453 throws SAXException
454 {
455 if (_declHandler != null) {
456 _declHandler.externalEntityDecl(name, publicId, systemId);
457 }
458 }
459
460 /**
461 * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
462 */
463 public void internalEntityDecl(String name, String value)
464 throws SAXException
465 {
466 if (_declHandler != null) {
467 _declHandler.internalEntityDecl(name, value);
468 }
469 }
470 }