KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > core > Wrapping


1 /*
2   Copyright (C) 2001-2003 Renaud Pawlak, Lionel Seinturier.
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   GNU Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17   USA */

18
19 package org.objectweb.jac.core;
20
21 import java.lang.reflect.InvocationTargetException JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Hashtable JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Vector JavaDoc;
31 import org.aopalliance.intercept.ConstructorInterceptor;
32 import org.aopalliance.intercept.Interceptor;
33 import org.aopalliance.intercept.MethodInterceptor;
34 import org.apache.log4j.Logger;
35 import org.objectweb.jac.core.rtti.AbstractMethodItem;
36 import org.objectweb.jac.core.rtti.ClassItem;
37 import org.objectweb.jac.core.rtti.ClassRepository;
38 import org.objectweb.jac.core.rtti.ConstructorItem;
39 import org.objectweb.jac.core.rtti.MethodItem;
40 import org.objectweb.jac.core.rtti.MixinMethodItem;
41 import org.objectweb.jac.core.rtti.NamingConventions;
42 import org.objectweb.jac.util.Strings;
43 import org.objectweb.jac.util.WrappedThrowableException;
44
45 /**
46  * This class provides a set of useful static methods that allow the
47  * wrapping of wrappable objects (wrappee) by some wrapper objects.
48  *
49  * @author <a HREF="mailto:pawlak@cnam.fr">Renaud Pawlak</a>
50  * @author <a HREF="mailto:Lionel.Seinturier@lip6.fr">Lionel Seinturier</a> */

