mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-26 20:30:29 +08:00
add substitutions to global inject method pool
This commit is contained in:
parent
24a0cb32b2
commit
14659f332d
@ -1,13 +1,10 @@
|
|||||||
package com.alibaba.testable.generator;
|
package com.alibaba.testable.generator;
|
||||||
|
|
||||||
import com.alibaba.testable.util.ConstPool;
|
import com.alibaba.testable.model.TestableContext;
|
||||||
import com.squareup.javapoet.*;
|
|
||||||
|
|
||||||
import javax.lang.model.element.Modifier;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate global n.e class code
|
* Generate global n.e class code
|
||||||
@ -16,55 +13,24 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class StaticNewClassGenerator {
|
public class StaticNewClassGenerator {
|
||||||
|
|
||||||
|
private final TestableContext cx;
|
||||||
|
|
||||||
|
public StaticNewClassGenerator(TestableContext cx) {
|
||||||
|
this.cx = cx;
|
||||||
|
}
|
||||||
|
|
||||||
public String fetch() {
|
public String fetch() {
|
||||||
return JavaFile.builder(ConstPool.SN_PKG,
|
ClassLoader classLoader = this.getClass().getClassLoader();
|
||||||
TypeSpec.classBuilder(ConstPool.SN_CLS)
|
File file = new File(classLoader.getResource("e.java").getFile());
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
if (!file.exists()) {
|
||||||
.addField(buildStaticPoolField())
|
cx.logger.error("Failed to fetch testable new stand-in.");
|
||||||
.addMethod(buildStaticNewMethod())
|
}
|
||||||
.build())
|
try {
|
||||||
.build().toString();
|
return new String(Files.readAllBytes(file.toPath()));
|
||||||
}
|
} catch (IOException e) {
|
||||||
|
cx.logger.error("Failed to generate testable new stand-in.");
|
||||||
private FieldSpec buildStaticPoolField() {
|
return "";
|
||||||
return FieldSpec.builder(ParameterizedTypeName.get(Map.class, Class.class, Object.class), "pool", Modifier.PUBLIC)
|
}
|
||||||
.addModifiers(Modifier.STATIC)
|
|
||||||
.initializer("new $T<>()", HashMap.class)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MethodSpec buildStaticNewMethod() {
|
|
||||||
TypeVariableName typeVariable = TypeVariableName.get("T");
|
|
||||||
MethodSpec.Builder builder = MethodSpec.methodBuilder(ConstPool.SN_METHOD)
|
|
||||||
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC)
|
|
||||||
.addTypeVariable(typeVariable)
|
|
||||||
.varargs(true)
|
|
||||||
.addParameter(ParameterizedTypeName.get(ClassName.get(Class.class), typeVariable), "type")
|
|
||||||
.addParameter(ArrayTypeName.of(Object.class), "args")
|
|
||||||
.returns(typeVariable);
|
|
||||||
addStaticNewMethodStatement(builder);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addStaticNewMethodStatement(MethodSpec.Builder builder) {
|
|
||||||
builder.addStatement("$T<$T> pts = new $T<>()", List.class, Class.class, ArrayList.class)
|
|
||||||
.beginControlFlow("for (Object o : args)")
|
|
||||||
.addStatement("pts.add(o.getClass())")
|
|
||||||
.endControlFlow()
|
|
||||||
.beginControlFlow("if (!pool.isEmpty())")
|
|
||||||
.beginControlFlow("try")
|
|
||||||
.addStatement("T obj = (T)pool.get(type)")
|
|
||||||
.beginControlFlow("if (obj != null)")
|
|
||||||
.addStatement("return obj")
|
|
||||||
.endControlFlow()
|
|
||||||
.nextControlFlow("catch (Exception e)")
|
|
||||||
.endControlFlow()
|
|
||||||
.endControlFlow()
|
|
||||||
.beginControlFlow("try")
|
|
||||||
.addStatement("return type.getConstructor(pts.toArray(new Class[0])).newInstance(args)")
|
|
||||||
.nextControlFlow("catch (Exception e)")
|
|
||||||
.addStatement("return null")
|
|
||||||
.endControlFlow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import com.sun.tools.javac.code.Type;
|
|||||||
import com.sun.tools.javac.tree.JCTree;
|
import com.sun.tools.javac.tree.JCTree;
|
||||||
import com.sun.tools.javac.tree.TreeTranslator;
|
import com.sun.tools.javac.tree.TreeTranslator;
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
|
import com.sun.tools.javac.tree.JCTree.*;
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
@ -23,11 +24,15 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
|||||||
private static final String ANNOTATION_JUNIT5_SETUP = "org.junit.jupiter.api.BeforeEach";
|
private static final String ANNOTATION_JUNIT5_SETUP = "org.junit.jupiter.api.BeforeEach";
|
||||||
private static final String ANNOTATION_JUNIT5_TEST = "org.junit.jupiter.api.Test";
|
private static final String ANNOTATION_JUNIT5_TEST = "org.junit.jupiter.api.Test";
|
||||||
private final TestableContext cx;
|
private final TestableContext cx;
|
||||||
private String sourceClassName;
|
private String sourceClassName = "";
|
||||||
private ListBuffer<Name> sourceClassIns = new ListBuffer();
|
private ListBuffer<Name> sourceClassIns = new ListBuffer();
|
||||||
private List<String> stubbornFields = List.nil();
|
private List<String> stubbornFields = List.nil();
|
||||||
private ListBuffer<Pair<Type, Pair<Name, List<Type>>>> injectMethods = new ListBuffer<>();
|
|
||||||
private String testSetupMethodName;
|
/**
|
||||||
|
* MethodName -> (ResultType -> ParameterTypes)
|
||||||
|
*/
|
||||||
|
private ListBuffer<Pair<Name, Pair<JCExpression, List<JCExpression>>>> injectMethods = new ListBuffer<>();
|
||||||
|
private String testSetupMethodName = "";
|
||||||
private TestLibType testLibType = TestLibType.JUnit4;
|
private TestLibType testLibType = TestLibType.JUnit4;
|
||||||
|
|
||||||
public TestableClassTestRoleTranslator(String pkgName, String className, TestableContext cx) {
|
public TestableClassTestRoleTranslator(String pkgName, String className, TestableContext cx) {
|
||||||
@ -44,29 +49,39 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitVarDef(JCTree.JCVariableDecl jcVariableDecl) {
|
public void visitVarDef(JCVariableDecl jcVariableDecl) {
|
||||||
super.visitVarDef(jcVariableDecl);
|
super.visitVarDef(jcVariableDecl);
|
||||||
if (((JCTree.JCIdent)jcVariableDecl.vartype).name.toString().equals(sourceClassName)) {
|
if (((JCIdent)jcVariableDecl.vartype).name.toString().equals(sourceClassName)) {
|
||||||
jcVariableDecl.vartype = getTestableClassIdent(jcVariableDecl.vartype);
|
jcVariableDecl.vartype = getTestableClassIdent(jcVariableDecl.vartype);
|
||||||
sourceClassIns.add(jcVariableDecl.name);
|
sourceClassIns.add(jcVariableDecl.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNewClass(JCTree.JCNewClass jcNewClass) {
|
public void visitNewClass(JCNewClass jcNewClass) {
|
||||||
super.visitNewClass(jcNewClass);
|
super.visitNewClass(jcNewClass);
|
||||||
if (((JCTree.JCIdent)jcNewClass.clazz).name.toString().equals(sourceClassName)) {
|
if (getSimpleClassName(jcNewClass).equals(sourceClassName)) {
|
||||||
jcNewClass.clazz = getTestableClassIdent(jcNewClass.clazz);
|
jcNewClass.clazz = getTestableClassIdent(jcNewClass.clazz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getSimpleClassName(JCNewClass jcNewClass) {
|
||||||
|
if (jcNewClass.clazz.getClass().equals(JCIdent.class)) {
|
||||||
|
return ((JCIdent)jcNewClass.clazz).name.toString();
|
||||||
|
} else if (jcNewClass.clazz.getClass().equals(JCFieldAccess.class)) {
|
||||||
|
return ((JCFieldAccess)jcNewClass.clazz).name.toString();
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitExec(JCTree.JCExpressionStatement jcExpressionStatement) {
|
public void visitExec(JCExpressionStatement jcExpressionStatement) {
|
||||||
if (jcExpressionStatement.expr.getClass().equals(JCTree.JCAssign.class) &&
|
if (jcExpressionStatement.expr.getClass().equals(JCAssign.class) &&
|
||||||
isAssignStubbornField((JCTree.JCAssign)jcExpressionStatement.expr)) {
|
isAssignStubbornField((JCAssign)jcExpressionStatement.expr)) {
|
||||||
JCTree.JCAssign assign = (JCTree.JCAssign)jcExpressionStatement.expr;
|
JCAssign assign = (JCAssign)jcExpressionStatement.expr;
|
||||||
// TODO: Use treeMaker.Apply() and treeMaker.Select()
|
// TODO: Use treeMaker.Apply() and treeMaker.Select()
|
||||||
TestableFieldAccess stubbornSetter = new TestableFieldAccess(((JCTree.JCFieldAccess)assign.lhs).selected,
|
TestableFieldAccess stubbornSetter = new TestableFieldAccess(((JCFieldAccess)assign.lhs).selected,
|
||||||
getStubbornSetterMethodName(assign), null);
|
getStubbornSetterMethodName(assign), null);
|
||||||
jcExpressionStatement.expr = new TestableMethodInvocation(null, stubbornSetter,
|
jcExpressionStatement.expr = new TestableMethodInvocation(null, stubbornSetter,
|
||||||
com.sun.tools.javac.util.List.of(assign.rhs));
|
com.sun.tools.javac.util.List.of(assign.rhs));
|
||||||
@ -75,15 +90,16 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitMethodDef(JCTree.JCMethodDecl jcMethodDecl) {
|
public void visitMethodDef(JCMethodDecl jcMethodDecl) {
|
||||||
for (JCTree.JCAnnotation a : jcMethodDecl.mods.annotations) {
|
for (JCAnnotation a : jcMethodDecl.mods.annotations) {
|
||||||
switch (a.type.tsym.toString()) {
|
switch (a.type.tsym.toString()) {
|
||||||
case ANNOTATION_TESTABLE_INJECT:
|
case ANNOTATION_TESTABLE_INJECT:
|
||||||
ListBuffer<Type> args = new ListBuffer<>();
|
ListBuffer<JCExpression> args = new ListBuffer<>();
|
||||||
for (JCTree.JCVariableDecl p : jcMethodDecl.params) {
|
for (JCVariableDecl p : jcMethodDecl.params) {
|
||||||
args.add(p.vartype.type);
|
args.add(cx.treeMaker.Select(p.vartype, cx.names.fromString("class")));
|
||||||
}
|
}
|
||||||
injectMethods.add(Pair.of(jcMethodDecl.restype.type, Pair.of(jcMethodDecl.name, args.toList())));
|
JCExpression retType = cx.treeMaker.Select(jcMethodDecl.restype, cx.names.fromString("class"));
|
||||||
|
injectMethods.add(Pair.of(jcMethodDecl.name, Pair.of(retType, args.toList())));
|
||||||
break;
|
break;
|
||||||
case ANNOTATION_JUNIT5_SETUP:
|
case ANNOTATION_JUNIT5_SETUP:
|
||||||
testSetupMethodName = jcMethodDecl.name.toString();
|
testSetupMethodName = jcMethodDecl.name.toString();
|
||||||
@ -99,35 +115,22 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {
|
public void visitClassDef(JCClassDecl jcClassDecl) {
|
||||||
super.visitClassDef(jcClassDecl);
|
super.visitClassDef(jcClassDecl);
|
||||||
ListBuffer<JCTree> ndefs = new ListBuffer<>();
|
ListBuffer<JCTree> ndefs = new ListBuffer<>();
|
||||||
ndefs.addAll(jcClassDecl.defs);
|
ndefs.addAll(jcClassDecl.defs);
|
||||||
JCTree.JCModifiers mods = cx.treeMaker.Modifiers(Modifier.PUBLIC, makeAnnotations());
|
JCModifiers mods = cx.treeMaker.Modifiers(Modifier.PUBLIC, makeAnnotations(ANNOTATION_JUNIT5_SETUP));
|
||||||
ndefs.add(cx.treeMaker.MethodDef(mods, cx.names.fromString("testableSetup"),
|
ndefs.add(cx.treeMaker.MethodDef(mods, cx.names.fromString("testableSetup"),
|
||||||
cx.treeMaker.Type(new Type.JCVoidType()), List.<JCTree.JCTypeParameter>nil(),
|
cx.treeMaker.Type(new Type.JCVoidType()), List.<JCTypeParameter>nil(),
|
||||||
List.<JCTree.JCVariableDecl>nil(), List.<JCTree.JCExpression>nil(), testableSetupBlock(), null));
|
List.<JCVariableDecl>nil(), List.<JCExpression>nil(), testableSetupBlock(), null));
|
||||||
jcClassDecl.defs = ndefs.toList();
|
jcClassDecl.defs = ndefs.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<JCTree.JCAnnotation> makeAnnotations() {
|
|
||||||
String[] elems = ANNOTATION_JUNIT5_TEST.split("\\.");
|
|
||||||
JCTree.JCExpression e = cx.treeMaker.Ident(cx.names.fromString(elems[0]));
|
|
||||||
for (int i = 1 ; i < elems.length ; i++) {
|
|
||||||
e = cx.treeMaker.Select(e, cx.names.fromString(elems[i]));
|
|
||||||
}
|
|
||||||
return List.of(cx.treeMaker.Annotation(e, List.<JCTree.JCExpression>nil()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private JCTree.JCBlock testableSetupBlock() {
|
|
||||||
return cx.treeMaker.Block(0, List.<JCTree.JCStatement>nil());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For break point
|
* For break point
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitAssign(JCTree.JCAssign jcAssign) {
|
public void visitAssign(JCAssign jcAssign) {
|
||||||
super.visitAssign(jcAssign);
|
super.visitAssign(jcAssign);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,14 +138,53 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
|||||||
* For break point
|
* For break point
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
|
public void visitSelect(JCFieldAccess jcFieldAccess) {
|
||||||
super.visitSelect(jcFieldAccess);
|
super.visitSelect(jcFieldAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<JCTree.JCAnnotation> removeAnnotation(
|
private List<JCAnnotation> makeAnnotations(String fullAnnotationName) {
|
||||||
List<JCTree.JCAnnotation> annotations, String target) {
|
JCExpression setupAnnotation = nameToExpression(fullAnnotationName);
|
||||||
ListBuffer<JCTree.JCAnnotation> nb = new ListBuffer<>();
|
return List.of(cx.treeMaker.Annotation(setupAnnotation, List.<JCExpression>nil()));
|
||||||
for (JCTree.JCAnnotation i : annotations) {
|
}
|
||||||
|
|
||||||
|
private JCExpression nameToExpression(String dotName) {
|
||||||
|
String[] nameParts = dotName.split("\\.");
|
||||||
|
JCExpression e = cx.treeMaker.Ident(cx.names.fromString(nameParts[0]));
|
||||||
|
for (int i = 1 ; i < nameParts.length ; i++) {
|
||||||
|
e = cx.treeMaker.Select(e, cx.names.fromString(nameParts[i]));
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JCBlock testableSetupBlock() {
|
||||||
|
ListBuffer<JCStatement> statements = new ListBuffer<>();
|
||||||
|
for (Pair<Name, Pair<JCExpression, List<JCExpression>>> m : injectMethods.toList()) {
|
||||||
|
JCExpression key = nameToExpression("n.e.k");
|
||||||
|
JCExpression classType = m.snd.fst;
|
||||||
|
JCExpression parameterTypes = cx.treeMaker.NewArray(cx.treeMaker.Ident(cx.names.fromString("Class")),
|
||||||
|
List.<JCExpression>nil(), m.snd.snd);
|
||||||
|
JCNewClass keyClass = cx.treeMaker.NewClass(null, List.<JCExpression>nil(), key,
|
||||||
|
List.of(classType, parameterTypes), null);
|
||||||
|
JCExpression value = nameToExpression("n.e.v");
|
||||||
|
JCExpression thisIns = cx.treeMaker.Ident(cx.names.fromString("this"));
|
||||||
|
JCExpression methodName = cx.treeMaker.Literal(m.fst.toString());
|
||||||
|
JCNewClass valClass = cx.treeMaker.NewClass(null, List.<JCExpression>nil(), value,
|
||||||
|
List.of(thisIns, methodName), null);
|
||||||
|
JCExpression addInjectMethod = nameToExpression("n.e.a");
|
||||||
|
JCMethodInvocation apply = cx.treeMaker.Apply(List.<JCExpression>nil(), addInjectMethod,
|
||||||
|
List.from(new JCExpression[] {keyClass, valClass}));
|
||||||
|
statements.append(cx.treeMaker.Exec(apply));
|
||||||
|
}
|
||||||
|
if (!testSetupMethodName.isEmpty()) {
|
||||||
|
statements.append(cx.treeMaker.Exec(cx.treeMaker.Apply(List.<JCExpression>nil(),
|
||||||
|
nameToExpression(testSetupMethodName), List.<JCExpression>nil())));
|
||||||
|
}
|
||||||
|
return cx.treeMaker.Block(0, statements.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<JCAnnotation> removeAnnotation(List<JCAnnotation> annotations, String target) {
|
||||||
|
ListBuffer<JCAnnotation> nb = new ListBuffer<>();
|
||||||
|
for (JCAnnotation i : annotations) {
|
||||||
if (!i.type.tsym.toString().equals(target)) {
|
if (!i.type.tsym.toString().equals(target)) {
|
||||||
nb.add(i);
|
nb.add(i);
|
||||||
}
|
}
|
||||||
@ -150,19 +192,19 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
|||||||
return nb.toList();
|
return nb.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Name getStubbornSetterMethodName(JCTree.JCAssign assign) {
|
private Name getStubbornSetterMethodName(JCAssign assign) {
|
||||||
String name = ((JCTree.JCFieldAccess)assign.lhs).name.toString() + ConstPool.TESTABLE_SET_METHOD_PREFIX;
|
String name = ((JCFieldAccess)assign.lhs).name.toString() + ConstPool.TESTABLE_SET_METHOD_PREFIX;
|
||||||
return cx.names.fromString(name);
|
return cx.names.fromString(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAssignStubbornField(JCTree.JCAssign expr) {
|
private boolean isAssignStubbornField(JCAssign expr) {
|
||||||
return expr.lhs.getClass().equals(JCTree.JCFieldAccess.class) &&
|
return expr.lhs.getClass().equals(JCFieldAccess.class) &&
|
||||||
sourceClassIns.contains(((JCTree.JCIdent)((JCTree.JCFieldAccess)(expr).lhs).selected).name) &&
|
sourceClassIns.contains(((JCIdent)((JCFieldAccess)(expr).lhs).selected).name) &&
|
||||||
stubbornFields.contains(((JCTree.JCFieldAccess)(expr).lhs).name.toString());
|
stubbornFields.contains(((JCFieldAccess)(expr).lhs).name.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private JCTree.JCIdent getTestableClassIdent(JCTree.JCExpression clazz) {
|
private JCIdent getTestableClassIdent(JCExpression clazz) {
|
||||||
Name className = ((JCTree.JCIdent)clazz).name;
|
Name className = ((JCIdent)clazz).name;
|
||||||
return cx.treeMaker.Ident(cx.names.fromString(className + ConstPool.TESTABLE));
|
return cx.treeMaker.Ident(cx.names.fromString(className + ConstPool.TESTABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
71
src/main/resources/e.java
Normal file
71
src/main/resources/e.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package n;
|
||||||
|
|
||||||
|
import java.lang.Class;
|
||||||
|
import java.lang.Object;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public final class e {
|
||||||
|
|
||||||
|
public static class k {
|
||||||
|
public Class c; // target instance type
|
||||||
|
public Class[] a; // constructor parameter types
|
||||||
|
|
||||||
|
public k(Class c, Class[] a) {
|
||||||
|
this.c = c;
|
||||||
|
this.a = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o.getClass().equals(k.class) && c.equals(((k)o).c) && Arrays.equals(a, ((k)o).a);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 31 * c.hashCode() + Arrays.hashCode(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class v {
|
||||||
|
public Object o; // testable object
|
||||||
|
public String m; // method to create instance
|
||||||
|
|
||||||
|
public v(Object o, String m) {
|
||||||
|
this.o = o;
|
||||||
|
this.m = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<k, v> pool = new HashMap<>();
|
||||||
|
|
||||||
|
public static void a(k ki, v vi) {
|
||||||
|
pool.put(ki, vi);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T w(Class<T> ct, Object... as) {
|
||||||
|
Class[] cs = new Class[as.length / 2];
|
||||||
|
Object[] ps = new Object[as.length / 2];
|
||||||
|
for (int i = 0; i < cs.length; i++) {
|
||||||
|
cs[i] = (Class)as[i];
|
||||||
|
}
|
||||||
|
System.arraycopy(as, ps.length, ps, 0, ps.length);
|
||||||
|
if (!pool.isEmpty()) {
|
||||||
|
try {
|
||||||
|
v p = pool.get(new k(ct, cs));
|
||||||
|
if (p != null) {
|
||||||
|
Method m = p.o.getClass().getDeclaredMethod(p.m, cs);
|
||||||
|
m.setAccessible(true);
|
||||||
|
return (T)m.invoke(p.o, ps);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return ct.getConstructor(cs).newInstance(ps);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user