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