use of org.redkale.asm.ClassWriter.COMPUTE_FRAMES 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