1 /* 2 * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. 3 * @LastModified: Oct 2017 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xalan.internal.xsltc.runtime; 23 24 import com.sun.org.apache.xalan.internal.XalanConstants; 25 import com.sun.org.apache.xalan.internal.utils.FactoryImpl; 26 import com.sun.org.apache.xalan.internal.xsltc.DOM; 27 import com.sun.org.apache.xalan.internal.xsltc.DOMCache; 28 import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM; 29 import com.sun.org.apache.xalan.internal.xsltc.Translet; 30 import com.sun.org.apache.xalan.internal.xsltc.TransletException; 31 import com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter; 32 import com.sun.org.apache.xalan.internal.xsltc.dom.KeyIndex; 33 import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory; 34 import com.sun.org.apache.xml.internal.dtm.DTM; 35 import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 36 import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 37 import java.io.BufferedOutputStream; 38 import java.io.File; 39 import java.io.FileOutputStream; 40 import java.text.DecimalFormat; 41 import java.text.DecimalFormatSymbols; 42 import java.util.ArrayList; 43 import java.util.HashMap; 44 import java.util.List; 45 import java.util.Map; 46 import javax.xml.parsers.DocumentBuilderFactory; 47 import javax.xml.parsers.ParserConfigurationException; 48 import javax.xml.transform.Templates; 49 import org.w3c.dom.DOMImplementation; 50 import org.w3c.dom.Document; 51 52 /** 53 * @author Jacek Ambroziak 54 * @author Santiago Pericas-Geertsen 55 * @author Morten Jorgensen 56 * @author G. Todd Miller 57 * @author John Howard, JohnH@schemasoft.com 58 */ 59 public abstract class AbstractTranslet implements Translet { 60 61 // These attributes are extracted from the xsl:output element. They also 62 // appear as fields (with the same type, only public) in Output.java 63 public String _version = "1.0"; 64 public String _method = null; 65 public String _encoding = "UTF-8"; 66 public boolean _omitHeader = false; 67 public String _standalone = null; 68 //see OutputPropertiesFactory.ORACLE_IS_STANDALONE 69 public boolean _isStandalone = false; 70 public String _doctypePublic = null; 71 public String _doctypeSystem = null; 72 public boolean _indent = false; 73 public String _mediaType = null; 74 public List<String> _cdata = null; 75 public int _indentamount = -1; 76 77 public static final int FIRST_TRANSLET_VERSION = 100; 78 public static final int VER_SPLIT_NAMES_ARRAY = 101; 79 public static final int CURRENT_TRANSLET_VERSION = VER_SPLIT_NAMES_ARRAY; 80 81 // Initialize Translet version field to base value. A class that extends 82 // AbstractTranslet may override this value to a more recent translet 83 // version; if it doesn't override the value (because it was compiled 84 // before the notion of a translet version was introduced, it will get 85 // this default value). 86 protected int transletVersion = FIRST_TRANSLET_VERSION; 87 88 // DOM/translet handshaking - the arrays are set by the compiled translet 89 protected String[] namesArray; 90 protected String[] urisArray; 91 protected int[] typesArray; 92 protected String[] namespaceArray; 93 94 // The Templates object that is used to create this Translet instance 95 protected Templates _templates = null; 96 97 // Boolean flag to indicate whether this translet has id functions. 98 protected boolean _hasIdCall = false; 99 100 // TODO - these should only be instanciated when needed 101 protected StringValueHandler stringValueHandler = new StringValueHandler(); 102 103 // Use one empty string instead of constantly instanciating String(""); 104 private final static String EMPTYSTRING = ""; 105 106 // This is the name of the index used for ID attributes 107 private final static String ID_INDEX_NAME = "##id"; 108 109 private boolean _useServicesMechanism; 110 111 // The OutputStream for redirect function 112 private FileOutputStream output = null; 113 114 /** 115 * protocols allowed for external references set by the stylesheet processing instruction, Document() function, Import and Include element. 116 */ 117 private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT; 118 119 /************************************************************************ 120 * Debugging 121 ************************************************************************/ 122 public void printInternalState() { 123 System.out.println("-------------------------------------"); 124 System.out.println("AbstractTranslet this = " + this); 125 System.out.println("pbase = " + pbase); 126 System.out.println("vframe = " + pframe); 127 System.out.println("paramsStack.size() = " + paramsStack.size()); 128 System.out.println("namesArray.size = " + namesArray.length); 129 System.out.println("namespaceArray.size = " + namespaceArray.length); 130 System.out.println(""); 131 System.out.println("Total memory = " + Runtime.getRuntime().totalMemory()); 132 } 133 134 /** 135 * Wrap the initial input DOM in a dom adapter. This adapter is wrapped in 136 * a DOM multiplexer if the document() function is used (handled by compiled 137 * code in the translet - see compiler/Stylesheet.compileTransform()). 138 */ 139 public final DOMAdapter makeDOMAdapter(DOM dom) 140 throws TransletException { 141 setRootForKeys(dom.getDocument()); 142 return new DOMAdapter(dom, namesArray, urisArray, typesArray, namespaceArray); 143 } 144 145 /************************************************************************ 146 * Parameter handling 147 ************************************************************************/ 148 149 // Parameter's stack: <tt>pbase</tt> and <tt>pframe</tt> are used 150 // to denote the current parameter frame. 151 protected int pbase = 0, pframe = 0; 152 protected List<Object> paramsStack = new ArrayList<>(); 153 154 /** 155 * Push a new parameter frame. 156 */ 157 public final void pushParamFrame() { 158 paramsStack.add(pframe, pbase); 159 pbase = ++pframe; 160 } 161 162 /** 163 * Pop the topmost parameter frame. 164 */ 165 public final void popParamFrame() { 166 if (pbase > 0) { 167 final int oldpbase = ((Integer)paramsStack.get(--pbase)); 168 for (int i = pframe - 1; i >= pbase; i--) { 169 paramsStack.remove(i); 170 } 171 pframe = pbase; pbase = oldpbase; 172 } 173 } 174 175 /** 176 * Add a new global parameter if not already in the current frame. 177 * To setParameters of the form {http://foo.bar}xyz 178 * This needs to get mapped to an instance variable in the class 179 * The mapping created so that 180 * the global variables in the generated class become 181 * http$colon$$flash$$flash$foo$dot$bar$colon$xyz 182 */ 183 public final Object addParameter(String name, Object value) { 184 name = BasisLibrary.mapQNameToJavaName (name); 185 return addParameter(name, value, false); 186 } 187 188 /** 189 * Add a new global or local parameter if not already in the current frame. 190 * The 'isDefault' parameter is set to true if the value passed is the 191 * default value from the <xsl:parameter> element's select attribute or 192 * element body. 193 */ 194 public final Object addParameter(String name, Object value, 195 boolean isDefault) 196 { 197 // Local parameters need to be re-evaluated for each iteration 198 for (int i = pframe - 1; i >= pbase; i--) { 199 final Parameter param = (Parameter) paramsStack.get(i); 200 201 if (param._name.equals(name)) { 202 // Only overwrite if current value is the default value and 203 // the new value is _NOT_ the default value. 204 if (param._isDefault || !isDefault) { 205 param._value = value; 206 param._isDefault = isDefault; 207 return value; 208 } 209 return param._value; 210 } 211 } 212 213 // Add new parameter to parameter stack 214 paramsStack.add(pframe++, new Parameter(name, value, isDefault)); 215 return value; 216 } 217 218 /** 219 * Clears the parameter stack. 220 */ 221 public void clearParameters() { 222 pbase = pframe = 0; 223 paramsStack.clear(); 224 } 225 226 /** 227 * Get the value of a parameter from the current frame or 228 * <tt>null</tt> if undefined. 229 */ 230 public final Object getParameter(String name) { 231 232 name = BasisLibrary.mapQNameToJavaName (name); 233 234 for (int i = pframe - 1; i >= pbase; i--) { 235 final Parameter param = (Parameter)paramsStack.get(i); 236 if (param._name.equals(name)) return param._value; 237 } 238 return null; 239 } 240 241 /************************************************************************ 242 * Message handling - implementation of <xsl:message> 243 ************************************************************************/ 244 245 // Holds the translet's message handler - used for <xsl:message>. 246 // The deault message handler dumps a string stdout, but anything can be 247 // used, such as a dialog box for applets, etc. 248 private MessageHandler _msgHandler = null; 249 250 /** 251 * Set the translet's message handler - must implement MessageHandler 252 */ 253 public final void setMessageHandler(MessageHandler handler) { 254 _msgHandler = handler; 255 } 256 257 /** 258 * Pass a message to the message handler - used by Message class. 259 */ 260 public final void displayMessage(String msg) { 261 if (_msgHandler == null) { 262 System.err.println(msg); 263 } 264 else { 265 _msgHandler.displayMessage(msg); 266 } 267 } 268 269 /************************************************************************ 270 * Decimal number format symbol handling 271 ************************************************************************/ 272 273 // Contains decimal number formatting symbols used by FormatNumberCall 274 public Map<String, DecimalFormat> _formatSymbols = null; 275 276 /** 277 * Adds a DecimalFormat object to the _formatSymbols map. 278 * The entry is created with the input DecimalFormatSymbols. 279 */ 280 public void addDecimalFormat(String name, DecimalFormatSymbols symbols) { 281 // Instanciate map for formatting symbols if needed 282 if (_formatSymbols == null) _formatSymbols = new HashMap<>(); 283 284 // The name cannot be null - use empty string instead 285 if (name == null) name = EMPTYSTRING; 286 287 // Construct a DecimalFormat object containing the symbols we got 288 final DecimalFormat df = new DecimalFormat(); 289 if (symbols != null) { 290 df.setDecimalFormatSymbols(symbols); 291 } 292 _formatSymbols.put(name, df); 293 } 294 295 /** 296 * Retrieves a named DecimalFormat object from the _formatSymbols map. 297 */ 298 public final DecimalFormat getDecimalFormat(String name) { 299 300 if (_formatSymbols != null) { 301 // The name cannot be null - use empty string instead 302 if (name == null) name = EMPTYSTRING; 303 304 DecimalFormat df = _formatSymbols.get(name); 305 if (df == null) df = _formatSymbols.get(EMPTYSTRING); 306 return df; 307 } 308 return(null); 309 } 310 311 /** 312 * Give the translet an opportunity to perform a prepass on the document 313 * to extract any information that it can store in an optimized form. 314 * 315 * Currently, it only extracts information about attributes of type ID. 316 */ 317 public final void prepassDocument(DOM document) { 318 setIndexSize(document.getSize()); 319 buildIDIndex(document); 320 } 321 322 /** 323 * Leverages the Key Class to implement the XSLT id() function. 324 * buildIdIndex creates the index (##id) that Key Class uses. 325 * The index contains the element node index (int) and Id value (String). 326 */ 327 private final void buildIDIndex(DOM document) { 328 setRootForKeys(document.getDocument()); 329 330 if (document instanceof DOMEnhancedForDTM) { 331 DOMEnhancedForDTM enhancedDOM = (DOMEnhancedForDTM)document; 332 333 // If the input source is DOMSource, the KeyIndex table is not 334 // built at this time. It will be built later by the lookupId() 335 // and containsId() methods of the KeyIndex class. 336 if (enhancedDOM.hasDOMSource()) { 337 buildKeyIndex(ID_INDEX_NAME, document); 338 return; 339 } 340 else { 341 final Map<String, Integer> elementsByID = enhancedDOM.getElementsWithIDs(); 342 343 if (elementsByID == null) { 344 return; 345 } 346 347 // Given a Map of DTM nodes indexed by ID attribute values, 348 // loop through the table copying information to a KeyIndex 349 // for the mapping from ID attribute value to DTM node 350 boolean hasIDValues = false; 351 for (Map.Entry<String, Integer> entry : elementsByID.entrySet()) { 352 final int element = document.getNodeHandle(entry.getValue()); 353 buildKeyIndex(ID_INDEX_NAME, element, entry.getKey()); 354 hasIDValues = true; 355 } 356 357 if (hasIDValues) { 358 setKeyIndexDom(ID_INDEX_NAME, document); 359 } 360 } 361 } 362 } 363 364 /** 365 * After constructing the translet object, this method must be called to 366 * perform any version-specific post-initialization that's required. 367 */ 368 public final void postInitialization() { 369 // If the version of the translet had just one namesArray, split 370 // it into multiple fields. 371 if (transletVersion < VER_SPLIT_NAMES_ARRAY) { 372 int arraySize = namesArray.length; 373 String[] newURIsArray = new String[arraySize]; 374 String[] newNamesArray = new String[arraySize]; 375 int[] newTypesArray = new int[arraySize]; 376 377 for (int i = 0; i < arraySize; i++) { 378 String name = namesArray[i]; 379 int colonIndex = name.lastIndexOf(':'); 380 int lNameStartIdx = colonIndex+1; 381 382 if (colonIndex > -1) { 383 newURIsArray[i] = name.substring(0, colonIndex); 384 } 385 386 // Distinguish attribute and element names. Attribute has 387 // @ before local part of name. 388 if (name.charAt(lNameStartIdx) == '@') { 389 lNameStartIdx++; 390 newTypesArray[i] = DTM.ATTRIBUTE_NODE; 391 } else if (name.charAt(lNameStartIdx) == '?') { 392 lNameStartIdx++; 393 newTypesArray[i] = DTM.NAMESPACE_NODE; 394 } else { 395 newTypesArray[i] = DTM.ELEMENT_NODE; 396 } 397 newNamesArray[i] = 398 (lNameStartIdx == 0) ? name 399 : name.substring(lNameStartIdx); 400 } 401 402 namesArray = newNamesArray; 403 urisArray = newURIsArray; 404 typesArray = newTypesArray; 405 } 406 407 // Was translet compiled using a more recent version of the XSLTC 408 // compiler than is known by the AbstractTranslet class? If, so 409 // and we've made it this far (which is doubtful), we should give up. 410 if (transletVersion > CURRENT_TRANSLET_VERSION) { 411 BasisLibrary.runTimeError(BasisLibrary.UNKNOWN_TRANSLET_VERSION_ERR, 412 this.getClass().getName()); 413 } 414 } 415 416 /************************************************************************ 417 * Index(es) for <xsl:key> / key() / id() 418 ************************************************************************/ 419 420 // Container for all indexes for xsl:key elements 421 private Map<String, KeyIndex> _keyIndexes = null; 422 private KeyIndex _emptyKeyIndex = null; 423 private int _indexSize = 0; 424 private int _currentRootForKeys = 0; 425 426 /** 427 * This method is used to pass the largest DOM size to the translet. 428 * Needed to make sure that the translet can index the whole DOM. 429 */ 430 public void setIndexSize(int size) { 431 if (size > _indexSize) _indexSize = size; 432 } 433 434 /** 435 * Creates a KeyIndex object of the desired size - don't want to resize!!! 436 */ 437 public KeyIndex createKeyIndex() { 438 return(new KeyIndex(_indexSize)); 439 } 440 441 /** 442 * Adds a value to a key/id index 443 * @param name is the name of the index (the key or ##id) 444 * @param node is the node handle of the node to insert 445 * @param value is the value that will look up the node in the given index 446 */ 447 public void buildKeyIndex(String name, int node, String value) { 448 KeyIndex index = buildKeyIndexHelper(name); 449 index.add(value, node, _currentRootForKeys); 450 } 451 452 /** 453 * Create an empty KeyIndex in the DOM case 454 * @param name is the name of the index (the key or ##id) 455 * @param dom is the DOM 456 */ 457 public void buildKeyIndex(String name, DOM dom) { 458 KeyIndex index = buildKeyIndexHelper(name); 459 index.setDom(dom, dom.getDocument()); 460 } 461 462 /** 463 * Return KeyIndex for the buildKeyIndex methods. Note the difference from the 464 * public getKeyIndex method, this method creates a new Map if keyIndexes does 465 * not exist. 466 * 467 * @param name the name of the index (the key or ##id) 468 * @return a KeyIndex. 469 */ 470 private KeyIndex buildKeyIndexHelper(String name) { 471 if (_keyIndexes == null) _keyIndexes = new HashMap<>(); 472 473 KeyIndex index = _keyIndexes.get(name); 474 if (index == null) { 475 _keyIndexes.put(name, index = new KeyIndex(_indexSize)); 476 } 477 return index; 478 } 479 480 /** 481 * Returns the index for a given key (or id). 482 * The index implements our internal iterator interface 483 * @param name the name of the index (the key or ##id) 484 * @return a KeyIndex. 485 */ 486 public KeyIndex getKeyIndex(String name) { 487 // Return an empty key index iterator if none are defined 488 if (_keyIndexes == null) { 489 return (_emptyKeyIndex != null) 490 ? _emptyKeyIndex 491 : (_emptyKeyIndex = new KeyIndex(1)); 492 } 493 494 // Look up the requested key index 495 final KeyIndex index = _keyIndexes.get(name); 496 497 // Return an empty key index iterator if the requested index not found 498 if (index == null) { 499 return (_emptyKeyIndex != null) 500 ? _emptyKeyIndex 501 : (_emptyKeyIndex = new KeyIndex(1)); 502 } 503 504 return(index); 505 } 506 507 private void setRootForKeys(int root) { 508 _currentRootForKeys = root; 509 } 510 511 /** 512 * This method builds key indexes - it is overridden in the compiled 513 * translet in cases where the <xsl:key> element is used 514 */ 515 public void buildKeys(DOM document, DTMAxisIterator iterator, 516 SerializationHandler handler, 517 int root) throws TransletException { 518 519 } 520 521 /** 522 * This method builds key indexes - it is overridden in the compiled 523 * translet in cases where the <xsl:key> element is used 524 */ 525 public void setKeyIndexDom(String name, DOM document) { 526 getKeyIndex(name).setDom(document, document.getDocument()); 527 } 528 529 /************************************************************************ 530 * DOM cache handling 531 ************************************************************************/ 532 533 // Hold the DOM cache (if any) used with this translet 534 private DOMCache _domCache = null; 535 536 /** 537 * Sets the DOM cache used for additional documents loaded using the 538 * document() function. 539 */ 540 public void setDOMCache(DOMCache cache) { 541 _domCache = cache; 542 } 543 544 /** 545 * Returns the DOM cache used for this translet. Used by the LoadDocument 546 * class (if present) when the document() function is used. 547 */ 548 public DOMCache getDOMCache() { 549 return(_domCache); 550 } 551 552 /************************************************************************ 553 * Multiple output document extension. 554 * See compiler/TransletOutput for actual implementation. 555 ************************************************************************/ 556 557 public SerializationHandler openOutputHandler(String filename, boolean append) 558 throws TransletException 559 { 560 try { 561 final TransletOutputHandlerFactory factory 562 = TransletOutputHandlerFactory.newInstance(); 563 564 String dirStr = new File(filename).getParent(); 565 if ((null != dirStr) && (dirStr.length() > 0)) { 566 File dir = new File(dirStr); 567 dir.mkdirs(); 568 } 569 570 output = new FileOutputStream(filename, append); 571 factory.setEncoding(_encoding); 572 factory.setOutputMethod(_method); 573 factory.setOutputStream(new BufferedOutputStream(output)); 574 factory.setOutputType(TransletOutputHandlerFactory.STREAM); 575 576 final SerializationHandler handler 577 = factory.getSerializationHandler(); 578 579 transferOutputSettings(handler); 580 handler.startDocument(); 581 return handler; 582 } 583 catch (Exception e) { 584 throw new TransletException(e); 585 } 586 } 587 588 public SerializationHandler openOutputHandler(String filename) 589 throws TransletException 590 { 591 return openOutputHandler(filename, false); 592 } 593 594 public void closeOutputHandler(SerializationHandler handler) { 595 try { 596 handler.endDocument(); 597 handler.close(); 598 if (output != null) { 599 output.close(); 600 } 601 } 602 catch (Exception e) { 603 // what can you do? 604 } 605 } 606 607 /************************************************************************ 608 * Native API transformation methods - _NOT_ JAXP/TrAX 609 ************************************************************************/ 610 611 /** 612 * Main transform() method - this is overridden by the compiled translet 613 */ 614 public abstract void transform(DOM document, DTMAxisIterator iterator, 615 SerializationHandler handler) 616 throws TransletException; 617 618 /** 619 * Calls transform() with a given output handler 620 */ 621 public final void transform(DOM document, SerializationHandler handler) 622 throws TransletException { 623 try { 624 transform(document, document.getIterator(), handler); 625 } finally { 626 _keyIndexes = null; 627 } 628 } 629 630 /** 631 * Used by some compiled code as a shortcut for passing strings to the 632 * output handler 633 */ 634 public final void characters(final String string, 635 SerializationHandler handler) 636 throws TransletException { 637 if (string != null) { 638 //final int length = string.length(); 639 try { 640 handler.characters(string); 641 } catch (Exception e) { 642 throw new TransletException(e); 643 } 644 } 645 } 646 647 /** 648 * Add's a name of an element whose text contents should be output as CDATA 649 */ 650 public void addCdataElement(String name) { 651 if (_cdata == null) { 652 _cdata = new ArrayList<>(); 653 } 654 655 int lastColon = name.lastIndexOf(':'); 656 657 if (lastColon > 0) { 658 String uri = name.substring(0, lastColon); 659 String localName = name.substring(lastColon+1); 660 _cdata.add(uri); 661 _cdata.add(localName); 662 } else { 663 _cdata.add(null); 664 _cdata.add(name); 665 } 666 } 667 668 /** 669 * Transfer the output settings to the output post-processor 670 */ 671 protected void transferOutputSettings(SerializationHandler handler) { 672 if (_method != null) { 673 if (_method.equals("xml")) { 674 if (_standalone != null) { 675 handler.setStandalone(_standalone); 676 } 677 if (_omitHeader) { 678 handler.setOmitXMLDeclaration(true); 679 } 680 handler.setCdataSectionElements(_cdata); 681 if (_version != null) { 682 handler.setVersion(_version); 683 } 684 handler.setIndent(_indent); 685 if (_indentamount >= 0) 686 handler.setIndentAmount(_indentamount); 687 if (_doctypeSystem != null) { 688 handler.setDoctype(_doctypeSystem, _doctypePublic); 689 } 690 handler.setIsStandalone(_isStandalone); 691 } 692 else if (_method.equals("html")) { 693 handler.setIndent(_indent); 694 handler.setDoctype(_doctypeSystem, _doctypePublic); 695 if (_mediaType != null) { 696 handler.setMediaType(_mediaType); 697 } 698 } 699 } 700 else { 701 handler.setCdataSectionElements(_cdata); 702 if (_version != null) { 703 handler.setVersion(_version); 704 } 705 if (_standalone != null) { 706 handler.setStandalone(_standalone); 707 } 708 if (_omitHeader) { 709 handler.setOmitXMLDeclaration(true); 710 } 711 handler.setIndent(_indent); 712 handler.setDoctype(_doctypeSystem, _doctypePublic); 713 handler.setIsStandalone(_isStandalone); 714 } 715 } 716 717 private Map<String, Class<?>> _auxClasses = null; 718 719 public void addAuxiliaryClass(Class<?> auxClass) { 720 if (_auxClasses == null) _auxClasses = new HashMap<>(); 721 _auxClasses.put(auxClass.getName(), auxClass); 722 } 723 724 public void setAuxiliaryClasses(Map<String, Class<?>> auxClasses) { 725 _auxClasses = auxClasses; 726 } 727 728 public Class<?> getAuxiliaryClass(String className) { 729 if (_auxClasses == null) return null; 730 return((Class)_auxClasses.get(className)); 731 } 732 733 // GTM added (see pg 110) 734 public String[] getNamesArray() { 735 return namesArray; 736 } 737 738 public String[] getUrisArray() { 739 return urisArray; 740 } 741 742 public int[] getTypesArray() { 743 return typesArray; 744 } 745 746 public String[] getNamespaceArray() { 747 return namespaceArray; 748 } 749 750 public boolean hasIdCall() { 751 return _hasIdCall; 752 } 753 754 public Templates getTemplates() { 755 return _templates; 756 } 757 758 public void setTemplates(Templates templates) { 759 _templates = templates; 760 } 761 /** 762 * Return the state of the services mechanism feature. 763 */ 764 public boolean useServicesMechnism() { 765 return _useServicesMechanism; 766 } 767 768 /** 769 * Set the state of the services mechanism feature. 770 */ 771 public void setServicesMechnism(boolean flag) { 772 _useServicesMechanism = flag; 773 } 774 775 /** 776 * Return allowed protocols for accessing external stylesheet. 777 */ 778 public String getAllowedProtocols() { 779 return _accessExternalStylesheet; 780 } 781 782 /** 783 * Set allowed protocols for accessing external stylesheet. 784 */ 785 public void setAllowedProtocols(String protocols) { 786 _accessExternalStylesheet = protocols; 787 } 788 789 /************************************************************************ 790 * DOMImplementation caching for basis library 791 ************************************************************************/ 792 protected DOMImplementation _domImplementation = null; 793 794 public Document newDocument(String uri, String qname) 795 throws ParserConfigurationException 796 { 797 if (_domImplementation == null) { 798 DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(_useServicesMechanism); 799 _domImplementation = dbf.newDocumentBuilder().getDOMImplementation(); 800 } 801 return _domImplementation.createDocument(uri, qname, null); 802 } 803 }