FileDocCategorySizeDatePackage
XSLTC.javaAPI DocJava SE 5 API27043Fri Aug 26 14:55:38 BST 2005com.sun.org.apache.xalan.internal.xsltc.compiler

XSLTC

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

Fields Summary
private Parser
_parser
private XMLReader
_reader
private SourceLoader
_loader
private Stylesheet
_stylesheet
private int
_modeSerial
private int
_stylesheetSerial
private int
_stepPatternSerial
private int
_helperClassSerial
private int
_attributeSetSerial
private int[]
_numberFieldIndexes
private int
_nextGType
private Vector
_namesIndex
private Hashtable
_elements
private Hashtable
_attributes
private int
_nextNSType
private Vector
_namespaceIndex
private Hashtable
_namespaces
private Hashtable
_namespacePrefixes
private Vector
m_characterData
public static final int
FILE_OUTPUT
public static final int
JAR_OUTPUT
public static final int
BYTEARRAY_OUTPUT
public static final int
CLASSLOADER_OUTPUT
public static final int
BYTEARRAY_AND_FILE_OUTPUT
public static final int
BYTEARRAY_AND_JAR_OUTPUT
private boolean
_debug
private String
_jarFileName
private String
_className
private String
_packageName
private File
_destDir
private int
_outputType
private Vector
_classes
private Vector
_bcelClasses
private boolean
_callsNodeset
private boolean
_multiDocument
private boolean
_hasIdCall
private boolean
_templateInlining
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.
Constructors Summary
public XSLTC()
XSLTC compiler constructor


            
      
	_parser = new Parser(this);
    
Methods Summary
public intaddCharacterData(java.lang.String newData)
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: newData.length() ≤ 21845
return
int offset at which character data will be stored

        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;
    
public booleancallsNodeset()

	return _callsNodeset;
    
private java.lang.StringclassFileName(java.lang.String className)
Convert for Java class name of local system file name. (Replace '.' with '/' on UNIX and replace '.' by '\' on Windows/DOS.)

	return className.replace('.", File.separatorChar) + ".class";
    
public booleancompile(java.net.URL url)
Compiles an XSL stylesheet pointed to by a URL

param
url An URL containing the input XSL stylesheet

	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(e));
	    return false;
	}
    
public booleancompile(java.net.URL url, java.lang.String name)
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

	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(e));
	    return false;
	}
    
public booleancompile(java.io.InputStream stream, java.lang.String name)
Compiles an XSL stylesheet passed in through an InputStream

param
input 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

	final InputSource input = new InputSource(stream);
	input.setSystemId(name); // We have nothing else!!!
	return compile(input, name);
    
public booleancompile(org.xml.sax.InputSource input, java.lang.String 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

	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(e));
	}
	catch (Error e) {
	    if (_debug) e.printStackTrace();
	    _parser.reportError(Constants.FATAL, new ErrorMsg(e));
	}
	finally {
	    _reader = null; // reset this here to be sure it is not re-used
	}
	return !_parser.errorsFound();
    
public booleancompile(java.util.Vector stylesheets)
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

	// 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;
    
public byte[][]compile(java.lang.String name, org.xml.sax.InputSource input, int outputType)
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

	_outputType = outputType;
	if (compile(input, name))
	    return getBytecodes();
	else
	    return null;
    
public byte[][]compile(java.lang.String name, org.xml.sax.InputSource input)
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

        return compile(name, input, BYTEARRAY_OUTPUT);
    
public booleandebug()
Get current debugging message setting

	return _debug;
    
public voiddumpClass(com.sun.org.apache.bcel.internal.classfile.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 (!parentFile.exists())
	            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();
	}
    
