15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: FunctionCall.java,v 1.2.4.1 2005/09/12 10:31:32 pvedula Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.xsltc.compiler; 25 26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27 import com.sun.org.apache.bcel.internal.generic.IFEQ; 28 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 29 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 30 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 31 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 32 import com.sun.org.apache.bcel.internal.generic.InstructionConstants; 33 import com.sun.org.apache.bcel.internal.generic.InstructionList; 34 import com.sun.org.apache.bcel.internal.generic.InvokeInstruction; 35 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; 36 import com.sun.org.apache.bcel.internal.generic.NEW; 37 import com.sun.org.apache.bcel.internal.generic.PUSH; 38 import com.sun.org.apache.xalan.internal.utils.FeatureManager; 39 import com.sun.org.apache.xalan.internal.utils.ObjectFactory; 40 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.BooleanType; 41 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 42 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 43 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.IntType; 44 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 45 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; 46 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MultiHashtable; 47 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ObjectType; 48 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType; 49 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 50 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 51 import java.lang.reflect.Constructor; 52 import java.lang.reflect.Method; 53 import java.lang.reflect.Modifier; 54 import java.util.Collections; 55 import java.util.Enumeration; 56 import java.util.HashMap; 775 // Invoke the method in the basis library 776 index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name, 777 _chosenMethodType.toSignature(args)); 778 il.append(new INVOKESTATIC(index)); 779 } 780 // Add call to BasisLibrary.unresolved_externalF() to generate 781 // run-time error message for unsupported external functions 782 else if (unresolvedExternal) { 783 index = cpg.addMethodref(BASIS_LIBRARY_CLASS, 784 "unresolved_externalF", 785 "(Ljava/lang/String;)V"); 786 il.append(new PUSH(cpg, _fname.toString())); 787 il.append(new INVOKESTATIC(index)); 788 } 789 else if (_isExtConstructor) { 790 if (isSecureProcessing && !isExtensionFunctionEnabled) 791 translateUnallowedExtension(cpg, il); 792 793 final String clazz = 794 _chosenConstructor.getDeclaringClass().getName(); 795 Class[] paramTypes = _chosenConstructor.getParameterTypes(); 796 LocalVariableGen[] paramTemp = new LocalVariableGen[n]; 797 798 // Backwards branches are prohibited if an uninitialized object is 799 // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed. 800 // We don't know whether this code might contain backwards branches 801 // so we mustn't create the new object until after we've created 802 // the suspect arguments to its constructor. Instead we calculate 803 // the values of the arguments to the constructor first, store them 804 // in temporary variables, create the object and reload the 805 // arguments from the temporaries to avoid the problem. 806 807 for (int i = 0; i < n; i++) { 808 final Expression exp = argument(i); 809 Type expType = exp.getType(); 810 exp.translate(classGen, methodGen); 811 // Convert the argument to its Java type 812 exp.startIterator(classGen, methodGen); 813 expType.translateTo(classGen, methodGen, paramTypes[i]); 814 paramTemp[i] = 838 buffer.append("V"); 839 840 index = cpg.addMethodref(clazz, 841 "<init>", 842 buffer.toString()); 843 il.append(new INVOKESPECIAL(index)); 844 845 // Convert the return type back to our internal type 846 (Type.Object).translateFrom(classGen, methodGen, 847 _chosenConstructor.getDeclaringClass()); 848 849 } 850 // Invoke function calls that are handled in separate classes 851 else { 852 if (isSecureProcessing && !isExtensionFunctionEnabled) 853 translateUnallowedExtension(cpg, il); 854 855 final String clazz = _chosenMethod.getDeclaringClass().getName(); 856 Class[] paramTypes = _chosenMethod.getParameterTypes(); 857 858 // Push "this" if it is an instance method 859 if (_thisArgument != null) { 860 _thisArgument.translate(classGen, methodGen); 861 } 862 863 for (int i = 0; i < n; i++) { 864 final Expression exp = argument(i); 865 exp.translate(classGen, methodGen); 866 // Convert the argument to its Java type 867 exp.startIterator(classGen, methodGen); 868 exp.getType().translateTo(classGen, methodGen, paramTypes[i]); 869 } 870 871 final StringBuffer buffer = new StringBuffer(); 872 buffer.append('('); 873 for (int i = 0; i < paramTypes.length; i++) { 874 buffer.append(getSignature(paramTypes[i])); 875 } 876 buffer.append(')'); 877 buffer.append(getSignature(_chosenMethod.getReturnType())); 879 if (_thisArgument != null && _clazz.isInterface()) { 880 index = cpg.addInterfaceMethodref(clazz, 881 _fname.getLocalPart(), 882 buffer.toString()); 883 il.append(new INVOKEINTERFACE(index, n+1)); 884 } 885 else { 886 index = cpg.addMethodref(clazz, 887 _fname.getLocalPart(), 888 buffer.toString()); 889 il.append(_thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) : 890 (InvokeInstruction) new INVOKESTATIC(index)); 891 } 892 893 // Convert the return type back to our internal type 894 _type.translateFrom(classGen, methodGen, 895 _chosenMethod.getReturnType()); 896 } 897 } 898 899 @Override 900 public String toString() { 901 return "funcall(" + _fname + ", " + _arguments + ')'; 902 } 903 904 public boolean isStandard() { 905 final String namespace = _fname.getNamespace(); 906 return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING)); 907 } 908 909 public boolean isExtension() { 910 final String namespace = _fname.getNamespace(); 911 return (namespace != null) && (namespace.equals(EXT_XSLTC)); 912 } 913 914 /** 915 * Returns a vector with all methods named <code>_fname</code> 916 * after stripping its namespace or <code>null</code> 917 * if no such methods exist. 918 */ | 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: FunctionCall.java,v 1.2.4.1 2005/09/12 10:31:32 pvedula Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.xsltc.compiler; 25 26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27 import com.sun.org.apache.bcel.internal.generic.IFEQ; 28 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 29 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 30 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 31 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 32 import com.sun.org.apache.bcel.internal.generic.InstructionConstants; 33 import com.sun.org.apache.bcel.internal.generic.InstructionList; 34 import com.sun.org.apache.bcel.internal.generic.InvokeInstruction; 35 import com.sun.org.apache.bcel.internal.generic.LDC; 36 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; 37 import com.sun.org.apache.bcel.internal.generic.NEW; 38 import com.sun.org.apache.bcel.internal.generic.POP; 39 import com.sun.org.apache.bcel.internal.generic.PUSH; 40 import com.sun.org.apache.xalan.internal.utils.FeatureManager; 41 import com.sun.org.apache.xalan.internal.utils.ObjectFactory; 42 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.BooleanType; 43 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 44 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 45 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.IntType; 46 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 47 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; 48 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MultiHashtable; 49 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ObjectType; 50 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType; 51 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 52 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 53 import java.lang.reflect.Constructor; 54 import java.lang.reflect.Method; 55 import java.lang.reflect.Modifier; 56 import java.util.Collections; 57 import java.util.Enumeration; 58 import java.util.HashMap; 777 // Invoke the method in the basis library 778 index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name, 779 _chosenMethodType.toSignature(args)); 780 il.append(new INVOKESTATIC(index)); 781 } 782 // Add call to BasisLibrary.unresolved_externalF() to generate 783 // run-time error message for unsupported external functions 784 else if (unresolvedExternal) { 785 index = cpg.addMethodref(BASIS_LIBRARY_CLASS, 786 "unresolved_externalF", 787 "(Ljava/lang/String;)V"); 788 il.append(new PUSH(cpg, _fname.toString())); 789 il.append(new INVOKESTATIC(index)); 790 } 791 else if (_isExtConstructor) { 792 if (isSecureProcessing && !isExtensionFunctionEnabled) 793 translateUnallowedExtension(cpg, il); 794 795 final String clazz = 796 _chosenConstructor.getDeclaringClass().getName(); 797 798 // Generate call to Module.addReads: 799 // <TransletClass>.class.getModule().addReads( 800 generateAddReads(classGen, methodGen, clazz); 801 802 Class[] paramTypes = _chosenConstructor.getParameterTypes(); 803 LocalVariableGen[] paramTemp = new LocalVariableGen[n]; 804 805 // Backwards branches are prohibited if an uninitialized object is 806 // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed. 807 // We don't know whether this code might contain backwards branches 808 // so we mustn't create the new object until after we've created 809 // the suspect arguments to its constructor. Instead we calculate 810 // the values of the arguments to the constructor first, store them 811 // in temporary variables, create the object and reload the 812 // arguments from the temporaries to avoid the problem. 813 814 for (int i = 0; i < n; i++) { 815 final Expression exp = argument(i); 816 Type expType = exp.getType(); 817 exp.translate(classGen, methodGen); 818 // Convert the argument to its Java type 819 exp.startIterator(classGen, methodGen); 820 expType.translateTo(classGen, methodGen, paramTypes[i]); 821 paramTemp[i] = 845 buffer.append("V"); 846 847 index = cpg.addMethodref(clazz, 848 "<init>", 849 buffer.toString()); 850 il.append(new INVOKESPECIAL(index)); 851 852 // Convert the return type back to our internal type 853 (Type.Object).translateFrom(classGen, methodGen, 854 _chosenConstructor.getDeclaringClass()); 855 856 } 857 // Invoke function calls that are handled in separate classes 858 else { 859 if (isSecureProcessing && !isExtensionFunctionEnabled) 860 translateUnallowedExtension(cpg, il); 861 862 final String clazz = _chosenMethod.getDeclaringClass().getName(); 863 Class[] paramTypes = _chosenMethod.getParameterTypes(); 864 865 866 // Generate call to Module.addReads: 867 // <TransletClass>.class.getModule().addReads( 868 // Class.forName(<clazz>).getModule()); 869 generateAddReads(classGen, methodGen, clazz); 870 871 // Push "this" if it is an instance method 872 if (_thisArgument != null) { 873 _thisArgument.translate(classGen, methodGen); 874 } 875 876 for (int i = 0; i < n; i++) { 877 final Expression exp = argument(i); 878 exp.translate(classGen, methodGen); 879 // Convert the argument to its Java type 880 exp.startIterator(classGen, methodGen); 881 exp.getType().translateTo(classGen, methodGen, paramTypes[i]); 882 } 883 884 final StringBuffer buffer = new StringBuffer(); 885 buffer.append('('); 886 for (int i = 0; i < paramTypes.length; i++) { 887 buffer.append(getSignature(paramTypes[i])); 888 } 889 buffer.append(')'); 890 buffer.append(getSignature(_chosenMethod.getReturnType())); 892 if (_thisArgument != null && _clazz.isInterface()) { 893 index = cpg.addInterfaceMethodref(clazz, 894 _fname.getLocalPart(), 895 buffer.toString()); 896 il.append(new INVOKEINTERFACE(index, n+1)); 897 } 898 else { 899 index = cpg.addMethodref(clazz, 900 _fname.getLocalPart(), 901 buffer.toString()); 902 il.append(_thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) : 903 (InvokeInstruction) new INVOKESTATIC(index)); 904 } 905 906 // Convert the return type back to our internal type 907 _type.translateFrom(classGen, methodGen, 908 _chosenMethod.getReturnType()); 909 } 910 } 911 912 private void generateAddReads(ClassGenerator classGen, MethodGenerator methodGen, 913 String clazz) { 914 final ConstantPoolGen cpg = classGen.getConstantPool(); 915 final InstructionList il = methodGen.getInstructionList(); 916 917 if (classGen.getMajor() < com.sun.org.apache.bcel.internal.Constants.MAJOR_1_5) { 918 // Major version needs to be >= 5.0 in order to support loading 919 // a class ref from the constant pool (LDC) 920 classGen.setMajor(com.sun.org.apache.bcel.internal.Constants.MAJOR_1_5); 921 classGen.setMinor(com.sun.org.apache.bcel.internal.Constants.MINOR_1_5); 922 } 923 924 // Generate call to Module.addReads: 925 // <TransletClass>.class.getModule().addReads( 926 // Class.forName(<clazz>).getModule()); 927 // Class.forName may throw ClassNotFoundException. 928 // This is OK as it will caught higher up the stack in 929 // TransformerImpl.transform() and wrapped into a 930 // TransformerException. 931 methodGen.markChunkStart(); 932 933 int index = cpg.addMethodref(CLASS_CLASS, 934 GET_MODULE, 935 GET_MODULE_SIG); 936 il.append(new LDC(cpg.addClass(classGen.getClassName()))); 937 il.append(new INVOKEVIRTUAL(index)); 938 int index2 = cpg.addMethodref(CLASS_CLASS, 939 FOR_NAME, 940 FOR_NAME_SIG); 941 il.append(new LDC(cpg.addString(clazz))); 942 il.append(new INVOKESTATIC(index2)); 943 il.append(new INVOKEVIRTUAL(index)); 944 index = cpg.addMethodref(MODULE_CLASS, 945 ADD_READS, 946 ADD_READS_SIG); 947 il.append(new INVOKEVIRTUAL(index)); 948 il.append(new POP()); 949 950 methodGen.markChunkEnd(); 951 } 952 953 @Override 954 public String toString() { 955 return "funcall(" + _fname + ", " + _arguments + ')'; 956 } 957 958 public boolean isStandard() { 959 final String namespace = _fname.getNamespace(); 960 return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING)); 961 } 962 963 public boolean isExtension() { 964 final String namespace = _fname.getNamespace(); 965 return (namespace != null) && (namespace.equals(EXT_XSLTC)); 966 } 967 968 /** 969 * Returns a vector with all methods named <code>_fname</code> 970 * after stripping its namespace or <code>null</code> 971 * if no such methods exist. 972 */ |