/*
 * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sun.org.apache.xalan.internal.xsltc.compiler;

import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import com.sun.org.apache.xalan.internal.utils.FeatureManager.Feature;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
import com.sun.org.apache.xml.internal.dtm.DTM;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import javax.xml.XMLConstants;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

/**
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 * @author G. Todd Miller
 * @author Morten Jorgensen
 * @author John Howard (johnh@schemasoft.com)
 */
public final class XSLTC {

    // A reference to the main stylesheet parser object.
    private Parser _parser;

    // A reference to an external XMLReader (SAX parser) passed to us
    private XMLReader _reader = null;

    // A reference to an external SourceLoader (for use with include/import)
    private SourceLoader _loader = null;

    // A reference to the stylesheet being compiled.
    private Stylesheet _stylesheet;

    // Counters used by various classes to generate unique names.
    // private int _variableSerial     = 1;
    private int _modeSerial         = 1;
    private int _stylesheetSerial   = 1;
    private int _stepPatternSerial  = 1;
    private int _helperClassSerial  = 0;
    private int _attributeSetSerial = 0;

    private int[] _numberFieldIndexes;

    // Name index tables
    private int       _nextGType;  // Next available element type
    private Vector    _namesIndex; // Index of all registered QNames
    private Map<String, Integer> _elements;   // Map of all registered elements
    private Map<String, Integer> _attributes; // Map of all registered attributes

    // Namespace index tables
    private int       _nextNSType; // Next available namespace type
    private Vector    _namespaceIndex; // Index of all registered namespaces
    private Map<String, Integer> _namespaces; // Map of all registered namespaces
    private Map<String, Integer> _namespacePrefixes;// Map of all registered namespace prefixes


    // All literal text in the stylesheet
    private Vector m_characterData;

    // These define the various methods for outputting the translet
    public static final int FILE_OUTPUT        = 0;
    public static final int JAR_OUTPUT         = 1;
    public static final int BYTEARRAY_OUTPUT   = 2;
    public static final int CLASSLOADER_OUTPUT = 3;
    public static final int BYTEARRAY_AND_FILE_OUTPUT = 4;
    public static final int BYTEARRAY_AND_JAR_OUTPUT  = 5;


    // Compiler options (passed from command line or XSLTC client)
    private boolean _debug = false;      // -x
    private String  _jarFileName = null; // -j <jar-file-name>
    private String  _className = null;   // -o <class-name>
    private String  _packageName = null; // -p <package-name>
    private File    _destDir = null;     // -d <directory-name>
    private int     _outputType = FILE_OUTPUT; // by default

    private Vector  _classes;
    private Vector  _bcelClasses;
    private boolean _callsNodeset = false;
    private boolean _multiDocument = false;
    private boolean _hasIdCall = false;

    /**
     * Set to true if template inlining is requested. Template
     * inlining used to be the default, but we have found that
     * Hotspots does a better job with shorter methods, so the
     * default is *not* to inline now.
     */
    private boolean _templateInlining = false;

    /**
     * State of the secure processing feature.
     */
    private boolean _isSecureProcessing = false;

    private boolean _useServicesMechanism = true;

    /**
     * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element.
     */
    private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
     /**
     * protocols allowed for external DTD references in source file and/or stylesheet.
     */
    private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;

    private XMLSecurityManager _xmlSecurityManager;

    private final FeatureManager _featureManager;

    /**
    *  Extension function class loader variables
    */

    /* Class loader reference that will be used for external extension functions loading */
    private ClassLoader _extensionClassLoader;

    /**
    *  HashMap with the loaded classes
    */
    private final Map<String, Class> _externalExtensionFunctions;

    /**
     * XSLTC compiler constructor
     */
    public XSLTC(boolean useServicesMechanism, FeatureManager featureManager) {
        _parser = new Parser(this, useServicesMechanism);
        _featureManager = featureManager;
        _extensionClassLoader = null;
        _externalExtensionFunctions = new HashMap<>();
    }

