This commit is contained in:
redkale
2024-10-10 20:10:08 +08:00
parent dc3396daf5
commit ed2d9527bf
20 changed files with 991 additions and 1055 deletions

View File

@@ -9,7 +9,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.redkale.annotation.Param;
import org.redkale.convert.json.JsonConvert;
/**
* 存放方法的字节信息
@@ -151,6 +150,7 @@ public class AsmMethodBean {
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
return "{params:" + params + ", access:" + access + ", name:" + name + ", desc:" + desc + ", signature:"
+ signature + ", exceptions:" + exceptions + '}';
}
}

View File

@@ -3,7 +3,6 @@
*/
package org.redkale.asm;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.TypeToken;
/**
@@ -67,6 +66,6 @@ public class AsmMethodParam {
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
return "{name:" + name + ", description:" + description + ", signature:" + signature + '}';
}
}

View File

@@ -22,7 +22,6 @@ import org.redkale.inject.Resourcable;
import org.redkale.inject.ResourceFactory;
import org.redkale.mq.spi.MessageAgent;
import org.redkale.net.http.WebSocketNode;
import org.redkale.net.sncp.SncpRemoteInfo.SncpRemoteAction;
import org.redkale.scheduled.Scheduled;
import org.redkale.service.*;
import org.redkale.util.AnyValue;

View File

@@ -0,0 +1,645 @@
/*
* Copyright (c) 2016-2116 Redkale
* All rights reserved.
*/
package org.redkale.net.sncp;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.nio.channels.CompletionHandler;
import java.util.Objects;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future;
import org.redkale.annotation.ClassDepends;
import org.redkale.annotation.NonBlocking;
import org.redkale.asm.ClassWriter;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import org.redkale.asm.Label;
import org.redkale.asm.MethodDebugVisitor;
import static org.redkale.asm.Opcodes.*;
import org.redkale.asm.Type;
import org.redkale.convert.Convert;
import org.redkale.convert.Reader;
import org.redkale.convert.pb.ProtobufFactory;
import org.redkale.service.Service;
import org.redkale.util.RedkaleClassLoader;
import org.redkale.util.TypeToken;
import org.redkale.util.Uint128;
/**
* 每个Service方法的SncpServlet对象
*
* <p>详情见: https://redkale.org
*
* @author zhangjx
* @since 2.8.0
*/
public abstract class SncpActionServlet extends SncpServlet {
protected final Method method;
protected final Uint128 actionid;
protected final boolean nonBlocking;
@ClassDepends
protected final java.lang.reflect.Type[] paramTypes; // 第一个元素存放返回类型return type void的返回参数类型为null, 数组长度为:1+参数个数
@ClassDepends
protected final java.lang.reflect.Type paramComposeBeanType;
protected final int paramHandlerIndex; // >=0表示存在CompletionHandler参数
protected final Class<? extends CompletionHandler> paramHandlerClass; // CompletionHandler参数的类型
protected final java.lang.reflect.Type paramHandlerResultType; // CompletionHandler.completed第一个参数的类型
@ClassDepends
protected final java.lang.reflect.Type returnObjectType; // 返回结果类型 void必须设为null
@ClassDepends
protected final java.lang.reflect.Type returnFutureResultType; // 返回结果的CompletableFuture的结果泛型类型
@ClassDepends
protected SncpActionServlet(
String resourceName,
Class resourceType,
Service service,
Uint128 serviceid,
Uint128 actionid,
final Method method) {
super(resourceName, resourceType, service, serviceid);
Objects.requireNonNull(method);
this.actionid = actionid;
this.method = method;
this.paramComposeBeanType = SncpRemoteAction.createParamComposeBeanType(
Sncp.getServiceType(service),
method,
actionid,
method.getGenericParameterTypes(),
method.getParameterTypes());
int handlerFuncIndex = -1;
Class handlerFuncClass = null;
java.lang.reflect.Type handlerResultType = null;
try {
final Class[] paramClasses = method.getParameterTypes();
java.lang.reflect.Type[] genericParams = method.getGenericParameterTypes();
for (int i = 0; i < paramClasses.length; i++) { // 反序列化方法的每个参数
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
handlerFuncIndex = i;
handlerFuncClass = paramClasses[i];
java.lang.reflect.Type handlerType = TypeToken.getGenericType(genericParams[i], service.getClass());
if (handlerType instanceof Class) {
handlerResultType = Object.class;
} else if (handlerType instanceof ParameterizedType) {
handlerResultType = TypeToken.getGenericType(
((ParameterizedType) handlerType).getActualTypeArguments()[0], handlerType);
} else {
throw new SncpException(service.getClass() + " had unknown genericType in " + method);
}
if (method.getReturnType() != void.class) {
throw new SncpException(
method + " have CompletionHandler type parameter but return type is not void");
}
break;
}
}
} catch (Throwable ex) {
// do nothing
}
java.lang.reflect.Type[] originalParamTypes =
TypeToken.getGenericType(method.getGenericParameterTypes(), service.getClass());
java.lang.reflect.Type originalReturnType =
TypeToken.getGenericType(method.getGenericReturnType(), service.getClass());
java.lang.reflect.Type[] types = new java.lang.reflect.Type[originalParamTypes.length + 1];
types[0] = originalReturnType;
System.arraycopy(originalParamTypes, 0, types, 1, originalParamTypes.length);
this.paramTypes = types;
this.paramHandlerIndex = handlerFuncIndex;
this.paramHandlerClass = handlerFuncClass;
this.paramHandlerResultType = handlerResultType;
this.returnObjectType =
originalReturnType == void.class || originalReturnType == Void.class ? null : originalReturnType;
if (Future.class.isAssignableFrom(method.getReturnType())) {
java.lang.reflect.Type futureType =
TypeToken.getGenericType(method.getGenericReturnType(), service.getClass());
java.lang.reflect.Type returnType = null;
if (futureType instanceof Class) {
returnType = Object.class;
} else if (futureType instanceof ParameterizedType) {
returnType = TypeToken.getGenericType(
((ParameterizedType) futureType).getActualTypeArguments()[0], futureType);
} else {
throw new SncpException(service.getClass() + " had unknown return genericType in " + method);
}
this.returnFutureResultType = returnType;
} else {
this.returnFutureResultType = null;
}
NonBlocking non = method.getAnnotation(NonBlocking.class);
if (non == null) {
non = service.getClass().getAnnotation(NonBlocking.class);
}
// Future代替CompletionStage 不容易判断异步
this.nonBlocking = non == null
&& (CompletionStage.class.isAssignableFrom(method.getReturnType()) || this.paramHandlerIndex >= 0);
}
@Override
public final void execute(SncpRequest request, SncpResponse response) throws IOException {
if (paramHandlerIndex > 0) {
response.paramAsyncHandler(paramHandlerClass, paramHandlerResultType);
}
try {
action(request, response);
} catch (IOException e) {
throw e;
} catch (Throwable t) {
throw new IOException(t);
}
}
protected abstract void action(SncpRequest request, SncpResponse response) throws Throwable;
public <T extends Service> T service() {
return (T) service;
}
@Override
public Uint128 getServiceid() {
return serviceid;
}
public Uint128 getActionid() {
return actionid;
}
public String actionName() {
return method.getDeclaringClass().getSimpleName() + "." + method.getName();
}
/**
*
*
* <blockquote>
*
* <pre>
* public interface TestService extends Service {
*
* public boolean change(TestBean bean, String name, int id);
*
* public void insert(BooleanHandler handler, TestBean bean, String name, int id);
*
* public void update(long show, short v2, CompletionHandler&#60;Boolean, TestBean&#62; handler, TestBean bean, String name, int id);
*
* public CompletableFuture&#60;String&#62; changeName(TestBean bean, String name, int id);
*
* }
*
* &#064;ResourceType(TestService.class)
* public class TestServiceImpl implements TestService {
*
* &#064;Override
* public boolean change(TestBean bean, String name, int id) {
* return false;
* }
*
* &#064;Override
* public void insert(BooleanHandler handler, TestBean bean, String name, int id) {
* }
*
* &#064;Override
* public void update(long show, short v2, CompletionHandler&#60;Boolean, TestBean&#62; handler, TestBean bean, String name, int id) {
* }
*
* &#064;Override
* public CompletableFuture&#60;String&#62; changeName(TestBean bean, String name, int id) {
* return null;
* }
* }
*
* public class BooleanHandler implements CompletionHandler&#60;Boolean, TestBean&#62; {
*
* &#064;Override
* public void completed(Boolean result, TestBean attachment) {
* }
*
* &#064;Override
* public void failed(Throwable exc, TestBean attachment) {
* }
*
* }
*
* public class DynActionTestService_change extends SncpActionServlet {
*
* public DynActionTestService_change(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
* String arg2 = convert.convertFrom(paramTypes[2], in);
* int arg3 = convert.convertFrom(paramTypes[3], in);
* TestService serviceObj = (TestService) service();
* Object rs = serviceObj.change(arg1, arg2, arg3);
* response.finish(boolean.class, rs);
* }
* }
*
* public class DynActionTestService_insert extends SncpActionServlet {
*
* public DynActionTestService_insert(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* BooleanHandler arg0 = response.getParamAsyncHandler();
* convert.convertFrom(CompletionHandler.class, in);
* TestBean arg1 = convert.convertFrom(paramTypes[2], in);
* String arg2 = convert.convertFrom(paramTypes[3], in);
* int arg3 = convert.convertFrom(paramTypes[4], in);
* TestService serviceObj = (TestService) service();
* serviceObj.insert(arg0, arg1, arg2, arg3);
* response.finishVoid();
* }
* }
*
* public class DynActionTestService_update extends SncpActionServlet {
*
* public DynActionTestService_update(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* long a1 = convert.convertFrom(paramTypes[1], in);
* short a2 = convert.convertFrom(paramTypes[2], in);
* CompletionHandler a3 = response.getParamAsyncHandler();
* convert.convertFrom(CompletionHandler.class, in);
* TestBean arg1 = convert.convertFrom(paramTypes[4], in);
* String arg2 = convert.convertFrom(paramTypes[5], in);
* int arg3 = convert.convertFrom(paramTypes[6], in);
* TestService serviceObj = (TestService) service();
* serviceObj.update(a1, a2, a3, arg1, arg2, arg3);
* response.finishVoid();
* }
* }
*
* public class DynActionTestService_changeName extends SncpActionServlet {
*
* public DynActionTestService_changeName(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
* String arg2 = convert.convertFrom(paramTypes[2], in);
* int arg3 = convert.convertFrom(paramTypes[3], in);
* TestService serviceObj = (TestService) service();
* CompletableFuture future = serviceObj.changeName(arg1, arg2, arg3);
* response.finishFuture(paramHandlerResultType, future);
* }
* }
*
* </pre>
*
* </blockquote>
*
* @param resourceName 资源名
* @param resourceType 资源类
* @param serviceImplClass Service实现类
* @param service Service
* @param serviceid 类ID
* @param actionid 操作ID
* @param method 方法
* @return SncpActionServlet
*/
@SuppressWarnings("unchecked")
public static SncpActionServlet create(
final String resourceName,
final Class resourceType,
final Class serviceImplClass,
final Service service,
final Uint128 serviceid,
final Uint128 actionid,
final Method method) {
final Class serviceClass = service.getClass();
final String supDynName = SncpActionServlet.class.getName().replace('.', '/');
final String serviceImpTypeName = serviceImplClass.getName().replace('.', '/');
final String convertName = Convert.class.getName().replace('.', '/');
final String uint128Desc = Type.getDescriptor(Uint128.class);
final String convertDesc = Type.getDescriptor(Convert.class);
final String readerDesc = Type.getDescriptor(Reader.class);
final String requestName = SncpRequest.class.getName().replace('.', '/');
final String responseName = SncpResponse.class.getName().replace('.', '/');
final String requestDesc = Type.getDescriptor(SncpRequest.class);
final String responseDesc = Type.getDescriptor(SncpResponse.class);
final String serviceDesc = Type.getDescriptor(Service.class);
final boolean boolReturnTypeFuture = Future.class.isAssignableFrom(method.getReturnType());
final String newDynName = "org/redkaledyn/sncp/servlet/action/_DynSncpActionServlet__"
+ resourceType.getSimpleName() + "_" + method.getName() + "_" + actionid;
Class<?> newClazz = null;
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
newClazz = clz == null
? Thread.currentThread().getContextClassLoader().loadClass(newDynName.replace('/', '.'))
: clz;
} catch (Throwable ex) {
// do nothing
}
final java.lang.reflect.Type[] originalParamTypes =
TypeToken.getGenericType(method.getGenericParameterTypes(), serviceClass);
final java.lang.reflect.Type originalReturnType =
TypeToken.getGenericType(method.getGenericReturnType(), serviceClass);
if (newClazz == null) {
// -------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
MethodDebugVisitor mv;
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
mv = new MethodDebugVisitor(cw.visitMethod(
ACC_PUBLIC,
"<init>",
"(Ljava/lang/String;Ljava/lang/Class;" + serviceDesc + uint128Desc + uint128Desc
+ "Ljava/lang/reflect/Method;)V",
null,
null));
Label label0 = new Label();
mv.visitLabel(label0);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 4);
mv.visitVarInsn(ALOAD, 5);
mv.visitVarInsn(ALOAD, 6);
mv.visitMethodInsn(
INVOKESPECIAL,
supDynName,
"<init>",
"(Ljava/lang/String;Ljava/lang/Class;" + serviceDesc + uint128Desc + uint128Desc
+ "Ljava/lang/reflect/Method;)V",
false);
mv.visitInsn(RETURN);
Label label2 = new Label();
mv.visitLabel(label2);
mv.visitLocalVariable("this", "L" + newDynName + ";", null, label0, label2, 0);
mv.visitLocalVariable("resourceName", "Ljava/lang/String;", null, label0, label2, 1);
mv.visitLocalVariable("resourceType", "Ljava/lang/Class;", null, label0, label2, 2);
mv.visitLocalVariable("service", serviceDesc, null, label0, label2, 3);
mv.visitLocalVariable("serviceid", uint128Desc, null, label0, label2, 4);
mv.visitLocalVariable("actionid", uint128Desc, null, label0, label2, 5);
mv.visitLocalVariable("method", "Ljava/lang/reflect/Method;", null, label0, label2, 6);
mv.visitMaxs(7, 7);
mv.visitEnd();
}
String convertFromDesc = "(Ljava/lang/reflect/Type;" + readerDesc + ")Ljava/lang/Object;";
try {
convertFromDesc = Type.getMethodDescriptor(
Convert.class.getMethod("convertFrom", java.lang.reflect.Type.class, Reader.class));
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
{ // action方法
mv = new MethodDebugVisitor(cw.visitMethod(
ACC_PUBLIC, "action", "(" + requestDesc + responseDesc + ")V", null, new String[] {
"java/lang/Throwable"
}));
// mv.setDebug(true);
{ // Convert
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, requestName, "getConvert", "()" + convertDesc, false);
mv.visitVarInsn(ASTORE, 3);
}
{ // Reader
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, requestName, "getReader", "()" + readerDesc, false);
mv.visitVarInsn(ASTORE, 4);
}
int iconst = ICONST_1;
int intconst = 1;
int store = 5; // action的参数个数+2
final Class[] paramClasses = method.getParameterTypes();
int[][] codes = new int[paramClasses.length][2];
int handlerFuncIndex = -1;
for (int i = 0; i < paramClasses.length; i++) { // 反序列化方法的每个参数
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
if (boolReturnTypeFuture) {
throw new SncpException(method + " have both CompletionHandler and CompletableFuture");
}
if (handlerFuncIndex >= 0) {
throw new SncpException(method + " have more than one CompletionHandler type parameter");
}
Sncp.checkAsyncModifier(paramClasses[i], method);
handlerFuncIndex = i;
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(
INVOKEVIRTUAL,
responseName,
"getParamAsyncHandler",
"()Ljava/nio/channels/CompletionHandler;",
false);
mv.visitTypeInsn(CHECKCAST, paramClasses[i].getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, store);
codes[i] = new int[] {ALOAD, store};
store++;
iconst++;
intconst++;
mv.visitVarInsn(ALOAD, 3);
mv.visitLdcInsn(Type.getType(Type.getDescriptor(CompletionHandler.class)));
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
mv.visitInsn(POP);
continue;
}
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;");
if (intconst < 6) {
mv.visitInsn(ICONST_0 + intconst);
} else if (iconst <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, intconst);
} else if (iconst <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, intconst);
} else {
mv.visitLdcInsn(intconst);
}
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
int load = ALOAD;
int v = 0;
if (paramClasses[i].isPrimitive()) {
int storecode = ISTORE;
load = ILOAD;
if (paramClasses[i] == long.class) {
storecode = LSTORE;
load = LLOAD;
v = 1;
} else if (paramClasses[i] == float.class) {
storecode = FSTORE;
load = FLOAD;
v = 1;
} else if (paramClasses[i] == double.class) {
storecode = DSTORE;
load = DLOAD;
v = 1;
}
Class bigPrimitiveClass = TypeToken.primitiveToWrapper(paramClasses[i]);
String bigPrimitiveName = bigPrimitiveClass.getName().replace('.', '/');
try {
Method pm = bigPrimitiveClass.getMethod(paramClasses[i].getSimpleName() + "Value");
mv.visitTypeInsn(CHECKCAST, bigPrimitiveName);
mv.visitMethodInsn(
INVOKEVIRTUAL, bigPrimitiveName, pm.getName(), Type.getMethodDescriptor(pm), false);
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
mv.visitVarInsn(storecode, store);
} else {
mv.visitTypeInsn(CHECKCAST, paramClasses[i].getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, store); //
}
codes[i] = new int[] {load, store};
store += v;
iconst++;
intconst++;
store++;
}
{ // 调用service
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "service", "()" + serviceDesc, false);
mv.visitTypeInsn(CHECKCAST, serviceImpTypeName);
mv.visitVarInsn(ASTORE, store);
mv.visitVarInsn(ALOAD, store);
for (int[] j : codes) {
mv.visitVarInsn(j[0], j[1]);
}
mv.visitMethodInsn(
serviceImplClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL,
serviceImpTypeName,
method.getName(),
Type.getMethodDescriptor(method),
serviceImplClass.isInterface());
store++;
}
if (method.getReturnType() != void.class) {
final Class returnClass = method.getReturnType();
if (returnClass.isPrimitive()) {
Class bigClass = TypeToken.primitiveToWrapper(returnClass);
try {
Method vo = bigClass.getMethod("valueOf", returnClass);
mv.visitMethodInsn(
INVOKESTATIC,
bigClass.getName().replace('.', '/'),
vo.getName(),
Type.getMethodDescriptor(vo),
false);
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
}
mv.visitVarInsn(ASTORE, store); // 11
if (boolReturnTypeFuture) { // 返回类型为Future
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "returnFutureResultType", "Ljava/lang/reflect/Type;");
mv.visitVarInsn(ALOAD, store);
mv.visitMethodInsn(
INVOKEVIRTUAL,
responseName,
"finishFuture",
"(Ljava/lang/reflect/Type;Ljava/util/concurrent/Future;)V",
false);
} else if (handlerFuncIndex >= 0) { // 参数有CompletionHandler
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
} else { // 普通对象
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "returnObjectType", "Ljava/lang/reflect/Type;");
mv.visitVarInsn(ALOAD, store);
mv.visitMethodInsn(
INVOKEVIRTUAL,
responseName,
"finish",
"(Ljava/lang/reflect/Type;Ljava/lang/Object;)V",
false);
}
} else { // void返回类型
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
}
mv.visitInsn(RETURN);
mv.visitMaxs(8, store);
mv.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
newClazz = new ClassLoader(serviceClass.getClassLoader()) {
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.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
try {
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), newClazz.getField("service"));
} catch (Exception e) {
// do nothing
}
for (java.lang.reflect.Type t : originalParamTypes) {
if (t == java.io.Serializable.class
|| t == java.io.Serializable[].class
|| t.toString().startsWith("java.lang.")) {
continue;
}
ProtobufFactory.root().loadDecoder(t);
}
if (originalReturnType != void.class && originalReturnType != Void.class) {
if (boolReturnTypeFuture && method.getReturnType() != method.getGenericReturnType()) {
java.lang.reflect.Type t =
((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0];
if (t != Void.class && t != java.lang.reflect.Type.class) {
ProtobufFactory.root().loadEncoder(t);
}
} else {
try {
ProtobufFactory.root().loadEncoder(originalReturnType);
} catch (Exception e) {
System.err.println(method);
}
}
}
}
try {
return (SncpActionServlet) newClazz.getConstructors()[0].newInstance(
resourceName, resourceType, service, serviceid, actionid, method);
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
}
}

