1
18 package net.bull.javamelody.internal.web;
19
20 import java.io.IOException;
21 import java.lang.annotation.Annotation;
22 import java.lang.annotation.ElementType;
23 import java.lang.annotation.Retention;
24 import java.lang.annotation.RetentionPolicy;
25 import java.lang.annotation.Target;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.util.HashMap;
29 import java.util.Map;
30
31 import javax.servlet.http.HttpServletRequest;
32
33 import net.bull.javamelody.internal.common.HttpParameter;
34 import net.bull.javamelody.internal.common.HttpPart;
35
36
41 class RequestToMethodMapper<T> {
42 private final Map<HttpPart, Method> methodsByPart = new HashMap<>();
43
44 @Target(ElementType.METHOD)
45 @Retention(RetentionPolicy.RUNTIME)
46 @interface RequestPart {
47
50 HttpPart value();
51 }
52
53 @Target(ElementType.PARAMETER)
54 @Retention(RetentionPolicy.RUNTIME)
55 @interface RequestParameter {
56
59 HttpParameter value();
60 }
61
62 @Target(ElementType.PARAMETER)
63 @Retention(RetentionPolicy.RUNTIME)
64 @interface RequestAttribute {
65
68 String value();
69 }
70
71 @Target(ElementType.PARAMETER)
72 @Retention(RetentionPolicy.RUNTIME)
73 @interface RequestHeader {
74
77 String value();
78 }
79
80 RequestToMethodMapper(Class<T> clazz) {
81 super();
82 for (final Method method : clazz.getDeclaredMethods()) {
83 final RequestPart partAnnotation = method.getAnnotation(RequestPart.class);
84 if (partAnnotation != null) {
85 methodsByPart.put(partAnnotation.value(), method);
86 }
87 }
88 }
89
90 void invoke(HttpServletRequest httpRequest, T controller) throws IOException {
91 invokeAndReturn(httpRequest, controller);
92 }
93
94 Object invokeAndReturn(HttpServletRequest httpRequest, T controller) throws IOException {
95 final String partParameter = HttpParameter.PART.getParameterFrom(httpRequest);
96 final HttpPart httpPart = HttpPart.getByName(partParameter);
97 final Method method = methodsByPart.get(httpPart);
98 if (method == null) {
99 throw new IllegalArgumentException("Unknown http part: " + partParameter);
100 }
101 try {
102
103 final Object[] parameterValues = getParameterValues(httpRequest, method);
104
105 return method.invoke(controller, parameterValues);
106 } catch (final IllegalAccessException e) {
107 throw new IllegalStateException(e);
108 } catch (final InvocationTargetException e) {
109 final Throwable targetException = e.getTargetException();
110 if (targetException instanceof IOException) {
111 throw (IOException) targetException;
112 } else if (targetException instanceof RuntimeException) {
113 throw (RuntimeException) targetException;
114 } else if (targetException instanceof Error) {
115 throw (Error) targetException;
116 }
117 throw new IOException(targetException);
118 }
119 }
120
121 private Object[] getParameterValues(HttpServletRequest request, Method method) {
122
123 final Annotation[][] parameters = method.getParameterAnnotations();
124 final Object[] values = new Object[parameters.length];
125 for (int i = 0; i < parameters.length; i++) {
126 final Annotation[] parameter = parameters[i];
127 boolean found = false;
128 for (final Annotation annotation : parameter) {
129 if (annotation.annotationType() == RequestParameter.class) {
130 final HttpParameter requestParameter = ((RequestParameter) annotation).value();
131 values[i] = requestParameter.getParameterFrom(request);
132 found = true;
133 break;
134 } else if (annotation.annotationType() == RequestAttribute.class) {
135 final String requestAttribute = ((RequestAttribute) annotation).value();
136 values[i] = request.getAttribute(requestAttribute);
137 found = true;
138 break;
139 } else if (annotation.annotationType() == RequestHeader.class) {
140 final String requestHeader = ((RequestHeader) annotation).value();
141 values[i] = request.getHeader(requestHeader);
142 found = true;
143 break;
144 }
145 }
146 if (!found) {
147 throw new IllegalStateException(
148 "a parameter not annotated in method " + method.getName());
149 }
150 }
151 return values;
152 }
153 }
154