src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java

Print this page




  82 import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;
  83 import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory;
  84 
  85 import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
  86 import com.sun.org.apache.xml.internal.utils.XMLReaderManager;
  87 
  88 import org.xml.sax.ContentHandler;
  89 import org.xml.sax.InputSource;
  90 import org.xml.sax.SAXException;
  91 import org.xml.sax.XMLReader;
  92 import org.xml.sax.ext.LexicalHandler;
  93 
  94 /**
  95  * @author Morten Jorgensen
  96  * @author G. Todd Miller
  97  * @author Santiago Pericas-Geertsen
  98  */
  99 public final class TransformerImpl extends Transformer
 100     implements DOMCache, ErrorListener
 101 {
 102     private final static String EMPTY_STRING = "";
 103     private final static String NO_STRING    = "no";
 104     private final static String YES_STRING   = "yes";
 105     private final static String XML_STRING   = "xml";
 106 
 107     private final static String LEXICAL_HANDLER_PROPERTY =
 108         "http://xml.org/sax/properties/lexical-handler";
 109     private static final String NAMESPACE_FEATURE =
 110         "http://xml.org/sax/features/namespaces";
 111 
 112     /**
 113      * Namespace prefixes feature for {@link XMLReader}.
 114      */
 115     private static final String NAMESPACE_PREFIXES_FEATURE =
 116         "http://xml.org/sax/features/namespace-prefixes";
 117 
 118     /**
 119      * A reference to the translet or null if the identity transform.
 120      */
 121     private AbstractTranslet _translet = null;
 122 
 123     /**
 124      * The output method of this transformation.
 125      */


 139      * An error listener for runtime errors.
 140      */
 141     private ErrorListener _errorListener = this;
 142 
 143     /**
 144      * A reference to a URI resolver for calls to document().
 145      */
 146     private URIResolver _uriResolver = null;
 147 
 148     /**
 149      * Output properties of this transformer instance.
 150      */
 151     private Properties _properties, _propertiesClone;
 152 
 153     /**
 154      * A reference to an output handler factory.
 155      */
 156     private TransletOutputHandlerFactory _tohFactory = null;
 157 
 158     /**
 159      * A reference to a internal DOM represenation of the input.
 160      */
 161     private DOM _dom = null;
 162 
 163     /**
 164      * Number of indent spaces to add when indentation is on.
 165      */
 166     private int _indentNumber;
 167 
 168     /**
 169      * A reference to the transformer factory that this templates
 170      * object belongs to.
 171      */
 172     private TransformerFactoryImpl _tfactory = null;
 173 
 174     /**
 175      * A reference to the output stream, if we create one in our code.
 176      */
 177     private OutputStream _ostream = null;
 178 
 179     /**


 221     /**
 222      * A hashtable to store parameters for the identity transform. These
 223      * are not needed during the transformation, but we must keep track of
 224      * them to be fully complaint with the JAXP API.
 225      */
 226     private Hashtable _parameters = null;
 227 
 228     /**
 229      * This class wraps an ErrorListener into a MessageHandler in order to
 230      * capture messages reported via xsl:message.
 231      */
 232     static class MessageHandler
 233            extends com.sun.org.apache.xalan.internal.xsltc.runtime.MessageHandler
 234     {
 235         private ErrorListener _errorListener;
 236 
 237         public MessageHandler(ErrorListener errorListener) {
 238             _errorListener = errorListener;
 239         }
 240 

 241         public void displayMessage(String msg) {
 242             if(_errorListener == null) {
 243                 System.err.println(msg);
 244             }
 245             else {
 246                 try {
 247                     _errorListener.warning(new TransformerException(msg));
 248                 }
 249                 catch (TransformerException e) {
 250                     // ignored
 251                 }
 252             }
 253         }
 254     }
 255 
 256     protected TransformerImpl(Properties outputProperties, int indentNumber,
 257         TransformerFactoryImpl tfactory)
 258     {
 259         this(null, outputProperties, indentNumber, tfactory);
 260         _isIdentity = true;


 306 
 307     /**
 308      * Returns the translet wrapped inside this Transformer or
 309      * null if this is the identity transform.
 310      */
 311     protected AbstractTranslet getTranslet() {
 312         return _translet;
 313     }
 314 
 315     public boolean isIdentity() {
 316         return _isIdentity;
 317     }
 318 
 319     /**
 320      * Implements JAXP's Transformer.transform()
 321      *
 322      * @param source Contains the input XML document
 323      * @param result Will contain the output from the transformation
 324      * @throws TransformerException
 325      */

 326     public void transform(Source source, Result result)
 327         throws TransformerException
 328     {
 329         if (!_isIdentity) {
 330             if (_translet == null) {
 331                 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_TRANSLET_ERR);
 332                 throw new TransformerException(err.toString());
 333             }
 334             // Pass output properties to the translet
 335             transferOutputProperties(_translet);
 336         }
 337 
 338         final SerializationHandler toHandler = getOutputHandler(result);
 339         if (toHandler == null) {
 340             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
 341             throw new TransformerException(err.toString());
 342         }
 343 
 344         if (_uriResolver != null && !_isIdentity) {
 345             _translet.setDOMCache(this);


 448                     return _tohFactory.getSerializationHandler();
 449                 }
 450 
 451                 // or try to get an OutputStream from Result object
 452                 final OutputStream ostream = target.getOutputStream();
 453                 if (ostream != null) {
 454                     _tohFactory.setOutputStream(ostream);
 455                     return _tohFactory.getSerializationHandler();
 456                 }
 457 
 458                 // or try to get just a systemId string from Result object
 459                 String systemId = result.getSystemId();
 460                 if (systemId == null) {
 461                     ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_RESULT_ERR);
 462                     throw new TransformerException(err.toString());
 463                 }
 464 
 465                 // System Id may be in one of several forms, (1) a uri
 466                 // that starts with 'file:', (2) uri that starts with 'http:'
 467                 // or (3) just a filename on the local system.
 468                 URL url = null;
 469                 if (systemId.startsWith("file:")) {
 470                     // if StreamResult(File) or setSystemID(File) was used,
 471                     // the systemId will be URI encoded as a result of File.toURI(),
 472                     // it must be decoded for use by URL
 473                     try{
 474                         URI uri = new URI(systemId) ;
 475                         systemId = "file:";
 476 
 477                         String host = uri.getHost(); // decoded String
 478                         String path = uri.getPath(); //decoded String
 479                         if (path == null) {
 480                          path = "";
 481                         }
 482 
 483                         // if host (URI authority) then file:// + host + path
 484                         // else just path (may be absolute or relative)
 485                         if (host != null) {
 486                          systemId += "//" + host + path;
 487                         } else {
 488                          systemId += "//" + path;


 520         }
 521         // If we cannot create the file specified by the SystemId
 522         catch (IOException e) {
 523             throw new TransformerException(e);
 524         }
 525         return null;
 526     }
 527 
 528     /**
 529      * Set the internal DOM that will be used for the next transformation
 530      */
 531     protected void setDOM(DOM dom) {
 532         _dom = dom;
 533     }
 534 
 535     /**
 536      * Builds an internal DOM from a TrAX Source object
 537      */
 538     private DOM getDOM(Source source) throws TransformerException {
 539         try {
 540             DOM dom = null;
 541 
 542             if (source != null) {
 543                 DTMWSFilter wsfilter;
 544                 if (_translet != null && _translet instanceof StripFilter) {
 545                     wsfilter = new DOMWSFilter(_translet);
 546                  } else {
 547                     wsfilter = null;
 548                  }
 549 
 550                  boolean hasIdCall = (_translet != null) ? _translet.hasIdCall()
 551                                                          : false;
 552 
 553                  if (_dtmManager == null) {
 554                      _dtmManager =
 555                          (XSLTCDTMManager)_tfactory.getDTMManagerClass()
 556                                                    .newInstance();
 557                      _dtmManager.setServicesMechnism(_useServicesMechanism);
 558                  }
 559                  dom = (DOM)_dtmManager.getDTM(source, false, wsfilter, true,
 560                                               false, false, 0, hasIdCall);
 561             } else if (_dom != null) {
 562                  dom = _dom;
 563                  _dom = null;  // use only once, so reset to 'null'
 564             } else {
 565                  return null;
 566             }
 567 
 568             if (!_isIdentity) {
 569                 // Give the translet the opportunity to make a prepass of
 570                 // the document, in case it can extract useful information early
 571                 _translet.prepassDocument(dom);
 572             }
 573 
 574             return dom;
 575 
 576         }


 659                 }
 660 
 661                 // Hook up reader and output handler
 662                 try {
 663                     reader.setProperty(LEXICAL_HANDLER_PROPERTY, handler);
 664                     reader.setFeature(NAMESPACE_PREFIXES_FEATURE, true);
 665                 } catch (SAXException e) {
 666                     // Falls through
 667                 }
 668                 reader.setContentHandler(handler);
 669 
 670                 // Start pushing SAX events
 671                 reader.parse(input);
 672             } finally {
 673                 if (!userReader) {
 674                     _readerManager.releaseXMLReader(reader);
 675                 }
 676             }
 677         } else if (source instanceof StAXSource) {
 678             final StAXSource staxSource = (StAXSource)source;
 679             StAXEvent2SAX staxevent2sax = null;
 680             StAXStream2SAX staxStream2SAX = null;
 681             if (staxSource.getXMLEventReader() != null) {
 682                 final XMLEventReader xmlEventReader = staxSource.getXMLEventReader();
 683                 staxevent2sax = new StAXEvent2SAX(xmlEventReader);
 684                 staxevent2sax.setContentHandler(handler);
 685                 staxevent2sax.parse();
 686                 handler.flushPending();
 687             } else if (staxSource.getXMLStreamReader() != null) {
 688                 final XMLStreamReader xmlStreamReader = staxSource.getXMLStreamReader();
 689                 staxStream2SAX = new StAXStream2SAX(xmlStreamReader);
 690                 staxStream2SAX.setContentHandler(handler);
 691                 staxStream2SAX.parse();
 692                 handler.flushPending();
 693             }
 694         } else if (source instanceof DOMSource) {
 695             final DOMSource domsrc = (DOMSource) source;
 696             new DOM2TO(domsrc.getNode(), handler).parse();
 697         } else if (source instanceof XSLTCSource) {
 698             final DOM dom = ((XSLTCSource) source).getDOM(null, _translet);
 699             ((SAXImpl)dom).copy(handler);
 700         } else {


 753         } finally {
 754             _dtmManager = null;
 755         }
 756 
 757         // If we create an output stream for the Result, we need to close it after the transformation.
 758         if (_ostream != null) {
 759             try {
 760                 _ostream.close();
 761             }
 762             catch (IOException e) {}
 763             _ostream = null;
 764         }
 765     }
 766 
 767     /**
 768      * Implements JAXP's Transformer.getErrorListener()
 769      * Get the error event handler in effect for the transformation.
 770      *
 771      * @return The error event handler currently in effect
 772      */

 773     public ErrorListener getErrorListener() {
 774         return _errorListener;
 775     }
 776 
 777     /**
 778      * Implements JAXP's Transformer.setErrorListener()
 779      * Set the error event listener in effect for the transformation.
 780      * Register a message handler in the translet in order to forward
 781      * xsl:messages to error listener.
 782      *
 783      * @param listener The error event listener to use
 784      * @throws IllegalArgumentException
 785      */

 786     public void setErrorListener(ErrorListener listener)
 787         throws IllegalArgumentException {
 788         if (listener == null) {
 789             ErrorMsg err = new ErrorMsg(ErrorMsg.ERROR_LISTENER_NULL_ERR,
 790                                         "Transformer");
 791             throw new IllegalArgumentException(err.toString());
 792         }
 793         _errorListener = listener;
 794 
 795         // Register a message handler to report xsl:messages
 796     if (_translet != null)
 797         _translet.setMessageHandler(new MessageHandler(_errorListener));
 798     }
 799 
 800     /**
 801      * Inform TrAX error listener of an error
 802      */
 803     private void postErrorToListener(String message) {
 804         try {
 805             _errorListener.error(new TransformerException(message));


 813      * Inform TrAX error listener of a warning
 814      */
 815     private void postWarningToListener(String message) {
 816         try {
 817             _errorListener.warning(new TransformerException(message));
 818         }
 819         catch (TransformerException e) {
 820             // ignored - transformation cannot be continued
 821         }
 822     }
 823 
 824     /**
 825      * The translet stores all CDATA sections set in the <xsl:output> element
 826      * in a Hashtable. This method will re-construct the whitespace separated
 827      * list of elements given in the <xsl:output> element.
 828      */
 829     private String makeCDATAString(Hashtable cdata) {
 830         // Return a 'null' string if no CDATA section elements were specified
 831         if (cdata == null) return null;
 832 
 833         StringBuffer result = new StringBuffer();
 834 
 835         // Get an enumeration of all the elements in the hashtable
 836         Enumeration elements = cdata.keys();
 837         if (elements.hasMoreElements()) {
 838             result.append((String)elements.nextElement());
 839             while (elements.hasMoreElements()) {
 840                 String element = (String)elements.nextElement();
 841                 result.append(' ');
 842                 result.append(element);
 843             }
 844         }
 845 
 846         return(result.toString());
 847     }
 848 
 849     /**
 850      * Implements JAXP's Transformer.getOutputProperties().
 851      * Returns a copy of the output properties for the transformation. This is
 852      * a set of layered properties. The first layer contains properties set by
 853      * calls to setOutputProperty() and setOutputProperties() on this class,
 854      * and the output settings defined in the stylesheet's <xsl:output>
 855      * element makes up the second level, while the default XSLT output
 856      * settings are returned on the third level.
 857      *
 858      * @return Properties in effect for this Transformer
 859      */

 860     public Properties getOutputProperties() {
 861         return (Properties) _properties.clone();
 862     }
 863 
 864     /**
 865      * Implements JAXP's Transformer.getOutputProperty().
 866      * Get an output property that is in effect for the transformation. The
 867      * property specified may be a property that was set with setOutputProperty,
 868      * or it may be a property specified in the stylesheet.
 869      *
 870      * @param name A non-null string that contains the name of the property
 871      * @throws IllegalArgumentException if the property name is not known
 872      */

 873     public String getOutputProperty(String name)
 874         throws IllegalArgumentException
 875     {
 876         if (!validOutputProperty(name)) {
 877             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 878             throw new IllegalArgumentException(err.toString());
 879         }
 880         return _properties.getProperty(name);
 881     }
 882 
 883     /**
 884      * Implements JAXP's Transformer.setOutputProperties().
 885      * Set the output properties for the transformation. These properties
 886      * will override properties set in the Templates with xsl:output.
 887      * Unrecognised properties will be quitely ignored.
 888      *
 889      * @param properties The properties to use for the Transformer
 890      * @throws IllegalArgumentException Never, errors are ignored
 891      */

 892     public void setOutputProperties(Properties properties)
 893         throws IllegalArgumentException
 894     {
 895         if (properties != null) {
 896             final Enumeration names = properties.propertyNames();
 897 
 898             while (names.hasMoreElements()) {
 899                 final String name = (String) names.nextElement();
 900 
 901                 // Ignore lower layer properties
 902                 if (isDefaultProperty(name, properties)) continue;
 903 
 904                 if (validOutputProperty(name)) {
 905                     _properties.setProperty(name, properties.getProperty(name));
 906                 }
 907                 else {
 908                     ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 909                     throw new IllegalArgumentException(err.toString());
 910                 }
 911             }
 912         }
 913         else {
 914             _properties = _propertiesClone;
 915         }
 916     }
 917 
 918     /**
 919      * Implements JAXP's Transformer.setOutputProperty().
 920      * Get an output property that is in effect for the transformation. The
 921      * property specified may be a property that was set with
 922      * setOutputProperty(), or it may be a property specified in the stylesheet.
 923      *
 924      * @param name The name of the property to set
 925      * @param value The value to assign to the property
 926      * @throws IllegalArgumentException Never, errors are ignored
 927      */

 928     public void setOutputProperty(String name, String value)
 929         throws IllegalArgumentException
 930     {
 931         if (!validOutputProperty(name)) {
 932             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 933             throw new IllegalArgumentException(err.toString());
 934         }
 935         _properties.setProperty(name, value);
 936     }
 937 
 938     /**
 939      * Internal method to pass any properties to the translet prior to
 940      * initiating the transformation
 941      */
 942     private void transferOutputProperties(AbstractTranslet translet)
 943     {
 944         // Return right now if no properties are set
 945         if (_properties == null) return;
 946 
 947         // Get a list of all the defined properties


1188                 name.equals(OutputPropertiesFactory.ORACLE_IS_STANDALONE) ||
1189                 name.charAt(0) == '{');
1190     }
1191 
1192     /**
1193      * Checks if a given output property is default (2nd layer only)
1194      */
1195     private boolean isDefaultProperty(String name, Properties properties) {
1196         return (properties.get(name) == null);
1197     }
1198 
1199     /**
1200      * Implements JAXP's Transformer.setParameter()
1201      * Add a parameter for the transformation. The parameter is simply passed
1202      * on to the translet - no validation is performed - so any unused
1203      * parameters are quitely ignored by the translet.
1204      *
1205      * @param name The name of the parameter
1206      * @param value The value to assign to the parameter
1207      */

1208     public void setParameter(String name, Object value) {
1209 
1210         if (value == null) {
1211             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_SET_PARAM_VALUE, name);
1212             throw new IllegalArgumentException(err.toString());
1213         }
1214 
1215         if (_isIdentity) {
1216             if (_parameters == null) {
1217                 _parameters = new Hashtable();
1218             }
1219             _parameters.put(name, value);
1220         }
1221         else {
1222             _translet.addParameter(name, value);
1223         }
1224     }
1225 
1226     /**
1227      * Implements JAXP's Transformer.clearParameters()
1228      * Clear all parameters set with setParameter. Clears the translet's
1229      * parameter stack.
1230      */