private java.lang.StringentryName(java.io.File f)
File separators are converted to forward slashes for ZIP files.

	return f.getName().replace(File.separatorChar, '/");
    
public byte[][]getBytecodes()
Returns an array of bytecode arrays generated by a compilation.

return
JVM bytecodes that represent translet class definition

	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;
    
public java.lang.StringgetCharacterData(int index)
Retrieve a string representation of the character data to be stored in the translet as a char[]. There may be more than one such array required.

param
index The index of the char[]. Zero-based.
return
String The character data to be stored in the corresponding char[].

        return ((StringBuffer) m_characterData.elementAt(index)).toString();
    
public intgetCharacterDataCount()
Get the number of char[] arrays, thus far, that will be created to store literal text in the stylesheet.

        return (m_characterData != null) ? m_characterData.size() : 0;
    
public java.lang.StringgetClassName()
Get the class name for the generated translet.

	return _className;
    
public java.util.VectorgetErrors()
Get a Vector containing all compile error messages

return
A Vector containing all compile error messages

	return _parser.getErrors();
    
public java.lang.StringgetHelperClassName()
Returns a unique name for every helper class needed to execute a translet.

	return getClassName() + '$" + _helperClassSerial++;
    
public java.lang.StringgetJarFileName()

	return _jarFileName;
    
public java.util.VectorgetNamesIndex()

	return _namesIndex;
    
public java.util.VectorgetNamespaceIndex()

	return _namespaceIndex;
    
public int[]getNumberFieldIndexes()

	return _numberFieldIndexes;
    
private java.io.FilegetOutputFile(java.lang.String className)
Generate an output File object to send the translet to

	if (_destDir != null)
	    return new File(_destDir, classFileName(className));
	else
	    return new File(classFileName(className));
    
public java.util.PropertiesgetOutputProperties()
Only for user by the internal TrAX implementation.

	return _parser.getOutputProperties();
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.ParsergetParser()
Only for user by the internal TrAX implementation.

        return _parser;
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.StylesheetgetStylesheet()
Returns the top-level stylesheet

	return _stylesheet;
    
public java.util.VectorgetWarnings()
Get a Vector containing all compile warning messages

return
A Vector containing all compile error messages

	return _parser.getWarnings();
    
public org.xml.sax.XMLReadergetXMLReader()
Get the XMLReader to use for parsing the next input stylesheet

	return _reader ;
    
public booleanhasIdCall()

    	return _hasIdCall;
    
public voidinit()
Initializes the compiler to compile a new stylesheet

	reset();
	_reader = null;
	_classes = new Vector();
	_bcelClasses = new Vector();
    
public booleanisMultiDocument()

	return _multiDocument;
    
public intnextAttributeSetSerial()

	return _attributeSetSerial++;
    
public intnextHelperClassSerial()

	return _helperClassSerial++;
    
public intnextModeSerial()

	return _modeSerial++;
    
public intnextStepPatternSerial()

	return _stepPatternSerial++;
    
public intnextStylesheetSerial()

	return _stylesheetSerial++;
    
public voidoutputToJar()
Generate output JAR-file and packages

	// 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();
    
public voidprintErrors()
Print all compile error messages to standard output

	_parser.printErrors();
    
public voidprintWarnings()
Print all compile warning messages to standard output

	_parser.printWarnings();
    
public intregisterAttribute(com.sun.org.apache.xalan.internal.xsltc.compiler.QName name)
Registers an attribute and gives it a type so that it can be mapped to DOM attribute types at run-time.

	Integer code = (Integer)_attributes.get(name.toString());
	if (code == null) {
	    code = new Integer(_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();
    
public intregisterElement(com.sun.org.apache.xalan.internal.xsltc.compiler.QName name)
Registers an element and gives it a type so that it can be mapped to DOM element types at run-time.

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

	Integer code = (Integer)_namespaces.get(namespaceURI);
	if (code == null) {
	    code = new Integer(_nextNSType++);
	    _namespaces.put(namespaceURI,code);
	    _namespaceIndex.addElement(namespaceURI);
	}
	return code.intValue();
    
public intregisterNamespacePrefix(com.sun.org.apache.xalan.internal.xsltc.compiler.QName name)
Registers a namespace prefix and gives it a type so that it can be mapped to DOM namespace types at run-time.

    
    Integer code = (Integer)_namespacePrefixes.get(name.toString());
    if (code == null) {   
        code = new Integer(_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();
    
private voidreset()
Initializes the compiler to produce a new translet

	_nextGType      = DTM.NTYPES;
	_elements       = new Hashtable();
	_attributes     = new Hashtable();
	_namespaces     = new Hashtable();
	_namespaces.put("",new Integer(_nextNSType));
	_namesIndex     = new Vector(128);
	_namespaceIndex = new Vector(32);
	_namespacePrefixes = new Hashtable();
        _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
	};
    
protected voidsetCallsNodeset(boolean flag)
This method is called by the XPathParser when it encounters a call to the nodeset() extension function. Implies multi document.

	if (flag) setMultiDocument(flag);
	_callsNodeset = flag;
    
public voidsetClassName(java.lang.String className)
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

	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;
    
public voidsetDebug(boolean debug)
Turn debugging messages on/off

	_debug = debug;
    
public booleansetDestDirectory(java.lang.String dstDirName)
Set the destination directory for the translet. The current working directory will be used by default.

	final File dir = new File(dstDirName);
	if (dir.exists() || dir.mkdirs()) {
	    _destDir = dir;
	    return true;
	}
	else {
	    _destDir = null;
	    return false;
	}
    
protected voidsetHasIdCall(boolean flag)

    	_hasIdCall = flag;
    
public voidsetJarFileName(java.lang.String jarFileName)
Set the name of an optional JAR-file to dump the translet and auxiliary classes to

	final String JAR_EXT = ".jar";
	if (jarFileName.endsWith(JAR_EXT))
	    _jarFileName = jarFileName;
	else
	    _jarFileName = jarFileName + JAR_EXT;
	_outputType = JAR_OUTPUT;
    
protected voidsetMultiDocument(boolean flag)
This method is called by the XPathParser when it encounters a call to the document() function. Affects the DOM used by the translet.

	_multiDocument = flag;
    
public voidsetOutputType(int type)
Only for user by the internal TrAX implementation.

	_outputType = type;
    
public voidsetPIParameters(java.lang.String media, java.lang.String title, java.lang.String charset)
Set the parameters to use to locate the correct 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.

	_parser.setPIParameters(media, title, charset);
    
public voidsetPackageName(java.lang.String packageName)
Set an optional package name for the translet and auxiliary classes

	_packageName = packageName;
	if (_className != null) setClassName(_className);
    
public voidsetSourceLoader(com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader loader)
Defines an external SourceLoader to provide the compiler with documents referenced in xsl:include/import

param
loader The SourceLoader to use for include/import

	_loader = loader;
    
public voidsetStylesheet(com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet stylesheet)
Set the top-level stylesheet

	if (_stylesheet == null) _stylesheet = stylesheet;
    
public voidsetTemplateInlining(boolean templateInlining)
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).

	_templateInlining = templateInlining;
    
public voidsetXMLReader(org.xml.sax.XMLReader reader)
Set the XMLReader to use for parsing the next input stylesheet

param
reader XMLReader (SAX2 parser) to use

	_reader = reader;