KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SOFA > Tools > Resolver


1 /* $Id: Resolver.java,v 1.2 2004/05/20 14:23:53 bures Exp $ */
2 package SOFA.Tools.Resolver;
3
4 import org.objectweb.asm.ClassAdapter;
5 import org.objectweb.asm.ClassReader;
6 import org.objectweb.asm.ClassVisitor;
7 import org.objectweb.asm.ClassWriter;
8 import org.objectweb.asm.CodeAdapter;
9 import org.objectweb.asm.CodeVisitor;
10 import org.objectweb.asm.Constants;
11 import org.objectweb.asm.Label;
12
13 /** SOFA class name resolver. Tool for augmentation of Java class files.
14   *
15   * @author Petr Hnetynka
16   */

17 public class Resolver {
18   
19   private java.util.Hashtable JavaDoc trTable;
20   
21   /** Constucts new Resolver.
22     *
23     * @param table translation table with old names as keys
24     */

25   public Resolver(java.util.Hashtable JavaDoc table) {
26     trTable = table;
27   }
28
29   /** Process byte code augmention
30     *
31     * @param is input stream with byte code
32     * @return augmented byte code
33     * @throws IOException IO exception
34     */

35   public byte[] process(java.io.InputStream JavaDoc is) throws java.io.IOException JavaDoc {
36     ClassReader cr = new ClassReader(is);
37     ClassWriter cw = new ClassWriter(false);
38     ClassVisitor cv = new SOFAClassAdapter(cw, trTable);
39     cr.accept(cv, false);
40     return cw.toByteArray();
41   }
42
43   /** Converts class name to class name used in the Java VM. Indeed, it replaces dots by slashes.
44     * E.g. java.lang.String -> java/lang/String
45     *
46     * @param className class name
47     * @return converted class name
48     */

49   public static String JavaDoc classNameToVMClassName(String JavaDoc className) {
50     StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
51     for (int i=0; i<className.length(); i++) {
52       if (className.charAt(i) == '.')
53         ret.append('/');
54       else
55         ret.append(className.charAt(i));
56     }
57     return ret.toString();
58   }
59
60   /** Converts class name of cdl definition to class name used in the Java VM.
61     * E.g. SOFA.demos.logdemo.LogInterface + ver: nenya.ms.mff.cuni.cz!0 -&gt;
62     * SOFA/demos/logdemo/LogInterface_Q_nenya_ms_mff_cuni_cz_E_0
63     *
64     * @param cdlClassName class name
65     * @param version version of cdl definition
66     * @return converted classname
67     */

68   public static String JavaDoc cdlClassNameToVMClassName(String JavaDoc cdlClassName, String JavaDoc version) {
69     StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
70     for (int i=0; i<cdlClassName.length(); i++) {
71       if (cdlClassName.charAt(i) == '.')
72         ret.append('/');
73       else
74         ret.append(cdlClassName.charAt(i));
75     }
76     ret.append("_Q_");
77     for (int i=0; i<version.length(); i++) {
78       switch (version.charAt(i)) {
79       case '.':
80         ret.append('_');
81         break;
82       case '!':
83         ret.append("_E_");
84         break;
85       default:
86         ret.append(version.charAt(i));
87       }
88     }
89     return ret.toString();
90   }
91 }
92
93 /** Performs augmentation of classes.
94   *
95   * @author Petr Hnetynka
96   */

