|
21 | 21 | import java.lang.annotation.Annotation; |
22 | 22 | import java.lang.reflect.AnnotatedElement; |
23 | 23 | import java.lang.reflect.Method; |
| 24 | +import java.lang.reflect.Modifier; |
24 | 25 | import java.util.ArrayList; |
25 | 26 | import java.util.Arrays; |
26 | 27 | import java.util.HashMap; |
|
29 | 30 | import java.util.Map; |
30 | 31 | import java.util.Optional; |
31 | 32 | import java.util.Set; |
| 33 | +import java.util.function.BiConsumer; |
| 34 | +import java.util.function.Consumer; |
32 | 35 | import java.util.function.Function; |
33 | 36 |
|
34 | 37 | import org.jooby.Env; |
@@ -71,31 +74,27 @@ public class MvcRoutes { |
71 | 74 | .add(Consumes.class) |
72 | 75 | .build(); |
73 | 76 |
|
74 | | - @SuppressWarnings({"unchecked", "rawtypes" }) |
75 | 77 | public static List<Route.Definition> routes(final Env env, final RouteMetadata classInfo, |
76 | 78 | final String rpath, final Class<?> routeClass) { |
77 | 79 |
|
| 80 | + // check and fail fast |
| 81 | + methods(routeClass, methods -> { |
| 82 | + routes(methods, (m, a) -> { |
| 83 | + if (!Modifier.isPublic(m.getModifiers())) { |
| 84 | + throw new IllegalArgumentException("Not a public method: " + m); |
| 85 | + } |
| 86 | + }); |
| 87 | + }); |
| 88 | + |
78 | 89 | RequestParamProvider provider = new RequestParamProviderImpl( |
79 | 90 | new RequestParamNameProviderImpl(classInfo)); |
80 | 91 |
|
81 | 92 | String[] rootPaths = path(routeClass); |
82 | 93 | String[] rootExcludes = excludes(routeClass, EMPTY); |
83 | 94 |
|
| 95 | + // we are good, now collect them |
84 | 96 | Map<Method, List<Class<?>>> methods = new HashMap<>(); |
85 | | - for (Method method : routeClass.getMethods()) { |
86 | | - List<Class<?>> annotations = new ArrayList<>(); |
87 | | - for (Class annotationType : VERBS) { |
88 | | - Annotation annotation = method.getAnnotation(annotationType); |
89 | | - if (annotation != null) { |
90 | | - annotations.add(annotationType); |
91 | | - } |
92 | | - } |
93 | | - if (annotations.size() > 0) { |
94 | | - methods.put(method, annotations); |
95 | | - } else if (method.isAnnotationPresent(Path.class)) { |
96 | | - methods.put(method, Arrays.asList(GET.class)); |
97 | | - } |
98 | | - } |
| 97 | + routes(routeClass.getMethods(), methods::put); |
99 | 98 |
|
100 | 99 | List<Definition> definitions = new ArrayList<>(); |
101 | 100 | Map<String, Object> attrs = attrs(routeClass.getAnnotations()); |
@@ -145,6 +144,32 @@ public static List<Route.Definition> routes(final Env env, final RouteMetadata c |
145 | 144 | return definitions; |
146 | 145 | } |
147 | 146 |
|
| 147 | + private static void methods(final Class<?> clazz, final Consumer<Method[]> callback) { |
| 148 | + if (clazz != Object.class) { |
| 149 | + callback.accept(clazz.getDeclaredMethods()); |
| 150 | + methods(clazz.getSuperclass(), callback); |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + @SuppressWarnings({"rawtypes", "unchecked" }) |
| 155 | + private static void routes(final Method[] methods, |
| 156 | + final BiConsumer<Method, List<Class<?>>> consumer) { |
| 157 | + for (Method method : methods) { |
| 158 | + List<Class<?>> annotations = new ArrayList<>(); |
| 159 | + for (Class annotationType : VERBS) { |
| 160 | + Annotation annotation = method.getAnnotation(annotationType); |
| 161 | + if (annotation != null) { |
| 162 | + annotations.add(annotationType); |
| 163 | + } |
| 164 | + } |
| 165 | + if (annotations.size() > 0) { |
| 166 | + consumer.accept(method, annotations); |
| 167 | + } else if (method.isAnnotationPresent(Path.class)) { |
| 168 | + consumer.accept(method, Arrays.asList(GET.class)); |
| 169 | + } |
| 170 | + } |
| 171 | + } |
| 172 | + |
148 | 173 | private static Map<String, Object> attrs(final Annotation[] annotations) { |
149 | 174 | Map<String, Object> result = new LinkedHashMap<>(); |
150 | 175 | for (Annotation annotation : annotations) { |
|
0 commit comments