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