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);
+ }
+}