KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > reflection > ReflectionAspect


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.aop.reflection;
23
24 import gnu.trove.TLongObjectHashMap;
25 import org.jboss.aop.Advised;
26 import org.jboss.aop.AspectManager;
27 import org.jboss.aop.ClassAdvisor;
28 import org.jboss.aop.ConByConInfo;
29 import org.jboss.aop.ConByMethodInfo;
30 import org.jboss.aop.ConstructorInfo;
31 import org.jboss.aop.FieldInfo;
32 import org.jboss.aop.MethodByConInfo;
33 import org.jboss.aop.MethodByMethodInfo;
34 import org.jboss.aop.advice.Interceptor;
35 import org.jboss.aop.instrument.Untransformable;
36 import org.jboss.aop.joinpoint.Invocation;
37 import org.jboss.aop.joinpoint.MethodCalledByConstructorInvocation;
38 import org.jboss.aop.joinpoint.MethodCalledByMethodInvocation;
39 import org.jboss.aop.util.MethodHashing;
40
41 import java.lang.reflect.Constructor JavaDoc;
42 import java.lang.reflect.Field JavaDoc;
43 import java.lang.reflect.Method JavaDoc;
44 import java.lang.reflect.Modifier JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.HashMap JavaDoc;
47 import java.util.Iterator JavaDoc;
48 import java.util.regex.Matcher JavaDoc;
49 import java.util.regex.Pattern JavaDoc;
50
51 /**
52  * @author <a HREF="mailto:kabirkhan@bigfoot.com">Kabir Khan</a>
53  * <p/>
54  * Aspect to intercept calls to the reflection API. Calls to
55  * Class.newInstance(), Field.setXXX(), Field.getXXX(), Constructor.newInstance()
56  * don't get intercepted even though the underlying constructor/field
57  * might have an advice associated with it. This class adds advices to help intercept these
58  * calls and attach to the original chains on the caller or target object. Method.invoke()
59  * works for chains on the target object "out of the box", but bypasses caller chains.
60  * <p/>
61  * <BR>
62  * <BR>
63  * Also, Class.getMethods(), Class.getDeclaredMethods(), Class.getInterfaces(),
64  * and Class.getDeclaredFields() return extra methods/interfaces/fields added
65  * by the AOP framework. The aspects contained here cleans this information.
66  */

