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