    /**
     * Set the state of the secure processing feature.
     */
    public void setSecureProcessing(boolean flag) {
        _isSecureProcessing = flag;
    }

    /**
     * Return the state of the secure processing feature.
     */
    public boolean isSecureProcessing() {
        return _isSecureProcessing;
    }
    /**
     * Return the state of the services mechanism feature.
     */
    public boolean useServicesMechnism() {
        return _useServicesMechanism;
    }

    /**
     * Set the state of the services mechanism feature.
     */
    public void setServicesMechnism(boolean flag) {
        _useServicesMechanism = flag;
    }

     /**
     * Return the value of the specified feature
     * @param name name of the feature
     * @return true if the feature is enabled, false otherwise
     */
    public boolean getFeature(Feature name) {
        return _featureManager.isFeatureEnabled(name);
    }

    /**
     * Return allowed protocols for accessing external stylesheet.
     */
    public Object getProperty(String name) {
        if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) {
            return _accessExternalStylesheet;
        }
        else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
            return _accessExternalDTD;
        } else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
            return _xmlSecurityManager;
        } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
            return _extensionClassLoader;
        }
        return null;
    }

    /**
     * Set allowed protocols for accessing external stylesheet.
     */
    public void setProperty(String name, Object value) {
        if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) {
            _accessExternalStylesheet = (String)value;
        }
        else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
            _accessExternalDTD = (String)value;
        } else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
            _xmlSecurityManager = (XMLSecurityManager)value;
        } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
            _extensionClassLoader = (ClassLoader) value;
            /* Clear the external extension functions HashMap if extension class
               loader was changed */
            _externalExtensionFunctions.clear();
        }
    }

    /**
     * Only for user by the internal TrAX implementation.
     */
    public Parser getParser() {
        return _parser;
    }

    /**
     * Only for user by the internal TrAX implementation.
     */
    public void setOutputType(int type) {
        _outputType = type;
    }

    /**
     * Only for user by the internal TrAX implementation.
     */
    public Properties getOutputProperties() {
        return _parser.getOutputProperties();
    }

    /**
     * Initializes the compiler to compile a new stylesheet
     */
    public void init() {
        reset();
        _reader = null;
        _classes = new Vector();
        _bcelClasses = new Vector();
    }

    private void setExternalExtensionFunctions(String name, Class clazz) {
        if (_isSecureProcessing && clazz != null && !_externalExtensionFunctions.containsKey(name)) {
            _externalExtensionFunctions.put(name, clazz);
        }
    }

    /*
     * Function loads an external extension function.
     * The filtering of function types (external,internal) takes place in FunctionCall class
     *
     */
    Class loadExternalFunction(String name) throws ClassNotFoundException {
        Class loaded = null;
        //Check if the function is not loaded already
        if (_externalExtensionFunctions.containsKey(name)) {
            loaded = _externalExtensionFunctions.get(name);
        } else if (_extensionClassLoader != null) {
            loaded = Class.forName(name, true, _extensionClassLoader);
            setExternalExtensionFunctions(name, loaded);
        }
        if (loaded == null) {
            throw new ClassNotFoundException(name);
        }
        //Return loaded class
        return (Class) loaded;
    }

    /*
     * Returns unmodifiable view of HashMap with loaded external extension
     * functions - will be needed for the TransformerImpl
    */
    public Map<String, Class> getExternalExtensionFunctions() {
        return Collections.unmodifiableMap(_externalExtensionFunctions);
    }

    /**
     * Initializes the compiler to produce a new translet
     */
    private void reset() {
        _nextGType      = DTM.NTYPES;
        _elements       = new HashMap<>();
        _attributes     = new HashMap<>();
        _namespaces     = new HashMap<>();
        _namespaces.put("",new Integer(_nextNSType));
        _namesIndex     = new Vector(128);
        _namespaceIndex = new Vector(32);
        _namespacePrefixes = new HashMap<>();
        _stylesheet     = null;
        _parser.init();
        //_variableSerial     = 1;
        _modeSerial         = 1;
        _stylesheetSerial   = 1;
        _stepPatternSerial  = 1;
        _helperClassSerial  = 0;
        _attributeSetSerial = 0;
        _multiDocument      = false;
        _hasIdCall          = false;
        _numberFieldIndexes = new int[] {
            -1,         // LEVEL_SINGLE
            -1,         // LEVEL_MULTIPLE
            -1          // LEVEL_ANY
        };
        _externalExtensionFunctions.clear();
    }

    /**
     * Defines an external SourceLoader to provide the compiler with documents
     * referenced in xsl:include/import
     * @param loader The SourceLoader to use for include/import
     */
    public void setSourceLoader(SourceLoader loader) {
        _loader = loader;
    }

    /**
     * Set a flag indicating if templates are to be inlined or not. The
     * default is to do inlining, but this causes problems when the
     * stylesheets have a large number of templates (e.g. branch targets
     * exceeding 64K or a length of a method exceeding 64K).
     */
    public void setTemplateInlining(boolean templateInlining) {
        _templateInlining = templateInlining;
    }
     /**
     * Return the state of the template inlining feature.
     */
    public boolean getTemplateInlining() {
        return _templateInlining;
    }

    /**
     * Set the parameters to use to locate the correct <?xml-stylesheet ...?>
     * processing instruction in the case where the input document to the
     * compiler (and parser) is an XML document.
     * @param media The media attribute to be matched. May be null, in which
     * case the prefered templates will be used (i.e. alternate = no).
     * @param title The value of the title attribute to match. May be null.
     * @param charset The value of the charset attribute to match. May be null.
     */
    public void setPIParameters(String media, String title, String charset) {
        _parser.setPIParameters(media, title, charset);
    }

    /**
     * Compiles an XSL stylesheet pointed to by a URL
     * @param url An URL containing the input XSL stylesheet
     */
    public boolean compile(URL url) {
        try {
            // Open input stream from URL and wrap inside InputSource
            final InputStream stream = url.openStream();
            final InputSource input = new InputSource(stream);
            input.setSystemId(url.toString());
            return compile(input, _className);
        }
        catch (IOException e) {
            _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
            return false;
        }
    }

    /**
     * Compiles an XSL stylesheet pointed to by a URL
     * @param url An URL containing the input XSL stylesheet
     * @param name The name to assign to the translet class
     */
    public boolean compile(URL url, String name) {
        try {
            // Open input stream from URL and wrap inside InputSource
            final InputStream stream = url.openStream();
            final InputSource input = new InputSource(stream);
            input.setSystemId(url.toString());
            return compile(input, name);
        }
        catch (IOException e) {
            _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
            return false;
        }
    }

    /**
     * Compiles an XSL stylesheet passed in through an InputStream
     * @param stream An InputStream that will pass in the stylesheet contents
     * @param name The name of the translet class to generate
     * @return 'true' if the compilation was successful
     */
    public boolean compile(InputStream stream, String name) {
        final InputSource input = new InputSource(stream);
        input.setSystemId(name); // We have nothing else!!!
        return compile(input, name);
    }

    /**
     * Compiles an XSL stylesheet passed in through an InputStream
     * @param input An InputSource that will pass in the stylesheet contents
     * @param name The name of the translet class to generate - can be null
     * @return 'true' if the compilation was successful
     */
    public boolean compile(InputSource input, String name) {
        try {
            // Reset globals in case we're called by compile(Vector v);
            reset();

            // The systemId may not be set, so we'll have to check the URL
            String systemId = null;
            if (input != null) {
                systemId = input.getSystemId();
            }

            // Set the translet class name if not already set
            if (_className == null) {
                if (name != null) {
                    setClassName(name);
                }
                else if (systemId != null && !systemId.equals("")) {
                    setClassName(Util.baseName(systemId));
                }

                // Ensure we have a non-empty class name at this point
                if (_className == null || _className.length() == 0) {
                    setClassName("GregorSamsa"); // default translet name
                }
            }

            // Get the root node of the abstract syntax tree
            SyntaxTreeNode element = null;
            if (_reader == null) {
                element = _parser.parse(input);
            }
            else {
                element = _parser.parse(_reader, input);
            }

            // Compile the translet - this is where the work is done!
            if ((!_parser.errorsFound()) && (element != null)) {
                // Create a Stylesheet element from the root node
                _stylesheet = _parser.makeStylesheet(element);
                _stylesheet.setSourceLoader(_loader);
                _stylesheet.setSystemId(systemId);
                _stylesheet.setParentStylesheet(null);
                _stylesheet.setTemplateInlining(_templateInlining);
                _parser.setCurrentStylesheet(_stylesheet);

                // Create AST under the Stylesheet element (parse & type-check)
                _parser.createAST(_stylesheet);
            }
            // Generate the bytecodes and output the translet class(es)
            if ((!_parser.errorsFound()) && (_stylesheet != null)) {
                _stylesheet.setCallsNodeset(_callsNodeset);
                _stylesheet.setMultiDocument(_multiDocument);
                _stylesheet.setHasIdCall(_hasIdCall);

                // Class synchronization is needed for BCEL
                synchronized (getClass()) {
                    _stylesheet.translate();
                }
            }
        }
        catch (Exception e) {
            /*if (_debug)*/ e.printStackTrace();
            _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
        }
        catch (Error e) {
            if (_debug) e.printStackTrace();
            _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
        }
        finally {
            _reader = null; // reset this here to be sure it is not re-used
        }
        return !_parser.errorsFound();
    }

    /**
     * Compiles a set of stylesheets pointed to by a Vector of URLs
     * @param stylesheets A Vector containing URLs pointing to the stylesheets
     * @return 'true' if the compilation was successful
     */
    public boolean compile(Vector stylesheets) {
        // Get the number of stylesheets (ie. URLs) in the vector
        final int count = stylesheets.size();

        // Return straight away if the vector is empty
        if (count == 0) return true;

        // Special handling needed if the URL count is one, becuase the
        // _className global must not be reset if it was set explicitly
        if (count == 1) {
            final Object url = stylesheets.firstElement();
            if (url instanceof URL)
                return compile((URL)url);
            else
                return false;
        }
        else {
            // Traverse all elements in the vector and compile
            final Enumeration urls = stylesheets.elements();
            while (urls.hasMoreElements()) {
                _className = null; // reset, so that new name will be computed
                final Object url = urls.nextElement();
                if (url instanceof URL) {
                    if (!compile((URL)url)) return false;
                }
            }
        }
        return true;
    }

    /**
     * Returns an array of bytecode arrays generated by a compilation.
     * @return JVM bytecodes that represent translet class definition
     */
    public byte[][] getBytecodes() {
        final int count = _classes.size();
        final byte[][] result = new byte[count][1];
        for (int i = 0; i < count; i++)
            result[i] = (byte[])_classes.elementAt(i);
        return result;
    }

    /**
     * Compiles a stylesheet pointed to by a URL. The result is put in a
     * set of byte arrays. One byte array for each generated class.
     * @param name The name of the translet class to generate
     * @param input An InputSource that will pass in the stylesheet contents
     * @param outputType The output type
     * @return JVM bytecodes that represent translet class definition
     */
    public byte[][] compile(String name, InputSource input, int outputType) {
        _outputType = outputType;
        if (compile(input, name))
            return getBytecodes();
        else
            return null;
    }

    /**
     * Compiles a stylesheet pointed to by a URL. The result is put in a
     * set of byte arrays. One byte array for each generated class.
     * @param name The name of the translet class to generate
     * @param input An InputSource that will pass in the stylesheet contents
     * @return JVM bytecodes that represent translet class definition
     */
    public byte[][] compile(String name, InputSource input) {
        return compile(name, input, BYTEARRAY_OUTPUT);
    }

    /**
     * Set the XMLReader to use for parsing the next input stylesheet
     * @param reader XMLReader (SAX2 parser) to use
     */
    public void setXMLReader(XMLReader reader) {
        _reader = reader;
    }

    /**
     * Get the XMLReader to use for parsing the next input stylesheet
     */
    public XMLReader getXMLReader() {
        return _reader ;
    }

    /**
     * Get a list of all compile error messages
     * @return A List containing all compile error messages
     */
    public ArrayList<ErrorMsg> getErrors() {
        return _parser.getErrors();
    }

    /**
     * Get a list of all compile warning messages
     * @return A List containing all compile error messages
     */
    public ArrayList<ErrorMsg> getWarnings() {
        return _parser.getWarnings();
    }

    /**
     * Print all compile error messages to standard output
     */
    public void printErrors() {
        _parser.printErrors();
    }

    /**
     * Print all compile warning messages to standard output
     */
    public void printWarnings() {
        _parser.printWarnings();
    }

    /**
     * This method is called by the XPathParser when it encounters a call
     * to the document() function. Affects the DOM used by the translet.
     */
    protected void setMultiDocument(boolean flag) {
        _multiDocument = flag;
    }

    public boolean isMultiDocument() {
        return _multiDocument;
    }

    /**
     * This method is called by the XPathParser when it encounters a call
     * to the nodeset() extension function. Implies multi document.
     */
    protected void setCallsNodeset(boolean flag) {
        if (flag) setMultiDocument(flag);
        _callsNodeset = flag;
    }

    public boolean callsNodeset() {
        return _callsNodeset;
    }

    protected void setHasIdCall(boolean flag) {
        _hasIdCall = flag;
    }

    public boolean hasIdCall() {
        return _hasIdCall;
    }

    /**
     * Set the class name for the generated translet. This class name is
     * overridden if multiple stylesheets are compiled in one go using the
     * compile(Vector urls) method.
     * @param className The name to assign to the translet class
     */
    public void setClassName(String className) {
        final String base  = Util.baseName(className);
        final String noext = Util.noExtName(base);
        String name  = Util.toJavaName(noext);

        if (_packageName == null)
            _className = name;
        else
            _className = _packageName + '.' + name;
    }

    /**
     * Get the class name for the generated translet.
     */
    public String getClassName() {
        return _className;
    }

    /**
     * Convert for Java class name of local system file name.
     * (Replace '.' with '/' on UNIX and replace '.' by '\' on Windows/DOS.)
     */
    private String classFileName(final String className) {
        return className.replace('.', File.separatorChar) + ".class";
    }

    /**
     * Generate an output File object to send the translet to
     */
    private File getOutputFile(String className) {
        if (_destDir != null)
            return new File(_destDir, classFileName(className));
        else
            return new File(classFileName(className));
    }

    /**
     * Set the destination directory for the translet.
     * The current working directory will be used by default.
     */
    public boolean setDestDirectory(String dstDirName) {
        final File dir = new File(dstDirName);
        if (SecuritySupport.getFileExists(dir) || dir.mkdirs()) {
            _destDir = dir;
            return true;
        }
        else {
            _destDir = null;
            return false;
        }
    }

    /**
     * Set an optional package name for the translet and auxiliary classes
     */
    public void setPackageName(String packageName) {
        _packageName = packageName;
        if (_className != null) setClassName(_className);
    }

    /**
     * Set the name of an optional JAR-file to dump the translet and
     * auxiliary classes to
     */
    public void setJarFileName(String jarFileName) {
        final String JAR_EXT = ".jar";
        if (jarFileName.endsWith(JAR_EXT))
            _jarFileName = jarFileName;
        else
            _jarFileName = jarFileName + JAR_EXT;
        _outputType = JAR_OUTPUT;
    }

    public String getJarFileName() {
        return _jarFileName;
    }

    /**
     * Set the top-level stylesheet
     */
    public void setStylesheet(Stylesheet stylesheet) {
        if (_stylesheet == null) _stylesheet = stylesheet;
    }

    /**
     * Returns the top-level stylesheet
     */
    public Stylesheet getStylesheet() {
        return _stylesheet;
    }

    /**
     * Registers an attribute and gives it a type so that it can be mapped to
     * DOM attribute types at run-time.
     */
    public int registerAttribute(QName name) {
        Integer code = _attributes.get(name.toString());
        if (code == null) {
            code = _nextGType++;
            _attributes.put(name.toString(), code);
            final String uri = name.getNamespace();
            final String local = "@"+name.getLocalPart();
            if ((uri != null) && (!uri.equals("")))
                _namesIndex.addElement(uri+":"+local);
            else
                _namesIndex.addElement(local);
            if (name.getLocalPart().equals("*")) {
                registerNamespace(name.getNamespace());
            }
        }
        return code.intValue();
    }

    /**
     * Registers an element and gives it a type so that it can be mapped to
     * DOM element types at run-time.
     */
    public int registerElement(QName name) {
        // Register element (full QName)
        Integer code = _elements.get(name.toString());
        if (code == null) {
            _elements.put(name.toString(), code = _nextGType++);
            _namesIndex.addElement(name.toString());
        }
        if (name.getLocalPart().equals("*")) {
            registerNamespace(name.getNamespace());
        }
        return code.intValue();
    }

     /**
      * Registers a namespace prefix and gives it a type so that it can be mapped to
      * DOM namespace types at run-time.
      */

    public int registerNamespacePrefix(QName name) {

    Integer code = _namespacePrefixes.get(name.toString());
    if (code == null) {
        code = _nextGType++;
        _namespacePrefixes.put(name.toString(), code);
        final String uri = name.getNamespace();
        if ((uri != null) && (!uri.equals(""))){
            // namespace::ext2:ped2 will be made empty in TypedNamespaceIterator
            _namesIndex.addElement("?");
        } else{
           _namesIndex.addElement("?"+name.getLocalPart());
        }
    }
    return code.intValue();
    }

    /**
     * Registers a namespace and gives it a type so that it can be mapped to
     * DOM namespace types at run-time.
     */
    public int registerNamespace(String namespaceURI) {
        Integer code = _namespaces.get(namespaceURI);
        if (code == null) {
            code = _nextNSType++;
            _namespaces.put(namespaceURI,code);
            _namespaceIndex.addElement(namespaceURI);
        }
        return code.intValue();
    }

    public int nextModeSerial() {
        return _modeSerial++;
    }

    public int nextStylesheetSerial() {
        return _stylesheetSerial++;
    }

    public int nextStepPatternSerial() {
        return _stepPatternSerial++;
    }

    public int[] getNumberFieldIndexes() {
        return _numberFieldIndexes;
    }

    public int nextHelperClassSerial() {
        return _helperClassSerial++;
    }

    public int nextAttributeSetSerial() {
        return _attributeSetSerial++;
    }

    public Vector getNamesIndex() {
        return _namesIndex;
    }

    public Vector getNamespaceIndex() {
        return _namespaceIndex;
    }

    /**
     * Returns a unique name for every helper class needed to
     * execute a translet.
     */
    public String getHelperClassName() {
        return getClassName() + '$' + _helperClassSerial++;
    }

    public void dumpClass(JavaClass clazz) {

        if (_outputType == FILE_OUTPUT ||
            _outputType == BYTEARRAY_AND_FILE_OUTPUT)
        {
            File outFile = getOutputFile(clazz.getClassName());
            String parentDir = outFile.getParent();
            if (parentDir != null) {
                File parentFile = new File(parentDir);
                if (!SecuritySupport.getFileExists(parentFile))
                    parentFile.mkdirs();
            }
        }

        try {
            switch (_outputType) {
            case FILE_OUTPUT:
                clazz.dump(
                    new BufferedOutputStream(
                        new FileOutputStream(
                            getOutputFile(clazz.getClassName()))));
                break;
            case JAR_OUTPUT:
                _bcelClasses.addElement(clazz);
                break;
            case BYTEARRAY_OUTPUT:
            case BYTEARRAY_AND_FILE_OUTPUT:
            case BYTEARRAY_AND_JAR_OUTPUT:
            case CLASSLOADER_OUTPUT:
                ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
                clazz.dump(out);
                _classes.addElement(out.toByteArray());

                if (_outputType == BYTEARRAY_AND_FILE_OUTPUT)
                  clazz.dump(new BufferedOutputStream(
                        new FileOutputStream(getOutputFile(clazz.getClassName()))));
                else if (_outputType == BYTEARRAY_AND_JAR_OUTPUT)
                  _bcelClasses.addElement(clazz);

                break;
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * File separators are converted to forward slashes for ZIP files.
     */
    private String entryName(File f) throws IOException {
        return f.getName().replace(File.separatorChar, '/');
    }

    /**
     * Generate output JAR-file and packages
     */
    public void outputToJar() throws IOException {
        // create the manifest
        final Manifest manifest = new Manifest();
        final java.util.jar.Attributes atrs = manifest.getMainAttributes();
        atrs.put(java.util.jar.Attributes.Name.MANIFEST_VERSION,"1.2");

        final Map map = manifest.getEntries();
        // create manifest
        Enumeration classes = _bcelClasses.elements();
        final String now = (new Date()).toString();
        final java.util.jar.Attributes.Name dateAttr =
            new java.util.jar.Attributes.Name("Date");
        while (classes.hasMoreElements()) {
            final JavaClass clazz = (JavaClass)classes.nextElement();
            final String className = clazz.getClassName().replace('.','/');
            final java.util.jar.Attributes attr = new java.util.jar.Attributes();
            attr.put(dateAttr, now);
            map.put(className+".class", attr);
        }

        final File jarFile = new File(_destDir, _jarFileName);
        final JarOutputStream jos =
            new JarOutputStream(new FileOutputStream(jarFile), manifest);
        classes = _bcelClasses.elements();
        while (classes.hasMoreElements()) {
            final JavaClass clazz = (JavaClass)classes.nextElement();
            final String className = clazz.getClassName().replace('.','/');
            jos.putNextEntry(new JarEntry(className+".class"));
            final ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
            clazz.dump(out); // dump() closes it's output stream
            out.writeTo(jos);
        }
        jos.close();
    }

    /**
     * Turn debugging messages on/off
     */
    public void setDebug(boolean debug) {
        _debug = debug;
    }

    /**
     * Get current debugging message setting
     */
    public boolean debug() {
        return _debug;
    }


    /**
     * Retrieve a string representation of the character data to be stored
     * in the translet as a <code>char[]</code>.  There may be more than
     * one such array required.
     * @param index The index of the <code>char[]</code>.  Zero-based.
     * @return String The character data to be stored in the corresponding
     *               <code>char[]</code>.
     */
    public String getCharacterData(int index) {
        return ((StringBuffer) m_characterData.elementAt(index)).toString();
    }

    /**
     * Get the number of char[] arrays, thus far, that will be created to
     * store literal text in the stylesheet.
     */
    public int getCharacterDataCount() {
        return (m_characterData != null) ? m_characterData.size() : 0;
    }

    /**
     * Add literal text to char arrays that will be used to store character
     * data in the stylesheet.
     * @param newData String data to be added to char arrays.
     *                Pre-condition:  <code>newData.length() &le; 21845</code>
     * @return int offset at which character data will be stored
     */
    public int addCharacterData(String newData) {
        StringBuffer currData;
        if (m_characterData == null) {
            m_characterData = new Vector();
            currData = new StringBuffer();
            m_characterData.addElement(currData);
        } else {
            currData = (StringBuffer) m_characterData
                                           .elementAt(m_characterData.size()-1);
        }

        // Character data could take up to three-times as much space when
        // written to the class file as UTF-8.  The maximum size for a
        // constant is 65535/3.  If we exceed that,
        // (We really should use some "bin packing".)
        if (newData.length() + currData.length() > 21845) {
            currData = new StringBuffer();
            m_characterData.addElement(currData);
        }

        int newDataOffset = currData.length();
        currData.append(newData);

        return newDataOffset;
    }
}