View File

@@ -0,0 +1,318 @@
/*
* Copyright (c) 2016-2116 Redkale
* All rights reserved.
*/
package org.redkale.net.sncp;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.SocketAddress;
import java.nio.channels.CompletionHandler;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import org.redkale.asm.AnnotationVisitor;
import org.redkale.asm.AsmMethodBean;
import org.redkale.asm.AsmMethodBoost;
import org.redkale.asm.AsmMethodParam;
import org.redkale.asm.Asms;
import org.redkale.asm.ClassWriter;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import org.redkale.asm.FieldVisitor;
import org.redkale.asm.MethodDebugVisitor;
import static org.redkale.asm.Opcodes.*;
import org.redkale.convert.ConvertColumn;
import org.redkale.convert.ObjectEncoder;
import org.redkale.convert.pb.ProtobufFactory;
import org.redkale.service.RpcAttachment;
import org.redkale.service.RpcSourceAddress;
import org.redkale.service.RpcTargetAddress;
import org.redkale.service.RpcTargetTopic;
import org.redkale.util.Creator;
import org.redkale.util.RedkaleClassLoader;
import org.redkale.util.TypeToken;
import org.redkale.util.Uint128;
/**
* 每个Service方法的相关信息对象
*
* <p>详情见: https://redkale.org
*
* @author zhangjx
* @since 2.8.0
*/
public final class SncpRemoteAction {
protected final Uint128 actionid;
protected final Method method;
protected final Type returnObjectType; // void必须设为null
protected final Type[] paramTypes;
protected final Class[] paramClasses;
// 参数数量为0: 值为null; 参数数量为1且参数类型为JavaBean: 值为第一个参数的类型; 其他情况: 动态生成的Object类
protected final Type paramComposeBeanType;
protected final int paramHandlerIndex;
protected final int paramHandlerAttachIndex;
protected final int paramAddressTargetIndex;
protected final int paramAddressSourceIndex;
protected final int paramTopicTargetIndex;
protected final Class<? extends CompletionHandler> paramHandlerClass; // CompletionHandler参数的类型
protected final java.lang.reflect.Type paramHandlerResultType; // CompletionHandler.completed第一个参数的类型
protected final java.lang.reflect.Type returnFutureResultType; // 返回结果的CompletableFuture的结果泛型类型
protected final Class<? extends Future> returnFutureClass; // 返回结果的CompletableFuture类型
protected final Creator<? extends CompletableFuture> returnFutureCreator; // 返回CompletableFuture类型的构建器
protected final SncpHeader header;
@SuppressWarnings("unchecked")
SncpRemoteAction(
final Class serviceImplClass,
Class resourceType,
Method method,
Uint128 serviceid,
Uint128 actionid,
final SncpClient sncpClient) {
this.actionid = actionid == null ? Sncp.actionid(method) : actionid;
Type rt = TypeToken.getGenericType(method.getGenericReturnType(), serviceImplClass);
this.returnObjectType = rt == void.class || rt == Void.class ? null : rt;
this.paramTypes = TypeToken.getGenericType(method.getGenericParameterTypes(), serviceImplClass);
this.paramClasses = method.getParameterTypes();
this.paramComposeBeanType =
createParamComposeBeanType(serviceImplClass, method, actionid, paramTypes, paramClasses);
this.method = method;
Annotation[][] anns = method.getParameterAnnotations();
int topicAddrIndex = -1;
int targetAddrIndex = -1;
int sourceAddrIndex = -1;
int handlerAttachIndex = -1;
int handlerFuncIndex = -1;
Class handlerFuncClass = null;
java.lang.reflect.Type handlerResultType = null;
Class<?>[] params = method.getParameterTypes();
Type[] genericParams = method.getGenericParameterTypes();
for (int i = 0; i < params.length; i++) {
if (CompletionHandler.class.isAssignableFrom(params[i])) {
if (Future.class.isAssignableFrom(method.getReturnType())) {
throw new SncpException(method + " have both CompletionHandler and CompletableFuture");
}
if (handlerFuncIndex >= 0) {
throw new SncpException(method + " have more than one CompletionHandler type parameter");
}
Sncp.checkAsyncModifier(params[i], method);
handlerFuncIndex = i;
handlerFuncClass = paramClasses[i];
java.lang.reflect.Type handlerType = TypeToken.getGenericType(genericParams[i], serviceImplClass);
if (handlerType instanceof Class) {
handlerResultType = Object.class;
} else if (handlerType instanceof ParameterizedType) {
handlerResultType = TypeToken.getGenericType(
((ParameterizedType) handlerType).getActualTypeArguments()[0], handlerType);
} else {
throw new SncpException(serviceImplClass + " had unknown genericType in " + method);
}
if (method.getReturnType() != void.class) {
throw new SncpException(
method + " have CompletionHandler type parameter but return type is not void");
}
break;
}
}
if (anns.length > 0) {
for (int i = 0; i < anns.length; i++) {
if (anns[i].length > 0) {
for (Annotation ann : anns[i]) {
if (ann.annotationType() == RpcAttachment.class) {
if (handlerAttachIndex >= 0) {
throw new SncpException(method + " have more than one @RpcAttachment parameter");
}
handlerAttachIndex = i;
} else if (ann.annotationType() == RpcTargetAddress.class) {
if (SocketAddress.class.isAssignableFrom(params[i])) {
if (sourceAddrIndex >= 0) {
throw new SncpException(method + " have more than one @RpcTargetAddress parameter");
} else {
targetAddrIndex = i;
}
} else {
throw new SncpException(
method + " must be SocketAddress Type on @RpcTargetAddress parameter");
}
} else if (ann.annotationType() == RpcSourceAddress.class) {
if (SocketAddress.class.isAssignableFrom(params[i])) {
if (sourceAddrIndex >= 0) {
throw new SncpException(method + " have more than one @RpcSourceAddress parameter");
} else {
sourceAddrIndex = i;
}
} else {
throw new SncpException(
method + " must be SocketAddress Type on @RpcSourceAddress parameter");
}
} else if (ann.annotationType() == RpcTargetTopic.class) {
if (String.class.isAssignableFrom(params[i])) {
if (sourceAddrIndex >= 0) {
throw new SncpException(method + " have more than one @RpcTargetTopic parameter");
} else {
topicAddrIndex = i;
}
} else {
throw new SncpException(method + " must be String Type on @RpcTargetTopic parameter");
}
}
}
}
}
}
this.paramTopicTargetIndex = topicAddrIndex;
this.paramAddressTargetIndex = targetAddrIndex;
this.paramAddressSourceIndex = sourceAddrIndex;
this.paramHandlerIndex = handlerFuncIndex;
this.paramHandlerClass = handlerFuncClass;
this.paramHandlerResultType = handlerResultType;
this.paramHandlerAttachIndex = handlerAttachIndex;
this.header = SncpHeader.create(
sncpClient == null ? null : sncpClient.getClientSncpAddress(),
serviceid,
resourceType.getName(),
actionid,
method.getName());
if (this.paramHandlerIndex >= 0 && method.getReturnType() != void.class) {
throw new SncpException(method + " have CompletionHandler type parameter but return type is not void");
}
if (Future.class.isAssignableFrom(method.getReturnType())) {
java.lang.reflect.Type futureType =
TypeToken.getGenericType(method.getGenericReturnType(), serviceImplClass);
java.lang.reflect.Type returnType = null;
if (futureType instanceof Class) {
returnType = Object.class;
} else if (futureType instanceof ParameterizedType) {
returnType = TypeToken.getGenericType(
((ParameterizedType) futureType).getActualTypeArguments()[0], futureType);
} else {
throw new SncpException(serviceImplClass + " had unknown return genericType in " + method);
}
this.returnFutureResultType = returnType;
this.returnFutureClass = method.getReturnType().isAssignableFrom(CompletableFuture.class)
? CompletableFuture.class
: (Class) method.getReturnType();
if (method.getReturnType().isAssignableFrom(CompletableFuture.class)
|| CompletableFuture.class.isAssignableFrom(method.getReturnType())) {
this.returnFutureCreator = (Creator) Creator.create(this.returnFutureClass);
} else {
throw new SncpException(serviceImplClass + " return must be CompletableFuture or subclass");
}
} else {
this.returnFutureResultType = null;
this.returnFutureClass = null;
this.returnFutureCreator = null;
}
}
public String actionName() {
return method.getDeclaringClass().getSimpleName() + "." + method.getName();
}
@Override
public String toString() {
return "{" + actionid + "," + (method == null ? "null" : method.getName()) + "}";
}
public static Type createParamComposeBeanType(
Class resourceType, Method method, Uint128 actionid, Type[] paramTypes, Class[] paramClasses) {
if (paramTypes == null || paramTypes.length == 0) {
return null;
}
if (paramTypes.length == 1 && ProtobufFactory.root().createEncoder(paramTypes[0]) instanceof ObjectEncoder) {
return paramTypes[0];
}
// 动态生成组合JavaBean类
final Class serviceClass = resourceType.getClass();
final String columnDesc = org.redkale.asm.Type.getDescriptor(ConvertColumn.class);
final String newDynName = "org/redkaledyn/sncp/servlet/action/_DynSncpActionParamBean__"
+ resourceType.getSimpleName() + "_" + method.getName() + "_" + actionid;
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
Class<?> newClazz = clz == null
? Thread.currentThread().getContextClassLoader().loadClass(newDynName.replace('/', '.'))
: clz;
return newClazz;
} catch (Throwable ex) {
// do nothing
}
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(resourceType);
AsmMethodBean methodBean = Objects.requireNonNull(methodBeans.get(AsmMethodBoost.getMethodBeanKey(method)));
// -------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodDebugVisitor mv;
AnnotationVisitor av;
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, "java/lang/Object", null);
final List<AsmMethodParam> asmParams = methodBean.getParams();
for (int i = 1; i <= paramClasses.length; i++) {
AsmMethodParam param = asmParams.get(i - 1);
String paramDesc = org.redkale.asm.Type.getDescriptor(paramClasses[i - 1]);
fv = cw.visitField(ACC_PUBLIC, "arg" + i, paramDesc, param.getSignature(), null);
av = fv.visitAnnotation(columnDesc, true);
av.visit("index", i);
av.visitEnd();
fv.visitEnd();
}
{ // 空参数构造函数
mv = new MethodDebugVisitor(cw.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();
}
{ // 带参数构造函数
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, "<init>", "([Ljava/lang/Object;)V", null, null));
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
for (int i = 1; i <= paramClasses.length; i++) {
String paramDesc = org.redkale.asm.Type.getDescriptor(paramClasses[i - 1]);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
Asms.visitInsn(mv, i - 1);
mv.visitInsn(AALOAD);
Asms.visitCheckCast(mv, paramClasses[i - 1]);
mv.visitFieldInsn(PUTFIELD, newDynName, "arg" + i, paramDesc);
}
mv.visitInsn(RETURN);
mv.visitMaxs(3, 2);
mv.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Class newClazz = new ClassLoader(serviceClass.getClassLoader()) {
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.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
return newClazz;
}
}

