286N/A/*
286N/A * reserved comment block
286N/A * DO NOT REMOVE OR ALTER!
286N/A */
286N/A/*
286N/A * Copyright 2001-2004 The Apache Software Foundation.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A/*
286N/A * $Id: AbstractTranslet.java,v 1.6 2006/06/19 19:49:03 spericas Exp $
286N/A */
286N/A
286N/Apackage com.sun.org.apache.xalan.internal.xsltc.runtime;
286N/A
559N/Aimport com.sun.org.apache.xalan.internal.XalanConstants;
286N/Aimport com.sun.org.apache.xalan.internal.utils.FactoryImpl;
286N/Aimport java.io.File;
286N/Aimport java.io.FileOutputStream;
286N/Aimport java.io.BufferedOutputStream;
286N/Aimport java.text.DecimalFormat;
286N/Aimport java.text.DecimalFormatSymbols;
286N/Aimport java.util.ArrayList;
286N/Aimport java.util.Enumeration;
286N/Aimport java.util.Vector;
286N/Aimport javax.xml.transform.Templates;
286N/Aimport javax.xml.parsers.DocumentBuilderFactory;
286N/Aimport org.w3c.dom.Document;
286N/Aimport org.w3c.dom.DOMImplementation;
286N/Aimport javax.xml.parsers.ParserConfigurationException;
286N/A
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTM;
286N/A
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.DOM;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.DOMCache;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.Translet;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.TransletException;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.dom.KeyIndex;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
286N/Aimport com.sun.org.apache.xml.internal.serializer.SerializationHandler;
286N/A
286N/A/**
286N/A * @author Jacek Ambroziak
286N/A * @author Santiago Pericas-Geertsen
286N/A * @author Morten Jorgensen
286N/A * @author G. Todd Miller
286N/A * @author John Howard, JohnH@schemasoft.com
286N/A */
286N/Apublic abstract class AbstractTranslet implements Translet {
286N/A
286N/A // These attributes are extracted from the xsl:output element. They also
286N/A // appear as fields (with the same type, only public) in Output.java
286N/A public String _version = "1.0";
286N/A public String _method = null;
286N/A public String _encoding = "UTF-8";
286N/A public boolean _omitHeader = false;
286N/A public String _standalone = null;
331N/A //see OutputPropertiesFactory.ORACLE_IS_STANDALONE
331N/A public boolean _isStandalone = false;
286N/A public String _doctypePublic = null;
286N/A public String _doctypeSystem = null;
286N/A public boolean _indent = false;
286N/A public String _mediaType = null;
286N/A public Vector _cdata = null;
286N/A public int _indentamount = -1;
286N/A
286N/A public static final int FIRST_TRANSLET_VERSION = 100;
286N/A public static final int VER_SPLIT_NAMES_ARRAY = 101;
286N/A public static final int CURRENT_TRANSLET_VERSION = VER_SPLIT_NAMES_ARRAY;
286N/A
286N/A // Initialize Translet version field to base value. A class that extends
286N/A // AbstractTranslet may override this value to a more recent translet
286N/A // version; if it doesn't override the value (because it was compiled
286N/A // before the notion of a translet version was introduced, it will get
286N/A // this default value).
286N/A protected int transletVersion = FIRST_TRANSLET_VERSION;
286N/A
286N/A // DOM/translet handshaking - the arrays are set by the compiled translet
286N/A protected String[] namesArray;
286N/A protected String[] urisArray;
286N/A protected int[] typesArray;
286N/A protected String[] namespaceArray;
286N/A
286N/A // The Templates object that is used to create this Translet instance
286N/A protected Templates _templates = null;
286N/A
286N/A // Boolean flag to indicate whether this translet has id functions.
286N/A protected boolean _hasIdCall = false;
286N/A
286N/A // TODO - these should only be instanciated when needed
286N/A protected StringValueHandler stringValueHandler = new StringValueHandler();
286N/A
286N/A // Use one empty string instead of constantly instanciating String("");
286N/A private final static String EMPTYSTRING = "";
286N/A
286N/A // This is the name of the index used for ID attributes
286N/A private final static String ID_INDEX_NAME = "##id";
286N/A
286N/A private boolean _useServicesMechanism;
286N/A
559N/A /**
559N/A * protocols allowed for external references set by the stylesheet processing instruction, Document() function, Import and Include element.
559N/A */
559N/A private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
559N/A
286N/A /************************************************************************
286N/A * Debugging
286N/A ************************************************************************/
286N/A public void printInternalState() {
286N/A System.out.println("-------------------------------------");
286N/A System.out.println("AbstractTranslet this = " + this);
286N/A System.out.println("pbase = " + pbase);
286N/A System.out.println("vframe = " + pframe);
286N/A System.out.println("paramsStack.size() = " + paramsStack.size());
286N/A System.out.println("namesArray.size = " + namesArray.length);
286N/A System.out.println("namespaceArray.size = " + namespaceArray.length);
286N/A System.out.println("");
286N/A System.out.println("Total memory = " + Runtime.getRuntime().totalMemory());
286N/A }
286N/A
286N/A /**
286N/A * Wrap the initial input DOM in a dom adapter. This adapter is wrapped in
286N/A * a DOM multiplexer if the document() function is used (handled by compiled
286N/A * code in the translet - see compiler/Stylesheet.compileTransform()).
286N/A */
286N/A public final DOMAdapter makeDOMAdapter(DOM dom)
286N/A throws TransletException {
286N/A setRootForKeys(dom.getDocument());
286N/A return new DOMAdapter(dom, namesArray, urisArray, typesArray, namespaceArray);
286N/A }
286N/A
286N/A /************************************************************************
286N/A * Parameter handling
286N/A ************************************************************************/
286N/A
286N/A // Parameter's stack: <tt>pbase</tt> and <tt>pframe</tt> are used
286N/A // to denote the current parameter frame.
286N/A protected int pbase = 0, pframe = 0;
286N/A protected ArrayList paramsStack = new ArrayList();
286N/A
286N/A /**
286N/A * Push a new parameter frame.
286N/A */
286N/A public final void pushParamFrame() {
286N/A paramsStack.add(pframe, new Integer(pbase));
286N/A pbase = ++pframe;
286N/A }
286N/A
286N/A /**
286N/A * Pop the topmost parameter frame.
286N/A */
286N/A public final void popParamFrame() {
286N/A if (pbase > 0) {
286N/A final int oldpbase = ((Integer)paramsStack.get(--pbase)).intValue();
286N/A for (int i = pframe - 1; i >= pbase; i--) {
286N/A paramsStack.remove(i);
286N/A }
286N/A pframe = pbase; pbase = oldpbase;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Add a new global parameter if not already in the current frame.
286N/A * To setParameters of the form {http://foo.bar}xyz
286N/A * This needs to get mapped to an instance variable in the class
286N/A * The mapping created so that
286N/A * the global variables in the generated class become
286N/A * http$colon$$flash$$flash$foo$dot$bar$colon$xyz
286N/A */
286N/A public final Object addParameter(String name, Object value) {
286N/A name = BasisLibrary.mapQNameToJavaName (name);
286N/A return addParameter(name, value, false);
286N/A }
286N/A
286N/A /**
286N/A * Add a new global or local parameter if not already in the current frame.
286N/A * The 'isDefault' parameter is set to true if the value passed is the
286N/A * default value from the <xsl:parameter> element's select attribute or
286N/A * element body.
286N/A */
286N/A public final Object addParameter(String name, Object value,
286N/A boolean isDefault)
286N/A {
286N/A // Local parameters need to be re-evaluated for each iteration
286N/A for (int i = pframe - 1; i >= pbase; i--) {
286N/A final Parameter param = (Parameter) paramsStack.get(i);
286N/A
286N/A if (param._name.equals(name)) {
286N/A // Only overwrite if current value is the default value and
286N/A // the new value is _NOT_ the default value.
286N/A if (param._isDefault || !isDefault) {
286N/A param._value = value;
286N/A param._isDefault = isDefault;
286N/A return value;
286N/A }
286N/A return param._value;
286N/A }
286N/A }
286N/A
286N/A // Add new parameter to parameter stack
286N/A paramsStack.add(pframe++, new Parameter(name, value, isDefault));
286N/A return value;
286N/A }
286N/A
286N/A /**
286N/A * Clears the parameter stack.
286N/A */
286N/A public void clearParameters() {
286N/A pbase = pframe = 0;
286N/A paramsStack.clear();
286N/A }
286N/A
286N/A /**
286N/A * Get the value of a parameter from the current frame or
286N/A * <tt>null</tt> if undefined.
286N/A */
286N/A public final Object getParameter(String name) {
286N/A
286N/A name = BasisLibrary.mapQNameToJavaName (name);
286N/A
286N/A for (int i = pframe - 1; i >= pbase; i--) {
286N/A final Parameter param = (Parameter)paramsStack.get(i);
286N/A if (param._name.equals(name)) return param._value;
286N/A }
286N/A return null;
286N/A }
286N/A
286N/A /************************************************************************
286N/A * Message handling - implementation of <xsl:message>
286N/A ************************************************************************/
286N/A
286N/A // Holds the translet's message handler - used for <xsl:message>.
286N/A // The deault message handler dumps a string stdout, but anything can be
286N/A // used, such as a dialog box for applets, etc.
286N/A private MessageHandler _msgHandler = null;
286N/A
286N/A /**
286N/A * Set the translet's message handler - must implement MessageHandler
286N/A */
286N/A public final void setMessageHandler(MessageHandler handler) {
286N/A _msgHandler = handler;
286N/A }
286N/A
286N/A /**
286N/A * Pass a message to the message handler - used by Message class.
286N/A */
286N/A public final void displayMessage(String msg) {
286N/A if (_msgHandler == null) {
286N/A System.err.println(msg);
286N/A }
286N/A else {
286N/A _msgHandler.displayMessage(msg);
286N/A }
286N/A }
286N/A
286N/A /************************************************************************
286N/A * Decimal number format symbol handling
286N/A ************************************************************************/
286N/A
286N/A // Contains decimal number formatting symbols used by FormatNumberCall
286N/A public Hashtable _formatSymbols = null;
286N/A
286N/A /**
286N/A * Adds a DecimalFormat object to the _formatSymbols hashtable.
286N/A * The entry is created with the input DecimalFormatSymbols.
286N/A */
286N/A public void addDecimalFormat(String name, DecimalFormatSymbols symbols) {
286N/A // Instanciate hashtable for formatting symbols if needed
286N/A if (_formatSymbols == null) _formatSymbols = new Hashtable();
286N/A
286N/A // The name cannot be null - use empty string instead
286N/A if (name == null) name = EMPTYSTRING;
286N/A
286N/A // Construct a DecimalFormat object containing the symbols we got
286N/A final DecimalFormat df = new DecimalFormat();
286N/A if (symbols != null) {
286N/A df.setDecimalFormatSymbols(symbols);
286N/A }
286N/A _formatSymbols.put(name, df);
286N/A }
286N/A
286N/A /**
286N/A * Retrieves a named DecimalFormat object from _formatSymbols hashtable.
286N/A */
286N/A public final DecimalFormat getDecimalFormat(String name) {
286N/A
286N/A if (_formatSymbols != null) {
286N/A // The name cannot be null - use empty string instead
286N/A if (name == null) name = EMPTYSTRING;
286N/A
286N/A DecimalFormat df = (DecimalFormat)_formatSymbols.get(name);
286N/A if (df == null) df = (DecimalFormat)_formatSymbols.get(EMPTYSTRING);
286N/A return df;
286N/A }
286N/A return(null);
286N/A }
286N/A
286N/A /**
286N/A * Give the translet an opportunity to perform a prepass on the document
286N/A * to extract any information that it can store in an optimized form.
286N/A *
286N/A * Currently, it only extracts information about attributes of type ID.
286N/A */
286N/A public final void prepassDocument(DOM document) {
286N/A setIndexSize(document.getSize());
286N/A buildIDIndex(document);
286N/A }
286N/A
286N/A /**
286N/A * Leverages the Key Class to implement the XSLT id() function.
286N/A * buildIdIndex creates the index (##id) that Key Class uses.
286N/A * The index contains the element node index (int) and Id value (String).
286N/A */
286N/A private final void buildIDIndex(DOM document) {
286N/A setRootForKeys(document.getDocument());
286N/A
286N/A if (document instanceof DOMEnhancedForDTM) {
286N/A DOMEnhancedForDTM enhancedDOM = (DOMEnhancedForDTM)document;
286N/A
286N/A // If the input source is DOMSource, the KeyIndex table is not
286N/A // built at this time. It will be built later by the lookupId()
286N/A // and containsId() methods of the KeyIndex class.
286N/A if (enhancedDOM.hasDOMSource()) {
286N/A buildKeyIndex(ID_INDEX_NAME, document);
286N/A return;
286N/A }
286N/A else {
286N/A final Hashtable elementsByID = enhancedDOM.getElementsWithIDs();
286N/A
286N/A if (elementsByID == null) {
286N/A return;
286N/A }
286N/A
286N/A // Given a Hashtable of DTM nodes indexed by ID attribute values,
286N/A // loop through the table copying information to a KeyIndex
286N/A // for the mapping from ID attribute value to DTM node
286N/A final Enumeration idValues = elementsByID.keys();
286N/A boolean hasIDValues = false;
286N/A
286N/A while (idValues.hasMoreElements()) {
286N/A final Object idValue = idValues.nextElement();
286N/A final int element =
286N/A document.getNodeHandle(
286N/A ((Integer)elementsByID.get(idValue))
286N/A .intValue());
286N/A
286N/A buildKeyIndex(ID_INDEX_NAME, element, idValue);
286N/A hasIDValues = true;
286N/A }
286N/A
286N/A if (hasIDValues) {
286N/A setKeyIndexDom(ID_INDEX_NAME, document);
286N/A }
286N/A }
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * After constructing the translet object, this method must be called to
286N/A * perform any version-specific post-initialization that's required.
286N/A */
286N/A public final void postInitialization() {
286N/A // If the version of the translet had just one namesArray, split
286N/A // it into multiple fields.
286N/A if (transletVersion < VER_SPLIT_NAMES_ARRAY) {
286N/A int arraySize = namesArray.length;
286N/A String[] newURIsArray = new String[arraySize];
286N/A String[] newNamesArray = new String[arraySize];
286N/A int[] newTypesArray = new int[arraySize];
286N/A
286N/A for (int i = 0; i < arraySize; i++) {
286N/A String name = namesArray[i];
286N/A int colonIndex = name.lastIndexOf(':');
286N/A int lNameStartIdx = colonIndex+1;
286N/A
286N/A if (colonIndex > -1) {
286N/A newURIsArray[i] = name.substring(0, colonIndex);
286N/A }
286N/A
286N/A // Distinguish attribute and element names. Attribute has
286N/A // @ before local part of name.
286N/A if (name.charAt(lNameStartIdx) == '@') {
286N/A lNameStartIdx++;
286N/A newTypesArray[i] = DTM.ATTRIBUTE_NODE;
286N/A } else if (name.charAt(lNameStartIdx) == '?') {
286N/A lNameStartIdx++;
286N/A newTypesArray[i] = DTM.NAMESPACE_NODE;
286N/A } else {
286N/A newTypesArray[i] = DTM.ELEMENT_NODE;
286N/A }
286N/A newNamesArray[i] =
286N/A (lNameStartIdx == 0) ? name
286N/A : name.substring(lNameStartIdx);
286N/A }
286N/A
286N/A namesArray = newNamesArray;
286N/A urisArray = newURIsArray;
286N/A typesArray = newTypesArray;
286N/A }
286N/A
286N/A // Was translet compiled using a more recent version of the XSLTC
286N/A // compiler than is known by the AbstractTranslet class? If, so
286N/A // and we've made it this far (which is doubtful), we should give up.
286N/A if (transletVersion > CURRENT_TRANSLET_VERSION) {
286N/A BasisLibrary.runTimeError(BasisLibrary.UNKNOWN_TRANSLET_VERSION_ERR,
286N/A this.getClass().getName());
286N/A }
286N/A }
286N/A
286N/A /************************************************************************
286N/A * Index(es) for <xsl:key> / key() / id()
286N/A ************************************************************************/
286N/A
286N/A // Container for all indexes for xsl:key elements
286N/A private Hashtable _keyIndexes = null;
286N/A private KeyIndex _emptyKeyIndex = null;
286N/A private int _indexSize = 0;
286N/A private int _currentRootForKeys = 0;
286N/A
286N/A /**
286N/A * This method is used to pass the largest DOM size to the translet.
286N/A * Needed to make sure that the translet can index the whole DOM.
286N/A */
286N/A public void setIndexSize(int size) {
286N/A if (size > _indexSize) _indexSize = size;
286N/A }
286N/A
286N/A /**
286N/A * Creates a KeyIndex object of the desired size - don't want to resize!!!
286N/A */
286N/A public KeyIndex createKeyIndex() {
286N/A return(new KeyIndex(_indexSize));
286N/A }
286N/A
286N/A /**
286N/A * Adds a value to a key/id index
286N/A * @param name is the name of the index (the key or ##id)
286N/A * @param node is the node handle of the node to insert
286N/A * @param value is the value that will look up the node in the given index
286N/A */
286N/A public void buildKeyIndex(String name, int node, Object value) {
286N/A if (_keyIndexes == null) _keyIndexes = new Hashtable();
286N/A
286N/A KeyIndex index = (KeyIndex)_keyIndexes.get(name);
286N/A if (index == null) {
286N/A _keyIndexes.put(name, index = new KeyIndex(_indexSize));
286N/A }
286N/A index.add(value, node, _currentRootForKeys);
286N/A }
286N/A
286N/A /**
286N/A * Create an empty KeyIndex in the DOM case
286N/A * @param name is the name of the index (the key or ##id)
286N/A * @param dom is the DOM
286N/A */
286N/A public void buildKeyIndex(String name, DOM dom) {
286N/A if (_keyIndexes == null) _keyIndexes = new Hashtable();
286N/A
286N/A KeyIndex index = (KeyIndex)_keyIndexes.get(name);
286N/A if (index == null) {
286N/A _keyIndexes.put(name, index = new KeyIndex(_indexSize));
286N/A }
286N/A index.setDom(dom, dom.getDocument());
286N/A }
286N/A
286N/A /**
286N/A * Returns the index for a given key (or id).
286N/A * The index implements our internal iterator interface
286N/A */
286N/A public KeyIndex getKeyIndex(String name) {
286N/A // Return an empty key index iterator if none are defined
286N/A if (_keyIndexes == null) {
286N/A return (_emptyKeyIndex != null)
286N/A ? _emptyKeyIndex
286N/A : (_emptyKeyIndex = new KeyIndex(1));
286N/A }
286N/A
286N/A // Look up the requested key index
286N/A final KeyIndex index = (KeyIndex)_keyIndexes.get(name);
286N/A
286N/A // Return an empty key index iterator if the requested index not found
286N/A if (index == null) {
286N/A return (_emptyKeyIndex != null)
286N/A ? _emptyKeyIndex
286N/A : (_emptyKeyIndex = new KeyIndex(1));
286N/A }
286N/A
286N/A return(index);
286N/A }
286N/A
286N/A private void setRootForKeys(int root) {
286N/A _currentRootForKeys = root;
286N/A }
286N/A
286N/A /**
286N/A * This method builds key indexes - it is overridden in the compiled
286N/A * translet in cases where the <xsl:key> element is used
286N/A */
286N/A public void buildKeys(DOM document, DTMAxisIterator iterator,
286N/A SerializationHandler handler,
286N/A int root) throws TransletException {
286N/A
286N/A }
286N/A
286N/A /**
286N/A * This method builds key indexes - it is overridden in the compiled
286N/A * translet in cases where the <xsl:key> element is used
286N/A */
286N/A public void setKeyIndexDom(String name, DOM document) {
286N/A getKeyIndex(name).setDom(document, document.getDocument());
286N/A }
286N/A
286N/A /************************************************************************
286N/A * DOM cache handling
286N/A ************************************************************************/
286N/A
286N/A // Hold the DOM cache (if any) used with this translet
286N/A private DOMCache _domCache = null;
286N/A
286N/A /**
286N/A * Sets the DOM cache used for additional documents loaded using the
286N/A * document() function.
286N/A */
286N/A public void setDOMCache(DOMCache cache) {
286N/A _domCache = cache;
286N/A }
286N/A
286N/A /**
286N/A * Returns the DOM cache used for this translet. Used by the LoadDocument
286N/A * class (if present) when the document() function is used.
286N/A */
286N/A public DOMCache getDOMCache() {
286N/A return(_domCache);
286N/A }
286N/A
286N/A /************************************************************************
286N/A * Multiple output document extension.
286N/A * See compiler/TransletOutput for actual implementation.
286N/A ************************************************************************/
286N/A
286N/A public SerializationHandler openOutputHandler(String filename, boolean append)
286N/A throws TransletException
286N/A {
286N/A try {
286N/A final TransletOutputHandlerFactory factory
286N/A = TransletOutputHandlerFactory.newInstance();
286N/A
286N/A String dirStr = new File(filename).getParent();
286N/A if ((null != dirStr) && (dirStr.length() > 0)) {
286N/A File dir = new File(dirStr);
286N/A dir.mkdirs();
286N/A }
286N/A
286N/A factory.setEncoding(_encoding);
286N/A factory.setOutputMethod(_method);
286N/A factory.setOutputStream(new BufferedOutputStream(new FileOutputStream(filename, append)));
286N/A factory.setOutputType(TransletOutputHandlerFactory.STREAM);
286N/A
286N/A final SerializationHandler handler
286N/A = factory.getSerializationHandler();
286N/A
286N/A transferOutputSettings(handler);
286N/A handler.startDocument();
286N/A return handler;
286N/A }
286N/A catch (Exception e) {
286N/A throw new TransletException(e);
286N/A }
286N/A }
286N/A
286N/A public SerializationHandler openOutputHandler(String filename)
286N/A throws TransletException
286N/A {
286N/A return openOutputHandler(filename, false);
286N/A }
286N/A
286N/A public void closeOutputHandler(SerializationHandler handler) {
286N/A try {
286N/A handler.endDocument();
286N/A handler.close();
286N/A }
286N/A catch (Exception e) {
286N/A // what can you do?
286N/A }
286N/A }
286N/A
286N/A /************************************************************************
286N/A * Native API transformation methods - _NOT_ JAXP/TrAX
286N/A ************************************************************************/
286N/A
286N/A /**
286N/A * Main transform() method - this is overridden by the compiled translet
286N/A */
286N/A public abstract void transform(DOM document, DTMAxisIterator iterator,
286N/A SerializationHandler handler)
286N/A throws TransletException;
286N/A
286N/A /**
286N/A * Calls transform() with a given output handler
286N/A */
286N/A public final void transform(DOM document, SerializationHandler handler)
286N/A throws TransletException {
286N/A try {
286N/A transform(document, document.getIterator(), handler);
286N/A } finally {
286N/A _keyIndexes = null;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Used by some compiled code as a shortcut for passing strings to the
286N/A * output handler
286N/A */
286N/A public final void characters(final String string,
286N/A SerializationHandler handler)
286N/A throws TransletException {
286N/A if (string != null) {
286N/A //final int length = string.length();
286N/A try {
286N/A handler.characters(string);
286N/A } catch (Exception e) {
286N/A throw new TransletException(e);
286N/A }
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Add's a name of an element whose text contents should be output as CDATA
286N/A */
286N/A public void addCdataElement(String name) {
286N/A if (_cdata == null) {
286N/A _cdata = new Vector();
286N/A }
286N/A
286N/A int lastColon = name.lastIndexOf(':');
286N/A
286N/A if (lastColon > 0) {
286N/A String uri = name.substring(0, lastColon);
286N/A String localName = name.substring(lastColon+1);
286N/A _cdata.addElement(uri);
286N/A _cdata.addElement(localName);
286N/A } else {
286N/A _cdata.addElement(null);
286N/A _cdata.addElement(name);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Transfer the output settings to the output post-processor
286N/A */
286N/A protected void transferOutputSettings(SerializationHandler handler) {
286N/A if (_method != null) {
286N/A if (_method.equals("xml")) {
286N/A if (_standalone != null) {
286N/A handler.setStandalone(_standalone);
286N/A }
286N/A if (_omitHeader) {
286N/A handler.setOmitXMLDeclaration(true);
286N/A }
286N/A handler.setCdataSectionElements(_cdata);
286N/A if (_version != null) {
286N/A handler.setVersion(_version);
286N/A }
286N/A handler.setIndent(_indent);
286N/A handler.setIndentAmount(_indentamount);
286N/A if (_doctypeSystem != null) {
286N/A handler.setDoctype(_doctypeSystem, _doctypePublic);
286N/A }
331N/A handler.setIsStandalone(_isStandalone);
286N/A }
286N/A else if (_method.equals("html")) {
286N/A handler.setIndent(_indent);
286N/A handler.setDoctype(_doctypeSystem, _doctypePublic);
286N/A if (_mediaType != null) {
286N/A handler.setMediaType(_mediaType);
286N/A }
286N/A }
286N/A }
286N/A else {
286N/A handler.setCdataSectionElements(_cdata);
286N/A if (_version != null) {
286N/A handler.setVersion(_version);
286N/A }
286N/A if (_standalone != null) {
286N/A handler.setStandalone(_standalone);
286N/A }
286N/A if (_omitHeader) {
286N/A handler.setOmitXMLDeclaration(true);
286N/A }
286N/A handler.setIndent(_indent);
286N/A handler.setDoctype(_doctypeSystem, _doctypePublic);
331N/A handler.setIsStandalone(_isStandalone);
286N/A }
286N/A }
286N/A
286N/A private Hashtable _auxClasses = null;
286N/A
286N/A public void addAuxiliaryClass(Class auxClass) {
286N/A if (_auxClasses == null) _auxClasses = new Hashtable();
286N/A _auxClasses.put(auxClass.getName(), auxClass);
286N/A }
286N/A
286N/A public void setAuxiliaryClasses(Hashtable auxClasses) {
286N/A _auxClasses = auxClasses;
286N/A }
286N/A
286N/A public Class getAuxiliaryClass(String className) {
286N/A if (_auxClasses == null) return null;
286N/A return((Class)_auxClasses.get(className));
286N/A }
286N/A
286N/A // GTM added (see pg 110)
286N/A public String[] getNamesArray() {
286N/A return namesArray;
286N/A }
286N/A
286N/A public String[] getUrisArray() {
286N/A return urisArray;
286N/A }
286N/A
286N/A public int[] getTypesArray() {
286N/A return typesArray;
286N/A }
286N/A
286N/A public String[] getNamespaceArray() {
286N/A return namespaceArray;
286N/A }
286N/A
286N/A public boolean hasIdCall() {
286N/A return _hasIdCall;
286N/A }
286N/A
286N/A public Templates getTemplates() {
286N/A return _templates;
286N/A }
286N/A
286N/A public void setTemplates(Templates templates) {
286N/A _templates = templates;
286N/A }
286N/A /**
286N/A * Return the state of the services mechanism feature.
286N/A */
286N/A public boolean useServicesMechnism() {
286N/A return _useServicesMechanism;
286N/A }
286N/A
286N/A /**
286N/A * Set the state of the services mechanism feature.
286N/A */
286N/A public void setServicesMechnism(boolean flag) {
286N/A _useServicesMechanism = flag;
286N/A }
286N/A
559N/A /**
559N/A * Return allowed protocols for accessing external stylesheet.
559N/A */
559N/A public String getAllowedProtocols() {
559N/A return _accessExternalStylesheet;
559N/A }
559N/A
559N/A /**
559N/A * Set allowed protocols for accessing external stylesheet.
559N/A */
559N/A public void setAllowedProtocols(String protocols) {
559N/A _accessExternalStylesheet = protocols;
559N/A }
559N/A
286N/A /************************************************************************
286N/A * DOMImplementation caching for basis library
286N/A ************************************************************************/
286N/A protected DOMImplementation _domImplementation = null;
286N/A
286N/A public Document newDocument(String uri, String qname)
286N/A throws ParserConfigurationException
286N/A {
286N/A if (_domImplementation == null) {
286N/A DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(_useServicesMechanism);
286N/A _domImplementation = dbf.newDocumentBuilder().getDOMImplementation();
286N/A }
286N/A return _domImplementation.createDocument(uri, qname, null);
286N/A }
286N/A}