Java tutorial
/* * Copyright 2012 Alibaba.com All right reserved. This software is the * confidential and proprietary information of Alibaba.com ("Confidential * Information"). You shall not disclose such Confidential Information and shall * use it only in accordance with the terms of the license agreement you entered * into with Alibaba.com. */ package com.taobao.rpc.doclet; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import sun.reflect.generics.reflectiveObjects.TypeVariableImpl; import com.alibaba.citrus.extension.rpc.annotation.ResourceMapping; import com.alibaba.citrus.extension.rpc.annotation.Security; import com.alibaba.citrus.extension.rpc.databind.File; import com.alibaba.citrus.extension.rpc.databind.JsonParam; import com.alibaba.citrus.extension.rpc.databind.PathParam; import com.alibaba.citrus.extension.rpc.integration.apiinfo.RPCAPIInfo; import com.alibaba.citrus.extension.rpc.integration.doclet.support.ClassInfo; import com.alibaba.citrus.extension.rpc.integration.doclet.support.FieldInfo; import com.alibaba.citrus.extension.rpc.integration.doclet.support.MethodInfo; import com.alibaba.citrus.extension.rpc.integration.doclet.support.ParameterInfo; import com.alibaba.citrus.extension.rpc.validation.ErrorContext; import com.alibaba.nonda.databind.annotation.RequestParam; import com.alibaba.nonda.databind.annotation.RequestParams; import com.taobao.rpc.doclet.util.StringUtil; /** * @author ZhangYouQun */ @SuppressWarnings("restriction") public class RPCAPIInfoHelper { static final Logger logger = LoggerFactory.getLogger(RPCAPIInfoHelper.class); public static RPCAPIInfo getAPIInfo(String realPath, Method method) { RPCAPIInfo apiInfo = new RPCAPIInfo(); ClassInfo classInfo = RPCAPIDocletUtil.getClassInfo(method.getDeclaringClass().getName()); MethodInfo methodInfo = null; if (classInfo != null) { methodInfo = classInfo.getMethodInfo(method.getName()); } if (methodInfo != null) { apiInfo.setComment(methodInfo.getComment()); } Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Security securityAnnotation = method.getAnnotation(Security.class); ResourceMapping resourceMapping = method.getAnnotation(ResourceMapping.class); Object returnType = null; returnType = buildTypeStructure(method.getReturnType(), method.getGenericReturnType(), null); boolean checkCSRF = false; if (securityAnnotation != null) { checkCSRF = securityAnnotation.checkCSRF(); } apiInfo.setPattern(realPath.replaceAll("///", "/")); apiInfo.setCheckCSRF(checkCSRF); apiInfo.setResponseMimes(StringUtils.arrayToDelimitedString(resourceMapping.produces(), ",")); apiInfo.setHttpMethod(StringUtils.arrayToDelimitedString(resourceMapping.method(), ",")); List<RPCAPIInfo.Parameter> parameters = new ArrayList<RPCAPIInfo.Parameter>(); RPCAPIInfo.Parameter parameter = null; LocalVariableTableParameterNameDiscoverer nameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); String[] paramNames = nameDiscoverer.getParameterNames(method); int i = 0; Class<?>[] parameterTypes = method.getParameterTypes(); Type[] genericParameterTypes = method.getGenericParameterTypes(); Class<?> paramType = null; Type genericType; for (int k = 0; k < parameterTypes.length; k++) { paramType = parameterTypes[k]; genericType = genericParameterTypes[k]; Annotation[] pAnnotations = parameterAnnotations[i]; if (HttpServletRequest.class.isAssignableFrom(paramType) || HttpServletResponse.class.isAssignableFrom(paramType) || ErrorContext.class.isAssignableFrom(paramType)) { continue; } // end if String realParamName = paramNames[k]; if (pAnnotations.length == 0) { parameter = apiInfo.new Parameter(); parameter.setName(realParamName); parameter.setType(buildTypeStructure(paramType, genericType, null)); parameters.add(parameter); setParameterComment(parameter, realParamName, methodInfo); continue; } // end if for (Annotation annotation : pAnnotations) { parameter = apiInfo.new Parameter(); setParameterComment(parameter, realParamName, methodInfo); if (annotation instanceof RequestParam) { RequestParam requestParam = (RequestParam) annotation; parameter.setName(requestParam.name()); parameter.setType(buildTypeStructure(paramType, genericType, null)); if (!StringUtil.isBlank(requestParam.defaultValue())) { parameter.setDefaultValue(requestParam.defaultValue().trim()); } parameters.add(parameter); } else if (annotation instanceof PathParam) { PathParam pathParam = (PathParam) annotation; parameter.setName(pathParam.name()); parameter.setType(buildTypeStructure(paramType, genericType, null)); if (!StringUtil.isBlank(pathParam.defaultValue())) { parameter.setDefaultValue(pathParam.defaultValue().trim()); } parameters.add(parameter); } else if (annotation instanceof JsonParam) { JsonParam pathParam = (JsonParam) annotation; parameter.setName(pathParam.value()); parameter.setType(buildTypeStructure(paramType, genericType, null)); parameters.add(parameter); } else if (annotation instanceof RequestParams) { parameter.setName(realParamName); parameter.setType(buildTypeStructure(paramType, genericType, null)); parameters.add(parameter); } else if (annotation instanceof File) { File file = (File) annotation; parameter.setName(file.value()); parameter.setType(""); parameters.add(parameter); } // end if } // end for i++; } // end for apiInfo.setParmeters(parameters); apiInfo.setReturnType(returnType); return apiInfo; } private static void setParameterComment(RPCAPIInfo.Parameter parameter, String realParamName, MethodInfo methodInfo) { if (methodInfo != null) { ParameterInfo parameterInfo = methodInfo.getParameterInfo(realParamName); if (parameterInfo != null) { parameter.setComment(parameterInfo.getComment()); } } } public static Object buildTypeStructure(Class<?> type) { return buildTypeStructure(type, null, null); } /** * ? * * @param method * @return */ public static Object buildTypeStructure(Class<?> type, Type genericType, Type oriGenericType) { if ("void".equalsIgnoreCase(type.getName()) || ClassUtils.isPrimitiveOrWrapper(type) || String.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type) || URL.class.isAssignableFrom(type)) { // return type.getName().replaceAll("java.lang.", "").replaceAll("java.util.", "").replaceAll("java.sql.", ""); } // end if if (type.isArray()) { // return new Object[] { buildTypeStructure(type.getComponentType(), type.getComponentType(), genericType) }; } // end if if (ClassUtils.isAssignable(Map.class, type)) { // Map return Map.class.getName(); } // end if if (type.isEnum()) { // Enum return Enum.class.getName(); } // end if boolean isCollection = type != null ? Collection.class.isAssignableFrom(type) : false; if (isCollection) { Type rawType = type; if (genericType != null) { if (genericType instanceof ParameterizedType) { ParameterizedType _type = (ParameterizedType) genericType; Type[] actualTypeArguments = _type.getActualTypeArguments(); rawType = actualTypeArguments[0]; } else if (genericType instanceof GenericArrayType) { rawType = ((GenericArrayType) genericType).getGenericComponentType(); } if (genericType instanceof WildcardType) { rawType = ((WildcardType) genericType).getUpperBounds()[0]; } } if (rawType == type) { return new Object[] { rawType.getClass().getName() }; } else { if (rawType.getClass().isAssignableFrom(TypeVariableImpl.class)) { return new Object[] { buildTypeStructure( (Class<?>) ((ParameterizedType) oriGenericType).getActualTypeArguments()[0], rawType, genericType) }; } else { if (rawType instanceof ParameterizedType) { if (((ParameterizedType) rawType).getRawType() == Map.class) { return new Object[] { Map.class.getName() }; } } if (oriGenericType == rawType) { return new Object[] { rawType.getClass().getName() }; } return new Object[] { buildTypeStructure((Class<?>) rawType, rawType, genericType) }; } } } if (type.isInterface()) { return type.getName(); } ClassInfo paramClassInfo = RPCAPIDocletUtil.getClassInfo(type.getName()); //added if (null == paramClassInfo) { System.out.println("failed to get paramClassInfo for :" + type.getName()); return null; } List<FieldInfo> typeConstructure = new ArrayList<FieldInfo>(); BeanWrapper bean = new BeanWrapperImpl(type); PropertyDescriptor[] propertyDescriptors = bean.getPropertyDescriptors(); Method readMethod; String name; for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { readMethod = propertyDescriptor.getReadMethod(); if (readMethod == null || "getClass".equals(readMethod.getName())) { continue; } name = propertyDescriptor.getName(); FieldInfo fieldInfo = paramClassInfo.getFieldInfo(name); if (readMethod.getReturnType().isAssignableFrom(type)) { String comment = "structure is the same with parent."; typeConstructure .add(FieldInfo.create(name, fieldInfo != null ? fieldInfo.getComment() : "", comment)); } else { typeConstructure.add( FieldInfo.create(name, fieldInfo != null ? fieldInfo.getComment() : "", buildTypeStructure( readMethod.getReturnType(), readMethod.getGenericReturnType(), genericType))); } // end if } return typeConstructure; } }