-
Notifications
You must be signed in to change notification settings - Fork 1
/
RpcUtilsCracker.java
66 lines (62 loc) · 2.83 KB
/
RpcUtilsCracker.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.github.cherrythefatbunny.reactive.dubbo.extensions.rpc.support;
import javassist.*;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.Invocation;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
/**
* crack RpcUtils.getReturnTypes,supporting mono and flux
* @author cherry
*/
public class RpcUtilsCracker {
private static final Logger LOGGER = LoggerFactory.getLogger(RpcUtilsCracker.class);
private static final String RPCUTILS_CLASS_NAME = "org.apache.dubbo.rpc.support.RpcUtils";
public static void crack() {
try {
ClassPool classPool = ClassPool.getDefault();
classPool.appendClassPath(new LoaderClassPath(RpcUtilsCracker.class.getClassLoader()));
CtClass ctClass = classPool.get(RPCUTILS_CLASS_NAME);
CtMethod ctMethod = ctClass.getDeclaredMethod("getReturnTypes");
//rename method `getReturnTypes` to `getReturnTypes0`
ctClass.removeMethod(ctMethod);
ctMethod.setName("getReturnTypes0");
ctClass.addMethod(ctMethod);
//add new method `getReturnTypes` according to RpcUtilsCracker.getReturnTypes
CtClass ctClass1 = classPool.get(RpcUtilsCracker.class.getName());
ctMethod = new CtMethod(ctClass1.getDeclaredMethod("getReturnTypes"),ctClass,null);
ctClass.addMethod(ctMethod);
ctClass.toClass();
} catch (NotFoundException|CannotCompileException e) {
LOGGER.error("crack RpcUtils failed",e);
}
}
public static Type[] getReturnTypes0(Invocation invocation) {
return null;
}
/**
* template method of RpcUtils.getReturnTypes
* @param invocation the invocation instance of the interface
* @return return types of the invokee
* */
public static Type[] getReturnTypes(Invocation invocation) {
Type[] types = getReturnTypes0(invocation);
if(types==null)return null;
if (types[0] == Mono.class) {
Class<Mono> returnType = (Class<Mono>) types[0];
ParameterizedType genericReturnType = (ParameterizedType) types[1];
return new Type[]{genericReturnType.getActualTypeArguments()[0]};
}
if (types[0] == Flux.class) {
Class<Flux> returnType = (Class<Flux>) types[0];
ParameterizedType genericReturnType = (ParameterizedType) types[1];
genericReturnType = ParameterizedTypeImpl.make(List.class,new Type[]{genericReturnType.getActualTypeArguments()[0]},null);
return new Type[]{List.class, genericReturnType};
}
return types;
}
}