1 | |
package org.apache.onami.autobind.aop.feature; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
import java.lang.annotation.Annotation; |
21 | |
import java.lang.reflect.Method; |
22 | |
import java.lang.reflect.Type; |
23 | |
import java.util.HashMap; |
24 | |
import java.util.Map; |
25 | |
import java.util.logging.Level; |
26 | |
import java.util.logging.Logger; |
27 | |
|
28 | |
import javax.inject.Singleton; |
29 | |
import javax.interceptor.Interceptor; |
30 | |
|
31 | |
import org.aopalliance.intercept.MethodInterceptor; |
32 | |
import org.aopalliance.intercept.MethodInvocation; |
33 | |
import org.apache.onami.autobind.aop.ClassMatcher; |
34 | |
import org.apache.onami.autobind.aop.GuiceMethodInterceptor; |
35 | |
import org.apache.onami.autobind.aop.Invoke; |
36 | |
import org.apache.onami.autobind.aop.MethodMatcher; |
37 | |
import org.apache.onami.autobind.install.BindingStage; |
38 | |
import org.apache.onami.autobind.scanner.features.BindingScannerFeature; |
39 | |
|
40 | |
import com.google.inject.matcher.Matcher; |
41 | |
import com.google.inject.matcher.Matchers; |
42 | |
|
43 | |
|
44 | |
@Singleton |
45 | 0 | public class InterceptorFeature extends BindingScannerFeature { |
46 | 0 | private Logger _logger = Logger.getLogger(InterceptorFeature.class.getName()); |
47 | |
|
48 | |
@Override |
49 | |
public BindingStage accept(Class<Object> annotatedClass, Map<String, Annotation> annotations) { |
50 | 0 | if (annotations.containsKey(Interceptor.class.getName())) { |
51 | 0 | return BindingStage.BOOT; |
52 | |
} |
53 | 0 | return BindingStage.IGNORE; |
54 | |
} |
55 | |
|
56 | |
@SuppressWarnings("unchecked") |
57 | |
@Override |
58 | |
public void process(Class<Object> annotatedClass, Map<String, Annotation> annotations) { |
59 | |
MethodInterceptor interceptor; |
60 | 0 | final Object possibleInterceptor = injector.getInstance(annotatedClass); |
61 | |
|
62 | 0 | Matcher<? super Class<?>> classMatcher = null; |
63 | 0 | Matcher<? super Method> methodMatcher = null; |
64 | 0 | if (possibleInterceptor instanceof GuiceMethodInterceptor) { |
65 | 0 | interceptor = (MethodInterceptor) possibleInterceptor; |
66 | 0 | GuiceMethodInterceptor guiceInterceptor = (GuiceMethodInterceptor) interceptor; |
67 | 0 | classMatcher = guiceInterceptor.getClassMatcher(); |
68 | 0 | methodMatcher = guiceInterceptor.getMethodMatcher(); |
69 | 0 | } else { |
70 | 0 | Method[] declaredMethods = annotatedClass.getDeclaredMethods(); |
71 | 0 | Map<Class<? extends Annotation>, Method> methods = new HashMap<Class<? extends Annotation>, Method>(); |
72 | |
|
73 | 0 | for (Method method : declaredMethods) { |
74 | 0 | Annotation[] methodAnnotations = method.getAnnotations(); |
75 | 0 | for (Annotation methodAnnotation : methodAnnotations) { |
76 | 0 | methods.put(methodAnnotation.annotationType(), method); |
77 | |
} |
78 | |
} |
79 | |
try { |
80 | 0 | if (methods.containsKey(ClassMatcher.class)) { |
81 | 0 | Method method = methods.get(ClassMatcher.class); |
82 | 0 | Type genericReturnType = method.getGenericReturnType(); |
83 | 0 | if (GuiceMethodInterceptor.CLASS_MATCHER_TYPE.equals(genericReturnType)) { |
84 | 0 | classMatcher = (Matcher<? super Class<?>>) method.invoke( |
85 | |
possibleInterceptor, new Object[0]); |
86 | |
} else { |
87 | 0 | _logger.log(Level.WARNING, |
88 | |
"Return Type of the annotated @ClassMatcher-Method, does not return: " |
89 | |
+ GuiceMethodInterceptor.CLASS_MATCHER_TYPE |
90 | |
+ " instead it returns " + genericReturnType); |
91 | |
} |
92 | |
} |
93 | |
|
94 | 0 | if (methods.containsKey(MethodMatcher.class)) { |
95 | 0 | Method method = methods.get(MethodMatcher.class); |
96 | 0 | Type genericReturnType = method.getGenericReturnType(); |
97 | 0 | if (GuiceMethodInterceptor.METHOD_MATCHER_TYPE.equals(genericReturnType)) { |
98 | 0 | methodMatcher = (Matcher<? super Method>) method.invoke( |
99 | |
possibleInterceptor, new Object[0]); |
100 | |
} else { |
101 | 0 | _logger.log(Level.WARNING, |
102 | |
"Return Type of the annotated @MethodMatcher-Method, does not return: " |
103 | |
+ GuiceMethodInterceptor.METHOD_MATCHER_TYPE |
104 | |
+ " instead it returns " + genericReturnType); |
105 | |
} |
106 | |
} |
107 | 0 | } catch (Exception e) { |
108 | 0 | _logger |
109 | |
.log( |
110 | |
Level.WARNING, |
111 | |
"Skipping process(..) of \"" |
112 | |
+ annotatedClass |
113 | |
+ "\", because an Exception occured while trying to invoke a Method of the found Intercepter.", |
114 | |
e); |
115 | 0 | return; |
116 | 0 | } |
117 | |
|
118 | 0 | if (possibleInterceptor instanceof MethodInterceptor) { |
119 | 0 | interceptor = (MethodInterceptor) possibleInterceptor; |
120 | |
} else { |
121 | 0 | if (methods.containsKey(Invoke.class)) { |
122 | 0 | final Method method = methods.get(Invoke.class); |
123 | 0 | Class<?>[] parameterTypes = method.getParameterTypes(); |
124 | 0 | if (parameterTypes != null && parameterTypes.length == 1 |
125 | |
&& parameterTypes[0] == MethodInvocation.class) { |
126 | 0 | interceptor = new MethodInterceptor() { |
127 | |
@Override |
128 | |
public Object invoke(MethodInvocation invocation) throws Throwable { |
129 | 0 | return method.invoke(possibleInterceptor, invocation); |
130 | |
} |
131 | |
}; |
132 | |
} else { |
133 | 0 | _logger |
134 | |
.log( |
135 | |
Level.WARNING, |
136 | |
"Skipping \"" |
137 | |
+ annotatedClass |
138 | |
+ "\", because the Parameter of the with @Invoke annotated Method \"" |
139 | |
+ method.getName() |
140 | |
+ "\" doesn't match the expected one. " |
141 | |
+ method.getName() + "(MethodInvocation invocation)"); |
142 | 0 | return; |
143 | |
} |
144 | 0 | } else { |
145 | 0 | _logger.log(Level.WARNING, "Skipping \"" + annotatedClass |
146 | |
+ "\" is either Child of \"" |
147 | |
+ GuiceMethodInterceptor.class.getName() + "\" / \"" |
148 | |
+ MethodInterceptor.class.getName() |
149 | |
+ "\" nor has a Method annotated with \"" + Invoke.class.getName() |
150 | |
+ "\""); |
151 | 0 | return; |
152 | |
} |
153 | |
} |
154 | |
} |
155 | |
|
156 | 0 | if (classMatcher == null) { |
157 | 0 | classMatcher = Matchers.any(); |
158 | |
} |
159 | |
|
160 | 0 | if (methodMatcher == null) { |
161 | 0 | methodMatcher = Matchers.any(); |
162 | |
} |
163 | |
|
164 | 0 | _binder.bindInterceptor(classMatcher, methodMatcher, interceptor); |
165 | 0 | } |
166 | |
} |