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 }