KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > ejb > containers > interceptors > InterceptorManager


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * Created on Jan 7, 2005
26  *
27  * TODO To change the template for this generated file go to
28  * Window - Preferences - Java - Code Style - Code Templates
29  */

30 package com.sun.ejb.containers.interceptors;
31
32 import com.sun.ejb.EJBUtils;
33 import com.sun.ejb.Invocation;
34 import com.sun.ejb.Invocation.InterceptorChain;
35 import com.sun.ejb.containers.BaseContainer;
36 import com.sun.ejb.containers.EJBContextImpl;
37
38 import com.sun.enterprise.deployment.EjbDescriptor;
39 import com.sun.enterprise.deployment.EjbInterceptor;
40 import com.sun.enterprise.deployment.MethodDescriptor;
41 import com.sun.enterprise.deployment.LifecycleCallbackDescriptor;
42 import static com.sun.enterprise.deployment.LifecycleCallbackDescriptor.CallbackType;
43 import com.sun.enterprise.deployment.EjbSessionDescriptor;
44
45 import java.io.Serializable JavaDoc;
46 import java.lang.reflect.Method JavaDoc;
47
48 import java.util.*;
49 import java.util.logging.Level JavaDoc;
50 import java.util.logging.Logger JavaDoc;
51
52 import javax.interceptor.InvocationContext;
53
54
55 /**
56  * UserInterceptorsManager manages UserInterceptors. There
57  * is one instance of InterceptorManager per container.
58  *
59  * @author Mahesh Kannan
60  */

