KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > fractal > julia > asm > MergeClassGenerator


1 /***
2  * Julia: France Telecom's implementation of the Fractal API
3  * Copyright (C) 2001-2002 France Telecom R&D
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Contact: Eric.Bruneton@rd.francetelecom.com
20  *
21  * Author: Eric Bruneton
22  */

23
24 package org.objectweb.fractal.julia.asm;
25
26 import org.objectweb.fractal.api.control.BindingController;
27 import org.objectweb.fractal.api.control.LifeCycleController;
28
29 import org.objectweb.fractal.julia.control.binding.ContentBindingController;
30 import org.objectweb.fractal.julia.control.lifecycle.ContentLifeCycleController;
31 import org.objectweb.fractal.julia.loader.Generated;
32 import org.objectweb.fractal.julia.loader.Loader;
33 import org.objectweb.fractal.julia.loader.Tree;
34 import org.objectweb.fractal.julia.loader.Initializable;
35
36 import org.objectweb.asm.ClassAdapter;
37 import org.objectweb.asm.ClassReader;
38 import org.objectweb.asm.ClassVisitor;
39 import org.objectweb.asm.ClassWriter;
40 import org.objectweb.asm.CodeAdapter;
41 import org.objectweb.asm.CodeVisitor;
42 import org.objectweb.asm.Constants;
43 import org.objectweb.asm.Type;
44 import org.objectweb.asm.Attribute;
45
46 import java.io.IOException JavaDoc;
47 import java.lang.reflect.Method JavaDoc;
48 import java.lang.reflect.Modifier JavaDoc;
49 import java.util.ArrayList JavaDoc;
50 import java.util.HashMap JavaDoc;
51 import java.util.List JavaDoc;
52 import java.util.Map JavaDoc;
53
54 /**
55  * A class generator to merge several classes into a single one. This class
56  * generator copies all the non static fields and all the non static methods of
57  * the given classes (and of their super class, super super class, and so on)
58  * into a new class, with the following exceptions:
59  * <ul>
60  * <li>fields whose name begins with "weaveable" are replaced by <tt>this</tt>.
61  * One of the merged classes must implement the corresponding interface,
62  * otherwise an exception is thrown.</li>
63  * <li>fields whose name begins with "weaveableOpt" are replaced by
64  * <tt>this</tt> if the corresponding interface is implemented by one of the
65  * merged classes, or by <tt>null</tt> otherwise.</li>
66  * <li>the method of the {@link org.objectweb.fractal.julia.Controller}
67  * interface are merged into a single method.</li>
68  * </ul>
69  * <b>Notes</b>:
70  * <ul>
71  * <li>since static fields and methods are not copied, and since the generated
72  * class will generally not be in the same package than the original classes,
73  * all the static fields and methods used by the non static methods must be
74  * public (but those that are used only by static methods may be private).</li>
75  * <li>the constructors are not copied (this limitation will perhaps be removed
76  * in future versions).</li>
77  * </ul>
78  * Except for the "weaveable" fields, and for the {@link
79  * org.objectweb.fractal.julia.Controller} method, the fields and methods of the
80  * classes to be merged should all be distinct: otherwise the generated class
81  * will not be valid, because of duplicated field or method declarations.
82  * <p>
83  * As an example, the merging of the B and C classes below:
84  * <pre>
85  * public class A {
86  * public int a;
87  * public void m () { ... }
88  * }
89  *
90  * public class B extends A implements I {
91  * private int b;
92  * private J weaveableJ;
93  * private K weaveableOptK;
94  * public void m () { super.m(); ... }
95  * public void n () { weaveableJ.o(weaveableOptK); }
96  * }
97  *
98  * public class C implement J {
99  * public void o (K k) { p(); }
100  * public static p () { q(); }
101  * private static q () { ... }
102  * }
103  * </pre>
104  * is the following class:
105  * <pre>
106  * public class <i>XYZ</i> implements I, J, Generated {
107  * public int a; // copied from B's super class
108  * private int b; // copied from B
109  * // weaveableJ // NOT copied
110  * // weaveableOptK // NOT copied
111  * private void m$0 () { ... } // copied from B's super class
112  * public void m () { m$0(); ... } // copied from B
113  * public void n () { <b>o(null);</b> } // copied from B
114  * public void o (K k) { <b>C.</b>p(); } // copied from C
115  * // p // NOT copied (static)
116  * // q // NOT copied (static)
117  * public String getFcGeneratorParameters () {
118  * return "(...MergeClassGenerator java.lang.Object B C)";
119  * }
120  * }
121  * </pre>
122  */

