package eu.codearte.resteeth.core; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; /** * @author Jakub Kubrynski */ class MetadataExtractor { private final static Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); MethodMetadata extractMethodMetadata(Method method, RequestMapping controllerRequestMapping, ResteethAnnotationMetadata resteethAnnotationMetadata) { RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); String methodUrl = extractUrl(requestMapping, controllerRequestMapping); Class<?>[] parameterTypes = method.getParameterTypes(); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Integer requestBody = null; Integer pojoQueryParameter = null; HashMap<Integer, String> urlVariables = new HashMap<>(); HashMap<Integer, String> queryParameters = new HashMap<>(); if (parameterTypes != null && parameterTypes.length > 0) { for (int i = 0; i < parameterTypes.length; i++) { if (parameterAnnotations[i].length > 0) { for (Annotation parameterAnnotation : parameterAnnotations[i]) { if (PathVariable.class.isAssignableFrom(parameterAnnotation.getClass())) { urlVariables.put(i, ((PathVariable) parameterAnnotation).value()); } else if (RequestParam.class.isAssignableFrom(parameterAnnotation.getClass())) { queryParameters.put(i, ((RequestParam) parameterAnnotation).value()); } else if (RequestBody.class.isAssignableFrom(parameterAnnotation.getClass())) { requestBody = i; } } } else { pojoQueryParameter = i; } } } return new MethodMetadata(methodUrl, extractRequestMethod(requestMapping, controllerRequestMapping), extractReturnType(method), extractHeaders(requestMapping, controllerRequestMapping), new MethodAnnotationMetadata(resteethAnnotationMetadata), new ParameterMetadata(requestBody, urlVariables, queryParameters, pojoQueryParameter)); } private Class<?> extractReturnType(Method method) { return method.getReturnType() == void.class ? Void.class : method.getReturnType(); } private HttpHeaders extractHeaders(RequestMapping requestMapping, RequestMapping controllerRequestMapping) { HttpHeaders headers = new HttpHeaders(); String[] consumes = requestMapping.consumes(); if (consumes.length == 0 && controllerRequestMapping != null) { consumes = controllerRequestMapping.consumes(); } if (consumes.length > 0) { headers.setContentType(MediaType.valueOf(consumes[0])); } String[] produces = requestMapping.produces(); if (produces.length == 0 && controllerRequestMapping != null) { produces = controllerRequestMapping.produces(); } if (produces.length > 0) { ArrayList<MediaType> acceptableMediaTypes = new ArrayList<>(); for (String acceptType : produces) { acceptableMediaTypes.add(MediaType.valueOf(acceptType)); } headers.setAccept(acceptableMediaTypes); } return headers; } private String extractUrl(RequestMapping methodMapping, RequestMapping controllerMapping) { String foundUrl = ""; String[] controllerValues = controllerMapping != null ? controllerMapping.value() : new String[0]; String[] methodValues = methodMapping.value(); if (methodValues.length == 0 && controllerValues.length == 0) { throw new IncorrectRequestMapping("No request url found!"); } if (controllerValues.length > 0) { foundUrl += controllerValues[0]; if (controllerValues.length > 1) { LOG.warn("Found more than one controller URL mapping. Using first specified: {}", foundUrl); } } if (methodValues.length > 0) { foundUrl += methodValues[0]; if (methodValues.length > 1) { LOG.warn("Found more than one URL mapping. Using first specified: {}", foundUrl); } } return foundUrl; } private HttpMethod extractRequestMethod(RequestMapping requestMapping, RequestMapping controllerRequestMapping) { RequestMethod[] requestMethods = requestMapping.method(); if (requestMethods == null || requestMethods.length == 0) { if (controllerRequestMapping == null || controllerRequestMapping.method() == null || controllerRequestMapping.method().length == 0) { LOG.warn("No request mapping requestMethods found"); throw new IncorrectRequestMapping("No requestMethods specified!"); } else { requestMethods = controllerRequestMapping.method(); } } else if (requestMethods.length > 1) { LOG.warn("More than one request method found. Using first specified"); } return HttpMethod.valueOf(requestMethods[0].name()); } }