1231     public void clearParameters() {
1232         if (_isIdentity && _parameters != null) {
1233             _parameters.clear();
1234         }
1235         else {
1236             _translet.clearParameters();
1237         }
1238     }
1239 
1240     /**
1241      * Implements JAXP's Transformer.getParameter()
1242      * Returns the value of a given parameter. Note that the translet will not
1243      * keep values for parameters that were not defined in the stylesheet.
1244      *
1245      * @param name The name of the parameter
1246      * @return An object that contains the value assigned to the parameter
1247      */

1248     public final Object getParameter(String name) {
1249         if (_isIdentity) {
1250             return (_parameters != null) ? _parameters.get(name) : null;
1251         }
1252         else {
1253             return _translet.getParameter(name);
1254         }
1255     }
1256 
1257     /**
1258      * Implements JAXP's Transformer.getURIResolver()
1259      * Set the object currently used to resolve URIs used in document().
1260      *
1261      * @return  The URLResolver object currently in use
1262      */

1263     public URIResolver getURIResolver() {
1264         return _uriResolver;
1265     }
1266 
1267     /**
1268      * Implements JAXP's Transformer.setURIResolver()
1269      * Set an object that will be used to resolve URIs used in document().
1270      *
1271      * @param resolver The URIResolver to use in document()
1272      */

