You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by ff...@apache.org on 2014/09/03 08:09:51 UTC

svn commit: r1622167 - in /servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc: compiler/FunctionCall.java runtime/AbstractTranslet.java trax/TemplatesImpl.java

Author: ffang
Date: Wed Sep  3 06:09:50 2014
New Revision: 1622167

URL: http://svn.apache.org/r1622167
Log:
[SMX4-1815]add more TCCL as fallback classloader

Added:
    servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/compiler/FunctionCall.java
    servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
    servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/trax/TemplatesImpl.java

Added: servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/compiler/FunctionCall.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/compiler/FunctionCall.java?rev=1622167&view=auto
==============================================================================
--- servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/compiler/FunctionCall.java (added)
+++ servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/compiler/FunctionCall.java Wed Sep  3 06:09:50 2014
@@ -0,0 +1,1093 @@
+/*
+ * 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.
+ */
+/*
+ * $Id: FunctionCall.java 468650 2006-10-28 07:03:30Z minchau $
+ */
+
+package org.apache.xalan.xsltc.compiler;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.IFEQ;
+import org.apache.bcel.generic.INVOKEINTERFACE;
+import org.apache.bcel.generic.INVOKESPECIAL;
+import org.apache.bcel.generic.INVOKESTATIC;
+import org.apache.bcel.generic.INVOKEVIRTUAL;
+import org.apache.bcel.generic.InstructionConstants;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.InvokeInstruction;
+import org.apache.bcel.generic.LocalVariableGen;
+import org.apache.bcel.generic.NEW;
+import org.apache.bcel.generic.PUSH;
+import org.apache.xalan.xsltc.compiler.util.BooleanType;
+import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
+import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
+import org.apache.xalan.xsltc.compiler.util.IntType;
+import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
+import org.apache.xalan.xsltc.compiler.util.MethodType;
+import org.apache.xalan.xsltc.compiler.util.MultiHashtable;
+import org.apache.xalan.xsltc.compiler.util.ObjectType;
+import org.apache.xalan.xsltc.compiler.util.ReferenceType;
+import org.apache.xalan.xsltc.compiler.util.Type;
+import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
+
+/**
+ * @author Jacek Ambroziak
+ * @author Santiago Pericas-Geertsen
+ * @author Morten Jorgensen
+ * @author Erwin Bolwidt <ej...@klomp.org>
+ * @author Todd Miller
+ */
+class FunctionCall extends Expression {
+
+    // Name of this function call
+    private QName  _fname;
+    // Arguments to this function call (might not be any)
+    private final Vector _arguments;
+    // Empty argument list, used for certain functions
+    private final static Vector EMPTY_ARG_LIST = new Vector(0);
+
+    // Valid namespaces for Java function-call extension
+    protected final static String EXT_XSLTC = 
+	TRANSLET_URI;
+
+    protected final static String JAVA_EXT_XSLTC = 
+	EXT_XSLTC + "/java";
+
+    protected final static String EXT_XALAN =
+	"http://xml.apache.org/xalan";
+
+    protected final static String JAVA_EXT_XALAN =
+	"http://xml.apache.org/xalan/java";
+
+    protected final static String JAVA_EXT_XALAN_OLD =
+	"http://xml.apache.org/xslt/java";
+	
+    protected final static String EXSLT_COMMON =
+	"http://exslt.org/common";
+
+    protected final static String EXSLT_MATH =
+	"http://exslt.org/math";
+	
+    protected final static String EXSLT_SETS =
+	"http://exslt.org/sets";
+
+    protected final static String EXSLT_DATETIME =
+	"http://exslt.org/dates-and-times";
+
+    protected final static String EXSLT_STRINGS =
+	"http://exslt.org/strings";
+	
+    // Namespace format constants
+    protected final static int NAMESPACE_FORMAT_JAVA = 0;
+    protected final static int NAMESPACE_FORMAT_CLASS = 1;
+    protected final static int NAMESPACE_FORMAT_PACKAGE = 2;
+    protected final static int NAMESPACE_FORMAT_CLASS_OR_PACKAGE = 3;
+	
+    // Namespace format
+    private int _namespace_format = NAMESPACE_FORMAT_JAVA;
+        
+    /**
+     * Stores reference to object for non-static Java calls
+     */
+    Expression _thisArgument = null;
+
+    // External Java function's class/method/signature
+    private String      _className;
+    private Class       _clazz;
+    private Method      _chosenMethod;
+    private Constructor _chosenConstructor;
+    private MethodType  _chosenMethodType;
+
+    // Encapsulates all unsupported external function calls
+    private boolean    unresolvedExternal;
+
+    // If FunctionCall is a external java constructor 
+    private boolean     _isExtConstructor = false; 
+
+    // If the java method is static
+    private boolean 	  _isStatic = false;
+
+    // Legal conversions between internal and Java types.
+    private static final MultiHashtable _internal2Java = new MultiHashtable();
+
+    // Legal conversions between Java and internal types.
+    private static final Hashtable _java2Internal = new Hashtable();
+    
+    // The mappings between EXSLT extension namespaces and implementation classes
+    private static final Hashtable _extensionNamespaceTable = new Hashtable();
+
+    // Extension functions that are implemented in BasisLibrary
+    private static final Hashtable _extensionFunctionTable = new Hashtable();
+    /**
+     * inner class to used in internal2Java mappings, contains
+     * the Java type and the distance between the internal type and
+     * the Java type. 
+     */
+    static class JavaType {
+	public Class  type;
+	public int distance;
+	
+	public JavaType(Class type, int distance){
+	    this.type = type;
+	    this.distance = distance;
+	}
+	public boolean equals(Object query){
+	    return query.equals(type);
+	}
+    } 
+
+    /**
+     * Defines 2 conversion tables:
+     * 1. From internal types to Java types and
+     * 2. From Java types to internal types.
+     * These two tables are used when calling external (Java) functions.
+     */
+    static {
+	try {
+	    final Class nodeClass     = Class.forName("org.w3c.dom.Node");
+	    final Class nodeListClass = Class.forName("org.w3c.dom.NodeList");
+
+	    // -- Internal to Java --------------------------------------------
+            
+            // Type.Boolean -> { boolean(0), Boolean(1), Object(2) }
+	    _internal2Java.put(Type.Boolean, new JavaType(Boolean.TYPE, 0));
+	    _internal2Java.put(Type.Boolean, new JavaType(Boolean.class, 1));
+	    _internal2Java.put(Type.Boolean, new JavaType(Object.class, 2));
+
+            // Type.Real -> { double(0), Double(1), float(2), long(3), int(4),
+            //                short(5), byte(6), char(7), Object(8) }
+	    _internal2Java.put(Type.Real, new JavaType(Double.TYPE, 0));
+	    _internal2Java.put(Type.Real, new JavaType(Double.class, 1));
+	    _internal2Java.put(Type.Real, new JavaType(Float.TYPE, 2));
+	    _internal2Java.put(Type.Real, new JavaType(Long.TYPE, 3));
+	    _internal2Java.put(Type.Real, new JavaType(Integer.TYPE, 4));
+	    _internal2Java.put(Type.Real, new JavaType(Short.TYPE, 5));
+	    _internal2Java.put(Type.Real, new JavaType(Byte.TYPE, 6));
+	    _internal2Java.put(Type.Real, new JavaType(Character.TYPE, 7)); 
+	    _internal2Java.put(Type.Real, new JavaType(Object.class, 8));
+            
+            // Type.Int must be the same as Type.Real
+	    _internal2Java.put(Type.Int, new JavaType(Double.TYPE, 0));
+	    _internal2Java.put(Type.Int, new JavaType(Double.class, 1));
+	    _internal2Java.put(Type.Int, new JavaType(Float.TYPE, 2));
+	    _internal2Java.put(Type.Int, new JavaType(Long.TYPE, 3));
+	    _internal2Java.put(Type.Int, new JavaType(Integer.TYPE, 4));
+	    _internal2Java.put(Type.Int, new JavaType(Short.TYPE, 5));
+	    _internal2Java.put(Type.Int, new JavaType(Byte.TYPE, 6));
+	    _internal2Java.put(Type.Int, new JavaType(Character.TYPE, 7)); 
+	    _internal2Java.put(Type.Int, new JavaType(Object.class, 8));
+            
+            // Type.String -> { String(0), Object(1) }
+	    _internal2Java.put(Type.String, new JavaType(String.class, 0)); 
+	    _internal2Java.put(Type.String, new JavaType(Object.class, 1));
+
+            // Type.NodeSet -> { NodeList(0), Node(1), Object(2), String(3) }
+	    _internal2Java.put(Type.NodeSet, new JavaType(nodeListClass, 0)); 
+	    _internal2Java.put(Type.NodeSet, new JavaType(nodeClass, 1)); 
+	    _internal2Java.put(Type.NodeSet, new JavaType(Object.class, 2));
+	    _internal2Java.put(Type.NodeSet, new JavaType(String.class, 3)); 
+
+            // Type.Node -> { Node(0), NodeList(1), Object(2), String(3) }
+	    _internal2Java.put(Type.Node, new JavaType(nodeListClass, 0));
+	    _internal2Java.put(Type.Node, new JavaType(nodeClass, 1));  
+	    _internal2Java.put(Type.Node, new JavaType(Object.class, 2));
+	    _internal2Java.put(Type.Node, new JavaType(String.class, 3));
+
+            // Type.ResultTree -> { NodeList(0), Node(1), Object(2), String(3) }
+	    _internal2Java.put(Type.ResultTree, new JavaType(nodeListClass, 0));
+	    _internal2Java.put(Type.ResultTree, new JavaType(nodeClass, 1)); 
+	    _internal2Java.put(Type.ResultTree, new JavaType(Object.class, 2));
+	    _internal2Java.put(Type.ResultTree, new JavaType(String.class, 3));
+
+	    _internal2Java.put(Type.Reference, new JavaType(Object.class, 0));
+
+	    // Possible conversions between Java and internal types
+	    _java2Internal.put(Boolean.TYPE, Type.Boolean); 
+	    _java2Internal.put(Void.TYPE, Type.Void);
+	    _java2Internal.put(Character.TYPE, Type.Real); 
+	    _java2Internal.put(Byte.TYPE, Type.Real);
+	    _java2Internal.put(Short.TYPE, Type.Real);
+	    _java2Internal.put(Integer.TYPE, Type.Real);
+	    _java2Internal.put(Long.TYPE, Type.Real);
+	    _java2Internal.put(Float.TYPE, Type.Real);
+	    _java2Internal.put(Double.TYPE, Type.Real);
+
+	    _java2Internal.put(String.class, Type.String);
+
+	    _java2Internal.put(Object.class, Type.Reference);
+
+	    // Conversions from org.w3c.dom.Node/NodeList to internal NodeSet
+	    _java2Internal.put(nodeListClass, Type.NodeSet);
+	    _java2Internal.put(nodeClass, Type.NodeSet);
+	    
+	    // Initialize the extension namespace table
+	    _extensionNamespaceTable.put(EXT_XALAN, "org.apache.xalan.lib.Extensions");
+	    _extensionNamespaceTable.put(EXSLT_COMMON, "org.apache.xalan.lib.ExsltCommon");
+	    _extensionNamespaceTable.put(EXSLT_MATH, "org.apache.xalan.lib.ExsltMath");
+	    _extensionNamespaceTable.put(EXSLT_SETS, "org.apache.xalan.lib.ExsltSets");
+	    _extensionNamespaceTable.put(EXSLT_DATETIME, "org.apache.xalan.lib.ExsltDatetime");
+	    _extensionNamespaceTable.put(EXSLT_STRINGS, "org.apache.xalan.lib.ExsltStrings");
+	    
+	    // Initialize the extension function table
+	    _extensionFunctionTable.put(EXSLT_COMMON + ":nodeSet", "nodeset");
+	    _extensionFunctionTable.put(EXSLT_COMMON + ":objectType", "objectType");	    
+	    _extensionFunctionTable.put(EXT_XALAN + ":nodeset", "nodeset");
+	}
+	catch (ClassNotFoundException e) {
+	    System.err.println(e);
+	}
+    }
+		
+    public FunctionCall(QName fname, Vector arguments) {
+	_fname = fname;
+	_arguments = arguments;
+	_type = null;
+    }
+
+    public FunctionCall(QName fname) {
+	this(fname, EMPTY_ARG_LIST);
+    }
+
+    public String getName() {
+	return(_fname.toString());
+    }
+
+    public void setParser(Parser parser) {
+	super.setParser(parser);
+	if (_arguments != null) {
+	    final int n = _arguments.size();
+	    for (int i = 0; i < n; i++) {
+		final Expression exp = (Expression)_arguments.elementAt(i);
+		exp.setParser(parser);
+		exp.setParent(this);
+	    }
+	}
+    }
+
+    public String getClassNameFromUri(String uri) 
+    {   
+        String className = (String)_extensionNamespaceTable.get(uri);
+    
+        if (className != null)
+            return className;
+        else {
+            if (uri.startsWith(JAVA_EXT_XSLTC)) {
+      	    	int length = JAVA_EXT_XSLTC.length() + 1;
+            	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
+            }
+            else if (uri.startsWith(JAVA_EXT_XALAN)) {
+      	    	int length = JAVA_EXT_XALAN.length() + 1;
+            	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
+            }
+            else if (uri.startsWith(JAVA_EXT_XALAN_OLD)) {
+      	    	int length = JAVA_EXT_XALAN_OLD.length() + 1;
+            	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
+            }
+            else {
+      	    	int index = uri.lastIndexOf('/');
+      	    	return (index > 0) ? uri.substring(index+1) : uri;
+            }      
+        }
+    }
+
+    /**
+     * Type check a function call. Since different type conversions apply,
+     * type checking is different for standard and external (Java) functions.
+     */
+    public Type typeCheck(SymbolTable stable) 
+	throws TypeCheckError 
+    {
+        if (_type != null) return _type;
+
+	final String namespace = _fname.getNamespace();
+	String local = _fname.getLocalPart();
+
+	if (isExtension()) {
+	    _fname = new QName(null, null, local);
+	    return typeCheckStandard(stable);
+	}
+	else if (isStandard()) {
+	    return typeCheckStandard(stable);
+	}
+	// Handle extension functions (they all have a namespace)
+	else {
+	    try {
+	    	_className = getClassNameFromUri(namespace);
+		  
+                final int pos = local.lastIndexOf('.');
+		if (pos > 0) {
+		    _isStatic = true;
+		    if (_className != null && _className.length() > 0) {
+		    	_namespace_format = NAMESPACE_FORMAT_PACKAGE;
+		     	_className = _className + "." + local.substring(0, pos);
+		    }
+		    else {
+		     	_namespace_format = NAMESPACE_FORMAT_JAVA;
+		     	_className = local.substring(0, pos);
+		    }
+			  
+		    _fname = new QName(namespace, null, local.substring(pos + 1));
+		}
+		else {
+		    if (_className != null && _className.length() > 0) {
+		    	try {
+                            _clazz = ObjectFactory.findProviderClass(
+                                _className, ObjectFactory.findClassLoader(), true);
+		            _namespace_format = NAMESPACE_FORMAT_CLASS;
+		    	}
+		    	catch (ClassNotFoundException e) {
+		      	    _namespace_format = NAMESPACE_FORMAT_PACKAGE;	
+		        }
+		    }
+		    else
+	            	_namespace_format = NAMESPACE_FORMAT_JAVA;
+			
+		    if (local.indexOf('-') > 0) {
+		        local = replaceDash(local);
+		    }
+		    
+		    String extFunction = (String)_extensionFunctionTable.get(namespace + ":" + local);
+		    if (extFunction != null) {
+		      	_fname = new QName(null, null, extFunction);
+		      	return typeCheckStandard(stable);
+		    }
+		    else
+		      	_fname = new QName(namespace, null, local);
+		}
+		  
+		return typeCheckExternal(stable);
+	    } 
+	    catch (TypeCheckError e) {
+		ErrorMsg errorMsg = e.getErrorMsg();
+		if (errorMsg == null) {
+		    final String name = _fname.getLocalPart();
+		    errorMsg = new ErrorMsg(ErrorMsg.METHOD_NOT_FOUND_ERR, name);
+		}
+		getParser().reportError(ERROR, errorMsg);
+		return _type = Type.Void;
+	    }
+	  }
+    }
+
+    /**
+     * Type check a call to a standard function. Insert CastExprs when needed.
+     * If as a result of the insertion of a CastExpr a type check error is 
+     * thrown, then catch it and re-throw it with a new "this".
+     */
+    public Type typeCheckStandard(SymbolTable stable) throws TypeCheckError {
+	_fname.clearNamespace(); 	// HACK!!!
+
+	final int n = _arguments.size();
+	final Vector argsType = typeCheckArgs(stable);
+	final MethodType args = new MethodType(Type.Void, argsType);
+	final MethodType ptype =
+	    lookupPrimop(stable, _fname.getLocalPart(), args);
+
+	if (ptype != null) {
+	    for (int i = 0; i < n; i++) {
+		final Type argType = (Type) ptype.argsType().elementAt(i);
+		final Expression exp = (Expression)_arguments.elementAt(i);
+		if (!argType.identicalTo(exp.getType())) {
+		    try {
+			_arguments.setElementAt(new CastExpr(exp, argType), i);
+		    }
+		    catch (TypeCheckError e) {
+			throw new TypeCheckError(this);	// invalid conversion
+		    }
+		}
+	    }
+	    _chosenMethodType = ptype;
+	    return _type = ptype.resultType();
+	}
+	throw new TypeCheckError(this);
+    }
+
+   
+
+    public Type typeCheckConstructor(SymbolTable stable) throws TypeCheckError{
+        final Vector constructors = findConstructors();
+	if (constructors == null) {
+            // Constructor not found in this class
+            throw new TypeCheckError(ErrorMsg.CONSTRUCTOR_NOT_FOUND, 
+		_className);
+        
+	}
+
+	final int nConstructors = constructors.size();
+	final int nArgs = _arguments.size();
+	final Vector argsType = typeCheckArgs(stable);
+
+	// Try all constructors 
+	int bestConstrDistance = Integer.MAX_VALUE;
+	_type = null;			// reset
+	for (int j, i = 0; i < nConstructors; i++) {
+	    // Check if all parameters to this constructor can be converted
+	    final Constructor constructor = 
+		(Constructor)constructors.elementAt(i);
+	    final Class[] paramTypes = constructor.getParameterTypes();
+
+	    Class extType = null;
+	    int currConstrDistance = 0;
+	    for (j = 0; j < nArgs; j++) {
+		// Convert from internal (translet) type to external (Java) type
+		extType = paramTypes[j];
+		final Type intType = (Type)argsType.elementAt(j);
+		Object match = _internal2Java.maps(intType, extType);
+		if (match != null) {
+		    currConstrDistance += ((JavaType)match).distance;
+		}
+		else if (intType instanceof ObjectType) {
+		    ObjectType objectType = (ObjectType)intType;
+		    if (objectType.getJavaClass() == extType)
+		        continue;
+		    else if (extType.isAssignableFrom(objectType.getJavaClass()))
+		        currConstrDistance += 1;
+		    else {
+			currConstrDistance = Integer.MAX_VALUE;
+			break;
+		    }
+		}
+		else {
+		    // no mapping available
+		    currConstrDistance = Integer.MAX_VALUE;
+		    break;
+		} 
+	    }
+
+	    if (j == nArgs && currConstrDistance < bestConstrDistance ) {
+	        _chosenConstructor = constructor;
+	        _isExtConstructor = true;
+		bestConstrDistance = currConstrDistance;
+		
+                _type = (_clazz != null) ? Type.newObjectType(_clazz)
+                    : Type.newObjectType(_className);
+	    }
+	}
+
+	if (_type != null) {
+	    return _type;
+	}
+
+	throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType));
+    }
+
+
+    /**
+     * Type check a call to an external (Java) method.
+     * The method must be static an public, and a legal type conversion
+     * must exist for all its arguments and its return type.
+     * Every method of name <code>_fname</code> is inspected
+     * as a possible candidate.
+     */
+    public Type typeCheckExternal(SymbolTable stable) throws TypeCheckError {
+	int nArgs = _arguments.size();
+	final String name = _fname.getLocalPart();
+    
+ 	// check if function is a contructor 'new'
+	if (_fname.getLocalPart().equals("new")) {
+	    return typeCheckConstructor(stable);
+	}
+	// check if we are calling an instance method
+	else {
+	    boolean hasThisArgument = false;
+	  
+	    if (nArgs == 0)
+	        _isStatic = true;
+	  
+	    if (!_isStatic) {
+	        if (_namespace_format == NAMESPACE_FORMAT_JAVA
+	  	    || _namespace_format == NAMESPACE_FORMAT_PACKAGE)
+	   	    hasThisArgument = true;
+	  	  
+	  	Expression firstArg = (Expression)_arguments.elementAt(0);
+	  	Type firstArgType = (Type)firstArg.typeCheck(stable);
+	  	
+	  	if (_namespace_format == NAMESPACE_FORMAT_CLASS
+	  	    && firstArgType instanceof ObjectType
+	  	    && _clazz != null
+	  	    && _clazz.isAssignableFrom(((ObjectType)firstArgType).getJavaClass()))
+	  	    hasThisArgument = true;
+	  	
+	  	if (hasThisArgument) {
+	  	    _thisArgument = (Expression) _arguments.elementAt(0);
+	  	    _arguments.remove(0); nArgs--;
+		    if (firstArgType instanceof ObjectType) {
+		    	_className = ((ObjectType) firstArgType).getJavaClassName();
+		    }
+		    else
+		    	throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, name);  	  	
+	  	}
+	    }
+	    else if (_className.length() == 0) {
+		/*
+		 * Warn user if external function could not be resolved.
+		 * Warning will _NOT_ be issued is the call is properly
+		 * wrapped in an <xsl:if> or <xsl:when> element. For details
+		 * see If.parserContents() and When.parserContents()
+		 */
+		final Parser parser = getParser();
+		if (parser != null) {
+		    reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR,
+				  _fname.toString());
+		}
+		unresolvedExternal = true;
+		return _type = Type.Int;	// use "Int" as "unknown"
+	    }
+	}
+	
+	final Vector methods = findMethods();
+	
+	if (methods == null) {
+	    // Method not found in this class
+	    throw new TypeCheckError(ErrorMsg.METHOD_NOT_FOUND_ERR, _className + "." + name);
+	}
+
+	Class extType = null;
+	final int nMethods = methods.size();
+	final Vector argsType = typeCheckArgs(stable);
+
+	// Try all methods to identify the best fit 
+	int bestMethodDistance  = Integer.MAX_VALUE;
+	_type = null;                       // reset internal type 
+	for (int j, i = 0; i < nMethods; i++) {
+	    // Check if all paramteters to this method can be converted
+	    final Method method = (Method)methods.elementAt(i);
+	    final Class[] paramTypes = method.getParameterTypes();
+	    
+	    int currMethodDistance = 0;
+	    for (j = 0; j < nArgs; j++) {
+		// Convert from internal (translet) type to external (Java) type
+		extType = paramTypes[j];
+		final Type intType = (Type)argsType.elementAt(j);
+		Object match = _internal2Java.maps(intType, extType);
+		if (match != null) {
+		    currMethodDistance += ((JavaType)match).distance; 
+		}
+		else {
+		    // no mapping available
+		    //
+		    // Allow a Reference type to match any external (Java) type at
+		    // the moment. The real type checking is performed at runtime.
+		    if (intType instanceof ReferenceType) {
+		       currMethodDistance += 1; 
+		    }
+		    else if (intType instanceof ObjectType) {
+		        ObjectType object = (ObjectType)intType;
+		        if (extType.getName().equals(object.getJavaClassName()))
+		            currMethodDistance += 0;
+		      	else if (extType.isAssignableFrom(object.getJavaClass()))
+		            currMethodDistance += 1;
+		      	else {
+		      	    currMethodDistance = Integer.MAX_VALUE;
+		      	    break;
+		        }
+		    }
+		    else {
+		        currMethodDistance = Integer.MAX_VALUE;
+		        break;
+		    }
+		}
+	    }
+
+	    if (j == nArgs) {
+		  // Check if the return type can be converted
+		  extType = method.getReturnType();
+		
+		  _type = (Type) _java2Internal.get(extType);
+		  if (_type == null) {
+		      _type = Type.newObjectType(extType);
+		  }		
+
+		  // Use this method if all parameters & return type match
+		  if (_type != null && currMethodDistance < bestMethodDistance) {
+		      _chosenMethod = method;
+		      bestMethodDistance = currMethodDistance;
+		  }
+	    }
+	}
+	
+	// It is an error if the chosen method is an instance menthod but we don't
+	// have a this argument.
+	if (_chosenMethod != null && _thisArgument == null &&
+	    !Modifier.isStatic(_chosenMethod.getModifiers())) {
+	    throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, getMethodSignature(argsType));
+	}
+
+	if (_type != null) {
+	    if (_type == Type.NodeSet) {
+            	getXSLTC().setMultiDocument(true);
+            }
+	    return _type;
+	}
+
+	throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType));
+    }
+
+    /**
+     * Type check the actual arguments of this function call.
+     */
+    public Vector typeCheckArgs(SymbolTable stable) throws TypeCheckError {
+	final Vector result = new Vector();
+	final Enumeration e = _arguments.elements();	
+	while (e.hasMoreElements()) {
+	    final Expression exp = (Expression)e.nextElement();
+	    result.addElement(exp.typeCheck(stable));
+	}
+	return result;
+    }
+
+    protected final Expression argument(int i) {
+	return (Expression)_arguments.elementAt(i);
+    }
+
+    protected final Expression argument() {
+	return argument(0);
+    }
+    
+    protected final int argumentCount() {
+	return _arguments.size();
+    }
+
+    protected final void setArgument(int i, Expression exp) {
+	_arguments.setElementAt(exp, i);
+    }
+
+    /**
+     * Compile the function call and treat as an expression
+     * Update true/false-lists.
+     */
+    public void translateDesynthesized(ClassGenerator classGen,
+				       MethodGenerator methodGen) 
+    {
+	Type type = Type.Boolean;
+	if (_chosenMethodType != null)
+	    type = _chosenMethodType.resultType();
+
+	final InstructionList il = methodGen.getInstructionList();
+	translate(classGen, methodGen);
+
+	if ((type instanceof BooleanType) || (type instanceof IntType)) {
+	    _falseList.add(il.append(new IFEQ(null)));
+	}
+    }
+
+
+    /**
+     * Translate a function call. The compiled code will leave the function's
+     * return value on the JVM's stack.
+     */
+    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+	final int n = argumentCount();
+	final ConstantPoolGen cpg = classGen.getConstantPool();
+	final InstructionList il = methodGen.getInstructionList();
+	final boolean isSecureProcessing = classGen.getParser().getXSLTC().isSecureProcessing();
+	int index;
+
+	// Translate calls to methods in the BasisLibrary
+	if (isStandard() || isExtension()) {
+	    for (int i = 0; i < n; i++) {
+		final Expression exp = argument(i);
+		exp.translate(classGen, methodGen);
+		exp.startIterator(classGen, methodGen);
+	    }
+
+	    // append "F" to the function's name
+	    final String name = _fname.toString().replace('-', '_') + "F";
+	    String args = Constants.EMPTYSTRING;
+
+	    // Special precautions for some method calls
+	    if (name.equals("sumF")) {
+		args = DOM_INTF_SIG;
+		il.append(methodGen.loadDOM());
+	    }
+	    else if (name.equals("normalize_spaceF")) {
+		if (_chosenMethodType.toSignature(args).
+		    equals("()Ljava/lang/String;")) {
+		    args = "I"+DOM_INTF_SIG;
+		    il.append(methodGen.loadContextNode());
+		    il.append(methodGen.loadDOM());
+		}
+	    }
+
+	    // Invoke the method in the basis library
+	    index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name,
+				     _chosenMethodType.toSignature(args));
+	    il.append(new INVOKESTATIC(index));
+	}
+	// Add call to BasisLibrary.unresolved_externalF() to generate
+	// run-time error message for unsupported external functions
+	else if (unresolvedExternal) {
+	    index = cpg.addMethodref(BASIS_LIBRARY_CLASS,
+				     "unresolved_externalF",
+				     "(Ljava/lang/String;)V");
+	    il.append(new PUSH(cpg, _fname.toString()));
+	    il.append(new INVOKESTATIC(index));
+	}
+	else if (_isExtConstructor) {
+	    if (isSecureProcessing)
+	        translateUnallowedExtension(cpg, il);
+	    
+	    final String clazz = 
+		_chosenConstructor.getDeclaringClass().getName();
+	    Class[] paramTypes = _chosenConstructor.getParameterTypes();
+            LocalVariableGen[] paramTemp = new LocalVariableGen[n];
+
+            // Backwards branches are prohibited if an uninitialized object is
+            // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed.
+            // We don't know whether this code might contain backwards branches
+            // so we mustn't create the new object until after we've created
+            // the suspect arguments to its constructor.  Instead we calculate
+            // the values of the arguments to the constructor first, store them
+            // in temporary variables, create the object and reload the
+            // arguments from the temporaries to avoid the problem.
+
+	    for (int i = 0; i < n; i++) {
+		final Expression exp = argument(i);
+                Type expType = exp.getType();
+		exp.translate(classGen, methodGen);
+		// Convert the argument to its Java type
+		exp.startIterator(classGen, methodGen);
+		expType.translateTo(classGen, methodGen, paramTypes[i]);
+                paramTemp[i] =
+                    methodGen.addLocalVariable("function_call_tmp"+i,
+                                               expType.toJCType(),
+                                               null, null);
+                paramTemp[i].setStart(
+                        il.append(expType.STORE(paramTemp[i].getIndex())));
+	    }
+
+	    il.append(new NEW(cpg.addClass(_className)));
+	    il.append(InstructionConstants.DUP);
+
+            for (int i = 0; i < n; i++) {
+                final Expression arg = argument(i);
+                paramTemp[i].setEnd(
+                        il.append(arg.getType().LOAD(paramTemp[i].getIndex())));
+            }
+
+	    final StringBuffer buffer = new StringBuffer();
+	    buffer.append('(');
+	    for (int i = 0; i < paramTypes.length; i++) {
+		buffer.append(getSignature(paramTypes[i]));
+	    }
+	    buffer.append(')');
+	    buffer.append("V");
+
+	    index = cpg.addMethodref(clazz,
+				     "<init>", 
+				     buffer.toString());
+	    il.append(new INVOKESPECIAL(index));
+
+	    // Convert the return type back to our internal type
+	    (Type.Object).translateFrom(classGen, methodGen, 
+				_chosenConstructor.getDeclaringClass());
+	    
+	}
+	// Invoke function calls that are handled in separate classes
+	else {
+	    if (isSecureProcessing)
+	        translateUnallowedExtension(cpg, il);
+	    
+	    final String clazz = _chosenMethod.getDeclaringClass().getName();
+	    Class[] paramTypes = _chosenMethod.getParameterTypes();
+
+	    // Push "this" if it is an instance method
+	    if (_thisArgument != null) {
+		_thisArgument.translate(classGen, methodGen);
+	    }	    
+
+	    for (int i = 0; i < n; i++) {
+		final Expression exp = argument(i);
+		exp.translate(classGen, methodGen);
+		// Convert the argument to its Java type
+		exp.startIterator(classGen, methodGen);
+		exp.getType().translateTo(classGen, methodGen, paramTypes[i]);
+	    }
+
+	    final StringBuffer buffer = new StringBuffer();
+	    buffer.append('(');
+	    for (int i = 0; i < paramTypes.length; i++) {
+		buffer.append(getSignature(paramTypes[i]));
+	    }
+	    buffer.append(')');
+	    buffer.append(getSignature(_chosenMethod.getReturnType()));
+
+	    if (_thisArgument != null && _clazz.isInterface()) {
+	        index = cpg.addInterfaceMethodref(clazz,
+				     _fname.getLocalPart(),
+				     buffer.toString());
+		il.append(new INVOKEINTERFACE(index, n+1));
+            }
+            else {
+	        index = cpg.addMethodref(clazz,
+				     _fname.getLocalPart(),
+				     buffer.toString());
+	        il.append(_thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) :
+	    		  (InvokeInstruction) new INVOKESTATIC(index));
+            }
+ 
+	    // Convert the return type back to our internal type
+	    _type.translateFrom(classGen, methodGen,
+				_chosenMethod.getReturnType());
+	}
+    }
+
+    public String toString() {
+	return "funcall(" + _fname + ", " + _arguments + ')';
+    }
+
+    public boolean isStandard() {
+	final String namespace = _fname.getNamespace();
+	return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING));
+    }
+
+    public boolean isExtension() {
+	final String namespace = _fname.getNamespace();
+	return (namespace != null) && (namespace.equals(EXT_XSLTC));
+    }
+
+    /**
+     * Returns a vector with all methods named <code>_fname</code>
+     * after stripping its namespace or <code>null</code>
+     * if no such methods exist.
+     */
+    private Vector findMethods() {
+	  
+	  Vector result = null;
+	  final String namespace = _fname.getNamespace();
+
+	  if (_className != null && _className.length() > 0) {
+	    final int nArgs = _arguments.size();
+	    try {
+	      if (_clazz == null) {
+                _clazz = ObjectFactory.findProviderClass(
+                  _className, ObjectFactory.findClassLoader(), true);
+
+		if (_clazz == null) {
+		  final ErrorMsg msg =
+		        new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
+		  getParser().reportError(Constants.ERROR, msg);
+		}
+	      }
+
+	      final String methodName = _fname.getLocalPart();
+	      final Method[] methods = _clazz.getMethods();
+
+	      for (int i = 0; i < methods.length; i++) {
+		final int mods = methods[i].getModifiers();
+		// Is it public and same number of args ?
+		if (Modifier.isPublic(mods)
+		    && methods[i].getName().equals(methodName)
+		    && methods[i].getParameterTypes().length == nArgs)
+		{
+		  if (result == null) {
+		    result = new Vector();
+	          }
+		  result.addElement(methods[i]);
+		}
+	      }
+	    }
+	    catch (ClassNotFoundException e) {
+		  final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
+		  getParser().reportError(Constants.ERROR, msg);
+	    }
+	  }
+	  return result;
+    }
+
+    /**
+     * Returns a vector with all constructors named <code>_fname</code>
+     * after stripping its namespace or <code>null</code>
+     * if no such methods exist.
+     */
+    private Vector findConstructors() {
+        Vector result = null;
+        final String namespace = _fname.getNamespace();
+
+        final int nArgs = _arguments.size();
+        try {
+          if (_clazz == null) {
+            _clazz = ObjectFactory.findProviderClass(
+              _className, ObjectFactory.findClassLoader(), true);
+
+            if (_clazz == null) {
+              final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
+              getParser().reportError(Constants.ERROR, msg);
+            }          
+          }
+
+          final Constructor[] constructors = _clazz.getConstructors();
+
+          for (int i = 0; i < constructors.length; i++) {
+              final int mods = constructors[i].getModifiers();
+              // Is it public, static and same number of args ?
+              if (Modifier.isPublic(mods) &&
+                  constructors[i].getParameterTypes().length == nArgs)
+              {
+                if (result == null) {
+                  result = new Vector();
+                }
+                result.addElement(constructors[i]);
+              }
+          }
+        }
+        catch (ClassNotFoundException e) {
+          final ErrorMsg msg = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, _className);
+          getParser().reportError(Constants.ERROR, msg);
+        }
+            
+        return result;
+    }
+
+
+    /**
+     * Compute the JVM signature for the class.
+     */
+    static final String getSignature(Class clazz) {
+	if (clazz.isArray()) {
+	    final StringBuffer sb = new StringBuffer();
+	    Class cl = clazz;
+	    while (cl.isArray()) {
+		sb.append("[");
+		cl = cl.getComponentType();
+	    }
+	    sb.append(getSignature(cl));
+	    return sb.toString();
+	}
+	else if (clazz.isPrimitive()) {
+	    if (clazz == Integer.TYPE) {
+		return "I";
+	    }
+	    else if (clazz == Byte.TYPE) {
+		return "B";
+	    }
+	    else if (clazz == Long.TYPE) {
+		return "J";
+	    }
+	    else if (clazz == Float.TYPE) {
+		return "F";
+	    }
+	    else if (clazz == Double.TYPE) {
+		return "D";
+	    }
+	    else if (clazz == Short.TYPE) {
+		return "S";
+	    }
+	    else if (clazz == Character.TYPE) {
+		return "C";
+	    }
+	    else if (clazz == Boolean.TYPE) {
+		return "Z";
+	    }
+	    else if (clazz == Void.TYPE) {
+		return "V";
+	    }
+	    else {
+		final String name = clazz.toString();
+		ErrorMsg err = new ErrorMsg(ErrorMsg.UNKNOWN_SIG_TYPE_ERR,name);
+		throw new Error(err.toString());
+	    }
+	}
+	else {
+	    return "L" + clazz.getName().replace('.', '/') + ';';
+	}
+    }
+
+    /**
+     * Compute the JVM method descriptor for the method.
+     */
+    static final String getSignature(Method meth) {
+	final StringBuffer sb = new StringBuffer();
+	sb.append('(');
+	final Class[] params = meth.getParameterTypes(); // avoid clone
+	for (int j = 0; j < params.length; j++) {
+	    sb.append(getSignature(params[j]));
+	}
+	return sb.append(')').append(getSignature(meth.getReturnType()))
+	    .toString();
+    }
+
+    /**
+     * Compute the JVM constructor descriptor for the constructor.
+     */
+    static final String getSignature(Constructor cons) {
+	final StringBuffer sb = new StringBuffer();
+	sb.append('(');
+	final Class[] params = cons.getParameterTypes(); // avoid clone
+	for (int j = 0; j < params.length; j++) {
+	    sb.append(getSignature(params[j]));
+	}
+	return sb.append(")V").toString();
+    }
+    
+    /**
+     * Return the signature of the current method
+     */
+    private String getMethodSignature(Vector argsType) {
+ 	final StringBuffer buf = new StringBuffer(_className);
+        buf.append('.').append(_fname.getLocalPart()).append('(');
+	  
+	int nArgs = argsType.size();	    
+	for (int i = 0; i < nArgs; i++) {
+	    final Type intType = (Type)argsType.elementAt(i);
+	    buf.append(intType.toString());
+	    if (i < nArgs - 1) buf.append(", ");
+	}
+	  
+	buf.append(')');
+	return buf.toString();
+    }
+
+    /**
+     * To support EXSLT extensions, convert names with dash to allowable Java names: 
+     * e.g., convert abc-xyz to abcXyz.
+     * Note: dashes only appear in middle of an EXSLT function or element name.
+     */
+    protected static String replaceDash(String name)
+    {
+        char dash = '-';
+        StringBuffer buff = new StringBuffer("");
+        for (int i = 0; i < name.length(); i++) {
+        if (i > 0 && name.charAt(i-1) == dash)
+            buff.append(Character.toUpperCase(name.charAt(i)));
+        else if (name.charAt(i) != dash)
+            buff.append(name.charAt(i));
+        }
+        return buff.toString();
+    }
+ 	 
+    /**
+     * Translate code to call the BasisLibrary.unallowed_extensionF(String)
+     * method.
+     */
+    private void translateUnallowedExtension(ConstantPoolGen cpg,
+                                             InstructionList il) {
+	int index = cpg.addMethodref(BASIS_LIBRARY_CLASS,
+				     "unallowed_extension_functionF",
+				     "(Ljava/lang/String;)V");
+	il.append(new PUSH(cpg, _fname.toString()));
+	il.append(new INVOKESTATIC(index));   
+    } 	 
+}

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

