KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > easybeans > deployment > annotations > helper > bean > session > checks > InterceptorsValidator


1 /**
2  * EasyBeans
3  * Copyright (C) 2006 Bull S.A.S.
4  * Contact: easybeans@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: InterceptorsValidator.java 450 2006-05-12 15:30:25Z benoitf $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.easybeans.deployment.annotations.helper.bean.session.checks;
27
28 import java.util.List JavaDoc;
29 import static org.objectweb.asm.Opcodes.ACC_STATIC;
30 import static org.objectweb.asm.Opcodes.ACC_FINAL;
31
32 import org.objectweb.easybeans.deployment.annotations.JMethod;
33 import org.objectweb.easybeans.deployment.annotations.exceptions.InterceptorsValidationException;
34 import org.objectweb.easybeans.deployment.annotations.impl.JInterceptors;
35 import org.objectweb.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
36 import org.objectweb.easybeans.deployment.annotations.metadata.EjbJarAnnotationMetadata;
37 import org.objectweb.easybeans.deployment.annotations.metadata.MethodAnnotationMetadata;
38
39 /**
40  * This class ensures that the interceptors have the correct signature.
41  * @author Florent Benoit
42  */

43 public final class InterceptorsValidator {
44
45     /**
46      * Signature for an AroundInvoke interceptor (InvocationContext).
47      */

48     private static final String JavaDoc AROUND_INVOKE_DESCRIPTOR_EJB = "(Ljavax/interceptor/InvocationContext;)Ljava/lang/Object;";
49
50     /**
51      * Signature for a lifecycle interceptor inside the bean (void type).
52      */

53     private static final String JavaDoc LIFECYCLE_DESCRIPTOR_OUTSIDEBEAN = "(Ljavax/interceptor/InvocationContext;)V";
54
55     /**
56      * Signature for a lifecycle interceptor inside the bean (void type).
57      */

58     private static final String JavaDoc LIFECYCLE_DESCRIPTOR_BEAN = "()V";
59
60     /**
61      * Exception required in AroundInvoke interceptor.
62      */

63     private static final String JavaDoc AROUND_INVOKE_EXCEPTION = "java/lang/Exception";
64
65     /**
66      * Constructor without args.
67      */

68     private static final String JavaDoc DEFAULT_CONSTRUCTOR_DESCRIPTOR = "()V";
69
70     /**
71      * Default constructor method's name.
72      */

73     private static final String JavaDoc CONSTRUCTOR_METHOD = "<init>";
74
75     /**
76      * Helper class, no public constructor.
77      */

78     private InterceptorsValidator() {
79     }
80
81     /**
82      * Validate a bean.
83      * @param bean bean to validate.
84      */

85     public static void validate(final ClassAnnotationMetadata bean) {
86
87         // Root metadata
88
EjbJarAnnotationMetadata ejbMetaData = bean.getEjbJarAnnotationMetadata();
89
90         // Interceptors in the bean
91
if (bean.isBean()) {
92             for (MethodAnnotationMetadata method : bean.getMethodAnnotationMetadataCollection()) {
93
94                 // lifecycle
95
if (method.isLifeCycleMethod()) {
96                     validateJMethod(method.getJMethod(), LIFECYCLE_DESCRIPTOR_BEAN, null, bean.getClassName());
97                 } else if (method.isAroundInvoke()) {
98                     validateJMethod(method.getJMethod(), AROUND_INVOKE_DESCRIPTOR_EJB, AROUND_INVOKE_EXCEPTION, bean
99                             .getClassName());
100                 }
101
102                 // Interceptors defined on the bean's methods
103
JInterceptors methodInterceptors = method.getAnnotationInterceptors();
104                 // Look in the interceptor class
105
if (methodInterceptors != null) {
106                     for (String JavaDoc className : methodInterceptors.getClasses()) {
107                         analyzeInterceptorClass(ejbMetaData, className);
108                     }
109                 }
110             }
111
112             // Now, check interceptors outside the bean
113
JInterceptors methodInterceptors = bean.getAnnotationInterceptors();
114             // Look in the interceptor class
115
if (methodInterceptors != null) {
116                 for (String JavaDoc className : methodInterceptors.getClasses()) {
117                     analyzeInterceptorClass(ejbMetaData, className);
118                 }
119             }
120
121             // Analyze interfaces and check that there are no methods with
122
// @AroundInvoke or @PostConstruct
123
String JavaDoc[] interfaces = bean.getInterfaces();
124             if (interfaces != null) {
125                 for (String JavaDoc itf : interfaces) {
126                     ClassAnnotationMetadata interfaceMetaData = ejbMetaData.getClassAnnotationMetadata(itf);
127                     if (interfaceMetaData != null) {
128                         for (MethodAnnotationMetadata method : interfaceMetaData
129                                 .getMethodAnnotationMetadataCollection()) {
130                             // no AroundInvoke or PostConstruct
131
if (method.isAroundInvoke()) {
132                                 throw new InterceptorsValidationException("The method '" + method
133                                         + "' in the bean class '" + bean.getClassName()
134                                         + "' cannot be an AroundInvoke as it is an interface");
135                             }
136                             if (method.isLifeCycleMethod()) {
137                                 throw new InterceptorsValidationException("The method '" + method
138                                         + "' in the bean class '" + bean.getClassName()
139                                         + "' cannot be a lifecycle as it is an interface");
140                             }
141                         }
142                     }
143                 }
144             }
145         }
146
147         // Standalone interceptors
148
if (bean.isInterceptor()) {
149             analyzeInterceptorClass(ejbMetaData, bean.getClassName());
150         }
151
152     }
153
154     /**
155      * Analyze an interceptor class and check the interceptors method.
156      * @param ejbMetaData root metadata used to extract class metadata
157      * @param className the name of the class being analyzed
158      */

159     private static void analyzeInterceptorClass(final EjbJarAnnotationMetadata ejbMetaData, final String JavaDoc className) {
160         // get the metadata of the class
161
ClassAnnotationMetadata interceptorMetaData = ejbMetaData.getClassAnnotationMetadata(className);
162         if (interceptorMetaData == null) {
163             throw new InterceptorsValidationException("Internal problem as no metadata was found for '" + className
164                     + "'.");
165         }
166
167         List JavaDoc<MethodAnnotationMetadata> aroundInvokeList = interceptorMetaData.getAroundInvokeMethodMetadatas();
168         if (aroundInvokeList != null && aroundInvokeList.size() > 1) {
169             String JavaDoc errMsg = "There are severals @AroundInvoke in the class '" + className
170                     + "', while only one is allowed. List of Methods : '" + aroundInvokeList + "'.";
171             throw new InterceptorsValidationException(errMsg);
172         }
173
174         // Ensure that interceptor has a default constructor.
175
JMethod defaultConstructor = new JMethod(0, CONSTRUCTOR_METHOD, DEFAULT_CONSTRUCTOR_DESCRIPTOR, null, null);
176         if (interceptorMetaData.getMethodAnnotationMetadata(defaultConstructor) == null) {
177             throw new InterceptorsValidationException("No default constructor in the interceptor class '" + className
178                     + "'.");
179         }
180
181         for (MethodAnnotationMetadata method : interceptorMetaData.getMethodAnnotationMetadataCollection()) {
182
183             // lifecycle (outside the bean)
184
if (method.isLifeCycleMethod() && !method.getClassAnnotationMetadata().isBean()) {
185                 validateJMethod(method.getJMethod(), LIFECYCLE_DESCRIPTOR_OUTSIDEBEAN, null, className);
186             } else if (method.isAroundInvoke()) {
187                 // signature
188
validateJMethod(method.getJMethod(), AROUND_INVOKE_DESCRIPTOR_EJB, AROUND_INVOKE_EXCEPTION, className);
189
190                 // No final or static method
191
ensureNoAccess(ACC_FINAL, method.getJMethod(), "Final", className);
192                 ensureNoAccess(ACC_STATIC, method.getJMethod(), "Static", className);
193             }
194
195         }
196
197     }
198
199     /**
200      * Validate that a given method don't use a given access mode.
201      * @param acc the access mode to refuse.
202      * @param jMethod method to check.
203      * @param desc the description of the access.
204      * @param className the name of the class of the given method.
205      */

206     private static void ensureNoAccess(final int acc, final JMethod jMethod, final String JavaDoc desc, final String JavaDoc className) {
207         if ((jMethod.getAccess() & acc) == acc) {
208             throw new InterceptorsValidationException("The method '" + jMethod + "' of the class '" + className
209                     + "' is not compliant on the method access. It shouldn't use the '" + desc + "' keyword.");
210         }
211     }
212
213     /**
214      * Validate the given method with the given signature/exceptions.
215      * @param jMethod method to check.
216      * @param desc signature to ensure.
217      * @param awaitedException exception to ensure.
218      * @param className the name of the class of the given method.
219      */

220     private static void validateJMethod(final JMethod jMethod, final String JavaDoc desc, final String JavaDoc awaitedException,
221             final String JavaDoc className) {
222
223         // validate signature
224
if (!jMethod.getDescriptor().equals(desc)) {
225             throw new InterceptorsValidationException("Method '" + jMethod + "' of the class '" + className
226                     + "' is not compliant with the signature '" + desc + "'. Signature found = '"
227                     + jMethod.getDescriptor() + "'.");
228         }
229
230         // validate exceptions
231
String JavaDoc[] exceptions = jMethod.getExceptions();
232         if (awaitedException == null) {
233             return;
234         }
235
236         boolean found = false;
237
238         if (exceptions != null) {
239             for (String JavaDoc exception : exceptions) {
240                 if (exception.equals(awaitedException)) {
241                     found = true;
242                 }
243             }
244         }
245         if (!found) {
246             throw new InterceptorsValidationException("Method '" + jMethod + "' of the class '" + className
247                     + "' is not compliant with the signature '" + desc + "' as the required exception '"
248                     + awaitedException + "' is missing.");
249         }
250     }
251
252 }
253
Popular Tags