1273     public void setURIResolver(URIResolver resolver) {
1274         _uriResolver = resolver;
1275     }
1276 
1277     /**
1278      * This class should only be used as a DOMCache for the translet if the
1279      * URIResolver has been set.
1280      *
1281      * The method implements XSLTC's DOMCache interface, which is used to
1282      * plug in an external document loader into a translet. This method acts
1283      * as an adapter between TrAX's URIResolver interface and XSLTC's
1284      * DOMCache interface. This approach is simple, but removes the
1285      * possibility of using external document caches with XSLTC.
1286      *
1287      * @param baseURI The base URI used by the document call.
1288      * @param href The href argument passed to the document function.
1289      * @param translet A reference to the translet requesting the document
1290      */

1291     public DOM retrieveDocument(String baseURI, String href, Translet translet) {
1292         try {
1293             // Argument to document function was: document('');
1294             if (href.length() == 0) {
1295                 href = baseURI;
1296             }
1297 
1298             /*
1299              *  Fix for bug 24188
1300              *  Incase the _uriResolver.resolve(href,base) is null
1301              *  try to still  retrieve the document before returning null
1302              *  and throwing the FileNotFoundException in
1303              *  com.sun.org.apache.xalan.internal.xsltc.dom.LoadDocument
1304              *
1305              */
1306             Source resolvedSource = _uriResolver.resolve(href, baseURI);
1307             if (resolvedSource == null)  {
1308                 StreamSource streamSource = new StreamSource(
1309                      SystemIDResolver.getAbsoluteURI(href, baseURI));
1310                 return getDOM(streamSource) ;


1313             return getDOM(resolvedSource);
1314         }
1315         catch (TransformerException e) {
1316             if (_errorListener != null)
1317                 postErrorToListener("File not found: " + e.getMessage());
1318             return(null);
1319         }
1320     }
1321 
1322     /**
1323      * Receive notification of a recoverable error.
1324      * The transformer must continue to provide normal parsing events after
1325      * invoking this method. It should still be possible for the application
1326      * to process the document through to the end.
1327      *
1328      * @param e The warning information encapsulated in a transformer
1329      * exception.
1330      * @throws TransformerException if the application chooses to discontinue
1331      * the transformation (always does in our case).
1332      */

1333     public void error(TransformerException e)
1334         throws TransformerException
1335     {
1336         Throwable wrapped = e.getException();
1337         if (wrapped != null) {
1338             System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG,
1339                                             e.getMessageAndLocation(),
1340                                             wrapped.getMessage()));
1341         } else {
1342             System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG,
1343                                             e.getMessageAndLocation()));
1344         }
1345         throw e;
1346     }
1347 
1348     /**
1349      * Receive notification of a non-recoverable error.
1350      * The application must assume that the transformation cannot continue
1351      * after the Transformer has invoked this method, and should continue
1352      * (if at all) only to collect addition error messages. In fact,
1353      * Transformers are free to stop reporting events once this method has
1354      * been invoked.
1355      *
1356      * @param e The warning information encapsulated in a transformer
1357      * exception.
1358      * @throws TransformerException if the application chooses to discontinue
1359      * the transformation (always does in our case).
1360      */

