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