51
52 public class Wrapping {
53     static Logger logger = Logger.getLogger("wrapping");
54     static Logger loggerExc = Logger.getLogger("exceptions");
55     static Logger loggerRole = Logger.getLogger("rolemethod");
56     static Logger loggerWuni = Logger.getLogger("wuni");
57
58     /** The local Aspect Component manager for this container (on
59         optimization purpose). */

60     /** The wrapping chains for the base methods
61         (wrappingChains[object]->hastable[method]->vector). */

62     static transient Map JavaDoc wrappingChains = new java.util.WeakHashMap JavaDoc();
63     /** The wrapping chains for the static base methods
64         (staticWrappingChains[method]->vector). */

65     static transient Map JavaDoc staticWrappingChains = new Hashtable JavaDoc();
66
67     /** The exceptions handlers for the base methods. */
68     static transient Map JavaDoc catchingChains = new java.util.WeakHashMap JavaDoc();
69
70     /** The exceptions handlers for the static base methods. */
71     static transient Map JavaDoc staticCatchingChains = new Hashtable JavaDoc();
72
73     /** The wrappers for the base object. */
74     static transient Map JavaDoc wrappers = new java.util.WeakHashMap JavaDoc();
75
76     /** The wrappers for the base classes. */
77     static transient Map JavaDoc staticWrappers = new Hashtable JavaDoc();
78
79     /** The wrapper classes for the base object. */
80     static transient Map JavaDoc wrapperClasses = new java.util.WeakHashMap JavaDoc();
81
82     /** The wrapper classes for the base classes. */
83     static transient Map JavaDoc staticWrapperClasses = new Hashtable JavaDoc();
84
85     public static final Object JavaDoc[] emptyArray = new Object JavaDoc[0];
86
87     /**
88      * Returns the wrapping chain that wraps the given method.
89      *
90      * @param wrappee the wrappee (if null, the given method is
91      * nesserally a static method)
92      * @param method the wrapped method (can be static, then wrappee is
93      * null)
94      */

95     public static WrappingChain getWrappingChain(
96         Wrappee wrappee,
97         AbstractMethodItem method)
98     {
99         // System.out.println("getting wrapping chain for "+method);
100

101         if (method.isStatic()) {
102             WrappingChain result =
103                 (WrappingChain) staticWrappingChains.get(method);
104             if (result == null) {
105                 result = new WrappingChain();
106                 staticWrappingChains.put(method, result);
107             }
108             //System.out.println("return "+result);
109
return result;
110         } else {
111             Map JavaDoc wrappeeChains = (Map JavaDoc) wrappingChains.get(wrappee);
112             if (wrappeeChains == null) {
113                 wrappeeChains = new Hashtable JavaDoc();
114                 wrappingChains.put(wrappee, wrappeeChains);
115             }
116             WrappingChain result = (WrappingChain) wrappeeChains.get(method);
117             if (result == null) {
118                 result = new WrappingChain();
119                 wrappeeChains.put(method, result);
120             }
121             return result;
122         }
123     }
124
125     /**
126      * Returns the catching chain that wraps the given method.
127      *
128      * @param wrappee the wrappee (if null, the given method is
129      * nesserally a static method)
130      * @param method the wrapped method (can be static, then wrappee is
131      * null)
132      */

133     public static List JavaDoc getCatchingChain(
134         Wrappee wrappee,
135         AbstractMethodItem method)
136     {
137         if (method.isStatic()) {
138             List JavaDoc chain = (List JavaDoc) staticCatchingChains.get(method);
139             if (chain == null) {
140                 chain = new Vector JavaDoc();
141                 staticCatchingChains.put(method, chain);
142             }
143             return chain;
144         } else {
145             Map JavaDoc wrappeeChain = (Map JavaDoc) catchingChains.get(wrappee);
146             if (wrappeeChain == null) {
147                 wrappeeChain = new Hashtable JavaDoc();
148                 catchingChains.put(wrappee, wrappeeChain);
149             }
150             List JavaDoc chain = (List JavaDoc) wrappeeChain.get(method);
151             if (chain == null) {
152                 chain = new Vector JavaDoc();
153                 wrappeeChain.put(method, chain);
154             }
155             return chain;
156         }
157     }
158
159     /**
160      * Returns the wrappers that wrap the given wrappee or wrappee's
161      * class.
162      *
163      * @param wrappee the wrappee (can be null if wrappeeClass is not
164      * null)
165      * @param wrappeeClass the wrappee's class (can be null if wrappee
166      * is not null)
167      */

168     public static List JavaDoc getWrappers(Wrappee wrappee, ClassItem wrappeeClass) {
169         if (wrappee == null) {
170             List JavaDoc wrappers = (List JavaDoc) staticWrappers.get(wrappeeClass);
171             if (wrappers == null) {
172                 wrappers = new Vector JavaDoc();
173                 staticWrappers.put(wrappeeClass, wrappers);
174             }
175             return wrappers;
176         } else {
177             List JavaDoc result = (List JavaDoc) wrappers.get(wrappee);
178             if (result == null) {
179                 result = new Vector JavaDoc();
180                 wrappers.put(wrappee, result);
181             }
182             return result;
183         }
184     }
185
186     /**
187      * Returns the classes of the wrappers that wrap the given wrappee
188      * or wrappee's class.
189      *
190      * @param wrappee the wrappee (can be null if wrappeeClass is not
191      * null)
192      * @param wrappeeClass the wrappee's class (can be null if wrappee
193      * is not null)
194      */

195     public static List JavaDoc getWrapperClasses(
196         Wrappee wrappee,
197         ClassItem wrappeeClass)
198     {
199         if (wrappee == null) {
200             List JavaDoc result = (List JavaDoc) staticWrapperClasses.get(wrappeeClass);
201             if (result == null) {
202                 result = new Vector JavaDoc();
203                 staticWrapperClasses.put(wrappeeClass, result);
204             }
205             return result;
206         } else {
207             List JavaDoc result = (List JavaDoc) wrapperClasses.get(wrappee);
208             if (result == null) {
209                 result = new Vector JavaDoc();
210                 wrapperClasses.put(wrappee, result);
211             }
212             return result;
213         }
214     }
215
216     /**
217      * Adds a wrapper to the current wrappee.
218      *
219      * <p>Any method of this wrapper can then be used on the wrappee
220      * with <code>invokeRoleMethod</code>.
221      *
222      * <p>To precise which method of this wrapper should actually wrap
223      * the current wrappee methods, use the <code>wrap</code> methods.
224      *
225      * @param wrappee the wrappee (can be null if wrappeeClass is not
226      * null, then wraps all the instances of the class in a static
227      * mode)
228      * @param wrappeeClass the wrappee's class (can be null if wrappee
229      * is not null)
230      * @param wrapper the new wrapper */

231
232     public static void wrap(
233         Wrappee wrappee,
234         ClassItem wrappeeClass,
235         Wrapper wrapper)
236     {
237         logger.debug("wrapping " + wrappee + "(" + wrappeeClass + ") with " + wrapper);
238         List JavaDoc wrappers = getWrappers(wrappee, wrappeeClass);
239         if (wrappers.contains(wrapper)) {
240             logger.debug(" ignoring already present wrapper");
241             return;
242         }
243
244         wrappers.add(wrapper);
245         getWrapperClasses(wrappee, wrappeeClass).add(wrapper.getClass());
246
247         /*
248         String ac = (String) Collaboration.get().getCurAC();
249         if ( ac != null ) {
250            AspectComponent temp_ac = (AspectComponent)
251               ACManager.get().getObject( ac );
252            if ( temp_ac != null ) {
253               temp_ac.addWrapper( wrapper );
254               wrapper.setAspectComponent( ac );
255            }
256         }
257         */

258     }
259
260     static private HashMap JavaDoc wrappableMethods = new HashMap JavaDoc();
261
262     /**
263      * Tells if a given method is wrappable.
264      *
265      * @param method the method to check */

266
267     public static boolean isWrappable(AbstractMethodItem method) {
268         // We use a cache because it is too slow otherwise
269
Boolean JavaDoc ret = (Boolean JavaDoc) wrappableMethods.get(method);
270         if (ret == null) {
271             try {
272                 // getClass().getField( "_" + methodName + "_method_name" );
273
((ClassItem) method.getParent()).getActualClass().getField(
274                     "__JAC_TRANSLATED");
275             } catch (Exception JavaDoc e) {
276                 //Log.trace("wrappable","* isWrappable("+method+") -> false");
277
wrappableMethods.put(method, Boolean.FALSE);
278                 return false;
279             }
280             //Log.trace("wrappable","* isWrappable("+method+") -> true");
281
wrappableMethods.put(method, new Boolean JavaDoc(true));
282             return true;
283         } else {
284             //Log.trace("wrappable","isWrappable("+method+") -> "+ret);
285
return ret.booleanValue();
286         }
287     }
288
289     public static String JavaDoc printWrappingChain(Interceptor[] wrappingChain) {
290         String JavaDoc result = "[";
291         for (int i = 0; i < wrappingChain.length; i++) {
292             if (i != 0) {
293                 result += ",";
294             }
295             result += wrappingChain[i].toString();
296         }
297
298         result += "]";
299         return result;
300     }
301
302     static CompositionAspect ca = null;
303
304     /**
305      * Wrap a method of an object.
306      *
307      * @param wrappee the object to wrap
308      * @param wrapper the wrapper
309      * @param wrappedMethod the method of wrappee to wrap
310      */

311     public static void wrap(
312         Wrappee wrappee,
313         Wrapper wrapper,
314         AbstractMethodItem wrappedMethod)
315     {
316         if (wrapMethod(wrappee,wrapper,wrappedMethod)) {
317             // Add to list of wrappers
318
Wrapping.wrap(wrappee, wrappedMethod.getClassItem(), wrapper);
319         }
320     }
321
322     /**
323      * Wrap a method of an object. Only updates the wrapping chain of
324      * the method.
325      *
326      * @param wrappee the object to wrap
327      * @param wrapper the wrapper
328      * @param wrappedMethod the method of wrappee to wrap
329      *
330      * @return true if the method was actually wrapped
331      */

332     public static boolean wrapMethod(
333         Wrappee wrappee,
334         Wrapper wrapper,
335         AbstractMethodItem wrappedMethod)
336     {
337         if (isWrappable(wrappedMethod)) {
338             logger.debug(wrappedMethod + Strings.hash(wrappedMethod)+" is wrapped by " + wrapper);
339
340             WrappingChain wrappingChain =
341                 getWrappingChain(wrappee, wrappedMethod.getConcreteMethod());
342             logger.debug(" "+wrappedMethod.getConcreteMethod()+" -> "+wrappingChain+
343                          Strings.hash(wrappingChain));
344
345             if (wrappingChain.contains(wrapper)) {
346                 logger.debug(" skipping "+wrapper);
347                 return false;
348             }
349
350             int rank = 0;
351
352             ACManager acm = ACManager.getACM();
353             if (acm != null) {
354                 if (ca == null)
355                     ca = (CompositionAspect) acm.objects.get(
356                         "JAC_composition_aspect");
357                 if (ca != null) {
358                     rank = ca.getWeaveTimeRank(wrappingChain, wrapper);
359                     //Log.trace("wrap.wrap","found rank="+rank+"/"+wrappingChain.size());
360
} else {
361                     /*
362                     if( wrappingChain.size() > 0 ) {
363                     Log.warning( "no composition aspect found when wrapping "+
364                                  wrappedMethod + " with " +
365                                  wrapper.getClass().getName() );
366                     }
367                     */

368                 }
369             }
370
371             wrappingChain.add(rank, wrapper);
372             return true;
373             //System.out.println("WrappingChain = "+printWrappingChain(wrappingChain));
374
} else {
375             //logger.debug(wrappedMethod+" is not wrappable");
376
return false;
377         }
378
379     }
380
381     /**
382      * A nicer way to write <code>wrap</code> when several base methods
383      * need to be wrapped.
384      *
385      * @param wrappee the wrappee (can be null if the wrappeed methods
386      * are static)
387      * @param wrapper the wrapper where the wrapping method is
388      * implemented
389      * @param wrappedMethods the names of the wrapped methods
390      */

391     public static void wrap(
392         Wrappee wrappee,
393         Wrapper wrapper,
394         AbstractMethodItem[] wrappedMethods)
395     {
396         if (wrappedMethods == null)
397             return;
398         for (int i = 0; i < wrappedMethods.length; i++) {
399             if (wrappedMethods[i] != null) {
400                 wrap(wrappee, wrapper, wrappedMethods[i]);
401             }
402         }
403     }
404
405     /**
406      * A string based version of wrap (for simplification purpose).
407      *
408      * @param wrappee the wrappee (cannot be null, this version only
409      * works for non-static methods)
410      * @param wrapper the wrapper where the wrapping method is
411      * implemented
412      * @param wrappedMethods the names of the wrapped methods
413      *
414      * @see #wrap(Wrappee,Wrapper,AbstractMethodItem[])
415      */

416     public static void wrap(
417         Wrappee wrappee,
418         Wrapper wrapper,
419         String JavaDoc[] wrappedMethods)
420     {
421         ClassItem cli = ClassRepository.get().getClass(wrappee);
422         if (wrappedMethods == null)
423             return;
424         for (int i = 0; i < wrappedMethods.length; i++) {
425             if (wrappedMethods[i] != null) {
426                 try {
427                     MethodItem[] methods = cli.getMethods(wrappedMethods[i]);
428                     for (int j = 0; j < methods.length; j++) {
429                         wrap(wrappee, wrapper, methods[j]);
430                     }
431                 } catch (org.objectweb.jac.core.rtti.NoSuchMethodException e) {
432                     logger.error("wrap "+wrappee+","+wrapper+","+Arrays.asList(wrappedMethods)+": "+e);
433                 }
434             }
435         }
436     }
437
438     /**
439      * Wraps all the wrappable (public) methods of the current wrappee.
440      *
441      * @param wrappee the wrappee (can be null, then only wrap static
442      * methods)
443      * @param wrappeeClass the wrappee's class (can be null if wrappee
444      * is not null)
445      * @param wrapper the wrapper
446      */

447     public static void wrapAll(
448         Wrappee wrappee,
449         ClassItem wrappeeClass,
450         Wrapper wrapper)
451     {
452         Collection JavaDoc methods = null;
453         if (wrappeeClass != null) {
454             methods = wrappeeClass.getAllMethods();
455         } else {
456             methods =
457                 ClassRepository
458                     .get()
459                     .getClass(wrappee.getClass())
460                     .getAllMethods();
461         }
462         Iterator JavaDoc i = methods.iterator();
463         while (i.hasNext()) {
464             wrap(wrappee, wrapper, (AbstractMethodItem) i.next());
465         }
466     }
467
468     /**
469      * Wraps all the writer wrappable (public) methods of the current
470      * wrappee.
471      *
472      * @param wrappee the wrappee (cannot be null, this version only
473      * works for non-static methods)
474      * @param wrapper the wrapper
475      */

476     public static void wrapModifiers(Wrappee wrappee, Wrapper wrapper) {
477         try {
478             Collection JavaDoc methods =
479                 ClassRepository.get().getClass(wrappee).getAllModifiers();
480             Iterator JavaDoc i = methods.iterator();
481             while (i.hasNext()) {
482                 MethodItem method = (MethodItem) i.next();
483                 wrap(wrappee, wrapper, method);
484             }
485         } catch (Exception JavaDoc e) {
486             e.printStackTrace();
487         }
488     }
489
490     /**
491      * Definitively removes a wrapper.
492      *
493      * <p>When this method is called, none of the methods of the
494      * wrapper can be used as role methods anymore.
495      *
496      * <p>This method before calls the <code>unwrapAll</code> to ensure
497      * that none of the current wrappee methods are yet wrapped.
498      *
499      * @param wrappee the wrappee (can be null, then only wrap static
500      * methods)
501      * @param wrappeeClass the wrappee's class (can be null if wrappee
502      * is not null)
503      * @param wrapper the wrapper to remove
504      *
505      * @see #unwrapAll(Wrappee,ClassItem,Wrapper)
506      * @see #invokeRoleMethod(Wrappee,String,Object[])
507      */

508     public static void unwrap(
509         Wrappee wrappee,
510         ClassItem wrappeeClass,
511         Wrapper wrapper)
512     {
513         List JavaDoc wrappers = getWrappers(wrappee, wrappeeClass);
514         if (!wrappers.contains(wrapper))
515             return;
516         logger.debug("unwrapping " + wrappee + " with " + wrapper);
517         wrappers.remove(wrapper);
518         getWrapperClasses(wrappee, wrappeeClass).remove(wrapper.getClass());
519         unwrapAll(wrappee, wrappeeClass, wrapper);
520     }
521
522     /**
523      * Removes all wrappers that belong to list of wrappers
524      *
525      * @param wrappee the wrappee to unwrap (may be null for static methods)
526      * @param wrappeeClass the class of the wrappee to unwrap
527      * @param acWrappers the wrappers to remove (the wrappers of an aspect component)
528      */

529     public static void unwrap(
530         Wrappee wrappee,
531         ClassItem wrappeeClass,
532         Collection JavaDoc acWrappers)
533     {
534         List JavaDoc wrappers = getWrappers(wrappee, wrappeeClass);
535         // Since acWrappers.size() >> wrappers.size(), we iterate on wappers
536
Iterator JavaDoc it = wrappers.iterator();
537         while(it.hasNext()) {
538             Wrapper wrapper = (Wrapper)it.next();
539             if (acWrappers.contains(wrapper)) {
540                 logger.debug("unwrapping " + wrappee + " with " + wrapper);
541                 it.remove();
542                 getWrapperClasses(wrappee, wrappeeClass).remove(wrapper.getClass());
543                 unwrapAll(wrappee, wrappeeClass, wrapper);
544             } else {
545                 logger.debug("leaving "+wrapper);
546             }
547         }
548     }
549
550     /**
551      * Unwraps a single method.
552      *
553      * <p>The wrapper must implement <code>wrappingMethod</code>. If
554      * the wrapped method was not actually wrapped at the time this
555      * method is called, then this code has no effect.
556      *
557      * <p>To definitively remove the wrapper so that none of its method
558      * will not be considered as role methods anymore, use the
559      * <code>unwrap(Wrappee,ClassItem,Wrapper)</code> method.
560      *
561      * @param wrappee the wrappee (can be null, then the wrappedMethod
562      * must be static)
563      * @param wrapper the wrapper
564      * @param wrappedMethod the name of the method to unwrap
565      *
566      * @see #unwrap(Wrappee,ClassItem,Wrapper)
567      */

568     public static void unwrap(
569         Wrappee wrappee,
570         Wrapper wrapper,
571         AbstractMethodItem wrappedMethod)
572     {
573         logger.debug("unwrapping " + (wrappee != null ? wrappee.getClass().getName() : "-")+
574                      "."+wrappedMethod+"("+Strings.hex(wrappedMethod)+"-"+
575                      Strings.hex(wrappedMethod.getClassItem())+")"+
576                      " with "+wrapper+"???");
577         WrappingChain wrappingChain = getWrappingChain(wrappee, wrappedMethod.getConcreteMethod());
578         for (int i=0; i<wrappingChain.size(); i++) {
579             if (wrappingChain.get(i) == wrapper) {
580                 logger.debug("unwrapping "+wrappedMethod+"("+Strings.hex(wrappedMethod)+")"+
581                              " with "+wrapper);
582                 wrappingChain.remove(i);
583             }
584         }
585     }
586
587     public static void unwrapAll(
588         Wrappee wrappee,
589         ClassItem wrappeeClass,
590         Wrapper wrapper)
591     {
592         logger.debug("unwrapAll "+wrappeeClass+"-"+Strings.hex(wrappeeClass)+
593                      "-"+wrappeeClass.getClass().getClassLoader());
594         Collection JavaDoc methods = wrappeeClass.getAllMethods();
595         Iterator JavaDoc i = methods.iterator();
596         while (i.hasNext()) {
597             AbstractMethodItem m = (AbstractMethodItem)i.next();
598             if (!(m instanceof MixinMethodItem))
599                 unwrap(wrappee, wrapper, m);
600         }
601     }
602
603     /**
604      * Tells wether a wrapper wraps a wrappee or a class
605      */

606     public static boolean isWrappedBy(
607         Wrappee wrappee,
608         ClassItem wrappeeClass,
609         Wrapper wrapper)
610     {
611         return getWrappers(wrappee, wrappeeClass).contains(wrapper);
612     }
613
614     /**
615      * Returns true if the wrappee or the wrappeeClass is wrapped by a
616      * wrapper class.
617      */

618     public static boolean isWrappedBy(
619         Wrappee wrappee,
620         ClassItem wrappeeClass,
621         Class JavaDoc wrapperClass)
622     {
623         return getWrapperClasses(wrappee, wrappeeClass).contains(wrapperClass);
624     }
625
626     /**
627      * Tells wether a wrappee has a wrapper whose class can be
628      * assigned to a given wrapper class.
629      */

630     public static boolean isExtendedBy(
631         Wrappee wrappee,
632         ClassItem wrappeeClass,
633         Class JavaDoc wrapperClass)
634     {
635         Iterator JavaDoc i = getWrapperClasses(wrappee, wrappeeClass).iterator();
636         while (i.hasNext()) {
637             Class JavaDoc cl = (Class JavaDoc) i.next();
638             if (wrapperClass.isAssignableFrom(cl))
639                 return true;
640         }
641         return false;
642     }
643
644     public static void addExceptionHandler(
645         Wrappee wrappee,
646         Wrapper wrapper,
647         String JavaDoc method,
648         AbstractMethodItem listenedMethod)
649     {
650         Vector JavaDoc catchingChain =
651             (Vector JavaDoc) getCatchingChain(wrappee, listenedMethod);
652
653         Object JavaDoc[] catchingMethod = new Object JavaDoc[2];
654         catchingMethod[0] = wrapper;
655         Method JavaDoc[] methods =
656             ClassRepository.getDirectMethodAccess(wrapper.getClass(), method);
657         if (methods.length > 0) {
658             catchingMethod[1] = methods[0];
659             catchingChain.add(catchingMethod);
660         } else {
661             throw new NoSuchMethodError JavaDoc(
662                 "No such method "
663                     + method
664                     + " in class "
665                     + wrapper.getClass().getName());
666         }
667     }
668
669     public static void addExceptionHandler(
670         Wrappee wrappee,
671         Wrapper wrapper,
672         String JavaDoc method)
673     {
674         Collection JavaDoc meths =
675             ClassRepository.get().getClass(wrappee.getClass()).getAllMethods();
676         Iterator JavaDoc i = meths.iterator();
677         while (i.hasNext()) {
678             addExceptionHandler(
679                 wrappee,
680                 wrapper,
681                 method,
682                 (AbstractMethodItem) i.next());
683         }
684     }
685
686     /**
687      * Invokes a role method on the wrappee. The first wrapper which
688      * defines a role method with that name is used, so in order to
689      * avoid ambiguity, it is preferable to use
690      * invokeRoleMethod(Wrappee,Class,String,Object[])
691      *
692      * @param wrappee the wrappee (must be wrapped by a wrapper that
693      * supports the role method)
694      * @param methodName the name of the role method to invoke.
695      * @param parameters the parameters.
696      * @return the returned object
697      *
698      * @see #invokeRoleMethod(Wrappee,Class,String,Object[])
699      */

700     public static Object JavaDoc invokeRoleMethod(
701         Wrappee wrappee,
702         String JavaDoc methodName,
703         Object JavaDoc[] parameters)
704     {
705         Iterator JavaDoc wrappers = getWrappers(wrappee, null).iterator();
706         Object JavaDoc ret = null;
707         MethodItem method = null;
708         Object JavaDoc wrapper = null;
709
710         // Seek the role method
711
while (wrappers.hasNext()) {
712             wrapper = wrappers.next();
713             try {
714                 method =
715                     (MethodItem) ClassRepository.get().getClass(
716                         wrapper).getAbstractMethods(
717                         methodName)[0];
718             } catch (org.objectweb.jac.core.rtti.NoSuchMethodException e) {
719             }
720             if (method != null)
721                 break;
722         }
723         if (method == null) {
724             logger.warn(
725                 "no such role method " + methodName
726                     + " found on " + wrappee.getClass());
727             return ret;
728         }
729
730         try {
731
732             // Starts a new interaction
733
//Collaboration.get().newInteraction();
734
Object JavaDoc[] actualParameters;
735             if (method.getParameterTypes().length > 0
736                 && method.getParameterTypes()[0] == Wrappee.class) {
737                 actualParameters =
738                     new Object JavaDoc[method.getParameterTypes().length];
739                 actualParameters[0] = wrappee;
740                 System.arraycopy(
741                     parameters,
742                     0,
743                     actualParameters,
744                     1,
745                     actualParameters.length - 1);
746             } else {
747                 actualParameters = parameters;
748             }
749             // invoke...
750
ret = method.invoke(wrapper, actualParameters);
751
752         } finally {
753             //Collaboration.get().endOfInteraction();
754
}
755         return ret;
756     }
757
758     /**
759      * Invokes a role method on the wrappee.
760      *
761      * @param wrappee the wrappee (must be wrapped by a wrapper that
762      * supports the role method).
763      * @param wrapperClass the class of the role method to invoke.
764      * @param methodName the name of the role method to invoke.
765      * @param parameters the parameters.
766      * @return the returned object
767      */

768     public static Object JavaDoc invokeRoleMethod(
769         Wrappee wrappee,
770         Class JavaDoc wrapperClass,
771         String JavaDoc methodName,
772         Object JavaDoc[] parameters)
773     {
774         return invokeRoleMethod(
775             wrappee,
776             null,
777             wrapperClass,
778             methodName,
779             parameters);
780     }
781
782     /**
783      * Invokes a role method on the wrappee.
784      *
785      * @param wrappee the wrappee (must be wrapped by a wrapper that
786      * supports the role method).
787      * @param wrappeeClass the class of the wrapper (for static methods)
788      * @param wrapperClass the class of the role method to invoke.
789      * @param methodName the name of the role method to invoke.
790      * @param parameters the parameters.
791      * @return the returned object
792      */

793
794     public static Object JavaDoc invokeRoleMethod(
795         Wrappee wrappee,
796         ClassItem wrappeeClass,
797         Class JavaDoc wrapperClass,
798         String JavaDoc methodName,
799         Object JavaDoc[] parameters)
800     {
801         loggerRole.debug("invokeRoleMethod " + wrapperClass + "." + methodName
802                          + " on " + wrappee + "(" + wrappeeClass + ")");
803         if (wrappee == null)
804             ACManager.getACM().whenUsingNewClass(wrappeeClass);
805
806         Iterator JavaDoc wrappers = getWrappers(wrappee, wrappeeClass).iterator();
807         Object JavaDoc ret = null;
808         MethodItem method = null;
809         Object JavaDoc wrapper = null;
810
811         loggerRole.debug("wrappers for " + wrappee + "(" + wrappeeClass + ") : "
812                          + getWrappers(wrappee, wrappeeClass));
813
814         // Seek the role method
815
while (wrappers.hasNext()) {
816             wrapper = wrappers.next();
817             if (wrapperClass.isAssignableFrom(wrapper.getClass())) {
818                 try {
819                     method =
820                         (MethodItem) ClassRepository.get().getClass(
821                             wrapper).getAbstractMethods(
822                             methodName)[0];
823                 } catch (org.objectweb.jac.core.rtti.NoSuchMethodException e) {
824                     logger.warn(
825                         "no such role method " + methodName
826                             + " found on " + wrappee.getClass());
827                     return ret;
828                 }
829             }
830             if (method != null)
831                 break;
832         }
833
834         if (method == null) {
835             logger.warn(
836                 "no such role method "+ methodName +
837                 " found on " + wrappee.getClass());
838             return ret;
839         }
840         try {
841
842             // Starts a new interaction
843
//Collaboration.get().newInteraction();
844
Object JavaDoc[] actualParameters;
845             Class JavaDoc parameterTypes[] = method.getParameterTypes();
846             if (parameterTypes.length > 0
847                 && parameterTypes[0] == Wrappee.class) {
848                 actualParameters = new Object JavaDoc[parameterTypes.length];
849                 actualParameters[0] = wrappee;
850                 System.arraycopy(
851                     parameters,
852                     0,
853                     actualParameters,
854                     1,
855                     actualParameters.length - 1);
856             } else {
857                 actualParameters = parameters;
858             }
859
860             // invoke...
861
ret = method.invoke(wrapper, actualParameters);
862
863         } finally {
864             //Collaboration.get().endOfInteraction();
865
}
866         return ret;
867     }
868
869     /**
870      * This method can be used to shortcut the wrapping chain and
871      * directly call the original method.
872      *
873      * <p><b>NOTE</b>: avoid doing this unless you really know what you
874      * are doing. It is not clean to shortcut the whole wrapping
875      * chain. Instead, use the <code>invoke</code> method or, if you
876      * really need to,
877      * <code>AspectComponent.before/afterRunningWrapper()</code> to
878      * skip some wrappers.
879      *
880      * @param wrappee the object that supports the method
881      * @param name the name of the method to call
882      * @param parameters the argument values
883      * @return the called method return value as an object
884      *
885      * @see AspectComponent#beforeRunningWrapper(Wrapper,String)
886      * @see AspectComponent#afterRunningWrapper(Wrapper,String)
887      **/

888
889     public static Object JavaDoc invokeOrg(
890         Wrappee wrappee,
891         String JavaDoc name,
892         Object JavaDoc[] parameters)
893     {
894         Object JavaDoc ret = null;
895
896         Method JavaDoc[] methods = wrappee.getClass().getMethods();
897         boolean ok = false;
898         boolean found = false;
899         String JavaDoc orgName =
900             "_org_"
901                 + name
902                 + "_"
903                 + NamingConventions.getShortClassName(wrappee.getClass());
904         for (int i = 0; i < methods.length; i++) {
905             if (methods[i].getParameterTypes().length == parameters.length
906                 && methods[i].getName().equals(orgName)) {
907                 found = true;
908                 try {
909                     ok = false;
910                     ret = methods[i].invoke(wrappee, parameters);
911                     ok = true;
912                 } catch (IllegalArgumentException JavaDoc e) {
913                 } catch (InvocationTargetException JavaDoc e) {
914                     Throwable JavaDoc t = e.getTargetException();
915                     if (t instanceof RuntimeException JavaDoc) {
916                         throw (RuntimeException JavaDoc) t;
917                     }
918                     throw new RuntimeException JavaDoc(
919                         "invokeOrg("
920                             + wrappee + ","
921                             + name + ","
922                             + Arrays.asList(parameters) + ") failed: " + e);
923                 } catch (IllegalAccessException JavaDoc e) {
924                     throw new RuntimeException JavaDoc(
925                         "invokeOrg("
926                             + wrappee + ","
927                             + name + ","
928                             + Arrays.asList(parameters) + ") failed: " + e);
929                 }
930                 if (ok)
931                     break;
932             }
933         }
934         // if there was no "_org_" prefixed method, try to call the method directly
935
if (!found) {
936             logger.warn(
937                 "original method "
938                     + orgName
939                     + " was not found in "
940                     + wrappee.getClass().getName());
941             for (int i = 0; i < methods.length; i++) {
942                 if (methods[i].getName().equals(name)
943                     && methods[i].getParameterTypes().length
944                         == parameters.length) {
945                     try {
946                         ok = false;
947                         ret = methods[i].invoke(wrappee, parameters);
948                         ok = true;
949                     } catch (IllegalArgumentException JavaDoc e) {
950                     } catch (InvocationTargetException JavaDoc e) {
951                         Throwable JavaDoc t = e.getTargetException();
952                         if (t instanceof RuntimeException JavaDoc) {
953                             throw (RuntimeException JavaDoc) t;
954                         }
955                         throw new RuntimeException JavaDoc(
956                             "invokeOrg("
957                                 + wrappee + ","
958                                 + name + ","
959                                 + Arrays.asList(parameters) + ") failed: " + e);
960                     } catch (IllegalAccessException JavaDoc e) {
961                         throw new RuntimeException JavaDoc(
962                             "invokeOrg("
963                                 + wrappee + ","
964                                 + name + ","
965                                 + Arrays.asList(parameters) + ") failed: " + e);
966                     }
967                     if (ok)
968                         break;
969                 }
970             }
971         }
972         if (!ok) {
973             throw new IllegalArgumentException JavaDoc(
974                 "No such original method has been found: "
975                     + wrappee.getClass().getName()
976                     + "."
977                     + name);
978         }
979
980         return ret;
981     }
982
983
984     public static Object JavaDoc invokeOrg(
985         Wrappee wrappee,
986         MethodItem method,
987         Object JavaDoc[] parameters)
988     {
989         try {
990             return method.getOrgMethod().invoke(wrappee, parameters);
991         } catch (InvocationTargetException JavaDoc e) {
992             Throwable JavaDoc t = e.getTargetException();
993             if (t instanceof RuntimeException JavaDoc) {
994                 throw (RuntimeException JavaDoc) t;
995             }
996             throw new RuntimeException JavaDoc(
997                 "invokeOrg("
998                 + wrappee + "," + method.getName() + "," + Arrays.asList(parameters)
999                 + ") failed: " + e);
1000        } catch (IllegalAccessException JavaDoc e) {
1001            throw new RuntimeException JavaDoc(
1002                "invokeOrg("
1003                + wrappee + "," + method.getName() + "," + Arrays.asList(parameters)
1004                + ") failed: " + e);
1005        }
1006    }
1007
1008    public static Object JavaDoc clone(Object JavaDoc org) {
1009        return org;
1010    }
1011
1012    // -------
1013
// Internal JAC method used to initialize or execute wrapping chains
1014

1015    /**
1016     * This method factorizes the common code that is used when the
1017     * next wrapper is called.
1018     *
1019     * @param interaction the method call being intercepted
1020     */

1021    public static Object JavaDoc nextWrapper(Interaction interaction)
1022    // throws Throwable
1023
{
1024        Logger methodLogger = Logger.getLogger("wrapping." + interaction.method.getName());
1025        if (methodLogger.isDebugEnabled())
1026            methodLogger.debug(
1027                "nextWrapper "
1028                + interaction.method.getParent()+"."+interaction.method
1029                + ", rank=" + interaction.rank
1030                + ", isConstructor=" + (interaction.method instanceof ConstructorItem));
1031        Object JavaDoc ret = null;
1032        //boolean start_rank = interaction.rank == 0;
1033
Method JavaDoc m = null; // invoked method (wrapping method or _org_)
1034

1035        //Collaboration collaboration = Collaboration.get();
1036
int rank = interaction.rank;
1037        Wrappee wrappee = interaction.wrappee;
1038        AbstractMethodItem method = interaction.method;
1039        String JavaDoc forcedName = null;
1040
1041        try {
1042
1043            if (rank == 0) {
1044                //collaboration.newInteraction();
1045

1046                //Log.trace("jac", "done.");
1047
// here, the attribute is persistent for optimization purpose
1048
// we save it to restore it at the end
1049

1050                //oldApplicationName = collaboration.getCurApp();
1051
if (method instanceof ConstructorItem) {
1052                    // only call whenUsingNewInstance once for each method
1053
if (((ClassItem) method.getParent()).getActualClass()
1054                        == wrappee.getClass()) {
1055                        ObjectRepository.register(wrappee);
1056                        if (ACManager.getACM() != null) {
1057                            loggerWuni.debug("calling WUNI on " + Strings.hex(wrappee));
1058                            ACManager.getACM().whenUsingNewInstance(
1059                                interaction);
1060                            interaction.wrappingChain =
1061                                getWrappingChain(wrappee, method).chain;
1062                        }
1063                        // <HACK>
1064
} else {
1065                        // We have to save the forced name if there's one,
1066
// or it could be used for some object created by
1067
// the super constructor (like collections's vector)
1068
Collaboration collab = Collaboration.get();
1069                        forcedName = (String JavaDoc) collab.getAttribute(Naming.FORCE_NAME);
1070                        if (forcedName != null) {
1071                            collab.removeAttribute(Naming.FORCE_NAME);
1072                        }
1073                    }
1074                    // </HACK>
1075
} else if (method.isStatic() && ACManager.getACM() != null) {
1076                    //wrappingChain=getWrappingChain(wrappee,method);
1077
loggerWuni.debug("calling WUNI for static method "
1078                                     + method.getParent() + "." + method);
1079                    ACManager.getACM().whenUsingNewClass(
1080                        interaction.getClassItem());
1081                    interaction.wrappingChain =
1082                        getWrappingChain(wrappee, method).chain;
1083                }
1084            }
1085
1086            if (methodLogger.isDebugEnabled())
1087                methodLogger.debug("wrapping chain: "
1088                                   + printWrappingChain(interaction.wrappingChain));
1089            //System.out.println("===>"+interaction.wrappingChain);
1090

1091            if (rank < interaction.wrappingChain.length) {
1092                Interceptor to_invoke =
1093                    interaction.wrappingChain[rank];
1094                if (method instanceof ConstructorItem){
1095                    ret = ((ConstructorInterceptor)to_invoke).construct(interaction);
1096                } else {
1097                    ret = ((MethodInterceptor)to_invoke).invoke(interaction);
1098                }
1099                //Log.trace("jac", "wrapping method returns " + ret );
1100
} else {
1101                //Log.trace("jac", "calling org " + method );
1102
// collaboration.setCurAC(null);
1103
if (method instanceof ConstructorItem || method.isStatic()) {
1104                    try {
1105                        ret =
1106                            ((ClassItem) method.getParent())
1107                                .getActualClass()
1108                                .getMethod(
1109                                    "_org_" + method.getName(),
1110                                    method.getParameterTypes())
1111                                .invoke(wrappee, interaction.args);
1112                    } catch (java.lang.NoSuchMethodException JavaDoc e) {
1113                        throw new RuntimeException JavaDoc(
1114                            "Failed to invoke org method "
1115                                + "_org_" + method.getName()
1116                                + " on " + wrappee
1117                                + ": " + e);
1118                    }
1119                } else {
1120                    m = ((MethodItem) method).getOrgMethod();
1121                    if (m != null) {
1122                        ret = m.invoke(wrappee, interaction.args);
1123                    } else {
1124                        try {
1125                            m =
1126                                ClassRepository.getDirectMethodAccess(
1127                                    wrappee.getClass(),
1128                                    "_org_" + method.getName())[0];
1129                            ret = m.invoke(wrappee, interaction.args);
1130                        } catch (IllegalArgumentException JavaDoc ill) {
1131                            try {
1132                                ret =
1133                                    ClassRepository.invokeDirect(
1134                                        wrappee.getClass(),
1135                                        "_org_" + method.getName(),
1136                                        wrappee,
1137                                        interaction.args);
1138                            } catch (java.lang.NoSuchMethodException JavaDoc e) {
1139                                throw new RuntimeException JavaDoc(
1140                                    "Failed to invoke org method "
1141                                        + "_org_" + method.getName()
1142                                        + " on " + wrappee
1143                                        + ": " + e);
1144                            }
1145                        }
1146                    }
1147                }
1148
1149                //Log.trace("jac", "end of calling org " + method + " ret="+ret);
1150

1151            }
1152
1153        } catch (Throwable JavaDoc t) {
1154            if(t instanceof InvocationTargetException JavaDoc)
1155                t=((InvocationTargetException JavaDoc)t).getTargetException();
1156            loggerExc.info(interaction.wrappee+ "."+ method
1157                      + "(" + m + ") catching " + t);
1158            WrappedThrowableException wrapped = null;
1159            if (t instanceof WrappedThrowableException) {
1160                wrapped = (WrappedThrowableException) t;
1161                t = ((WrappedThrowableException) t).getWrappedThrowable();
1162            }
1163            // loggerExc.info("wrapped exception is "+t);
1164
/*
1165            if (start_rank) {
1166               collaboration.endOfInteraction();
1167            }
1168            */

1169
1170            boolean caught = false;
1171
1172            List JavaDoc catchingChain = getCatchingChain(wrappee, method);
1173
1174            if (catchingChain != null) {
1175                Iterator JavaDoc it = catchingChain.iterator();
1176                loggerExc.info("trying to find catcher...");
1177                while (it.hasNext()) {
1178                    try {
1179                        Object JavaDoc[] wm = (Object JavaDoc[]) it.next();
1180                        loggerExc.info("trying " + wm[1]
1181                                  + " on " + wm[0]
1182                                  + " (" + t + ")"
1183                                  + " ->" + t.getClass());
1184                        ((Method JavaDoc) wm[1]).invoke(wm[0], new Object JavaDoc[] { t });
1185                        loggerExc.info("caught.");
1186                        caught = true;
1187                        // several handlers on the same exception can cause trouble!!!
1188
// e.g.: InputWrapper.inputCanceled + TransactionWrapper.rollback!
1189
// => handlers should be correctly ordered!
1190
break;
1191                    } catch (Exception JavaDoc e1) {
1192                        if ((e1 instanceof InvocationTargetException JavaDoc)) {
1193                            //logger.warn("oops! Exception handler generates an exception");
1194
throw new WrappedThrowableException(
1195                                ((InvocationTargetException JavaDoc) e1)
1196                                    .getTargetException());
1197                        }
1198                    }
1199                }
1200            }
1201
1202            if (!caught) {
1203                loggerExc.info("forwarding exception " + t);
1204                loggerExc.debug("forwarding exception",t);
1205                if (wrapped != null) {
1206                    throw wrapped;
1207                } else {
1208                    throw new WrappedThrowableException(t);
1209                }
1210            } else {
1211                loggerExc.info("silent exception");
1212            }
1213        }
1214
1215        if (forcedName != null) {
1216            Collaboration.get().addAttribute(Naming.FORCE_NAME, forcedName);
1217        }
1218        return ret;
1219    }
1220
1221    public static Object JavaDoc methodNextWrapper(Interaction interaction) {
1222        //Collaboration collaboration = Collaboration.get();
1223
Logger methodLogger = Logger.getLogger("wrapping." + interaction.method.getName());
1224        if (methodLogger.isDebugEnabled())
1225            methodLogger.debug("methodNextWrapper " + interaction.method.getLongName());
1226        try {
1227            if (interaction.wrappingChain.length > 0) {
1228                return (
1229                    (MethodInterceptor) interaction.wrappingChain[0]).invoke(
1230                    interaction);
1231            } else {
1232                if (methodLogger.isDebugEnabled())
1233                    methodLogger.debug(
1234                        "invoke org method "
1235                        + ((MethodItem) interaction.method).getOrgMethod());
1236                return ((MethodItem) interaction.method).getOrgMethod().invoke(
1237                    interaction.wrappee,
1238                    interaction.args);
1239            }
1240        } catch (Throwable JavaDoc t) {
1241            if(t instanceof InvocationTargetException JavaDoc)
1242                t=((InvocationTargetException JavaDoc)t).getTargetException();
1243            loggerExc.info("Catching " + t + " (stack trace follows)",t);
1244            WrappedThrowableException wrapped = null;
1245            if (t instanceof WrappedThrowableException) {
1246                wrapped = (WrappedThrowableException) t;
1247                t = ((WrappedThrowableException) t).getWrappedThrowable();
1248            }
1249            boolean caught = false;
1250
1251            List JavaDoc catchingChain =
1252                getCatchingChain(interaction.wrappee, interaction.method);
1253
1254            if (catchingChain != null) {
1255                Iterator JavaDoc it = catchingChain.iterator();
1256                while (it.hasNext()) {
1257                    try {
1258                        Object JavaDoc[] wm = (Object JavaDoc[]) it.next();
1259                        ((Method JavaDoc) wm[1]).invoke(wm[0], new Object JavaDoc[] { t });
1260                        caught = true;
1261                        // several handlers on the same exception can cause trouble!!!
1262
// e.g.: InputWrapper.inputCanceled + TransactionWrapper.rollback!
1263
// => handlers should be correctly ordered!
1264
break;
1265                    } catch (Exception JavaDoc e1) {
1266                        if ((e1 instanceof InvocationTargetException JavaDoc)) {
1267                            //logger.warn("oops! Exception handler generates an exception");
1268
throw new WrappedThrowableException(
1269                                ((InvocationTargetException JavaDoc) e1)
1270                                    .getTargetException());
1271                        }
1272                    }
1273                }
1274            }
1275
1276            if (!caught) {
1277                loggerExc.info("forwarding exception " + t);
1278                loggerExc.debug("forwarding exception",t);
1279                if (wrapped != null) {
1280                    throw wrapped;
1281                } else {
1282                    throw new WrappedThrowableException(t);
1283                }
1284            }
1285
1286            return null;
1287        }
1288
1289    }
1290}
1291
Popular Tags