1 | /** |
2 | * |
3 | * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com> |
4 | * |
5 | * ==================================================================== |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * you may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
17 | * ==================================================================== |
18 | */ |
19 | package org.jclouds.rest.internal; |
20 | |
21 | import static com.google.common.collect.Sets.difference; |
22 | import static org.jclouds.rest.internal.RestAnnotationProcessor.delegationMap; |
23 | import static org.jclouds.rest.internal.RestAnnotationProcessor.getHttpMethods; |
24 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToBinderParamAnnotation; |
25 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToEndpointAnnotations; |
26 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToEndpointParamAnnotations; |
27 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToFormParamAnnotations; |
28 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToHeaderParamAnnotations; |
29 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToMatrixParamAnnotations; |
30 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToParamParserAnnotations; |
31 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToPartParamAnnotations; |
32 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToPathParamAnnotations; |
33 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToPostParamAnnotations; |
34 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToQueryParamAnnotations; |
35 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToWrapWithAnnotation; |
36 | import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexesOfOptions; |
37 | |
38 | import java.lang.reflect.Method; |
39 | |
40 | import javax.annotation.Resource; |
41 | import javax.inject.Named; |
42 | import javax.inject.Singleton; |
43 | import javax.ws.rs.Path; |
44 | import javax.ws.rs.PathParam; |
45 | |
46 | import org.jclouds.http.HttpRequest; |
47 | import org.jclouds.logging.Logger; |
48 | import org.jclouds.rest.annotations.Delegate; |
49 | import org.jclouds.rest.internal.RestAnnotationProcessor.MethodKey; |
50 | |
51 | import com.google.common.base.Function; |
52 | import com.google.common.collect.ImmutableSet; |
53 | import com.google.common.collect.Multimap; |
54 | import com.google.inject.Inject; |
55 | import com.google.inject.Injector; |
56 | import com.google.inject.Key; |
57 | import com.google.inject.Provides; |
58 | |
59 | /** |
60 | * seeds the annotation cache |
61 | * |
62 | * @author Adrian Cole |
63 | */ |
64 | |
65 | @Singleton |
66 | public class SeedAnnotationCache implements Function<Class<?>, Boolean> { |
67 | @Resource |
68 | protected Logger logger = Logger.NULL; |
69 | |
70 | protected final Multimap<String, String> constants; |
71 | protected final Injector injector; |
72 | |
73 | @Inject |
74 | public SeedAnnotationCache(Injector injector, @Named("CONSTANTS") Multimap<String, String> constants) { |
75 | this.injector = injector; |
76 | this.constants = constants; |
77 | } |
78 | |
79 | public void bindConstant(Method method) { |
80 | String key = method.getAnnotation(PathParam.class).value(); |
81 | String value = injector.getInstance(Key.get(String.class, method.getAnnotation(Named.class))); |
82 | constants.put(key, value); |
83 | } |
84 | |
85 | public Boolean apply(Class<?> declaring) { |
86 | for (Method method : difference(ImmutableSet.copyOf(declaring.getMethods()), ImmutableSet.copyOf(Object.class |
87 | .getMethods()))) { |
88 | if (isHttpMethod(method) || method.isAnnotationPresent(Delegate.class)) { |
89 | for (int index = 0; index < method.getParameterTypes().length; index++) { |
90 | methodToIndexOfParamToBinderParamAnnotation.get(method).get(index); |
91 | methodToIndexOfParamToWrapWithAnnotation.get(method).get(index); |
92 | methodToIndexOfParamToHeaderParamAnnotations.get(method).get(index); |
93 | methodToIndexOfParamToMatrixParamAnnotations.get(method).get(index); |
94 | methodToIndexOfParamToFormParamAnnotations.get(method).get(index); |
95 | methodToIndexOfParamToQueryParamAnnotations.get(method).get(index); |
96 | methodToIndexOfParamToEndpointAnnotations.get(method).get(index); |
97 | methodToIndexOfParamToEndpointParamAnnotations.get(method).get(index); |
98 | methodToIndexOfParamToPathParamAnnotations.get(method).get(index); |
99 | methodToIndexOfParamToPostParamAnnotations.get(method).get(index); |
100 | methodToIndexOfParamToParamParserAnnotations.get(method).get(index); |
101 | methodToIndexOfParamToPartParamAnnotations.get(method).get(index); |
102 | methodToIndexesOfOptions.get(method); |
103 | } |
104 | delegationMap.put(new MethodKey(method), method); |
105 | } else if (isConstantDeclaration(method)) { |
106 | bindConstant(method); |
107 | } else if (!method.getDeclaringClass().equals(declaring)) { |
108 | logger.trace("skipping potentially overridden method %s", method); |
109 | } else if (method.isAnnotationPresent(Provides.class)) { |
110 | logger.trace("skipping provider method %s", method); |
111 | } else { |
112 | logger.trace("Method is not annotated as either http or constant: %s", method); |
113 | } |
114 | } |
115 | return true; |
116 | } |
117 | |
118 | public static boolean isHttpMethod(Method method) { |
119 | return method.isAnnotationPresent(Path.class) || getHttpMethods(method) != null |
120 | || ImmutableSet.copyOf(method.getParameterTypes()).contains(HttpRequest.class); |
121 | } |
122 | |
123 | public static boolean isConstantDeclaration(Method method) { |
124 | return method.isAnnotationPresent(PathParam.class) && method.isAnnotationPresent(Named.class); |
125 | } |
126 | } |