use of org.redkale.asm.MethodDebugVisitor in project redkale by redkale.
the class Rest method createRestWebSocketServlet.
public static <T extends HttpServlet> T createRestWebSocketServlet(final ClassLoader classLoader, final Class<? extends WebSocket> webSocketType) {
if (webSocketType == null)
throw new RuntimeException("Rest WebSocket Class is null on createRestWebSocketServlet");
if (Modifier.isAbstract(webSocketType.getModifiers()))
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot abstract on createRestWebSocketServlet");
if (Modifier.isFinal(webSocketType.getModifiers()))
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot final on createRestWebSocketServlet");
final RestWebSocket rws = webSocketType.getAnnotation(RestWebSocket.class);
if (rws == null || rws.ignore())
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") have not @RestWebSocket or @RestWebSocket.ignore=true on createRestWebSocketServlet");
boolean valid = false;
for (Constructor c : webSocketType.getDeclaredConstructors()) {
if (c.getParameterCount() == 0 && (Modifier.isPublic(c.getModifiers()) || Modifier.isProtected(c.getModifiers()))) {
valid = true;
break;
}
}
if (!valid)
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") must have public or protected Constructor on createRestWebSocketServlet");
final String rwsname = ResourceFactory.formatResourceName(rws.name());
if (!checkName(rws.catalog()))
throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".catalog, only 0-9 a-z A-Z _ cannot begin 0-9");
if (!checkName(rwsname))
throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".name, only 0-9 a-z A-Z _ cannot begin 0-9");
// ----------------------------------------------------------------------------------------
final Set<Field> resourcesFieldSet = new LinkedHashSet<>();
final ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
final Set<String> resourcesFieldNameSet = new HashSet<>();
Class clzz = webSocketType;
do {
for (Field field : clzz.getDeclaredFields()) {
if (field.getAnnotation(Resource.class) == null)
continue;
if (resourcesFieldNameSet.contains(field.getName()))
continue;
if (Modifier.isStatic(field.getModifiers()))
throw new RuntimeException(field + " cannot static on createRestWebSocketServlet");
if (Modifier.isFinal(field.getModifiers()))
throw new RuntimeException(field + " cannot final on createRestWebSocketServlet");
if (!Modifier.isPublic(field.getModifiers()) && !Modifier.isProtected(field.getModifiers())) {
throw new RuntimeException(field + " must be public or protected on createRestWebSocketServlet");
}
resourcesFieldNameSet.add(field.getName());
resourcesFieldSet.add(field);
}
} while ((clzz = clzz.getSuperclass()) != Object.class);
final List<Field> resourcesFields = new ArrayList<>(resourcesFieldSet);
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < resourcesFields.size(); i++) {
Field field = resourcesFields.get(i);
sb1.append(Type.getDescriptor(field.getType()));
sb2.append(Utility.getTypeDescriptor(field.getGenericType()));
}
final String resourceDescriptor = sb1.toString();
final String resourceGenericDescriptor = sb1.length() == sb2.length() ? null : sb2.toString();
// ----------------------------------------------------------------------------------------
final Map<String, List<String>> asmParamMap = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), webSocketType);
final Set<String> messageNames = new HashSet<>();
final List<Method> messageMethods = new ArrayList<>();
for (Method method : webSocketType.getMethods()) {
RestOnMessage rom = method.getAnnotation(RestOnMessage.class);
if (rom == null)
continue;
String name = rom.name();
if (Modifier.isFinal(method.getModifiers()))
throw new RuntimeException("@RestOnMessage method can not final but (" + method + ")");
if (Modifier.isStatic(method.getModifiers()))
throw new RuntimeException("@RestOnMessage method can not static but (" + method + ")");
if (method.getReturnType() != void.class)
throw new RuntimeException("@RestOnMessage method must return void but (" + method + ")");
if (method.getExceptionTypes().length > 0)
throw new RuntimeException("@RestOnMessage method can not throw exception but (" + method + ")");
if (name.isEmpty())
throw new RuntimeException(method + " RestOnMessage.name is empty createRestWebSocketServlet");
if (messageNames.contains(name))
throw new RuntimeException(method + " repeat RestOnMessage.name(" + name + ") createRestWebSocketServlet");
messageNames.add(name);
messageMethods.add(method);
}
// ----------------------------------------------------------------------------------------
final String resDesc = Type.getDescriptor(Resource.class);
final String wsDesc = Type.getDescriptor(WebSocket.class);
final String wsParamDesc = Type.getDescriptor(WebSocketParam.class);
final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
final String convertDisabledDesc = Type.getDescriptor(ConvertDisabled.class);
final String webSocketParamName = Type.getInternalName(WebSocketParam.class);
final String supDynName = WebSocketServlet.class.getName().replace('.', '/');
final String webServletDesc = Type.getDescriptor(WebServlet.class);
final String webSocketInternalName = Type.getInternalName(webSocketType);
final String newDynName = webSocketInternalName.substring(0, webSocketInternalName.lastIndexOf('/') + 1) + "_Dyn" + webSocketType.getSimpleName() + "Servlet";
final String newDynWebSokcetSimpleName = "_Dyn" + webSocketType.getSimpleName();
final String newDynWebSokcetFullName = newDynName + "$" + newDynWebSokcetSimpleName;
final String newDynMessageSimpleName = "_Dyn" + webSocketType.getSimpleName() + "Message";
final String newDynMessageFullName = newDynName + "$" + newDynMessageSimpleName;
final String newDynConsumerSimpleName = "_DynRestOnMessageConsumer";
final String newDynConsumerFullName = newDynName + "$" + newDynConsumerSimpleName;
// ----------------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodDebugVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
// RestDynSourceType
av0 = cw.visitAnnotation(Type.getDescriptor(RestDynSourceType.class), true);
av0.visit("value", Type.getType(Type.getDescriptor(webSocketType)));
av0.visitEnd();
}
{
// 注入 @WebServlet 注解
String urlpath = (rws.catalog().isEmpty() ? "/" : ("/" + rws.catalog() + "/")) + rwsname;
av0 = cw.visitAnnotation(webServletDesc, true);
{
AnnotationVisitor av1 = av0.visitArray("value");
av1.visit(null, urlpath);
av1.visitEnd();
}
av0.visit("moduleid", 0);
av0.visit("repair", rws.repair());
av0.visit("comment", rws.comment());
av0.visitEnd();
}
{
// 内部类
cw.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
cw.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
cw.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
for (int i = 0; i < messageMethods.size(); i++) {
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
cw.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
}
}
{
// @Resource
for (int i = 0; i < resourcesFields.size(); i++) {
Field field = resourcesFields.get(i);
Resource res = field.getAnnotation(Resource.class);
java.lang.reflect.Type fieldType = field.getGenericType();
fv = cw.visitField(ACC_PRIVATE, "_redkale_resource_" + i, Type.getDescriptor(field.getType()), fieldType == field.getType() ? null : Utility.getTypeDescriptor(fieldType), null);
{
av0 = fv.visitAnnotation(resDesc, true);
av0.visit("name", res.name());
av0.visitEnd();
}
fv.visitEnd();
}
}
{
// _DynWebSocketServlet构造函数
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(Type.getObjectType(newDynName + "$" + newDynWebSokcetSimpleName + "Message"));
mv.visitFieldInsn(PUTFIELD, newDynName, "messageTextType", "Ljava/lang/reflect/Type;");
mv.visitVarInsn(ALOAD, 0);
pushInt(mv, rws.liveinterval());
mv.visitFieldInsn(PUTFIELD, newDynName, "liveinterval", "I");
mv.visitVarInsn(ALOAD, 0);
pushInt(mv, rws.wsmaxconns());
mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxconns", "I");
mv.visitVarInsn(ALOAD, 0);
pushInt(mv, rws.wsmaxbody());
mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxbody", "I");
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(rws.single() ? ICONST_1 : ICONST_0);
mv.visitFieldInsn(PUTFIELD, newDynName, "single", "Z");
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(rws.anyuser() ? ICONST_1 : ICONST_0);
mv.visitFieldInsn(PUTFIELD, newDynName, "anyuser", "Z");
mv.visitInsn(RETURN);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
{
// createWebSocket 方法
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createWebSocket", "()" + wsDesc, "<G::Ljava/io/Serializable;T:Ljava/lang/Object;>()L" + WebSocket.class.getName().replace('.', '/') + "<TG;TT;>;", null));
mv.visitTypeInsn(NEW, newDynName + "$" + newDynWebSokcetSimpleName);
mv.visitInsn(DUP);
for (int i = 0; i < resourcesFields.size(); i++) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_resource_" + i, Type.getDescriptor(resourcesFields.get(i).getType()));
}
mv.visitMethodInsn(INVOKESPECIAL, newDynWebSokcetFullName, "<init>", "(" + resourceDescriptor + ")V", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2 + resourcesFields.size(), 1);
mv.visitEnd();
}
{
// createRestOnMessageConsumer
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createRestOnMessageConsumer", "()Ljava/util/function/BiConsumer;", "()Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", null));
mv.visitTypeInsn(NEW, newDynConsumerFullName);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, newDynConsumerFullName, "<init>", "()V", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
{
// resourceName
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "resourceName", "()Ljava/lang/String;", null, null));
mv.visitLdcInsn(rwsname);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
RestClassLoader newLoader = new RestClassLoader(loader);
for (int i = 0; i < messageMethods.size(); i++) {
// _DyncXXXWebSocketMessage 子消息List
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynMessageFullName + endfix, null, "java/lang/Object", new String[] { webSocketParamName, "java/lang/Runnable" });
cw2.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
Set<String> paramnames = new HashSet<>();
String methodesc = method.getName() + ":" + Type.getMethodDescriptor(method);
List<String> names = asmParamMap.get(methodesc);
Parameter[] params = method.getParameters();
// 必须使用LinkedHashMap确保顺序
final LinkedHashMap<String, Parameter> paramap = new LinkedHashMap();
for (int j = 0; j < params.length; j++) {
// 字段列表
Parameter param = params[j];
String paramname = param.getName();
RestParam rp = param.getAnnotation(RestParam.class);
if (rp != null && !rp.name().isEmpty()) {
paramname = rp.name();
} else if (names != null && names.size() > j) {
paramname = names.get(j);
}
if (paramnames.contains(paramname))
throw new RuntimeException(method + " has same @RestParam.name");
paramnames.add(paramname);
paramap.put(paramname, param);
fv = cw2.visitField(ACC_PUBLIC, paramname, Type.getDescriptor(param.getType()), param.getType() == param.getParameterizedType() ? null : Utility.getTypeDescriptor(param.getParameterizedType()), null);
fv.visitEnd();
}
{
// _redkale_websocket
fv = cw2.visitField(ACC_PUBLIC, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";", null, null);
av0 = fv.visitAnnotation(convertDisabledDesc, true);
av0.visitEnd();
fv.visitEnd();
}
{
// 空构造函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// getNames
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getNames", "()[Ljava/lang/String;", null, null));
pushInt(mv, paramap.size());
mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
int index = -1;
for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
mv.visitInsn(DUP);
pushInt(mv, ++index);
mv.visitLdcInsn(en.getKey());
mv.visitInsn(AASTORE);
}
mv.visitInsn(ARETURN);
mv.visitMaxs(paramap.size() + 2, 1);
mv.visitEnd();
}
{
// getValue
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getValue", "(Ljava/lang/String;)Ljava/lang/Object;", "<T:Ljava/lang/Object;>(Ljava/lang/String;)TT;", null));
for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
Class paramType = en.getValue().getType();
mv.visitLdcInsn(en.getKey());
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynMessageFullName + endfix, en.getKey(), Type.getDescriptor(paramType));
if (paramType.isPrimitive()) {
Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(paramType, 1), 0).getClass();
mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(paramType) + ")" + Type.getDescriptor(bigclaz), false);
}
mv.visitInsn(ARETURN);
mv.visitLabel(l1);
}
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
{
// execute
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "execute", "(L" + newDynWebSokcetFullName + ";)V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, newDynMessageFullName + endfix, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(method.getAnnotation(RestOnMessage.class).name());
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, "preOnMessage", "(Ljava/lang/String;" + wsParamDesc + "Ljava/lang/Runnable;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
{
// run
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "run", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynMessageFullName + endfix, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, (newDynMessageFullName + endfix), en.getKey(), Type.getDescriptor(en.getValue().getType()));
}
mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, method.getName(), Type.getMethodDescriptor(method), false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
{
// toString
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
cw2.visitEnd();
newLoader.loadClass((newDynMessageFullName + endfix).replace('/', '.'), cw2.toByteArray());
}
{
// _DynXXXWebSocketMessage class
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynMessageFullName, null, "java/lang/Object", null);
cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
for (int i = 0; i < messageMethods.size(); i++) {
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
cw2.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
fv = cw2.visitField(ACC_PUBLIC, method.getAnnotation(RestOnMessage.class).name(), "L" + newDynMessageFullName + endfix + ";", null, null);
fv.visitEnd();
}
{
// 构造函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// toString
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
cw2.visitEnd();
newLoader.loadClass(newDynMessageFullName.replace('/', '.'), cw2.toByteArray());
}
{
// _DynXXXWebSocket class
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynWebSokcetFullName, null, webSocketInternalName, null);
cw2.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
{
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + resourceDescriptor + ")V", resourceGenericDescriptor == null ? null : ("(" + resourceGenericDescriptor + ")V"), null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, webSocketInternalName, "<init>", "()V", false);
for (int i = 0; i < resourcesFields.size(); i++) {
Field field = resourcesFields.get(i);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, i + 1);
mv.visitFieldInsn(PUTFIELD, newDynWebSokcetFullName, field.getName(), Type.getDescriptor(field.getType()));
}
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1 + resourcesFields.size());
mv.visitEnd();
}
cw2.visitEnd();
newLoader.loadClass(newDynWebSokcetFullName.replace('/', '.'), cw2.toByteArray());
}
{
// _DynRestOnMessageConsumer class
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynConsumerFullName, "Ljava/lang/Object;Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", "java/lang/Object", new String[] { "java/util/function/BiConsumer" });
cw2.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
for (int i = 0; i < messageMethods.size(); i++) {
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
cw2.visitInnerClass(newDynMessageFullName + endfix, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
}
{
// 构造函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// accept函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", null, null));
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, newDynWebSokcetFullName);
mv.visitVarInsn(ASTORE, 3);
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, newDynMessageFullName);
mv.visitVarInsn(ASTORE, 4);
for (int i = 0; i < messageMethods.size(); i++) {
final Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
final String messagename = method.getAnnotation(RestOnMessage.class).name();
mv.visitVarInsn(ALOAD, 4);
mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + (newDynMessageFullName + endfix) + ";");
Label ifLabel = new Label();
mv.visitJumpInsn(IFNULL, ifLabel);
mv.visitVarInsn(ALOAD, 4);
mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + (newDynMessageFullName + endfix) + ";");
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKEVIRTUAL, (newDynMessageFullName + endfix), "execute", "(L" + newDynWebSokcetFullName + ";)V", false);
mv.visitInsn(RETURN);
mv.visitLabel(ifLabel);
}
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3 + messageMethods.size());
mv.visitEnd();
}
{
// 虚拟accept函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "accept", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, WebSocket.class.getName().replace('.', '/'));
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, "java/lang/Object");
mv.visitMethodInsn(INVOKEVIRTUAL, newDynConsumerFullName, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw2.visitEnd();
newLoader.loadClass(newDynConsumerFullName.replace('/', '.'), cw2.toByteArray());
}
cw.visitEnd();
Class<?> newClazz = newLoader.loadClass(newDynName.replace('/', '.'), cw.toByteArray());
try {
return (T) newClazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.redkale.asm.MethodDebugVisitor in project redkale by redkale.
the class Sncp method createRemoteService.
/**
* <blockquote><pre>
* @Resource(name = "")
* @SncpDyn(remote = true)
* @ResourceType(TestService.class)
* public final class _DynRemoteTestService extends TestService{
*
* private AnyValue _redkale_conf;
*
* private SncpClient _redkale_client;
*
* @SncpDyn(remote = false, index = 0)
* public void _redkale_createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){
* _redkale_client.remote(0, selfrunnable, samerunnable, diffrunnable, bean);
* }
*
* @SncpDyn(remote = false, index = 1)
* public String _redkale_updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){
* return _redkale_client.remote(1, selfrunnable, samerunnable, diffrunnable, id);
* }
*
* @Override
* public void createSomeThing(TestBean bean){
* _redkale_client.remote(2, bean);
* }
*
* @Override
* public String findSomeThing(){
* return _redkale_client.remote(3);
* }
*
* @Override
* public String updateSomeThing(String id){
* return _redkale_client.remote(4, id);
* }
* }
* </pre></blockquote>
*
* 创建远程模式的Service实例
*
* @param <T> Service泛型
* @param classLoader ClassLoader
* @param name 资源名
* @param serviceTypeOrImplClass Service类
* @param transportFactory TransportFactory
* @param clientAddress 本地IP地址
* @param groups0 所有的组节点,包含自身
* @param conf 启动配置项
*
* @return Service的远程模式实例
*/
@SuppressWarnings("unchecked")
public static <T extends Service> T createRemoteService(final ClassLoader classLoader, final String name, final Class<T> serviceTypeOrImplClass, final TransportFactory transportFactory, final InetSocketAddress clientAddress, final Set<String> groups0, final AnyValue conf) {
if (serviceTypeOrImplClass == null)
return null;
if (!Service.class.isAssignableFrom(serviceTypeOrImplClass))
return null;
Set<String> groups = groups0 == null ? new HashSet<>() : groups0;
ResourceFactory.checkResourceName(name);
int mod = serviceTypeOrImplClass.getModifiers();
boolean realed = !(java.lang.reflect.Modifier.isAbstract(mod) || serviceTypeOrImplClass.isInterface());
if (!java.lang.reflect.Modifier.isPublic(mod))
return null;
final String supDynName = serviceTypeOrImplClass.getName().replace('.', '/');
final String clientName = SncpClient.class.getName().replace('.', '/');
final String resDesc = Type.getDescriptor(Resource.class);
final String clientDesc = Type.getDescriptor(SncpClient.class);
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceTypeOrImplClass.getSimpleName();
try {
Class newClazz = loader.loadClass(newDynName.replace('/', '.'));
T rs = (T) newClazz.getDeclaredConstructor().newInstance();
SncpClient client = new SncpClient(name, serviceTypeOrImplClass, rs, transportFactory, true, realed ? createLocalServiceClass(loader, name, serviceTypeOrImplClass) : serviceTypeOrImplClass, clientAddress);
client.setRemoteGroups(groups);
client.setRemoteGroupTransport(transportFactory.loadRemoteTransport(clientAddress, groups));
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
c.setAccessible(true);
c.set(rs, client);
transportFactory.addSncpService(rs);
return rs;
} catch (Throwable ex) {
}
// ------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodDebugVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, serviceTypeOrImplClass.isInterface() ? "java/lang/Object" : supDynName, serviceTypeOrImplClass.isInterface() ? new String[] { supDynName } : null);
{
av0 = cw.visitAnnotation(resDesc, true);
av0.visit("name", name);
av0.visitEnd();
}
{
av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
ResourceType rty = serviceTypeOrImplClass.getAnnotation(ResourceType.class);
av0.visit("value", Type.getType(Type.getDescriptor(rty == null ? serviceTypeOrImplClass : rty.value())));
av0.visitEnd();
}
{
av0 = cw.visitAnnotation(sncpDynDesc, true);
av0.visit("remote", Boolean.TRUE);
av0.visitEnd();
}
{
// 给新类加上 原有的Annotation
for (Annotation ann : serviceTypeOrImplClass.getAnnotations()) {
if (ann instanceof Resource || ann instanceof SncpDyn || ann instanceof ResourceType)
continue;
visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
}
}
{
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
fv.visitEnd();
}
{
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_client", clientDesc, null, null);
fv.visitEnd();
}
{
// 构造函数
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
// mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, serviceTypeOrImplClass.isInterface() ? "java/lang/Object" : supDynName, "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// init
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "init", "(" + anyValueDesc + ")V", null, null));
mv.visitInsn(RETURN);
mv.visitMaxs(0, 2);
mv.visitEnd();
}
{
// destroy
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "destroy", "(" + anyValueDesc + ")V", null, null));
mv.visitInsn(RETURN);
mv.visitMaxs(0, 2);
mv.visitEnd();
}
{
// toString()
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
Label l1 = new Label();
mv.visitJumpInsn(IFNONNULL, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
Label l2 = new Label();
mv.visitJumpInsn(GOTO, l2);
mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "toSimpleString", "()Ljava/lang/String;", false);
mv.visitLabel(l2);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
int i = -1;
for (final SncpAction entry : SncpClient.getSncpActions(realed ? createLocalServiceClass(loader, name, serviceTypeOrImplClass) : serviceTypeOrImplClass)) {
final int index = ++i;
final java.lang.reflect.Method method = entry.method;
{
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, method.getName(), Type.getMethodDescriptor(method), null, null));
// mv.setDebug(true);
{
// 给参数加上 Annotation
final Annotation[][] anns = method.getParameterAnnotations();
for (int k = 0; k < anns.length; k++) {
for (Annotation ann : anns[k]) {
visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
}
}
}
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
pushInt(mv, index);
{
// 传参数
int paramlen = entry.paramTypes.length;
pushInt(mv, paramlen);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
java.lang.reflect.Type[] paramtypes = entry.paramTypes;
int insn = 0;
for (int j = 0; j < paramtypes.length; j++) {
final java.lang.reflect.Type pt = paramtypes[j];
mv.visitInsn(DUP);
insn++;
pushInt(mv, j);
if (pt instanceof Class && ((Class) pt).isPrimitive()) {
if (pt == long.class) {
mv.visitVarInsn(LLOAD, insn++);
} else if (pt == float.class) {
mv.visitVarInsn(FLOAD, insn++);
} else if (pt == double.class) {
mv.visitVarInsn(DLOAD, insn++);
} else {
mv.visitVarInsn(ILOAD, insn);
}
Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance((Class) pt, 1), 0).getClass();
mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor((Class) pt) + ")" + Type.getDescriptor(bigclaz), false);
} else {
mv.visitVarInsn(ALOAD, insn);
}
mv.visitInsn(AASTORE);
}
}
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "remote", "(I[Ljava/lang/Object;)Ljava/lang/Object;", false);
// mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
if (method.getGenericReturnType() == void.class) {
mv.visitInsn(POP);
mv.visitInsn(RETURN);
} else {
Class returnclz = method.getReturnType();
Class bigPrimitiveClass = returnclz.isPrimitive() ? java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(returnclz, 1), 0).getClass() : returnclz;
mv.visitTypeInsn(CHECKCAST, (returnclz.isPrimitive() ? bigPrimitiveClass : returnclz).getName().replace('.', '/'));
if (returnclz.isPrimitive()) {
String bigPrimitiveName = bigPrimitiveClass.getName().replace('.', '/');
try {
java.lang.reflect.Method pm = bigPrimitiveClass.getMethod(returnclz.getSimpleName() + "Value");
mv.visitMethodInsn(INVOKEVIRTUAL, bigPrimitiveName, pm.getName(), Type.getMethodDescriptor(pm), false);
} catch (Exception ex) {
// 不可能会发生
throw new RuntimeException(ex);
}
if (returnclz == long.class) {
mv.visitInsn(LRETURN);
} else if (returnclz == float.class) {
mv.visitInsn(FRETURN);
} else if (returnclz == double.class) {
mv.visitInsn(DRETURN);
} else {
mv.visitInsn(IRETURN);
}
} else {
mv.visitInsn(ARETURN);
}
}
mv.visitMaxs(20, 20);
mv.visitEnd();
}
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Class<?> newClazz = new ClassLoader(loader) {
public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
try {
T rs = (T) newClazz.getDeclaredConstructor().newInstance();
SncpClient client = new SncpClient(name, serviceTypeOrImplClass, rs, transportFactory, true, realed ? createLocalServiceClass(loader, name, serviceTypeOrImplClass) : serviceTypeOrImplClass, clientAddress);
client.setRemoteGroups(groups);
client.setRemoteGroupTransport(transportFactory.loadRemoteTransport(clientAddress, groups));
{
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
c.setAccessible(true);
c.set(rs, client);
}
{
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
c.setAccessible(true);
c.set(rs, conf);
}
transportFactory.addSncpService(rs);
return rs;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
use of org.redkale.asm.MethodDebugVisitor in project redkale by redkale.
the class Rest method createRestWebSocketServlet.
public static <T extends WebSocketServlet> T createRestWebSocketServlet(final ClassLoader classLoader, final Class<? extends WebSocket> webSocketType, MessageAgent messageAgent) {
if (webSocketType == null)
throw new RuntimeException("Rest WebSocket Class is null on createRestWebSocketServlet");
if (Modifier.isAbstract(webSocketType.getModifiers()))
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot abstract on createRestWebSocketServlet");
if (Modifier.isFinal(webSocketType.getModifiers()))
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") cannot final on createRestWebSocketServlet");
final RestWebSocket rws = webSocketType.getAnnotation(RestWebSocket.class);
if (rws == null || rws.ignore())
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") have not @RestWebSocket or @RestWebSocket.ignore=true on createRestWebSocketServlet");
boolean valid = false;
for (Constructor c : webSocketType.getDeclaredConstructors()) {
if (c.getParameterCount() == 0 && (Modifier.isPublic(c.getModifiers()) || Modifier.isProtected(c.getModifiers()))) {
valid = true;
break;
}
}
if (!valid)
throw new RuntimeException("Rest WebSocket Class(" + webSocketType + ") must have public or protected Constructor on createRestWebSocketServlet");
final String rwsname = ResourceFactory.formatResourceName(rws.name());
if (!checkName(rws.catalog()))
throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".catalog, only 0-9 a-z A-Z _ cannot begin 0-9");
if (!checkName(rwsname))
throw new RuntimeException(webSocketType.getName() + " have illegal " + RestWebSocket.class.getSimpleName() + ".name, only 0-9 a-z A-Z _ cannot begin 0-9");
// ----------------------------------------------------------------------------------------
final Set<Field> resourcesFieldSet = new LinkedHashSet<>();
final ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
final Set<String> resourcesFieldNameSet = new HashSet<>();
Class clzz = webSocketType;
do {
for (Field field : clzz.getDeclaredFields()) {
if (field.getAnnotation(Resource.class) == null)
continue;
if (resourcesFieldNameSet.contains(field.getName()))
continue;
if (Modifier.isStatic(field.getModifiers()))
throw new RuntimeException(field + " cannot static on createRestWebSocketServlet");
if (Modifier.isFinal(field.getModifiers()))
throw new RuntimeException(field + " cannot final on createRestWebSocketServlet");
if (!Modifier.isPublic(field.getModifiers()) && !Modifier.isProtected(field.getModifiers())) {
throw new RuntimeException(field + " must be public or protected on createRestWebSocketServlet");
}
resourcesFieldNameSet.add(field.getName());
resourcesFieldSet.add(field);
}
} while ((clzz = clzz.getSuperclass()) != Object.class);
// ----------------------------------------------------------------------------------------
boolean namePresent = false;
try {
Method m0 = null;
for (Method method : webSocketType.getMethods()) {
if (method.getParameterCount() > 0) {
m0 = method;
break;
}
}
namePresent = m0 == null ? true : m0.getParameters()[0].isNamePresent();
} catch (Exception e) {
}
final Map<String, List<String>> asmParamMap = namePresent ? null : MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), webSocketType);
final Set<String> messageNames = new HashSet<>();
Method wildcardMethod = null;
List<Method> mmethods = new ArrayList<>();
for (Method method : webSocketType.getMethods()) {
RestOnMessage rom = method.getAnnotation(RestOnMessage.class);
if (rom == null)
continue;
String name = rom.name();
if (!"*".equals(name) && !checkName(name))
throw new RuntimeException("@RestOnMessage.name contains illegal characters on (" + method + ")");
if (Modifier.isFinal(method.getModifiers()))
throw new RuntimeException("@RestOnMessage method can not final but (" + method + ")");
if (Modifier.isStatic(method.getModifiers()))
throw new RuntimeException("@RestOnMessage method can not static but (" + method + ")");
if (method.getReturnType() != void.class)
throw new RuntimeException("@RestOnMessage method must return void but (" + method + ")");
if (method.getExceptionTypes().length > 0)
throw new RuntimeException("@RestOnMessage method can not throw exception but (" + method + ")");
if (name.isEmpty())
throw new RuntimeException(method + " RestOnMessage.name is empty createRestWebSocketServlet");
if (messageNames.contains(name))
throw new RuntimeException(method + " repeat RestOnMessage.name(" + name + ") createRestWebSocketServlet");
messageNames.add(name);
if ("*".equals(name)) {
wildcardMethod = method;
} else {
mmethods.add(method);
}
}
final List<Method> messageMethods = new ArrayList<>();
messageMethods.addAll(mmethods);
// wildcardMethod 必须放最后, _DynRestOnMessageConsumer 是按messageMethods顺序来判断的
if (wildcardMethod != null)
messageMethods.add(wildcardMethod);
// ----------------------------------------------------------------------------------------
final String resDesc = Type.getDescriptor(Resource.class);
final String wsDesc = Type.getDescriptor(WebSocket.class);
final String wsParamDesc = Type.getDescriptor(WebSocketParam.class);
final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
final String convertDisabledDesc = Type.getDescriptor(ConvertDisabled.class);
final String webSocketParamName = Type.getInternalName(WebSocketParam.class);
final String supDynName = WebSocketServlet.class.getName().replace('.', '/');
final String webServletDesc = Type.getDescriptor(WebServlet.class);
final String webSocketInternalName = Type.getInternalName(webSocketType);
final String newDynName = "org/redkaledyn/http/restws/" + "_DynWebScoketServlet__" + webSocketType.getName().replace('.', '_').replace('$', '_');
final String newDynWebSokcetSimpleName = "_Dyn" + webSocketType.getSimpleName();
final String newDynWebSokcetFullName = newDynName + "$" + newDynWebSokcetSimpleName;
final String newDynMessageSimpleName = "_Dyn" + webSocketType.getSimpleName() + "Message";
final String newDynMessageFullName = newDynName + "$" + newDynMessageSimpleName;
final String newDynConsumerSimpleName = "_DynRestOnMessageConsumer";
final String newDynConsumerFullName = newDynName + "$" + newDynConsumerSimpleName;
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
if (clz == null)
clz = loader.loadClass(newDynName.replace('/', '.'));
T servlet = (T) clz.getDeclaredConstructor().newInstance();
Map<String, Annotation[]> msgclassToAnnotations = new HashMap<>();
for (int i = 0; i < messageMethods.size(); i++) {
// _DyncXXXWebSocketMessage 子消息List
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
msgclassToAnnotations.put(newDynSuperMessageFullName, method.getAnnotations());
}
clz.getField("_redkale_annotations").set(null, msgclassToAnnotations);
if (rws.cryptor() != Cryptor.class) {
Cryptor cryptor = rws.cryptor().getDeclaredConstructor().newInstance();
// WebSocketServlet
Field cryptorField = clz.getSuperclass().getDeclaredField("cryptor");
cryptorField.setAccessible(true);
cryptorField.set(servlet, cryptor);
}
if (messageAgent != null)
((WebSocketServlet) servlet).messageAgent = messageAgent;
return servlet;
} catch (Throwable e) {
}
final List<Field> resourcesFields = new ArrayList<>(resourcesFieldSet);
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < resourcesFields.size(); i++) {
Field field = resourcesFields.get(i);
sb1.append(Type.getDescriptor(field.getType()));
sb2.append(Utility.getTypeDescriptor(field.getGenericType()));
}
final String resourceDescriptor = sb1.toString();
final String resourceGenericDescriptor = sb1.length() == sb2.length() ? null : sb2.toString();
// ----------------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodDebugVisitor mv;
AnnotationVisitor av0;
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
// RestDyn
av0 = cw.visitAnnotation(Type.getDescriptor(RestDyn.class), true);
av0.visit("simple", false);
{
AnnotationVisitor av1 = av0.visitArray("types");
av1.visit(null, Type.getType("L" + newDynConsumerFullName.replace('.', '/') + ";"));
av1.visit(null, Type.getType("L" + newDynWebSokcetFullName.replace('.', '/') + ";"));
// 位置固定第三个,下面用Message类进行loadDecoder会用到
av1.visit(null, Type.getType("L" + newDynMessageFullName.replace('.', '/') + ";"));
av1.visitEnd();
}
av0.visitEnd();
}
{
// RestDynSourceType
av0 = cw.visitAnnotation(Type.getDescriptor(RestDynSourceType.class), true);
av0.visit("value", Type.getType(Type.getDescriptor(webSocketType)));
av0.visitEnd();
}
{
// 注入 @WebServlet 注解
String urlpath = (rws.catalog().isEmpty() ? "/" : ("/" + rws.catalog() + "/")) + rwsname;
av0 = cw.visitAnnotation(webServletDesc, true);
{
AnnotationVisitor av1 = av0.visitArray("value");
av1.visit(null, urlpath);
av1.visitEnd();
}
av0.visit("name", rwsname);
av0.visit("moduleid", 0);
av0.visit("repair", rws.repair());
av0.visit("comment", rws.comment());
av0.visitEnd();
}
{
// 内部类
cw.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
cw.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
cw.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
for (int i = 0; i < messageMethods.size(); i++) {
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
cw.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
}
}
{
// @Resource
for (int i = 0; i < resourcesFields.size(); i++) {
Field field = resourcesFields.get(i);
Resource res = field.getAnnotation(Resource.class);
java.lang.reflect.Type fieldType = field.getGenericType();
fv = cw.visitField(ACC_PRIVATE, "_redkale_resource_" + i, Type.getDescriptor(field.getType()), fieldType == field.getType() ? null : Utility.getTypeDescriptor(fieldType), null);
{
av0 = fv.visitAnnotation(resDesc, true);
av0.visit("name", res.name());
av0.visitEnd();
}
fv.visitEnd();
}
}
{
// _redkale_annotations
fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, "_redkale_annotations", "Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;[Ljava/lang/annotation/Annotation;>;", null);
fv.visitEnd();
}
{
// _DynWebSocketServlet构造函数
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(Type.getObjectType(newDynName + "$" + newDynWebSokcetSimpleName + "Message"));
mv.visitFieldInsn(PUTFIELD, newDynName, "messageRestType", "Ljava/lang/reflect/Type;");
mv.visitVarInsn(ALOAD, 0);
MethodDebugVisitor.pushInt(mv, rws.liveinterval());
mv.visitFieldInsn(PUTFIELD, newDynName, "liveinterval", "I");
mv.visitVarInsn(ALOAD, 0);
MethodDebugVisitor.pushInt(mv, rws.wsmaxconns());
mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxconns", "I");
mv.visitVarInsn(ALOAD, 0);
MethodDebugVisitor.pushInt(mv, rws.wsmaxbody());
mv.visitFieldInsn(PUTFIELD, newDynName, "wsmaxbody", "I");
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(rws.mergemsg() ? ICONST_1 : ICONST_0);
mv.visitFieldInsn(PUTFIELD, newDynName, "mergemsg", "Z");
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(rws.single() ? ICONST_1 : ICONST_0);
mv.visitFieldInsn(PUTFIELD, newDynName, "single", "Z");
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(rws.anyuser() ? ICONST_1 : ICONST_0);
mv.visitFieldInsn(PUTFIELD, newDynName, "anyuser", "Z");
mv.visitInsn(RETURN);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
{
// createWebSocket 方法
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createWebSocket", "()" + wsDesc, "<G::Ljava/io/Serializable;T:Ljava/lang/Object;>()L" + WebSocket.class.getName().replace('.', '/') + "<TG;TT;>;", null));
mv.visitTypeInsn(NEW, newDynName + "$" + newDynWebSokcetSimpleName);
mv.visitInsn(DUP);
for (int i = 0; i < resourcesFields.size(); i++) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_resource_" + i, Type.getDescriptor(resourcesFields.get(i).getType()));
}
mv.visitMethodInsn(INVOKESPECIAL, newDynWebSokcetFullName, "<init>", "(" + resourceDescriptor + ")V", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2 + resourcesFields.size(), 1);
mv.visitEnd();
}
{
// createRestOnMessageConsumer
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PROTECTED, "createRestOnMessageConsumer", "()Ljava/util/function/BiConsumer;", "()Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", null));
mv.visitTypeInsn(NEW, newDynConsumerFullName);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, newDynConsumerFullName, "<init>", "()V", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
{
// resourceName
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "resourceName", "()Ljava/lang/String;", null, null));
mv.visitLdcInsn(rwsname);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
RestClassLoader newLoader = new RestClassLoader(loader);
Map<String, Annotation[]> msgclassToAnnotations = new HashMap<>();
for (int i = 0; i < messageMethods.size(); i++) {
// _DyncXXXWebSocketMessage 子消息List
final Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
msgclassToAnnotations.put(newDynSuperMessageFullName, method.getAnnotations());
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynSuperMessageFullName, null, "java/lang/Object", new String[] { webSocketParamName, "java/lang/Runnable" });
cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
Set<String> paramnames = new HashSet<>();
String methodesc = method.getName() + ":" + Type.getMethodDescriptor(method);
List<String> names = asmParamMap == null ? null : asmParamMap.get(methodesc);
// 删掉空元素
if (names != null)
while (names.remove(" ")) ;
Parameter[] params = method.getParameters();
// 必须使用LinkedHashMap确保顺序
final LinkedHashMap<String, Parameter> paramap = new LinkedHashMap();
for (int j = 0; j < params.length; j++) {
// 字段列表
Parameter param = params[j];
String paramname = param.getName();
RestParam rp = param.getAnnotation(RestParam.class);
if (rp != null && !rp.name().isEmpty()) {
paramname = rp.name();
} else if (names != null && names.size() > j) {
paramname = names.get(j);
}
if (paramnames.contains(paramname))
throw new RuntimeException(method + " has same @RestParam.name");
paramnames.add(paramname);
paramap.put(paramname, param);
fv = cw2.visitField(ACC_PUBLIC, paramname, Type.getDescriptor(param.getType()), param.getType() == param.getParameterizedType() ? null : Utility.getTypeDescriptor(param.getParameterizedType()), null);
fv.visitEnd();
}
if (method == wildcardMethod) {
for (int j = 0; j < messageMethods.size(); j++) {
Method method2 = messageMethods.get(j);
if (method2 == wildcardMethod)
continue;
String endfix2 = "_" + method2.getName() + "_" + (j > 9 ? j : ("0" + j));
String newDynSuperMessageFullName2 = newDynMessageFullName + (method2 == wildcardMethod ? "" : endfix2);
cw2.visitInnerClass(newDynSuperMessageFullName2, newDynName, newDynMessageSimpleName + endfix2, ACC_PUBLIC + ACC_STATIC);
fv = cw2.visitField(ACC_PUBLIC, method2.getAnnotation(RestOnMessage.class).name(), "L" + newDynSuperMessageFullName2 + ";", null, null);
fv.visitEnd();
}
}
{
// _redkale_websocket
fv = cw2.visitField(ACC_PUBLIC, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";", null, null);
av0 = fv.visitAnnotation(convertDisabledDesc, true);
av0.visitEnd();
fv.visitEnd();
}
{
// 空构造函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// getNames
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getNames", "()[Ljava/lang/String;", null, null));
av0 = mv.visitAnnotation(convertDisabledDesc, true);
av0.visitEnd();
MethodDebugVisitor.pushInt(mv, paramap.size());
mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
int index = -1;
for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
mv.visitInsn(DUP);
MethodDebugVisitor.pushInt(mv, ++index);
mv.visitLdcInsn(en.getKey());
mv.visitInsn(AASTORE);
}
mv.visitInsn(ARETURN);
mv.visitMaxs(paramap.size() + 2, 1);
mv.visitEnd();
}
{
// getValue
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getValue", "(Ljava/lang/String;)Ljava/lang/Object;", "<T:Ljava/lang/Object;>(Ljava/lang/String;)TT;", null));
for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
Class paramType = en.getValue().getType();
mv.visitLdcInsn(en.getKey());
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynSuperMessageFullName, en.getKey(), Type.getDescriptor(paramType));
if (paramType.isPrimitive()) {
Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(paramType, 1), 0).getClass();
mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(paramType) + ")" + Type.getDescriptor(bigclaz), false);
}
mv.visitInsn(ARETURN);
mv.visitLabel(l1);
}
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
{
// getAnnotations
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "getAnnotations", "()[Ljava/lang/annotation/Annotation;", null, null));
av0 = mv.visitAnnotation(convertDisabledDesc, true);
av0.visitEnd();
mv.visitFieldInsn(GETSTATIC, newDynName, "_redkale_annotations", "Ljava/util/Map;");
mv.visitLdcInsn(newDynSuperMessageFullName);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/annotation/Annotation;");
mv.visitVarInsn(ASTORE, 1);
mv.visitVarInsn(ALOAD, 1);
Label l2 = new Label();
mv.visitJumpInsn(IFNONNULL, l2);
mv.visitInsn(ICONST_0);
mv.visitTypeInsn(ANEWARRAY, "java/lang/annotation/Annotation");
mv.visitInsn(ARETURN);
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "[Ljava/lang/annotation/Annotation;" }, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(ARRAYLENGTH);
mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "copyOf", "([Ljava/lang/Object;I)[Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/annotation/Annotation;");
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
{
// execute
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "execute", "(L" + newDynWebSokcetFullName + ";)V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, newDynSuperMessageFullName, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(method.getAnnotation(RestOnMessage.class).name());
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, "preOnMessage", "(Ljava/lang/String;" + wsParamDesc + "Ljava/lang/Runnable;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
{
// run
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "run", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynSuperMessageFullName, "_redkale_websocket", "L" + newDynWebSokcetFullName + ";");
for (Map.Entry<String, Parameter> en : paramap.entrySet()) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, (newDynSuperMessageFullName), en.getKey(), Type.getDescriptor(en.getValue().getType()));
}
mv.visitMethodInsn(INVOKEVIRTUAL, newDynWebSokcetFullName, method.getName(), Type.getMethodDescriptor(method), false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
{
// toString
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
cw2.visitEnd();
byte[] bytes = cw2.toByteArray();
Class cz = newLoader.loadClass((newDynSuperMessageFullName).replace('/', '.'), bytes);
RedkaleClassLoader.putDynClass((newDynSuperMessageFullName).replace('/', '.'), bytes, cz);
}
if (wildcardMethod == null) {
// _DynXXXWebSocketMessage class
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynMessageFullName, null, "java/lang/Object", null);
cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
for (int i = 0; i < messageMethods.size(); i++) {
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
fv = cw2.visitField(ACC_PUBLIC, method.getAnnotation(RestOnMessage.class).name(), "L" + newDynSuperMessageFullName + ";", null, null);
fv.visitEnd();
}
{
// 构造函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// toString
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
mv.visitMethodInsn(INVOKESTATIC, JsonConvert.class.getName().replace('.', '/'), "root", "()" + jsonConvertDesc, false);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, JsonConvert.class.getName().replace('.', '/'), "convertTo", "(Ljava/lang/Object;)Ljava/lang/String;", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
cw2.visitEnd();
byte[] bytes = cw2.toByteArray();
Class cz = newLoader.loadClass(newDynMessageFullName.replace('/', '.'), bytes);
RedkaleClassLoader.putDynClass(newDynMessageFullName.replace('/', '.'), bytes, cz);
}
{
// _DynXXXWebSocket class
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynWebSokcetFullName, null, webSocketInternalName, null);
cw2.visitInnerClass(newDynWebSokcetFullName, newDynName, newDynWebSokcetSimpleName, ACC_PUBLIC + ACC_STATIC);
{
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + resourceDescriptor + ")V", resourceGenericDescriptor == null ? null : ("(" + resourceGenericDescriptor + ")V"), null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, webSocketInternalName, "<init>", "()V", false);
for (int i = 0; i < resourcesFields.size(); i++) {
Field field = resourcesFields.get(i);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, i + 1);
mv.visitFieldInsn(PUTFIELD, newDynWebSokcetFullName, field.getName(), Type.getDescriptor(field.getType()));
}
mv.visitInsn(RETURN);
mv.visitMaxs(2, 1 + resourcesFields.size());
mv.visitEnd();
}
{
// RestDyn
av0 = cw2.visitAnnotation(Type.getDescriptor(RestDyn.class), true);
av0.visit("simple", false);
av0.visitEnd();
}
cw2.visitEnd();
byte[] bytes = cw2.toByteArray();
Class cz = newLoader.loadClass(newDynWebSokcetFullName.replace('/', '.'), bytes);
RedkaleClassLoader.putDynClass(newDynWebSokcetFullName.replace('/', '.'), bytes, cz);
}
{
// _DynRestOnMessageConsumer class
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynConsumerFullName, "Ljava/lang/Object;Ljava/util/function/BiConsumer<" + wsDesc + "Ljava/lang/Object;>;", "java/lang/Object", new String[] { "java/util/function/BiConsumer" });
cw2.visitInnerClass(newDynConsumerFullName, newDynName, newDynConsumerSimpleName, ACC_PUBLIC + ACC_STATIC);
cw2.visitInnerClass(newDynMessageFullName, newDynName, newDynMessageSimpleName, ACC_PUBLIC + ACC_STATIC);
for (int i = 0; i < messageMethods.size(); i++) {
Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
}
{
// 构造函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// accept函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", null, null));
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, newDynWebSokcetFullName);
mv.visitVarInsn(ASTORE, 3);
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, newDynMessageFullName);
mv.visitVarInsn(ASTORE, 4);
for (int i = 0; i < messageMethods.size(); i++) {
final Method method = messageMethods.get(i);
String endfix = "_" + method.getName() + "_" + (i > 9 ? i : ("0" + i));
String newDynSuperMessageFullName = newDynMessageFullName + (method == wildcardMethod ? "" : endfix);
final String messagename = method.getAnnotation(RestOnMessage.class).name();
if (method == wildcardMethod) {
mv.visitVarInsn(ALOAD, 4);
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynSuperMessageFullName, "execute", "(L" + newDynWebSokcetFullName + ";)V", false);
} else {
mv.visitVarInsn(ALOAD, 4);
mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + newDynSuperMessageFullName + ";");
Label ifLabel = new Label();
mv.visitJumpInsn(IFNULL, ifLabel);
mv.visitVarInsn(ALOAD, 4);
mv.visitFieldInsn(GETFIELD, newDynMessageFullName, messagename, "L" + newDynSuperMessageFullName + ";");
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynSuperMessageFullName, "execute", "(L" + newDynWebSokcetFullName + ";)V", false);
mv.visitInsn(RETURN);
mv.visitLabel(ifLabel);
}
}
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3 + messageMethods.size());
mv.visitEnd();
}
{
// 虚拟accept函数
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "accept", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, WebSocket.class.getName().replace('.', '/'));
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, "java/lang/Object");
mv.visitMethodInsn(INVOKEVIRTUAL, newDynConsumerFullName, "accept", "(" + wsDesc + "Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw2.visitEnd();
byte[] bytes = cw2.toByteArray();
Class cz = newLoader.loadClass(newDynConsumerFullName.replace('/', '.'), bytes);
RedkaleClassLoader.putDynClass(newDynConsumerFullName.replace('/', '.'), bytes, cz);
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Class<?> newClazz = newLoader.loadClass(newDynName.replace('/', '.'), bytes);
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
// 固定Message类
JsonFactory.root().loadDecoder(newClazz.getAnnotation(RestDyn.class).types()[2]);
RedkaleClassLoader.putReflectionPublicMethods(webSocketType.getName());
Class cwt = webSocketType;
do {
RedkaleClassLoader.putReflectionDeclaredFields(cwt.getName());
} while ((cwt = cwt.getSuperclass()) != Object.class);
RedkaleClassLoader.putReflectionDeclaredConstructors(webSocketType, webSocketType.getName());
try {
T servlet = (T) newClazz.getDeclaredConstructor().newInstance();
Field field = newClazz.getField("_redkale_annotations");
field.set(null, msgclassToAnnotations);
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), field);
if (rws.cryptor() != Cryptor.class) {
RedkaleClassLoader.putReflectionDeclaredConstructors(rws.cryptor(), rws.cryptor().getName());
Cryptor cryptor = rws.cryptor().getDeclaredConstructor().newInstance();
// WebSocketServlet
Field cryptorField = newClazz.getSuperclass().getDeclaredField("cryptor");
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), cryptorField);
cryptorField.setAccessible(true);
cryptorField.set(servlet, cryptor);
}
if (messageAgent != null)
((WebSocketServlet) servlet).messageAgent = messageAgent;
return servlet;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.redkale.asm.MethodDebugVisitor in project redkale by redkale.
the class Sncp method createLocalServiceClass.
/**
* <blockquote><pre>
* public class TestService implements Service{
*
* public String findSomeThing(){
* return "hello";
* }
*
* @RpcMultiRun(selfrun = false)
* public void createSomeThing(TestBean bean){
* //do something
* }
*
* @RpcMultiRun
* public String updateSomeThing(String id){
* return "hello" + id;
* }
* }
* </pre></blockquote>
*
* <blockquote><pre>
* @Resource(name = "")
* @SncpDyn(remote = false)
* @ResourceType(TestService.class)
* public final class _DynLocalTestService extends TestService{
*
* private AnyValue _redkale_conf;
*
* private SncpClient _redkale_client;
*
* @Override
* public String toString() {
* return _redkale_selfstring == null ? super.toString() : _redkale_selfstring;
* }
* }
* </pre></blockquote>
*
* 创建Service的本地模式Class
*
* @param <T> Service子类
* @param classLoader ClassLoader
* @param name 资源名
* @param serviceImplClass Service类
*
* @return Service实例
*/
@SuppressWarnings("unchecked")
protected static <T extends Service> Class<? extends T> createLocalServiceClass(ClassLoader classLoader, final String name, final Class<T> serviceImplClass) {
if (serviceImplClass == null)
return null;
if (!Service.class.isAssignableFrom(serviceImplClass))
return serviceImplClass;
ResourceFactory.checkResourceName(name);
int mod = serviceImplClass.getModifiers();
if (!java.lang.reflect.Modifier.isPublic(mod))
return serviceImplClass;
if (java.lang.reflect.Modifier.isAbstract(mod))
return serviceImplClass;
final String supDynName = serviceImplClass.getName().replace('.', '/');
final String clientName = SncpClient.class.getName().replace('.', '/');
final String resDesc = Type.getDescriptor(Resource.class);
final String clientDesc = Type.getDescriptor(SncpClient.class);
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
// String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceImplClass.getSimpleName();
String newDynName = "org/redkaledyn/service/local/_DynLocalService__" + serviceImplClass.getName().replace('.', '_').replace('$', '_');
if (!name.isEmpty()) {
boolean normal = true;
for (char ch : name.toCharArray()) {
if (!((ch >= '0' && ch <= '9') || ch == '_' || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')))
normal = false;
}
if (!normal)
throw new RuntimeException(serviceImplClass + "'s resource name is illegal, must be 0-9 _ a-z A-Z");
newDynName += "_" + (normal ? name : hash(name));
}
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
return (Class<T>) (clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz);
} catch (ClassNotFoundException e) {
} catch (Throwable t) {
t.printStackTrace();
}
// ------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodDebugVisitor mv;
AnnotationVisitor av0;
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
av0 = cw.visitAnnotation(resDesc, true);
av0.visit("name", name);
av0.visitEnd();
}
{
av0 = cw.visitAnnotation(sncpDynDesc, true);
av0.visit("remote", Boolean.FALSE);
av0.visitEnd();
}
{
// 给新类加上 原有的Annotation
for (Annotation ann : serviceImplClass.getAnnotations()) {
if (ann instanceof Resource || ann instanceof SncpDyn || ann instanceof ResourceType)
continue;
MethodDebugVisitor.visitAnnotation(cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
}
}
{
av0 = cw.visitAnnotation(Type.getDescriptor(ResourceType.class), true);
ResourceType rty = serviceImplClass.getAnnotation(ResourceType.class);
av0.visit("value", Type.getType(Type.getDescriptor(rty == null ? serviceImplClass : rty.value())));
av0.visitEnd();
}
{
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_conf", anyValueDesc, null, null);
fv.visitEnd();
}
{
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_client", clientDesc, null, null);
fv.visitEnd();
}
{
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_messageagent", Type.getDescriptor(MessageAgent.class), null, null);
fv.visitEnd();
}
{
// 构造函数
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
// mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// toString()
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
Label l1 = new Label();
mv.visitJumpInsn(IFNONNULL, l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
Label l2 = new Label();
mv.visitJumpInsn(GOTO, l2);
mv.visitLabel(l1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "toSimpleString", "()Ljava/lang/String;", false);
mv.visitLabel(l2);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Class<?> newClazz = new ClassLoader(loader) {
public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
RedkaleClassLoader.putReflectionPublicClasses(newDynName.replace('/', '.'));
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
try {
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
c = newClazz.getDeclaredField(FIELDPREFIX + "_messageagent");
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
} catch (Exception e) {
}
return (Class<T>) newClazz;
}
use of org.redkale.asm.MethodDebugVisitor in project redkale by redkale.
the class Rest method createRestServlet.
public static <T extends HttpServlet> T createRestServlet(final ClassLoader classLoader, final Class userType0, final Class<T> baseServletType, final Class<? extends Service> serviceType) {
if (baseServletType == null || serviceType == null)
throw new RuntimeException(" Servlet or Service is null Class on createRestServlet");
if (!HttpServlet.class.isAssignableFrom(baseServletType))
throw new RuntimeException(baseServletType + " is not HttpServlet Class on createRestServlet");
int mod = baseServletType.getModifiers();
if (!java.lang.reflect.Modifier.isPublic(mod))
throw new RuntimeException(baseServletType + " is not Public Class on createRestServlet");
if (java.lang.reflect.Modifier.isAbstract(mod)) {
for (Method m : baseServletType.getDeclaredMethods()) {
if (java.lang.reflect.Modifier.isAbstract(m.getModifiers())) {
// @since 2.4.0
throw new RuntimeException(baseServletType + " cannot contains a abstract Method on " + baseServletType);
}
}
}
final String restInternalName = Type.getInternalName(Rest.class);
final String serviceDesc = Type.getDescriptor(serviceType);
final String webServletDesc = Type.getDescriptor(WebServlet.class);
final String resDesc = Type.getDescriptor(Resource.class);
final String reqDesc = Type.getDescriptor(HttpRequest.class);
final String respDesc = Type.getDescriptor(HttpResponse.class);
final String convertDesc = Type.getDescriptor(Convert.class);
final String typeDesc = Type.getDescriptor(java.lang.reflect.Type.class);
final String retDesc = Type.getDescriptor(RetResult.class);
final String httpResultDesc = Type.getDescriptor(HttpResult.class);
final String httpScopeDesc = Type.getDescriptor(HttpScope.class);
final String stageDesc = Type.getDescriptor(CompletionStage.class);
final String flipperDesc = Type.getDescriptor(Flipper.class);
final String channelDesc = Type.getDescriptor(ChannelContext.class);
final String httpServletName = HttpServlet.class.getName().replace('.', '/');
final String actionEntryName = HttpServlet.ActionEntry.class.getName().replace('.', '/');
final String attrDesc = Type.getDescriptor(org.redkale.util.Attribute.class);
final String multiContextDesc = Type.getDescriptor(MultiContext.class);
final String multiContextName = MultiContext.class.getName().replace('.', '/');
final String mappingDesc = Type.getDescriptor(HttpMapping.class);
final String httpParamDesc = Type.getDescriptor(HttpParam.class);
final String httpParamsDesc = Type.getDescriptor(HttpParam.HttpParams.class);
final String sourcetypeDesc = Type.getDescriptor(HttpParam.HttpParameterStyle.class);
final String reqInternalName = Type.getInternalName(HttpRequest.class);
final String respInternalName = Type.getInternalName(HttpResponse.class);
final String attrInternalName = Type.getInternalName(org.redkale.util.Attribute.class);
final String retInternalName = Type.getInternalName(RetResult.class);
final String serviceTypeInternalName = Type.getInternalName(serviceType);
HttpUserType hut = baseServletType.getAnnotation(HttpUserType.class);
final Class userType = (userType0 == null || userType0 == Object.class) ? (hut == null ? null : hut.value()) : userType0;
if (userType != null && (userType.isPrimitive() || userType.getName().startsWith("java.") || userType.getName().startsWith("javax."))) {
throw new RuntimeException(HttpUserType.class.getSimpleName() + " must be a JavaBean but found " + userType);
}
final String supDynName = baseServletType.getName().replace('.', '/');
final RestService controller = serviceType.getAnnotation(RestService.class);
// 标记为ignore=true不创建Servlet
if (controller != null && controller.ignore())
throw new RuntimeException(serviceType + " is ignore Rest Service Class");
final boolean serrpconly = controller != null && controller.rpconly();
ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
String stname = serviceType.getSimpleName();
if (stname.startsWith("Service")) {
// 类似ServiceWatchService这样的类保留第一个Service字样
stname = "Service" + stname.substring("Service".length()).replaceAll("Service.*$", "");
} else {
stname = stname.replaceAll("Service.*$", "");
}
// String newDynName = serviceTypeInternalName.substring(0, serviceTypeInternalName.lastIndexOf('/') + 1) + "_Dyn" + stname + "RestServlet";
final String newDynName = "org/redkaledyn/http/rest/" + "_Dyn" + stname + "RestServlet__" + serviceType.getName().replace('.', '_').replace('$', '_') + "DynServlet";
try {
Class newClazz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
if (newClazz == null)
newClazz = loader.loadClass(newDynName.replace('/', '.'));
T obj = (T) newClazz.getDeclaredConstructor().newInstance();
final String defmodulename = getWebModuleNameLowerCase(serviceType);
final String bigmodulename = getWebModuleName(serviceType);
final Map<String, Object> classMap = new LinkedHashMap<>();
final List<MappingEntry> entrys = new ArrayList<>();
final List<java.lang.reflect.Type[]> paramTypes = new ArrayList<>();
final List<java.lang.reflect.Type> retvalTypes = new ArrayList<>();
final List<Object[]> restConverts = new ArrayList<>();
final Map<java.lang.reflect.Type, String> typeRefs = new LinkedHashMap<>();
final Map<String, Method> mappingurlToMethod = new HashMap<>();
final Map<String, org.redkale.util.Attribute> restAttributes = new LinkedHashMap<>();
final Map<String, java.lang.reflect.Type> bodyTypes = new HashMap<>();
{
// entrys、paramTypes赋值
final Method[] allMethods = serviceType.getMethods();
Arrays.sort(allMethods, (m1, m2) -> {
// 必须排序,否则paramTypes顺序容易乱
int s = m1.getName().compareTo(m2.getName());
if (s != 0)
return s;
s = Arrays.toString(m1.getParameterTypes()).compareTo(Arrays.toString(m2.getParameterTypes()));
return s;
});
int methodidex = 0;
for (final Method method : allMethods) {
if (Modifier.isStatic(method.getModifiers()))
continue;
if (method.isSynthetic())
continue;
if (EXCLUDERMETHODS.contains(method.getName()))
continue;
if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == AnyValue.class) {
if ("init".equals(method.getName()))
continue;
if ("stop".equals(method.getName()))
continue;
if ("destroy".equals(method.getName()))
continue;
}
if (controller == null)
continue;
RestMapping[] mappings = method.getAnnotationsByType(RestMapping.class);
if (!controller.automapping() && mappings.length < 1)
continue;
boolean ignore = false;
for (RestMapping mapping : mappings) {
if (mapping.ignore()) {
ignore = true;
break;
}
}
if (ignore)
continue;
paramTypes.add(TypeToken.getGenericType(method.getGenericParameterTypes(), serviceType));
retvalTypes.add(formatRestReturnType(method, serviceType));
if (mappings.length == 0) {
// 没有Mapping,设置一个默认值
MappingEntry entry = new MappingEntry(serrpconly, methodidex, null, bigmodulename, method);
entrys.add(entry);
} else {
for (RestMapping mapping : mappings) {
MappingEntry entry = new MappingEntry(serrpconly, methodidex, mapping, defmodulename, method);
entrys.add(entry);
}
}
methodidex++;
}
Collections.sort(entrys);
}
{
// restConverts、typeRefs、mappingurlToMethod、restAttributes、bodyTypes赋值
for (final MappingEntry entry : entrys) {
mappingurlToMethod.put(entry.mappingurl, entry.mappingMethod);
final Method method = entry.mappingMethod;
final Class returnType = method.getReturnType();
final Parameter[] params = method.getParameters();
final RestConvert[] rcs = method.getAnnotationsByType(RestConvert.class);
final RestConvertCoder[] rcc = method.getAnnotationsByType(RestConvertCoder.class);
if ((rcs != null && rcs.length > 0) || (rcc != null && rcc.length > 0)) {
restConverts.add(new Object[] { rcs, rcc });
}
// 解析方法中的每个参数
List<Object[]> paramlist = new ArrayList<>();
for (int i = 0; i < params.length; i++) {
final Parameter param = params[i];
final Class ptype = param.getType();
String n = null;
String comment = "";
boolean required = true;
int radix = 10;
RestHeader annhead = param.getAnnotation(RestHeader.class);
if (annhead != null) {
n = annhead.name();
radix = annhead.radix();
comment = annhead.comment();
required = annhead.required();
}
RestCookie anncookie = param.getAnnotation(RestCookie.class);
if (anncookie != null) {
n = anncookie.name();
radix = anncookie.radix();
comment = anncookie.comment();
}
RestSessionid annsid = param.getAnnotation(RestSessionid.class);
RestAddress annaddr = param.getAnnotation(RestAddress.class);
if (annaddr != null) {
comment = annaddr.comment();
}
RestBody annbody = param.getAnnotation(RestBody.class);
if (annbody != null) {
comment = annbody.comment();
}
RestUploadFile annfile = param.getAnnotation(RestUploadFile.class);
if (annfile != null) {
comment = annfile.comment();
}
RestURI annuri = param.getAnnotation(RestURI.class);
if (annuri != null) {
comment = annuri.comment();
}
RestUserid userid = param.getAnnotation(RestUserid.class);
if (userid != null) {
comment = "";
}
RestHeaders annheaders = param.getAnnotation(RestHeaders.class);
if (annheaders != null) {
comment = "";
}
RestParams annparams = param.getAnnotation(RestParams.class);
if (annparams != null) {
comment = "";
}
RestParam annpara = param.getAnnotation(RestParam.class);
if (annpara != null)
radix = annpara.radix();
if (annpara != null)
comment = annpara.comment();
if (annpara != null)
required = annpara.required();
if (n == null)
n = (annpara == null || annpara.name().isEmpty()) ? null : annpara.name();
// 用户类型特殊处理
if (n == null && ptype == userType)
n = "&";
if (n == null) {
if (param.isNamePresent()) {
n = param.getName();
} else if (ptype == Flipper.class) {
n = "flipper";
}
}
// n maybe is null
java.lang.reflect.Type paramtype = TypeToken.getGenericType(param.getParameterizedType(), serviceType);
paramlist.add(new Object[] { param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, userid, annheaders, annparams, paramtype });
}
for (Object[] ps : paramlist) {
// {param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, annuserid, annheaders, annparams, paramtype}
// 是否取userid
final boolean isuserid = ((RestUserid) ps[14]) != null;
// @RestUserid 不需要生成 @HttpParam
if ((ps[1] != null && ps[1].toString().indexOf('&') >= 0) || isuserid)
continue;
// @RestAddress 不需要生成 @HttpParam
if (((RestAddress) ps[8]) != null)
continue;
java.lang.reflect.Type pgtype = TypeToken.getGenericType(((Parameter) ps[0]).getParameterizedType(), serviceType);
if (pgtype != (Class) ps[2]) {
String refid = typeRefs.get(pgtype);
if (refid == null) {
refid = "_typeref_" + typeRefs.size();
typeRefs.put(pgtype, refid);
}
}
// 参数类型
final Parameter param = (Parameter) ps[0];
// 参数名
String pname = (String) ps[1];
// 参数类型
Class ptype = (Class) ps[2];
int radix = (Integer) ps[3];
String comment = (String) ps[4];
boolean required = (Boolean) ps[5];
RestParam annpara = (RestParam) ps[6];
RestSessionid annsid = (RestSessionid) ps[7];
RestAddress annaddr = (RestAddress) ps[8];
RestHeader annhead = (RestHeader) ps[9];
RestCookie anncookie = (RestCookie) ps[10];
RestBody annbody = (RestBody) ps[11];
RestUploadFile annfile = (RestUploadFile) ps[12];
RestURI annuri = (RestURI) ps[13];
RestUserid annuserid = (RestUserid) ps[14];
RestHeaders annheaders = (RestHeaders) ps[15];
RestParams annparams = (RestParams) ps[16];
if (CompletionHandler.class.isAssignableFrom(ptype)) {
// HttpResponse.createAsyncHandler() or HttpResponse.createAsyncHandler(Class)
} else if (annsid != null) {
// HttpRequest.getSessionid(true|false)
} else if (annaddr != null) {
// HttpRequest.getRemoteAddr
} else if (annheaders != null) {
// HttpRequest.getHeaders
} else if (annparams != null) {
// HttpRequest.getParameters
} else if (annbody != null) {
// HttpRequest.getBodyUTF8 / HttpRequest.getBody
} else if (annfile != null) {
// MultiContext.partsFirstBytes / HttpRequest.partsFirstFile / HttpRequest.partsFiles
} else if (annuri != null) {
// HttpRequest.getRequestURI
} else if (annuserid != null) {
// HttpRequest.currentUserid
} else if ("#".equals(pname)) {
// 从request.getRequstURI 中取参数
} else if (pname != null && pname.charAt(0) == '#') {
// 从request.getRequstURIPath 中去参数
} else if ("&".equals(pname) && ptype == userType) {
// 当前用户对象的类名
} else if (ptype.isPrimitive()) {
} else if (ptype == String.class) {
} else if (ptype == ChannelContext.class) {
} else if (ptype == Flipper.class) {
} else {
// 其他Json对象
// 构建 RestHeader、RestCookie、RestAddress 等赋值操作
Class loop = ptype;
Set<String> fields = new HashSet<>();
Map<String, Object[]> attrParaNames = new LinkedHashMap<>();
do {
// 接口时getSuperclass可能会得到null
if (loop == null || loop.isInterface())
break;
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()))
continue;
if (Modifier.isFinal(field.getModifiers()))
continue;
if (fields.contains(field.getName()))
continue;
RestHeader rh = field.getAnnotation(RestHeader.class);
RestCookie rc = field.getAnnotation(RestCookie.class);
RestSessionid rs = field.getAnnotation(RestSessionid.class);
RestAddress ra = field.getAnnotation(RestAddress.class);
RestBody rb = field.getAnnotation(RestBody.class);
RestUploadFile ru = field.getAnnotation(RestUploadFile.class);
RestURI ri = field.getAnnotation(RestURI.class);
if (rh == null && rc == null && ra == null && rb == null && rs == null && ru == null && ri == null)
continue;
org.redkale.util.Attribute attr = org.redkale.util.Attribute.create(loop, field);
String attrFieldName;
String restname = "";
if (rh != null) {
attrFieldName = "_redkale_attr_header_" + (field.getType() != String.class ? "json_" : "") + restAttributes.size();
restname = rh.name();
} else if (rc != null) {
attrFieldName = "_redkale_attr_cookie_" + restAttributes.size();
restname = rc.name();
} else if (rs != null) {
attrFieldName = "_redkale_attr_sessionid_" + restAttributes.size();
// 用于下面区分create值
restname = rs.create() ? "1" : "";
} else if (ra != null) {
attrFieldName = "_redkale_attr_address_" + restAttributes.size();
// restname = "";
} else if (rb != null && field.getType() == String.class) {
attrFieldName = "_redkale_attr_bodystring_" + restAttributes.size();
// restname = "";
} else if (rb != null && field.getType() == byte[].class) {
attrFieldName = "_redkale_attr_bodybytes_" + restAttributes.size();
// restname = "";
} else if (rb != null && field.getType() != String.class && field.getType() != byte[].class) {
attrFieldName = "_redkale_attr_bodyjson_" + restAttributes.size();
// restname = "";
} else if (ru != null && field.getType() == byte[].class) {
attrFieldName = "_redkale_attr_uploadbytes_" + restAttributes.size();
// restname = "";
} else if (ru != null && field.getType() == File.class) {
attrFieldName = "_redkale_attr_uploadfile_" + restAttributes.size();
// restname = "";
} else if (ru != null && field.getType() == File[].class) {
attrFieldName = "_redkale_attr_uploadfiles_" + restAttributes.size();
// restname = "";
} else if (ri != null && field.getType() == String.class) {
attrFieldName = "_redkale_attr_uri_" + restAttributes.size();
// restname = "";
} else {
continue;
}
restAttributes.put(attrFieldName, attr);
attrParaNames.put(attrFieldName, new Object[] { restname, field.getType(), field.getGenericType(), ru });
fields.add(field.getName());
}
} while ((loop = loop.getSuperclass()) != Object.class);
if (!attrParaNames.isEmpty()) {
// 参数存在 RestHeader、RestCookie、RestSessionid、RestAddress、RestBody字段
for (Map.Entry<String, Object[]> en : attrParaNames.entrySet()) {
if (en.getKey().contains("_header_")) {
String headerkey = en.getValue()[0].toString();
if ("Host".equalsIgnoreCase(headerkey)) {
} else if ("Content-Type".equalsIgnoreCase(headerkey)) {
} else if ("Connection".equalsIgnoreCase(headerkey)) {
} else if ("Method".equalsIgnoreCase(headerkey)) {
} else if (en.getKey().contains("_header_json_")) {
String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
}
} else if (en.getKey().contains("_cookie_")) {
} else if (en.getKey().contains("_sessionid_")) {
} else if (en.getKey().contains("_address_")) {
} else if (en.getKey().contains("_uri_")) {
} else if (en.getKey().contains("_bodystring_")) {
} else if (en.getKey().contains("_bodybytes_")) {
} else if (en.getKey().contains("_bodyjson_")) {
// JavaBean 转 Json
String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
} else if (en.getKey().contains("_uploadbytes_")) {
// 只需mv.visitVarInsn(ALOAD, 4), 无需处理
} else if (en.getKey().contains("_uploadfile_")) {
// 只需mv.visitVarInsn(ALOAD, 4), 无需处理
} else if (en.getKey().contains("_uploadfiles_")) {
// 只需mv.visitVarInsn(ALOAD, 4), 无需处理
}
}
}
}
}
java.lang.reflect.Type grt = TypeToken.getGenericType(method.getGenericReturnType(), serviceType);
Class rtc = returnType;
if (rtc == void.class) {
rtc = RetResult.class;
grt = TYPE_RETRESULT_STRING;
} else if (CompletionStage.class.isAssignableFrom(returnType)) {
ParameterizedType ptgrt = (ParameterizedType) grt;
grt = ptgrt.getActualTypeArguments()[0];
rtc = TypeToken.typeToClass(grt);
// 应该不会发生吧?
if (rtc == null)
rtc = Object.class;
} else if (Flows.maybePublisherClass(returnType)) {
java.lang.reflect.Type grt0 = Flows.maybePublisherSubType(grt);
if (grt0 != null)
grt = grt0;
}
if (grt != rtc) {
String refid = typeRefs.get(grt);
if (refid == null) {
refid = "_typeref_" + typeRefs.size();
typeRefs.put(grt, refid);
}
}
}
}
for (Map.Entry<java.lang.reflect.Type, String> en : typeRefs.entrySet()) {
Field refField = newClazz.getDeclaredField(en.getValue());
refField.setAccessible(true);
refField.set(obj, en.getKey());
}
for (Map.Entry<String, org.redkale.util.Attribute> en : restAttributes.entrySet()) {
Field attrField = newClazz.getDeclaredField(en.getKey());
attrField.setAccessible(true);
attrField.set(obj, en.getValue());
}
for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
Field genField = newClazz.getDeclaredField(en.getKey());
genField.setAccessible(true);
genField.set(obj, en.getValue());
}
for (int i = 0; i < restConverts.size(); i++) {
Field genField = newClazz.getDeclaredField(REST_CONVERT_FIELD_PREFIX + (i + 1));
genField.setAccessible(true);
Object[] rc = restConverts.get(i);
genField.set(obj, createJsonConvert((RestConvert[]) rc[0], (RestConvertCoder[]) rc[1]));
}
Field typesfield = newClazz.getDeclaredField(REST_PARAMTYPES_FIELD_NAME);
typesfield.setAccessible(true);
java.lang.reflect.Type[][] paramtypeArray = new java.lang.reflect.Type[paramTypes.size()][];
paramtypeArray = paramTypes.toArray(paramtypeArray);
typesfield.set(obj, paramtypeArray);
Field retfield = newClazz.getDeclaredField(REST_RETURNTYPES_FIELD_NAME);
retfield.setAccessible(true);
java.lang.reflect.Type[] rettypeArray = new java.lang.reflect.Type[retvalTypes.size()];
rettypeArray = retvalTypes.toArray(rettypeArray);
retfield.set(obj, rettypeArray);
Field tostringfield = newClazz.getDeclaredField(REST_TOSTRINGOBJ_FIELD_NAME);
tostringfield.setAccessible(true);
java.util.function.Supplier<String> sSupplier = () -> JsonConvert.root().convertTo(classMap);
tostringfield.set(obj, sSupplier);
Method restactMethod = newClazz.getDeclaredMethod("_createRestActionEntry");
restactMethod.setAccessible(true);
Field tmpentrysfield = HttpServlet.class.getDeclaredField("_actionmap");
tmpentrysfield.setAccessible(true);
HashMap<String, HttpServlet.ActionEntry> innerEntryMap = (HashMap) restactMethod.invoke(obj);
for (Map.Entry<String, HttpServlet.ActionEntry> en : innerEntryMap.entrySet()) {
Method m = mappingurlToMethod.get(en.getKey());
if (m != null)
en.getValue().annotations = HttpServlet.ActionEntry.annotations(m);
}
tmpentrysfield.set(obj, innerEntryMap);
return obj;
} catch (ClassNotFoundException e) {
} catch (Throwable e) {
e.printStackTrace();
}
// ------------------------------------------------------------------------------
final String defmodulename = getWebModuleNameLowerCase(serviceType);
final String bigmodulename = getWebModuleName(serviceType);
final String catalog = controller == null ? "" : controller.catalog();
if (!checkName(catalog))
throw new RuntimeException(serviceType.getName() + " have illegal " + RestService.class.getSimpleName() + ".catalog, only 0-9 a-z A-Z _ cannot begin 0-9");
if (!checkName(defmodulename))
throw new RuntimeException(serviceType.getName() + " have illegal " + RestService.class.getSimpleName() + ".value, only 0-9 a-z A-Z _ cannot begin 0-9");
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodDebugVisitor mv;
AnnotationVisitor av0;
final List<MappingEntry> entrys = new ArrayList<>();
final Map<String, org.redkale.util.Attribute> restAttributes = new LinkedHashMap<>();
final Map<String, Object> classMap = new LinkedHashMap<>();
final Map<java.lang.reflect.Type, String> typeRefs = new LinkedHashMap<>();
final List<java.lang.reflect.Type[]> paramTypes = new ArrayList<>();
final List<java.lang.reflect.Type> retvalTypes = new ArrayList<>();
final Map<String, java.lang.reflect.Type> bodyTypes = new HashMap<>();
final List<Object[]> restConverts = new ArrayList<>();
final Map<String, Method> mappingurlToMethod = new HashMap<>();
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
// RestDynSourceType
av0 = cw.visitAnnotation(Type.getDescriptor(RestDynSourceType.class), true);
av0.visit("value", Type.getType(Type.getDescriptor(serviceType)));
av0.visitEnd();
}
boolean dynsimple = true;
// 获取所有可以转换成HttpMapping的方法
int methodidex = 0;
final MessageMultiConsumer mmc = serviceType.getAnnotation(MessageMultiConsumer.class);
if (mmc != null && (mmc.module() == null || mmc.module().isEmpty())) {
throw new RuntimeException("@" + MessageMultiConsumer.class.getSimpleName() + ".module can not empty in " + serviceType.getName());
}
if (mmc != null && !checkName2(mmc.module())) {
throw new RuntimeException(serviceType.getName() + " have illegal " + MessageMultiConsumer.class.getSimpleName() + ".module, only 0-9 a-z A-Z _ - . cannot begin 0-9");
}
if (mmc != null) {
MethodDebugVisitor.visitAnnotation(cw.visitAnnotation(Type.getDescriptor(mmc.annotationType()), true), mmc);
}
final Method[] allMethods = serviceType.getMethods();
Arrays.sort(allMethods, (m1, m2) -> {
// 必须排序,否则paramTypes顺序容易乱
int s = m1.getName().compareTo(m2.getName());
if (s != 0)
return s;
s = Arrays.toString(m1.getParameterTypes()).compareTo(Arrays.toString(m2.getParameterTypes()));
return s;
});
for (final Method method : allMethods) {
if (Modifier.isStatic(method.getModifiers()))
continue;
if (method.isSynthetic())
continue;
if (EXCLUDERMETHODS.contains(method.getName()))
continue;
if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == AnyValue.class) {
if ("init".equals(method.getName()))
continue;
if ("stop".equals(method.getName()))
continue;
if ("destroy".equals(method.getName()))
continue;
}
if (controller == null)
continue;
RestMapping[] mappings = method.getAnnotationsByType(RestMapping.class);
if (!controller.automapping() && mappings.length < 1)
continue;
boolean ignore = false;
for (RestMapping mapping : mappings) {
if (mapping.ignore()) {
ignore = true;
break;
}
}
if (ignore)
continue;
Class[] extypes = method.getExceptionTypes();
if (extypes.length > 0) {
for (Class exp : extypes) {
if (!RuntimeException.class.isAssignableFrom(exp) && !IOException.class.isAssignableFrom(exp)) {
throw new RuntimeException("@" + RestMapping.class.getSimpleName() + " only for method(" + method + ") with throws IOException");
}
}
}
if (mmc != null && method.getReturnType() != void.class) {
throw new RuntimeException("@" + RestMapping.class.getSimpleName() + " only for method(" + method + ") with return void by @" + MessageMultiConsumer.class.getSimpleName() + " Service");
}
paramTypes.add(TypeToken.getGenericType(method.getGenericParameterTypes(), serviceType));
retvalTypes.add(formatRestReturnType(method, serviceType));
if (mappings.length == 0) {
// 没有Mapping,设置一个默认值
MappingEntry entry = new MappingEntry(serrpconly, methodidex, null, bigmodulename, method);
if (entrys.contains(entry))
throw new RuntimeException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat");
entrys.add(entry);
} else {
for (RestMapping mapping : mappings) {
MappingEntry entry = new MappingEntry(serrpconly, methodidex, mapping, defmodulename, method);
if (entrys.contains(entry))
throw new RuntimeException(serviceType.getName() + " on " + method.getName() + " 's mapping(" + entry.name + ") is repeat");
entrys.add(entry);
}
}
methodidex++;
}
// 没有可HttpMapping的方法
if (entrys.isEmpty())
return null;
Collections.sort(entrys);
RestClassLoader newLoader = new RestClassLoader(loader);
final int moduleid = controller == null ? 0 : controller.moduleid();
{
// 注入 @WebServlet 注解
String urlpath = "";
boolean repair = controller == null ? true : controller.repair();
String comment = controller == null ? "" : controller.comment();
av0 = cw.visitAnnotation(webServletDesc, true);
{
AnnotationVisitor av1 = av0.visitArray("value");
boolean pound = false;
for (MappingEntry entry : entrys) {
if (entry.existsPound) {
pound = true;
break;
}
}
if (defmodulename.isEmpty() || (!pound && entrys.size() <= 2)) {
for (MappingEntry entry : entrys) {
String suburl = (catalog.isEmpty() ? "/" : ("/" + catalog + "/")) + (defmodulename.isEmpty() ? "" : (defmodulename + "/")) + entry.name;
if ("//".equals(suburl)) {
suburl = "/";
} else if (suburl.length() > 2 && suburl.endsWith("/")) {
suburl += "*";
}
urlpath += "," + suburl;
av1.visit(null, suburl);
}
if (urlpath.length() > 0)
urlpath = urlpath.substring(1);
} else {
urlpath = (catalog.isEmpty() ? "/" : ("/" + catalog + "/")) + defmodulename + "/*";
av1.visit(null, urlpath);
}
av1.visitEnd();
}
av0.visit("name", defmodulename);
av0.visit("moduleid", moduleid);
av0.visit("repair", repair);
av0.visit("comment", comment);
av0.visitEnd();
classMap.put("type", serviceType.getName());
classMap.put("url", urlpath);
classMap.put("moduleid", moduleid);
classMap.put("repair", repair);
// classMap.put("comment", comment); //不显示太多信息
}
{
// 内部类
cw.visitInnerClass(actionEntryName, httpServletName, HttpServlet.ActionEntry.class.getSimpleName(), ACC_PROTECTED + ACC_FINAL + ACC_STATIC);
for (final MappingEntry entry : entrys) {
cw.visitInnerClass(newDynName + "$" + entry.newActionClassName, newDynName, entry.newActionClassName, ACC_PRIVATE + ACC_STATIC);
}
}
{
// 注入 @Resource private XXXService _service;
fv = cw.visitField(ACC_PRIVATE, REST_SERVICE_FIELD_NAME, serviceDesc, null, null);
av0 = fv.visitAnnotation(resDesc, true);
av0.visit("name", "");
av0.visitEnd();
fv.visitEnd();
}
{
// 注入 @Resource(name = "APP_HOME") private File _redkale_home;
fv = cw.visitField(ACC_PRIVATE, "_redkale_home", Type.getDescriptor(File.class), null, null);
av0 = fv.visitAnnotation(resDesc, true);
av0.visit("name", "APP_HOME");
av0.visitEnd();
fv.visitEnd();
}
{
// _servicemap字段 Map<String, XXXService>
fv = cw.visitField(ACC_PRIVATE, REST_SERVICEMAP_FIELD_NAME, "Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;" + serviceDesc + ">;", null);
fv.visitEnd();
}
{
// _redkale_tostringsupplier字段 Supplier<String>
fv = cw.visitField(ACC_PRIVATE, REST_TOSTRINGOBJ_FIELD_NAME, "Ljava/util/function/Supplier;", "Ljava/util/function/Supplier<Ljava/lang/String;>;", null);
fv.visitEnd();
}
{
// 构造函数
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
// mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
// 将每个Service可转换的方法生成HttpServlet对应的HttpMapping方法
boolean namePresent = false;
try {
Method m0 = null;
for (final MappingEntry entry : entrys) {
if (entry.mappingMethod.getParameterCount() > 0) {
m0 = entry.mappingMethod;
break;
}
}
namePresent = m0 == null ? true : m0.getParameters()[0].isNamePresent();
} catch (Exception e) {
}
final Map<String, List<String>> asmParamMap = namePresent ? null : MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), serviceType);
Map<String, byte[]> innerClassBytesMap = new LinkedHashMap<>();
for (final MappingEntry entry : entrys) {
RestUploadFile mupload = null;
Class muploadType = null;
final Method method = entry.mappingMethod;
final Class returnType = method.getReturnType();
final java.lang.reflect.Type retvalType = formatRestReturnType(method, serviceType);
final String methodDesc = Type.getMethodDescriptor(method);
final Parameter[] params = method.getParameters();
final RestConvert[] rcs = method.getAnnotationsByType(RestConvert.class);
final RestConvertCoder[] rcc = method.getAnnotationsByType(RestConvertCoder.class);
if ((rcs != null && rcs.length > 0) || (rcc != null && rcc.length > 0)) {
restConverts.add(new Object[] { rcs, rcc });
}
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, entry.newMethodName, "(" + reqDesc + respDesc + ")V", null, new String[] { "java/io/IOException" }));
// mv.setDebug(true);
mv.debugLine();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICEMAP_FIELD_NAME, "Ljava/util/Map;");
Label lmapif = new Label();
mv.visitJumpInsn(IFNONNULL, lmapif);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICE_FIELD_NAME, serviceDesc);
Label lserif = new Label();
mv.visitJumpInsn(GOTO, lserif);
mv.visitLabel(lmapif);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICEMAP_FIELD_NAME, "Ljava/util/Map;");
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(REST_HEADER_RESOURCE_NAME);
mv.visitLdcInsn("");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeader", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
mv.visitTypeInsn(CHECKCAST, serviceTypeInternalName);
mv.visitLabel(lserif);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { serviceTypeInternalName });
mv.visitVarInsn(ASTORE, 3);
final int maxStack = 3 + params.length;
List<int[]> varInsns = new ArrayList<>();
int maxLocals = 4;
List<String> asmParamNames = asmParamMap == null ? null : asmParamMap.get(method.getName() + ":" + Type.getMethodDescriptor(method));
// 删掉空元素
if (asmParamNames != null)
while (asmParamNames.remove(" ")) ;
List<Object[]> paramlist = new ArrayList<>();
// 解析方法中的每个参数
for (int i = 0; i < params.length; i++) {
final Parameter param = params[i];
final Class ptype = param.getType();
String n = null;
String comment = "";
boolean required = true;
int radix = 10;
RestHeader annhead = param.getAnnotation(RestHeader.class);
if (annhead != null) {
if (ptype != String.class && ptype != InetSocketAddress.class)
throw new RuntimeException("@RestHeader must on String or InetSocketAddress Parameter in " + method);
n = annhead.name();
radix = annhead.radix();
comment = annhead.comment();
if (n.isEmpty())
throw new RuntimeException("@RestHeader.value is illegal in " + method);
}
RestCookie anncookie = param.getAnnotation(RestCookie.class);
if (anncookie != null) {
if (annhead != null)
throw new RuntimeException("@RestCookie and @RestHeader cannot on the same Parameter in " + method);
if (ptype != String.class)
throw new RuntimeException("@RestCookie must on String Parameter in " + method);
n = anncookie.name();
radix = anncookie.radix();
comment = anncookie.comment();
if (n.isEmpty())
throw new RuntimeException("@RestCookie.value is illegal in " + method);
}
RestSessionid annsid = param.getAnnotation(RestSessionid.class);
if (annsid != null) {
if (annhead != null)
throw new RuntimeException("@RestSessionid and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestSessionid and @RestCookie cannot on the same Parameter in " + method);
if (ptype != String.class)
throw new RuntimeException("@RestSessionid must on String Parameter in " + method);
}
RestAddress annaddr = param.getAnnotation(RestAddress.class);
if (annaddr != null) {
if (annhead != null)
throw new RuntimeException("@RestAddress and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestAddress and @RestCookie cannot on the same Parameter in " + method);
if (annsid != null)
throw new RuntimeException("@RestAddress and @RestSessionid cannot on the same Parameter in " + method);
if (ptype != String.class)
throw new RuntimeException("@RestAddress must on String Parameter in " + method);
comment = annaddr.comment();
}
RestBody annbody = param.getAnnotation(RestBody.class);
if (annbody != null) {
if (annhead != null)
throw new RuntimeException("@RestBody and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestBody and @RestCookie cannot on the same Parameter in " + method);
if (annsid != null)
throw new RuntimeException("@RestBody and @RestSessionid cannot on the same Parameter in " + method);
if (annaddr != null)
throw new RuntimeException("@RestBody and @RestAddress cannot on the same Parameter in " + method);
if (ptype.isPrimitive())
throw new RuntimeException("@RestBody cannot on primitive type Parameter in " + method);
comment = annbody.comment();
}
RestUploadFile annfile = param.getAnnotation(RestUploadFile.class);
if (annfile != null) {
if (mupload != null)
throw new RuntimeException("@RestUploadFile repeat in " + method);
mupload = annfile;
muploadType = ptype;
if (annhead != null)
throw new RuntimeException("@RestUploadFile and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestUploadFile and @RestCookie cannot on the same Parameter in " + method);
if (annsid != null)
throw new RuntimeException("@RestUploadFile and @RestSessionid cannot on the same Parameter in " + method);
if (annaddr != null)
throw new RuntimeException("@RestUploadFile and @RestAddress cannot on the same Parameter in " + method);
if (annbody != null)
throw new RuntimeException("@RestUploadFile and @RestBody cannot on the same Parameter in " + method);
if (ptype != byte[].class && ptype != File.class && ptype != File[].class)
throw new RuntimeException("@RestUploadFile must on byte[] or File or File[] Parameter in " + method);
comment = annfile.comment();
}
RestURI annuri = param.getAnnotation(RestURI.class);
if (annuri != null) {
if (annhead != null)
throw new RuntimeException("@RestURI and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestURI and @RestCookie cannot on the same Parameter in " + method);
if (annsid != null)
throw new RuntimeException("@RestURI and @RestSessionid cannot on the same Parameter in " + method);
if (annaddr != null)
throw new RuntimeException("@RestURI and @RestAddress cannot on the same Parameter in " + method);
if (annbody != null)
throw new RuntimeException("@RestURI and @RestBody cannot on the same Parameter in " + method);
if (annfile != null)
throw new RuntimeException("@RestURI and @RestUploadFile cannot on the same Parameter in " + method);
if (ptype != String.class)
throw new RuntimeException("@RestURI must on String Parameter in " + method);
comment = annuri.comment();
}
RestUserid userid = param.getAnnotation(RestUserid.class);
if (userid != null) {
if (annhead != null)
throw new RuntimeException("@RestUserid and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestUserid and @RestCookie cannot on the same Parameter in " + method);
if (annsid != null)
throw new RuntimeException("@RestUserid and @RestSessionid cannot on the same Parameter in " + method);
if (annaddr != null)
throw new RuntimeException("@RestUserid and @RestAddress cannot on the same Parameter in " + method);
if (annbody != null)
throw new RuntimeException("@RestUserid and @RestBody cannot on the same Parameter in " + method);
if (annfile != null)
throw new RuntimeException("@RestUserid and @RestUploadFile cannot on the same Parameter in " + method);
if (!ptype.isPrimitive() && !java.io.Serializable.class.isAssignableFrom(ptype))
throw new RuntimeException("@RestUserid must on java.io.Serializable Parameter in " + method);
comment = "";
}
RestHeaders annheaders = param.getAnnotation(RestHeaders.class);
if (annheaders != null) {
if (annhead != null)
throw new RuntimeException("@RestHeaders and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestHeaders and @RestCookie cannot on the same Parameter in " + method);
if (annsid != null)
throw new RuntimeException("@RestHeaders and @RestSessionid cannot on the same Parameter in " + method);
if (annaddr != null)
throw new RuntimeException("@RestHeaders and @RestAddress cannot on the same Parameter in " + method);
if (annbody != null)
throw new RuntimeException("@RestHeaders and @RestBody cannot on the same Parameter in " + method);
if (annfile != null)
throw new RuntimeException("@RestHeaders and @RestUploadFile cannot on the same Parameter in " + method);
if (userid != null)
throw new RuntimeException("@RestHeaders and @RestUserid cannot on the same Parameter in " + method);
if (!TYPE_MAP_STRING_STRING.equals(param.getParameterizedType()))
throw new RuntimeException("@RestHeaders must on Map<String, String> Parameter in " + method);
comment = "";
}
RestParams annparams = param.getAnnotation(RestParams.class);
if (annparams != null) {
if (annhead != null)
throw new RuntimeException("@RestParams and @RestHeader cannot on the same Parameter in " + method);
if (anncookie != null)
throw new RuntimeException("@RestParams and @RestCookie cannot on the same Parameter in " + method);
if (annsid != null)
throw new RuntimeException("@RestParams and @RestSessionid cannot on the same Parameter in " + method);
if (annaddr != null)
throw new RuntimeException("@RestParams and @RestAddress cannot on the same Parameter in " + method);
if (annbody != null)
throw new RuntimeException("@RestParams and @RestBody cannot on the same Parameter in " + method);
if (annfile != null)
throw new RuntimeException("@RestParams and @RestUploadFile cannot on the same Parameter in " + method);
if (userid != null)
throw new RuntimeException("@RestParams and @RestUserid cannot on the same Parameter in " + method);
if (annheaders != null)
throw new RuntimeException("@RestParams and @RestHeaders cannot on the same Parameter in " + method);
if (!TYPE_MAP_STRING_STRING.equals(param.getParameterizedType()))
throw new RuntimeException("@RestParams must on Map<String, String> Parameter in " + method);
comment = "";
}
RestParam annpara = param.getAnnotation(RestParam.class);
if (annpara != null)
radix = annpara.radix();
if (annpara != null)
comment = annpara.comment();
if (annpara != null)
required = annpara.required();
if (n == null)
n = (annpara == null || annpara.name().isEmpty()) ? null : annpara.name();
// 用户类型特殊处理
if (n == null && ptype == userType)
n = "&";
if (n == null && asmParamNames != null && asmParamNames.size() > i)
n = asmParamNames.get(i);
if (n == null) {
if (param.isNamePresent()) {
n = param.getName();
} else if (ptype == Flipper.class) {
n = "flipper";
} else {
throw new RuntimeException("Parameter " + param.getName() + " not found name by @RestParam in " + method);
}
}
if (annhead == null && anncookie == null && annsid == null && annaddr == null && annbody == null && annfile == null && !ptype.isPrimitive() && ptype != String.class && ptype != Flipper.class && !CompletionHandler.class.isAssignableFrom(ptype) && !ptype.getName().startsWith("java") && n.charAt(0) != '#' && !"&".equals(n)) {
// 判断Json对象是否包含@RestUploadFile
Class loop = ptype;
do {
// 接口时getSuperclass可能会得到null
if (loop == null || loop.isInterface())
break;
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()))
continue;
if (Modifier.isFinal(field.getModifiers()))
continue;
RestUploadFile ruf = field.getAnnotation(RestUploadFile.class);
if (ruf == null)
continue;
if (mupload != null)
throw new RuntimeException("@RestUploadFile repeat in " + method + " or field " + field);
mupload = ruf;
muploadType = field.getType();
}
} while ((loop = loop.getSuperclass()) != Object.class);
}
java.lang.reflect.Type paramtype = TypeToken.getGenericType(param.getParameterizedType(), serviceType);
paramlist.add(new Object[] { param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, userid, annheaders, annparams, paramtype });
}
Map<String, Object> mappingMap = new LinkedHashMap<>();
{
// 设置 Annotation
// 设置 HttpMapping
boolean reqpath = false;
for (Object[] ps : paramlist) {
if ("#".equals((String) ps[1])) {
reqpath = true;
break;
}
}
if (method.getAnnotation(Deprecated.class) != null) {
av0 = mv.visitAnnotation(Type.getDescriptor(Deprecated.class), true);
av0.visitEnd();
}
av0 = mv.visitAnnotation(mappingDesc, true);
String url = (catalog.isEmpty() ? "/" : ("/" + catalog + "/")) + (defmodulename.isEmpty() ? "" : (defmodulename + "/")) + entry.name + (reqpath ? "/" : "");
if ("//".equals(url))
url = "/";
av0.visit("url", url);
av0.visit("name", (defmodulename.isEmpty() ? "" : (defmodulename + "_")) + entry.name);
av0.visit("example", entry.example);
av0.visit("rpconly", entry.rpconly);
av0.visit("auth", entry.auth);
av0.visit("cacheseconds", entry.cacheseconds);
av0.visit("actionid", entry.actionid);
av0.visit("comment", entry.comment);
AnnotationVisitor av1 = av0.visitArray("methods");
for (String m : entry.methods) {
av1.visit(null, m);
}
av1.visitEnd();
java.lang.reflect.Type grt = TypeToken.getGenericType(method.getGenericReturnType(), serviceType);
Class rtc = returnType;
if (rtc == void.class) {
rtc = RetResult.class;
grt = TYPE_RETRESULT_STRING;
} else if (CompletionStage.class.isAssignableFrom(returnType)) {
ParameterizedType ptgrt = (ParameterizedType) grt;
grt = ptgrt.getActualTypeArguments()[0];
rtc = TypeToken.typeToClass(grt);
// 应该不会发生吧?
if (rtc == null)
rtc = Object.class;
}
av0.visit("result", Type.getType(Type.getDescriptor(rtc)));
if (grt != rtc) {
String refid = typeRefs.get(grt);
if (refid == null) {
refid = "_typeref_" + typeRefs.size();
typeRefs.put(grt, refid);
}
av0.visit("resultref", refid);
}
av0.visitEnd();
mappingMap.put("url", url);
mappingMap.put("rpconly", entry.rpconly);
mappingMap.put("auth", entry.auth);
mappingMap.put("cacheseconds", entry.cacheseconds);
mappingMap.put("actionid", entry.actionid);
mappingMap.put("comment", entry.comment);
mappingMap.put("methods", entry.methods);
mappingMap.put("result", grt == returnType ? returnType.getName() : String.valueOf(grt));
entry.mappingurl = url;
}
{
// 设置 Annotation
av0 = mv.visitAnnotation(httpParamsDesc, true);
AnnotationVisitor av1 = av0.visitArray("value");
// 设置 HttpParam
for (Object[] ps : paramlist) {
// {param, n, ptype, radix, comment, required, annpara, annsid, annaddr, annhead, anncookie, annbody, annfile, annuri, annuserid, annheaders, annparams, paramtype}
String n = ps[1].toString();
// 是否取userid
final boolean isuserid = ((RestUserid) ps[14]) != null;
// @RestUserid 不需要生成 @HttpParam
if (n.indexOf('&') >= 0 || isuserid)
continue;
// @RestAddress 不需要生成 @HttpParam
if (((RestAddress) ps[8]) != null)
continue;
// 是否取getHeader 而不是 getParameter
final boolean ishead = ((RestHeader) ps[9]) != null;
// 是否取getCookie
final boolean iscookie = ((RestCookie) ps[10]) != null;
// 是否取getBody
final boolean isbody = ((RestBody) ps[11]) != null;
AnnotationVisitor av2 = av1.visitAnnotation(null, httpParamDesc);
av2.visit("name", (String) ps[1]);
if (((Parameter) ps[0]).getAnnotation(Deprecated.class) != null) {
av2.visit("deprecated", true);
}
av2.visit("type", Type.getType(Type.getDescriptor((Class) ps[2])));
java.lang.reflect.Type pgtype = TypeToken.getGenericType(((Parameter) ps[0]).getParameterizedType(), serviceType);
if (pgtype != (Class) ps[2]) {
String refid = typeRefs.get(pgtype);
if (refid == null) {
refid = "_typeref_" + typeRefs.size();
typeRefs.put(pgtype, refid);
}
av2.visit("typeref", refid);
}
av2.visit("radix", (Integer) ps[3]);
if (ishead) {
av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.HEADER.name());
av2.visit("example", ((RestHeader) ps[9]).example());
} else if (iscookie) {
av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.COOKIE.name());
av2.visit("example", ((RestCookie) ps[10]).example());
} else if (isbody) {
av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.BODY.name());
av2.visit("example", ((RestBody) ps[11]).example());
} else if (ps[6] != null) {
av2.visitEnum("style", sourcetypeDesc, HttpParam.HttpParameterStyle.QUERY.name());
av2.visit("example", ((RestParam) ps[6]).example());
}
av2.visit("comment", (String) ps[4]);
av2.visit("required", (Boolean) ps[5]);
av2.visitEnd();
}
av1.visitEnd();
av0.visitEnd();
}
int uploadLocal = 0;
if (mupload != null) {
// 存在文件上传
if (muploadType == byte[].class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()" + multiContextDesc, false);
mv.visitLdcInsn(mupload.maxLength());
mv.visitLdcInsn(mupload.fileNameReg());
mv.visitLdcInsn(mupload.contentTypeReg());
mv.visitMethodInsn(INVOKEVIRTUAL, multiContextName, "partsFirstBytes", "(JLjava/lang/String;Ljava/lang/String;)[B", false);
mv.visitVarInsn(ASTORE, maxLocals);
uploadLocal = maxLocals;
} else if (muploadType == File.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()" + multiContextDesc, false);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_home", "Ljava/io/File;");
mv.visitLdcInsn(mupload.maxLength());
mv.visitLdcInsn(mupload.fileNameReg());
mv.visitLdcInsn(mupload.contentTypeReg());
mv.visitMethodInsn(INVOKEVIRTUAL, multiContextName, "partsFirstFile", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)Ljava/io/File;", false);
mv.visitVarInsn(ASTORE, maxLocals);
uploadLocal = maxLocals;
} else if (muploadType == File[].class) {
// File[]
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()" + multiContextDesc, false);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "_redkale_home", "Ljava/io/File;");
mv.visitLdcInsn(mupload.maxLength());
mv.visitLdcInsn(mupload.fileNameReg());
mv.visitLdcInsn(mupload.contentTypeReg());
mv.visitMethodInsn(INVOKEVIRTUAL, multiContextName, "partsFiles", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)[Ljava/io/File;", false);
mv.visitVarInsn(ASTORE, maxLocals);
uploadLocal = maxLocals;
}
maxLocals++;
}
List<Map<String, Object>> paramMaps = new ArrayList<>();
// 获取每个参数的值
boolean hasAsyncHandler = false;
for (Object[] ps : paramlist) {
Map<String, Object> paramMap = new LinkedHashMap<>();
// 参数类型
final Parameter param = (Parameter) ps[0];
// 参数名
String pname = (String) ps[1];
// 参数类型
Class ptype = (Class) ps[2];
int radix = (Integer) ps[3];
String comment = (String) ps[4];
boolean required = (Boolean) ps[5];
RestParam annpara = (RestParam) ps[6];
RestSessionid annsid = (RestSessionid) ps[7];
RestAddress annaddr = (RestAddress) ps[8];
RestHeader annhead = (RestHeader) ps[9];
RestCookie anncookie = (RestCookie) ps[10];
RestBody annbody = (RestBody) ps[11];
RestUploadFile annfile = (RestUploadFile) ps[12];
RestURI annuri = (RestURI) ps[13];
RestUserid userid = (RestUserid) ps[14];
RestHeaders annheaders = (RestHeaders) ps[15];
RestParams annparams = (RestParams) ps[16];
java.lang.reflect.Type pgentype = (java.lang.reflect.Type) ps[17];
if (dynsimple && (annsid != null || annaddr != null || annhead != null || anncookie != null || annfile != null || annheaders != null))
dynsimple = false;
// 是否取getHeader 而不是 getParameter
final boolean ishead = annhead != null;
// 是否取getCookie
final boolean iscookie = anncookie != null;
paramMap.put("name", pname);
paramMap.put("type", ptype.getName());
if (CompletionHandler.class.isAssignableFrom(ptype)) {
// HttpResponse.createAsyncHandler() or HttpResponse.createAsyncHandler(Class)
if (ptype == CompletionHandler.class) {
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "createAsyncHandler", "()Ljava/nio/channels/CompletionHandler;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else {
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 2);
mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype)));
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "createAsyncHandler", "(Ljava/lang/Class;)Ljava/nio/channels/CompletionHandler;", false);
mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
}
hasAsyncHandler = true;
} else if (annsid != null) {
// HttpRequest.getSessionid(true|false)
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(annsid.create() ? ICONST_1 : ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getSessionid", "(Z)Ljava/lang/String;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (annaddr != null) {
// HttpRequest.getRemoteAddr
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRemoteAddr", "()Ljava/lang/String;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (annheaders != null) {
// HttpRequest.getHeaders
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeaders", "()Ljava/util/Map;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (annparams != null) {
// HttpRequest.getParameters
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getParameters", "()Ljava/util/Map;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (annbody != null) {
// HttpRequest.getBodyUTF8 / HttpRequest.getBody
if (ptype == String.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyUTF8", "()Ljava/lang/String;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (ptype == byte[].class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBody", "()[B", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else {
// JavaBean 转 Json
String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
bodyTypes.put(typefieldname, pgentype);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyJson", "(Ljava/lang/reflect/Type;)Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ptype));
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
}
} else if (annfile != null) {
// MultiContext.partsFirstBytes / HttpRequest.partsFirstFile / HttpRequest.partsFiles
mv.visitVarInsn(ALOAD, 4);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (annuri != null) {
// HttpRequest.getRequestURI
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequestURI", "()Ljava/lang/String;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (userid != null) {
// HttpRequest.currentUserid
mv.visitVarInsn(ALOAD, 1);
if (ptype == int.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
} else if (ptype == long.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
} else {
mv.visitLdcInsn(Type.getType(Type.getInternalName(ptype)));
}
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "currentUserid", "(Ljava/lang/Class;)Ljava/io/Serializable;", false);
if (ptype == int.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitMethodInsn(INVOKESTATIC, restInternalName, "orElse", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == long.class) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
mv.visitInsn(LCONST_0);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
mv.visitMethodInsn(INVOKESTATIC, restInternalName, "orElse", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
mv.visitVarInsn(LSTORE, maxLocals);
varInsns.add(new int[] { LLOAD, maxLocals });
maxLocals++;
} else {
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ptype));
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
}
} else if ("#".equals(pname)) {
// 从request.getRequstURI 中取参数
if (ptype == boolean.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "parseBoolean", "(Ljava/lang/String;)Z", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == byte.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "parseByte", "(Ljava/lang/String;I)B", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == short.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "parseShort", "(Ljava/lang/String;I)S", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == char.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == int.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "parseInt", "(Ljava/lang/String;I)I", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == float.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "parseFloat", "(Ljava/lang/String;)F", false);
mv.visitVarInsn(FSTORE, maxLocals);
varInsns.add(new int[] { FLOAD, maxLocals });
} else if (ptype == long.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "parseLong", "(Ljava/lang/String;I)J", false);
mv.visitVarInsn(LSTORE, maxLocals);
varInsns.add(new int[] { LLOAD, maxLocals });
maxLocals++;
} else if (ptype == double.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "parseDouble", "(Ljava/lang/String;)D", false);
mv.visitVarInsn(DSTORE, maxLocals);
varInsns.add(new int[] { DLOAD, maxLocals });
maxLocals++;
} else if (ptype == String.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURILastPath", "()Ljava/lang/String;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else {
throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)");
}
} else if (pname.charAt(0) == '#') {
// 从request.getRequstURIPath 中去参数
if (ptype == boolean.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("false");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "parseBoolean", "(Ljava/lang/String;)Z", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == byte.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "parseByte", "(Ljava/lang/String;I)B", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == short.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "parseShort", "(Ljava/lang/String;I)S", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == char.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == int.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "parseInt", "(Ljava/lang/String;I)I", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == float.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "parseFloat", "(Ljava/lang/String;)F", false);
mv.visitVarInsn(FSTORE, maxLocals);
varInsns.add(new int[] { FLOAD, maxLocals });
} else if (ptype == long.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "parseLong", "(Ljava/lang/String;I)J", false);
mv.visitVarInsn(LSTORE, maxLocals);
varInsns.add(new int[] { LLOAD, maxLocals });
maxLocals++;
} else if (ptype == double.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "parseDouble", "(Ljava/lang/String;)D", false);
mv.visitVarInsn(DSTORE, maxLocals);
varInsns.add(new int[] { DLOAD, maxLocals });
maxLocals++;
} else if (ptype == String.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname.substring(1));
mv.visitLdcInsn("");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequstURIPath", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else {
throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)");
}
} else if ("&".equals(pname) && ptype == userType) {
// 当前用户对象的类名
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "currentUser", "()Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ptype));
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (ptype == boolean.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname);
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getBooleanHeader" : "getBooleanParameter", "(Ljava/lang/String;Z)Z", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == byte.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname);
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getHeader" : "getParameter", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitIntInsn(BIPUSH, radix);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "parseByte", "(Ljava/lang/String;I)B", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == short.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitIntInsn(BIPUSH, radix);
mv.visitLdcInsn(pname);
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getShortHeader" : "getShortParameter", "(ILjava/lang/String;S)S", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == char.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname);
mv.visitLdcInsn("0");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getHeader" : "getParameter", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == int.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitIntInsn(BIPUSH, radix);
mv.visitLdcInsn(pname);
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getIntHeader" : "getIntParameter", "(ILjava/lang/String;I)I", false);
mv.visitVarInsn(ISTORE, maxLocals);
varInsns.add(new int[] { ILOAD, maxLocals });
} else if (ptype == float.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname);
mv.visitInsn(FCONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getFloatHeader" : "getFloatParameter", "(Ljava/lang/String;F)F", false);
mv.visitVarInsn(FSTORE, maxLocals);
varInsns.add(new int[] { FLOAD, maxLocals });
} else if (ptype == long.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitIntInsn(BIPUSH, radix);
mv.visitLdcInsn(pname);
mv.visitInsn(LCONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getLongHeader" : "getLongParameter", "(ILjava/lang/String;J)J", false);
mv.visitVarInsn(LSTORE, maxLocals);
varInsns.add(new int[] { LLOAD, maxLocals });
maxLocals++;
} else if (ptype == double.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname);
mv.visitInsn(DCONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getDoubleHeader" : "getDoubleParameter", "(Ljava/lang/String;D)D", false);
mv.visitVarInsn(DSTORE, maxLocals);
varInsns.add(new int[] { DLOAD, maxLocals });
maxLocals++;
} else if (ptype == String.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(pname);
mv.visitLdcInsn("");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, iscookie ? "getCookie" : (ishead ? "getHeader" : "getParameter"), "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (ptype == ChannelContext.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getChannelContext", "()" + channelDesc, false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else if (ptype == Flipper.class) {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getFlipper", "()" + flipperDesc, false);
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
} else {
// 其他Json对象
mv.visitVarInsn(ALOAD, 1);
if (param.getType() == param.getParameterizedType()) {
mv.visitLdcInsn(Type.getType(Type.getDescriptor(ptype)));
} else {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_PARAMTYPES_FIELD_NAME, "[[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
int paramidx = -1;
for (int i = 0; i < params.length; i++) {
if (params[i] == param) {
paramidx = i;
break;
}
}
// 参数下标
MethodDebugVisitor.pushInt(mv, paramidx);
mv.visitInsn(AALOAD);
}
mv.visitLdcInsn(pname);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, ishead ? "getJsonHeader" : "getJsonParameter", "(Ljava/lang/reflect/Type;Ljava/lang/String;)Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, ptype.getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[] { ALOAD, maxLocals });
JsonFactory.root().loadDecoder(param.getParameterizedType());
// 构建 RestHeader、RestCookie、RestAddress 等赋值操作
Class loop = ptype;
Set<String> fields = new HashSet<>();
Map<String, Object[]> attrParaNames = new LinkedHashMap<>();
do {
// 接口时getSuperclass可能会得到null
if (loop == null || loop.isInterface())
break;
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()))
continue;
if (Modifier.isFinal(field.getModifiers()))
continue;
if (fields.contains(field.getName()))
continue;
RestHeader rh = field.getAnnotation(RestHeader.class);
RestCookie rc = field.getAnnotation(RestCookie.class);
RestSessionid rs = field.getAnnotation(RestSessionid.class);
RestAddress ra = field.getAnnotation(RestAddress.class);
RestBody rb = field.getAnnotation(RestBody.class);
RestUploadFile ru = field.getAnnotation(RestUploadFile.class);
RestURI ri = field.getAnnotation(RestURI.class);
if (rh == null && rc == null && ra == null && rb == null && rs == null && ru == null && ri == null)
continue;
if (rh != null && field.getType() != String.class && field.getType() != InetSocketAddress.class)
throw new RuntimeException("@RestHeader must on String Field in " + field);
if (rc != null && field.getType() != String.class)
throw new RuntimeException("@RestCookie must on String Field in " + field);
if (rs != null && field.getType() != String.class)
throw new RuntimeException("@RestSessionid must on String Field in " + field);
if (ra != null && field.getType() != String.class)
throw new RuntimeException("@RestAddress must on String Field in " + field);
if (rb != null && field.getType().isPrimitive())
throw new RuntimeException("@RestBody must on cannot on primitive type Field in " + field);
if (ru != null && field.getType() != byte[].class && field.getType() != File.class && field.getType() != File[].class) {
throw new RuntimeException("@RestUploadFile must on byte[] or File or File[] Field in " + field);
}
if (ri != null && field.getType() != String.class)
throw new RuntimeException("@RestURI must on String Field in " + field);
org.redkale.util.Attribute attr = org.redkale.util.Attribute.create(loop, field);
String attrFieldName;
String restname = "";
if (rh != null) {
attrFieldName = "_redkale_attr_header_" + (field.getType() != String.class ? "json_" : "") + restAttributes.size();
restname = rh.name();
} else if (rc != null) {
attrFieldName = "_redkale_attr_cookie_" + restAttributes.size();
restname = rc.name();
} else if (rs != null) {
attrFieldName = "_redkale_attr_sessionid_" + restAttributes.size();
// 用于下面区分create值
restname = rs.create() ? "1" : "";
} else if (ra != null) {
attrFieldName = "_redkale_attr_address_" + restAttributes.size();
// restname = "";
} else if (rb != null && field.getType() == String.class) {
attrFieldName = "_redkale_attr_bodystring_" + restAttributes.size();
// restname = "";
} else if (rb != null && field.getType() == byte[].class) {
attrFieldName = "_redkale_attr_bodybytes_" + restAttributes.size();
// restname = "";
} else if (rb != null && field.getType() != String.class && field.getType() != byte[].class) {
attrFieldName = "_redkale_attr_bodyjson_" + restAttributes.size();
// restname = "";
} else if (ru != null && field.getType() == byte[].class) {
attrFieldName = "_redkale_attr_uploadbytes_" + restAttributes.size();
// restname = "";
} else if (ru != null && field.getType() == File.class) {
attrFieldName = "_redkale_attr_uploadfile_" + restAttributes.size();
// restname = "";
} else if (ru != null && field.getType() == File[].class) {
attrFieldName = "_redkale_attr_uploadfiles_" + restAttributes.size();
// restname = "";
} else if (ri != null && field.getType() == String.class) {
attrFieldName = "_redkale_attr_uri_" + restAttributes.size();
// restname = "";
} else {
continue;
}
restAttributes.put(attrFieldName, attr);
attrParaNames.put(attrFieldName, new Object[] { restname, field.getType(), field.getGenericType(), ru });
fields.add(field.getName());
}
} while ((loop = loop.getSuperclass()) != Object.class);
if (!attrParaNames.isEmpty()) {
// 参数存在 RestHeader、RestCookie、RestSessionid、RestAddress、RestBody字段
// 加载JsonBean
mv.visitVarInsn(ALOAD, maxLocals);
Label lif = new Label();
// if(bean != null) {
mv.visitJumpInsn(IFNULL, lif);
for (Map.Entry<String, Object[]> en : attrParaNames.entrySet()) {
RestUploadFile ru = (RestUploadFile) en.getValue()[3];
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, en.getKey(), attrDesc);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitVarInsn(ALOAD, en.getKey().contains("_upload") ? uploadLocal : 1);
if (en.getKey().contains("_header_")) {
String headerkey = en.getValue()[0].toString();
if ("Host".equalsIgnoreCase(headerkey)) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHost", "()Ljava/lang/String;", false);
} else if ("Content-Type".equalsIgnoreCase(headerkey)) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getContentType", "()Ljava/lang/String;", false);
} else if ("Connection".equalsIgnoreCase(headerkey)) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getConnection", "()Ljava/lang/String;", false);
} else if ("Method".equalsIgnoreCase(headerkey)) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMethod", "()Ljava/lang/String;", false);
} else if (en.getKey().contains("_header_json_")) {
String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
mv.visitLdcInsn(headerkey);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getJsonHeader", "(Ljava/lang/reflect/Type;Ljava/lang/String;)Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName((Class) en.getValue()[1]));
JsonFactory.root().loadDecoder((java.lang.reflect.Type) en.getValue()[2]);
} else {
mv.visitLdcInsn(headerkey);
mv.visitLdcInsn("");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeader", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
}
} else if (en.getKey().contains("_cookie_")) {
mv.visitLdcInsn(en.getValue()[0].toString());
mv.visitLdcInsn("");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getCookie", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
} else if (en.getKey().contains("_sessionid_")) {
mv.visitInsn(en.getValue()[0].toString().isEmpty() ? ICONST_0 : ICONST_1);
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getSessionid", "(Z)Ljava/lang/String;", false);
} else if (en.getKey().contains("_address_")) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRemoteAddr", "()Ljava/lang/String;", false);
} else if (en.getKey().contains("_uri_")) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getRequestURI", "()Ljava/lang/String;", false);
} else if (en.getKey().contains("_bodystring_")) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyUTF8", "()Ljava/lang/String;", false);
} else if (en.getKey().contains("_bodybytes_")) {
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBody", "()[B", false);
} else if (en.getKey().contains("_bodyjson_")) {
// JavaBean 转 Json
String typefieldname = "_redkale_body_jsontype_" + bodyTypes.size();
bodyTypes.put(typefieldname, (java.lang.reflect.Type) en.getValue()[2]);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, typefieldname, "Ljava/lang/reflect/Type;");
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getBodyJson", "(Ljava/lang/reflect/Type;)Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName((Class) en.getValue()[1]));
JsonFactory.root().loadDecoder((java.lang.reflect.Type) en.getValue()[2]);
} else if (en.getKey().contains("_uploadbytes_")) {
// 只需mv.visitVarInsn(ALOAD, 4), 无需处理
} else if (en.getKey().contains("_uploadfile_")) {
// 只需mv.visitVarInsn(ALOAD, 4), 无需处理
} else if (en.getKey().contains("_uploadfiles_")) {
// 只需mv.visitVarInsn(ALOAD, 4), 无需处理
}
mv.visitMethodInsn(INVOKEINTERFACE, attrInternalName, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
}
// end if }
mv.visitLabel(lif);
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { ptype.getName().replace('.', '/') }, 0, null);
}
}
maxLocals++;
paramMaps.add(paramMap);
}
// end params for each
// mv.visitVarInsn(ALOAD, 0); //调用this
// mv.visitFieldInsn(GETFIELD, newDynName, REST_SERVICE_FIELD_NAME, serviceDesc);
mv.visitVarInsn(ALOAD, 3);
for (int[] ins : varInsns) {
mv.visitVarInsn(ins[0], ins[1]);
}
mv.visitMethodInsn(INVOKEVIRTUAL, serviceTypeInternalName, method.getName(), methodDesc, false);
if (hasAsyncHandler) {
mv.visitInsn(RETURN);
} else if (returnType == void.class) {
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitMethodInsn(INVOKESTATIC, retInternalName, "success", "()" + retDesc, false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + typeDesc + "Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
} else if (returnType == boolean.class) {
mv.visitVarInsn(ISTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ILOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Z)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == byte.class) {
mv.visitVarInsn(ISTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ILOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == short.class) {
mv.visitVarInsn(ISTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ILOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == char.class) {
mv.visitVarInsn(ISTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ILOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(C)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == int.class) {
mv.visitVarInsn(ISTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ILOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == float.class) {
mv.visitVarInsn(FSTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(FLOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(F)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == long.class) {
mv.visitVarInsn(LSTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(LLOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(J)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals += 2;
} else if (returnType == double.class) {
mv.visitVarInsn(DSTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(DLOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(D)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals += 2;
} else if (returnType == byte[].class) {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "([B)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == String.class) {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == File.class) {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/io/File;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (Number.class.isAssignableFrom(returnType) || CharSequence.class.isAssignableFrom(returnType)) {
// returnType == String.class 必须放在前面
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
maxLocals++;
} else if (RetResult.class.isAssignableFrom(returnType)) {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
if (rcs != null && rcs.length > 0) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + retDesc + ")V", false);
} else {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + retDesc + ")V", false);
}
mv.visitInsn(RETURN);
maxLocals++;
} else if (HttpResult.class.isAssignableFrom(returnType)) {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
if (rcs != null && rcs.length > 0) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + httpResultDesc + ")V", false);
} else {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + httpResultDesc + ")V", false);
}
mv.visitInsn(RETURN);
maxLocals++;
} else if (HttpScope.class.isAssignableFrom(returnType)) {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
if (rcs != null && rcs.length > 0) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + httpScopeDesc + ")V", false);
} else {
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + httpScopeDesc + ")V", false);
}
mv.visitInsn(RETURN);
maxLocals++;
} else if (CompletionStage.class.isAssignableFrom(returnType)) {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
if (rcs != null && rcs.length > 0) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + stageDesc + ")V", false);
} else {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + stageDesc + ")V", false);
}
mv.visitInsn(RETURN);
maxLocals++;
} else if (Flows.maybePublisherClass(returnType)) {
// Flow.Publisher
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
if (rcs != null && rcs.length > 0) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishPublisher", "(" + convertDesc + typeDesc + "Ljava/lang/Object;)V", false);
} else {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishPublisher", "(" + typeDesc + "Ljava/lang/Object;)V", false);
}
mv.visitInsn(RETURN);
maxLocals++;
} else if (returnType == retvalType) {
// 普通JavaBean或JavaBean[]
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
if (rcs != null && rcs.length > 0) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + Type.getDescriptor(JsonConvert.class) + typeDesc + "Ljava/lang/Object;)V", false);
} else {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finishJson", "(" + typeDesc + "Ljava/lang/Object;)V", false);
}
mv.visitInsn(RETURN);
maxLocals++;
} else {
mv.visitVarInsn(ASTORE, maxLocals);
// response
mv.visitVarInsn(ALOAD, 2);
if (rcs != null && rcs.length > 0) {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_CONVERT_FIELD_PREFIX + restConverts.size(), convertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + "Ljava/lang/Object;)V", false);
} else {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;");
// 方法下标
MethodDebugVisitor.pushInt(mv, entry.methodidx);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + typeDesc + "Ljava/lang/Object;)V", false);
}
mv.visitInsn(RETURN);
maxLocals++;
}
mv.visitMaxs(maxStack, maxLocals);
mappingMap.put("params", paramMaps);
{
// _Dync_XXX__HttpServlet.class
ClassWriter cw2 = new ClassWriter(COMPUTE_FRAMES);
cw2.visit(V11, ACC_SUPER, newDynName + "$" + entry.newActionClassName, null, httpServletName, null);
cw2.visitInnerClass(newDynName + "$" + entry.newActionClassName, newDynName, entry.newActionClassName, ACC_PRIVATE + ACC_STATIC);
{
fv = cw2.visitField(0, "servlet", "L" + newDynName + ";", null, null);
fv.visitEnd();
}
{
mv = new MethodDebugVisitor(cw2.visitMethod(0, "<init>", "(L" + newDynName + ";)V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, httpServletName, "<init>", "()V", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, newDynName + "$" + entry.newActionClassName, "servlet", "L" + newDynName + ";");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
// if (false) {
// mv = new MethodDebugVisitor(cw2.visitMethod(ACC_SYNTHETIC, "<init>", "(L" + newDynName + ";L" + newDynName + "$" + entry.newActionClassName + ";)V", null, null));
// mv.visitVarInsn(ALOAD, 0);
// mv.visitVarInsn(ALOAD, 1);
// mv.visitMethodInsn(INVOKESPECIAL, newDynName + "$" + entry.newActionClassName, "<init>", "L" + newDynName + ";", false);
// mv.visitInsn(RETURN);
// mv.visitMaxs(2, 3);
// mv.visitEnd();
// }
{
mv = new MethodDebugVisitor(cw2.visitMethod(ACC_PUBLIC, "execute", "(" + reqDesc + respDesc + ")V", null, new String[] { "java/io/IOException" }));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName + "$" + entry.newActionClassName, "servlet", "L" + newDynName + ";");
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, entry.newMethodName, "(" + reqDesc + respDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw2.visitEnd();
byte[] bytes = cw2.toByteArray();
newLoader.addClass((newDynName + "$" + entry.newActionClassName).replace('/', '.'), bytes);
innerClassBytesMap.put((newDynName + "$" + entry.newActionClassName).replace('/', '.'), bytes);
}
}
// end for each
// HashMap<String, ActionEntry> _createRestActionEntry() {
// HashMap<String, ActionEntry> map = new HashMap<>();
// map.put("asyncfind3", new ActionEntry(100000,200000,"asyncfind3", new String[]{},null,false,false,0, new _Dync_asyncfind3_HttpServlet()));
// map.put("asyncfind2", new ActionEntry(1,2,"asyncfind2", new String[]{"GET", "POST"},null,false,true,0, new _Dync_asyncfind2_HttpServlet()));
// return map;
// }
{
// _createRestActionEntry 方法
mv = new MethodDebugVisitor(cw.visitMethod(0, "_createRestActionEntry", "()Ljava/util/HashMap;", "()Ljava/util/HashMap<Ljava/lang/String;L" + actionEntryName + ";>;", null));
// mv.setDebug(true);
mv.visitTypeInsn(NEW, "java/util/HashMap");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false);
mv.visitVarInsn(ASTORE, 1);
for (final MappingEntry entry : entrys) {
mappingurlToMethod.put(entry.mappingurl, entry.mappingMethod);
mv.visitVarInsn(ALOAD, 1);
// name
mv.visitLdcInsn(entry.mappingurl);
// new ActionEntry
mv.visitTypeInsn(NEW, actionEntryName);
mv.visitInsn(DUP);
// moduleid
MethodDebugVisitor.pushInt(mv, moduleid);
// actionid
MethodDebugVisitor.pushInt(mv, entry.actionid);
// name
mv.visitLdcInsn(entry.mappingurl);
// methods
MethodDebugVisitor.pushInt(mv, entry.methods.length);
mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
for (int i = 0; i < entry.methods.length; i++) {
mv.visitInsn(DUP);
MethodDebugVisitor.pushInt(mv, i);
mv.visitLdcInsn(entry.methods[i]);
mv.visitInsn(AASTORE);
}
// method
mv.visitInsn(ACONST_NULL);
// rpconly
mv.visitInsn(entry.rpconly ? ICONST_1 : ICONST_0);
// auth
mv.visitInsn(entry.auth ? ICONST_1 : ICONST_0);
// cacheseconds
MethodDebugVisitor.pushInt(mv, entry.cacheseconds);
mv.visitTypeInsn(NEW, newDynName + "$" + entry.newActionClassName);
mv.visitInsn(DUP);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, newDynName + "$" + entry.newActionClassName, "<init>", "(L" + newDynName + ";)V", false);
mv.visitMethodInsn(INVOKESPECIAL, actionEntryName, "<init>", "(IILjava/lang/String;[Ljava/lang/String;Ljava/lang/reflect/Method;ZZILorg/redkale/net/http/HttpServlet;)V", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitInsn(POP);
}
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
fv = cw.visitField(ACC_PRIVATE, en.getKey(), "Ljava/lang/reflect/Type;", null, null);
av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
av0.visit("value", en.getValue().toString());
av0.visitEnd();
fv.visitEnd();
}
for (Map.Entry<java.lang.reflect.Type, String> en : typeRefs.entrySet()) {
fv = cw.visitField(ACC_PRIVATE, en.getValue(), "Ljava/lang/reflect/Type;", null, null);
av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
av0.visit("value", en.getKey().toString());
av0.visitEnd();
fv.visitEnd();
}
for (Map.Entry<String, org.redkale.util.Attribute> en : restAttributes.entrySet()) {
fv = cw.visitField(ACC_PRIVATE, en.getKey(), attrDesc, null, null);
av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
av0.visit("value", en.getValue().toString());
av0.visitEnd();
fv.visitEnd();
}
for (int i = 1; i <= restConverts.size(); i++) {
fv = cw.visitField(ACC_PRIVATE, REST_CONVERT_FIELD_PREFIX + i, convertDesc, null, null);
fv.visitEnd();
}
{
// _paramtypes字段 java.lang.reflect.Type[][]
fv = cw.visitField(ACC_PRIVATE, REST_PARAMTYPES_FIELD_NAME, "[[Ljava/lang/reflect/Type;", null, null);
av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
StringBuilder sb = new StringBuilder().append('[');
for (java.lang.reflect.Type[] rs : paramTypes) {
sb.append(Arrays.toString(rs)).append(',');
}
av0.visit("value", sb.append(']').toString());
av0.visitEnd();
fv.visitEnd();
}
{
// _returntypes字段 java.lang.reflect.Type[]
fv = cw.visitField(ACC_PRIVATE, REST_RETURNTYPES_FIELD_NAME, "[Ljava/lang/reflect/Type;", null, null);
av0 = fv.visitAnnotation(Type.getDescriptor(Comment.class), true);
av0.visit("value", retvalTypes.toString());
av0.visitEnd();
fv.visitEnd();
}
// classMap.put("mappings", mappingMaps); //不显示太多信息
{
// toString函数
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null));
// mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, REST_TOSTRINGOBJ_FIELD_NAME, "Ljava/util/function/Supplier;");
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/function/Supplier", "get", "()Ljava/lang/Object;", true);
mv.visitTypeInsn(CHECKCAST, "java/lang/String");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
// RestDyn
av0 = cw.visitAnnotation(Type.getDescriptor(RestDyn.class), true);
av0.visit("simple", (Boolean) dynsimple);
av0.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
newLoader.addClass(newDynName.replace('/', '.'), bytes);
try {
Class<?> newClazz = newLoader.findClass(newDynName.replace('/', '.'));
innerClassBytesMap.forEach((n, bs) -> {
try {
RedkaleClassLoader.putDynClass(n, bs, newLoader.findClass(n));
RedkaleClassLoader.putReflectionClass(n);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
});
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
for (java.lang.reflect.Type t : retvalTypes) {
JsonFactory.root().loadEncoder(t);
}
T obj = ((Class<T>) newClazz).getDeclaredConstructor().newInstance();
{
Field serviceField = newClazz.getDeclaredField(REST_SERVICE_FIELD_NAME);
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), serviceField);
Field servicemapField = newClazz.getDeclaredField(REST_SERVICEMAP_FIELD_NAME);
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), servicemapField);
}
for (Map.Entry<java.lang.reflect.Type, String> en : typeRefs.entrySet()) {
Field refField = newClazz.getDeclaredField(en.getValue());
refField.setAccessible(true);
refField.set(obj, en.getKey());
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), refField);
}
for (Map.Entry<String, org.redkale.util.Attribute> en : restAttributes.entrySet()) {
Field attrField = newClazz.getDeclaredField(en.getKey());
attrField.setAccessible(true);
attrField.set(obj, en.getValue());
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), attrField);
}
for (Map.Entry<String, java.lang.reflect.Type> en : bodyTypes.entrySet()) {
Field genField = newClazz.getDeclaredField(en.getKey());
genField.setAccessible(true);
genField.set(obj, en.getValue());
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), genField);
}
for (int i = 0; i < restConverts.size(); i++) {
Field genField = newClazz.getDeclaredField(REST_CONVERT_FIELD_PREFIX + (i + 1));
genField.setAccessible(true);
Object[] rc = restConverts.get(i);
genField.set(obj, createJsonConvert((RestConvert[]) rc[0], (RestConvertCoder[]) rc[1]));
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), genField);
}
Field typesfield = newClazz.getDeclaredField(REST_PARAMTYPES_FIELD_NAME);
typesfield.setAccessible(true);
java.lang.reflect.Type[][] paramtypeArray = new java.lang.reflect.Type[paramTypes.size()][];
paramtypeArray = paramTypes.toArray(paramtypeArray);
typesfield.set(obj, paramtypeArray);
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), typesfield);
Field retfield = newClazz.getDeclaredField(REST_RETURNTYPES_FIELD_NAME);
retfield.setAccessible(true);
java.lang.reflect.Type[] rettypeArray = new java.lang.reflect.Type[retvalTypes.size()];
rettypeArray = retvalTypes.toArray(rettypeArray);
retfield.set(obj, rettypeArray);
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), retfield);
Field tostringfield = newClazz.getDeclaredField(REST_TOSTRINGOBJ_FIELD_NAME);
tostringfield.setAccessible(true);
java.util.function.Supplier<String> sSupplier = () -> JsonConvert.root().convertTo(classMap);
tostringfield.set(obj, sSupplier);
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), tostringfield);
Method restactMethod = newClazz.getDeclaredMethod("_createRestActionEntry");
restactMethod.setAccessible(true);
RedkaleClassLoader.putReflectionMethod(newDynName.replace('/', '.'), restactMethod);
Field tmpentrysfield = HttpServlet.class.getDeclaredField("_actionmap");
tmpentrysfield.setAccessible(true);
HashMap<String, HttpServlet.ActionEntry> innerEntryMap = (HashMap) restactMethod.invoke(obj);
for (Map.Entry<String, HttpServlet.ActionEntry> en : innerEntryMap.entrySet()) {
Method m = mappingurlToMethod.get(en.getKey());
if (m != null)
en.getValue().annotations = HttpServlet.ActionEntry.annotations(m);
}
tmpentrysfield.set(obj, innerEntryMap);
RedkaleClassLoader.putReflectionField(HttpServlet.class.getName(), tmpentrysfield);
return obj;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
Aggregations