123
124 public class MergeClassGenerator implements ClassGenerator, Constants {
125
126   /**
127    * The loader to be used to load or generate auxiliary classes, if needed.
128    */

129
130   public Loader loader;
131
132   /**
133    * The class loader to be used to load auxiliary classes, if needed.
134    */

135   
136   public ClassLoader JavaDoc classLoader;
137   
138   /**
139    * The parameters used to generate the merged class.
140    */

141
142   public String JavaDoc parameters;
143
144   /**
145    * Internal name of the merged class generated by this generator.
146    */

147
148   String JavaDoc mergedClassName;
149
150   /**
151    * The interfaces implemented by the classes to be merged. This list is a
152    * list of Class object.
153    */

154
155   List JavaDoc interfaces;
156
157   /**
158    * Index of the class that is currently being merged into the merged class.
159    */

160
161   int currentClassIndex;
162
163   /**
164    * Internal name of the class that is currently being merged into the merged
165    * class.
166    */

167
168   String JavaDoc currentClassName;
169
170   /**
171    * The class that is currently being merged into the merged class.
172    */

173
174   Class JavaDoc currentClass;
175
176   /**
177    * The super classes of the class that is currently being merged into the
178    * merged class.
179    */

180
181   List JavaDoc inheritedClasses;
182
183   /**
184    * A map associating a counter to each method name and descriptor. These
185    * Integer counters are used to rename overriden methods with "$x" suffixes.
186    * Each counter corresponds to the number of time the corresponding method
187    * is overriden by the sub classes of its class, minus one.
188    */

189
190   Map JavaDoc counters;
191
192   /**
193    * The code visitor used to generate the merged "initialize" method.
194    */

195
196   CodeVisitor inicv;
197
198   /**
199    * The code visitor used to generate the merged "initFcController" method.
200    */

201
202   CodeVisitor icv;
203
204   /**
205    * Generates a class by merging the given classes.
206    *
207    * @param name the name of the class to be generated.
208    * @param args a tree of the form "(objectDescriptor superClassName
209    * className1 ... classNameN)", where className1 ... classNameN are the
210    * names of the classes to be merged, and superClassName is the name of
211    * the super class to be used for the merged class.
212    * @param loader the loader to be used to load or generate auxiliary classes,
213    * if needed.
214    * @param classLoader the class loader to be used to load auxiliary classes,
215    * if needed.
216    * @return a class constructed by merging the given classes.
217    * @throws ClassGenerationException if a problem occurs during the generation
218    * of the class.
219    */

220
221   public byte[] generateClass (
222     final String JavaDoc name,
223     final Tree args,
224     final Loader loader,
225     final ClassLoader JavaDoc classLoader) throws ClassGenerationException
226   {
227     this.loader = loader;
228     this.classLoader = classLoader;
229     String JavaDoc superClassName = args.getSubTree(1).toString().replace('.', '/');
230     mergedClassName = name.replace('.', '/');
231
232     Class JavaDoc[] classes = new Class JavaDoc[args.getSize() - 2];
233     interfaces = new ArrayList JavaDoc();
234     interfaces.add(Generated.class);
235     interfaces.add(Initializable.class);
236     for (int i = 0; i < classes.length; ++i) {
237       try {
238         classes[i] = loader.loadClass(args.getSubTree(i + 2), classLoader);
239       } catch (ClassNotFoundException JavaDoc e) {
240         throw new ClassGenerationException(
241           e,
242           args.toString(),
243           "Cannot load the '" + args.getSubTree(i + 2) + "' class");
244       }
245       Class JavaDoc c = classes[i];
246       while (c != Object JavaDoc.class) {
247         Class JavaDoc[] citfs = c.getInterfaces();
248         for (int j = 0; j < citfs.length; ++j) {
249           if (!interfaces.contains(citfs[j])) {
250             interfaces.add(citfs[j]);
251           }
252         }
253         c = c.getSuperclass();
254       }
255     }
256     // adds the ContentLifeCycleController interface if the super class
257
// implements LifeCycleController (see ContentLifeCycleController);
258
// likewise for ContentBindingController
259
Class JavaDoc superClass;
260     try {
261       superClass = loader.loadClass(args.getSubTree(1), classLoader);
262     } catch (ClassNotFoundException JavaDoc e) {
263       throw new ClassGenerationException(
264         e,
265         args.toString(),
266         "Cannot load the '" + args.getSubTree(1) + "' class");
267     }
268     if (LifeCycleController.class.isAssignableFrom(superClass)) {
269       interfaces.add(ContentLifeCycleController.class);
270     }
271     if (BindingController.class.isAssignableFrom(superClass)) {
272       interfaces.add(ContentBindingController.class);
273     }
274
275     // creates an empty class
276
ClassWriter cw = new ClassWriter(false);
277     String JavaDoc[] itfs = new String JavaDoc[interfaces.size()];
278     for (int i = 0; i < itfs.length; ++i) {
279       itfs[i] = Type.getInternalName((Class JavaDoc)interfaces.get(i));
280     }
281     cw.visit(V1_1, ACC_PUBLIC, mergedClassName, superClassName, itfs, "MERGED");
282
283     // generates the default constructor
284
CodeVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
285     mw.visitVarInsn(ALOAD, 0);
286     mw.visitMethodInsn(INVOKESPECIAL, superClassName, "<init>", "()V");
287     mw.visitInsn(RETURN);
288     mw.visitMaxs(1, 1);
289
290     // generates the 'getFcGeneratorParameters' method
291
parameters = args.toString();
292     String JavaDoc mName = "getFcGeneratorParameters";
293     String JavaDoc mDesc = "()Ljava/lang/String;";
294     CodeVisitor mv = cw.visitMethod(ACC_PUBLIC, mName, mDesc, null, null);
295     mv.visitLdcInsn(parameters);
296     mv.visitInsn(ARETURN);
297     mv.visitMaxs(1, 1);
298
299     // generates the 'initialize' method
300
inicv = cw.visitMethod(
301       ACC_PUBLIC,
302       "initialize",
303       "(Lorg/objectweb/fractal/julia/loader/Tree;)V",
304       null,
305       null);
306
307     // generates the 'initFcController' method
308
icv = cw.visitMethod(
309       ACC_PUBLIC,
310       "initFcController",
311       "(Lorg/objectweb/fractal/julia/InitializationContext;)V",
312       null,
313       null);
314
315     // merges all the classes
316
for (int i = 0; i < classes.length; ++i) {
317       inheritedClasses = new ArrayList JavaDoc();
318       counters = new HashMap JavaDoc();
319
320       Class JavaDoc c = classes[i];
321       while (c != Object JavaDoc.class) {
322         inheritedClasses.add(Type.getInternalName(c));
323         c = c.getSuperclass();
324       }
325
326       c = classes[i];
327       while (c != Object JavaDoc.class) {
328         currentClass = c;
329         currentClassIndex = i;
330         currentClassName = Type.getInternalName(c);
331         MergeClassAdapter mca = new MergeClassAdapter(cw);
332         try {
333           getClassReader(c).accept(mca, false);
334         } catch (IOException JavaDoc e) {
335           throw new ClassGenerationException(
336             e, args.toString(), "Cannot read the '" + c.getName() + "' class");
337         } catch (VisitException e) {
338           throw e.getException();
339         }
340         updateCounters(c);
341         c = c.getSuperclass();
342       }
343     }
344
345     inicv.visitInsn(RETURN);
346     inicv.visitMaxs(3, 2);
347
348     icv.visitInsn(RETURN);
349     icv.visitMaxs(2, 2);
350
351     // generates the ContentLifeCycleController interface if the super class
352
// implements LifeCycleController (see ContentLifeCycleController)
353
if (LifeCycleController.class.isAssignableFrom(superClass)) {
354       // generates the 'startFcContent' method
355
mName = "startFcContent";
356       mv = cw.visitMethod(ACC_PUBLIC, mName, "()V", null, null);
357       mv.visitVarInsn(ALOAD, 0);
358       mv.visitMethodInsn(INVOKESPECIAL, superClassName, "startFc", "()V");
359       mv.visitInsn(RETURN);
360       mv.visitMaxs(1, 1);
361       // generates the 'stopFcContent' method
362
mName = "stopFcContent";
363       mv = cw.visitMethod(ACC_PUBLIC, mName, "()V", null, null);
364       mv.visitVarInsn(ALOAD, 0);
365       mv.visitMethodInsn(INVOKESPECIAL, superClassName, "stopFc", "()V");
366       mv.visitInsn(RETURN);
367       mv.visitMaxs(1, 1);
368     }
369
370     // generates the ContentBindingController interface if the super class
371
// implements BindingController (see ContentBindingController)
372
if (BindingController.class.isAssignableFrom(superClass)) {
373       // generates the 'listFcContent' method
374
mName = "listFcContent";
375       mv = cw.visitMethod(
376         ACC_PUBLIC, mName, "()[Ljava/lang/String;", null, null);
377       mv.visitVarInsn(ALOAD, 0);
378       mv.visitMethodInsn(
379         INVOKESPECIAL, superClassName, "listFc", "()[Ljava/lang/String;");
380       mv.visitInsn(ARETURN);
381       mv.visitMaxs(1, 1);
382       // generates the 'lookupFcContent' method
383
mName = "lookupFcContent";
384       mv = cw.visitMethod(
385         ACC_PUBLIC, mName, "(Ljava/lang/String;)Ljava/lang/Object;", null, null);
386       mv.visitVarInsn(ALOAD, 0);
387       mv.visitVarInsn(ALOAD, 1);
388       mv.visitMethodInsn(
389         INVOKESPECIAL,
390         superClassName,
391         "lookupFc",
392         "(Ljava/lang/String;)Ljava/lang/Object;");
393       mv.visitInsn(ARETURN);
394       mv.visitMaxs(2, 2);
395       // generates the 'bindFcContent' method
396
mName = "bindFcContent";
397       mv = cw.visitMethod(
398         ACC_PUBLIC, mName, "(Ljava/lang/String;Ljava/lang/Object;)V", null, null);
399       mv.visitVarInsn(ALOAD, 0);
400       mv.visitVarInsn(ALOAD, 1);
401       mv.visitVarInsn(ALOAD, 2);
402       mv.visitMethodInsn(
403         INVOKESPECIAL,
404         superClassName,
405         "bindFc",
406         "(Ljava/lang/String;Ljava/lang/Object;)V");
407       mv.visitInsn(RETURN);
408       mv.visitMaxs(3, 3);
409       // generates the 'unbindFcContent' method
410
mName = "unbindFcContent";
411       mv = cw.visitMethod(
412         ACC_PUBLIC, mName, "(Ljava/lang/String;)V", null, null);
413       mv.visitVarInsn(ALOAD, 0);
414       mv.visitVarInsn(ALOAD, 1);
415       mv.visitMethodInsn(
416         INVOKESPECIAL, superClassName, "unbindFc", "(Ljava/lang/String;)V");
417       mv.visitInsn(RETURN);
418       mv.visitMaxs(2, 2);
419     }
420
421     // returns the merged class
422
return cw.toByteArray();
423   }
424
425   /**
426    * Returns a {@link ClassReader} to analyze the given class.
427    *
428    * @param c a class.
429    * @return a {@link ClassReader} to analyze the given class.
430    * @throws IOException if the bytecode of the class cannot be found.
431    */

432
433   ClassReader getClassReader (final Class JavaDoc c) throws IOException JavaDoc {
434     try {
435       return new ClassReader(c.getName());
436     } catch (IOException JavaDoc e) {
437       // an exception can occur if c is a dynamically generated class;
438
// indeed, in this case, it can not be found by the system class loader.
439
String JavaDoc s = Type.getInternalName(c) + ".class";
440       return new ClassReader(c.getClassLoader().getResourceAsStream(s));
441     }
442   }
443
444   /**
445    * Returns the counter associated to the given method.
446    *
447    * @param name the method's name.
448    * @param desc the method's descriptor.
449    * @return the counter associated to the given method.
450    */

451
452   int getCounter (final String JavaDoc name, final String JavaDoc desc) {
453     Integer JavaDoc value = (Integer JavaDoc)counters.get(name + desc);
454     return value == null ? -1 : value.intValue();
455   }
456
457   /**
458    * Updates the {@link #counters counters} map with the given class. This
459    * method increments the counter associated to each non static method of the
460    * given class.
461    *
462    * @param c a class.
463    */

464
465   void updateCounters (final Class JavaDoc c) {
466     Method JavaDoc[] meths = c.getDeclaredMethods();
467     for (int i = 0; i < meths.length; ++i) {
468       Method JavaDoc meth = meths[i];
469       if (!Modifier.isStatic(meth.getModifiers())) {
470         String JavaDoc key = meth.getName() + Type.getMethodDescriptor(meth);
471         Integer JavaDoc value = (Integer JavaDoc)counters.get(key);
472         int count = value == null ? 0 : value.intValue() + 1;
473         counters.put(key, new Integer JavaDoc(count));
474       }
475     }
476   }
477
478   /**
479    * Tests if the given method is declared in the given class.
480    *
481    * @param m the name and descriptor of a method.
482    * @param c a class.
483    * @return <tt>true</tt> if the <tt>c</tt> declares a method with same name,
484    * the same formal parameter types, and the same return type than
485    * <tt>m</tt>.
486    */

487
488   static boolean declares (final String JavaDoc m, final Class JavaDoc c) {
489     Method JavaDoc[] meths = c.getDeclaredMethods();
490     for (int i = 0; i < meths.length; ++i) {
491       if (m.equals(meths[i].getName() + Type.getMethodDescriptor(meths[i]))) {
492         return true;
493       }
494     }
495     return false;
496   }
497
498   /**
499    * A class adapter to remove some fields and methods in a class to be merged.
500    */

501
502   class MergeClassAdapter extends ClassAdapter implements Constants {
503
504     /**
505      * Constructs a new {@link MergeClassGenerator.MergeClassAdapter} object.
506      *
507      * @param cv the class vistor to which this adapter must delegate calls.
508      */

509
510     public MergeClassAdapter (final ClassVisitor cv) {
511       super(cv);
512     }
513
514     public void visit (
515       final int version,
516       final int access,
517       final String JavaDoc name,
518       final String JavaDoc superName,
519       final String JavaDoc[] interfaces,
520       final String JavaDoc sourceFile)
521     {
522       // does nothing
523
}
524
525     public void visitField (
526       final int access,
527       final String JavaDoc name,
528       final String JavaDoc desc,
529       final Object JavaDoc value,
530       final Attribute attrs)
531     {
532       if ((access & ACC_STATIC) == 0) {
533         if (!name.startsWith("weaveable")) {
534           super.visitField(access, name, desc, value, attrs);
535         }
536       }
537     }
538
539     public CodeVisitor visitMethod (
540       final int access,
541       final String JavaDoc name,
542       final String JavaDoc desc,
543       final String JavaDoc[] exceptions,
544       final Attribute attrs)
545     {
546       if ((access & ACC_STATIC) != 0 ||
547           (access & ACC_ABSTRACT) != 0 ||
548           name.equals("<init>") ||
549           name.startsWith("getFcGeneratorParameters"))
550       {
551         return null;
552       }
553       CodeVisitor mv;
554       int count = getCounter(name, desc);
555       if (count == -1) {
556         if (name.equals("initFcController")) {
557           icv.visitVarInsn(ALOAD, 0);
558           icv.visitVarInsn(ALOAD, 1);
559           icv.visitMethodInsn(
560             INVOKESPECIAL,
561             mergedClassName,
562             "$" + currentClassIndex + "$" + name,
563             "(Lorg/objectweb/fractal/julia/InitializationContext;)V");
564         }
565         if (name.equals("initialize")
566             && desc.equals("(Lorg/objectweb/fractal/julia/loader/Tree;)V"))
567         {
568           inicv.visitVarInsn(ALOAD, 0);
569           inicv.visitVarInsn(ALOAD, 1);
570           inicv.visitIntInsn(SIPUSH, currentClassIndex);
571           inicv.visitMethodInsn(
572             INVOKEVIRTUAL,
573             "org/objectweb/fractal/julia/loader/Tree",
574             "getSubTree",
575             "(I)Lorg/objectweb/fractal/julia/loader/Tree;");
576           inicv.visitMethodInsn(
577             INVOKESPECIAL,
578             mergedClassName,
579             "$" + currentClassIndex + "$" + name,
580             desc);
581         }
582
583         if (name.startsWith("initFcController")
584             || (name.startsWith("initialize")
585             && desc.equals("(Lorg/objectweb/fractal/julia/loader/Tree;)V")))
586         {
587           mv = cv.visitMethod(
588             ACC_PRIVATE,
589             "$" + currentClassIndex + "$" + name,
590             desc,
591             exceptions,
592             attrs);
593         } else {
594           mv = cv.visitMethod(access, name, desc, exceptions, attrs);
595         }
596       } else {
597         int newAccess = access & ~(ACC_PUBLIC | ACC_PROTECTED) | ACC_PRIVATE;
598         String JavaDoc newName = name + "$" + count;
599         if (name.startsWith("initFcController")
600             || (name.startsWith("initialize")
601             && desc.equals("(Lorg/objectweb/fractal/julia/loader/Tree;)V")))
602         {
603           mv = cv.visitMethod(
604             ACC_PRIVATE,
605             "$" + currentClassIndex + "$" + newName,
606             desc,
607             exceptions,
608             attrs);
609         } else {
610           mv = cv.visitMethod(newAccess, newName, desc, exceptions, attrs);
611         }
612       }
613       return new MergeCodeAdapter(mv);
614     }
615   }
616
617   /**
618    * A code adapter to replace access to removed fields in a class to be merged.
619    */

620
621   class MergeCodeAdapter extends CodeAdapter implements Constants {
622
623     /**
624      * Constructs a new {@link MergeClassGenerator.MergeCodeAdapter} object.
625      *
626      * @param cv the code vistor to which this adapter must delegate calls.
627      */

628
629     public MergeCodeAdapter (final CodeVisitor cv) {
630       super(cv);
631     }
632
633     public void visitFieldInsn (
634       final int opcode,
635       final String JavaDoc owner,
636       final String JavaDoc name,
637       final String JavaDoc desc)
638     {
639       if (opcode == GETFIELD) {
640         if (inheritedClasses.contains(owner)) {
641           boolean remove = false;
642           boolean replaceNull = false;
643           if (name.startsWith("weaveable")) {
644             remove = true;
645             String JavaDoc s = desc.substring(1, desc.length() - 1).replace('/', '.');
646             Class JavaDoc c;
647             try {
648               c = loader.loadClass(s, classLoader);
649             } catch (ClassNotFoundException JavaDoc e) {
650               throw new VisitException(new ClassGenerationException(
651                 e,
652                 parameters,
653                 "Cannot load the '" + s +
654                 "' interface required by one the classes to be merged"));
655             }
656             replaceNull = true;
657             for (int i = 0; i < interfaces.size(); ++i) {
658               if (c.isAssignableFrom((Class JavaDoc)interfaces.get(i))) {
659                 replaceNull = false;
660                 break;
661               }
662             }
663             if (!name.startsWith("weaveableOpt") && replaceNull) {
664               throw new VisitException(new ClassGenerationException(
665                 null,
666                 parameters,
667                 "The required interface '" + name +
668                 "' is not provided by any of the classes to be merged"));
669             }
670           }
671           if (remove) {
672             if (replaceNull) {
673               visitInsn(POP);
674               visitInsn(ACONST_NULL);
675             }
676           } else {
677             super.visitFieldInsn(opcode, mergedClassName, name, desc);
678           }
679         } else {
680           super.visitFieldInsn(opcode, owner, name, desc);
681         }
682       } else if (opcode == PUTFIELD) {
683         if (inheritedClasses.contains(owner)) {
684           if (name.startsWith("weaveable")) {
685             visitInsn(POP2);
686           } else {
687             super.visitFieldInsn(opcode, mergedClassName, name, desc);
688           }
689         } else {
690           super.visitFieldInsn(opcode, owner, name, desc);
691         }
692       } else {
693         super.visitFieldInsn(opcode, owner, name, desc);
694       }
695     }
696
697     public void visitMethodInsn (
698       final int opcode,
699       final String JavaDoc owner,
700       final String JavaDoc name,
701       final String JavaDoc desc)
702     {
703       if (opcode != INVOKESTATIC && inheritedClasses.contains(owner)) {
704         // call to a method of the current class or of one of its super classes
705
if (opcode == INVOKESPECIAL && !owner.equals(currentClassName)) {
706           // call to an overriden method
707
String JavaDoc superName;
708           if (declares(name + desc, currentClass)) {
709             superName = name + "$" + (getCounter(name, desc) + 1);
710           } else if (getCounter(name, desc) >= 0) {
711             superName = name + "$" + getCounter(name, desc);
712           } else {
713             superName = name;
714           }
715           super.visitMethodInsn(opcode, mergedClassName, superName, desc);
716         } else {
717           if (name.startsWith("initFcController")
718               || (name.startsWith("initialize")
719               && desc.equals("(Lorg/objectweb/fractal/julia/loader/Tree;)V")))
720           {
721             super.visitMethodInsn(
722               opcode,
723               mergedClassName,
724               "$" + currentClassIndex + "$" + name,
725               desc);
726           } else {
727             // call to a private method
728
super.visitMethodInsn(opcode, mergedClassName, name, desc);
729           }
730         }
731       } else {
732         super.visitMethodInsn(opcode, owner, name, desc);
733       }
734     }
735   }
736 }
737
Popular Tags