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