1361     public void fatalError(TransformerException e)
1362         throws TransformerException
1363     {
1364         Throwable wrapped = e.getException();
1365         if (wrapped != null) {
1366             System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG,
1367                                             e.getMessageAndLocation(),
1368                                             wrapped.getMessage()));
1369         } else {
1370             System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG,
1371                                             e.getMessageAndLocation()));
1372         }
1373         throw e;
1374     }
1375 
1376     /**
1377      * Receive notification of a warning.
1378      * Transformers can use this method to report conditions that are not
1379      * errors or fatal errors. The default behaviour is to take no action.
1380      * After invoking this method, the Transformer must continue with the
1381      * transformation. It should still be possible for the application to
1382      * process the document through to the end.
1383      *
1384      * @param e The warning information encapsulated in a transformer
1385      * exception.
1386      * @throws TransformerException if the application chooses to discontinue
1387      * the transformation (never does in our case).
1388      */

1389     public void warning(TransformerException e)
1390         throws TransformerException
1391     {
1392         Throwable wrapped = e.getException();
1393         if (wrapped != null) {
1394             System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG,
1395                                             e.getMessageAndLocation(),
1396                                             wrapped.getMessage()));
1397         } else {
1398             System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG,
1399                                             e.getMessageAndLocation()));
1400         }
1401     }
1402 
1403     /**
1404      * This method resets  the Transformer to its original configuration
1405      * Transformer code is reset to the same state it was when it was
1406      * created
1407      * @since 1.5
1408      */

