KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > easybeans > deployment > annotations > helper > bean > InterceptorsClassResolver


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: InterceptorsClassResolver.java 848 2006-07-12 11:23:26Z benoitf $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.easybeans.deployment.annotations.helper.bean;
27
28 import java.util.ArrayList JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.LinkedList JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33
34 import javax.ejb.Remove JavaDoc;
35
36 import org.objectweb.asm.Type;
37 import org.objectweb.easybeans.container.session.stateful.interceptors.RemoveAlwaysInterceptor;
38 import org.objectweb.easybeans.container.session.stateful.interceptors.RemoveOnlyWithoutExceptionInterceptor;
39 import org.objectweb.easybeans.deployment.annotations.InterceptorType;
40 import org.objectweb.easybeans.deployment.annotations.JClassInterceptor;
41 import org.objectweb.easybeans.deployment.annotations.JMethod;
42 import org.objectweb.easybeans.deployment.annotations.exceptions.ResolverException;
43 import org.objectweb.easybeans.deployment.annotations.impl.JInterceptors;
44 import org.objectweb.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
45 import org.objectweb.easybeans.deployment.annotations.metadata.EjbJarAnnotationMetadata;
46 import org.objectweb.easybeans.deployment.annotations.metadata.MethodAnnotationMetadata;
47 import org.objectweb.easybeans.naming.interceptors.ENCManager;
48 import static org.objectweb.easybeans.deployment.annotations.helper.bean.InheritanceInterfacesHelper.JAVA_LANG_OBJECT;
49 /**
50  * This class sets the EasyBeans interceptors used when invoking business methods and also for life cycle events.
51  * @author Florent Benoit
52  */