61 public class InterceptorManager {
62
63     private BaseContainer container;
64
65     private EjbDescriptor ejbDesc;
66
67     private ClassLoader JavaDoc loader;
68
69     private Class JavaDoc beanClass;
70
71     private String JavaDoc beanClassName;
72
73     private Logger JavaDoc _logger;
74
75     private Class JavaDoc[] interceptorClasses;
76     
77     private Class JavaDoc[] serializableInterceptorClasses;
78
79     private Map<String JavaDoc, Integer JavaDoc> instanceIndexMap
80             = new HashMap<String JavaDoc, Integer JavaDoc>();
81
82     private boolean methodInterceptorsExists;
83
84     private String JavaDoc[] pre30LCMethodNames;
85
86     private Class JavaDoc[] lcAnnotationClasses;
87
88     private CallbackChainImpl[] callbackChain;
89
90
91     public InterceptorManager(Logger JavaDoc _logger, BaseContainer container,
92                               Class JavaDoc[] lcAnnotationClasses, String JavaDoc[] pre30LCMethodNames)
93             throws Exception JavaDoc {
94         this._logger = _logger;
95         this.container = container;
96         this.lcAnnotationClasses = lcAnnotationClasses;
97         this.pre30LCMethodNames = pre30LCMethodNames;
98
99         ejbDesc = container.getEjbDescriptor();
100         loader = container.getClassLoader();
101         beanClassName = ejbDesc.getEjbImplClassName();
102
103         this.beanClass = loader.loadClass(beanClassName);
104         buildInterceptorChain();
105         if (_logger.isLoggable(Level.FINE)) {
106             _logger.log(Level.FINE, "InterceptorManager: " + toString());
107         }
108     }
109
110     public Object JavaDoc[] createInterceptorInstances() {
111         int size = serializableInterceptorClasses.length;
112         Object JavaDoc[] interceptors = new Object JavaDoc[size];
113         for (int index = 0; index < size; index++) {
114             Class JavaDoc clazz = serializableInterceptorClasses[index];
115             try {
116                 interceptors[index] = clazz.newInstance();
117             } catch (IllegalAccessException JavaDoc illEx) {
118                 throw new RuntimeException JavaDoc(illEx);
119             } catch (InstantiationException JavaDoc instEx) {
120                 throw new RuntimeException JavaDoc(instEx);
121             }
122         }
123
124         return interceptors;
125     }
126
127     public InterceptorChain getAroundInvokeChain(MethodDescriptor mDesc, Method JavaDoc beanMethod) {
128         List<EjbInterceptor> list = ejbDesc.getAroundInvokeInterceptors(mDesc);
129         ArrayList<AroundInvokeInterceptor> interceptors =
130                 new ArrayList<AroundInvokeInterceptor>();
131         for (EjbInterceptor interceptor : list) {
132             String JavaDoc className = interceptor.getInterceptorClassName();
133             Set<LifecycleCallbackDescriptor> aroundInvokeDescs =
134                 interceptor.getAroundInvokeDescriptors();
135             if(aroundInvokeDescs.isEmpty() ) {
136                 continue;
137             }
138
139             List<LifecycleCallbackDescriptor> orderedAIInterceptors =
140                 new ArrayList<LifecycleCallbackDescriptor>();
141             try {
142                 orderedAIInterceptors = interceptor.getOrderedAroundInvokeDescriptors(loader);
143             } catch (Exception JavaDoc e) {
144                throw new IllegalStateException JavaDoc("No AroundInvokeIntercetpors found "
145                    + " on class " + className, e);
146             }
147
148             Iterator<LifecycleCallbackDescriptor> aiIterator = orderedAIInterceptors.iterator();
149             while (aiIterator.hasNext()) {
150                 LifecycleCallbackDescriptor aroundInvokeDesc = aiIterator.next();
151                 
152                 Method JavaDoc method = null;
153                 try {
154                     method = aroundInvokeDesc.getLifecycleCallbackMethodObject(loader);
155                 } catch(Exception JavaDoc e) {
156                    throw new IllegalStateException JavaDoc("No callback method of name " +
157                            aroundInvokeDesc.getLifecycleCallbackMethod()
158                    + " found on class " + className, e);
159                 }
160
161                 if (interceptor.getFromBeanClass()) {
162                     interceptors.add(new BeanAroundInvokeInterceptor(method));
163                 } else {
164                     Integer JavaDoc bigInt = instanceIndexMap.get(className);
165                     int index = (bigInt == null) ? -1 : bigInt;
166                     if (index == -1) {
167                         throw new IllegalStateException JavaDoc(getInternalErrorString(className));
168                     }
169                     Class JavaDoc clazz = interceptorClasses[index];
170                     _logger.log(Level.FINE, "*[md.getDeclaredMethod() => "
171                                 + method + " FOR CLAZZ: " + clazz);
172                     interceptors.add(new AroundInvokeInterceptor(index, method));
173                 }
174             }
175         }
176
177         AroundInvokeInterceptor[] inter = interceptors.toArray(
178                 new AroundInvokeInterceptor[interceptors.size()]);
179         return new AroundInvokeChainImpl(container, inter);
180     }
181
182     public boolean hasInterceptors() {
183         return this.methodInterceptorsExists;
184     }
185
186     public Object JavaDoc intercept(Invocation inv)
187             throws Throwable JavaDoc {
188         return inv.getInterceptorChain().invokeNext(0, inv);
189     }
190
191     public boolean intercept(CallbackType eventType, EJBContextImpl ctx)
192             throws Throwable JavaDoc {
193
194         CallbackChainImpl chain = null;
195         switch (eventType) {
196             case POST_CONSTRUCT:
197             case PRE_PASSIVATE:
198             case POST_ACTIVATE:
199             case PRE_DESTROY:
200                 chain = callbackChain[eventType.ordinal()];
201                 CallbackInvocationContext invContext = new
202                     CallbackInvocationContext(ctx, chain);
203                 if (chain != null) {
204                     chain.invokeNext(0, invContext);
205                 }
206                 break;
207             default:
208                 throw new IllegalStateException JavaDoc("Invalid event type");
209         }
210
211         return true;
212     }
213
214     private void buildInterceptorChain()
215             throws ClassNotFoundException JavaDoc, Exception JavaDoc {
216         initInterceptorClassNames();
217         initCallbackIndices();
218     }
219
220     private void initInterceptorClassNames()
221             throws ClassNotFoundException JavaDoc, Exception JavaDoc {
222         Set<String JavaDoc> interceptorClassNames = ejbDesc.getInterceptorClassNames();
223         int size = interceptorClassNames.size();
224         interceptorClasses = new Class JavaDoc[size];
225         serializableInterceptorClasses = new Class JavaDoc[size];
226         int index = 0;
227         for (String JavaDoc className : interceptorClassNames) {
228             Class JavaDoc interClass = loader.loadClass(className);
229             interceptorClasses[index] = interClass;
230             serializableInterceptorClasses[index] = interClass;
231             instanceIndexMap.put(className, index);
232             if (!Serializable JavaDoc.class.isAssignableFrom(interClass)) {
233                 serializableInterceptorClasses[index] =
234                     EJBUtils.loadGeneratedSerializableClass(loader, className);
235             }
236             index++;
237         }
238         methodInterceptorsExists = interceptorClassNames.size() > 0;
239
240         if (ejbDesc.hasAroundInvokeMethod()) {
241             methodInterceptorsExists = true;
242         }
243         instanceIndexMap.put(beanClassName, index++);
244     }
245
246     private void initCallbackIndices()
247             throws ClassNotFoundException JavaDoc, Exception JavaDoc {
248
249         int size = CallbackType.values().length;
250         ArrayList[] callbacks = new ArrayList[size];
251         boolean scanFor2xLifecycleMethods = true;
252
253         for (CallbackType eventType : CallbackType.values()) {
254             int index = eventType.ordinal();
255             callbacks[index] = new ArrayList<CallbackInterceptor>();
256             boolean scanForCallbacks = true;
257             if (! (ejbDesc instanceof EjbSessionDescriptor)) {
258                 if ((eventType == CallbackType.PRE_PASSIVATE) ||
259                         (eventType == CallbackType.POST_ACTIVATE)) {
260                     scanForCallbacks = false;
261                 }
262             }
263
264             if (scanForCallbacks) {
265                 List<EjbInterceptor> callbackList = ejbDesc.getCallbackInterceptors(eventType);
266                 for (EjbInterceptor callback : callbackList) {
267                     List<CallbackInterceptor> inters = createCallbackInterceptors(eventType, callback);
268                     for (CallbackInterceptor inter : inters) {
269                         callbacks[index].add(inter);
270                     }
271                 }
272             }
273
274             if (callbacks[index].size() > 0) {
275                 scanFor2xLifecycleMethods = false;
276             }
277         }
278
279         if (scanFor2xLifecycleMethods) {
280             load2xLifecycleMethods(callbacks);
281         }
282
283         callbackChain = new CallbackChainImpl[size];
284         for (CallbackType eventType : CallbackType.values()) {
285             int index = eventType.ordinal();
286             CallbackInterceptor[] interceptors = (CallbackInterceptor[])
287                     callbacks[index].toArray(new CallbackInterceptor[callbacks[index].size()]);
288             callbackChain[index] = new CallbackChainImpl(container, interceptors);
289         }
290
291     }
292
293     private List<CallbackInterceptor> createCallbackInterceptors(CallbackType eventType,
294                                                           EjbInterceptor inter) throws Exception JavaDoc {
295         List<CallbackInterceptor> callbackList = new ArrayList<CallbackInterceptor>();
296         
297         List<LifecycleCallbackDescriptor> orderedCallbackMethods =
298             inter.getOrderedCallbackDescriptors(eventType, loader);
299
300         String JavaDoc className = inter.getInterceptorClassName();
301
302
303         for (LifecycleCallbackDescriptor callbackDesc : orderedCallbackMethods) {
304             Method JavaDoc method = null;
305             try {
306                 method = callbackDesc.getLifecycleCallbackMethodObject(loader);
307             } catch(Exception JavaDoc e) {
308                 throw new IllegalStateException JavaDoc("No callback method of name " +
309                    callbackDesc.getLifecycleCallbackMethod()
310                    + " found on class " + className, e);
311         }
312
313
314             CallbackInterceptor interceptor = null;
315             if (inter.getFromBeanClass()) {
316                 interceptor = new BeanCallbackInterceptor(method);
317             } else {
318                 Integer JavaDoc bigInt = instanceIndexMap.get(className);
319                 int index = (bigInt == null) ? -1 : bigInt;
320                 if (index == -1) {
321                     throw new IllegalStateException JavaDoc(getInternalErrorString(className));
322                 }
323                 interceptor = new CallbackInterceptor(index, method);
324             }
325             callbackList.add(interceptor);
326         }
327         return callbackList;
328     }
329
330
331     private void load2xLifecycleMethods(ArrayList<CallbackInterceptor>[] metaArray) {
332
333         if (javax.ejb.EnterpriseBean JavaDoc.class.isAssignableFrom(beanClass)) {
334             int sz = lcAnnotationClasses.length;
335             for (int i = 0; i < sz; i++) {
336                 if (pre30LCMethodNames[i] == null) {
337                     continue;
338                 }
339                 try {
340                     Method JavaDoc method = beanClass.getMethod(
341                             pre30LCMethodNames[i], (Class JavaDoc[]) null);
342                     if (method != null) {
343                         CallbackInterceptor meta =
344                                 new BeanCallbackInterceptor(method);
345                         metaArray[i].add(meta);
346                         _logger.log(Level.FINE, "**## bean has 2.x LM: " + meta);
347                     }
348                 } catch (NoSuchMethodException JavaDoc nsmEx) {
349                     //TODO: Log exception
350
//Error for a 2.x bean????
351
}
352             }
353         }
354     }
355
356     public String JavaDoc toString() {
357         StringBuilder JavaDoc sbldr = new StringBuilder JavaDoc();
358         sbldr.append("##########################################################\n");
359         sbldr.append("InterceptorManager<").append(beanClassName).append("> has ")
360                 .append(interceptorClasses.length).append(" interceptors");
361         sbldr.append("\n\tbeanClassName: ").append(beanClassName);
362         sbldr.append("\n\tInterceptors: ");
363         for (Class JavaDoc clazz : interceptorClasses) {
364             sbldr.append("\n\t\t").append(clazz.getName());
365         }
366         sbldr.append("\n\tCallback Interceptors: ");
367         for (int i = 0; i < lcAnnotationClasses.length; i++) {
368             CallbackChainImpl chain = callbackChain[i];
369             sbldr.append("\n\t").append(i)
370                     .append(": ").append(lcAnnotationClasses[i]);
371             sbldr.append("\n\t\t").append(chain.toString());
372         }
373         sbldr.append("\n");
374         sbldr.append("##########################################################\n");
375         return sbldr.toString();
376     }
377
378     private String JavaDoc getInternalErrorString(String JavaDoc className) {
379         StringBuilder JavaDoc sbldr = new StringBuilder JavaDoc("Internal error: ");
380         sbldr.append(" className: ").append(className)
381                 .append(" is neither a bean class (")
382                 .append(beanClassName).append(") nor an ")
383                 .append("interceptor class (");
384         for (Class JavaDoc cn : interceptorClasses) {
385             sbldr.append(cn.getName()).append("; ");
386         }
387         sbldr.append(")");
388         _logger.log(Level.INFO, "++ : " + sbldr.toString());
389         return sbldr.toString();
390     }
391
392 }
393
394 class AroundInvokeChainImpl
395         implements InterceptorChain {
396     enum ChainType {
397         METHOD, CALLBACK}
398
399     ;
400
401     protected BaseContainer container;
402     protected AroundInvokeInterceptor[] interceptors;
403     protected int size;
404
405     protected AroundInvokeChainImpl(BaseContainer container,
406                                     AroundInvokeInterceptor[] interceptors) {
407         this.container = container;
408         this.interceptors = interceptors;
409         this.size = (interceptors == null) ? 0 : interceptors.length;
410     }
411
412     public Object JavaDoc invokeNext(int index, Invocation inv)
413             throws Throwable JavaDoc {
414         return (index < size)
415                 ? interceptors[index].intercept(inv)
416                 : container.invokeBeanMethod(inv);
417     }
418
419     public String JavaDoc toString() {
420         StringBuilder JavaDoc bldr = new StringBuilder JavaDoc();
421         for (AroundInvokeInterceptor inter : interceptors) {
422             bldr.append("\n\t").append(inter);
423         }
424
425         return bldr.toString();
426     }
427 }
428
429 class CallbackChainImpl {
430
431     protected BaseContainer container;
432     protected CallbackInterceptor[] interceptors;
433     protected int size;
434
435     CallbackChainImpl(BaseContainer container,
436                       CallbackInterceptor[] interceptors) {
437         this.container = container;
438         this.interceptors = interceptors;
439         this.size = (interceptors == null) ? 0 : interceptors.length;
440     }
441
442     public Object JavaDoc invokeNext(int index, CallbackInvocationContext invContext)
443             throws Throwable JavaDoc {
444
445         Object JavaDoc result = null;
446
447         if (index < size) {
448             result = interceptors[index].intercept(invContext);
449         }
450
451         return result;
452     }
453
454     public String JavaDoc toString() {
455         StringBuilder JavaDoc bldr = new StringBuilder JavaDoc("CallbackInterceptorChainImpl");
456         for (CallbackInterceptor inter : interceptors) {
457             bldr.append("\n\t\t").append(inter);
458         }
459
460         return bldr.toString();
461     }
462 }
463
464 class AroundInvokeInterceptor {
465     protected int index;
466     protected Method JavaDoc method;
467
468     AroundInvokeInterceptor(int index, Method JavaDoc method) {
469         this.index = index;
470         this.method = method;
471     }
472
473     Object JavaDoc intercept(final Invocation invCtx) throws Throwable JavaDoc {
474         try {
475             final Object JavaDoc[] interceptors = ((EJBContextImpl) invCtx.context)
476                     .getInterceptorInstances();
477             // Wrap actual value insertion in doPrivileged to
478
// allow for private/protected field access.
479
return java.security.AccessController
480                     .doPrivileged(new java.security.PrivilegedExceptionAction JavaDoc() {
481                         public java.lang.Object JavaDoc run() throws Exception JavaDoc {
482                             if (!method.isAccessible()) {
483                                 method.setAccessible(true);
484                             }
485                             return method.invoke(interceptors[index], invCtx);
486                         }
487                     });
488         } catch (java.lang.reflect.InvocationTargetException JavaDoc invEx) {
489             throw invEx.getCause();
490         } catch (java.security.PrivilegedActionException JavaDoc paEx) {
491             Throwable JavaDoc th = paEx.getCause();
492             if (th.getCause() != null) {
493                 throw th.getCause();
494             }
495             throw th;
496         }
497     }
498
499     public String JavaDoc toString() {
500         return "[" + index + "]: " + method;
501     }
502
503 }
504
505 class BeanAroundInvokeInterceptor
506         extends AroundInvokeInterceptor {
507     private static final Object JavaDoc[] NULL_ARGS = null;
508
509     BeanAroundInvokeInterceptor(Method JavaDoc method) {
510         super(-1, method);
511     }
512
513     Object JavaDoc intercept(final Invocation invCtx) throws Throwable JavaDoc {
514         try {
515             // Wrap actual value insertion in doPrivileged to
516
// allow for private/protected field access.
517
return java.security.AccessController
518                     .doPrivileged(new java.security.PrivilegedExceptionAction JavaDoc() {
519                         public java.lang.Object JavaDoc run() throws Exception JavaDoc {
520                             if (!method.isAccessible()) {
521                                 method.setAccessible(true);
522                             }
523                             return method.invoke(invCtx.getTarget(), invCtx);
524                         }
525                     });
526         } catch (java.lang.reflect.InvocationTargetException JavaDoc invEx) {
527             throw invEx.getCause();
528         } catch (java.security.PrivilegedActionException JavaDoc paEx) {
529             Throwable JavaDoc th = paEx.getCause();
530             if (th.getCause() != null) {
531                 throw th.getCause();
532             }
533             throw th;
534         }
535     }
536 }
537
538 class CallbackInterceptor {
539     protected int index;
540     protected Method JavaDoc method;
541
542     CallbackInterceptor(int index, Method JavaDoc method) {
543         this.index = index;
544         this.method = method;
545     }
546
547     Object JavaDoc intercept(final CallbackInvocationContext invContext)
548         throws Throwable JavaDoc {
549         try {
550             EJBContextImpl ejbContextImpl = (EJBContextImpl)
551                 invContext.getEJBContext();
552             final Object JavaDoc[] interceptors = ejbContextImpl
553                     .getInterceptorInstances();
554             // Wrap actual value insertion in doPrivileged to
555
// allow for private/protected field access.
556
return java.security.AccessController
557                     .doPrivileged(new java.security.PrivilegedExceptionAction JavaDoc() {
558                         public java.lang.Object JavaDoc run() throws Exception JavaDoc {
559                             if (!method.isAccessible()) {
560                                 method.setAccessible(true);
561                             }
562                             return method.invoke(interceptors[index],
563                                                  invContext);
564                         }
565                     });
566         } catch (java.lang.reflect.InvocationTargetException JavaDoc invEx) {
567             throw invEx.getCause();
568         } catch (java.security.PrivilegedActionException JavaDoc paEx) {
569             Throwable JavaDoc th = paEx.getCause();
570             if (th.getCause() != null) {
571                 throw th.getCause();
572             }
573             throw th;
574         }
575     }
576
577     public String JavaDoc toString() {
578         return "callback[" + index + "]: " + method;
579     }
580 }
581
582 class BeanCallbackInterceptor
583         extends CallbackInterceptor {
584     private static final Object JavaDoc[] NULL_ARGS = null;
585
586     BeanCallbackInterceptor(Method JavaDoc method) {
587         super(-1, method);
588     }
589
590     Object JavaDoc intercept(final CallbackInvocationContext invContext)
591         throws Throwable JavaDoc {
592         try {
593             // Wrap actual value insertion in doPrivileged to
594
// allow for private/protected field access.
595
return java.security.AccessController
596                     .doPrivileged(new java.security.PrivilegedExceptionAction JavaDoc() {
597                         public java.lang.Object JavaDoc run() throws Exception JavaDoc {
598                             if (!method.isAccessible()) {
599                                 method.setAccessible(true);
600                             }
601                             method.invoke(invContext.getTarget(),
602                                     NULL_ARGS);
603                             return invContext.proceed();
604                         }
605                     });
606         } catch (java.lang.reflect.InvocationTargetException JavaDoc invEx) {
607             throw invEx.getCause();
608         } catch (java.security.PrivilegedActionException JavaDoc paEx) {
609             Throwable JavaDoc th = paEx.getCause();
610             if (th.getCause() != null) {
611                 throw th.getCause();
612             }
613             throw th;
614         }
615     }
616
617     public String JavaDoc toString() {
618         return "beancallback[" + index + "]: " + method;
619     }
620 }
621
622
Popular Tags