1409     public void reset() {
1410 
1411         _method = null;
1412         _encoding = null;
1413         _sourceSystemId = null;
1414         _errorListener = this;
1415         _uriResolver = null;
1416         _dom = null;
1417         _parameters = null;
1418         _indentNumber = 0;
1419         setOutputProperties (null);
1420         _tohFactory = null;
1421         _ostream = null;
1422 
1423     }
1424 }


  82 import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;
  83 import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory;
  84 
  85 import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
  86 import com.sun.org.apache.xml.internal.utils.XMLReaderManager;
  87 
  88 import org.xml.sax.ContentHandler;
  89 import org.xml.sax.InputSource;
  90 import org.xml.sax.SAXException;
  91 import org.xml.sax.XMLReader;
  92 import org.xml.sax.ext.LexicalHandler;
  93 
  94 /**
  95  * @author Morten Jorgensen
  96  * @author G. Todd Miller
  97  * @author Santiago Pericas-Geertsen
  98  */
  99 public final class TransformerImpl extends Transformer
 100     implements DOMCache, ErrorListener
 101 {




 102 
 103     private final static String LEXICAL_HANDLER_PROPERTY =
 104         "http://xml.org/sax/properties/lexical-handler";
 105     private static final String NAMESPACE_FEATURE =
 106         "http://xml.org/sax/features/namespaces";
 107 
 108     /**
 109      * Namespace prefixes feature for {@link XMLReader}.
 110      */
 111     private static final String NAMESPACE_PREFIXES_FEATURE =
 112         "http://xml.org/sax/features/namespace-prefixes";
 113 
 114     /**
 115      * A reference to the translet or null if the identity transform.
 116      */
 117     private AbstractTranslet _translet = null;
 118 
 119     /**
 120      * The output method of this transformation.
 121      */


 135      * An error listener for runtime errors.
 136      */
 137     private ErrorListener _errorListener = this;
 138 
 139     /**
 140      * A reference to a URI resolver for calls to document().
 141      */
 142     private URIResolver _uriResolver = null;
 143 
 144     /**
 145      * Output properties of this transformer instance.
 146      */
 147     private Properties _properties, _propertiesClone;
 148 
 149     /**
 150      * A reference to an output handler factory.
 151      */
 152     private TransletOutputHandlerFactory _tohFactory = null;
 153 
 154     /**
 155      * A reference to a internal DOM representation of the input.
 156      */
 157     private DOM _dom = null;
 158 
 159     /**
 160      * Number of indent spaces to add when indentation is on.
 161      */
 162     private int _indentNumber;
 163 
 164     /**
 165      * A reference to the transformer factory that this templates
 166      * object belongs to.
 167      */
 168     private TransformerFactoryImpl _tfactory = null;
 169 
 170     /**
 171      * A reference to the output stream, if we create one in our code.
 172      */
 173     private OutputStream _ostream = null;
 174 
 175     /**


 217     /**
 218      * A hashtable to store parameters for the identity transform. These
 219      * are not needed during the transformation, but we must keep track of
 220      * them to be fully complaint with the JAXP API.
 221      */
 222     private Hashtable _parameters = null;
 223 
 224     /**
 225      * This class wraps an ErrorListener into a MessageHandler in order to
 226      * capture messages reported via xsl:message.
 227      */
 228     static class MessageHandler
 229            extends com.sun.org.apache.xalan.internal.xsltc.runtime.MessageHandler
 230     {
 231         private ErrorListener _errorListener;
 232 
 233         public MessageHandler(ErrorListener errorListener) {
 234             _errorListener = errorListener;
 235         }
 236 
 237         @Override
 238         public void displayMessage(String msg) {
 239             if(_errorListener == null) {
 240                 System.err.println(msg);
 241             }
 242             else {
 243                 try {
 244                     _errorListener.warning(new TransformerException(msg));
 245                 }
 246                 catch (TransformerException e) {
 247                     // ignored
 248                 }
 249             }
 250         }
 251     }
 252 
 253     protected TransformerImpl(Properties outputProperties, int indentNumber,
 254         TransformerFactoryImpl tfactory)
 255     {
 256         this(null, outputProperties, indentNumber, tfactory);
 257         _isIdentity = true;


 303 
 304     /**
 305      * Returns the translet wrapped inside this Transformer or
 306      * null if this is the identity transform.
 307      */
 308     protected AbstractTranslet getTranslet() {
 309         return _translet;
 310     }
 311 
 312     public boolean isIdentity() {
 313         return _isIdentity;
 314     }
 315 
 316     /**
 317      * Implements JAXP's Transformer.transform()
 318      *
 319      * @param source Contains the input XML document
 320      * @param result Will contain the output from the transformation
 321      * @throws TransformerException
 322      */
 323     @Override
 324     public void transform(Source source, Result result)
 325         throws TransformerException
 326     {
 327         if (!_isIdentity) {
 328             if (_translet == null) {
 329                 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_TRANSLET_ERR);
 330                 throw new TransformerException(err.toString());
 331             }
 332             // Pass output properties to the translet
 333             transferOutputProperties(_translet);
 334         }
 335 
 336         final SerializationHandler toHandler = getOutputHandler(result);
 337         if (toHandler == null) {
 338             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
 339             throw new TransformerException(err.toString());
 340         }
 341 
 342         if (_uriResolver != null && !_isIdentity) {
 343             _translet.setDOMCache(this);


 446                     return _tohFactory.getSerializationHandler();
 447                 }
 448 
 449                 // or try to get an OutputStream from Result object
 450                 final OutputStream ostream = target.getOutputStream();
 451                 if (ostream != null) {
 452                     _tohFactory.setOutputStream(ostream);
 453                     return _tohFactory.getSerializationHandler();
 454                 }
 455 
 456                 // or try to get just a systemId string from Result object
 457                 String systemId = result.getSystemId();
 458                 if (systemId == null) {
 459                     ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_RESULT_ERR);
 460                     throw new TransformerException(err.toString());
 461                 }
 462 
 463                 // System Id may be in one of several forms, (1) a uri
 464                 // that starts with 'file:', (2) uri that starts with 'http:'
 465                 // or (3) just a filename on the local system.
 466                 URL url;
 467                 if (systemId.startsWith("file:")) {
 468                     // if StreamResult(File) or setSystemID(File) was used,
 469                     // the systemId will be URI encoded as a result of File.toURI(),
 470                     // it must be decoded for use by URL
 471                     try{
 472                         URI uri = new URI(systemId) ;
 473                         systemId = "file:";
 474 
 475                         String host = uri.getHost(); // decoded String
 476                         String path = uri.getPath(); //decoded String
 477                         if (path == null) {
 478                          path = "";
 479                         }
 480 
 481                         // if host (URI authority) then file:// + host + path
 482                         // else just path (may be absolute or relative)
 483                         if (host != null) {
 484                          systemId += "//" + host + path;
 485                         } else {
 486                          systemId += "//" + path;


 518         }
 519         // If we cannot create the file specified by the SystemId
 520         catch (IOException e) {
 521             throw new TransformerException(e);
 522         }
 523         return null;
 524     }
 525 
 526     /**
 527      * Set the internal DOM that will be used for the next transformation
 528      */
 529     protected void setDOM(DOM dom) {
 530         _dom = dom;
 531     }
 532 
 533     /**
 534      * Builds an internal DOM from a TrAX Source object
 535      */
 536     private DOM getDOM(Source source) throws TransformerException {
 537         try {
 538             DOM dom;
 539 
 540             if (source != null) {
 541                 DTMWSFilter wsfilter;
 542                 if (_translet != null && _translet instanceof StripFilter) {
 543                     wsfilter = new DOMWSFilter(_translet);
 544                  } else {
 545                     wsfilter = null;
 546                  }
 547 
 548                  boolean hasIdCall = (_translet != null) ? _translet.hasIdCall()
 549                                                          : false;
 550 
 551                  if (_dtmManager == null) {
 552                      _dtmManager =
 553                          _tfactory.createNewDTMManagerInstance();

 554                      _dtmManager.setServicesMechnism(_useServicesMechanism);
 555                  }
 556                  dom = (DOM)_dtmManager.getDTM(source, false, wsfilter, true,
 557                                               false, false, 0, hasIdCall);
 558             } else if (_dom != null) {
 559                  dom = _dom;
 560                  _dom = null;  // use only once, so reset to 'null'
 561             } else {
 562                  return null;
 563             }
 564 
 565             if (!_isIdentity) {
 566                 // Give the translet the opportunity to make a prepass of
 567                 // the document, in case it can extract useful information early
 568                 _translet.prepassDocument(dom);
 569             }
 570 
 571             return dom;
 572 
 573         }


 656                 }
 657 
 658                 // Hook up reader and output handler
 659                 try {
 660                     reader.setProperty(LEXICAL_HANDLER_PROPERTY, handler);
 661                     reader.setFeature(NAMESPACE_PREFIXES_FEATURE, true);
 662                 } catch (SAXException e) {
 663                     // Falls through
 664                 }
 665                 reader.setContentHandler(handler);
 666 
 667                 // Start pushing SAX events
 668                 reader.parse(input);
 669             } finally {
 670                 if (!userReader) {
 671                     _readerManager.releaseXMLReader(reader);
 672                 }
 673             }
 674         } else if (source instanceof StAXSource) {
 675             final StAXSource staxSource = (StAXSource)source;
 676             StAXEvent2SAX staxevent2sax;
 677             StAXStream2SAX staxStream2SAX;
 678             if (staxSource.getXMLEventReader() != null) {
 679                 final XMLEventReader xmlEventReader = staxSource.getXMLEventReader();
 680                 staxevent2sax = new StAXEvent2SAX(xmlEventReader);
 681                 staxevent2sax.setContentHandler(handler);
 682                 staxevent2sax.parse();
 683                 handler.flushPending();
 684             } else if (staxSource.getXMLStreamReader() != null) {
 685                 final XMLStreamReader xmlStreamReader = staxSource.getXMLStreamReader();
 686                 staxStream2SAX = new StAXStream2SAX(xmlStreamReader);
 687                 staxStream2SAX.setContentHandler(handler);
 688                 staxStream2SAX.parse();
 689                 handler.flushPending();
 690             }
 691         } else if (source instanceof DOMSource) {
 692             final DOMSource domsrc = (DOMSource) source;
 693             new DOM2TO(domsrc.getNode(), handler).parse();
 694         } else if (source instanceof XSLTCSource) {
 695             final DOM dom = ((XSLTCSource) source).getDOM(null, _translet);
 696             ((SAXImpl)dom).copy(handler);
 697         } else {


 750         } finally {
 751             _dtmManager = null;
 752         }
 753 
 754         // If we create an output stream for the Result, we need to close it after the transformation.
 755         if (_ostream != null) {
 756             try {
 757                 _ostream.close();
 758             }
 759             catch (IOException e) {}
 760             _ostream = null;
 761         }
 762     }
 763 
 764     /**
 765      * Implements JAXP's Transformer.getErrorListener()
 766      * Get the error event handler in effect for the transformation.
 767      *
 768      * @return The error event handler currently in effect
 769      */
 770     @Override
 771     public ErrorListener getErrorListener() {
 772         return _errorListener;
 773     }
 774 
 775     /**
 776      * Implements JAXP's Transformer.setErrorListener()
 777      * Set the error event listener in effect for the transformation.
 778      * Register a message handler in the translet in order to forward
 779      * xsl:messages to error listener.
 780      *
 781      * @param listener The error event listener to use
 782      * @throws IllegalArgumentException
 783      */
 784     @Override
 785     public void setErrorListener(ErrorListener listener)
 786         throws IllegalArgumentException {
 787         if (listener == null) {
 788             ErrorMsg err = new ErrorMsg(ErrorMsg.ERROR_LISTENER_NULL_ERR,
 789                                         "Transformer");
 790             throw new IllegalArgumentException(err.toString());
 791         }
 792         _errorListener = listener;
 793 
 794         // Register a message handler to report xsl:messages
 795     if (_translet != null)
 796         _translet.setMessageHandler(new MessageHandler(_errorListener));
 797     }
 798 
 799     /**
 800      * Inform TrAX error listener of an error
 801      */
 802     private void postErrorToListener(String message) {
 803         try {
 804             _errorListener.error(new TransformerException(message));


 812      * Inform TrAX error listener of a warning
 813      */
 814     private void postWarningToListener(String message) {
 815         try {
 816             _errorListener.warning(new TransformerException(message));
 817         }
 818         catch (TransformerException e) {
 819             // ignored - transformation cannot be continued
 820         }
 821     }
 822 
 823     /**
 824      * The translet stores all CDATA sections set in the <xsl:output> element
 825      * in a Hashtable. This method will re-construct the whitespace separated
 826      * list of elements given in the <xsl:output> element.
 827      */
 828     private String makeCDATAString(Hashtable cdata) {
 829         // Return a 'null' string if no CDATA section elements were specified
 830         if (cdata == null) return null;
 831 
 832         final StringBuilder result = new StringBuilder();
 833 
 834         // Get an enumeration of all the elements in the hashtable
 835         Enumeration elements = cdata.keys();
 836         if (elements.hasMoreElements()) {
 837             result.append((String)elements.nextElement());
 838             while (elements.hasMoreElements()) {
 839                 String element = (String)elements.nextElement();
 840                 result.append(' ');
 841                 result.append(element);
 842             }
 843         }
 844 
 845         return(result.toString());
 846     }
 847 
 848     /**
 849      * Implements JAXP's Transformer.getOutputProperties().
 850      * Returns a copy of the output properties for the transformation. This is
 851      * a set of layered properties. The first layer contains properties set by
 852      * calls to setOutputProperty() and setOutputProperties() on this class,
 853      * and the output settings defined in the stylesheet's <xsl:output>
 854      * element makes up the second level, while the default XSLT output
 855      * settings are returned on the third level.
 856      *
 857      * @return Properties in effect for this Transformer
 858      */
 859     @Override
 860     public Properties getOutputProperties() {
 861         return (Properties) _properties.clone();
 862     }
 863 
 864     /**
 865      * Implements JAXP's Transformer.getOutputProperty().
 866      * Get an output property that is in effect for the transformation. The
 867      * property specified may be a property that was set with setOutputProperty,
 868      * or it may be a property specified in the stylesheet.
 869      *
 870      * @param name A non-null string that contains the name of the property
 871      * @throws IllegalArgumentException if the property name is not known
 872      */
 873     @Override
 874     public String getOutputProperty(String name)
 875         throws IllegalArgumentException
 876     {
 877         if (!validOutputProperty(name)) {
 878             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 879             throw new IllegalArgumentException(err.toString());
 880         }
 881         return _properties.getProperty(name);
 882     }
 883 
 884     /**
 885      * Implements JAXP's Transformer.setOutputProperties().
 886      * Set the output properties for the transformation. These properties
 887      * will override properties set in the Templates with xsl:output.
 888      * Unrecognised properties will be quitely ignored.
 889      *
 890      * @param properties The properties to use for the Transformer
 891      * @throws IllegalArgumentException Never, errors are ignored
 892      */
 893     @Override
 894     public void setOutputProperties(Properties properties)
 895         throws IllegalArgumentException
 896     {
 897         if (properties != null) {
 898             final Enumeration names = properties.propertyNames();
 899 
 900             while (names.hasMoreElements()) {
 901                 final String name = (String) names.nextElement();
 902 
 903                 // Ignore lower layer properties
 904                 if (isDefaultProperty(name, properties)) continue;
 905 
 906                 if (validOutputProperty(name)) {
 907                     _properties.setProperty(name, properties.getProperty(name));
 908                 }
 909                 else {
 910                     ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 911                     throw new IllegalArgumentException(err.toString());
 912                 }
 913             }
 914         }
 915         else {
 916             _properties = _propertiesClone;
 917         }
 918     }
 919 
 920     /**
 921      * Implements JAXP's Transformer.setOutputProperty().
 922      * Get an output property that is in effect for the transformation. The
 923      * property specified may be a property that was set with
 924      * setOutputProperty(), or it may be a property specified in the stylesheet.
 925      *
 926      * @param name The name of the property to set
 927      * @param value The value to assign to the property
 928      * @throws IllegalArgumentException Never, errors are ignored
 929      */
 930     @Override
 931     public void setOutputProperty(String name, String value)
 932         throws IllegalArgumentException
 933     {
 934         if (!validOutputProperty(name)) {
 935             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 936             throw new IllegalArgumentException(err.toString());
 937         }
 938         _properties.setProperty(name, value);
 939     }
 940 
 941     /**
 942      * Internal method to pass any properties to the translet prior to
 943      * initiating the transformation
 944      */
 945     private void transferOutputProperties(AbstractTranslet translet)
 946     {
 947         // Return right now if no properties are set
 948         if (_properties == null) return;
 949 
 950         // Get a list of all the defined properties


1191                 name.equals(OutputPropertiesFactory.ORACLE_IS_STANDALONE) ||
1192                 name.charAt(0) == '{');
1193     }
1194 
1195     /**
1196      * Checks if a given output property is default (2nd layer only)
1197      */
1198     private boolean isDefaultProperty(String name, Properties properties) {
1199         return (properties.get(name) == null);
1200     }
1201 
1202     /**
1203      * Implements JAXP's Transformer.setParameter()
1204      * Add a parameter for the transformation. The parameter is simply passed
1205      * on to the translet - no validation is performed - so any unused
1206      * parameters are quitely ignored by the translet.
1207      *
1208      * @param name The name of the parameter
1209      * @param value The value to assign to the parameter
1210      */
1211     @Override
1212     public void setParameter(String name, Object value) {
1213 
1214         if (value == null) {
1215             ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_SET_PARAM_VALUE, name);
1216             throw new IllegalArgumentException(err.toString());
1217         }
1218 
1219         if (_isIdentity) {
1220             if (_parameters == null) {
1221                 _parameters = new Hashtable();
1222             }
1223             _parameters.put(name, value);
1224         }
1225         else {
1226             _translet.addParameter(name, value);
1227         }
1228     }
1229 
1230     /**
1231      * Implements JAXP's Transformer.clearParameters()
1232      * Clear all parameters set with setParameter. Clears the translet's
1233      * parameter stack.
1234      */
1235     @Override
1236     public void clearParameters() {
1237         if (_isIdentity && _parameters != null) {
1238             _parameters.clear();
1239         }
1240         else {
1241             _translet.clearParameters();
1242         }
1243     }
1244 
1245     /**
1246      * Implements JAXP's Transformer.getParameter()
1247      * Returns the value of a given parameter. Note that the translet will not
1248      * keep values for parameters that were not defined in the stylesheet.
1249      *
1250      * @param name The name of the parameter
1251      * @return An object that contains the value assigned to the parameter
1252      */
1253     @Override
1254     public final Object getParameter(String name) {
1255         if (_isIdentity) {
1256             return (_parameters != null) ? _parameters.get(name) : null;
1257         }
1258         else {
1259             return _translet.getParameter(name);
1260         }
1261     }
1262 
1263     /**
1264      * Implements JAXP's Transformer.getURIResolver()
1265      * Set the object currently used to resolve URIs used in document().
1266      *
1267      * @return  The URLResolver object currently in use
1268      */
1269     @Override
1270     public URIResolver getURIResolver() {
1271         return _uriResolver;
1272     }
1273 
1274     /**
1275      * Implements JAXP's Transformer.setURIResolver()
1276      * Set an object that will be used to resolve URIs used in document().
1277      *
1278      * @param resolver The URIResolver to use in document()
1279      */
1280     @Override
1281     public void setURIResolver(URIResolver resolver) {
1282         _uriResolver = resolver;
1283     }
1284 
1285     /**
1286      * This class should only be used as a DOMCache for the translet if the
1287      * URIResolver has been set.
1288      *
1289      * The method implements XSLTC's DOMCache interface, which is used to
1290      * plug in an external document loader into a translet. This method acts
1291      * as an adapter between TrAX's URIResolver interface and XSLTC's
1292      * DOMCache interface. This approach is simple, but removes the
1293      * possibility of using external document caches with XSLTC.
1294      *
1295      * @param baseURI The base URI used by the document call.
1296      * @param href The href argument passed to the document function.
1297      * @param translet A reference to the translet requesting the document
1298      */
1299     @Override
1300     public DOM retrieveDocument(String baseURI, String href, Translet translet) {
1301         try {
1302             // Argument to document function was: document('');
1303             if (href.length() == 0) {
1304                 href = baseURI;
1305             }
1306 
1307             /*
1308              *  Fix for bug 24188
1309              *  Incase the _uriResolver.resolve(href,base) is null
1310              *  try to still  retrieve the document before returning null
1311              *  and throwing the FileNotFoundException in
1312              *  com.sun.org.apache.xalan.internal.xsltc.dom.LoadDocument
1313              *
1314              */
1315             Source resolvedSource = _uriResolver.resolve(href, baseURI);
1316             if (resolvedSource == null)  {
1317                 StreamSource streamSource = new StreamSource(
1318                      SystemIDResolver.getAbsoluteURI(href, baseURI));
1319                 return getDOM(streamSource) ;


1322             return getDOM(resolvedSource);
1323         }
1324         catch (TransformerException e) {
1325             if (_errorListener != null)
1326                 postErrorToListener("File not found: " + e.getMessage());
1327             return(null);
1328         }
1329     }
1330 
1331     /**
1332      * Receive notification of a recoverable error.
1333      * The transformer must continue to provide normal parsing events after
1334      * invoking this method. It should still be possible for the application
1335      * to process the document through to the end.
1336      *
1337      * @param e The warning information encapsulated in a transformer
1338      * exception.
1339      * @throws TransformerException if the application chooses to discontinue
1340      * the transformation (always does in our case).
1341      */
1342     @Override
1343     public void error(TransformerException e)
1344         throws TransformerException
1345     {
1346         Throwable wrapped = e.getException();
1347         if (wrapped != null) {
1348             System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG,
1349                                             e.getMessageAndLocation(),
1350                                             wrapped.getMessage()));
1351         } else {
1352             System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG,
1353                                             e.getMessageAndLocation()));
1354         }
1355         throw e;
1356     }
1357 
1358     /**
1359      * Receive notification of a non-recoverable error.
1360      * The application must assume that the transformation cannot continue
1361      * after the Transformer has invoked this method, and should continue
1362      * (if at all) only to collect addition error messages. In fact,
1363      * Transformers are free to stop reporting events once this method has
1364      * been invoked.
1365      *
1366      * @param e The warning information encapsulated in a transformer
1367      * exception.
1368      * @throws TransformerException if the application chooses to discontinue
1369      * the transformation (always does in our case).
1370      */
1371     @Override
1372     public void fatalError(TransformerException e)
1373         throws TransformerException
1374     {
1375         Throwable wrapped = e.getException();
1376         if (wrapped != null) {
1377             System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG,
1378                                             e.getMessageAndLocation(),
1379                                             wrapped.getMessage()));
1380         } else {
1381             System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG,
1382                                             e.getMessageAndLocation()));
1383         }
1384         throw e;
1385     }
1386 
1387     /**
1388      * Receive notification of a warning.
1389      * Transformers can use this method to report conditions that are not
1390      * errors or fatal errors. The default behaviour is to take no action.
1391      * After invoking this method, the Transformer must continue with the
1392      * transformation. It should still be possible for the application to
1393      * process the document through to the end.
1394      *
1395      * @param e The warning information encapsulated in a transformer
1396      * exception.
1397      * @throws TransformerException if the application chooses to discontinue
1398      * the transformation (never does in our case).
1399      */
1400     @Override
1401     public void warning(TransformerException e)
1402         throws TransformerException
1403     {
1404         Throwable wrapped = e.getException();
1405         if (wrapped != null) {
1406             System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG,
1407                                             e.getMessageAndLocation(),
1408                                             wrapped.getMessage()));
1409         } else {
1410             System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG,
1411                                             e.getMessageAndLocation()));
1412         }
1413     }
1414 
1415     /**
1416      * This method resets  the Transformer to its original configuration
1417      * Transformer code is reset to the same state it was when it was
1418      * created
1419      * @since 1.5
1420      */
1421     @Override
1422     public void reset() {
1423 
1424         _method = null;
1425         _encoding = null;
1426         _sourceSystemId = null;
1427         _errorListener = this;
1428         _uriResolver = null;
1429         _dom = null;
1430         _parameters = null;
1431         _indentNumber = 0;
1432         setOutputProperties (null);
1433         _tohFactory = null;
1434         _ostream = null;
1435 
1436     }
1437 }