53 public final class InterceptorsClassResolver {
54
55     /**
56      * Signature of EasyBeans interceptors.
57      */

58     private static final JMethod EASYBEANS_INTERCEPTOR = new JMethod(0, "intercept",
59             "(Lorg/objectweb/easybeans/api/EasyBeansInvocationContext;)Ljava/lang/Object;",
60             null, new String JavaDoc[] {"java/lang/Exception"});
61
62
63     /**
64      * Helper class, no public constructor.
65      */

66     private InterceptorsClassResolver() {
67
68     }
69
70
71     /**
72      * Found all interceptors of the class (including business and lifecycle events) and also set EasyBeans interceptors.
73      * @param classAnnotationMetadata class to analyze
74      * @throws ResolverException if metadata is missing
75      */

76     public static void resolve(final ClassAnnotationMetadata classAnnotationMetadata) throws ResolverException {
77
78         // First, EasyBeans interceptors
79
List JavaDoc<String JavaDoc> easyBeansInterceptorsClasses = new ArrayList JavaDoc<String JavaDoc>();
80         // Add EasyBeans interceptors for all methods
81
easyBeansInterceptorsClasses.add(Type.getInternalName(ENCManager.getInterceptorClass()));
82         // Set list of global interceptors (applied on all business methods)
83
List JavaDoc<JClassInterceptor> easyBeansGlobalInterceptors = new ArrayList JavaDoc<JClassInterceptor>();
84         for (String JavaDoc easyBeansInterceptor : easyBeansInterceptorsClasses) {
85             easyBeansGlobalInterceptors.add(new JClassInterceptor(easyBeansInterceptor, EASYBEANS_INTERCEPTOR));
86         }
87         classAnnotationMetadata.setGlobalEasyBeansInterceptors(easyBeansGlobalInterceptors);
88
89         // TODO: adds the default interceptor (set in the DD)
90

91
92         // And then, set the user interceptors (found in external class)
93
List JavaDoc<String JavaDoc> externalInterceptorsClasses = new ArrayList JavaDoc<String JavaDoc>();
94
95         // Interceptors from other classes (will be analyzed after)
96
// See 3.5.3 of simplified EJB 3.0 spec : multiple interceptors
97
// Add interceptor classes found on super classes (if any)
98

99
100         // Invert list of the inheritance on the current class
101
LinkedList JavaDoc<ClassAnnotationMetadata> invertedInheritanceClassesList =
102             getInvertedSuperClassesMetadata(classAnnotationMetadata);
103         // Add interceptors found on these classes (order is super super class
104
// before super class, ie : top level first)
105
for (ClassAnnotationMetadata superMetaData : invertedInheritanceClassesList) {
106             JInterceptors classIinterceptors = superMetaData.getAnnotationInterceptors();
107             if (classIinterceptors != null) {
108                 for (String JavaDoc cls : classIinterceptors.getClasses()) {
109                     externalInterceptorsClasses.add(cls);
110                 }
111             }
112         }
113
114
115         // Get the interceptors defined by the user on external classes
116
Map JavaDoc<InterceptorType, List JavaDoc<JClassInterceptor>> externalMapClassInterceptors =
117             getInterceptors(classAnnotationMetadata.getClassName(), classAnnotationMetadata.getEjbJarAnnotationMetadata(),
118                     externalInterceptorsClasses);
119         classAnnotationMetadata.setExternalUserInterceptors(externalMapClassInterceptors);
120
121
122         // interceptor in the bean class ? (LifeCycle event interceptors are not in the bean
123
// because they don't take an InvocationContext as parameter, this is the intercepted method
124
List JavaDoc<String JavaDoc> internalInterceptorsClasses = new ArrayList JavaDoc<String JavaDoc>();
125
126         if (classAnnotationMetadata.isAroundInvokeMethodMetadata()) {
127             internalInterceptorsClasses.add(classAnnotationMetadata.getClassName());
128         }
129         // Get the interceptors defined by the user on the class
130
Map JavaDoc<InterceptorType, List JavaDoc<JClassInterceptor>> internalMapClassInterceptors =
131             getInterceptors(classAnnotationMetadata.getClassName(), classAnnotationMetadata.getEjbJarAnnotationMetadata(),
132                     internalInterceptorsClasses);
133         classAnnotationMetadata.setInternalUserInterceptors(internalMapClassInterceptors);
134
135
136         // Now, analyze each interceptors found on methods.
137
for (MethodAnnotationMetadata methodAnnotationMetaData
138                 : classAnnotationMetadata.getMethodAnnotationMetadataCollection()) {
139
140             // Set global interceptors for a given method (ie : Remove)
141
Remove JavaDoc remove = methodAnnotationMetaData.getJRemove();
142             if (remove != null) {
143                 List JavaDoc<JClassInterceptor> easyBeansMethodGlobalInterceptors = new ArrayList JavaDoc<JClassInterceptor>();
144                 String JavaDoc classType = null;
145                 // choose right interceptor class
146
if (remove.retainIfException()) {
147                     classType = Type.getInternalName(RemoveOnlyWithoutExceptionInterceptor.class);
148                 } else {
149                     classType = Type.getInternalName(RemoveAlwaysInterceptor.class);
150                 }
151                 easyBeansMethodGlobalInterceptors.add(new JClassInterceptor(classType, EASYBEANS_INTERCEPTOR));
152
153                 // set list
154
methodAnnotationMetaData.setGlobalEasyBeansInterceptors(easyBeansMethodGlobalInterceptors);
155             }
156
157             JInterceptors methodAnnotationInterceptors = methodAnnotationMetaData.getAnnotationInterceptors();
158             if (methodAnnotationInterceptors != null) {
159                 List JavaDoc<String JavaDoc> methodInterceptorsClasses = new ArrayList JavaDoc<String JavaDoc>();
160                 for (String JavaDoc cls : methodAnnotationInterceptors.getClasses()) {
161                     methodInterceptorsClasses.add(cls);
162                 }
163                 Map JavaDoc<InterceptorType, List JavaDoc<JClassInterceptor>> mapMethodInterceptors =
164                     getInterceptors(classAnnotationMetadata.getClassName() + "/Method "
165                             + methodAnnotationMetaData.getMethodName(),
166                             classAnnotationMetadata.getEjbJarAnnotationMetadata(), methodInterceptorsClasses);
167                 methodAnnotationMetaData.setUserInterceptors(mapMethodInterceptors);
168             }
169
170         }
171
172     }
173
174
175     /**
176      * Found interceptors method in the given class. It will analyze each interceptor class and
177      * fill a structure with a mapping between the annotation type and the corresponding interceptors.
178      * @param referencingName name of the class/method that reference these interceptors
179      * @param ejbJarAnnotationMetadata root of all annotations (used to find the metadata)
180      * @param interceptorsClasses list of classes that contains interceptors
181      * @return the map between the type of interceptor (PostConstrut, AroundInvoke, ...) and the JClassInterceptor objects
182      * @throws ResolverException if analyze fails
183      */

184     private static Map JavaDoc<InterceptorType, List JavaDoc<JClassInterceptor>> getInterceptors(final String JavaDoc referencingName,
185             final EjbJarAnnotationMetadata ejbJarAnnotationMetadata,
186             final List JavaDoc<String JavaDoc> interceptorsClasses) throws ResolverException {
187         // Define the mapping object.
188
Map JavaDoc<InterceptorType, List JavaDoc<JClassInterceptor>> mapInterceptors = new HashMap JavaDoc<InterceptorType, List JavaDoc<JClassInterceptor>>();
189         // Init the map for each interceptor type
190
for (InterceptorType type : InterceptorType.values()) {
191             mapInterceptors.put(type, new ArrayList JavaDoc<JClassInterceptor>());
192         }
193
194         int interceptorClassAnalyzed = 0;
195
196         // For each interceptors classes, take the method with @AroundInvoke or @PostConstruct, etc. and build list
197
for (String JavaDoc className : interceptorsClasses) {
198             ClassAnnotationMetadata interceptorMetadata = ejbJarAnnotationMetadata.getClassAnnotationMetadata(className);
199             if (interceptorMetadata == null) {
200                 throw new ResolverException("No medata for interceptor class " + className
201                         + " referenced by " + referencingName);
202             }
203
204             // Another interceptor class
205
interceptorClassAnalyzed++;
206
207             // No inner class of the bean
208
if (interceptorMetadata.getClassName().contains("$")) {
209                 throw new IllegalStateException JavaDoc("Interceptor can't be defined in an inner class.");
210             }
211
212
213             // Takes all methods of the super class and add them to the current class.
214
InheritanceMethodResolver.resolve(interceptorMetadata);
215
216
217             // Invert list of the inheritance on the current class
218
LinkedList JavaDoc<ClassAnnotationMetadata> invertedInheritanceClassesList =
219                 getInvertedSuperClassesMetadata(interceptorMetadata);
220
221             // For each class (starting super class first, add the interceptor methods)
222
for (ClassAnnotationMetadata currentMetaData : invertedInheritanceClassesList) {
223             // Analyze methods of the interceptor meta-data and add it in the map
224
for (MethodAnnotationMetadata method : currentMetaData.getMethodAnnotationMetadataCollection()) {
225                     // Don't look inherited methods.
226
if (method.isInherited()) {
227                         continue;
228                     }
229                     JClassInterceptor jInterceptor = new JClassInterceptor(className, method.getJMethod(),
230                             interceptorClassAnalyzed);
231
232                     // If the method is overriden, take care of using the
233
// annotation of the lower class in the inheritance classes.
234
// As the method is only add once for a single interceptor
235
// class.
236
MethodAnnotationMetadata analyzedMethod = method;
237                     MethodAnnotationMetadata methodSubClass = interceptorMetadata.getMethodAnnotationMetadata(method
238                             .getJMethod());
239                     if (methodSubClass != null) {
240                         analyzedMethod = methodSubClass;
241                     }
242
243
244                     // A method can be designed to run for all annotation, so no "else if" !
245
if (analyzedMethod.isAroundInvoke()) {
246                         addOnlyIfNotPresent(mapInterceptors.get(InterceptorType.AROUND_INVOKE), jInterceptor);
247                     }
248                     // Only if interceptor class is not a bean's class. Else, it is only simple methods.
249
if (!currentMetaData.isBean()) {
250                         // build interceptor object.
251
if (analyzedMethod.isPostActivate()) {
252                             addOnlyIfNotPresent(mapInterceptors.get(InterceptorType.POST_ACTIVATE), jInterceptor);
253                         }
254                         if (analyzedMethod.isPostConstruct()) {
255                             addOnlyIfNotPresent(mapInterceptors.get(InterceptorType.POST_CONSTRUCT), jInterceptor);
256                         }
257                         if (analyzedMethod.isPreDestroy()) {
258                             addOnlyIfNotPresent(mapInterceptors.get(InterceptorType.PRE_DESTROY), jInterceptor);
259                         }
260                         if (analyzedMethod.isPrePassivate()) {
261                             addOnlyIfNotPresent(mapInterceptors.get(InterceptorType.PRE_PASSIVATE), jInterceptor);
262                         }
263                     }
264                 }
265             }
266
267         }
268
269
270
271
272         return mapInterceptors;
273     }
274
275     /**
276      * Adds in the given interceptors list the interceptor object.
277      * If the object is already present in the list, doesn't add it again.
278      * @param interceptors the list of interceptors.
279      * @param jInterceptor the interceptor to add.
280      */

281     private static void addOnlyIfNotPresent(final List JavaDoc<JClassInterceptor> interceptors, final JClassInterceptor jInterceptor) {
282         if (!interceptors.contains(jInterceptor)) {
283             interceptors.add(jInterceptor);
284         }
285     }
286
287     /**
288      * Gets the inverted list of metadata for a given class (super class is the first one in the list).
289      * @param classAnnotationMetadata the class to analyze
290      * @return the given list
291      */

292     private static LinkedList JavaDoc<ClassAnnotationMetadata> getInvertedSuperClassesMetadata(
293             final ClassAnnotationMetadata classAnnotationMetadata) {
294
295         // get list of super classes
296
LinkedList JavaDoc<ClassAnnotationMetadata> superClassesList = new LinkedList JavaDoc<ClassAnnotationMetadata>();
297         String JavaDoc superClassName = classAnnotationMetadata.getSuperName();
298         // loop while super class is not java.lang.Object
299
while (!JAVA_LANG_OBJECT.equals(superClassName)) {
300             ClassAnnotationMetadata superMetaData = classAnnotationMetadata.getEjbJarAnnotationMetadata()
301                     .getClassAnnotationMetadata(superClassName);
302             if (superMetaData != null) {
303                 superClassName = superMetaData.getSuperName();
304                 superClassesList.addFirst(superMetaData);
305             } else {
306                 superClassName = JAVA_LANG_OBJECT;
307             }
308         }
309         superClassesList.addLast(classAnnotationMetadata);
310         return superClassesList;
311     }
312
313 }
314
Popular Tags