diff options
author | Benedikt Ritter <britter@apache.org> | 2016-09-06 06:38:18 +0000 |
---|---|---|
committer | Benedikt Ritter <britter@apache.org> | 2016-09-06 06:38:18 +0000 |
commit | c96a3e5a40040ef43e0a51935a368458763d3424 (patch) | |
tree | e698d0ceebc8d38e34f9402ffef7af735c1c2de6 /src/test | |
parent | 7ceb5a6b8236517d708d7965f4873344c5630969 (diff) | |
download | apache-commons-bcel-c96a3e5a40040ef43e0a51935a368458763d3424.tar.gz |
BCEL-276: LocalVariableTypeTable is not updated. Thanks to Sam Yoon. This also fixes #10 from GitHub.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/bcel/trunk@1759364 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java | 142 | ||||
-rw-r--r-- | src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java | 34 |
2 files changed, 176 insertions, 0 deletions
diff --git a/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java b/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java new file mode 100644 index 00000000..ca7e2da1 --- /dev/null +++ b/src/test/java/org/apache/bcel/LocalVariableTypeTableTestCase.java @@ -0,0 +1,142 @@ +/* + * 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. + * + */ +package org.apache.bcel; + +import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.ACONST_NULL; +import org.apache.bcel.generic.ALOAD; +import org.apache.bcel.generic.ConstantPoolGen; +import org.apache.bcel.generic.GETSTATIC; +import org.apache.bcel.generic.INVOKEVIRTUAL; +import org.apache.bcel.generic.Instruction; +import org.apache.bcel.generic.InstructionList; +import org.apache.bcel.generic.LocalVariableGen; +import org.apache.bcel.generic.MethodGen; +import org.apache.bcel.generic.Type; +import org.junit.Test; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.LinkedList; +import java.util.List; + +public class LocalVariableTypeTableTestCase extends AbstractTestCase { + public class TestClassLoader extends ClassLoader { + public TestClassLoader(ClassLoader parent) { + super(parent); + } + + public Class<?> findClass(String name, byte[] bytes) { + return defineClass(name, bytes, 0, bytes.length); + } + } + + @Test + public void testWithGenericArguement() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException { + String targetClass = PACKAGE_BASE_NAME + ".data.SimpleClassHasMethodIncludeGenericArgument"; + TestClassLoader loader = new TestClassLoader(getClass().getClassLoader()); + Class cls = loader.findClass(targetClass, getBytesFromClass(targetClass)); + + java.lang.reflect.Method method = cls.getDeclaredMethod("a", String.class, List.class); + method.invoke(null, "a1", new LinkedList<String>()); + method = cls.getDeclaredMethod("b", String.class, List.class); + method.invoke(null, "b1", new LinkedList<String>()); + method = cls.getDeclaredMethod("c", String.class, String.class); + method.invoke(null, "c1", "c2"); + method = cls.getDeclaredMethod("d", List.class, String.class); + method.invoke(null, new LinkedList<String>(), "d2"); + } + + private byte[] getBytesFromClass(String className) throws ClassNotFoundException, IOException { + JavaClass clazz = getTestClass(className); + ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool()); + + Method[] methods = clazz.getMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (!method.isNative() && !method.isAbstract()) + methods[i] = injection(clazz, method, cp, findFirstStringLocalVariableOffset(method)); + } + + clazz.setConstantPool(cp.getFinalConstantPool()); + + return clazz.getBytes(); + } + + public Method injection(JavaClass clazz, Method method, ConstantPoolGen cp, int firstStringOffset) { + MethodGen methodGen = new MethodGen(method, clazz.getClassName(), cp); + + InstructionList instructionList = methodGen.getInstructionList(); + instructionList.insert(instructionList.getStart(), makeWillBeAddedInstructionList(methodGen, firstStringOffset)); + + methodGen.setMaxStack(); + methodGen.setMaxLocals(); + + method = methodGen.getMethod(); + instructionList.dispose(); + + return method; + } + + public InstructionList makeWillBeAddedInstructionList(MethodGen methodGen, int firstStringOffset) { + if (firstStringOffset == -1) + return new InstructionList(); + + LocalVariableGen localVariableGen = methodGen.getLocalVariables()[firstStringOffset]; + Instruction instruction; + + if (localVariableGen != null) + instruction = new ALOAD(localVariableGen.getIndex()); + else + instruction = new ACONST_NULL(); + + return createPrintln(methodGen.getConstantPool(), instruction); + } + + public InstructionList createPrintln(ConstantPoolGen cp, Instruction instruction) { + final InstructionList il = new InstructionList(); + + final int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;"); + final int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V"); + il.append(new GETSTATIC(out)); + il.append(instruction); + il.append(new INVOKEVIRTUAL(println)); + + return il; + } + + public int findFirstStringLocalVariableOffset(Method method) { + Type[] argumentTypes = method.getArgumentTypes(); + int offset = -1; + + for (int i = 0, count = argumentTypes.length; i < count; i++) { + if (Type.STRING.getSignature().equals(argumentTypes[i].getSignature())) { + if (method.isStatic()) + offset = i; + else + offset = i + 1; + + break; + } + } + + return offset; + } +} diff --git a/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java b/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java new file mode 100644 index 00000000..c9acb259 --- /dev/null +++ b/src/test/java/org/apache/bcel/data/SimpleClassHasMethodIncludeGenericArgument.java @@ -0,0 +1,34 @@ +/* + * 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. + * + */ +package org.apache.bcel.data; + +import java.util.List; + +public class SimpleClassHasMethodIncludeGenericArgument { + public static void a(String a1, List<String> a2) { + } + + public static void b(String b1, List b2) { + } + + public static void c(String c1, String c2) { + } + + public static void d(List<String> d1, String d2) { + } +} |