1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.common.events.annotated;
20
21 import java.lang.annotation.Annotation;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Modifier;
24
25 import org.eclipse.jetty.util.StringUtil;
26 import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
27 import org.eclipse.jetty.websocket.common.events.ParamList;
28
29
30
31
32 public abstract class AbstractMethodAnnotationScanner<T>
33 {
34 protected void assertIsPublicNonStatic(Method method)
35 {
36 int mods = method.getModifiers();
37 if (!Modifier.isPublic(mods))
38 {
39 StringBuilder err = new StringBuilder();
40 err.append("Invalid declaration of ");
41 err.append(method);
42 err.append(StringUtil.__LINE_SEPARATOR);
43
44 err.append("Method modifier must be public");
45
46 throw new InvalidWebSocketException(err.toString());
47 }
48
49 if (Modifier.isStatic(mods))
50 {
51 StringBuilder err = new StringBuilder();
52 err.append("Invalid declaration of ");
53 err.append(method);
54 err.append(StringUtil.__LINE_SEPARATOR);
55
56 err.append("Method modifier may not be static");
57
58 throw new InvalidWebSocketException(err.toString());
59 }
60 }
61
62 protected void assertIsReturn(Method method, Class<?> type)
63 {
64 if (!type.equals(method.getReturnType()))
65 {
66 StringBuilder err = new StringBuilder();
67 err.append("Invalid declaration of ");
68 err.append(method);
69 err.append(StringUtil.__LINE_SEPARATOR);
70
71 err.append("Return type must be ").append(type);
72
73 throw new InvalidWebSocketException(err.toString());
74 }
75 }
76
77 protected void assertIsVoidReturn(Method method)
78 {
79 assertIsReturn(method,Void.TYPE);
80 }
81
82 protected void assertUnset(CallableMethod callable, Class<? extends Annotation> annoClass, Method method)
83 {
84 if (callable != null)
85 {
86
87 StringBuilder err = new StringBuilder();
88 err.append("Duplicate @").append(annoClass.getSimpleName()).append(" declaration on ");
89 err.append(method);
90 err.append(StringUtil.__LINE_SEPARATOR);
91
92 err.append("@").append(annoClass.getSimpleName()).append(" previously declared at ");
93 err.append(callable.getMethod());
94
95 throw new InvalidWebSocketException(err.toString());
96 }
97 }
98
99 protected void assertValidSignature(Method method, Class<? extends Annotation> annoClass, ParamList validParams)
100 {
101 assertIsPublicNonStatic(method);
102 assertIsReturn(method,Void.TYPE);
103
104 boolean valid = false;
105
106
107 Class<?> actual[] = method.getParameterTypes();
108 for (Class<?>[] params : validParams)
109 {
110 if (isSameParameters(actual,params))
111 {
112 valid = true;
113 break;
114 }
115 }
116
117 if (!valid)
118 {
119 throw InvalidSignatureException.build(method,annoClass,validParams);
120 }
121 }
122
123 public boolean isAnnotation(Annotation annotation, Class<? extends Annotation> annotationClass)
124 {
125 return annotation.annotationType().equals(annotationClass);
126 }
127
128 public boolean isSameParameters(Class<?>[] actual, Class<?>[] params)
129 {
130 if (actual.length != params.length)
131 {
132
133 return false;
134 }
135
136 int len = params.length;
137 for (int i = 0; i < len; i++)
138 {
139 if (!actual[i].equals(params[i]))
140 {
141 return false;
142 }
143 }
144
145 return true;
146 }
147
148 protected boolean isSignatureMatch(Method method, ParamList validParams)
149 {
150 assertIsPublicNonStatic(method);
151 assertIsReturn(method,Void.TYPE);
152
153
154 Class<?> actual[] = method.getParameterTypes();
155 for (Class<?>[] params : validParams)
156 {
157 if (isSameParameters(actual,params))
158 {
159 return true;
160 }
161 }
162
163 return false;
164 }
165
166 protected boolean isTypeAnnotated(Class<?> pojo, Class<? extends Annotation> expectedAnnotation)
167 {
168 return pojo.getAnnotation(expectedAnnotation) != null;
169 }
170
171 public abstract void onMethodAnnotation(T metadata, Class<?> pojo, Method method, Annotation annotation);
172
173 public void scanMethodAnnotations(T metadata, Class<?> pojo)
174 {
175 Class<?> clazz = pojo;
176
177 while ((clazz != null) && Object.class.isAssignableFrom(clazz))
178 {
179 for (Method method : clazz.getDeclaredMethods())
180 {
181 Annotation annotations[] = method.getAnnotations();
182 if ((annotations == null) || (annotations.length <= 0))
183 {
184 continue;
185 }
186 for (Annotation annotation : annotations)
187 {
188 onMethodAnnotation(metadata,clazz,method,annotation);
189 }
190 }
191
192 clazz = clazz.getSuperclass();
193 }
194 }
195 }