View File

@@ -3,7 +3,6 @@
*/
package org.redkale.net.sncp;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.net.*;
import java.nio.ByteBuffer;
@@ -348,194 +347,4 @@ public class SncpRemoteInfo<S extends Service> {
public Set<InetSocketAddress> getRemoteAddresses() {
return remoteAddresses;
}
public static final class SncpRemoteAction {
protected final Uint128 actionid;
protected final Method method;
protected final Type returnObjectType; // void必须设为null
protected final Type[] paramTypes;
protected final Class[] paramClasses;
protected final int paramHandlerIndex;
protected final int paramHandlerAttachIndex;
protected final int paramAddressTargetIndex;
protected final int paramAddressSourceIndex;
protected final int paramTopicTargetIndex;
protected final Class<? extends CompletionHandler> paramHandlerClass; // CompletionHandler参数的类型
protected final java.lang.reflect.Type paramHandlerResultType; // CompletionHandler.completed第一个参数的类型
protected final java.lang.reflect.Type returnFutureResultType; // 返回结果的CompletableFuture的结果泛型类型
protected final Class<? extends Future> returnFutureClass; // 返回结果的CompletableFuture类型
protected final Creator<? extends CompletableFuture> returnFutureCreator; // 返回CompletableFuture类型的构建器
protected final SncpHeader header;
@SuppressWarnings("unchecked")
SncpRemoteAction(
final Class serviceImplClass,
Class resourceType,
Method method,
Uint128 serviceid,
Uint128 actionid,
final SncpClient sncpClient) {
this.actionid = actionid == null ? Sncp.actionid(method) : actionid;
Type rt = TypeToken.getGenericType(method.getGenericReturnType(), serviceImplClass);
this.returnObjectType = rt == void.class || rt == Void.class ? null : rt;
this.paramTypes = TypeToken.getGenericType(method.getGenericParameterTypes(), serviceImplClass);
this.paramClasses = method.getParameterTypes();
this.method = method;
Annotation[][] anns = method.getParameterAnnotations();
int topicAddrIndex = -1;
int targetAddrIndex = -1;
int sourceAddrIndex = -1;
int handlerAttachIndex = -1;
int handlerFuncIndex = -1;
Class handlerFuncClass = null;
java.lang.reflect.Type handlerResultType = null;
Class<?>[] params = method.getParameterTypes();
Type[] genericParams = method.getGenericParameterTypes();
for (int i = 0; i < params.length; i++) {
if (CompletionHandler.class.isAssignableFrom(params[i])) {
if (Future.class.isAssignableFrom(method.getReturnType())) {
throw new SncpException(method + " have both CompletionHandler and CompletableFuture");
}
if (handlerFuncIndex >= 0) {
throw new SncpException(method + " have more than one CompletionHandler type parameter");
}
Sncp.checkAsyncModifier(params[i], method);
handlerFuncIndex = i;
handlerFuncClass = paramClasses[i];
java.lang.reflect.Type handlerType = TypeToken.getGenericType(genericParams[i], serviceImplClass);
if (handlerType instanceof Class) {
handlerResultType = Object.class;
} else if (handlerType instanceof ParameterizedType) {
handlerResultType = TypeToken.getGenericType(
((ParameterizedType) handlerType).getActualTypeArguments()[0], handlerType);
} else {
throw new SncpException(serviceImplClass + " had unknown genericType in " + method);
}
if (method.getReturnType() != void.class) {
throw new SncpException(
method + " have CompletionHandler type parameter but return type is not void");
}
break;
}
}
if (anns.length > 0) {
for (int i = 0; i < anns.length; i++) {
if (anns[i].length > 0) {
for (Annotation ann : anns[i]) {
if (ann.annotationType() == RpcAttachment.class) {
if (handlerAttachIndex >= 0) {
throw new SncpException(method + " have more than one @RpcAttachment parameter");
}
handlerAttachIndex = i;
} else if (ann.annotationType() == RpcTargetAddress.class) {
if (SocketAddress.class.isAssignableFrom(params[i])) {
if (sourceAddrIndex >= 0) {
throw new SncpException(
method + " have more than one @RpcTargetAddress parameter");
} else {
targetAddrIndex = i;
}
} else {
throw new SncpException(
method + " must be SocketAddress Type on @RpcTargetAddress parameter");
}
} else if (ann.annotationType() == RpcSourceAddress.class) {
if (SocketAddress.class.isAssignableFrom(params[i])) {
if (sourceAddrIndex >= 0) {
throw new SncpException(
method + " have more than one @RpcSourceAddress parameter");
} else {
sourceAddrIndex = i;
}
} else {
throw new SncpException(
method + " must be SocketAddress Type on @RpcSourceAddress parameter");
}
} else if (ann.annotationType() == RpcTargetTopic.class) {
if (String.class.isAssignableFrom(params[i])) {
if (sourceAddrIndex >= 0) {
throw new SncpException(
method + " have more than one @RpcTargetTopic parameter");
} else {
topicAddrIndex = i;
}
} else {
throw new SncpException(
method + " must be String Type on @RpcTargetTopic parameter");
}
}
}
}
}
}
this.paramTopicTargetIndex = topicAddrIndex;
this.paramAddressTargetIndex = targetAddrIndex;
this.paramAddressSourceIndex = sourceAddrIndex;
this.paramHandlerIndex = handlerFuncIndex;
this.paramHandlerClass = handlerFuncClass;
this.paramHandlerResultType = handlerResultType;
this.paramHandlerAttachIndex = handlerAttachIndex;
this.header = SncpHeader.create(
sncpClient == null ? null : sncpClient.getClientSncpAddress(),
serviceid,
resourceType.getName(),
actionid,
method.getName());
if (this.paramHandlerIndex >= 0 && method.getReturnType() != void.class) {
throw new SncpException(method + " have CompletionHandler type parameter but return type is not void");
}
if (Future.class.isAssignableFrom(method.getReturnType())) {
java.lang.reflect.Type futureType =
TypeToken.getGenericType(method.getGenericReturnType(), serviceImplClass);
java.lang.reflect.Type returnType = null;
if (futureType instanceof Class) {
returnType = Object.class;
} else if (futureType instanceof ParameterizedType) {
returnType = TypeToken.getGenericType(
((ParameterizedType) futureType).getActualTypeArguments()[0], futureType);
} else {
throw new SncpException(serviceImplClass + " had unknown return genericType in " + method);
}
this.returnFutureResultType = returnType;
this.returnFutureClass = method.getReturnType().isAssignableFrom(CompletableFuture.class)
? CompletableFuture.class
: (Class) method.getReturnType();
if (method.getReturnType().isAssignableFrom(CompletableFuture.class)
|| CompletableFuture.class.isAssignableFrom(method.getReturnType())) {
this.returnFutureCreator = (Creator) Creator.create(this.returnFutureClass);
} else {
throw new SncpException(serviceImplClass + " return must be CompletableFuture or subclass");
}
} else {
this.returnFutureResultType = null;
this.returnFutureClass = null;
this.returnFutureCreator = null;
}
}
public String actionName() {
return method.getDeclaringClass().getSimpleName() + "." + method.getName();
}
@Override
public String toString() {
return "{" + actionid + "," + (method == null ? "null" : method.getName()) + "}";
}
}
}

