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: XSLTC.java,v 1.2.4.1 2005/09/05 09:51:38 pvedula Exp $
286N/A */
286N/A
286N/Apackage com.sun.org.apache.xalan.internal.xsltc.compiler;
286N/A
286N/Aimport java.io.BufferedOutputStream;
286N/Aimport java.io.ByteArrayOutputStream;
286N/Aimport java.io.File;
286N/Aimport java.io.FileOutputStream;
286N/Aimport java.io.IOException;
286N/Aimport java.io.InputStream;
286N/Aimport java.net.URL;
286N/Aimport java.util.Date;
286N/Aimport java.util.Enumeration;
286N/Aimport java.util.Hashtable;
286N/Aimport java.util.Map;
286N/Aimport java.util.Properties;
286N/Aimport java.util.Vector;
286N/Aimport java.util.jar.JarEntry;
286N/Aimport java.util.jar.JarOutputStream;
286N/Aimport java.util.jar.Manifest;
559N/Aimport javax.xml.XMLConstants;
286N/A
286N/Aimport com.sun.org.apache.bcel.internal.classfile.JavaClass;
559N/Aimport com.sun.org.apache.xalan.internal.XalanConstants;
524N/Aimport com.sun.org.apache.xalan.internal.utils.SecuritySupport;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTM;
286N/A
524N/Aimport com.sun.org.apache.xalan.internal.utils.SecuritySupport;
286N/Aimport org.xml.sax.InputSource;
286N/Aimport org.xml.sax.XMLReader;
286N/A
286N/A/**
286N/A * @author Jacek Ambroziak
286N/A * @author Santiago Pericas-Geertsen
286N/A * @author G. Todd Miller
286N/A * @author Morten Jorgensen
286N/A * @author John Howard (johnh@schemasoft.com)
286N/A */
286N/Apublic final class XSLTC {
286N/A
286N/A // A reference to the main stylesheet parser object.
286N/A private Parser _parser;
286N/A
286N/A // A reference to an external XMLReader (SAX parser) passed to us
286N/A private XMLReader _reader = null;
286N/A
286N/A // A reference to an external SourceLoader (for use with include/import)
286N/A private SourceLoader _loader = null;
286N/A
286N/A // A reference to the stylesheet being compiled.
286N/A private Stylesheet _stylesheet;
286N/A
286N/A // Counters used by various classes to generate unique names.
286N/A // private int _variableSerial = 1;
286N/A private int _modeSerial = 1;
286N/A private int _stylesheetSerial = 1;
286N/A private int _stepPatternSerial = 1;
286N/A private int _helperClassSerial = 0;
286N/A private int _attributeSetSerial = 0;
286N/A
286N/A private int[] _numberFieldIndexes;
286N/A
286N/A // Name index tables
286N/A private int _nextGType; // Next available element type
286N/A private Vector _namesIndex; // Index of all registered QNames
286N/A private Hashtable _elements; // Hashtable of all registered elements
286N/A private Hashtable _attributes; // Hashtable of all registered attributes
286N/A
286N/A // Namespace index tables
286N/A private int _nextNSType; // Next available namespace type
286N/A private Vector _namespaceIndex; // Index of all registered namespaces
286N/A private Hashtable _namespaces; // Hashtable of all registered namespaces
286N/A private Hashtable _namespacePrefixes;// Hashtable of all registered namespace prefixes
286N/A
286N/A
286N/A // All literal text in the stylesheet
286N/A private Vector m_characterData;
286N/A
286N/A // These define the various methods for outputting the translet
286N/A public static final int FILE_OUTPUT = 0;
286N/A public static final int JAR_OUTPUT = 1;
286N/A public static final int BYTEARRAY_OUTPUT = 2;
286N/A public static final int CLASSLOADER_OUTPUT = 3;
286N/A public static final int BYTEARRAY_AND_FILE_OUTPUT = 4;
286N/A public static final int BYTEARRAY_AND_JAR_OUTPUT = 5;
286N/A
286N/A
286N/A // Compiler options (passed from command line or XSLTC client)
286N/A private boolean _debug = false; // -x
286N/A private String _jarFileName = null; // -j <jar-file-name>
286N/A private String _className = null; // -o <class-name>
286N/A private String _packageName = null; // -p <package-name>
286N/A private File _destDir = null; // -d <directory-name>
286N/A private int _outputType = FILE_OUTPUT; // by default
286N/A
286N/A private Vector _classes;
286N/A private Vector _bcelClasses;
286N/A private boolean _callsNodeset = false;
286N/A private boolean _multiDocument = false;
286N/A private boolean _hasIdCall = false;
293N/A
286N/A /**
286N/A * Set to true if template inlining is requested. Template
286N/A * inlining used to be the default, but we have found that
286N/A * Hotspots does a better job with shorter methods, so the
286N/A * default is *not* to inline now.
286N/A */
286N/A private boolean _templateInlining = false;
286N/A
286N/A /**
286N/A * State of the secure processing feature.
286N/A */
286N/A private boolean _isSecureProcessing = false;
286N/A
286N/A private boolean _useServicesMechanism = true;
286N/A
286N/A /**
559N/A * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element.
559N/A */
559N/A private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
559N/A /**
559N/A * protocols allowed for external DTD references in source file and/or stylesheet.
559N/A */
559N/A private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
559N/A
559N/A
559N/A /**
286N/A * XSLTC compiler constructor
286N/A */
286N/A public XSLTC(boolean useServicesMechanism) {
286N/A _parser = new Parser(this, useServicesMechanism);
286N/A }
286N/A
286N/A /**
286N/A * Set the state of the secure processing feature.
286N/A */
286N/A public void setSecureProcessing(boolean flag) {
286N/A _isSecureProcessing = flag;
286N/A }
286N/A
286N/A /**
286N/A * Return the state of the secure processing feature.
286N/A */
286N/A public boolean isSecureProcessing() {
286N/A return _isSecureProcessing;
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
286N/A /**
559N/A * Return allowed protocols for accessing external stylesheet.
559N/A */
559N/A public String getProperty(String name) {
559N/A if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) {
559N/A return _accessExternalStylesheet;
559N/A }
559N/A else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
559N/A return _accessExternalDTD;
559N/A }
559N/A return null;
559N/A }
559N/A
559N/A /**
559N/A * Set allowed protocols for accessing external stylesheet.
559N/A */
559N/A public void setProperty(String name, String value) {
559N/A if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) {
559N/A _accessExternalStylesheet = (String)value;
559N/A }
559N/A else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) {
559N/A _accessExternalDTD = (String)value;
559N/A }
559N/A }
559N/A
559N/A /**
286N/A * Only for user by the internal TrAX implementation.
286N/A */
286N/A public Parser getParser() {
286N/A return _parser;
286N/A }
286N/A
286N/A /**
286N/A * Only for user by the internal TrAX implementation.
286N/A */
286N/A public void setOutputType(int type) {
286N/A _outputType = type;
286N/A }
286N/A
286N/A /**
286N/A * Only for user by the internal TrAX implementation.
286N/A */
286N/A public Properties getOutputProperties() {
286N/A return _parser.getOutputProperties();
286N/A }
286N/A
286N/A /**
286N/A * Initializes the compiler to compile a new stylesheet
286N/A */
286N/A public void init() {
286N/A reset();
286N/A _reader = null;
286N/A _classes = new Vector();
286N/A _bcelClasses = new Vector();
286N/A }
286N/A
286N/A /**
286N/A * Initializes the compiler to produce a new translet
286N/A */
286N/A private void reset() {
286N/A _nextGType = DTM.NTYPES;
286N/A _elements = new Hashtable();
286N/A _attributes = new Hashtable();
286N/A _namespaces = new Hashtable();
286N/A _namespaces.put("",new Integer(_nextNSType));
286N/A _namesIndex = new Vector(128);
286N/A _namespaceIndex = new Vector(32);
286N/A _namespacePrefixes = new Hashtable();
286N/A _stylesheet = null;
286N/A _parser.init();
286N/A //_variableSerial = 1;
286N/A _modeSerial = 1;
286N/A _stylesheetSerial = 1;
286N/A _stepPatternSerial = 1;
286N/A _helperClassSerial = 0;
286N/A _attributeSetSerial = 0;
286N/A _multiDocument = false;
286N/A _hasIdCall = false;
286N/A _numberFieldIndexes = new int[] {
286N/A -1, // LEVEL_SINGLE
286N/A -1, // LEVEL_MULTIPLE
286N/A -1 // LEVEL_ANY
286N/A };
286N/A }
286N/A
286N/A /**
286N/A * Defines an external SourceLoader to provide the compiler with documents
286N/A * referenced in xsl:include/import
286N/A * @param loader The SourceLoader to use for include/import
286N/A */
286N/A public void setSourceLoader(SourceLoader loader) {
286N/A _loader = loader;
286N/A }
286N/A
286N/A /**
286N/A * Set a flag indicating if templates are to be inlined or not. The
286N/A * default is to do inlining, but this causes problems when the
286N/A * stylesheets have a large number of templates (e.g. branch targets
286N/A * exceeding 64K or a length of a method exceeding 64K).
286N/A */
286N/A public void setTemplateInlining(boolean templateInlining) {
286N/A _templateInlining = templateInlining;
286N/A }
286N/A /**
286N/A * Return the state of the template inlining feature.
286N/A */
286N/A public boolean getTemplateInlining() {
286N/A return _templateInlining;
286N/A }
286N/A
286N/A /**
286N/A * Set the parameters to use to locate the correct <?xml-stylesheet ...?>
286N/A * processing instruction in the case where the input document to the
286N/A * compiler (and parser) is an XML document.
286N/A * @param media The media attribute to be matched. May be null, in which
286N/A * case the prefered templates will be used (i.e. alternate = no).
286N/A * @param title The value of the title attribute to match. May be null.
286N/A * @param charset The value of the charset attribute to match. May be null.
286N/A */
286N/A public void setPIParameters(String media, String title, String charset) {
286N/A _parser.setPIParameters(media, title, charset);
286N/A }
286N/A
286N/A /**
286N/A * Compiles an XSL stylesheet pointed to by a URL
286N/A * @param url An URL containing the input XSL stylesheet
286N/A */
286N/A public boolean compile(URL url) {
286N/A try {
286N/A // Open input stream from URL and wrap inside InputSource
286N/A final InputStream stream = url.openStream();
286N/A final InputSource input = new InputSource(stream);
286N/A input.setSystemId(url.toString());
286N/A return compile(input, _className);
286N/A }
286N/A catch (IOException e) {
524N/A _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
286N/A return false;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Compiles an XSL stylesheet pointed to by a URL
286N/A * @param url An URL containing the input XSL stylesheet
286N/A * @param name The name to assign to the translet class
286N/A */
286N/A public boolean compile(URL url, String name) {
286N/A try {
286N/A // Open input stream from URL and wrap inside InputSource
286N/A final InputStream stream = url.openStream();
286N/A final InputSource input = new InputSource(stream);
286N/A input.setSystemId(url.toString());
286N/A return compile(input, name);
286N/A }
286N/A catch (IOException e) {
524N/A _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
286N/A return false;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Compiles an XSL stylesheet passed in through an InputStream
286N/A * @param stream An InputStream that will pass in the stylesheet contents
286N/A * @param name The name of the translet class to generate
286N/A * @return 'true' if the compilation was successful
286N/A */
286N/A public boolean compile(InputStream stream, String name) {
286N/A final InputSource input = new InputSource(stream);
286N/A input.setSystemId(name); // We have nothing else!!!
286N/A return compile(input, name);
286N/A }
286N/A
286N/A /**
286N/A * Compiles an XSL stylesheet passed in through an InputStream
286N/A * @param input An InputSource that will pass in the stylesheet contents
286N/A * @param name The name of the translet class to generate - can be null
286N/A * @return 'true' if the compilation was successful
286N/A */
286N/A public boolean compile(InputSource input, String name) {
286N/A try {
286N/A // Reset globals in case we're called by compile(Vector v);
286N/A reset();
286N/A
286N/A // The systemId may not be set, so we'll have to check the URL
286N/A String systemId = null;
286N/A if (input != null) {
286N/A systemId = input.getSystemId();
286N/A }
286N/A
286N/A // Set the translet class name if not already set
286N/A if (_className == null) {
286N/A if (name != null) {
286N/A setClassName(name);
286N/A }
286N/A else if (systemId != null && !systemId.equals("")) {
286N/A setClassName(Util.baseName(systemId));
286N/A }
286N/A
286N/A // Ensure we have a non-empty class name at this point
286N/A if (_className == null || _className.length() == 0) {
286N/A setClassName("GregorSamsa"); // default translet name
286N/A }
286N/A }
286N/A
286N/A // Get the root node of the abstract syntax tree
286N/A SyntaxTreeNode element = null;
286N/A if (_reader == null) {
286N/A element = _parser.parse(input);
286N/A }
286N/A else {
286N/A element = _parser.parse(_reader, input);
286N/A }
286N/A
286N/A // Compile the translet - this is where the work is done!
286N/A if ((!_parser.errorsFound()) && (element != null)) {
286N/A // Create a Stylesheet element from the root node
286N/A _stylesheet = _parser.makeStylesheet(element);
286N/A _stylesheet.setSourceLoader(_loader);
286N/A _stylesheet.setSystemId(systemId);
286N/A _stylesheet.setParentStylesheet(null);
286N/A _stylesheet.setTemplateInlining(_templateInlining);
286N/A _parser.setCurrentStylesheet(_stylesheet);
286N/A
286N/A // Create AST under the Stylesheet element (parse & type-check)
286N/A _parser.createAST(_stylesheet);
286N/A }
286N/A // Generate the bytecodes and output the translet class(es)
286N/A if ((!_parser.errorsFound()) && (_stylesheet != null)) {
286N/A _stylesheet.setCallsNodeset(_callsNodeset);
286N/A _stylesheet.setMultiDocument(_multiDocument);
286N/A _stylesheet.setHasIdCall(_hasIdCall);
286N/A
286N/A // Class synchronization is needed for BCEL
286N/A synchronized (getClass()) {
286N/A _stylesheet.translate();
286N/A }
286N/A }
286N/A }
286N/A catch (Exception e) {
286N/A /*if (_debug)*/ e.printStackTrace();
524N/A _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
286N/A }
286N/A catch (Error e) {
286N/A if (_debug) e.printStackTrace();
524N/A _parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e));
286N/A }
286N/A finally {
286N/A _reader = null; // reset this here to be sure it is not re-used
286N/A }
286N/A return !_parser.errorsFound();
286N/A }
286N/A
286N/A /**
286N/A * Compiles a set of stylesheets pointed to by a Vector of URLs
286N/A * @param stylesheets A Vector containing URLs pointing to the stylesheets
286N/A * @return 'true' if the compilation was successful
286N/A */
286N/A public boolean compile(Vector stylesheets) {
286N/A // Get the number of stylesheets (ie. URLs) in the vector
286N/A final int count = stylesheets.size();
286N/A
286N/A // Return straight away if the vector is empty
286N/A if (count == 0) return true;
286N/A
286N/A // Special handling needed if the URL count is one, becuase the
286N/A // _className global must not be reset if it was set explicitly
286N/A if (count == 1) {
286N/A final Object url = stylesheets.firstElement();
286N/A if (url instanceof URL)
286N/A return compile((URL)url);
286N/A else
286N/A return false;
286N/A }
286N/A else {
286N/A // Traverse all elements in the vector and compile
286N/A final Enumeration urls = stylesheets.elements();
286N/A while (urls.hasMoreElements()) {
286N/A _className = null; // reset, so that new name will be computed
286N/A final Object url = urls.nextElement();
286N/A if (url instanceof URL) {
286N/A if (!compile((URL)url)) return false;
286N/A }
286N/A }
286N/A }
286N/A return true;
286N/A }
286N/A
286N/A /**
286N/A * Returns an array of bytecode arrays generated by a compilation.
286N/A * @return JVM bytecodes that represent translet class definition
286N/A */
286N/A public byte[][] getBytecodes() {
286N/A final int count = _classes.size();
286N/A final byte[][] result = new byte[count][1];
286N/A for (int i = 0; i < count; i++)
286N/A result[i] = (byte[])_classes.elementAt(i);
286N/A return result;
286N/A }
286N/A
286N/A /**
286N/A * Compiles a stylesheet pointed to by a URL. The result is put in a
286N/A * set of byte arrays. One byte array for each generated class.
286N/A * @param name The name of the translet class to generate
286N/A * @param input An InputSource that will pass in the stylesheet contents
286N/A * @param outputType The output type
286N/A * @return JVM bytecodes that represent translet class definition
286N/A */
286N/A public byte[][] compile(String name, InputSource input, int outputType) {
286N/A _outputType = outputType;
286N/A if (compile(input, name))
286N/A return getBytecodes();
286N/A else
286N/A return null;
286N/A }
286N/A
286N/A /**
286N/A * Compiles a stylesheet pointed to by a URL. The result is put in a
286N/A * set of byte arrays. One byte array for each generated class.
286N/A * @param name The name of the translet class to generate
286N/A * @param input An InputSource that will pass in the stylesheet contents
286N/A * @return JVM bytecodes that represent translet class definition
286N/A */
286N/A public byte[][] compile(String name, InputSource input) {
286N/A return compile(name, input, BYTEARRAY_OUTPUT);
286N/A }
286N/A
286N/A /**
286N/A * Set the XMLReader to use for parsing the next input stylesheet
286N/A * @param reader XMLReader (SAX2 parser) to use
286N/A */
286N/A public void setXMLReader(XMLReader reader) {
286N/A _reader = reader;
286N/A }
286N/A
286N/A /**
286N/A * Get the XMLReader to use for parsing the next input stylesheet
286N/A */
286N/A public XMLReader getXMLReader() {
286N/A return _reader ;
286N/A }
286N/A
286N/A /**
286N/A * Get a Vector containing all compile error messages
286N/A * @return A Vector containing all compile error messages
286N/A */
286N/A public Vector getErrors() {
286N/A return _parser.getErrors();
286N/A }
286N/A
286N/A /**
286N/A * Get a Vector containing all compile warning messages
286N/A * @return A Vector containing all compile error messages
286N/A */
286N/A public Vector getWarnings() {
286N/A return _parser.getWarnings();
286N/A }
286N/A
286N/A /**
286N/A * Print all compile error messages to standard output
286N/A */
286N/A public void printErrors() {
286N/A _parser.printErrors();
286N/A }
286N/A
286N/A /**
286N/A * Print all compile warning messages to standard output
286N/A */
286N/A public void printWarnings() {
286N/A _parser.printWarnings();
286N/A }
286N/A
286N/A /**
286N/A * This method is called by the XPathParser when it encounters a call
286N/A * to the document() function. Affects the DOM used by the translet.
286N/A */
286N/A protected void setMultiDocument(boolean flag) {
286N/A _multiDocument = flag;
286N/A }
286N/A
286N/A public boolean isMultiDocument() {
286N/A return _multiDocument;
286N/A }
286N/A
286N/A /**
286N/A * This method is called by the XPathParser when it encounters a call
286N/A * to the nodeset() extension function. Implies multi document.
286N/A */
286N/A protected void setCallsNodeset(boolean flag) {
286N/A if (flag) setMultiDocument(flag);
286N/A _callsNodeset = flag;
286N/A }
286N/A
286N/A public boolean callsNodeset() {
286N/A return _callsNodeset;
286N/A }
286N/A
286N/A protected void setHasIdCall(boolean flag) {
286N/A _hasIdCall = flag;
286N/A }
286N/A
286N/A public boolean hasIdCall() {
286N/A return _hasIdCall;
286N/A }
286N/A
286N/A /**
286N/A * Set the class name for the generated translet. This class name is
286N/A * overridden if multiple stylesheets are compiled in one go using the
286N/A * compile(Vector urls) method.
286N/A * @param className The name to assign to the translet class
286N/A */
286N/A public void setClassName(String className) {
286N/A final String base = Util.baseName(className);
286N/A final String noext = Util.noExtName(base);
286N/A String name = Util.toJavaName(noext);
286N/A
286N/A if (_packageName == null)
286N/A _className = name;
286N/A else
286N/A _className = _packageName + '.' + name;
286N/A }
286N/A
286N/A /**
286N/A * Get the class name for the generated translet.
286N/A */
286N/A public String getClassName() {
286N/A return _className;
286N/A }
286N/A
286N/A /**
286N/A * Convert for Java class name of local system file name.
286N/A * (Replace '.' with '/' on UNIX and replace '.' by '\' on Windows/DOS.)
286N/A */
286N/A private String classFileName(final String className) {
286N/A return className.replace('.', File.separatorChar) + ".class";
286N/A }
286N/A
286N/A /**
286N/A * Generate an output File object to send the translet to
286N/A */
286N/A private File getOutputFile(String className) {
286N/A if (_destDir != null)
286N/A return new File(_destDir, classFileName(className));
286N/A else
286N/A return new File(classFileName(className));
286N/A }
286N/A
286N/A /**
286N/A * Set the destination directory for the translet.
286N/A * The current working directory will be used by default.
286N/A */
286N/A public boolean setDestDirectory(String dstDirName) {
286N/A final File dir = new File(dstDirName);
524N/A if (SecuritySupport.getFileExists(dir) || dir.mkdirs()) {
286N/A _destDir = dir;
286N/A return true;
286N/A }
286N/A else {
286N/A _destDir = null;
286N/A return false;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Set an optional package name for the translet and auxiliary classes
286N/A */
286N/A public void setPackageName(String packageName) {
286N/A _packageName = packageName;
286N/A if (_className != null) setClassName(_className);
286N/A }
286N/A
286N/A /**
286N/A * Set the name of an optional JAR-file to dump the translet and
286N/A * auxiliary classes to
286N/A */
286N/A public void setJarFileName(String jarFileName) {
286N/A final String JAR_EXT = ".jar";
286N/A if (jarFileName.endsWith(JAR_EXT))
286N/A _jarFileName = jarFileName;
286N/A else
286N/A _jarFileName = jarFileName + JAR_EXT;
286N/A _outputType = JAR_OUTPUT;
286N/A }
286N/A
286N/A public String getJarFileName() {
286N/A return _jarFileName;
286N/A }
286N/A
286N/A /**
286N/A * Set the top-level stylesheet
286N/A */
286N/A public void setStylesheet(Stylesheet stylesheet) {
286N/A if (_stylesheet == null) _stylesheet = stylesheet;
286N/A }
286N/A
286N/A /**
286N/A * Returns the top-level stylesheet
286N/A */
286N/A public Stylesheet getStylesheet() {
286N/A return _stylesheet;
286N/A }
286N/A
286N/A /**
286N/A * Registers an attribute and gives it a type so that it can be mapped to
286N/A * DOM attribute types at run-time.
286N/A */
286N/A public int registerAttribute(QName name) {
286N/A Integer code = (Integer)_attributes.get(name.toString());
286N/A if (code == null) {
286N/A code = new Integer(_nextGType++);
286N/A _attributes.put(name.toString(), code);
286N/A final String uri = name.getNamespace();
286N/A final String local = "@"+name.getLocalPart();
286N/A if ((uri != null) && (!uri.equals("")))
286N/A _namesIndex.addElement(uri+":"+local);
286N/A else
286N/A _namesIndex.addElement(local);
286N/A if (name.getLocalPart().equals("*")) {
286N/A registerNamespace(name.getNamespace());
286N/A }
286N/A }
286N/A return code.intValue();
286N/A }
286N/A
286N/A /**
286N/A * Registers an element and gives it a type so that it can be mapped to
286N/A * DOM element types at run-time.
286N/A */
286N/A public int registerElement(QName name) {
286N/A // Register element (full QName)
286N/A Integer code = (Integer)_elements.get(name.toString());
286N/A if (code == null) {
286N/A _elements.put(name.toString(), code = new Integer(_nextGType++));
286N/A _namesIndex.addElement(name.toString());
286N/A }
286N/A if (name.getLocalPart().equals("*")) {
286N/A registerNamespace(name.getNamespace());
286N/A }
286N/A return code.intValue();
286N/A }
286N/A
286N/A /**
286N/A * Registers a namespace prefix and gives it a type so that it can be mapped to
286N/A * DOM namespace types at run-time.
286N/A */
286N/A
286N/A public int registerNamespacePrefix(QName name) {
286N/A
286N/A Integer code = (Integer)_namespacePrefixes.get(name.toString());
286N/A if (code == null) {
286N/A code = new Integer(_nextGType++);
286N/A _namespacePrefixes.put(name.toString(), code);
286N/A final String uri = name.getNamespace();
286N/A if ((uri != null) && (!uri.equals(""))){
286N/A // namespace::ext2:ped2 will be made empty in TypedNamespaceIterator
286N/A _namesIndex.addElement("?");
286N/A } else{
286N/A _namesIndex.addElement("?"+name.getLocalPart());
286N/A }
286N/A }
286N/A return code.intValue();
286N/A }
286N/A
286N/A /**
286N/A * Registers a namespace and gives it a type so that it can be mapped to
286N/A * DOM namespace types at run-time.
286N/A */
286N/A public int registerNamespace(String namespaceURI) {
286N/A Integer code = (Integer)_namespaces.get(namespaceURI);
286N/A if (code == null) {
286N/A code = new Integer(_nextNSType++);
286N/A _namespaces.put(namespaceURI,code);
286N/A _namespaceIndex.addElement(namespaceURI);
286N/A }
286N/A return code.intValue();
286N/A }
286N/A
286N/A public int nextModeSerial() {
286N/A return _modeSerial++;
286N/A }
286N/A
286N/A public int nextStylesheetSerial() {
286N/A return _stylesheetSerial++;
286N/A }
286N/A
286N/A public int nextStepPatternSerial() {
286N/A return _stepPatternSerial++;
286N/A }
286N/A
286N/A public int[] getNumberFieldIndexes() {
286N/A return _numberFieldIndexes;
286N/A }
286N/A
286N/A public int nextHelperClassSerial() {
286N/A return _helperClassSerial++;
286N/A }
286N/A
286N/A public int nextAttributeSetSerial() {
286N/A return _attributeSetSerial++;
286N/A }
286N/A
286N/A public Vector getNamesIndex() {
286N/A return _namesIndex;
286N/A }
286N/A
286N/A public Vector getNamespaceIndex() {
286N/A return _namespaceIndex;
286N/A }
286N/A
286N/A /**
286N/A * Returns a unique name for every helper class needed to
286N/A * execute a translet.
286N/A */
286N/A public String getHelperClassName() {
286N/A return getClassName() + '$' + _helperClassSerial++;
286N/A }
286N/A
286N/A public void dumpClass(JavaClass clazz) {
286N/A
286N/A if (_outputType == FILE_OUTPUT ||
286N/A _outputType == BYTEARRAY_AND_FILE_OUTPUT)
286N/A {
286N/A File outFile = getOutputFile(clazz.getClassName());
286N/A String parentDir = outFile.getParent();
286N/A if (parentDir != null) {
286N/A File parentFile = new File(parentDir);
524N/A if (!SecuritySupport.getFileExists(parentFile))
286N/A parentFile.mkdirs();
286N/A }
286N/A }
286N/A
286N/A try {
286N/A switch (_outputType) {
286N/A case FILE_OUTPUT:
286N/A clazz.dump(
286N/A new BufferedOutputStream(
286N/A new FileOutputStream(
286N/A getOutputFile(clazz.getClassName()))));
286N/A break;
286N/A case JAR_OUTPUT:
286N/A _bcelClasses.addElement(clazz);
286N/A break;
286N/A case BYTEARRAY_OUTPUT:
286N/A case BYTEARRAY_AND_FILE_OUTPUT:
286N/A case BYTEARRAY_AND_JAR_OUTPUT:
286N/A case CLASSLOADER_OUTPUT:
286N/A ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
286N/A clazz.dump(out);
286N/A _classes.addElement(out.toByteArray());
286N/A
286N/A if (_outputType == BYTEARRAY_AND_FILE_OUTPUT)
286N/A clazz.dump(new BufferedOutputStream(
286N/A new FileOutputStream(getOutputFile(clazz.getClassName()))));
286N/A else if (_outputType == BYTEARRAY_AND_JAR_OUTPUT)
286N/A _bcelClasses.addElement(clazz);
286N/A
286N/A break;
286N/A }
286N/A }
286N/A catch (Exception e) {
286N/A e.printStackTrace();
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * File separators are converted to forward slashes for ZIP files.
286N/A */
286N/A private String entryName(File f) throws IOException {
286N/A return f.getName().replace(File.separatorChar, '/');
286N/A }
286N/A
286N/A /**
286N/A * Generate output JAR-file and packages
286N/A */
286N/A public void outputToJar() throws IOException {
286N/A // create the manifest
286N/A final Manifest manifest = new Manifest();
286N/A final java.util.jar.Attributes atrs = manifest.getMainAttributes();
286N/A atrs.put(java.util.jar.Attributes.Name.MANIFEST_VERSION,"1.2");
286N/A
286N/A final Map map = manifest.getEntries();
286N/A // create manifest
286N/A Enumeration classes = _bcelClasses.elements();
286N/A final String now = (new Date()).toString();
286N/A final java.util.jar.Attributes.Name dateAttr =
286N/A new java.util.jar.Attributes.Name("Date");
286N/A while (classes.hasMoreElements()) {
286N/A final JavaClass clazz = (JavaClass)classes.nextElement();
286N/A final String className = clazz.getClassName().replace('.','/');
286N/A final java.util.jar.Attributes attr = new java.util.jar.Attributes();
286N/A attr.put(dateAttr, now);
286N/A map.put(className+".class", attr);
286N/A }
286N/A
286N/A final File jarFile = new File(_destDir, _jarFileName);
286N/A final JarOutputStream jos =
286N/A new JarOutputStream(new FileOutputStream(jarFile), manifest);
286N/A classes = _bcelClasses.elements();
286N/A while (classes.hasMoreElements()) {
286N/A final JavaClass clazz = (JavaClass)classes.nextElement();
286N/A final String className = clazz.getClassName().replace('.','/');
286N/A jos.putNextEntry(new JarEntry(className+".class"));
286N/A final ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
286N/A clazz.dump(out); // dump() closes it's output stream
286N/A out.writeTo(jos);
286N/A }
286N/A jos.close();
286N/A }
286N/A
286N/A /**
286N/A * Turn debugging messages on/off
286N/A */
286N/A public void setDebug(boolean debug) {
286N/A _debug = debug;
286N/A }
286N/A
286N/A /**
286N/A * Get current debugging message setting
286N/A */
286N/A public boolean debug() {
286N/A return _debug;
286N/A }
286N/A
286N/A
286N/A /**
286N/A * Retrieve a string representation of the character data to be stored
286N/A * in the translet as a <code>char[]</code>. There may be more than
286N/A * one such array required.
286N/A * @param index The index of the <code>char[]</code>. Zero-based.
286N/A * @return String The character data to be stored in the corresponding
286N/A * <code>char[]</code>.
286N/A */
286N/A public String getCharacterData(int index) {
286N/A return ((StringBuffer) m_characterData.elementAt(index)).toString();
286N/A }
286N/A
286N/A /**
286N/A * Get the number of char[] arrays, thus far, that will be created to
286N/A * store literal text in the stylesheet.
286N/A */
286N/A public int getCharacterDataCount() {
286N/A return (m_characterData != null) ? m_characterData.size() : 0;
286N/A }
286N/A
286N/A /**
286N/A * Add literal text to char arrays that will be used to store character
286N/A * data in the stylesheet.
286N/A * @param newData String data to be added to char arrays.
286N/A * Pre-condition: <code>newData.length() &le; 21845</code>
286N/A * @return int offset at which character data will be stored
286N/A */
286N/A public int addCharacterData(String newData) {
286N/A StringBuffer currData;
286N/A if (m_characterData == null) {
286N/A m_characterData = new Vector();
286N/A currData = new StringBuffer();
286N/A m_characterData.addElement(currData);
286N/A } else {
286N/A currData = (StringBuffer) m_characterData
286N/A .elementAt(m_characterData.size()-1);
286N/A }
286N/A
286N/A // Character data could take up to three-times as much space when
286N/A // written to the class file as UTF-8. The maximum size for a
286N/A // constant is 65535/3. If we exceed that,
286N/A // (We really should use some "bin packing".)
286N/A if (newData.length() + currData.length() > 21845) {
286N/A currData = new StringBuffer();
286N/A m_characterData.addElement(currData);
286N/A }
286N/A
286N/A int newDataOffset = currData.length();
286N/A currData.append(newData);
286N/A
286N/A return newDataOffset;
286N/A }
286N/A}