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: TransformerFactoryImpl.java,v 1.8 2007/04/09 21:30:41 joehw Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.xsltc.trax; 25 26 import java.io.File; 27 import java.io.FileInputStream; 28 import java.io.FileNotFoundException; 29 import java.io.FilenameFilter; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.net.MalformedURLException; 33 import java.net.URL; 34 import java.util.Enumeration; 35 import java.util.Hashtable; 36 import java.util.Properties; 37 import java.util.Vector; 38 import java.util.zip.ZipEntry; 39 import java.util.zip.ZipFile; 40 41 import javax.xml.XMLConstants; 42 import javax.xml.parsers.SAXParserFactory; 43 import javax.xml.parsers.SAXParser; 44 import javax.xml.parsers.ParserConfigurationException; 45 46 import javax.xml.transform.ErrorListener; 47 import javax.xml.transform.Source; 48 import javax.xml.transform.Templates; 49 import javax.xml.transform.Transformer; 50 import javax.xml.transform.TransformerConfigurationException; 51 import javax.xml.transform.TransformerException; 52 import javax.xml.transform.TransformerFactory; 53 import javax.xml.transform.URIResolver; 54 import javax.xml.transform.dom.DOMResult; 55 import javax.xml.transform.dom.DOMSource; 56 import javax.xml.transform.sax.SAXResult; 57 import javax.xml.transform.sax.SAXSource; 58 import javax.xml.transform.sax.SAXTransformerFactory; 59 import javax.xml.transform.sax.TemplatesHandler; 60 import javax.xml.transform.sax.TransformerHandler; 61 import javax.xml.transform.stream.StreamResult; 62 import javax.xml.transform.stream.StreamSource; 63 import javax.xml.transform.stax.*; 64 65 import com.sun.org.apache.xml.internal.utils.StylesheetPIHandler; 66 import com.sun.org.apache.xml.internal.utils.StopParseException; 67 68 import com.sun.org.apache.xalan.internal.XalanConstants; 69 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 70 import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader; 71 import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC; 72 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 73 import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager; 74 import com.sun.org.apache.xalan.internal.utils.ObjectFactory; 75 import com.sun.org.apache.xalan.internal.utils.FactoryImpl; 76 import com.sun.org.apache.xalan.internal.utils.SecuritySupport; 77 78 import org.xml.sax.InputSource; 79 import org.xml.sax.XMLFilter; 80 import org.xml.sax.XMLReader; 81 import org.xml.sax.helpers.XMLReaderFactory; 82 83 /** 84 * Implementation of a JAXP1.1 TransformerFactory for Translets. 85 * @author G. Todd Miller 86 * @author Morten Jorgensen 87 * @author Santiago Pericas-Geertsen 88 */ 89 public class TransformerFactoryImpl 90 extends SAXTransformerFactory implements SourceLoader, ErrorListener 91 { 92 // Public constants for attributes supported by the XSLTC TransformerFactory. 93 public final static String TRANSLET_NAME = "translet-name"; 94 public final static String DESTINATION_DIRECTORY = "destination-directory"; 95 public final static String PACKAGE_NAME = "package-name"; 96 public final static String JAR_NAME = "jar-name"; 97 public final static String GENERATE_TRANSLET = "generate-translet"; 98 public final static String AUTO_TRANSLET = "auto-translet"; 99 public final static String USE_CLASSPATH = "use-classpath"; 100 public final static String DEBUG = "debug"; 101 public final static String ENABLE_INLINING = "enable-inlining"; 102 public final static String INDENT_NUMBER = "indent-number"; 103 104 /** 105 * This error listener is used only for this factory and is not passed to 106 * the Templates or Transformer objects that we create. 107 */ 108 private ErrorListener _errorListener = this; 109 110 /** 111 * This URIResolver is passed to all created Templates and Transformers 112 */ 113 private URIResolver _uriResolver = null; 114 115 /** 116 * As Gregor Samsa awoke one morning from uneasy dreams he found himself 117 * transformed in his bed into a gigantic insect. He was lying on his hard, 118 * as it were armour plated, back, and if he lifted his head a little he 119 * could see his big, brown belly divided into stiff, arched segments, on 120 * top of which the bed quilt could hardly keep in position and was about 121 * to slide off completely. His numerous legs, which were pitifully thin 122 * compared to the rest of his bulk, waved helplessly before his eyes. 123 * "What has happened to me?", he thought. It was no dream.... 124 */ 125 protected final static String DEFAULT_TRANSLET_NAME = "GregorSamsa"; 126 127 /** 128 * The class name of the translet 129 */ 130 private String _transletName = DEFAULT_TRANSLET_NAME; 131 132 /** 133 * The destination directory for the translet 134 */ 135 private String _destinationDirectory = null; 136 137 /** 138 * The package name prefix for all generated translet classes 139 */ 140 private String _packageName = null; 141 142 /** 143 * The jar file name which the translet classes are packaged into 144 */ 145 private String _jarFileName = null; 146 147 /** 148 * This Hashtable is used to store parameters for locating 149 * <?xml-stylesheet ...?> processing instructions in XML docs. 150 */ 151 private Hashtable _piParams = null; 152 153 /** 154 * The above hashtable stores objects of this class. 155 */ 156 private static class PIParamWrapper { 157 public String _media = null; 158 public String _title = null; 159 public String _charset = null; 160 161 public PIParamWrapper(String media, String title, String charset) { 162 _media = media; 163 _title = title; 164 _charset = charset; 165 } 166 } 167 168 /** 169 * Set to <code>true</code> when debugging is enabled. 170 */ 171 private boolean _debug = false; 172 173 /** 174 * Set to <code>true</code> when templates are inlined. 175 */ 176 private boolean _enableInlining = false; 177 178 /** 179 * Set to <code>true</code> when we want to generate 180 * translet classes from the stylesheet. 181 */ 182 private boolean _generateTranslet = false; 183 184 /** 185 * If this is set to <code>true</code>, we attempt to use translet classes 186 * for transformation if possible without compiling the stylesheet. The 187 * translet class is only used if its timestamp is newer than the timestamp 188 * of the stylesheet. 189 */ 190 private boolean _autoTranslet = false; 191 192 /** 193 * If this is set to <code>true</code>, we attempt to load the translet 194 * from the CLASSPATH. 195 */ 196 private boolean _useClasspath = false; 197 198 /** 199 * Number of indent spaces when indentation is turned on. 200 */ 201 private int _indentNumber = -1; 202 203 /** 204 * The provider of the XSLTC DTM Manager service. This is fixed for any 205 * instance of this class. In order to change service providers, a new 206 * XSLTC <code>TransformerFactory</code> must be instantiated. 207 * @see XSLTCDTMManager#getDTMManagerClass() 208 */ 209 private Class m_DTMManagerClass; 210 211 /** 212 * <p>State of secure processing feature.</p> 213 */ 214 private boolean _isNotSecureProcessing = true; 215 /** 216 * <p>State of secure mode.</p> 217 */ 218 private boolean _isSecureMode = false; 219 220 /** 221 * Indicates whether implementation parts should use 222 * service loader (or similar). 223 * Note the default value (false) is the safe option.. 224 */ 225 private boolean _useServicesMechanism; 226 227 /** 228 * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element. 229 */ 230 private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; 231 /** 232 * protocols allowed for external DTD references in source file and/or stylesheet. 233 */ 234 private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; 235 236 237 /** 238 * javax.xml.transform.sax.TransformerFactory implementation. 239 */ 240 public TransformerFactoryImpl() { 241 this(true); 242 } 243 244 public static TransformerFactory newTransformerFactoryNoServiceLoader() { 245 return new TransformerFactoryImpl(false); 246 } 247 248 private TransformerFactoryImpl(boolean useServicesMechanism) { 249 this.m_DTMManagerClass = XSLTCDTMManager.getDTMManagerClass(useServicesMechanism); 250 this._useServicesMechanism = useServicesMechanism; 251 252 String defaultAccess = XalanConstants.EXTERNAL_ACCESS_DEFAULT; 253 if (System.getSecurityManager() != null) { 254 _isSecureMode = true; 255 _isNotSecureProcessing = false; 256 } 257 _accessExternalStylesheet = SecuritySupport.getDefaultAccessProperty( 258 XalanConstants.SP_ACCESS_EXTERNAL_STYLESHEET, defaultAccess); 259 _accessExternalDTD = SecuritySupport.getDefaultAccessProperty( 260 XalanConstants.SP_ACCESS_EXTERNAL_DTD, defaultAccess); 261 } 262 263 /** 264 * javax.xml.transform.sax.TransformerFactory implementation. 265 * Set the error event listener for the TransformerFactory, which is used 266 * for the processing of transformation instructions, and not for the 267 * transformation itself. 268 * 269 * @param listener The error listener to use with the TransformerFactory 270 * @throws IllegalArgumentException 271 */ 272 public void setErrorListener(ErrorListener listener) 273 throws IllegalArgumentException 274 { 275 if (listener == null) { 276 ErrorMsg err = new ErrorMsg(ErrorMsg.ERROR_LISTENER_NULL_ERR, 277 "TransformerFactory"); 278 throw new IllegalArgumentException(err.toString()); 279 } 280 _errorListener = listener; 281 } 282 283 /** 284 * javax.xml.transform.sax.TransformerFactory implementation. 285 * Get the error event handler for the TransformerFactory. 286 * 287 * @return The error listener used with the TransformerFactory 288 */ 289 public ErrorListener getErrorListener() { 290 return _errorListener; 291 } 292 293 /** 294 * javax.xml.transform.sax.TransformerFactory implementation. 295 * Returns the value set for a TransformerFactory attribute 296 * 297 * @param name The attribute name 298 * @return An object representing the attribute value 299 * @throws IllegalArgumentException 300 */ 301 public Object getAttribute(String name) 302 throws IllegalArgumentException 303 { 304 // Return value for attribute 'translet-name' 305 if (name.equals(TRANSLET_NAME)) { 306 return _transletName; 307 } 308 else if (name.equals(GENERATE_TRANSLET)) { 309 return new Boolean(_generateTranslet); 310 } 311 else if (name.equals(AUTO_TRANSLET)) { 312 return new Boolean(_autoTranslet); 313 } 314 else if (name.equals(ENABLE_INLINING)) { 315 if (_enableInlining) 316 return Boolean.TRUE; 317 else 318 return Boolean.FALSE; 319 } 320 else if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { 321 return _accessExternalStylesheet; 322 } 323 else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { 324 return _accessExternalDTD; 325 } 326 327 // Throw an exception for all other attributes 328 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name); 329 throw new IllegalArgumentException(err.toString()); 330 } 331 332 /** 333 * javax.xml.transform.sax.TransformerFactory implementation. 334 * Sets the value for a TransformerFactory attribute. 335 * 336 * @param name The attribute name 337 * @param value An object representing the attribute value 338 * @throws IllegalArgumentException 339 */ 340 public void setAttribute(String name, Object value) 341 throws IllegalArgumentException 342 { 343 // Set the default translet name (ie. class name), which will be used 344 // for translets that cannot be given a name from their system-id. 345 if (name.equals(TRANSLET_NAME) && value instanceof String) { 346 _transletName = (String) value; 347 return; 348 } 349 else if (name.equals(DESTINATION_DIRECTORY) && value instanceof String) { 350 _destinationDirectory = (String) value; 351 return; 352 } 353 else if (name.equals(PACKAGE_NAME) && value instanceof String) { 354 _packageName = (String) value; 355 return; 356 } 357 else if (name.equals(JAR_NAME) && value instanceof String) { 358 _jarFileName = (String) value; 359 return; 360 } 361 else if (name.equals(GENERATE_TRANSLET)) { 362 if (value instanceof Boolean) { 363 _generateTranslet = ((Boolean) value).booleanValue(); 364 return; 365 } 366 else if (value instanceof String) { 367 _generateTranslet = ((String) value).equalsIgnoreCase("true"); 368 return; 369 } 370 } 371 else if (name.equals(AUTO_TRANSLET)) { 372 if (value instanceof Boolean) { 373 _autoTranslet = ((Boolean) value).booleanValue(); 374 return; 375 } 376 else if (value instanceof String) { 377 _autoTranslet = ((String) value).equalsIgnoreCase("true"); 378 return; 379 } 380 } 381 else if (name.equals(USE_CLASSPATH)) { 382 if (value instanceof Boolean) { 383 _useClasspath = ((Boolean) value).booleanValue(); 384 return; 385 } 386 else if (value instanceof String) { 387 _useClasspath = ((String) value).equalsIgnoreCase("true"); 388 return; 389 } 390 } 391 else if (name.equals(DEBUG)) { 392 if (value instanceof Boolean) { 393 _debug = ((Boolean) value).booleanValue(); 394 return; 395 } 396 else if (value instanceof String) { 397 _debug = ((String) value).equalsIgnoreCase("true"); 398 return; 399 } 400 } 401 else if (name.equals(ENABLE_INLINING)) { 402 if (value instanceof Boolean) { 403 _enableInlining = ((Boolean) value).booleanValue(); 404 return; 405 } 406 else if (value instanceof String) { 407 _enableInlining = ((String) value).equalsIgnoreCase("true"); 408 return; 409 } 410 } 411 else if (name.equals(INDENT_NUMBER)) { 412 if (value instanceof String) { 413 try { 414 _indentNumber = Integer.parseInt((String) value); 415 return; 416 } 417 catch (NumberFormatException e) { 418 // Falls through 419 } 420 } 421 else if (value instanceof Integer) { 422 _indentNumber = ((Integer) value).intValue(); 423 return; 424 } 425 } 426 else if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { 427 _accessExternalStylesheet = (String)value; 428 return; 429 } 430 else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { 431 _accessExternalDTD = (String)value; 432 return; 433 } 434 435 // Throw an exception for all other attributes 436 final ErrorMsg err 437 = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name); 438 throw new IllegalArgumentException(err.toString()); 439 } 440 441 /** 442 * <p>Set a feature for this <code>TransformerFactory</code> and <code>Transformer</code>s 443 * or <code>Template</code>s created by this factory.</p> 444 * 445 * <p> 446 * Feature names are fully qualified {@link java.net.URI}s. 447 * Implementations may define their own features. 448 * An {@link TransformerConfigurationException} is thrown if this <code>TransformerFactory</code> or the 449 * <code>Transformer</code>s or <code>Template</code>s it creates cannot support the feature. 450 * It is possible for an <code>TransformerFactory</code> to expose a feature value but be unable to change its state. 451 * </p> 452 * 453 * <p>See {@link javax.xml.transform.TransformerFactory} for full documentation of specific features.</p> 454 * 455 * @param name Feature name. 456 * @param value Is feature state <code>true</code> or <code>false</code>. 457 * 458 * @throws TransformerConfigurationException if this <code>TransformerFactory</code> 459 * or the <code>Transformer</code>s or <code>Template</code>s it creates cannot support this feature. 460 * @throws NullPointerException If the <code>name</code> parameter is null. 461 */ 462 public void setFeature(String name, boolean value) 463 throws TransformerConfigurationException { 464 465 // feature name cannot be null 466 if (name == null) { 467 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_FEATURE_NULL_NAME); 468 throw new NullPointerException(err.toString()); 469 } 470 // secure processing? 471 else if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 472 if ((_isSecureMode) && (!value)) { 473 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SECUREPROCESSING_FEATURE); 474 throw new TransformerConfigurationException(err.toString()); 475 } 476 _isNotSecureProcessing = !value; 477 478 // set restriction, allowing no access to external stylesheet 479 if (value) { 480 _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP; 481 _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT_FSP; 482 } 483 return; 484 } 485 else if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) { 486 //in secure mode, let _useServicesMechanism be determined by the constructor 487 if (!_isSecureMode) 488 _useServicesMechanism = value; 489 } 490 else { 491 // unknown feature 492 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNSUPPORTED_FEATURE, name); 493 throw new TransformerConfigurationException(err.toString()); 494 } 495 } 496 497 /** 498 * javax.xml.transform.sax.TransformerFactory implementation. 499 * Look up the value of a feature (to see if it is supported). 500 * This method must be updated as the various methods and features of this 501 * class are implemented. 502 * 503 * @param name The feature name 504 * @return 'true' if feature is supported, 'false' if not 505 */ 506 public boolean getFeature(String name) { 507 // All supported features should be listed here 508 String[] features = { 509 DOMSource.FEATURE, 510 DOMResult.FEATURE, 511 SAXSource.FEATURE, 512 SAXResult.FEATURE, 513 StAXSource.FEATURE, 514 StAXResult.FEATURE, 515 StreamSource.FEATURE, 516 StreamResult.FEATURE, 517 SAXTransformerFactory.FEATURE, 518 SAXTransformerFactory.FEATURE_XMLFILTER, 519 XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM 520 }; 521 522 // feature name cannot be null 523 if (name == null) { 524 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_GET_FEATURE_NULL_NAME); 525 throw new NullPointerException(err.toString()); 526 } 527 528 // Inefficient, but array is small 529 for (int i =0; i < features.length; i++) { 530 if (name.equals(features[i])) { 531 return true; 532 } 533 } 534 // secure processing? 535 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 536 return !_isNotSecureProcessing; 537 } 538 539 // Feature not supported 540 return false; 541 } 542 /** 543 * Return the state of the services mechanism feature. 544 */ 545 public boolean useServicesMechnism() { 546 return _useServicesMechanism; 547 } 548 549 /** 550 * javax.xml.transform.sax.TransformerFactory implementation. 551 * Get the object that is used by default during the transformation to 552 * resolve URIs used in document(), xsl:import, or xsl:include. 553 * 554 * @return The URLResolver used for this TransformerFactory and all 555 * Templates and Transformer objects created using this factory 556 */ 557 public URIResolver getURIResolver() { 558 return _uriResolver; 559 } 560 561 /** 562 * javax.xml.transform.sax.TransformerFactory implementation. 563 * Set the object that is used by default during the transformation to 564 * resolve URIs used in document(), xsl:import, or xsl:include. Note that 565 * this does not affect Templates and Transformers that are already 566 * created with this factory. 567 * 568 * @param resolver The URLResolver used for this TransformerFactory and all 569 * Templates and Transformer objects created using this factory 570 */ 571 public void setURIResolver(URIResolver resolver) { 572 _uriResolver = resolver; 573 } 574 575 /** 576 * javax.xml.transform.sax.TransformerFactory implementation. 577 * Get the stylesheet specification(s) associated via the xml-stylesheet 578 * processing instruction (see http://www.w3.org/TR/xml-stylesheet/) with 579 * the document document specified in the source parameter, and that match 580 * the given criteria. 581 * 582 * @param source The XML source document. 583 * @param media The media attribute to be matched. May be null, in which 584 * case the prefered templates will be used (i.e. alternate = no). 585 * @param title The value of the title attribute to match. May be null. 586 * @param charset The value of the charset attribute to match. May be null. 587 * @return A Source object suitable for passing to the TransformerFactory. 588 * @throws TransformerConfigurationException 589 */ 590 public Source getAssociatedStylesheet(Source source, String media, 591 String title, String charset) 592 throws TransformerConfigurationException { 593 594 String baseId; 595 XMLReader reader = null; 596 InputSource isource = null; 597 598 599 /** 600 * Fix for bugzilla bug 24187 601 */ 602 StylesheetPIHandler _stylesheetPIHandler = new StylesheetPIHandler(null,media,title,charset); 603 604 try { 605 606 if (source instanceof DOMSource ) { 607 final DOMSource domsrc = (DOMSource) source; 608 baseId = domsrc.getSystemId(); 609 final org.w3c.dom.Node node = domsrc.getNode(); 610 final DOM2SAX dom2sax = new DOM2SAX(node); 611 612 _stylesheetPIHandler.setBaseId(baseId); 613 614 dom2sax.setContentHandler( _stylesheetPIHandler); 615 dom2sax.parse(); 616 } else { 617 isource = SAXSource.sourceToInputSource(source); 618 baseId = isource.getSystemId(); 619 620 SAXParserFactory factory = FactoryImpl.getSAXFactory(_useServicesMechanism); 621 factory.setNamespaceAware(true); 622 623 if (!_isNotSecureProcessing) { 624 try { 625 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); 626 } 627 catch (org.xml.sax.SAXException e) {} 628 } 629 630 SAXParser jaxpParser = factory.newSAXParser(); 631 632 reader = jaxpParser.getXMLReader(); 633 if (reader == null) { 634 reader = XMLReaderFactory.createXMLReader(); 635 } 636 637 _stylesheetPIHandler.setBaseId(baseId); 638 reader.setContentHandler(_stylesheetPIHandler); 639 reader.parse(isource); 640 641 } 642 643 if (_uriResolver != null ) { 644 _stylesheetPIHandler.setURIResolver(_uriResolver); 645 } 646 647 } catch (StopParseException e ) { 648 // startElement encountered so do not parse further 649 650 } catch (javax.xml.parsers.ParserConfigurationException e) { 651 652 throw new TransformerConfigurationException( 653 "getAssociatedStylesheets failed", e); 654 655 } catch (org.xml.sax.SAXException se) { 656 657 throw new TransformerConfigurationException( 658 "getAssociatedStylesheets failed", se); 659 660 661 } catch (IOException ioe ) { 662 throw new TransformerConfigurationException( 663 "getAssociatedStylesheets failed", ioe); 664 665 } 666 667 return _stylesheetPIHandler.getAssociatedStylesheet(); 668 669 } 670 671 /** 672 * javax.xml.transform.sax.TransformerFactory implementation. 673 * Create a Transformer object that copies the input document to the result. 674 * 675 * @return A Transformer object that simply copies the source to the result. 676 * @throws TransformerConfigurationException 677 */ 678 public Transformer newTransformer() 679 throws TransformerConfigurationException 680 { 681 TransformerImpl result = new TransformerImpl(new Properties(), 682 _indentNumber, this); 683 if (_uriResolver != null) { 684 result.setURIResolver(_uriResolver); 685 } 686 687 if (!_isNotSecureProcessing) { 688 result.setSecureProcessing(true); 689 } 690 return result; 691 } 692 693 /** 694 * javax.xml.transform.sax.TransformerFactory implementation. 695 * Process the Source into a Templates object, which is a a compiled 696 * representation of the source. Note that this method should not be 697 * used with XSLTC, as the time-consuming compilation is done for each 698 * and every transformation. 699 * 700 * @return A Templates object that can be used to create Transformers. 701 * @throws TransformerConfigurationException 702 */ 703 public Transformer newTransformer(Source source) throws 704 TransformerConfigurationException 705 { 706 final Templates templates = newTemplates(source); 707 final Transformer transformer = templates.newTransformer(); 708 if (_uriResolver != null) { 709 transformer.setURIResolver(_uriResolver); 710 } 711 return(transformer); 712 } 713 714 /** 715 * Pass warning messages from the compiler to the error listener 716 */ 717 private void passWarningsToListener(Vector messages) 718 throws TransformerException 719 { 720 if (_errorListener == null || messages == null) { 721 return; 722 } 723 // Pass messages to listener, one by one 724 final int count = messages.size(); 725 for (int pos = 0; pos < count; pos++) { 726 ErrorMsg msg = (ErrorMsg)messages.elementAt(pos); 727 // Workaround for the TCK failure ErrorListener.errorTests.error001. 728 if (msg.isWarningError()) 729 _errorListener.error( 730 new TransformerConfigurationException(msg.toString())); 731 else 732 _errorListener.warning( 733 new TransformerConfigurationException(msg.toString())); 734 } 735 } 736 737 /** 738 * Pass error messages from the compiler to the error listener 739 */ 740 private void passErrorsToListener(Vector messages) { 741 try { 742 if (_errorListener == null || messages == null) { 743 return; 744 } 745 // Pass messages to listener, one by one 746 final int count = messages.size(); 747 for (int pos = 0; pos < count; pos++) { 748 String message = messages.elementAt(pos).toString(); 749 _errorListener.error(new TransformerException(message)); 750 } 751 } 752 catch (TransformerException e) { 753 // nada 754 } 755 } 756 757 /** 758 * javax.xml.transform.sax.TransformerFactory implementation. 759 * Process the Source into a Templates object, which is a a compiled 760 * representation of the source. 761 * 762 * @param source The input stylesheet - DOMSource not supported!!! 763 * @return A Templates object that can be used to create Transformers. 764 * @throws TransformerConfigurationException 765 */ 766 public Templates newTemplates(Source source) 767 throws TransformerConfigurationException 768 { 769 // If the _useClasspath attribute is true, try to load the translet from 770 // the CLASSPATH and create a template object using the loaded 771 // translet. 772 if (_useClasspath) { 773 String transletName = getTransletBaseName(source); 774 775 if (_packageName != null) 776 transletName = _packageName + "." + transletName; 777 778 try { 779 final Class clazz = ObjectFactory.findProviderClass(transletName, true); 780 resetTransientAttributes(); 781 782 return new TemplatesImpl(new Class[]{clazz}, transletName, null, _indentNumber, this); 783 } 784 catch (ClassNotFoundException cnfe) { 785 ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, transletName); 786 throw new TransformerConfigurationException(err.toString()); 787 } 788 catch (Exception e) { 789 ErrorMsg err = new ErrorMsg( 790 new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY) 791 + e.getMessage()); 792 throw new TransformerConfigurationException(err.toString()); 793 } 794 } 795 796 // If _autoTranslet is true, we will try to load the bytecodes 797 // from the translet classes without compiling the stylesheet. 798 if (_autoTranslet) { 799 byte[][] bytecodes = null; 800 String transletClassName = getTransletBaseName(source); 801 802 if (_packageName != null) 803 transletClassName = _packageName + "." + transletClassName; 804 805 if (_jarFileName != null) 806 bytecodes = getBytecodesFromJar(source, transletClassName); 807 else 808 bytecodes = getBytecodesFromClasses(source, transletClassName); 809 810 if (bytecodes != null) { 811 if (_debug) { 812 if (_jarFileName != null) 813 System.err.println(new ErrorMsg( 814 ErrorMsg.TRANSFORM_WITH_JAR_STR, transletClassName, _jarFileName)); 815 else 816 System.err.println(new ErrorMsg( 817 ErrorMsg.TRANSFORM_WITH_TRANSLET_STR, transletClassName)); 818 } 819 820 // Reset the per-session attributes to their default values 821 // after each newTemplates() call. 822 resetTransientAttributes(); 823 824 return new TemplatesImpl(bytecodes, transletClassName, null, _indentNumber, this); 825 } 826 } 827 828 // Create and initialize a stylesheet compiler 829 final XSLTC xsltc = new XSLTC(_useServicesMechanism); 830 if (_debug) xsltc.setDebug(true); 831 if (_enableInlining) 832 xsltc.setTemplateInlining(true); 833 else 834 xsltc.setTemplateInlining(false); 835 836 if (!_isNotSecureProcessing) xsltc.setSecureProcessing(true); 837 xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet); 838 xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); 839 xsltc.init(); 840 841 // Set a document loader (for xsl:include/import) if defined 842 if (_uriResolver != null) { 843 xsltc.setSourceLoader(this); 844 } 845 846 // Pass parameters to the Parser to make sure it locates the correct 847 // <?xml-stylesheet ...?> PI in an XML input document 848 if ((_piParams != null) && (_piParams.get(source) != null)) { 849 // Get the parameters for this Source object 850 PIParamWrapper p = (PIParamWrapper)_piParams.get(source); 851 // Pass them on to the compiler (which will pass then to the parser) 852 if (p != null) { 853 xsltc.setPIParameters(p._media, p._title, p._charset); 854 } 855 } 856 857 // Set the attributes for translet generation 858 int outputType = XSLTC.BYTEARRAY_OUTPUT; 859 if (_generateTranslet || _autoTranslet) { 860 // Set the translet name 861 xsltc.setClassName(getTransletBaseName(source)); 862 863 if (_destinationDirectory != null) 864 xsltc.setDestDirectory(_destinationDirectory); 865 else { 866 String xslName = getStylesheetFileName(source); 867 if (xslName != null) { 868 File xslFile = new File(xslName); 869 String xslDir = xslFile.getParent(); 870 871 if (xslDir != null) 872 xsltc.setDestDirectory(xslDir); 873 } 874 } 875 876 if (_packageName != null) 877 xsltc.setPackageName(_packageName); 878 879 if (_jarFileName != null) { 880 xsltc.setJarFileName(_jarFileName); 881 outputType = XSLTC.BYTEARRAY_AND_JAR_OUTPUT; 882 } 883 else 884 outputType = XSLTC.BYTEARRAY_AND_FILE_OUTPUT; 885 } 886 887 // Compile the stylesheet 888 final InputSource input = Util.getInputSource(xsltc, source); 889 byte[][] bytecodes = xsltc.compile(null, input, outputType); 890 final String transletName = xsltc.getClassName(); 891 892 // Output to the jar file if the jar file name is set. 893 if ((_generateTranslet || _autoTranslet) 894 && bytecodes != null && _jarFileName != null) { 895 try { 896 xsltc.outputToJar(); 897 } 898 catch (java.io.IOException e) { } 899 } 900 901 // Reset the per-session attributes to their default values 902 // after each newTemplates() call. 903 resetTransientAttributes(); 904 905 // Pass compiler warnings to the error listener 906 if (_errorListener != this) { 907 try { 908 passWarningsToListener(xsltc.getWarnings()); 909 } 910 catch (TransformerException e) { 911 throw new TransformerConfigurationException(e); 912 } 913 } 914 else { 915 xsltc.printWarnings(); 916 } 917 918 // Check that the transformation went well before returning 919 if (bytecodes == null) { 920 Vector errs = xsltc.getErrors(); 921 ErrorMsg err = null; 922 if (errs != null) { 923 err = (ErrorMsg)errs.elementAt(errs.size()-1); 924 } else { 925 err = new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR); 926 } 927 Throwable cause = err.getCause(); 928 TransformerConfigurationException exc; 929 if (cause != null) { 930 exc = new TransformerConfigurationException(cause.getMessage(), cause); 931 } else { 932 exc = new TransformerConfigurationException(err.toString()); 933 } 934 935 // Pass compiler errors to the error listener 936 if (_errorListener != null) { 937 passErrorsToListener(xsltc.getErrors()); 938 939 // As required by TCK 1.2, send a fatalError to the 940 // error listener because compilation of the stylesheet 941 // failed and no further processing will be possible. 942 try { 943 _errorListener.fatalError(exc); 944 } catch (TransformerException te) { 945 // well, we tried. 946 } 947 } 948 else { 949 xsltc.printErrors(); 950 } 951 throw exc; 952 } 953 954 return new TemplatesImpl(bytecodes, transletName, 955 xsltc.getOutputProperties(), _indentNumber, this); 956 } 957 958 /** 959 * javax.xml.transform.sax.SAXTransformerFactory implementation. 960 * Get a TemplatesHandler object that can process SAX ContentHandler 961 * events into a Templates object. 962 * 963 * @return A TemplatesHandler object that can handle SAX events 964 * @throws TransformerConfigurationException 965 */ 966 public TemplatesHandler newTemplatesHandler() 967 throws TransformerConfigurationException 968 { 969 final TemplatesHandlerImpl handler = 970 new TemplatesHandlerImpl(_indentNumber, this); 971 if (_uriResolver != null) { 972 handler.setURIResolver(_uriResolver); 973 } 974 return handler; 975 } 976 977 /** 978 * javax.xml.transform.sax.SAXTransformerFactory implementation. 979 * Get a TransformerHandler object that can process SAX ContentHandler 980 * events into a Result. This method will return a pure copy transformer. 981 * 982 * @return A TransformerHandler object that can handle SAX events 983 * @throws TransformerConfigurationException 984 */ 985 public TransformerHandler newTransformerHandler() 986 throws TransformerConfigurationException 987 { 988 final Transformer transformer = newTransformer(); 989 if (_uriResolver != null) { 990 transformer.setURIResolver(_uriResolver); 991 } 992 return new TransformerHandlerImpl((TransformerImpl) transformer); 993 } 994 995 /** 996 * javax.xml.transform.sax.SAXTransformerFactory implementation. 997 * Get a TransformerHandler object that can process SAX ContentHandler 998 * events into a Result, based on the transformation instructions 999 * specified by the argument. 1000 * 1001 * @param src The source of the transformation instructions. 1002 * @return A TransformerHandler object that can handle SAX events 1003 * @throws TransformerConfigurationException 1004 */ 1005 public TransformerHandler newTransformerHandler(Source src) 1006 throws TransformerConfigurationException 1007 { 1008 final Transformer transformer = newTransformer(src); 1009 if (_uriResolver != null) { 1010 transformer.setURIResolver(_uriResolver); 1011 } 1012 return new TransformerHandlerImpl((TransformerImpl) transformer); 1013 } 1014 1015 /** 1016 * javax.xml.transform.sax.SAXTransformerFactory implementation. 1017 * Get a TransformerHandler object that can process SAX ContentHandler 1018 * events into a Result, based on the transformation instructions 1019 * specified by the argument. 1020 * 1021 * @param templates Represents a pre-processed stylesheet 1022 * @return A TransformerHandler object that can handle SAX events 1023 * @throws TransformerConfigurationException 1024 */ 1025 public TransformerHandler newTransformerHandler(Templates templates) 1026 throws TransformerConfigurationException 1027 { 1028 final Transformer transformer = templates.newTransformer(); 1029 final TransformerImpl internal = (TransformerImpl)transformer; 1030 return new TransformerHandlerImpl(internal); 1031 } 1032 1033 /** 1034 * javax.xml.transform.sax.SAXTransformerFactory implementation. 1035 * Create an XMLFilter that uses the given source as the 1036 * transformation instructions. 1037 * 1038 * @param src The source of the transformation instructions. 1039 * @return An XMLFilter object, or null if this feature is not supported. 1040 * @throws TransformerConfigurationException 1041 */ 1042 public XMLFilter newXMLFilter(Source src) 1043 throws TransformerConfigurationException 1044 { 1045 Templates templates = newTemplates(src); 1046 if (templates == null) return null; 1047 return newXMLFilter(templates); 1048 } 1049 1050 /** 1051 * javax.xml.transform.sax.SAXTransformerFactory implementation. 1052 * Create an XMLFilter that uses the given source as the 1053 * transformation instructions. 1054 * 1055 * @param templates The source of the transformation instructions. 1056 * @return An XMLFilter object, or null if this feature is not supported. 1057 * @throws TransformerConfigurationException 1058 */ 1059 public XMLFilter newXMLFilter(Templates templates) 1060 throws TransformerConfigurationException 1061 { 1062 try { 1063 return new com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter(templates); 1064 } 1065 catch (TransformerConfigurationException e1) { 1066 if (_errorListener != null) { 1067 try { 1068 _errorListener.fatalError(e1); 1069 return null; 1070 } 1071 catch (TransformerException e2) { 1072 new TransformerConfigurationException(e2); 1073 } 1074 } 1075 throw e1; 1076 } 1077 } 1078 1079 /** 1080 * Receive notification of a recoverable error. 1081 * The transformer must continue to provide normal parsing events after 1082 * invoking this method. It should still be possible for the application 1083 * to process the document through to the end. 1084 * 1085 * @param e The warning information encapsulated in a transformer 1086 * exception. 1087 * @throws TransformerException if the application chooses to discontinue 1088 * the transformation (always does in our case). 1089 */ 1090 public void error(TransformerException e) 1091 throws TransformerException 1092 { 1093 Throwable wrapped = e.getException(); 1094 if (wrapped != null) { 1095 System.err.println(new ErrorMsg(ErrorMsg.ERROR_PLUS_WRAPPED_MSG, 1096 e.getMessageAndLocation(), 1097 wrapped.getMessage())); 1098 } else { 1099 System.err.println(new ErrorMsg(ErrorMsg.ERROR_MSG, 1100 e.getMessageAndLocation())); 1101 } 1102 throw e; 1103 } 1104 1105 /** 1106 * Receive notification of a non-recoverable error. 1107 * The application must assume that the transformation cannot continue 1108 * after the Transformer has invoked this method, and should continue 1109 * (if at all) only to collect addition error messages. In fact, 1110 * Transformers are free to stop reporting events once this method has 1111 * been invoked. 1112 * 1113 * @param e warning information encapsulated in a transformer 1114 * exception. 1115 * @throws TransformerException if the application chooses to discontinue 1116 * the transformation (always does in our case). 1117 */ 1118 public void fatalError(TransformerException e) 1119 throws TransformerException 1120 { 1121 Throwable wrapped = e.getException(); 1122 if (wrapped != null) { 1123 System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_PLUS_WRAPPED_MSG, 1124 e.getMessageAndLocation(), 1125 wrapped.getMessage())); 1126 } else { 1127 System.err.println(new ErrorMsg(ErrorMsg.FATAL_ERR_MSG, 1128 e.getMessageAndLocation())); 1129 } 1130 throw e; 1131 } 1132 1133 /** 1134 * Receive notification of a warning. 1135 * Transformers can use this method to report conditions that are not 1136 * errors or fatal errors. The default behaviour is to take no action. 1137 * After invoking this method, the Transformer must continue with the 1138 * transformation. It should still be possible for the application to 1139 * process the document through to the end. 1140 * 1141 * @param e The warning information encapsulated in a transformer 1142 * exception. 1143 * @throws TransformerException if the application chooses to discontinue 1144 * the transformation (never does in our case). 1145 */ 1146 public void warning(TransformerException e) 1147 throws TransformerException 1148 { 1149 Throwable wrapped = e.getException(); 1150 if (wrapped != null) { 1151 System.err.println(new ErrorMsg(ErrorMsg.WARNING_PLUS_WRAPPED_MSG, 1152 e.getMessageAndLocation(), 1153 wrapped.getMessage())); 1154 } else { 1155 System.err.println(new ErrorMsg(ErrorMsg.WARNING_MSG, 1156 e.getMessageAndLocation())); 1157 } 1158 } 1159 1160 /** 1161 * This method implements XSLTC's SourceLoader interface. It is used to 1162 * glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes. 1163 * 1164 * @param href The URI of the document to load 1165 * @param context The URI of the currently loaded document 1166 * @param xsltc The compiler that resuests the document 1167 * @return An InputSource with the loaded document 1168 */ 1169 public InputSource loadSource(String href, String context, XSLTC xsltc) { 1170 try { 1171 if (_uriResolver != null) { 1172 final Source source = _uriResolver.resolve(href, context); 1173 if (source != null) { 1174 return Util.getInputSource(xsltc, source); 1175 } 1176 } 1177 } 1178 catch (TransformerException e) { 1179 // should catch it when the resolver explicitly throws the exception 1180 final ErrorMsg msg = new ErrorMsg(ErrorMsg.INVALID_URI_ERR, href + "\n" + e.getMessage(), this); 1181 xsltc.getParser().reportError(Constants.FATAL, msg); 1182 } 1183 1184 return null; 1185 } 1186 1187 /** 1188 * Reset the per-session attributes to their default values 1189 */ 1190 private void resetTransientAttributes() { 1191 _transletName = DEFAULT_TRANSLET_NAME; 1192 _destinationDirectory = null; 1193 _packageName = null; 1194 _jarFileName = null; 1195 } 1196 1197 /** 1198 * Load the translet classes from local .class files and return 1199 * the bytecode array. 1200 * 1201 * @param source The xsl source 1202 * @param fullClassName The full name of the translet 1203 * @return The bytecode array 1204 */ 1205 private byte[][] getBytecodesFromClasses(Source source, String fullClassName) 1206 { 1207 if (fullClassName == null) 1208 return null; 1209 1210 String xslFileName = getStylesheetFileName(source); 1211 File xslFile = null; 1212 if (xslFileName != null) 1213 xslFile = new File(xslFileName); 1214 1215 // Find the base name of the translet 1216 final String transletName; 1217 int lastDotIndex = fullClassName.lastIndexOf('.'); 1218 if (lastDotIndex > 0) 1219 transletName = fullClassName.substring(lastDotIndex+1); 1220 else 1221 transletName = fullClassName; 1222 1223 // Construct the path name for the translet class file 1224 String transletPath = fullClassName.replace('.', '/'); 1225 if (_destinationDirectory != null) { 1226 transletPath = _destinationDirectory + "/" + transletPath + ".class"; 1227 } 1228 else { 1229 if (xslFile != null && xslFile.getParent() != null) 1230 transletPath = xslFile.getParent() + "/" + transletPath + ".class"; 1231 else 1232 transletPath = transletPath + ".class"; 1233 } 1234 1235 // Return null if the translet class file does not exist. 1236 File transletFile = new File(transletPath); 1237 if (!transletFile.exists()) 1238 return null; 1239 1240 // Compare the timestamps of the translet and the xsl file. 1241 // If the translet is older than the xsl file, return null 1242 // so that the xsl file is used for the transformation and 1243 // the translet is regenerated. 1244 if (xslFile != null && xslFile.exists()) { 1245 long xslTimestamp = xslFile.lastModified(); 1246 long transletTimestamp = transletFile.lastModified(); 1247 if (transletTimestamp < xslTimestamp) 1248 return null; 1249 } 1250 1251 // Load the translet into a bytecode array. 1252 Vector bytecodes = new Vector(); 1253 int fileLength = (int)transletFile.length(); 1254 if (fileLength > 0) { 1255 FileInputStream input = null; 1256 try { 1257 input = new FileInputStream(transletFile); 1258 } 1259 catch (FileNotFoundException e) { 1260 return null; 1261 } 1262 1263 byte[] bytes = new byte[fileLength]; 1264 try { 1265 readFromInputStream(bytes, input, fileLength); 1266 input.close(); 1267 } 1268 catch (IOException e) { 1269 return null; 1270 } 1271 1272 bytecodes.addElement(bytes); 1273 } 1274 else 1275 return null; 1276 1277 // Find the parent directory of the translet. 1278 String transletParentDir = transletFile.getParent(); 1279 if (transletParentDir == null) 1280 transletParentDir = SecuritySupport.getSystemProperty("user.dir"); 1281 1282 File transletParentFile = new File(transletParentDir); 1283 1284 // Find all the auxiliary files which have a name pattern of "transletClass$nnn.class". 1285 final String transletAuxPrefix = transletName + "$"; 1286 File[] auxfiles = transletParentFile.listFiles(new FilenameFilter() { 1287 public boolean accept(File dir, String name) 1288 { 1289 return (name.endsWith(".class") && name.startsWith(transletAuxPrefix)); 1290 } 1291 }); 1292 1293 // Load the auxiliary class files and add them to the bytecode array. 1294 for (int i = 0; i < auxfiles.length; i++) 1295 { 1296 File auxfile = auxfiles[i]; 1297 int auxlength = (int)auxfile.length(); 1298 if (auxlength > 0) { 1299 FileInputStream auxinput = null; 1300 try { 1301 auxinput = new FileInputStream(auxfile); 1302 } 1303 catch (FileNotFoundException e) { 1304 continue; 1305 } 1306 1307 byte[] bytes = new byte[auxlength]; 1308 1309 try { 1310 readFromInputStream(bytes, auxinput, auxlength); 1311 auxinput.close(); 1312 } 1313 catch (IOException e) { 1314 continue; 1315 } 1316 1317 bytecodes.addElement(bytes); 1318 } 1319 } 1320 1321 // Convert the Vector of byte[] to byte[][]. 1322 final int count = bytecodes.size(); 1323 if ( count > 0) { 1324 final byte[][] result = new byte[count][1]; 1325 for (int i = 0; i < count; i++) { 1326 result[i] = (byte[])bytecodes.elementAt(i); 1327 } 1328 1329 return result; 1330 } 1331 else 1332 return null; 1333 } 1334 1335 /** 1336 * Load the translet classes from the jar file and return the bytecode. 1337 * 1338 * @param source The xsl source 1339 * @param fullClassName The full name of the translet 1340 * @return The bytecode array 1341 */ 1342 private byte[][] getBytecodesFromJar(Source source, String fullClassName) 1343 { 1344 String xslFileName = getStylesheetFileName(source); 1345 File xslFile = null; 1346 if (xslFileName != null) 1347 xslFile = new File(xslFileName); 1348 1349 // Construct the path for the jar file 1350 String jarPath = null; 1351 if (_destinationDirectory != null) 1352 jarPath = _destinationDirectory + "/" + _jarFileName; 1353 else { 1354 if (xslFile != null && xslFile.getParent() != null) 1355 jarPath = xslFile.getParent() + "/" + _jarFileName; 1356 else 1357 jarPath = _jarFileName; 1358 } 1359 1360 // Return null if the jar file does not exist. 1361 File file = new File(jarPath); 1362 if (!file.exists()) 1363 return null; 1364 1365 // Compare the timestamps of the jar file and the xsl file. Return null 1366 // if the xsl file is newer than the jar file. 1367 if (xslFile != null && xslFile.exists()) { 1368 long xslTimestamp = xslFile.lastModified(); 1369 long transletTimestamp = file.lastModified(); 1370 if (transletTimestamp < xslTimestamp) 1371 return null; 1372 } 1373 1374 // Create a ZipFile object for the jar file 1375 ZipFile jarFile = null; 1376 try { 1377 jarFile = new ZipFile(file); 1378 } 1379 catch (IOException e) { 1380 return null; 1381 } 1382 1383 String transletPath = fullClassName.replace('.', '/'); 1384 String transletAuxPrefix = transletPath + "$"; 1385 String transletFullName = transletPath + ".class"; 1386 1387 Vector bytecodes = new Vector(); 1388 1389 // Iterate through all entries in the jar file to find the 1390 // translet and auxiliary classes. 1391 Enumeration entries = jarFile.entries(); 1392 while (entries.hasMoreElements()) 1393 { 1394 ZipEntry entry = (ZipEntry)entries.nextElement(); 1395 String entryName = entry.getName(); 1396 if (entry.getSize() > 0 && 1397 (entryName.equals(transletFullName) || 1398 (entryName.endsWith(".class") && 1399 entryName.startsWith(transletAuxPrefix)))) 1400 { 1401 try { 1402 InputStream input = jarFile.getInputStream(entry); 1403 int size = (int)entry.getSize(); 1404 byte[] bytes = new byte[size]; 1405 readFromInputStream(bytes, input, size); 1406 input.close(); 1407 bytecodes.addElement(bytes); 1408 } 1409 catch (IOException e) { 1410 return null; 1411 } 1412 } 1413 } 1414 1415 // Convert the Vector of byte[] to byte[][]. 1416 final int count = bytecodes.size(); 1417 if (count > 0) { 1418 final byte[][] result = new byte[count][1]; 1419 for (int i = 0; i < count; i++) { 1420 result[i] = (byte[])bytecodes.elementAt(i); 1421 } 1422 1423 return result; 1424 } 1425 else 1426 return null; 1427 } 1428 1429 /** 1430 * Read a given number of bytes from the InputStream into a byte array. 1431 * 1432 * @param bytes The byte array to store the input content. 1433 * @param input The input stream. 1434 * @param size The number of bytes to read. 1435 */ 1436 private void readFromInputStream(byte[] bytes, InputStream input, int size) 1437 throws IOException 1438 { 1439 int n = 0; 1440 int offset = 0; 1441 int length = size; 1442 while (length > 0 && (n = input.read(bytes, offset, length)) > 0) { 1443 offset = offset + n; 1444 length = length - n; 1445 } 1446 } 1447 1448 /** 1449 * Return the base class name of the translet. 1450 * The translet name is resolved using the following rules: 1451 * 1. if the _transletName attribute is set and its value is not "GregorSamsa", 1452 * then _transletName is returned. 1453 * 2. otherwise get the translet name from the base name of the system ID 1454 * 3. return "GregorSamsa" if the result from step 2 is null. 1455 * 1456 * @param source The input Source 1457 * @return The name of the translet class 1458 */ 1459 private String getTransletBaseName(Source source) 1460 { 1461 String transletBaseName = null; 1462 if (!_transletName.equals(DEFAULT_TRANSLET_NAME)) 1463 return _transletName; 1464 else { 1465 String systemId = source.getSystemId(); 1466 if (systemId != null) { 1467 String baseName = Util.baseName(systemId); 1468 if (baseName != null) { 1469 baseName = Util.noExtName(baseName); 1470 transletBaseName = Util.toJavaName(baseName); 1471 } 1472 } 1473 } 1474 1475 return (transletBaseName != null) ? transletBaseName : DEFAULT_TRANSLET_NAME; 1476 } 1477 1478 /** 1479 * Return the local file name from the systemId of the Source object 1480 * 1481 * @param source The Source 1482 * @return The file name in the local filesystem, or null if the 1483 * systemId does not represent a local file. 1484 */ 1485 private String getStylesheetFileName(Source source) 1486 { 1487 String systemId = source.getSystemId(); 1488 if (systemId != null) { 1489 File file = new File(systemId); 1490 if (file.exists()) 1491 return systemId; 1492 else { 1493 URL url = null; 1494 try { 1495 url = new URL(systemId); 1496 } 1497 catch (MalformedURLException e) { 1498 return null; 1499 } 1500 1501 if ("file".equals(url.getProtocol())) 1502 return url.getFile(); 1503 else 1504 return null; 1505 } 1506 } 1507 else 1508 return null; 1509 } 1510 1511 /** 1512 * Returns the Class object the provides the XSLTC DTM Manager service. 1513 */ 1514 protected Class getDTMManagerClass() { 1515 return m_DTMManagerClass; 1516 } 1517 }