View File

@@ -139,6 +139,7 @@ public class SncpResponse extends Response<SncpContext, SncpRequest> {
finish(RETCODE_THROWEXCEPTION, null);
}
@ClassDepends
public final void finishVoid() {
int headerSize = SncpHeader.calcHeaderSize(request);
ProtobufWriter out = getWriter();
@@ -146,6 +147,7 @@ public class SncpResponse extends Response<SncpContext, SncpRequest> {
finish(0, out);
}
@ClassDepends
public final void finishFuture(final Type futureResultType, final Future future) {
if (future == null) {
finishVoid();

View File

@@ -7,17 +7,9 @@ package org.redkale.net.sncp;
import java.io.IOException;
import java.lang.reflect.*;
import java.nio.channels.CompletionHandler;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.Level;
import org.redkale.annotation.NonBlocking;
import org.redkale.asm.*;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import static org.redkale.asm.Opcodes.*;
import org.redkale.asm.Type;
import org.redkale.convert.*;
import org.redkale.convert.pb.ProtobufFactory;
import org.redkale.net.*;
import org.redkale.service.Service;
import org.redkale.util.*;
@@ -39,7 +31,7 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
private final HashMap<Uint128, SncpActionServlet> actions = new HashMap<>();
private SncpServlet(String resourceName, Class resourceType, Service service, Uint128 serviceid) {
protected SncpServlet(String resourceName, Class resourceType, Service service, Uint128 serviceid) {
Objects.requireNonNull(resourceName);
Objects.requireNonNull(resourceType);
Objects.requireNonNull(service);
@@ -194,601 +186,4 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
public final int hashCode() {
return Objects.hashCode(getServiceid());
}
public abstract static class SncpActionServlet extends SncpServlet {
protected final Method method;
protected final Uint128 actionid;
protected final boolean nonBlocking;
protected final java.lang.reflect.Type[] paramTypes; // 第一个元素存放返回类型return type void的返回参数类型为null, 数组长度为:1+参数个数
protected final java.lang.reflect.Type returnObjectType; // 返回结果类型 void必须设为null
protected final int paramHandlerIndex; // >=0表示存在CompletionHandler参数
protected final Class<? extends CompletionHandler> paramHandlerClass; // CompletionHandler参数的类型
protected final java.lang.reflect.Type paramHandlerResultType; // CompletionHandler.completed第一个参数的类型
protected final java.lang.reflect.Type returnFutureResultType; // 返回结果的CompletableFuture的结果泛型类型
protected final java.lang.reflect.Type paramComposeType;
protected SncpActionServlet(
String resourceName,
Class resourceType,
Service service,
Uint128 serviceid,
Uint128 actionid,
final Method method) {
super(resourceName, resourceType, service, serviceid);
Objects.requireNonNull(method);
this.actionid = actionid;
this.method = method;
this.paramComposeType = null; // 待实现
int handlerFuncIndex = -1;
Class handlerFuncClass = null;
java.lang.reflect.Type handlerResultType = null;
try {
final Class[] paramClasses = method.getParameterTypes();
java.lang.reflect.Type[] genericParams = method.getGenericParameterTypes();
for (int i = 0; i < paramClasses.length; i++) { // 反序列化方法的每个参数
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
handlerFuncIndex = i;
handlerFuncClass = paramClasses[i];
java.lang.reflect.Type handlerType =
TypeToken.getGenericType(genericParams[i], service.getClass());
if (handlerType instanceof Class) {
handlerResultType = Object.class;
} else if (handlerType instanceof ParameterizedType) {
handlerResultType = TypeToken.getGenericType(
((ParameterizedType) handlerType).getActualTypeArguments()[0], handlerType);
} else {
throw new SncpException(service.getClass() + " had unknown genericType in " + method);
}
if (method.getReturnType() != void.class) {
throw new SncpException(
method + " have CompletionHandler type parameter but return type is not void");
}
break;
}
}
} catch (Throwable ex) {
// do nothing
}
java.lang.reflect.Type[] originalParamTypes =
TypeToken.getGenericType(method.getGenericParameterTypes(), service.getClass());
java.lang.reflect.Type originalReturnType =
TypeToken.getGenericType(method.getGenericReturnType(), service.getClass());
java.lang.reflect.Type[] types = new java.lang.reflect.Type[originalParamTypes.length + 1];
types[0] = originalReturnType;
System.arraycopy(originalParamTypes, 0, types, 1, originalParamTypes.length);
this.paramTypes = types;
this.paramHandlerIndex = handlerFuncIndex;
this.paramHandlerClass = handlerFuncClass;
this.paramHandlerResultType = handlerResultType;
this.returnObjectType =
originalReturnType == void.class || originalReturnType == Void.class ? null : originalReturnType;
if (Future.class.isAssignableFrom(method.getReturnType())) {
java.lang.reflect.Type futureType =
TypeToken.getGenericType(method.getGenericReturnType(), service.getClass());
java.lang.reflect.Type returnType = null;
if (futureType instanceof Class) {
returnType = Object.class;
} else if (futureType instanceof ParameterizedType) {
returnType = TypeToken.getGenericType(
((ParameterizedType) futureType).getActualTypeArguments()[0], futureType);
} else {
throw new SncpException(service.getClass() + " had unknown return genericType in " + method);
}
this.returnFutureResultType = returnType;
} else {
this.returnFutureResultType = null;
}
NonBlocking non = method.getAnnotation(NonBlocking.class);
if (non == null) {
non = service.getClass().getAnnotation(NonBlocking.class);
}
// Future代替CompletionStage 不容易判断异步
this.nonBlocking = non == null
&& (CompletionStage.class.isAssignableFrom(method.getReturnType()) || this.paramHandlerIndex >= 0);
}
@Override
public final void execute(SncpRequest request, SncpResponse response) throws IOException {
if (paramHandlerIndex > 0) {
response.paramAsyncHandler(paramHandlerClass, paramHandlerResultType);
}
try {
action(request, response);
} catch (IOException e) {
throw e;
} catch (Throwable t) {
throw new IOException(t);
}
}
protected abstract void action(SncpRequest request, SncpResponse response) throws Throwable;
public <T extends Service> T service() {
return (T) service;
}
@Override
public Uint128 getServiceid() {
return serviceid;
}
public Uint128 getActionid() {
return actionid;
}
public String actionName() {
return method.getDeclaringClass().getSimpleName() + "." + method.getName();
}
/**
*
*
* <blockquote>
*
* <pre>
* public interface TestService extends Service {
*
* public boolean change(TestBean bean, String name, int id);
*
* public void insert(BooleanHandler handler, TestBean bean, String name, int id);
*
* public void update(long show, short v2, CompletionHandler&#60;Boolean, TestBean&#62; handler, TestBean bean, String name, int id);
*
* public CompletableFuture&#60;String&#62; changeName(TestBean bean, String name, int id);
*
* }
*
* &#064;ResourceType(TestService.class)
* public class TestServiceImpl implements TestService {
*
* &#064;Override
* public boolean change(TestBean bean, String name, int id) {
* return false;
* }
*
* &#064;Override
* public void insert(BooleanHandler handler, TestBean bean, String name, int id) {
* }
*
* &#064;Override
* public void update(long show, short v2, CompletionHandler&#60;Boolean, TestBean&#62; handler, TestBean bean, String name, int id) {
* }
*
* &#064;Override
* public CompletableFuture&#60;String&#62; changeName(TestBean bean, String name, int id) {
* return null;
* }
* }
*
* public class BooleanHandler implements CompletionHandler&#60;Boolean, TestBean&#62; {
*
* &#064;Override
* public void completed(Boolean result, TestBean attachment) {
* }
*
* &#064;Override
* public void failed(Throwable exc, TestBean attachment) {
* }
*
* }
*
* public class DynActionTestService_change extends SncpActionServlet {
*
* public DynActionTestService_change(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
* String arg2 = convert.convertFrom(paramTypes[2], in);
* int arg3 = convert.convertFrom(paramTypes[3], in);
* TestService serviceObj = (TestService) service();
* Object rs = serviceObj.change(arg1, arg2, arg3);
* response.finish(boolean.class, rs);
* }
* }
*
* public class DynActionTestService_insert extends SncpActionServlet {
*
* public DynActionTestService_insert(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* BooleanHandler arg0 = response.getParamAsyncHandler();
* convert.convertFrom(CompletionHandler.class, in);
* TestBean arg1 = convert.convertFrom(paramTypes[2], in);
* String arg2 = convert.convertFrom(paramTypes[3], in);
* int arg3 = convert.convertFrom(paramTypes[4], in);
* TestService serviceObj = (TestService) service();
* serviceObj.insert(arg0, arg1, arg2, arg3);
* response.finishVoid();
* }
* }
*
* public class DynActionTestService_update extends SncpActionServlet {
*
* public DynActionTestService_update(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* long a1 = convert.convertFrom(paramTypes[1], in);
* short a2 = convert.convertFrom(paramTypes[2], in);
* CompletionHandler a3 = response.getParamAsyncHandler();
* convert.convertFrom(CompletionHandler.class, in);
* TestBean arg1 = convert.convertFrom(paramTypes[4], in);
* String arg2 = convert.convertFrom(paramTypes[5], in);
* int arg3 = convert.convertFrom(paramTypes[6], in);
* TestService serviceObj = (TestService) service();
* serviceObj.update(a1, a2, a3, arg1, arg2, arg3);
* response.finishVoid();
* }
* }
*
* public class DynActionTestService_changeName extends SncpActionServlet {
*
* public DynActionTestService_changeName(String resourceName, Class resourceType, Service service, Uint128 serviceid, Uint128 actionid, final Method method) {
* super(resourceName, resourceType, service, serviceid, actionid, method);
* }
*
* &#064;Override
* public void action(SncpRequest request, SncpResponse response) throws Throwable {
* Convert&#60;Reader, Writer&#62; convert = request.getConvert();
* Reader in = request.getReader();
* TestBean arg1 = convert.convertFrom(paramTypes[1], in);
* String arg2 = convert.convertFrom(paramTypes[2], in);
* int arg3 = convert.convertFrom(paramTypes[3], in);
* TestService serviceObj = (TestService) service();
* CompletableFuture future = serviceObj.changeName(arg1, arg2, arg3);
* response.finishFuture(paramHandlerResultType, future);
* }
* }
*
* </pre>
*
* </blockquote>
*
* @param resourceName 资源名
* @param resourceType 资源类
* @param serviceImplClass Service实现类
* @param service Service
* @param serviceid 类ID
* @param actionid 操作ID
* @param method 方法
* @return SncpActionServlet
*/
@SuppressWarnings("unchecked")
public static SncpActionServlet create(
final String resourceName,
final Class resourceType,
final Class serviceImplClass,
final Service service,
final Uint128 serviceid,
final Uint128 actionid,
final Method method) {
final Class serviceClass = service.getClass();
final String supDynName = SncpActionServlet.class.getName().replace('.', '/');
final String serviceImpTypeName = serviceImplClass.getName().replace('.', '/');
final String convertName = Convert.class.getName().replace('.', '/');
final String uint128Desc = Type.getDescriptor(Uint128.class);
final String convertDesc = Type.getDescriptor(Convert.class);
final String readerDesc = Type.getDescriptor(Reader.class);
final String requestName = SncpRequest.class.getName().replace('.', '/');
final String responseName = SncpResponse.class.getName().replace('.', '/');
final String requestDesc = Type.getDescriptor(SncpRequest.class);
final String responseDesc = Type.getDescriptor(SncpResponse.class);
final String serviceDesc = Type.getDescriptor(Service.class);
final boolean boolReturnTypeFuture = Future.class.isAssignableFrom(method.getReturnType());
final String newDynName = "org/redkaledyn/sncp/servlet/action/_DynSncpActionServlet__"
+ resourceType.getSimpleName() + "_" + method.getName() + "_" + actionid;
Class<?> newClazz = null;
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
newClazz = clz == null
? Thread.currentThread().getContextClassLoader().loadClass(newDynName.replace('/', '.'))
: clz;
} catch (Throwable ex) {
// do nothing
}
final java.lang.reflect.Type[] originalParamTypes =
TypeToken.getGenericType(method.getGenericParameterTypes(), serviceClass);
final java.lang.reflect.Type originalReturnType =
TypeToken.getGenericType(method.getGenericReturnType(), serviceClass);
if (newClazz == null) {
// -------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
MethodDebugVisitor mv;
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
mv = new MethodDebugVisitor(cw.visitMethod(
ACC_PUBLIC,
"<init>",
"(Ljava/lang/String;Ljava/lang/Class;" + serviceDesc + uint128Desc + uint128Desc
+ "Ljava/lang/reflect/Method;)V",
null,
null));
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 4);
mv.visitVarInsn(ALOAD, 5);
mv.visitVarInsn(ALOAD, 6);
mv.visitMethodInsn(
INVOKESPECIAL,
supDynName,
"<init>",
"(Ljava/lang/String;Ljava/lang/Class;" + serviceDesc + uint128Desc + uint128Desc
+ "Ljava/lang/reflect/Method;)V",
false);
mv.visitInsn(RETURN);
mv.visitMaxs(7, 7);
mv.visitEnd();
}
String convertFromDesc = "(Ljava/lang/reflect/Type;" + readerDesc + ")Ljava/lang/Object;";
try {
convertFromDesc = Type.getMethodDescriptor(
Convert.class.getMethod("convertFrom", java.lang.reflect.Type.class, Reader.class));
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
{ // action方法
mv = new MethodDebugVisitor(cw.visitMethod(
ACC_PUBLIC, "action", "(" + requestDesc + responseDesc + ")V", null, new String[] {
"java/lang/Throwable"
}));
// mv.setDebug(true);
{ // Convert
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, requestName, "getConvert", "()" + convertDesc, false);
mv.visitVarInsn(ASTORE, 3);
}
{ // Reader
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, requestName, "getReader", "()" + readerDesc, false);
mv.visitVarInsn(ASTORE, 4);
}
int iconst = ICONST_1;
int intconst = 1;
int store = 5; // action的参数个数+2
final Class[] paramClasses = method.getParameterTypes();
int[][] codes = new int[paramClasses.length][2];
int handlerFuncIndex = -1;
for (int i = 0; i < paramClasses.length; i++) { // 反序列化方法的每个参数
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
if (boolReturnTypeFuture) {
throw new SncpException(method + " have both CompletionHandler and CompletableFuture");
}
if (handlerFuncIndex >= 0) {
throw new SncpException(
method + " have more than one CompletionHandler type parameter");
}
Sncp.checkAsyncModifier(paramClasses[i], method);
handlerFuncIndex = i;
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(
INVOKEVIRTUAL,
responseName,
"getParamAsyncHandler",
"()Ljava/nio/channels/CompletionHandler;",
false);
mv.visitTypeInsn(
CHECKCAST, paramClasses[i].getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, store);
codes[i] = new int[] {ALOAD, store};
store++;
iconst++;
intconst++;
mv.visitVarInsn(ALOAD, 3);
mv.visitLdcInsn(Type.getType(Type.getDescriptor(CompletionHandler.class)));
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
mv.visitInsn(POP);
continue;
}
mv.visitVarInsn(ALOAD, 3);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;");
if (intconst < 6) {
mv.visitInsn(ICONST_0 + intconst);
} else if (iconst <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, intconst);
} else if (iconst <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, intconst);
} else {
mv.visitLdcInsn(intconst);
}
mv.visitInsn(AALOAD);
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
int load = ALOAD;
int v = 0;
if (paramClasses[i].isPrimitive()) {
int storecode = ISTORE;
load = ILOAD;
if (paramClasses[i] == long.class) {
storecode = LSTORE;
load = LLOAD;
v = 1;
} else if (paramClasses[i] == float.class) {
storecode = FSTORE;
load = FLOAD;
v = 1;
} else if (paramClasses[i] == double.class) {
storecode = DSTORE;
load = DLOAD;
v = 1;
}
Class bigPrimitiveClass = TypeToken.primitiveToWrapper(paramClasses[i]);
String bigPrimitiveName =
bigPrimitiveClass.getName().replace('.', '/');
try {
Method pm = bigPrimitiveClass.getMethod(paramClasses[i].getSimpleName() + "Value");
mv.visitTypeInsn(CHECKCAST, bigPrimitiveName);
mv.visitMethodInsn(
INVOKEVIRTUAL,
bigPrimitiveName,
pm.getName(),
Type.getMethodDescriptor(pm),
false);
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
mv.visitVarInsn(storecode, store);
} else {
mv.visitTypeInsn(
CHECKCAST, paramClasses[i].getName().replace('.', '/'));
mv.visitVarInsn(ASTORE, store); //
}
codes[i] = new int[] {load, store};
store += v;
iconst++;
intconst++;
store++;
}
{ // 调用service
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "service", "()" + serviceDesc, false);
mv.visitTypeInsn(CHECKCAST, serviceImpTypeName);
mv.visitVarInsn(ASTORE, store);
mv.visitVarInsn(ALOAD, store);
for (int[] j : codes) {
mv.visitVarInsn(j[0], j[1]);
}
mv.visitMethodInsn(
serviceImplClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL,
serviceImpTypeName,
method.getName(),
Type.getMethodDescriptor(method),
serviceImplClass.isInterface());
store++;
}
if (method.getReturnType() != void.class) {
final Class returnClass = method.getReturnType();
if (returnClass.isPrimitive()) {
Class bigClass = TypeToken.primitiveToWrapper(returnClass);
try {
Method vo = bigClass.getMethod("valueOf", returnClass);
mv.visitMethodInsn(
INVOKESTATIC,
bigClass.getName().replace('.', '/'),
vo.getName(),
Type.getMethodDescriptor(vo),
false);
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
}
mv.visitVarInsn(ASTORE, store); // 11
if (boolReturnTypeFuture) { // 返回类型为Future
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(
GETFIELD, newDynName, "returnFutureResultType", "Ljava/lang/reflect/Type;");
mv.visitVarInsn(ALOAD, store);
mv.visitMethodInsn(
INVOKEVIRTUAL,
responseName,
"finishFuture",
"(Ljava/lang/reflect/Type;Ljava/util/concurrent/Future;)V",
false);
} else if (handlerFuncIndex >= 0) { // 参数有CompletionHandler
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
} else { // 普通对象
mv.visitVarInsn(ALOAD, 2);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, "returnObjectType", "Ljava/lang/reflect/Type;");
mv.visitVarInsn(ALOAD, store);
mv.visitMethodInsn(
INVOKEVIRTUAL,
responseName,
"finish",
"(Ljava/lang/reflect/Type;Ljava/lang/Object;)V",
false);
}
} else { // void返回类型
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, responseName, "finishVoid", "()V", false);
}
mv.visitInsn(RETURN);
mv.visitMaxs(8, store);
mv.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
newClazz = new ClassLoader(serviceClass.getClassLoader()) {
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.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
try {
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), newClazz.getField("service"));
} catch (Exception e) {
// do nothing
}
for (java.lang.reflect.Type t : originalParamTypes) {
if (t == java.io.Serializable.class
|| t == java.io.Serializable[].class
|| t.toString().startsWith("java.lang.")) {
continue;
}
ProtobufFactory.root().loadDecoder(t);
}
if (originalReturnType != void.class && originalReturnType != Void.class) {
if (boolReturnTypeFuture && method.getReturnType() != method.getGenericReturnType()) {
java.lang.reflect.Type t =
((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0];
if (t != Void.class && t != java.lang.reflect.Type.class) {
ProtobufFactory.root().loadEncoder(t);
}
} else {
try {
ProtobufFactory.root().loadEncoder(originalReturnType);
} catch (Exception e) {
System.err.println(method);
}
}
}
}
try {
return (SncpActionServlet) newClazz.getConstructors()[0].newInstance(
resourceName, resourceType, service, serviceid, actionid, method);
} catch (Exception ex) {
throw new SncpException(ex); // 不可能会发生
}
}
}
}