Added: servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/trax/TemplatesImpl.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/trax/TemplatesImpl.java?rev=1622167&view=auto
==============================================================================
--- servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/trax/TemplatesImpl.java (added)
+++ servicemix/smx4/bundles/trunk/xalan-2.7.2/src/main/java/org/apache/xalan/xsltc/trax/TemplatesImpl.java Wed Sep  3 06:09:50 2014
@@ -0,0 +1,410 @@
+/*
+ * 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.
+ */
+/*
+ * $Id: TemplatesImpl.java 468653 2006-10-28 07:07:05Z minchau $
+ */
+
+package org.apache.xalan.xsltc.trax;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Properties;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.URIResolver;
+
+import org.apache.xalan.xsltc.DOM;
+import org.apache.xalan.xsltc.Translet;
+import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
+import org.apache.xalan.xsltc.runtime.AbstractTranslet;
+import org.apache.xalan.xsltc.runtime.Hashtable;
+
+/**
+ * @author Morten Jorgensen
+ * @author G. Todd Millerj
+ * @author Jochen Cordes <Jo...@t-online.de>
+ * @author Santiago Pericas-Geertsen 
+ */
+public final class TemplatesImpl implements Templates, Serializable {
+    static final long serialVersionUID = 673094361519270707L;
+    /**
+     * Name of the superclass of all translets. This is needed to
+     * determine which, among all classes comprising a translet, 
+     * is the main one.
+     */
+    private static String ABSTRACT_TRANSLET 
+	= "org.apache.xalan.xsltc.runtime.AbstractTranslet";
+
+    /**
+     * Name of the main class or default name if unknown.
+     */
+    private String _name = null;
+
+    /**
+     * Contains the actual class definition for the translet class and
+     * any auxiliary classes.
+     */
+    private byte[][] _bytecodes = null;
+    
+    /**
+     * Contains the translet class definition(s). These are created when 
+     * this Templates is created or when it is read back from disk.
+     */
+    private Class[] _class = null;
+
+    /**
+     * The index of the main translet class in the arrays _class[] and
+     * _bytecodes.
+     */
+    private int _transletIndex = -1;
+    
+    /**
+     * Contains the list of auxiliary class definitions.
+     */
+    private Hashtable _auxClasses = null;
+    
+    /**
+     * Output properties of this translet.
+     */
+    private Properties _outputProperties; 
+
+    /**
+     * Number of spaces to add for output indentation.
+     */
+    private int _indentNumber;
+
+    /**
+     * This URIResolver is passed to all Transformers.
+     * Declaring it transient to fix bug 22438 
+     */
+    private transient URIResolver _uriResolver = null;
+
+    /**
+     * Cache the DTM for the stylesheet in a thread local variable,
+     * which is used by the document('') function.
+     * Use ThreadLocal because a DTM cannot be shared between
+     * multiple threads. 
+     * Declaring it transient to fix bug 22438 
+     */
+    private transient ThreadLocal _sdom = new ThreadLocal();
+    
+    /**
+     * A reference to the transformer factory that this templates
+     * object belongs to.
+     */
+    private transient TransformerFactoryImpl _tfactory = null;
+
+    static final class TransletClassLoader extends ClassLoader {
+	TransletClassLoader(ClassLoader parent) {
+	    super(parent);
+	}
+
+        /**
+         * Access to final protected superclass member from outer class.
+         */
+	Class defineClass(final byte[] b) {
+            return defineClass(null, b, 0, b.length);
+	}
+    }
+
+
+    /**
+     * Create an XSLTC template object from the bytecodes.
+     * The bytecodes for the translet and auxiliary classes, plus the name of
+     * the main translet class, must be supplied.
+     */
+    protected TemplatesImpl(byte[][] bytecodes, String transletName,
+	Properties outputProperties, int indentNumber,
+	TransformerFactoryImpl tfactory) 
+    {
+	_bytecodes = bytecodes;
+	_name      = transletName;
+	_outputProperties = outputProperties;
+	_indentNumber = indentNumber;
+	_tfactory = tfactory;
+    }
+    
+    /**
+     * Create an XSLTC template object from the translet class definition(s).
+     */
+    protected TemplatesImpl(Class[] transletClasses, String transletName,
+	Properties outputProperties, int indentNumber,
+	TransformerFactoryImpl tfactory) 
+    {
+	_class     = transletClasses;
+	_name      = transletName;
+	_transletIndex = 0;
+	_outputProperties = outputProperties;
+	_indentNumber = indentNumber;
+	_tfactory = tfactory;
+    }
+    
+
+    /**
+     * Need for de-serialization, see readObject().
+     */
+    public TemplatesImpl() { }
+
+    /**
+     *  Overrides the default readObject implementation since we decided
+     *  it would be cleaner not to serialize the entire tranformer
+     *  factory.  [ ref bugzilla 12317 ]
+     *  We need to check if the user defined class for URIResolver also
+     *  implemented Serializable
+     *  if yes then we need to deserialize the URIResolver
+     *  Fix for bugzilla bug 22438
+     */
+    private void  readObject(ObjectInputStream is) 
+      throws IOException, ClassNotFoundException 
+    {
+	is.defaultReadObject();
+        if (is.readBoolean()) {
+            _uriResolver = (URIResolver) is.readObject();
+        }
+
+	_tfactory = new TransformerFactoryImpl();
+    } 
+
+
+    /**
+     *  This is to fix bugzilla bug 22438
+     *  If the user defined class implements URIResolver and Serializable
+     *  then we want it to get serialized
+     */
+    private void writeObject(ObjectOutputStream os)
+        throws IOException, ClassNotFoundException {
+        os.defaultWriteObject();
+        if (_uriResolver instanceof Serializable) {
+            os.writeBoolean(true);
+            os.writeObject((Serializable) _uriResolver);
+        }
+        else {
+            os.writeBoolean(false);
+        }
+    }
+
+
+     /**
+     * Store URIResolver needed for Transformers.
+     */
+    public synchronized void setURIResolver(URIResolver resolver) {
+	_uriResolver = resolver;
+    }
+
+    /**
+     * The TransformerFactory must pass us the translet bytecodes using this
+     * method before we can create any translet instances
+     */
+    protected synchronized void setTransletBytecodes(byte[][] bytecodes) {
+	_bytecodes = bytecodes;
+    }
+
+    /**
+     * Returns the translet bytecodes stored in this template
+     */
+    public synchronized byte[][] getTransletBytecodes() {
+	return _bytecodes;
+    }
+
+    /**
+     * Returns the translet bytecodes stored in this template
+     */
+    public synchronized Class[] getTransletClasses() {
+	try {
+	    if (_class == null) defineTransletClasses();
+	}
+	catch (TransformerConfigurationException e) {
+	    // Falls through
+	}
+	return _class;
+    }
+
+    /**
+     * Returns the index of the main class in array of bytecodes
+     */
+    public synchronized int getTransletIndex() {
+	try {
+	    if (_class == null) defineTransletClasses();
+	}
+	catch (TransformerConfigurationException e) {
+	    // Falls through
+	}
+	return _transletIndex;
+    }
+
+    /**
+     * The TransformerFactory should call this method to set the translet name
+     */
+    protected synchronized void setTransletName(String name) {
+	_name = name;
+    }
+
+    /**
+     * Returns the name of the main translet class stored in this template
+     */
+    protected synchronized String getTransletName() {
+	return _name;
+    }
+
+    /**
+     * Defines the translet class and auxiliary classes.
+     * Returns a reference to the Class object that defines the main class
+     */
+    private void defineTransletClasses()
+	throws TransformerConfigurationException {
+
+	if (_bytecodes == null) {
+	    ErrorMsg err = new ErrorMsg(ErrorMsg.NO_TRANSLET_CLASS_ERR);
+	    throw new TransformerConfigurationException(err.toString());
+	}
+
+        TransletClassLoader loader = (TransletClassLoader)
+            AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    return new TransletClassLoader(ObjectFactory.findClassLoader());
+                }
+            });
+
+	try {
+	    final int classCount = _bytecodes.length;
+	    _class = new Class[classCount];
+
+	    if (classCount > 1) {
+	        _auxClasses = new Hashtable();
+	    }
+
+	    for (int i = 0; i < classCount; i++) {
+		_class[i] = loader.defineClass(_bytecodes[i]);
+		final Class superClass = _class[i].getSuperclass();
+
+		// Check if this is the main class
+		if (superClass.getName().equals(ABSTRACT_TRANSLET)) {
+		    _transletIndex = i;
+		}
+		else {
+		    _auxClasses.put(_class[i].getName(), _class[i]);
+		}
+	    }
+
+	    if (_transletIndex < 0) {
+		ErrorMsg err= new ErrorMsg(ErrorMsg.NO_MAIN_TRANSLET_ERR, _name);
+		throw new TransformerConfigurationException(err.toString());
+	    }
+	}
+	catch (ClassFormatError e) {
+	    ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_CLASS_ERR, _name);
+	    throw new TransformerConfigurationException(err.toString());
+	}
+	catch (LinkageError e) {
+	    ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
+	    throw new TransformerConfigurationException(err.toString());
+	}
+    }
+
+    /**
+     * This method generates an instance of the translet class that is
+     * wrapped inside this Template. The translet instance will later
+     * be wrapped inside a Transformer object.
+     */
+    private Translet getTransletInstance()
+	throws TransformerConfigurationException {
+	try {
+	    if (_name == null) return null;
+
+	    if (_class == null) defineTransletClasses();
+
+	    // The translet needs to keep a reference to all its auxiliary 
+	    // class to prevent the GC from collecting them
+	    AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
+            translet.postInitialization();
+	    translet.setTemplates(this);
+	    if (_auxClasses != null) {
+	        translet.setAuxiliaryClasses(_auxClasses);
+	    }
+	    
+	    return translet;
+	}
+	catch (InstantiationException e) {
+	    ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
+	    throw new TransformerConfigurationException(err.toString());
+	}
+	catch (IllegalAccessException e) {
+	    ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
+	    throw new TransformerConfigurationException(err.toString());
+	}
+    }
+
+    /**
+     * Implements JAXP's Templates.newTransformer()
+     *
+     * @throws TransformerConfigurationException
+     */
+    public synchronized Transformer newTransformer()
+	throws TransformerConfigurationException 
+    {
+	TransformerImpl transformer;
+
+	transformer = new TransformerImpl(getTransletInstance(), _outputProperties,
+	    _indentNumber, _tfactory);
+	
+	if (_uriResolver != null) {
+	    transformer.setURIResolver(_uriResolver);
+	}
+	
+	if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {
+	    transformer.setSecureProcessing(true);
+	}
+	return transformer;
+    }
+
+    /**
+     * Implements JAXP's Templates.getOutputProperties(). We need to 
+     * instanciate a translet to get the output settings, so
+     * we might as well just instanciate a Transformer and use its
+     * implementation of this method.
+     */
+    public synchronized Properties getOutputProperties() { 
+	try {
+	    return newTransformer().getOutputProperties();
+	}
+	catch (TransformerConfigurationException e) {
+	    return null;
+	}
+    }
+
+    /**
+     * Return the thread local copy of the stylesheet DOM.
+     */
+    public DOM getStylesheetDOM() {
+    	return (DOM)_sdom.get();
+    }
+    
+    /**
+     * Set the thread local copy of the stylesheet DOM.
+     */
+    public void setStylesheetDOM(DOM sdom) {
+    	_sdom.set(sdom);
+    }
+}