67 public class ReflectionAspect
68 {
69    // Constants -----------------------------------------------------
70

71    // Attributes ----------------------------------------------------
72

73    // Static --------------------------------------------------------
74

75    private static Pattern JavaDoc fieldGetPattern =
76    Pattern.compile("get(|Boolean|Byte|Char|Double|Float|Int|Long|Short)?");
77
78    private static Pattern JavaDoc fieldSetPattern =
79    Pattern.compile("set(|Boolean|Byte|Char|Double|Float|Int|Long|Short)?");
80
81    private static Pattern JavaDoc accessMethodPattern = Pattern.compile("access[$](\\d)+");
82    
83    // Constructors --------------------------------------------------
84

85    public ReflectionAspect()
86    {
87    }
88    
89    // Public --------------------------------------------------------
90

91    /**
92     * Advice for calls to Class.newInstance() and Constructor.newInstance(). Intended use is for
93     * caller pointcuts. If you wish to handle the intercepted calls, override interceptConstructor.
94     *
95     * @param invocation
96     * @return result of invocation
97     * @throws Throwable
98     * @see ReflectionAspect#interceptConstructor(Invocation, Constructor, Object[])
99     */

100    public Object JavaDoc interceptNewInstance(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
101    {
102
103       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
104       Object JavaDoc targetObject = invocation.getTargetObject();
105       Object JavaDoc[] args = invocation.getArguments();
106
107       return interceptNewInstance(invocation, reflectionMethod, targetObject, args);
108    }
109
110    /**
111     * Advice for calls to Class.newInstance() and Constructor.newInstance(). Intended use is for
112     * caller pointcuts. If you wish to handle the intercepted calls, override interceptConstructor.
113     *
114     * @param invocation
115     * @return result of invocation
116     * @throws Throwable
117     * @see ReflectionAspect#interceptConstructor(Invocation, Constructor, Object[])
118     */

119    public Object JavaDoc interceptNewInstance(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
120    {
121
122       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
123       Object JavaDoc targetObject = invocation.getTargetObject();
124       Object JavaDoc[] args = invocation.getArguments();
125
126       return interceptNewInstance(invocation, reflectionMethod, targetObject, args);
127    }
128
129
130    /**
131     * Advice for calls to Method.invoke(). Intended use is for
132     * caller pointcuts. If you wish to handle the intercepted calls, override interceptMethod.
133     *
134     * @param invocation
135     * @return result of invocation
136     * @throws Throwable
137     * @see ReflectionAspect#interceptMethod(Invocation, Object, Method, Object[])
138     */

139    public Object JavaDoc interceptMethodInvoke(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
140    {
141
142       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
143       Object JavaDoc targetObject = invocation.getTargetObject();
144       Object JavaDoc[] args = invocation.getArguments();
145
146       return interceptMethodInvoke(invocation, reflectionMethod, targetObject, args);
147    }
148
149    /**
150     * Advice for calls to Class.newInstance() and Constructor.newInstance(). Intended use is for
151     * caller pointcuts. If you wish to handle the intercepted calls, override interceptMethod.
152     *
153     * @param invocation
154     * @return result of invocation
155     * @throws Throwable
156     * @see ReflectionAspect#interceptMethod(Invocation, Object, Method, Object[])
157     */

158    public Object JavaDoc interceptMethodInvoke(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
159    {
160
161       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
162       Object JavaDoc targetObject = invocation.getTargetObject();
163       Object JavaDoc[] args = invocation.getArguments();
164
165       return interceptMethodInvoke(invocation, reflectionMethod, targetObject, args);
166    }
167
168
169    /**
170     * Advice for calls to Field.setXXX(). Intended use is for caller pointcuts. If you wish to handle
171     * the intercepted calls, override interceptFieldWrite.
172     *
173     * @param invocation
174     * @return result of invocation
175     * @throws Throwable
176     * @see ReflectionAspect#interceptFieldWrite(Invocation, Field, Object, Object)
177     */

178    public Object JavaDoc interceptFieldSet(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
179    {
180
181       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
182       Object JavaDoc targetObject = invocation.getTargetObject();
183       Object JavaDoc[] args = invocation.getArguments();
184
185       return interceptFieldSet(invocation, reflectionMethod, targetObject, args);
186    }
187
188    /**
189     * Advice for calls to Field.setXXX(). Intended use is for caller pointcuts. If you wish to handle
190     * the intercepted calls, override interceptFieldWrite.
191     *
192     * @param invocation
193     * @return result of invocation
194     * @throws Throwable
195     * @see ReflectionAspect#interceptFieldWrite(Invocation, Field, Object, Object)
196     */

197    public Object JavaDoc interceptFieldSet(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
198    {
199
200       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
201       Object JavaDoc targetObject = invocation.getTargetObject();
202       Object JavaDoc[] args = invocation.getArguments();
203
204       return interceptFieldSet(invocation, reflectionMethod, targetObject, args);
205    }
206
207    /**
208     * Advice for calls to Field.getXXX(). Intended use is for caller pointcuts. If you wish to handle
209     * the intercepted calls, override interceptFieldRead.
210     *
211     * @param invocation
212     * @return The value of the field (or whatever you choose)
213     * @throws Throwable
214     * @see ReflectionAspect#interceptFieldRead(Invocation, Field, Object)
215     */

216    public Object JavaDoc interceptFieldGet(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
217    {
218
219       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
220       Object JavaDoc targetObject = invocation.getTargetObject();
221       Object JavaDoc[] args = invocation.getArguments();
222
223       return interceptFieldGet(invocation, reflectionMethod, targetObject, args);
224    }
225
226
227    /**
228     * Advice for calls to Field.getXXX(). Intended use is for caller pointcuts. If you wish to handle
229     * the intercepted calls, override interceptFieldRead.
230     *
231     * @param invocation
232     * @return The value of the field (or whatever you choose)
233     * @throws Throwable
234     * @see ReflectionAspect#interceptFieldRead(Invocation, Field, Object)
235     */

236    public Object JavaDoc interceptFieldGet(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
237    {
238
239
240       Method JavaDoc reflectionMethod = invocation.getCalledMethod();
241       Object JavaDoc targetObject = invocation.getTargetObject();
242       Object JavaDoc[] args = invocation.getArguments();
243
244       return interceptFieldGet(invocation, reflectionMethod, targetObject, args);
245    }
246
247
248    /**
249     * Advice for calls to Class.getDeclaredMethods(). Cleans methods that get added to the
250     * class by the AOP framework (Methods introduced by introductions/mixin classes will
251     * still be returned). Intended use is for caller pointcuts.
252     *
253     * @param invocation The invocation
254     * @return java.lang.reflect.Method[] containing the declared methods of the class
255     * @throws Throwable
256     * @see Class#getDeclaredMethods()()
257     */

258    public final Object JavaDoc interceptGetDeclaredMethods(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
259    {
260
261       Object JavaDoc targetObject = invocation.getTargetObject();
262       return interceptGetDeclaredMethods((Class JavaDoc) targetObject);
263    }
264
265    /**
266     * Advice for calls to Class.getDeclaredMethods(). Cleans methods that get added to the
267     * class by the AOP framework (Methods introduced by introductions/mixin classes will
268     * still be returned). Intended use is for caller pointcuts.
269     *
270     * @param invocation The invocation
271     * @return java.lang.reflect.Method[] containing the declared methods of the class
272     * @throws Throwable
273     * @see Class#getDeclaredMethods()()
274     */

275    public final Object JavaDoc interceptGetDeclaredMethods(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
276    {
277
278       Object JavaDoc targetObject = invocation.getTargetObject();
279       return interceptGetDeclaredMethods((Class JavaDoc) targetObject);
280    }
281
282    /**
283     * Advice for calls to Class.getDeclaredMethod(). Cleans methods that get added to the
284     * class by the AOP framework (Methods introduced by introductions/mixin classes will
285     * still be returned). Intended use is for caller pointcuts.
286     *
287     * @param invocation The invocation
288     * @return java.lang.reflect.Method the declared method
289     * @throws Throwable
290     * @see Class#getDeclaredMethod()()
291     */

292    public final Object JavaDoc interceptGetDeclaredMethod(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
293    {
294
295       Object JavaDoc targetObject = invocation.getTargetObject();
296       Object JavaDoc[] args = invocation.getArguments();
297       return interceptGetDeclaredMethod((Class JavaDoc) targetObject, args);
298    }
299
300    /**
301     * Advice for calls to Class.getDeclaredMethod(). Cleans methods that get added to the
302     * class by the AOP framework (Methods introduced by introductions/mixin classes will
303     * still be returned). Intended use is for caller pointcuts.
304     *
305     * @param invocation The invocation
306     * @return java.lang.reflect.Method the declared method
307     * @throws Throwable
308     * @see Class#getDeclaredMethod()()
309     */

310    public final Object JavaDoc interceptGetDeclaredMethod(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
311    {
312
313       Object JavaDoc targetObject = invocation.getTargetObject();
314       Object JavaDoc[] args = invocation.getArguments();
315       return interceptGetDeclaredMethod((Class JavaDoc) targetObject, args);
316    }
317
318    /**
319     * Advice for calls to Class.getDeclaredMethod(). Cleans methods that get added to the
320     * class by the AOP framework (Methods introduced by introductions/mixin classes will
321     * still be returned). Intended use is for caller pointcuts.
322     *
323     * @param invocation The invocation
324     * @return java.lang.reflect.Method[] The methods of the class
325     * @throws Throwable
326     * @see Class#getDeclaredMethod()()
327     */

328    public final Object JavaDoc interceptGetMethods(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
329    {
330
331       Object JavaDoc targetObject = invocation.getTargetObject();
332       return interceptGetMethods((Class JavaDoc) targetObject);
333    }
334
335    /**
336     * Advice for calls to Class.getMethods(). Cleans methods that get added to the
337     * class by the AOP framework (Methods introduced by introductions/mixin classes will
338     * still be returned). Intended use is for caller pointcuts.
339     *
340     * @param invocation The invocation
341     * @return java.lang.reflect.Method[] The methods of the class
342     * @throws Throwable
343     * @see Class#getMethods()()
344     */

345    public final Object JavaDoc interceptGetMethods(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
346    {
347
348       Object JavaDoc targetObject = invocation.getTargetObject();
349       return interceptGetMethods((Class JavaDoc) targetObject);
350    }
351
352    /**
353     * Advice for calls to Class.getMethod(). Cleans methods that get added to the
354     * class by the AOP framework (Methods introduced by introductions/mixin classes will
355     * still be returned). Intended use is for caller pointcuts.
356     *
357     * @param invocation The invocation
358     * @return java.lang.reflect.Method The method
359     * @throws Throwable
360     * @see Class#getDeclaredMethod()()
361     */

362    public final Object JavaDoc interceptGetMethod(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
363    {
364
365       Object JavaDoc targetObject = invocation.getTargetObject();
366       Object JavaDoc[] args = invocation.getArguments();
367       return interceptGetMethod((Class JavaDoc) targetObject, args);
368    }
369
370    /**
371     * Advice for calls to Class.getMethod(). Cleans methods that get added to the
372     * class by the AOP framework (Methods introduced by introductions/mixin classes will
373     * still be returned). Intended use is for caller pointcuts.
374     *
375     * @param invocation The invocation
376     * @return java.lang.reflect.Method The method
377     * @throws Throwable
378     * @see Class#getDeclaredMethod()()
379     */

380    public final Object JavaDoc interceptGetMethod(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
381    {
382
383       Object JavaDoc targetObject = invocation.getTargetObject();
384       Object JavaDoc[] args = invocation.getArguments();
385       return interceptGetMethod((Class JavaDoc) targetObject, args);
386    }
387
388    /**
389     * Advice for calls to Class.getInterfaces(). Cleans interfaces that get added to the
390     * class by the AOP framework. (Interfaces introduced by introductions will
391     * still be returned). Intended use is for caller pointcuts.
392     *
393     * @param invocation The invocation
394     * @return java.lang.Class[] containing the interfaces of the class
395     * @throws Throwable
396     * @see Class#getInterfaces()
397     */

398    public final Object JavaDoc interceptGetInterfaces(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
399    {
400
401       Object JavaDoc targetObject = invocation.getTargetObject();
402       return interceptGetInterfaces((Class JavaDoc) targetObject);
403    }
404
405    /**
406     * Advice for calls to Class.getInterfaces(). Cleans interfaces that get added to the
407     * class by the AOP framework. (Interfaces introduced by introductions will
408     * still be returned). Intended use is for caller pointcuts.
409     *
410     * @param invocation The invocation
411     * @return java.lang.Class[] containing the interfaces of the class
412     * @throws Throwable
413     * @see Class#getInterfaces()
414     */

415    public final Object JavaDoc interceptGetInterfaces(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
416    {
417
418       Object JavaDoc targetObject = invocation.getTargetObject();
419       return interceptGetInterfaces((Class JavaDoc) targetObject);
420    }
421
422    /**
423     * Advice for calls to Class.getDeclaredClasses(). Cleans inner classes that get added to the
424     * class by the AOP framework. Intended use is for caller pointcuts.
425     *
426     * @param invocation The invocation
427     * @return java.lang.Class[] containing the Class objects representing inner classes of the class
428     * @throws Throwable
429     * @see Class#getDeclaredClasses()
430     */

431    public final Object JavaDoc interceptGetDeclaredClasses(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
432    {
433
434       Object JavaDoc targetObject = invocation.getTargetObject();
435       return interceptGetDeclaredClasses((Class JavaDoc) targetObject);
436    }
437
438    /**
439     * Advice for calls to Class.getDeclaredClasses(). Cleans inner classes that get added to the
440     * class by the AOP framework. Intended use is for caller pointcuts.
441     *
442     * @param invocation The invocation
443     * @return java.lang.Class[] containing the Class objects representing inner classes of the class
444     * @throws Throwable
445     * @see Class#getDeclaredClasses()
446     */

447    public final Object JavaDoc interceptGetDeclaredClasses(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
448    {
449
450       Object JavaDoc targetObject = invocation.getTargetObject();
451       return interceptGetDeclaredClasses((Class JavaDoc) targetObject);
452    }
453
454    /**
455     * Advice for calls to Class.getClasses(). Cleans inner classes that get added to the
456     * class by the AOP framework. Intended use is for caller pointcuts.
457     * Extra stuff only seems to get returned when using JRockit
458     *
459     * @param invocation The invocation
460     * @return java.lang.Class[] containing the Class objects representing inner classes of the class
461     * @throws Throwable
462     * @see Class#getClasses()
463     */

464    public final Object JavaDoc interceptGetClasses(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
465    {
466
467       Object JavaDoc targetObject = invocation.getTargetObject();
468       return interceptGetClasses((Class JavaDoc) targetObject);
469    }
470
471    /**
472     * Advice for calls to Class.getClasses(). Cleans inner classes that get added to the
473     * class by the AOP framework. Intended use is for caller pointcuts.
474     * Extra stuff only seems to get returned when using JRockit
475     *
476     * @param invocation The invocation
477     * @return java.lang.Class[] containing the Class objects representing inner classes of the class
478     * @throws Throwable
479     * @see Class#getDeclaredClasses()
480     */

481    public final Object JavaDoc interceptGetClasses(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
482    {
483       Object JavaDoc targetObject = invocation.getTargetObject();
484       return interceptGetClasses((Class JavaDoc) targetObject);
485    }
486
487    /**
488     * Advice for calls to Class.getDeclaredFields(). Cleans fields that get added to the
489     * class by the AOP framework. Intended use is for caller pointcuts.
490     *
491     * @param invocation The invocation
492     * @return java.lang.reflect.Field[] containing the Fields of the class
493     * @throws Throwable
494     * @see Class#getDeclaredClasses()
495     */

496    public final Object JavaDoc interceptGetDeclaredFields(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
497    {
498
499       Object JavaDoc targetObject = invocation.getTargetObject();
500       return interceptGetDeclaredFields((Class JavaDoc) targetObject);
501    }
502
503    /**
504     * Advice for calls to Class.getDeclaredFields(). Cleans fields that get added to the
505     * class by the AOP framework. Intended use is for caller pointcuts.
506     *
507     * @param invocation The invocation
508     * @return java.lang.reflect.Field[] containing the Fields of the class
509     * @throws Throwable
510     * @see Class#getDeclaredFields()
511     */

512    public final Object JavaDoc interceptGetDeclaredFields(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
513    {
514
515       Object JavaDoc targetObject = invocation.getTargetObject();
516       return interceptGetDeclaredFields((Class JavaDoc) targetObject);
517    }
518
519    /**
520     * Advice for calls to Class.getDeclaredField(). Cleans fields that get added to the
521     * class by the AOP framework. Intended use is for caller pointcuts.
522     *
523     * @param invocation The invocation
524     * @return java.lang.reflect.Field The Field
525     * @throws Throwable
526     * @see Class#getDeclaredField()
527     */

528    public final Object JavaDoc interceptGetDeclaredField(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
529    {
530
531       Object JavaDoc targetObject = invocation.getTargetObject();
532       Object JavaDoc[] args = invocation.getArguments();
533       return interceptGetDeclaredField((Class JavaDoc) targetObject, args);
534    }
535
536    /**
537     * Advice for calls to Class.getDeclaredField(). Cleans fields that get added to the
538     * class by the AOP framework. Intended use is for caller pointcuts.
539     *
540     * @param invocation The invocation
541     * @return java.lang.reflect.Field[] The Field
542     * @throws Throwable
543     * @see Class#getDeclaredField()
544     */

545    public final Object JavaDoc interceptGetDeclaredField(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
546    {
547       Object JavaDoc targetObject = invocation.getTargetObject();
548       Object JavaDoc[] args = invocation.getArguments();
549       return interceptGetDeclaredField((Class JavaDoc) targetObject, args);
550    }
551
552    /**
553     * Advice for calls to Class.getFields(). Cleans fields that get added to the
554     * class by the AOP framework. Intended use is for caller pointcuts.
555     *
556     * @param invocation The invocation
557     * @return java.lang.reflect.Field[] containing the Fields of the class
558     * @throws Throwable
559     * @see Class#getFields()
560     */

561    public final Object JavaDoc interceptGetFields(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
562    {
563
564       //Nothing seems to get added
565
return invocation.invokeNext();
566    }
567
568    /**
569     * Advice for calls to Class.getFields(). Cleans fields that get added to the
570     * class by the AOP framework. Intended use is for caller pointcuts.
571     *
572     * @param invocation The invocation
573     * @return java.lang.reflect.Field[] containing the Fields of the class
574     * @throws Throwable
575     * @see Class#getFields()
576     */

577    public final Object JavaDoc interceptGetFields(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
578    {
579
580       //Nothing seems to get added
581
return invocation.invokeNext();
582    }
583
584    /**
585     * Advice for calls to Class.getDeclaredConstructors(). Cleans constructors that get added to the
586     * class by the AOP framework. Intended use is for caller pointcuts.
587     *
588     * @param invocation The invocation
589     * @return java.lang.reflect.Constructor[] containing the Constructors of the class
590     * @throws Throwable
591     * @see Class#getDeclaredConstructors()
592     */

593    public final Object JavaDoc interceptGetDeclaredConstructors(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
594    {
595
596       //Nothing seems to get added
597
return invocation.invokeNext();
598    }
599
600    /**
601     * Advice for calls to Class.getDeclaredConstructors(). Cleans constructors that get added to the
602     * class by the AOP framework. Intended use is for caller pointcuts.
603     *
604     * @param invocation The invocation
605     * @return java.lang.reflect.Constructor[] containing the Constructors of the class
606     * @throws Throwable
607     * @see Class#getDeclaredConstructors()
608     */

609    public final Object JavaDoc interceptGetDeclaredConstructors(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
610    {
611
612       //Nothing seems to get added
613
return invocation.invokeNext();
614    }
615
616    /**
617     * Advice for calls to Class.getDeclaredConstructor(). Cleans constructors that get added to the
618     * class by the AOP framework. Intended use is for caller pointcuts.
619     *
620     * @param invocation The invocation
621     * @return java.lang.reflect.Constructor[] The constructor
622     * @throws Throwable
623     * @see Class#getFields()
624     */

625    public final Object JavaDoc interceptGetDeclaredConstructor(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
626    {
627
628       //Nothing seems to get added
629
return invocation.invokeNext();
630    }
631
632    /**
633     * Advice for calls to Class.getDeclaredConstructor(). Cleans constructors that get added to the
634     * class by the AOP framework. Intended use is for caller pointcuts.
635     *
636     * @param invocation The invocation
637     * @return java.lang.reflect.Constructor[] The constructor
638     * @throws Throwable
639     * @see Class#getFields()
640     */

641    public final Object JavaDoc interceptGetDeclaredConstructor(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
642    {
643
644       //Nothing seems to get added
645
return invocation.invokeNext();
646    }
647
648    /**
649     * Advice for calls to Class.getConstructors(). Cleans fields that get added to the
650     * class by the AOP framework. Intended use is for caller pointcuts.
651     *
652     * @param invocation The invocation
653     * @return java.lang.Constructor[] containing the Constructors of the class
654     * @throws Throwable
655     * @see Class#getFields()
656     */

657    public final Object JavaDoc interceptGetConstructors(MethodCalledByConstructorInvocation invocation) throws Throwable JavaDoc
658    {
659
660       //Nothing seems to get added
661
return invocation.invokeNext();
662    }
663
664    /**
665     * Advice for calls to Class.getConstructors(). Cleans constructors that get added to the
666     * class by the AOP framework. Intended use is for caller pointcuts.
667     *
668     * @param invocation The invocation
669     * @return java.lang.Constructor[] containing the Constructors of the class
670     * @throws Throwable
671     * @see Class#getFields()
672     */

673    public final Object JavaDoc interceptGetConstructors(MethodCalledByMethodInvocation invocation) throws Throwable JavaDoc
674    {
675
676       //Nothing seems to get added
677
return invocation.invokeNext();
678    }
679    
680
681    // Z implementation ----------------------------------------------
682

683    // Y overrides ---------------------------------------------------
684

685    // Package protected ---------------------------------------------
686

687    // Protected -----------------------------------------------------
688

689    
690    /**
691     * Overridable advice for a Constructor.newInstance() or Class.newInstance() call.
692     * Default behaviour is to first try to attach to any caller advice chain. If that
693     * does not exist, try to attach to the advice chains on the target object. And
694     * if that does not exist to invoke the reflected constructor.
695     *
696     * @param invocation The invocation
697     * @param constructor The field on which we are calling set
698     * @param args The arguments for the constructor
699     * @return The new instance
700     * @throws Throwable
701     */

702    protected Object JavaDoc interceptConstructor(Invocation invocation, Constructor JavaDoc constructor, Object JavaDoc[] args) throws Throwable JavaDoc
703    {
704       return invokeOriginalChainIfExists(invocation, constructor, args);
705    }
706
707    /**
708     * Overridable advice for a Field.setXXX() call.
709     * Default behaviour is to first try to attach to the advice chains on the target object. And
710     * if that does not exist to invoke the reflected field read.
711     *
712     * @param invocation The invocation
713     * @param field The field on which we are calling set
714     * @param instance The instance on which we want to write a field
715     * @return The value of the field (or whatever you choose)
716     * @throws Throwable
717     */

718    protected Object JavaDoc interceptFieldRead(Invocation invocation, Field JavaDoc field, Object JavaDoc instance) throws Throwable JavaDoc
719    {
720       return invokeOriginalChainIfExists(invocation, field, instance);
721    }
722
723    /**
724     * Overridable advice for a Field.setXXX() call.
725     * Default behaviour is to first try attach to the advice chains on the target object. And
726     * if that does not exist to invoke the reflected field write.
727     *
728     * @param invocation The invocation
729     * @param field The field on which we are calling set
730     * @param instance The instance on which we want to read a field
731     * @param arg The value we want to set the field to
732     * @return result of invocation
733     * @throws Throwable
734     */

735    protected Object JavaDoc interceptFieldWrite(Invocation invocation, Field JavaDoc field, Object JavaDoc instance, Object JavaDoc arg) throws Throwable JavaDoc
736    {
737       return invokeOriginalChainIfExists(invocation, field, instance, arg);
738    }
739
740    /**
741     * Overridable advice for a Method.invoke() call.
742     * Default behaviour is to first try to attach to any caller advice chain. If that
743     * does not exist, try to attach to the advice chains on the target object. And
744     * if that does not exist to invoke the reflected method.
745     *
746     * @param invocation The invocation
747     * @param method The method on which we are calling set
748     * @param instance The instance on which we want to read a field
749     * @param arg The value we want to set the field to
750     * @return result of invocation
751     * @throws Throwable
752     */

753    protected Object JavaDoc interceptMethod(Invocation invocation, Method JavaDoc method, Object JavaDoc instance, Object JavaDoc[] args) throws Throwable JavaDoc
754    {
755       return invokeOriginalChainIfExists(invocation, method, instance, args);
756    }
757    
758    
759    // Private -------------------------------------------------------
760

761    private Object JavaDoc interceptNewInstance(Invocation invocation,
762                                        Method JavaDoc reflectionMethod,
763                                        Object JavaDoc targetObject,
764                                        Object JavaDoc[] args) throws Throwable JavaDoc
765    {
766       Class JavaDoc reflectionClass = targetObject.getClass();
767
768       if (reflectionClass.equals(Class JavaDoc.class))
769       {
770
771          //For our purposes Class.newInstance() can be made into a call to the empty constructor
772
Constructor JavaDoc constructor = ((Class JavaDoc) targetObject).getConstructor(new Class JavaDoc[0]);
773          return interceptConstructor(invocation, constructor, args);
774       }
775       else if (reflectionClass.equals(Constructor JavaDoc.class))
776       {
777
778          if (reflectionMethod.getName().equals("newInstance"))
779          {
780             //Object newObject = args[0];
781

782             Object JavaDoc[] constructorArgs;
783
784             int length = args.length;
785
786             if (length < 1)
787             {
788                constructorArgs = new Object JavaDoc[0];
789             }
790             else
791             {
792                constructorArgs = (Object JavaDoc[]) args[0];
793             }
794
795             Constructor JavaDoc constructor = (Constructor JavaDoc) targetObject;
796             return interceptConstructor(invocation, constructor, constructorArgs);
797          }
798       }
799
800       return invocation.invokeNext();
801    }
802
803    private Object JavaDoc interceptMethodInvoke(Invocation invocation,
804                                         Method JavaDoc reflectionMethod,
805                                         Object JavaDoc targetObject,
806                                         Object JavaDoc[] args) throws Throwable JavaDoc
807    {
808       Method JavaDoc method = (Method JavaDoc) invocation.getTargetObject();
809       if (reflectionMethod.getName().equals("invoke"))
810       {
811          Object JavaDoc instance = args[0];
812          return interceptMethod(invocation, method, instance, (Object JavaDoc[]) args[1]);
813       }
814       return invocation.invokeNext();
815    }
816
817    private Class JavaDoc[] interceptGetInterfaces(Class JavaDoc clazz)
818    {
819       Class JavaDoc[] interfaces = clazz.getInterfaces();
820       ArrayList JavaDoc cleanedInterfaces = new ArrayList JavaDoc(interfaces.length);
821
822       for (int i = 0; i < interfaces.length; i++)
823       {
824          if (!interfaces[i].equals(Advised.class))
825          {
826             cleanedInterfaces.add(interfaces[i]);
827          }
828       }
829
830       return (Class JavaDoc[]) cleanedInterfaces.toArray(new Class JavaDoc[cleanedInterfaces.size()]);
831    }
832
833    private Object JavaDoc interceptFieldSet(Invocation invocation, Method JavaDoc reflectionMethod, Object JavaDoc targetObject, Object JavaDoc[] args) throws Throwable JavaDoc
834    {
835       Field JavaDoc field = (Field JavaDoc) invocation.getTargetObject();
836       Matcher JavaDoc m = fieldSetPattern.matcher(reflectionMethod.getName());
837       if (m.matches())
838       {
839          Object JavaDoc instance = args[0];
840          return interceptFieldWrite(invocation, field, instance, args[1]);
841       }
842       return invocation.invokeNext();
843    }
844
845    private Object JavaDoc interceptFieldGet(Invocation invocation, Method JavaDoc reflectionMethod, Object JavaDoc targetObject, Object JavaDoc[] args) throws Throwable JavaDoc
846    {
847       Field JavaDoc field = (Field JavaDoc) invocation.getTargetObject();
848       Matcher JavaDoc m = fieldGetPattern.matcher(reflectionMethod.getName());
849       if (m.matches())
850       {
851          Object JavaDoc instance = args[0];
852          return interceptFieldRead(invocation, field, instance);
853       }
854       return invocation.invokeNext();
855    }
856
857    private Method JavaDoc[] interceptGetDeclaredMethods(Class JavaDoc clazz)
858    {
859       ClassAdvisor advisor = AspectManager.instance().getAdvisorIfAdvised(clazz);
860
861       if (advisor == null)
862       {
863          return clazz.getDeclaredMethods();
864       }
865       else
866       {
867          Object JavaDoc[] advisedMethods = advisor.getAdvisedMethods().getValues();
868
869          ArrayList JavaDoc methods = new ArrayList JavaDoc(advisedMethods.length);
870
871          for (int i = 0; i < advisedMethods.length; i++)
872          {
873             Method JavaDoc m = (Method JavaDoc) advisedMethods[i];
874             if (clazz.equals(m.getDeclaringClass()) && isNotAccessMethod(m) && isNotJavassistWrappedMethod(m))
875             {
876                methods.add(m);
877             }
878          }
879
880          return (Method JavaDoc[]) methods.toArray(new Method JavaDoc[methods.size()]);
881       }
882    }
883
884    private Method JavaDoc interceptGetDeclaredMethod(Class JavaDoc clazz, Object JavaDoc[] args) throws NoSuchMethodException JavaDoc
885    {
886
887       ClassAdvisor advisor = AspectManager.instance().getAdvisorIfAdvised(clazz);
888       Method JavaDoc method = clazz.getDeclaredMethod((String JavaDoc) args[0], (Class JavaDoc[]) args[1]);
889
890       if (advisor == null)
891       {
892          return method;
893       }
894       else
895       {
896          Object JavaDoc[] advisedMethods = advisor.getAdvisedMethods().getValues();
897
898          for (int i = 0; i < advisedMethods.length; i++)
899          {
900             Method JavaDoc m = (Method JavaDoc) advisedMethods[i];
901             if (m.equals(method) && isNotAccessMethod(m) && isNotJavassistWrappedMethod(m))
902             {
903                return method;
904             }
905          }
906       }
907
908       throw new NoSuchMethodException JavaDoc();
909    }
910
911    
912    /**
913     * Java adds a few static void methods called access$0, access$1 etc. when inner classes are used
914     *
915     * @return true if this method is static, void, has package access and has a name like access$0, access$1 etc.
916     */

917    private boolean isNotAccessMethod(Method JavaDoc m)
918    {
919
920       //TODO: Normally access methods should return void, but having optimised field invocation
921
//it seems that javassist occasionally creates these methods with other return types
922

923       if (Modifier.isStatic(m.getModifiers()))
924       {
925          Matcher JavaDoc match = accessMethodPattern.matcher(m.getName());
926          if (match.matches())
927          {
928             return false;
929          }
930       }
931
932       return true;
933    }
934
935    private boolean isNotJavassistWrappedMethod(Method JavaDoc m)
936    {
937       if (Modifier.isPrivate(m.getModifiers()) && !Modifier.isStatic(m.getModifiers()))
938       {
939          if (m.getName().startsWith("_added_m$"))
940          {
941             return false;
942          }
943       }
944       
945       return true;
946    }
947
948    private Method JavaDoc[] interceptGetMethods(Class JavaDoc clazz)
949    {
950
951       ArrayList JavaDoc methods = new ArrayList JavaDoc();
952
953       //These are the methods that have already been added. Since we are
954
//using Class.getDeclaredMethods(), we don't want to add super
955
//implementations of overrriden methods
956
GetMethodsAlreadyFound methodsFound = new GetMethodsAlreadyFound();
957
958       while (clazz != null)
959       {
960          ClassAdvisor advisor = AspectManager.instance().getAdvisorIfAdvised(clazz);
961          Object JavaDoc[] foundMethods;
962
963          if (advisor == null)
964          {
965             foundMethods = clazz.getDeclaredMethods();
966          }
967          else
968          {
969             foundMethods = advisor.getAdvisedMethods().getValues();
970          }
971
972          for (int i = 0; i < foundMethods.length; i++)
973          {
974             Method JavaDoc m = (Method JavaDoc) foundMethods[i];
975             if (clazz.equals(m.getDeclaringClass()) && Modifier.isPublic(m.getModifiers()))
976             {
977
978                if (!methodsFound.existsMethod(m))
979                {
980                   methods.add(m);
981                   methodsFound.addMethod(m);
982                }
983             }
984          }
985
986          clazz = clazz.getSuperclass();
987       }
988
989       return (Method JavaDoc[]) methods.toArray(new Method JavaDoc[methods.size()]);
990    }
991
992    private Method JavaDoc interceptGetMethod(Class JavaDoc clazz, Object JavaDoc[] args) throws NoSuchMethodException JavaDoc
993    {
994       Method JavaDoc method = clazz.getMethod((String JavaDoc) args[0], (Class JavaDoc[]) args[1]);
995       Class JavaDoc declaringClass = method.getDeclaringClass();
996
997       while (clazz != null)
998       {
999          //Go up the inheritance hierachy looking for the class that declares this method
1000
if (clazz.equals(declaringClass))
1001         {
1002            ClassAdvisor advisor = AspectManager.instance().getAdvisorIfAdvised(clazz);
1003
1004            if (advisor == null)
1005            {
1006               return method;
1007            }
1008            else
1009            {
1010               Object JavaDoc[] methods = advisor.getAdvisedMethods().getValues();
1011
1012               for (int i = 0; i < methods.length; i++)
1013               {
1014                  Method JavaDoc m = (Method JavaDoc) methods[i];
1015                  if (m.equals(method))
1016                  {
1017                     return method;
1018                  }
1019               }
1020            }
1021         }
1022
1023         clazz = clazz.getSuperclass();
1024      }
1025
1026      throw new NoSuchMethodException JavaDoc();
1027   }
1028
1029
1030   private Field JavaDoc[] interceptGetDeclaredFields(Class JavaDoc clazz)
1031   {
1032      ClassAdvisor advisor = AspectManager.instance().getAdvisorIfAdvised(clazz);
1033
1034      if (advisor == null)
1035      {
1036         return clazz.getDeclaredFields();
1037      }
1038      else
1039      {
1040         Field JavaDoc[] advisedFields = advisor.getAdvisedFields();
1041
1042         ArrayList JavaDoc fields = new ArrayList JavaDoc(advisedFields.length);
1043
1044         for (int i = 0; i < advisedFields.length; i++)
1045         {
1046            Field JavaDoc f = advisedFields[i];
1047            if (clazz.equals(f.getDeclaringClass()))
1048            {
1049               fields.add(f);
1050            }
1051         }
1052
1053         return (Field JavaDoc[]) fields.toArray(new Field JavaDoc[fields.size()]);
1054      }
1055
1056   }
1057
1058   /** Sun JVMs do not return any extra info from Class.getClasses(),
1059    * JRockit does, so make it got through the same cleaning procedure
1060    * here
1061    */

1062   private Class JavaDoc[] interceptGetClasses(Class JavaDoc clazz) throws Throwable JavaDoc
1063   {
1064      Class JavaDoc[] classes = clazz.getClasses();
1065      return cleanClasses(classes);
1066   }
1067   
1068   private Class JavaDoc[] interceptGetDeclaredClasses(Class JavaDoc clazz) throws Throwable JavaDoc
1069   {
1070      Class JavaDoc[] classes = clazz.getDeclaredClasses();
1071      return cleanClasses(classes);
1072   }
1073   
1074   private Class JavaDoc[] cleanClasses(Class JavaDoc[] classes)
1075   {
1076      ArrayList JavaDoc clazzes = new ArrayList JavaDoc();
1077
1078      for (int i = 0; i < classes.length; i++)
1079      {
1080         Class JavaDoc innerClass = classes[i];
1081
1082         //Check if implements Untransformable
1083
Class JavaDoc[] interfaces = classes[i].getInterfaces();
1084         boolean implUntransformable = false;
1085
1086         for (int j = 0; j < interfaces.length; j++)
1087         {
1088            if (interfaces[j].equals(Untransformable.class))
1089            {
1090               implUntransformable = true;
1091               break;
1092            }
1093         }
1094
1095         if (!implUntransformable)
1096         {
1097            //Check if class implements Invocation at any stage
1098
boolean isInvocationImpl = false;
1099            Class JavaDoc superclass = innerClass.getSuperclass();
1100            while (superclass != null)
1101            {
1102
1103               interfaces = classes[i].getInterfaces();
1104
1105               for (int j = 0; j < interfaces.length; j++)
1106               {
1107                  if (interfaces[j].equals(Invocation.class))
1108                  {
1109                     isInvocationImpl = true;
1110                     break;
1111                  }
1112               }
1113               superclass = superclass.getSuperclass();
1114            }
1115
1116            if (!isInvocationImpl)
1117            {
1118               clazzes.add(innerClass);
1119            }
1120         }
1121      }
1122
1123      return (Class JavaDoc[]) clazzes.toArray(new Class JavaDoc[clazzes.size()]);
1124   }
1125
1126   private Field JavaDoc interceptGetDeclaredField(Class JavaDoc clazz, Object JavaDoc[] args) throws NoSuchFieldException JavaDoc
1127   {
1128
1129      ClassAdvisor advisor = AspectManager.instance().getAdvisorIfAdvised(clazz);
1130      Field JavaDoc field = clazz.getDeclaredField((String JavaDoc) args[0]);
1131
1132      if (advisor == null)
1133      {
1134         return field;
1135      }
1136      else
1137      {
1138         Field JavaDoc[] advisedFields = advisor.getAdvisedFields();
1139
1140         for (int i = 0; i < advisedFields.length; i++)
1141         {
1142            Field JavaDoc f = advisedFields[i];
1143            if (f.equals(field))
1144            {
1145               return field;
1146            }
1147         }
1148      }
1149
1150      throw new NoSuchFieldException JavaDoc();
1151   }
1152
1153   /**
1154    * First attempt to invoke the original caller interceptor chains in the
1155    * calling class, then attempt to invoke the original interceptor chain
1156    * attached to the constructor in the target class.
1157    * For now we don't bother attempting to use optimized invocations since we
1158    * are using reflection anyway
1159    */

1160   private Object JavaDoc invokeOriginalChainIfExists(Invocation invocation, Constructor JavaDoc constructor, Object JavaDoc[] args) throws Throwable JavaDoc
1161   {
1162      //Try to attach to the caller chain
1163
if (invocation instanceof MethodCalledByConstructorInvocation)
1164      {
1165         MethodCalledByConstructorInvocation inv = (MethodCalledByConstructorInvocation) invocation;
1166         Constructor JavaDoc callingCon = inv.getCalling();
1167         Class JavaDoc callingClass = callingCon.getDeclaringClass();
1168         if (isAdvised(callingClass))
1169         {
1170            ClassAdvisor advisor = AspectManager.instance().getAdvisor(callingClass);
1171            if (advisor != null)
1172            {
1173               int index = advisor.getConstructorIndex(callingCon);
1174               if (index >= 0)
1175               {
1176                  HashMap calledClassesMap = advisor.getConCalledByConInterceptors()[index];
1177                  if (calledClassesMap != null)
1178                  {
1179                     TLongObjectHashMap calledCons = (TLongObjectHashMap) calledClassesMap.get(constructor.getDeclaringClass().getName());
1180                     if (calledCons != null)
1181                     {
1182                        long calledHash = MethodHashing.constructorHash(constructor);
1183                        ConByConInfo info = (ConByConInfo) calledCons.get(calledHash);
1184
1185                        if (info != null && info.hasAdvices())
1186                        {
1187                           return advisor.invokeConCalledByCon(info, args);
1188                        }
1189                     }
1190                  }
1191               }
1192            }
1193         }
1194      }
1195      else if (invocation instanceof MethodCalledByMethodInvocation)
1196      {
1197         MethodCalledByMethodInvocation inv = (MethodCalledByMethodInvocation) invocation;
1198         Method JavaDoc callingMethod = inv.getCallingMethod();
1199         if (isAdvised(callingMethod.getDeclaringClass()))
1200         {
1201            ClassAdvisor advisor = AspectManager.instance().getAdvisor(callingMethod.getDeclaringClass());
1202            if (advisor != null)
1203            {
1204               long callingMethodHash = MethodHashing.calculateHash(callingMethod);
1205               long calledHash = MethodHashing.constructorHash(constructor);
1206
1207               HashMap calledClassesMap = (HashMap) advisor.getConCalledByMethodInterceptors().get(callingMethodHash);
1208               if (calledClassesMap != null)
1209               {
1210                  TLongObjectHashMap calledCons = (TLongObjectHashMap) calledClassesMap.get(constructor.getDeclaringClass().getName());
1211                  if (calledCons != null)
1212                  {
1213                     //CallerConstructorInfo info = (CallerConstructorInfo) calledCons.get(calledHash);
1214
ConByMethodInfo info = (ConByMethodInfo) calledCons.get(calledHash);
1215
1216                     if (info != null && info.hasAdvices())
1217                     {
1218                        //return advisor.invokeConCalledByMethod(callingMethodHash, args, info, inv.getCallingObject());
1219
return advisor.invokeConCalledByMethod(info, inv.getCallingObject(), args);
1220                     }
1221                  }
1222               }
1223            }
1224         }
1225      }
1226      
1227      //Try to attach to chain on target object
1228
Class JavaDoc calledClass = constructor.getDeclaringClass();
1229      if (isAdvised(calledClass))
1230      {
1231         ClassAdvisor advisor = AspectManager.instance().getAdvisor(constructor.getDeclaringClass());
1232
1233         if (advisor != null && advisor.hasAspects())
1234         {
1235            int index = advisor.getConstructorIndex(constructor);
1236            if (index >= 0)
1237            {
1238               ConstructorInfo jp = advisor.getConstructorInfos()[index];
1239               return jp.getWrapper().invoke(null, args);
1240            }
1241         }
1242      }
1243      return invocation.invokeNext();
1244   }
1245
1246
1247   /**
1248    * Attempt to invoke the original interceptor chain attached to the
1249    * field read in the target class.
1250    * For now we don't bother attempting to use optimized invocations since we
1251    * are using reflection anyway
1252    */

1253   private Object JavaDoc invokeOriginalChainIfExists(Invocation invocation, Field JavaDoc field, Object JavaDoc targetObject) throws Throwable JavaDoc
1254   {
1255      //Don't attach to caller chain, since we don't have caller interception for fields
1256

1257      //Try to attach to chain on target object
1258
ClassAdvisor advisor = AspectManager.instance().getAdvisor(field.getDeclaringClass());
1259
1260      Class JavaDoc calledClass = field.getDeclaringClass();
1261      if (isAdvised(calledClass))
1262      {
1263         if (advisor != null && advisor.hasAspects())
1264         {
1265            int index = advisor.getFieldIndex(field);
1266            if (index >= 0)
1267            {
1268               FieldInfo jp = advisor.getFieldReadInfos()[index];
1269               return jp.getWrapper().invoke(null, new Object JavaDoc[] {targetObject});
1270            }
1271         }
1272      }
1273      return invocation.invokeNext();
1274   }
1275
1276   /**
1277    * Attempt to invoke the original interceptor chain attached to the
1278    * field write in the target class.
1279    * For now we don't bother attempting to use optimized invocations since we
1280    * are using reflection anyway
1281    */

1282   private Object JavaDoc invokeOriginalChainIfExists(Invocation invocation, Field JavaDoc field, Object JavaDoc targetObject, Object JavaDoc value) throws Throwable JavaDoc
1283   {
1284      //Don't attach to caller chain, since we don't have caller interception for fields
1285

1286      //Try to attach to chain on target object
1287
ClassAdvisor advisor = AspectManager.instance().getAdvisor(field.getDeclaringClass());
1288
1289      Class JavaDoc calledClass = field.getDeclaringClass();
1290      if (isAdvised(calledClass))
1291      {
1292         if (advisor != null && advisor.hasAspects())
1293         {
1294            int index = advisor.getFieldIndex(field);
1295            if (index >= 0)
1296            {
1297               FieldInfo jp = advisor.getFieldWriteInfos()[index];
1298               return jp.getWrapper().invoke(null, new Object JavaDoc[] {targetObject, value});
1299            }
1300         }
1301      }
1302      return invocation.invokeNext();
1303   }
1304
1305   /**
1306    * Attempt to invoke the original interceptor chain attached to the
1307    * method call in the caller class.
1308    * For now we don't bother attempting to use optimized invocations since we
1309    * are using reflection anyway
1310    */

1311   private Object JavaDoc invokeOriginalChainIfExists(Invocation invocation, Method JavaDoc method, Object JavaDoc targetObject, Object JavaDoc[] args) throws Throwable JavaDoc
1312   {
1313      //Try to attach to the caller chain
1314
if (invocation instanceof MethodCalledByConstructorInvocation)
1315      {
1316         MethodCalledByConstructorInvocation inv = (MethodCalledByConstructorInvocation) invocation;
1317         Constructor JavaDoc callingCon = inv.getCalling();
1318         Class JavaDoc callingClass = callingCon.getDeclaringClass();
1319         if (isAdvised(callingClass))
1320         {
1321            ClassAdvisor advisor = AspectManager.instance().getAdvisor(callingClass);
1322            if (advisor != null)
1323            {
1324               int index = advisor.getConstructorIndex(callingCon);
1325               if (index >= 0)
1326               {
1327                  HashMap calledClassesMap = advisor.getMethodCalledByConInterceptors()[index];
1328                  if (calledClassesMap != null)
1329                  {
1330                     TLongObjectHashMap calledMethods = (TLongObjectHashMap) calledClassesMap.get(method.getDeclaringClass().getName());
1331                     if (calledMethods != null)
1332                     {
1333                        long calledHash = MethodHashing.calculateHash(method);
1334                        //CallerMethodInfo info = (CallerMethodInfo) calledMethods.get(calledHash);
1335
MethodByConInfo info = (MethodByConInfo) calledMethods.get(calledHash);
1336
1337                        if (info != null && info.hasAdvices())
1338                        {
1339                           //return advisor.invokeConstructorCaller(index, targetObject, args, info);
1340
return advisor.invokeConstructorCaller(info, targetObject, args);
1341                        }
1342                     }
1343                  }
1344               }
1345            }
1346         }
1347      }
1348      else if (invocation instanceof MethodCalledByMethodInvocation)
1349      {
1350         MethodCalledByMethodInvocation inv = (MethodCalledByMethodInvocation) invocation;
1351         Method JavaDoc callingMethod = inv.getCallingMethod();
1352         if (isAdvised(callingMethod.getDeclaringClass()))
1353         {
1354            ClassAdvisor advisor = AspectManager.instance().getAdvisor(callingMethod.getDeclaringClass());
1355            if (advisor != null)
1356            {
1357               long callingMethodHash = MethodHashing.calculateHash(callingMethod);
1358               long calledHash = MethodHashing.calculateHash(method);
1359
1360               HashMap calledClassesMap = (HashMap) advisor.getMethodCalledByMethodInterceptors().get(callingMethodHash);
1361               if (calledClassesMap != null)
1362               {
1363                  TLongObjectHashMap calledMethods = (TLongObjectHashMap) calledClassesMap.get(method.getDeclaringClass().getName());
1364                  if (calledMethods != null)
1365                  {
1366                     //CallerMethodInfo info = (CallerMethodInfo) calledMethods.get(calledHash);
1367
MethodByMethodInfo info = (MethodByMethodInfo) calledMethods.get(calledHash);
1368
1369                     if (info != null && info.hasAdvices())
1370                     {
1371                        //return advisor.invokeCaller(callingMethodHash, targetObject, args, info, inv.getCallingObject());
1372
return advisor.invokeCaller(info, inv.getCallingObject(), targetObject, args);
1373                     }
1374                  }
1375               }
1376            }
1377         }
1378      }
1379      
1380      //Don't try to attach to chain on target object, since this already is handled for us
1381
//(Wrapper is method itself)
1382
return invocation.invokeNext();
1383   }
1384
1385   private boolean isAdvised(Class JavaDoc clazz)
1386   {
1387      Class JavaDoc[] interfaces = clazz.getInterfaces();
1388
1389      for (int i = 0; i < interfaces.length; i++)
1390      {
1391         if (interfaces[i].equals(Advised.class))
1392         {
1393            return true;
1394         }
1395      }
1396      
1397      //Is this recursive check needed
1398
Class JavaDoc superClass = clazz.getSuperclass();
1399      if (superClass != null)
1400      {
1401         return isAdvised(superClass);
1402      }
1403
1404      return false;
1405   }
1406   // Inner classes -------------------------------------------------
1407

1408   /* Used by interceptGetMethods()
1409    */

1410   class GetMethodsAlreadyFound
1411   {
1412      HashMap methodMap = new HashMap();
1413
1414      public void addMethod(Method JavaDoc m)
1415      {
1416         String JavaDoc methodName = m.getName();
1417         ArrayList JavaDoc methods = (ArrayList JavaDoc) methodMap.get(methodName);
1418
1419         if (methods == null)
1420         {
1421            methods = new ArrayList JavaDoc();
1422            methodMap.put(methodName, methods);
1423         }
1424
1425         methods.add(m);
1426      }
1427
1428      public boolean existsMethod(Method JavaDoc method)
1429      {
1430         ArrayList JavaDoc methods = (ArrayList JavaDoc) methodMap.get(method.getName());
1431
1432         if (methods == null)
1433         {
1434            return false;
1435         }
1436
1437         Class JavaDoc[] methodParamTypes = method.getParameterTypes();
1438
1439         for (Iterator JavaDoc it = methods.iterator(); it.hasNext();)
1440         {
1441            Method JavaDoc found = (Method JavaDoc) it.next();
1442            Class JavaDoc[] foundParamTypes = found.getParameterTypes();
1443
1444            if (methodParamTypes.length == foundParamTypes.length)
1445            {
1446
1447               boolean same = true;
1448               for (int i = 0; i < methodParamTypes.length; i++)
1449               {
1450                  if (!methodParamTypes[i].equals(foundParamTypes[i]))
1451                  {
1452                     same = false;
1453                  }
1454               }
1455
1456               if (same)
1457               {
1458                  return true;
1459               }
1460            }
1461         }
1462
1463         return false;
1464      }
1465   }
1466}
1467
Popular Tags