1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 */ 22 /* 23 * $Id: TransformerImpl.java,v 1.10 2007/06/13 01:57:09 joehw Exp $ 24 */ 25 26 package com.sun.org.apache.xalan.internal.xsltc.trax; 27 28 import com.sun.org.apache.xalan.internal.XalanConstants; 29 import com.sun.org.apache.xalan.internal.utils.FactoryImpl; 30 import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; 31 import java.io.File; 32 import java.io.FileOutputStream; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.io.OutputStream; 36 import java.io.Reader; 37 import java.io.Writer; 38 import java.net.URI; 39 import java.net.URL; 40 import java.net.URLConnection; 41 import java.net.UnknownServiceException; 42 import java.util.Enumeration; 43 import java.util.Properties; 44 import java.util.StringTokenizer; 45 import java.util.ArrayList; 46 import java.lang.reflect.Constructor; 47 48 import javax.xml.parsers.DocumentBuilder; 49 import javax.xml.parsers.DocumentBuilderFactory; 50 import javax.xml.parsers.ParserConfigurationException; 51 import javax.xml.stream.XMLEventReader; 52 import javax.xml.stream.XMLStreamReader; 53 import javax.xml.transform.ErrorListener; 54 import javax.xml.transform.OutputKeys; 55 import javax.xml.transform.Result; 56 import javax.xml.transform.Source; 57 import javax.xml.transform.Transformer; 58 import javax.xml.transform.TransformerException; 59 import javax.xml.transform.URIResolver; 60 import javax.xml.transform.dom.DOMResult; 61 import javax.xml.transform.dom.DOMSource; 62 import javax.xml.transform.sax.SAXResult; 63 import javax.xml.transform.sax.SAXSource; 64 import javax.xml.transform.stax.StAXResult; 65 import javax.xml.transform.stax.StAXSource; 66 import javax.xml.transform.stream.StreamResult; 67 import javax.xml.transform.stream.StreamSource; 68 import javax.xml.XMLConstants; 69 70 import com.sun.org.apache.xml.internal.utils.SystemIDResolver; 71 72 import com.sun.org.apache.xalan.internal.xsltc.DOM; 73 import com.sun.org.apache.xalan.internal.xsltc.DOMCache; 74 import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM; 75 import com.sun.org.apache.xalan.internal.xsltc.StripFilter; 76 import com.sun.org.apache.xalan.internal.xsltc.Translet; 77 import com.sun.org.apache.xalan.internal.xsltc.TransletException; 78 import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory; 79 import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 80 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 81 import com.sun.org.apache.xalan.internal.xsltc.dom.DOMWSFilter; 82 import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl; 83 import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager; 84 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 85 import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable; 86 import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory; 87 88 import com.sun.org.apache.xml.internal.dtm.DTMWSFilter; 89 import com.sun.org.apache.xml.internal.utils.XMLReaderManager; 90 91 import org.xml.sax.ContentHandler; 92 import org.xml.sax.InputSource; 93 import org.xml.sax.SAXException; 94 import org.xml.sax.XMLReader; 95 import org.xml.sax.ext.LexicalHandler; 96 97 /** 98 * @author Morten Jorgensen 99 * @author G. Todd Miller 100 * @author Santiago Pericas-Geertsen 101 */ 102 public final class TransformerImpl extends Transformer 103 implements DOMCache, ErrorListener 104 { 105 106 private final static String LEXICAL_HANDLER_PROPERTY = 107 "http://xml.org/sax/properties/lexical-handler"; 108 private static final String NAMESPACE_FEATURE = 109 "http://xml.org/sax/features/namespaces"; 110 111 /** 112 * Namespace prefixes feature for {@link XMLReader}. 113 */ 114 private static final String NAMESPACE_PREFIXES_FEATURE = 115 "http://xml.org/sax/features/namespace-prefixes"; 116 117 /** 118 * A reference to the translet or null if the identity transform. 119 */ 120 private AbstractTranslet _translet = null; 121 122 /** 123 * The output method of this transformation. 124 */ 125 private String _method = null; 126 127 /** 128 * The output encoding of this transformation. 129 */ 130 private String _encoding = null; 131 132 /** 133 * The systemId set in input source. 134 */ 135 private String _sourceSystemId = null; 136 137 /** 138 * An error listener for runtime errors. 139 */ 140 private ErrorListener _errorListener = this; 141 142 /** 143 * A reference to a URI resolver for calls to document(). 144 */ 145 private URIResolver _uriResolver = null; 146 147 /** 148 * Output properties of this transformer instance. 149 */ 150 private Properties _properties, _propertiesClone; 151 152 /** 153 * A reference to an output handler factory. 154 */ 155 private TransletOutputHandlerFactory _tohFactory = null; 156 157 /** 158 * A reference to a internal DOM representation of the input. 159 */ 160 private DOM _dom = null; 161 162 /** 163 * Number of indent spaces to add when indentation is on. 164 */ 165 private int _indentNumber; 166 167 /** 168 * A reference to the transformer factory that this templates 169 * object belongs to. 170 */ 171 private TransformerFactoryImpl _tfactory = null; 172 173 /** 174 * A reference to the output stream, if we create one in our code. 175 */ 176 private OutputStream _ostream = null; 177 178 /** 179 * A reference to the XSLTCDTMManager which is used to build the DOM/DTM 180 * for this transformer. 181 */ 182 private XSLTCDTMManager _dtmManager = null; 183 184 /** 185 * A reference to an object that creates and caches XMLReader objects. 186 */ 187 private XMLReaderManager _readerManager; 188 189 /** 190 * A flag indicating whether we use incremental building of the DTM. 191 */ 192 //private boolean _isIncremental = false; 193 194 /** 195 * A flag indicating whether this transformer implements the identity 196 * transform. 197 */ 198 private boolean _isIdentity = false; 199 200 /** 201 * State of the secure processing feature. 202 */ 203 private boolean _isSecureProcessing = false; 204 205 /** 206 * Indicates whether implementation parts should use 207 * service loader (or similar). 208 * Note the default value (false) is the safe option.. 209 */ 210 private boolean _useServicesMechanism; 211 /** 212 * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element. 213 */ 214 private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; 215 /** 216 * protocols allowed for external DTD references in source file and/or stylesheet. 217 */ 218 private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; 219 220 private XMLSecurityManager _securityManager; 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 @Override 242 public void displayMessage(String msg) { 243 if(_errorListener == null) { 244 System.err.println(msg); 245 } 246 else { 247 try { 248 _errorListener.warning(new TransformerException(msg)); 249 } 250 catch (TransformerException e) { 251 // ignored 252 } 253 } 254 } 255 } 256 257 protected TransformerImpl(Properties outputProperties, int indentNumber, 258 TransformerFactoryImpl tfactory) 259 { 260 this(null, outputProperties, indentNumber, tfactory); 261 _isIdentity = true; 262 // _properties.put(OutputKeys.METHOD, "xml"); 263 } 264 265 protected TransformerImpl(Translet translet, Properties outputProperties, 266 int indentNumber, TransformerFactoryImpl tfactory) 267 { 268 _translet = (AbstractTranslet) translet; 269 _properties = createOutputProperties(outputProperties); 270 _propertiesClone = (Properties) _properties.clone(); 271 _indentNumber = indentNumber; 272 _tfactory = tfactory; 273 _useServicesMechanism = _tfactory.useServicesMechnism(); 274 _accessExternalStylesheet = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET); 275 _accessExternalDTD = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD); 276 _securityManager = (XMLSecurityManager)_tfactory.getAttribute(XalanConstants.SECURITY_MANAGER); 277 _readerManager = XMLReaderManager.getInstance(_useServicesMechanism); 278 _readerManager.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); 279 _readerManager.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _isSecureProcessing); 280 _readerManager.setProperty(XalanConstants.SECURITY_MANAGER, _securityManager); 281 //_isIncremental = tfactory._incremental; 282 } 283 284 /** 285 * Return the state of the secure processing feature. 286 */ 287 public boolean isSecureProcessing() { 288 return _isSecureProcessing; 289 } 290 291 /** 292 * Set the state of the secure processing feature. 293 */ 294 public void setSecureProcessing(boolean flag) { 295 _isSecureProcessing = flag; 296 _readerManager.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _isSecureProcessing); 297 } 298 /** 299 * Return the state of the services mechanism feature. 300 */ 301 public boolean useServicesMechnism() { 302 return _useServicesMechanism; 303 } 304 305 /** 306 * Set the state of the services mechanism feature. 307 */ 308 public void setServicesMechnism(boolean flag) { 309 _useServicesMechanism = flag; 310 } 311 312 /** 313 * Returns the translet wrapped inside this Transformer or 314 * null if this is the identity transform. 315 */ 316 protected AbstractTranslet getTranslet() { 317 return _translet; 318 } 319 320 public boolean isIdentity() { 321 return _isIdentity; 322 } 323 324 /** 325 * Implements JAXP's Transformer.transform() 326 * 327 * @param source Contains the input XML document 328 * @param result Will contain the output from the transformation 329 * @throws TransformerException 330 */ 331 @Override 332 public void transform(Source source, Result result) 333 throws TransformerException 334 { 335 if (!_isIdentity) { 336 if (_translet == null) { 337 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_TRANSLET_ERR); 338 throw new TransformerException(err.toString()); 339 } 340 // Pass output properties to the translet 341 transferOutputProperties(_translet); 342 } 343 344 final SerializationHandler toHandler = getOutputHandler(result); 345 if (toHandler == null) { 346 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR); 347 throw new TransformerException(err.toString()); 348 } 349 350 if (_uriResolver != null && !_isIdentity) { 351 _translet.setDOMCache(this); 352 } 353 354 // Pass output properties to handler if identity 355 if (_isIdentity) { 356 transferOutputProperties(toHandler); 357 } 358 359 transform(source, toHandler, _encoding); 360 try{ 361 if (result instanceof DOMResult) { 362 ((DOMResult)result).setNode(_tohFactory.getNode()); 363 } else if (result instanceof StAXResult) { 364 if (((StAXResult) result).getXMLEventWriter() != null) 365 { 366 (_tohFactory.getXMLEventWriter()).flush(); 367 } 368 else if (((StAXResult) result).getXMLStreamWriter() != null) { 369 (_tohFactory.getXMLStreamWriter()).flush(); 370 //result = new StAXResult(_tohFactory.getXMLStreamWriter()); 371 } 372 } 373 } catch (Exception e) { 374 System.out.println("Result writing error"); 375 } 376 } 377 378 /** 379 * Create an output handler for the transformation output based on 380 * the type and contents of the TrAX Result object passed to the 381 * transform() method. 382 */ 383 public SerializationHandler getOutputHandler(Result result) 384 throws TransformerException 385 { 386 // Get output method using get() to ignore defaults 387 _method = (String) _properties.get(OutputKeys.METHOD); 388 389 // Get encoding using getProperty() to use defaults 390 _encoding = (String) _properties.getProperty(OutputKeys.ENCODING); 391 392 _tohFactory = TransletOutputHandlerFactory.newInstance(_useServicesMechanism); 393 _tohFactory.setEncoding(_encoding); 394 if (_method != null) { 395 _tohFactory.setOutputMethod(_method); 396 } 397 398 // Set indentation number in the factory 399 if (_indentNumber >= 0) { 400 _tohFactory.setIndentNumber(_indentNumber); 401 } 402 403 // Return the content handler for this Result object 404 try { 405 // Result object could be SAXResult, DOMResult, or StreamResult 406 if (result instanceof SAXResult) { 407 final SAXResult target = (SAXResult)result; 408 final ContentHandler handler = target.getHandler(); 409 410 _tohFactory.setHandler(handler); 411 412 /** 413 * Fix for bug 24414 414 * If the lexicalHandler is set then we need to get that 415 * for obtaining the lexical information 416 */ 417 LexicalHandler lexicalHandler = target.getLexicalHandler(); 418 419 if (lexicalHandler != null ) { 420 _tohFactory.setLexicalHandler(lexicalHandler); 421 } 422 423 _tohFactory.setOutputType(TransletOutputHandlerFactory.SAX); 424 return _tohFactory.getSerializationHandler(); 425 } 426 else if (result instanceof StAXResult) { 427 if (((StAXResult) result).getXMLEventWriter() != null) 428 _tohFactory.setXMLEventWriter(((StAXResult) result).getXMLEventWriter()); 429 else if (((StAXResult) result).getXMLStreamWriter() != null) 430 _tohFactory.setXMLStreamWriter(((StAXResult) result).getXMLStreamWriter()); 431 _tohFactory.setOutputType(TransletOutputHandlerFactory.STAX); 432 return _tohFactory.getSerializationHandler(); 433 } 434 else if (result instanceof DOMResult) { 435 _tohFactory.setNode(((DOMResult) result).getNode()); 436 _tohFactory.setNextSibling(((DOMResult) result).getNextSibling()); 437 _tohFactory.setOutputType(TransletOutputHandlerFactory.DOM); 438 return _tohFactory.getSerializationHandler(); 439 } 440 else if (result instanceof StreamResult) { 441 // Get StreamResult 442 final StreamResult target = (StreamResult) result; 443 444 // StreamResult may have been created with a java.io.File, 445 // java.io.Writer, java.io.OutputStream or just a String 446 // systemId. 447 448 _tohFactory.setOutputType(TransletOutputHandlerFactory.STREAM); 449 450 // try to get a Writer from Result object 451 final Writer writer = target.getWriter(); 452 if (writer != null) { 453 _tohFactory.setWriter(writer); 454 return _tohFactory.getSerializationHandler(); 455 } 456 457 // or try to get an OutputStream from Result object 458 final OutputStream ostream = target.getOutputStream(); 459 if (ostream != null) { 460 _tohFactory.setOutputStream(ostream); 461 return _tohFactory.getSerializationHandler(); 462 } 463 464 // or try to get just a systemId string from Result object 465 String systemId = result.getSystemId(); 466 if (systemId == null) { 467 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_RESULT_ERR); 468 throw new TransformerException(err.toString()); 469 } 470 471 // System Id may be in one of several forms, (1) a uri 472 // that starts with 'file:', (2) uri that starts with 'http:' 473 // or (3) just a filename on the local system. 474 URL url; 475 if (systemId.startsWith("file:")) { 476 // if StreamResult(File) or setSystemID(File) was used, 477 // the systemId will be URI encoded as a result of File.toURI(), 478 // it must be decoded for use by URL 479 try{ 480 URI uri = new URI(systemId) ; 481 systemId = "file:"; 482 483 String host = uri.getHost(); // decoded String 484 String path = uri.getPath(); //decoded String 485 if (path == null) { 486 path = ""; 487 } 488 489 // if host (URI authority) then file:// + host + path 490 // else just path (may be absolute or relative) 491 if (host != null) { 492 systemId += "//" + host + path; 493 } else { 494 systemId += "//" + path; 495 } 496 } 497 catch (Exception exception) { 498 // URI exception which means nothing can be done so OK to ignore 499 } 500 501 url = new URL(systemId); 502 _ostream = new FileOutputStream(url.getFile()); 503 _tohFactory.setOutputStream(_ostream); 504 return _tohFactory.getSerializationHandler(); 505 } 506 else if (systemId.startsWith("http:")) { 507 url = new URL(systemId); 508 final URLConnection connection = url.openConnection(); 509 _tohFactory.setOutputStream(_ostream = connection.getOutputStream()); 510 return _tohFactory.getSerializationHandler(); 511 } 512 else { 513 // system id is just a filename 514 _tohFactory.setOutputStream( 515 _ostream = new FileOutputStream(new File(systemId))); 516 return _tohFactory.getSerializationHandler(); 517 } 518 } 519 } 520 // If we cannot write to the location specified by the SystemId 521 catch (UnknownServiceException e) { 522 throw new TransformerException(e); 523 } 524 catch (ParserConfigurationException e) { 525 throw new TransformerException(e); 526 } 527 // If we cannot create the file specified by the SystemId 528 catch (IOException e) { 529 throw new TransformerException(e); 530 } 531 return null; 532 } 533 534 /** 535 * Set the internal DOM that will be used for the next transformation 536 */ 537 protected void setDOM(DOM dom) { 538 _dom = dom; 539 } 540 541 /** 542 * Builds an internal DOM from a TrAX Source object 543 */ 544 private DOM getDOM(Source source) throws TransformerException { 545 try { 546 DOM dom; 547 548 if (source != null) { 549 DTMWSFilter wsfilter; 550 if (_translet != null && _translet instanceof StripFilter) { 551 wsfilter = new DOMWSFilter(_translet); 552 } else { 553 wsfilter = null; 554 } 555 556 boolean hasIdCall = (_translet != null) ? _translet.hasIdCall() 557 : false; 558 559 if (_dtmManager == null) { 560 _dtmManager = 561 _tfactory.createNewDTMManagerInstance(); 562 _dtmManager.setServicesMechnism(_useServicesMechanism); 563 } 564 dom = (DOM)_dtmManager.getDTM(source, false, wsfilter, true, 565 false, false, 0, hasIdCall); 566 } else if (_dom != null) { 567 dom = _dom; 568 _dom = null; // use only once, so reset to 'null' 569 } else { 570 return null; 571 } 572 573 if (!_isIdentity) { 574 // Give the translet the opportunity to make a prepass of 575 // the document, in case it can extract useful information early 576 _translet.prepassDocument(dom); 577 } 578 579 return dom; 580 581 } 582 catch (Exception e) { 583 if (_errorListener != null) { 584 postErrorToListener(e.getMessage()); 585 } 586 throw new TransformerException(e); 587 } 588 } 589 590 /** 591 * Returns the {@link com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl} 592 * object that create this <code>Transformer</code>. 593 */ 594 protected TransformerFactoryImpl getTransformerFactory() { 595 return _tfactory; 596 } 597 598 /** 599 * Returns the {@link com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory} 600 * object that create the <code>TransletOutputHandler</code>. 601 */ 602 protected TransletOutputHandlerFactory getTransletOutputHandlerFactory() { 603 return _tohFactory; 604 } 605 606 private void transformIdentity(Source source, SerializationHandler handler) 607 throws Exception 608 { 609 // Get systemId from source 610 if (source != null) { 611 _sourceSystemId = source.getSystemId(); 612 } 613 614 if (source instanceof StreamSource) { 615 final StreamSource stream = (StreamSource) source; 616 final InputStream streamInput = stream.getInputStream(); 617 final Reader streamReader = stream.getReader(); 618 final XMLReader reader = _readerManager.getXMLReader(); 619 620 try { 621 // Hook up reader and output handler 622 try { 623 reader.setProperty(LEXICAL_HANDLER_PROPERTY, handler); 624 reader.setFeature(NAMESPACE_PREFIXES_FEATURE, true); 625 } catch (SAXException e) { 626 // Falls through 627 } 628 reader.setContentHandler(handler); 629 630 // Create input source from source 631 InputSource input; 632 if (streamInput != null) { 633 input = new InputSource(streamInput); 634 input.setSystemId(_sourceSystemId); 635 } 636 else if (streamReader != null) { 637 input = new InputSource(streamReader); 638 input.setSystemId(_sourceSystemId); 639 } 640 else if (_sourceSystemId != null) { 641 input = new InputSource(_sourceSystemId); 642 } 643 else { 644 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_SOURCE_ERR); 645 throw new TransformerException(err.toString()); 646 } 647 648 // Start pushing SAX events 649 reader.parse(input); 650 } finally { 651 _readerManager.releaseXMLReader(reader); 652 } 653 } else if (source instanceof SAXSource) { 654 final SAXSource sax = (SAXSource) source; 655 XMLReader reader = sax.getXMLReader(); 656 final InputSource input = sax.getInputSource(); 657 boolean userReader = true; 658 659 try { 660 // Create a reader if not set by user 661 if (reader == null) { 662 reader = _readerManager.getXMLReader(); 663 userReader = false; 664 } 665 666 // Hook up reader and output handler 667 try { 668 reader.setProperty(LEXICAL_HANDLER_PROPERTY, handler); 669 reader.setFeature(NAMESPACE_PREFIXES_FEATURE, true); 670 } catch (SAXException e) { 671 // Falls through 672 } 673 reader.setContentHandler(handler); 674 675 // Start pushing SAX events 676 reader.parse(input); 677 } finally { 678 if (!userReader) { 679 _readerManager.releaseXMLReader(reader); 680 } 681 } 682 } else if (source instanceof StAXSource) { 683 final StAXSource staxSource = (StAXSource)source; 684 StAXEvent2SAX staxevent2sax; 685 StAXStream2SAX staxStream2SAX; 686 if (staxSource.getXMLEventReader() != null) { 687 final XMLEventReader xmlEventReader = staxSource.getXMLEventReader(); 688 staxevent2sax = new StAXEvent2SAX(xmlEventReader); 689 staxevent2sax.setContentHandler(handler); 690 staxevent2sax.parse(); 691 handler.flushPending(); 692 } else if (staxSource.getXMLStreamReader() != null) { 693 final XMLStreamReader xmlStreamReader = staxSource.getXMLStreamReader(); 694 staxStream2SAX = new StAXStream2SAX(xmlStreamReader); 695 staxStream2SAX.setContentHandler(handler); 696 staxStream2SAX.parse(); 697 handler.flushPending(); 698 } 699 } else if (source instanceof DOMSource) { 700 final DOMSource domsrc = (DOMSource) source; 701 new DOM2TO(domsrc.getNode(), handler).parse(); 702 } else if (source instanceof XSLTCSource) { 703 final DOM dom = ((XSLTCSource) source).getDOM(null, _translet); 704 ((SAXImpl)dom).copy(handler); 705 } else { 706 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_SOURCE_ERR); 707 throw new TransformerException(err.toString()); 708 } 709 } 710 711 /** 712 * Internal transformation method - uses the internal APIs of XSLTC 713 */ 714 private void transform(Source source, SerializationHandler handler, 715 String encoding) throws TransformerException 716 { 717 try { 718 /* 719 * According to JAXP1.2, new SAXSource()/StreamSource() 720 * should create an empty input tree, with a default root node. 721 * new DOMSource()creates an empty document using DocumentBuilder. 722 * newDocument(); Use DocumentBuilder.newDocument() for all 3 723 * situations, since there is no clear spec. how to create 724 * an empty tree when both SAXSource() and StreamSource() are used. 725 */ 726 if ((source instanceof StreamSource && source.getSystemId()==null 727 && ((StreamSource)source).getInputStream()==null && 728 ((StreamSource)source).getReader()==null)|| 729 (source instanceof SAXSource && 730 ((SAXSource)source).getInputSource()==null && 731 ((SAXSource)source).getXMLReader()==null )|| 732 (source instanceof DOMSource && 733 ((DOMSource)source).getNode()==null)){ 734 DocumentBuilderFactory builderF = FactoryImpl.getDOMFactory(_useServicesMechanism); 735 DocumentBuilder builder = builderF.newDocumentBuilder(); 736 String systemID = source.getSystemId(); 737 source = new DOMSource(builder.newDocument()); 738 739 // Copy system ID from original, empty Source to new 740 if (systemID != null) { 741 source.setSystemId(systemID); 742 } 743 } 744 if (_isIdentity) { 745 transformIdentity(source, handler); 746 } else { 747 _translet.transform(getDOM(source), handler); 748 } 749 } catch (TransletException e) { 750 if (_errorListener != null) postErrorToListener(e.getMessage()); 751 throw new TransformerException(e); 752 } catch (RuntimeException e) { 753 if (_errorListener != null) postErrorToListener(e.getMessage()); 754 throw new TransformerException(e); 755 } catch (Exception e) { 756 if (_errorListener != null) postErrorToListener(e.getMessage()); 757 throw new TransformerException(e); 758 } finally { 759 _dtmManager = null; 760 } 761 762 // If we create an output stream for the Result, we need to close it after the transformation. 763 if (_ostream != null) { 764 try { 765 _ostream.close(); 766 } 767 catch (IOException e) {} 768 _ostream = null; 769 } 770 } 771 772 /** 773 * Implements JAXP's Transformer.getErrorListener() 774 * Get the error event handler in effect for the transformation. 775 * 776 * @return The error event handler currently in effect 777 */ 778 @Override 779 public ErrorListener getErrorListener() { 780 return _errorListener; 781 } 782 783 /** 784 * Implements JAXP's Transformer.setErrorListener() 785 * Set the error event listener in effect for the transformation. 786 * Register a message handler in the translet in order to forward 787 * xsl:messages to error listener. 788 * 789 * @param listener The error event listener to use 790 * @throws IllegalArgumentException 791 */ 792 @Override 793 public void setErrorListener(ErrorListener listener) 794 throws IllegalArgumentException { 795 if (listener == null) { 796 ErrorMsg err = new ErrorMsg(ErrorMsg.ERROR_LISTENER_NULL_ERR, 797 "Transformer"); 798 throw new IllegalArgumentException(err.toString()); 799 } 800 _errorListener = listener; 801 802 // Register a message handler to report xsl:messages 803 if (_translet != null) 804 _translet.setMessageHandler(new MessageHandler(_errorListener)); 805 } 806 807 /** 808 * Inform TrAX error listener of an error 809 */ 810 private void postErrorToListener(String message) { 811 try { 812 _errorListener.error(new TransformerException(message)); 813 } 814 catch (TransformerException e) { 815 // ignored - transformation cannot be continued 816 } 817 } 818 819 /** 820 * Inform TrAX error listener of a warning 821 */ 822 private void postWarningToListener(String message) { 823 try { 824 _errorListener.warning(new TransformerException(message)); 825 } 826 catch (TransformerException e) { 827 // ignored - transformation cannot be continued 828 } 829 } 830 831 /** 832 * The translet stores all CDATA sections set in the <xsl:output> element 833 * in a Hashtable. This method will re-construct the whitespace separated 834 * list of elements given in the <xsl:output> element. 835 */ 836 private String makeCDATAString(Hashtable cdata) { 837 // Return a 'null' string if no CDATA section elements were specified 838 if (cdata == null) return null; 839 840 final StringBuilder result = new StringBuilder(); 841 842 // Get an enumeration of all the elements in the hashtable 843 Enumeration elements = cdata.keys(); 844 if (elements.hasMoreElements()) { 845 result.append((String)elements.nextElement()); 846 while (elements.hasMoreElements()) { 847 String element = (String)elements.nextElement(); 848 result.append(' '); 849 result.append(element); 850 } 851 } 852 853 return(result.toString()); 854 } 855 856 /** 857 * Implements JAXP's Transformer.getOutputProperties(). 858 * Returns a copy of the output properties for the transformation. This is 859 * a set of layered properties. The first layer contains properties set by 860 * calls to setOutputProperty() and setOutputProperties() on this class, 861 * and the output settings defined in the stylesheet's <xsl:output> 862 * element makes up the second level, while the default XSLT output 863 * settings are returned on the third level. 864 * 865 * @return Properties in effect for this Transformer 866 */ 867 @Override 868 public Properties getOutputProperties() { 869 return (Properties) _properties.clone(); 870 } 871 872 /** 873 * Implements JAXP's Transformer.getOutputProperty(). 874 * Get an output property that is in effect for the transformation. The 875 * property specified may be a property that was set with setOutputProperty, 876 * or it may be a property specified in the stylesheet. 877 * 878 * @param name A non-null string that contains the name of the property 879 * @throws IllegalArgumentException if the property name is not known 880 */ 881 @Override 882 public String getOutputProperty(String name) 883 throws IllegalArgumentException 884 { 885 if (!validOutputProperty(name)) { 886 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name); 887 throw new IllegalArgumentException(err.toString()); 888 } 889 return _properties.getProperty(name); 890 } 891 892 /** 893 * Implements JAXP's Transformer.setOutputProperties(). 894 * Set the output properties for the transformation. These properties 895 * will override properties set in the Templates with xsl:output. 896 * Unrecognised properties will be quitely ignored. 897 * 898 * @param properties The properties to use for the Transformer 899 * @throws IllegalArgumentException Never, errors are ignored 900 */ 901 @Override 902 public void setOutputProperties(Properties properties) 903 throws IllegalArgumentException 904 { 905 if (properties != null) { 906 final Enumeration names = properties.propertyNames(); 907 908 while (names.hasMoreElements()) { 909 final String name = (String) names.nextElement(); 910 911 // Ignore lower layer properties 912 if (isDefaultProperty(name, properties)) continue; 913 914 if (validOutputProperty(name)) { 915 _properties.setProperty(name, properties.getProperty(name)); 916 } 917 else { 918 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name); 919 throw new IllegalArgumentException(err.toString()); 920 } 921 } 922 } 923 else { 924 _properties = _propertiesClone; 925 } 926 } 927 928 /** 929 * Implements JAXP's Transformer.setOutputProperty(). 930 * Get an output property that is in effect for the transformation. The 931 * property specified may be a property that was set with 932 * setOutputProperty(), or it may be a property specified in the stylesheet. 933 * 934 * @param name The name of the property to set 935 * @param value The value to assign to the property 936 * @throws IllegalArgumentException Never, errors are ignored 937 */ 938 @Override 939 public void setOutputProperty(String name, String value) 940 throws IllegalArgumentException 941 { 942 if (!validOutputProperty(name)) { 943 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name); 944 throw new IllegalArgumentException(err.toString()); 945 } 946 _properties.setProperty(name, value); 947 } 948 949 /** 950 * Internal method to pass any properties to the translet prior to 951 * initiating the transformation 952 */ 953 private void transferOutputProperties(AbstractTranslet translet) 954 { 955 // Return right now if no properties are set 956 if (_properties == null) return; 957 958 // Get a list of all the defined properties 959 Enumeration names = _properties.propertyNames(); 960 while (names.hasMoreElements()) { 961 // Note the use of get() instead of getProperty() 962 String name = (String) names.nextElement(); 963 String value = (String) _properties.get(name); 964 965 // Ignore default properties 966 if (value == null) continue; 967 968 // Pass property value to translet - override previous setting 969 if (name.equals(OutputKeys.ENCODING)) { 970 translet._encoding = value; 971 } 972 else if (name.equals(OutputKeys.METHOD)) { 973 translet._method = value; 974 } 975 else if (name.equals(OutputKeys.DOCTYPE_PUBLIC)) { 976 translet._doctypePublic = value; 977 } 978 else if (name.equals(OutputKeys.DOCTYPE_SYSTEM)) { 979 translet._doctypeSystem = value; 980 } 981 else if (name.equals(OutputKeys.MEDIA_TYPE)) { 982 translet._mediaType = value; 983 } 984 else if (name.equals(OutputKeys.STANDALONE)) { 985 translet._standalone = value; 986 } 987 else if (name.equals(OutputKeys.VERSION)) { 988 translet._version = value; 989 } 990 else if (name.equals(OutputKeys.OMIT_XML_DECLARATION)) { 991 translet._omitHeader = 992 (value != null && value.toLowerCase().equals("yes")); 993 } 994 else if (name.equals(OutputKeys.INDENT)) { 995 translet._indent = 996 (value != null && value.toLowerCase().equals("yes")); 997 } 998 else if (name.equals(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL +"indent-amount")) { 999 if (value != null) { 1000 translet._indentamount = Integer.parseInt(value); 1001 } 1002 } 1003 else if (name.equals(OutputPropertiesFactory.S_BUILTIN_EXTENSIONS_UNIVERSAL +"indent-amount")) { 1004 if (value != null) { 1005 translet._indentamount = Integer.parseInt(value); 1006 } 1007 } 1008 else if (name.equals(OutputKeys.CDATA_SECTION_ELEMENTS)) { 1009 if (value != null) { 1010 translet._cdata = null; // clear previous setting 1011 StringTokenizer e = new StringTokenizer(value); 1012 while (e.hasMoreTokens()) { 1013 translet.addCdataElement(e.nextToken()); 1014 } 1015 } 1016 } 1017 else if (name.equals(OutputPropertiesFactory.ORACLE_IS_STANDALONE)) { 1018 if (value != null && value.equals("yes")) { 1019 translet._isStandalone = true; 1020 } 1021 } 1022 } 1023 } 1024 1025 /** 1026 * This method is used to pass any properties to the output handler 1027 * when running the identity transform. 1028 */ 1029 public void transferOutputProperties(SerializationHandler handler) 1030 { 1031 // Return right now if no properties are set 1032 if (_properties == null) return; 1033 1034 String doctypePublic = null; 1035 String doctypeSystem = null; 1036 1037 // Get a list of all the defined properties 1038 Enumeration names = _properties.propertyNames(); 1039 while (names.hasMoreElements()) { 1040 // Note the use of get() instead of getProperty() 1041 String name = (String) names.nextElement(); 1042 String value = (String) _properties.get(name); 1043 1044 // Ignore default properties 1045 if (value == null) continue; 1046 1047 // Pass property value to translet - override previous setting 1048 if (name.equals(OutputKeys.DOCTYPE_PUBLIC)) { 1049 doctypePublic = value; 1050 } 1051 else if (name.equals(OutputKeys.DOCTYPE_SYSTEM)) { 1052 doctypeSystem = value; 1053 } 1054 else if (name.equals(OutputKeys.MEDIA_TYPE)) { 1055 handler.setMediaType(value); 1056 } 1057 else if (name.equals(OutputKeys.STANDALONE)) { 1058 handler.setStandalone(value); 1059 } 1060 else if (name.equals(OutputKeys.VERSION)) { 1061 handler.setVersion(value); 1062 } 1063 else if (name.equals(OutputKeys.OMIT_XML_DECLARATION)) { 1064 handler.setOmitXMLDeclaration( 1065 value != null && value.toLowerCase().equals("yes")); 1066 } 1067 else if (name.equals(OutputKeys.INDENT)) { 1068 handler.setIndent( 1069 value != null && value.toLowerCase().equals("yes")); 1070 } 1071 else if (name.equals(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL +"indent-amount")) { 1072 if (value != null) { 1073 handler.setIndentAmount(Integer.parseInt(value)); 1074 } 1075 } 1076 else if (name.equals(OutputPropertiesFactory.S_BUILTIN_EXTENSIONS_UNIVERSAL +"indent-amount")) { 1077 if (value != null) { 1078 handler.setIndentAmount(Integer.parseInt(value)); 1079 } 1080 } 1081 else if (name.equals(OutputPropertiesFactory.ORACLE_IS_STANDALONE)) { 1082 if (value != null && value.equals("yes")) { 1083 handler.setIsStandalone(true); 1084 } 1085 } 1086 else if (name.equals(OutputKeys.CDATA_SECTION_ELEMENTS)) { 1087 if (value != null) { 1088 StringTokenizer e = new StringTokenizer(value); 1089 ArrayList<String> uriAndLocalNames = null; 1090 while (e.hasMoreTokens()) { 1091 final String token = e.nextToken(); 1092 1093 // look for the last colon, as the String may be 1094 // something like "http://abc.com:local" 1095 int lastcolon = token.lastIndexOf(':'); 1096 String uri; 1097 String localName; 1098 if (lastcolon > 0) { 1099 uri = token.substring(0, lastcolon); 1100 localName = token.substring(lastcolon+1); 1101 } else { 1102 // no colon at all, lets hope this is the 1103 // local name itself then 1104 uri = null; 1105 localName = token; 1106 } 1107 1108 if (uriAndLocalNames == null) { 1109 uriAndLocalNames = new ArrayList<>(); 1110 } 1111 // add the uri/localName as a pair, in that order 1112 uriAndLocalNames.add(uri); 1113 uriAndLocalNames.add(localName); 1114 } 1115 handler.setCdataSectionElements(uriAndLocalNames); 1116 } 1117 } 1118 } 1119 1120 // Call setDoctype() if needed 1121 if (doctypePublic != null || doctypeSystem != null) { 1122 handler.setDoctype(doctypeSystem, doctypePublic); 1123 } 1124 } 1125 1126 /** 1127 * Internal method to create the initial set of properties. There 1128 * are two layers of properties: the default layer and the base layer. 1129 * The latter contains properties defined in the stylesheet or by 1130 * the user using this API. 1131 */ 1132 private Properties createOutputProperties(Properties outputProperties) { 1133 final Properties defaults = new Properties(); 1134 setDefaults(defaults, "xml"); 1135 1136 // Copy propeties set in stylesheet to base 1137 final Properties base = new Properties(defaults); 1138 if (outputProperties != null) { 1139 final Enumeration names = outputProperties.propertyNames(); 1140 while (names.hasMoreElements()) { 1141 final String name = (String) names.nextElement(); 1142 base.setProperty(name, outputProperties.getProperty(name)); 1143 } 1144 } 1145 else { 1146 base.setProperty(OutputKeys.ENCODING, _translet._encoding); 1147 if (_translet._method != null) 1148 base.setProperty(OutputKeys.METHOD, _translet._method); 1149 } 1150 1151 // Update defaults based on output method 1152 final String method = base.getProperty(OutputKeys.METHOD); 1153 if (method != null) { 1154 if (method.equals("html")) { 1155 setDefaults(defaults,"html"); 1156 } 1157 else if (method.equals("text")) { 1158 setDefaults(defaults,"text"); 1159 } 1160 } 1161 1162 return base; 1163 } 1164 1165 /** 1166 * Internal method to get the default properties from the 1167 * serializer factory and set them on the property object. 1168 * @param props a java.util.Property object on which the properties are set. 1169 * @param method The output method type, one of "xml", "text", "html" ... 1170 */ 1171 private void setDefaults(Properties props, String method) 1172 { 1173 final Properties method_props = 1174 OutputPropertiesFactory.getDefaultMethodProperties(method); 1175 { 1176 final Enumeration names = method_props.propertyNames(); 1177 while (names.hasMoreElements()) 1178 { 1179 final String name = (String)names.nextElement(); 1180 props.setProperty(name, method_props.getProperty(name)); 1181 } 1182 } 1183 } 1184 /** 1185 * Verifies if a given output property name is a property defined in 1186 * the JAXP 1.1 / TrAX spec 1187 */ 1188 private boolean validOutputProperty(String name) { 1189 return (name.equals(OutputKeys.ENCODING) || 1190 name.equals(OutputKeys.METHOD) || 1191 name.equals(OutputKeys.INDENT) || 1192 name.equals(OutputKeys.DOCTYPE_PUBLIC) || 1193 name.equals(OutputKeys.DOCTYPE_SYSTEM) || 1194 name.equals(OutputKeys.CDATA_SECTION_ELEMENTS) || 1195 name.equals(OutputKeys.MEDIA_TYPE) || 1196 name.equals(OutputKeys.OMIT_XML_DECLARATION) || 1197 name.equals(OutputKeys.STANDALONE) || 1198 name.equals(OutputKeys.VERSION) || 1199 name.equals(OutputPropertiesFactory.ORACLE_IS_STANDALONE) || 1200 name.charAt(0) == '{'); 1201 } 1202 1203 /** 1204 * Checks if a given output property is default (2nd layer only) 1205 */ 1206 private boolean isDefaultProperty(String name, Properties properties) { 1207 return (properties.get(name) == null); 1208 } 1209 1210 /** 1211 * Implements JAXP's Transformer.setParameter() 1212 * Add a parameter for the transformation. The parameter is simply passed 1213 * on to the translet - no validation is performed - so any unused 1214 * parameters are quitely ignored by the translet. 1215 * 1216 * @param name The name of the parameter 1217 * @param value The value to assign to the parameter 1218 */ 1219 @Override 1220 public void setParameter(String name, Object value) { 1221 1222 if (value == null) { 1223 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_SET_PARAM_VALUE, name); 1224 throw new IllegalArgumentException(err.toString()); 1225 } 1226 1227 if (_isIdentity) { 1228 if (_parameters == null) { 1229 _parameters = new Hashtable(); 1230 } 1231 _parameters.put(name, value); 1232 } 1233 else { 1234 _translet.addParameter(name, value); 1235 } 1236 } 1237 1238 /** 1239 * Implements JAXP's Transformer.clearParameters() 1240 * Clear all parameters set with setParameter. Clears the translet's 1241 * parameter stack. 1242 */ 1243 @Override 1244 public void clearParameters() { 1245 if (_isIdentity && _parameters != null) { 1246 _parameters.clear(); 1247 } 1248 else { 1249 _translet.clearParameters(); 1250 } 1251 } 1252 1253 /** 1254 * Implements JAXP's Transformer.getParameter() 1255 * Returns the value of a given parameter. Note that the translet will not 1256 * keep values for parameters that were not defined in the stylesheet. 1257 * 1258 * @param name The name of the parameter 1259 * @return An object that contains the value assigned to the parameter 1260 */ 1261 @Override 1262 public final Object getParameter(String name) { 1263 if (_isIdentity) { 1264 return (_parameters != null) ? _parameters.get(name) : null; 1265 } 1266 else { 1267 return _translet.getParameter(name); 1268 } 1269 } 1270 1271 /** 1272 * Implements JAXP's Transformer.getURIResolver() 1273 * Set the object currently used to resolve URIs used in document(). 1274 * 1275 * @return The URLResolver object currently in use 1276 */ 1277 @Override 1278 public URIResolver getURIResolver() { 1279 return _uriResolver; 1280 } 1281 1282 /** 1283 * Implements JAXP's Transformer.setURIResolver() 1284 * Set an object that will be used to resolve URIs used in document(). 1285 * 1286 * @param resolver The URIResolver to use in document() 1287 */ 1288 @Override 1289 public void setURIResolver(URIResolver resolver) { 1290 _uriResolver = resolver; 1291 } 1292 1293 /** 1294 * This class should only be used as a DOMCache for the translet if the 1295 * URIResolver has been set. 1296 * 1297 * The method implements XSLTC's DOMCache interface, which is used to 1298 * plug in an external document loader into a translet. This method acts 1299 * as an adapter between TrAX's URIResolver interface and XSLTC's 1300 * DOMCache interface. This approach is simple, but removes the 1301 * possibility of using external document caches with XSLTC. 1302 * 1303 * @param baseURI The base URI used by the document call. 1304 * @param href The href argument passed to the document function. 1305 * @param translet A reference to the translet requesting the document 1306 */ 1307 @Override 1308 public DOM retrieveDocument(String baseURI, String href, Translet translet) { 1309 try { 1310 // Argument to document function was: document(''); 1311 if (href.length() == 0) { 1312 href = baseURI; 1313 } 1314 1315 /* 1316 * Fix for bug 24188 1317 * Incase the _uriResolver.resolve(href,base) is null 1318 * try to still retrieve the document before returning null 1319 * and throwing the FileNotFoundException in 1320 * com.sun.org.apache.xalan.internal.xsltc.dom.LoadDocument 1321 * 1322 */ 1323 Source resolvedSource = _uriResolver.resolve(href, baseURI); 1324 if (resolvedSource == null) { 1325 StreamSource streamSource = new StreamSource( 1326 SystemIDResolver.getAbsoluteURI(href, baseURI)); 1327 return getDOM(streamSource) ; 1328 } 1329 1330 return getDOM(resolvedSource); 1331 } 1332 catch (TransformerException e) { 1333 if (_errorListener != null) 1334 postErrorToListener("File not found: " + e.getMessage()); 1335 return(null); 1336 } 1337 } 1338 1339 /** 1340 * Receive notification of a recoverable error. 1341 * The transformer must continue to provide normal parsing events after 1342 * invoking this method. It should still be possible for the application 1343 * to process the document through to the end. 1344 * 1345 * @param e The warning information encapsulated in a transformer 1346 * exception. 1347 * @throws TransformerException if the application chooses to discontinue 1348 * the transformation (always does in our case). 1349 */ 1350 @Override 1351 public void error(TransformerException e) 1352 throws TransformerException 1353 { 1354 Throwable wrapped = e.getException(); 1355 if (wrapped != null) { 1356 System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG, 1357 e.getMessageAndLocation(), 1358 wrapped.getMessage())); 1359 } else { 1360 System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG, 1361 e.getMessageAndLocation())); 1362 } 1363 throw e; 1364 } 1365 1366 /** 1367 * Receive notification of a non-recoverable error. 1368 * The application must assume that the transformation cannot continue 1369 * after the Transformer has invoked this method, and should continue 1370 * (if at all) only to collect addition error messages. In fact, 1371 * Transformers are free to stop reporting events once this method has 1372 * been invoked. 1373 * 1374 * @param e The warning information encapsulated in a transformer 1375 * exception. 1376 * @throws TransformerException if the application chooses to discontinue 1377 * the transformation (always does in our case). 1378 */ 1379 @Override 1380 public void fatalError(TransformerException e) 1381 throws TransformerException 1382 { 1383 Throwable wrapped = e.getException(); 1384 if (wrapped != null) { 1385 System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG, 1386 e.getMessageAndLocation(), 1387 wrapped.getMessage())); 1388 } else { 1389 System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG, 1390 e.getMessageAndLocation())); 1391 } 1392 throw e; 1393 } 1394 1395 /** 1396 * Receive notification of a warning. 1397 * Transformers can use this method to report conditions that are not 1398 * errors or fatal errors. The default behaviour is to take no action. 1399 * After invoking this method, the Transformer must continue with the 1400 * transformation. It should still be possible for the application to 1401 * process the document through to the end. 1402 * 1403 * @param e The warning information encapsulated in a transformer 1404 * exception. 1405 * @throws TransformerException if the application chooses to discontinue 1406 * the transformation (never does in our case). 1407 */ 1408 @Override 1409 public void warning(TransformerException e) 1410 throws TransformerException 1411 { 1412 Throwable wrapped = e.getException(); 1413 if (wrapped != null) { 1414 System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG, 1415 e.getMessageAndLocation(), 1416 wrapped.getMessage())); 1417 } else { 1418 System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG, 1419 e.getMessageAndLocation())); 1420 } 1421 } 1422 1423 /** 1424 * This method resets the Transformer to its original configuration 1425 * Transformer code is reset to the same state it was when it was 1426 * created 1427 * @since 1.5 1428 */ 1429 @Override 1430 public void reset() { 1431 1432 _method = null; 1433 _encoding = null; 1434 _sourceSystemId = null; 1435 _errorListener = this; 1436 _uriResolver = null; 1437 _dom = null; 1438 _parameters = null; 1439 _indentNumber = 0; 1440 setOutputProperties (null); 1441 _tohFactory = null; 1442 _ostream = null; 1443 1444 } 1445 }