View File

@@ -4,8 +4,6 @@
*/
package org.redkale.util;
import static org.redkale.asm.Opcodes.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
@@ -15,6 +13,7 @@ import java.util.concurrent.*;
import java.util.function.*;
import org.redkale.annotation.ConstructorParameters;
import org.redkale.asm.*;
import static org.redkale.asm.Opcodes.*;
import org.redkale.asm.Type;
/**
@@ -385,7 +384,7 @@ public interface Creator<T> {
throw new RedkaleException(
"[" + clazz + "] have no public or ConstructorParameters-Annotation constructor.");
}
final int[] iconsts = {ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5};
// -------------------------------------------------------------
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
FieldVisitor fv;
@@ -410,29 +409,13 @@ public interface Creator<T> {
{ // paramTypes 方法
mv = cw.visitMethod(ACC_PUBLIC, "paramTypes", "()[Ljava/lang/Class;", null, null);
int paramLen = constructorParameters.length;
if (paramLen < 6) {
mv.visitInsn(ICONST_0 + paramLen);
} else if (paramLen <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, paramLen);
} else if (paramLen <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, paramLen);
} else {
mv.visitLdcInsn(paramLen);
}
Asms.visitInsn(mv, paramLen);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
for (int i = 0; i < constructorParameters.length; i++) {
final Class pt = constructorParameters[i].getValue();
mv.visitInsn(DUP);
if (i < 6) {
mv.visitInsn(iconsts[i]);
} else if (i <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, i);
} else if (i <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, i);
} else {
mv.visitLdcInsn(i);
}
Asms.visitInsn(mv, i);
Asms.visitFieldInsn(mv, pt);
mv.visitInsn(AASTORE);
}
@@ -459,28 +442,12 @@ public interface Creator<T> {
continue;
}
mv.visitVarInsn(ALOAD, 1);
if (i < 6) {
mv.visitInsn(iconsts[i]);
} else if (i <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, i);
} else if (i <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, i);
} else {
mv.visitLdcInsn(i);
}
Asms.visitInsn(mv, i);
mv.visitInsn(AALOAD);
Label lab = new Label();
mv.visitJumpInsn(IFNONNULL, lab);
mv.visitVarInsn(ALOAD, 1);
if (i < 6) {
mv.visitInsn(iconsts[i]);
} else if (i <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, i);
} else if (i <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, i);
} else {
mv.visitLdcInsn(i);
}
Asms.visitInsn(mv, i);
if (pt == int.class) {
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(
@@ -517,15 +484,7 @@ public interface Creator<T> {
{
for (int i = 0; i < constructorParameters.length; i++) {
mv.visitVarInsn(ALOAD, 1);
if (i < 6) {
mv.visitInsn(iconsts[i]);
} else if (i <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, i);
} else if (i <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, i);
} else {
mv.visitLdcInsn(i);
}
Asms.visitInsn(mv, i);
mv.visitInsn(AALOAD);
final Class ct = constructorParameters[i].getValue();
if (ct.isPrimitive()) {

View File

@@ -16,11 +16,8 @@ import org.redkale.util.*;
/** @author zhangjx */
public class SncpClientCodecTest {
private boolean main;
public static void main(String[] args) throws Throwable {
SncpClientCodecTest test = new SncpClientCodecTest();
test.main = true;
test.run();
}

View File

@@ -12,11 +12,9 @@ import org.redkale.net.sncp.SncpAsyncHandler;
/** @author zhangjx */
public class SncpHandlerTest {
private boolean main;
public static void main(String[] args) throws Throwable {
SncpHandlerTest test = new SncpHandlerTest();
test.main = true;
test.run();
}
@@ -25,9 +23,7 @@ public class SncpHandlerTest {
SncpAsyncHandler.createHandler(CompletionHandler.class, new CompletionHandler() {
@Override
public void completed(Object result, Object attachment) {
if (main) {
System.out.println("handler result: " + result + ", attachment: " + attachment);
}
System.out.println("handler result: " + result + ", attachment: " + attachment);
}
@Override

View File

@@ -16,11 +16,8 @@ import org.redkale.util.*;
/** @author zhangjx */
public class SncpRequestParseTest {
private boolean main;
public static void main(String[] args) throws Throwable {
SncpRequestParseTest test = new SncpRequestParseTest();
test.main = true;
test.run();
}

View File

@@ -1,8 +1,6 @@
package org.redkale.test.sncp;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import org.junit.jupiter.api.*;
@@ -64,7 +62,7 @@ public class SncpSleepTest {
CompletableFuture.allOf(futures).join();
long e = System.currentTimeMillis() - s;
System.out.println("耗时: " + e + " ms");
remoteCService.test(333L, new String[] {"aaa", "bbb"}, List.of(new File("D:/a.txt"), new File("D:/b.txt")));
//remoteCService.test(333L, new String[] {"aaa", "bbb"}, List.of(new File("D:/a.txt"), new File("D:/b.txt")));
server.shutdown();
workExecutor.shutdown();
Assertions.assertTrue(e < 600);

View File

@@ -1,166 +0,0 @@
/*
*
*/
package org.redkale.test.sncp;
import java.lang.reflect.Method;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CompletableFuture;
import org.redkale.annotation.ResourceType;
import org.redkale.convert.*;
import org.redkale.net.sncp.*;
import org.redkale.net.sncp.SncpServlet.SncpActionServlet;
import org.redkale.service.Service;
import org.redkale.test.util.TestBean;
import org.redkale.util.Uint128;
/** @author zhangjx */
public interface TestService extends Service {
public boolean change(TestBean bean, String name, int id);
public void insert(BooleanHandler handler, TestBean bean, String name, int id);
public void update(
long show, short v2, CompletionHandler<Boolean, TestBean> handler, TestBean bean, String name, int id);
public CompletableFuture<String> changeName(TestBean bean, String name, int id);
}
@ResourceType(TestService.class)
class TestServiceImpl implements TestService {
@Override
public boolean change(TestBean bean, String name, int id) {
return false;
}
public void delete(TestBean bean) {}
@Override
public void insert(BooleanHandler handler, TestBean bean, String name, int id) {}
@Override
public void update(
long show, short v2, CompletionHandler<Boolean, TestBean> handler, TestBean bean, String name, int id) {}
@Override
public CompletableFuture<String> changeName(TestBean bean, String name, int id) {
return null;
}
}
class BooleanHandler implements CompletionHandler<Boolean, TestBean> {
@Override
public void completed(Boolean result, TestBean attachment) {}
@Override
public void failed(Throwable exc, TestBean attachment) {}
}
class DynActionTestService_change extends SncpActionServlet {
public DynActionTestService_change(
String resourceName,
Class resourceType,
Service service,
Uint128 serviceid,
Uint128 actionid,
final Method method) {
super(resourceName, resourceType, service, serviceid, actionid, method);
}
@Override
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
TestBean arg1 = convert.convertFrom(paramTypes[1], in);
String arg2 = convert.convertFrom(paramTypes[2], in);
int arg3 = convert.convertFrom(paramTypes[3], in);
TestService serviceObj = (TestService) service();
Object rs = serviceObj.change(arg1, arg2, arg3);
response.finish(boolean.class, rs);
}
}
class DynActionTestService_insert extends SncpActionServlet {
public DynActionTestService_insert(
String resourceName,
Class resourceType,
Service service,
Uint128 serviceid,
Uint128 actionid,
final Method method) {
super(resourceName, resourceType, service, serviceid, actionid, method);
}
@Override
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
BooleanHandler arg0 = response.getParamAsyncHandler();
convert.convertFrom(CompletionHandler.class, in);
TestBean arg1 = convert.convertFrom(paramTypes[2], in);
String arg2 = convert.convertFrom(paramTypes[3], in);
int arg3 = convert.convertFrom(paramTypes[4], in);
TestService serviceObj = (TestService) service();
serviceObj.insert(arg0, arg1, arg2, arg3);
response.finishVoid();
}
}
class DynActionTestService_update extends SncpActionServlet {
public DynActionTestService_update(
String resourceName,
Class resourceType,
Service service,
Uint128 serviceid,
Uint128 actionid,
final Method method) {
super(resourceName, resourceType, service, serviceid, actionid, method);
}
@Override
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
long a1 = convert.convertFrom(paramTypes[1], in);
short a2 = convert.convertFrom(paramTypes[2], in);
CompletionHandler a3 = response.getParamAsyncHandler();
convert.convertFrom(CompletionHandler.class, in);
TestBean arg1 = convert.convertFrom(paramTypes[4], in);
String arg2 = convert.convertFrom(paramTypes[5], in);
int arg3 = convert.convertFrom(paramTypes[6], in);
TestService serviceObj = (TestService) service();
serviceObj.update(a1, a2, a3, arg1, arg2, arg3);
response.finishVoid();
}
}
class DynActionTestService_changeName extends SncpActionServlet {
public DynActionTestService_changeName(
String resourceName,
Class resourceType,
Service service,
Uint128 serviceid,
Uint128 actionid,
final Method method) {
super(resourceName, resourceType, service, serviceid, actionid, method);
}
@Override
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
TestBean arg1 = convert.convertFrom(paramTypes[1], in);
String arg2 = convert.convertFrom(paramTypes[2], in);
int arg3 = convert.convertFrom(paramTypes[3], in);
TestService serviceObj = (TestService) service();
CompletableFuture future = serviceObj.changeName(arg1, arg2, arg3);
response.finishFuture(paramHandlerResultType, future);
}
}

View File

@@ -1,12 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.test.sncp;
import org.redkale.annotation.ResourceType;
/** @author zhangjx */
@ResourceType(SncpTestIService.class)
public class _DynLocalSncpTestService extends SncpTestServiceImpl {}

View File

@@ -9,9 +9,9 @@ import org.redkale.convert.Convert;
import org.redkale.convert.ConvertColumn;
import org.redkale.convert.Reader;
import org.redkale.convert.Writer;
import org.redkale.net.sncp.SncpActionServlet;
import org.redkale.net.sncp.SncpRequest;
import org.redkale.net.sncp.SncpResponse;
import org.redkale.net.sncp.SncpServlet.SncpActionServlet;
import org.redkale.service.Service;
import org.redkale.test.util.TestBean;
import org.redkale.util.Uint128;
@@ -36,7 +36,7 @@ public class DynActionTestService_change extends SncpActionServlet {
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
DynActionTestService_change_paramBean bean = convert.convertFrom(paramComposeType, in);
DynActionTestService_change_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
TestService serviceObj = (TestService) service();
Object rs = serviceObj.change(bean.arg1, bean.arg2, bean.arg3);
response.finish(boolean.class, rs);

View File

@@ -10,9 +10,9 @@ import org.redkale.convert.Convert;
import org.redkale.convert.ConvertColumn;
import org.redkale.convert.Reader;
import org.redkale.convert.Writer;
import org.redkale.net.sncp.SncpActionServlet;
import org.redkale.net.sncp.SncpRequest;
import org.redkale.net.sncp.SncpResponse;
import org.redkale.net.sncp.SncpServlet.SncpActionServlet;
import org.redkale.service.Service;
import org.redkale.test.util.TestBean;
import org.redkale.util.Uint128;
@@ -37,7 +37,7 @@ public class DynActionTestService_changeName extends SncpActionServlet {
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
DynActionTestService_changeName_paramBean bean = convert.convertFrom(paramComposeType, in);
DynActionTestService_changeName_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
TestService serviceObj = (TestService) service();
CompletableFuture future = serviceObj.changeName(bean.arg1, bean.arg2, bean.arg3);
response.finishFuture(paramHandlerResultType, future);

View File

@@ -8,9 +8,9 @@ import java.lang.reflect.Method;
import org.redkale.convert.Convert;
import org.redkale.convert.Reader;
import org.redkale.convert.Writer;
import org.redkale.net.sncp.SncpActionServlet;
import org.redkale.net.sncp.SncpRequest;
import org.redkale.net.sncp.SncpResponse;
import org.redkale.net.sncp.SncpServlet;
import org.redkale.service.Service;
import org.redkale.test.util.TestBean;
import org.redkale.util.Uint128;
@@ -19,7 +19,7 @@ import org.redkale.util.Uint128;
*
* @author zhangjx
*/
public class DynActionTestService_hello extends SncpServlet.SncpActionServlet {
public class DynActionTestService_hello extends SncpActionServlet {
public DynActionTestService_hello(
String resourceName,
@@ -35,7 +35,7 @@ public class DynActionTestService_hello extends SncpServlet.SncpActionServlet {
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
TestBean bean = convert.convertFrom(paramComposeType, in);
TestBean bean = convert.convertFrom(paramComposeBeanType, in);
TestService serviceObj = (TestService) service();
serviceObj.hello(bean);
response.finishVoid();

View File

@@ -9,9 +9,9 @@ import org.redkale.convert.Convert;
import org.redkale.convert.ConvertColumn;
import org.redkale.convert.Reader;
import org.redkale.convert.Writer;
import org.redkale.net.sncp.SncpActionServlet;
import org.redkale.net.sncp.SncpRequest;
import org.redkale.net.sncp.SncpResponse;
import org.redkale.net.sncp.SncpServlet.SncpActionServlet;
import org.redkale.service.Service;
import org.redkale.test.util.TestBean;
import org.redkale.util.Uint128;
@@ -36,7 +36,7 @@ public class DynActionTestService_insert extends SncpActionServlet {
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
DynActionTestService_insert_paramBean bean = convert.convertFrom(paramComposeType, in);
DynActionTestService_insert_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
bean.arg0 = response.getParamAsyncHandler();
TestService serviceObj = (TestService) service();
serviceObj.insert(bean.arg0, bean.arg1, bean.arg2, bean.arg3);

View File

@@ -10,9 +10,9 @@ import org.redkale.convert.Convert;
import org.redkale.convert.ConvertColumn;
import org.redkale.convert.Reader;
import org.redkale.convert.Writer;
import org.redkale.net.sncp.SncpActionServlet;
import org.redkale.net.sncp.SncpRequest;
import org.redkale.net.sncp.SncpResponse;
import org.redkale.net.sncp.SncpServlet.SncpActionServlet;
import org.redkale.service.Service;
import org.redkale.test.util.TestBean;
import org.redkale.util.Uint128;
@@ -37,7 +37,7 @@ public class DynActionTestService_update extends SncpActionServlet {
public void action(SncpRequest request, SncpResponse response) throws Throwable {
Convert<Reader, Writer> convert = request.getConvert();
Reader in = request.getReader();
DynActionTestService_update_paramBean bean = convert.convertFrom(paramComposeType, in);
DynActionTestService_update_paramBean bean = convert.convertFrom(paramComposeBeanType, in);
bean.arg3 = response.getParamAsyncHandler();
TestService serviceObj = (TestService) service();
serviceObj.update(bean.arg1, bean.arg2, bean.arg3, bean.arg4, bean.arg5, bean.arg6);
@@ -75,4 +75,4 @@ public class DynActionTestService_update extends SncpActionServlet {
@ConvertColumn(index = 6)
public int arg6;
}
}
}