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