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      */
  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
  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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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     */
 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 }