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