97 class SOFAClassAdapter extends ClassAdapter implements Constants {
98   
99   private java.util.Hashtable JavaDoc trTable;
100   
101   /** Constructor
102     */

103   public SOFAClassAdapter (ClassVisitor cv, java.util.Hashtable JavaDoc table) {
104     super(cv);
105     trTable = table;
106   }
107
108   public void visit ( final int access, final String JavaDoc name, final String JavaDoc superName, final String JavaDoc[] interfaces, final String JavaDoc sourceFile) {
109     String JavaDoc newName = (String JavaDoc) trTable.get(name);
110     if (newName == null) {
111  // System.out.println("Warning: class \""+name+"\" was not augmented.");
112
newName = name;
113     }
114     String JavaDoc newSuperName = (String JavaDoc) trTable.get(superName);
115     newSuperName = (newSuperName != null) ? newSuperName : superName;
116     String JavaDoc [] newInterfaces = new String JavaDoc [interfaces.length];
117     for (int i=0; i<interfaces.length; i++) {
118       newInterfaces[i] = (String JavaDoc) trTable.get(interfaces[i]);
119       newInterfaces[i] = (newInterfaces[i] != null) ? newInterfaces[i] : interfaces[i];
120     }
121     cv.visit(access, newName, newSuperName, newInterfaces, sourceFile);
122   }
123
124   public void visitField(final int access, final String JavaDoc name, final String JavaDoc desc, final Object JavaDoc value) {
125     String JavaDoc newDesc = augmentSimpleDesc(desc, trTable);
126     cv.visitField(access, name, newDesc, value);
127   }
128
129   public CodeVisitor visitMethod(final int access, final String JavaDoc name, final String JavaDoc desc, final String JavaDoc[] exceptions) {
130     String JavaDoc [] newExceptions = null;
131     if (exceptions != null) { // augment exceptions
132
newExceptions = new String JavaDoc [exceptions.length];
133       for (int i=0; i<exceptions.length; i++) {
134         newExceptions[i] = (String JavaDoc) trTable.get(exceptions[i]);
135         newExceptions[i] = (newExceptions[i] != null) ? newExceptions[i] : exceptions[i];
136       }
137     }
138     // augment description
139
// description has format (parameteres_description)ret_type_description
140
String JavaDoc paramTypes = desc.substring(1,desc.indexOf(')'));
141     String JavaDoc retType = desc.substring(desc.indexOf(')')+1);
142     String JavaDoc newRetType = augmentSimpleDesc(retType, trTable);
143     String JavaDoc newParamTypes = augmentListOfDescs(paramTypes, trTable);
144     String JavaDoc newDesc = "(" + newParamTypes + ")" + newRetType;
145     CodeVisitor mv = cv.visitMethod(access, name, newDesc, newExceptions);
146     return mv == null ? null : new TraceFieldCodeAdapter(mv, trTable);
147   }
148
149   /** Performs augmentation of simple description of type.
150     *
151     * @param desc original type description
152     * @param trTable translation table
153     * @return augmented type description
154     */

155   public static String JavaDoc augmentSimpleDesc(String JavaDoc desc, java.util.Hashtable JavaDoc trTable) {
156     StringBuffer JavaDoc type = new StringBuffer JavaDoc();
157     StringBuffer JavaDoc prefix = new StringBuffer JavaDoc();
158     int i=0;
159     while (desc.charAt(i) == '[') { // skip field dcl
160
prefix.append('[');
161       i++;
162     }
163     if (desc.charAt(i) == 'L') {
164       i++; // skip 'L'
165
while (desc.charAt(i) != ';') { // read type
166
type.append(desc.charAt(i++));
167       }
168       String JavaDoc newType = (String JavaDoc) trTable.get(type.toString());
169       newType = (newType != null) ? newType : type.toString();
170       return prefix.toString() + "L" + newType + ";";
171     } else {
172       return desc;
173     }
174   }
175
176   /** Perform augmentation of list of descs (from method decl.).
177     *
178     * @param desc list of descs
179     * @param trTable translation table
180     * @return augmented list of descs
181     */

182   public static String JavaDoc augmentListOfDescs(String JavaDoc descs, java.util.Hashtable JavaDoc trTable) {
183     StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
184     StringBuffer JavaDoc cur = new StringBuffer JavaDoc();
185     boolean typeNow = false;
186     for (int i=0; i<descs.length(); i++) {
187       if (typeNow) {
188         if (descs.charAt(i) != ';') {
189           cur.append(descs.charAt(i));
190         } else {
191           String JavaDoc newType = (String JavaDoc) trTable.get(cur.toString());
192           newType = (newType != null) ? newType : cur.toString();
193           ret.append(newType);
194           ret.append(';');
195           cur = new StringBuffer JavaDoc();
196           typeNow = false;
197         }
198       } else {
199         if (descs.charAt(i) == 'L') {
200           typeNow = true;
201         }
202         ret.append(descs.charAt(i));
203       }
204     }
205     return ret.toString();
206   }
207 }
208
209 /** Goes through method's instructions and performs augmentation of references.
210   *
211   * @author Petr Hnetynka
212   */

213 class TraceFieldCodeAdapter extends CodeAdapter implements Constants {
214   private java.util.Hashtable JavaDoc trTable;
215   public TraceFieldCodeAdapter (CodeVisitor cv, java.util.Hashtable JavaDoc table) {
216     super(cv);
217     trTable = table;
218   }
219
220   public void visitFieldInsn(final int opcode, final String JavaDoc owner, final String JavaDoc name, final String JavaDoc desc) {
221     String JavaDoc newOwner = (String JavaDoc) trTable.get(owner);
222     newOwner = (newOwner != null) ? newOwner : owner;
223     String JavaDoc newDesc = SOFAClassAdapter.augmentSimpleDesc(desc, trTable);
224     cv.visitFieldInsn(opcode, newOwner, name, newDesc);
225   }
226
227   public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
228     String JavaDoc paramTypes = desc.substring(1,desc.indexOf(')'));
229     String JavaDoc retType = desc.substring(desc.indexOf(')')+1);
230     String JavaDoc newRetType = SOFAClassAdapter.augmentSimpleDesc(retType, trTable);
231     String JavaDoc newParamTypes = SOFAClassAdapter.augmentListOfDescs(paramTypes, trTable);
232     String JavaDoc newDesc = "(" + newParamTypes + ")" + newRetType;
233     String JavaDoc newOwner = (String JavaDoc) trTable.get(owner);
234     newOwner = (newOwner != null) ? newOwner : owner;
235     cv.visitMethodInsn(opcode, newOwner, name, newDesc);
236   }
237
238   public void visitTypeInsn(int opcode, String JavaDoc desc) {
239     String JavaDoc newDesc = (String JavaDoc) trTable.get(desc);
240     newDesc = (newDesc != null) ? newDesc : desc;
241     cv.visitTypeInsn(opcode, newDesc);
242   }
243
244   public void visitLocalVariable(String JavaDoc name, String JavaDoc desc, Label start, Label end, int index) {
245     String JavaDoc newDesc = SOFAClassAdapter.augmentSimpleDesc(desc, trTable);
246     cv.visitLocalVariable(name, newDesc, start, end, index);
247   }
248
249   public void visitMultiANewArrayInsn(String JavaDoc desc, int dims) {
250     String JavaDoc newDesc = SOFAClassAdapter.augmentSimpleDesc(desc, trTable);
251     cv.visitMultiANewArrayInsn(newDesc, dims);
252   }
253   
254   public void visitTryCatchBlock(Label start, Label end, Label handler, String JavaDoc type) {
255     String JavaDoc newType = null;
256     if (type != null) {
257       newType = (String JavaDoc) trTable.get(type);
258       newType = (newType != null) ? newType : type;
259     }
260     cv.visitTryCatchBlock(start, end, handler, newType);
261   }
262 }
263
Popular Tags