KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jbet > ProgramInfo


1 /*
2  * JBET - Java Binary Enhancement Tool
3  * Copyright (c) 2003 Networks Associates Technology, Inc.
4  *
5  * This software was developed under DARPA/SPAWAR contract
6  * N66001-00-C-8602 "SPMA" as part of the
7  * DARPA OASIS research program.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */

30
31 /*
32    Represents an entire program (multiple classes) to be transformed. Reads an input
33    program specified as a main class and determines which other classes are needed by
34    that program.
35
36    @author Andrew Reisse
37 */

38
39 package jbet;
40 import java.io.PrintStream JavaDoc;
41 import java.util.*;
42
43 public class ProgramInfo
44 {
45     private ClassFilter system;
46     private ClassFilter rename;
47     public Hashtable classes; // internal classes
48
public Hashtable externs; // external classes
49
public Hashtable renames; // classes to be renamed
50
public String JavaDoc mainclass; // the main that the user runs
51

52     public static class PClass
53     {
54     public ClassInfo cr; // original class
55
public DagClassInfo vcr; // dags for original class (temporary)
56
public int flags;
57     public PClass superclass;
58     public Vector interfaces; // list of PClasss for interfaces
59

60     public static final int External = 1; // this class is external
61
public static final String JavaDoc[] flagnames = {"External"};
62
63     public String JavaDoc toString() {
64         return cr.name() + " " + Util.flags2str (flags, flagnames);
65     }
66
67     public PClass interfaceAt (int i) {
68         return (PClass) interfaces.elementAt (i);
69     }
70
71     PClass() {}
72
73     PClass (ClassInfo _cr) {
74         cr = _cr;
75         superclass = null;
76     }
77
78     PClass (ClassInfo _cr, ProgramInfo pi) throws ClassFileException {
79         this (_cr, pi, false);
80     }
81
82     PClass (ClassInfo _cr, ProgramInfo pi, boolean load) throws ClassFileException {
83         cr = _cr;
84
85         if (cr.getSuperName() != null) {
86         superclass = (PClass) pi.classes.get (_cr.getSuperName());
87
88         if (load && superclass == null)
89             throw new ClassFileNotFoundException (_cr.getSuperName());
90         /* This next condition might be wrong */
91         else if (superclass == null)
92             superclass = (PClass) pi.externs.get (_cr.getSuperName ());
93         if (superclass == null)
94             throw new IllegalStateException JavaDoc ("cannot find superclass: " + _cr.getSuperName());
95         }
96
97         if (cr.numInterfaces() > 0) {
98         interfaces = new Vector();
99
100         for (int i = 0; i < cr.numInterfaces(); i++) {
101             String JavaDoc iname = cr.interfaceAt (i);
102             Object JavaDoc o = pi.classes.get (iname);
103
104             if (o == null)
105             o = pi.externs.get (iname);
106
107             if (o == null && load) {
108             throw new ClassFileNotFoundException (iname);
109             }
110
111             interfaces.addElement (o);
112         }
113         }
114         else
115         interfaces = Util.emptyVector;
116     }
117     }
118
119     public PClass getClassI (String JavaDoc name)
120     {
121     return (PClass) classes.get (name);
122     }
123
124     public PClass add (ClassInfo cr) throws ClassFileException
125     {
126     PClass ci = new PClass ();
127
128     ci.cr = cr;
129
130     if (rename.check (cr))
131         renames.put (cr, "java/lang/Object");
132     else if (system.check (cr)) {
133         ci.flags |= PClass.External;
134         externs.put (cr.name(), ci);
135         return ci;
136     }
137     else
138         renames.put (cr, cr.name());
139
140     if (cr.getSuperName() != null) {
141         Object JavaDoc o = classes.get (cr.getSuperName());
142         if (o == null)
143         o = externs.get (cr.getSuperName());
144
145         if (o == null)
146         ci.superclass = add (Jbet.loader.getClass (cr.getSuperName()));
147         else
148         ci.superclass = (PClass) o;
149     }
150
151     if (cr.numInterfaces() > 0) {
152         ci.interfaces = new Vector();
153
154         for (int i = 0; i < cr.numInterfaces(); i++) {
155         String JavaDoc iname = cr.interfaceAt (i);
156         Object JavaDoc o = classes.get (iname);
157
158         if (o == null)
159             o = externs.get (iname);
160
161         if (o == null)
162             ci.interfaces.addElement (add (Jbet.loader.getClass (iname)));
163         else
164             ci.interfaces.addElement (o);
165         }
166     }
167     else
168         ci.interfaces = Util.emptyVector;
169
170     HashSet newclasses = new HashSet();
171     HashSet newexterns = new HashSet();
172     boolean extern = false;
173
174     for (int i = 0; i < cr.numMethods(); i++) {
175         MethodInfo mi = cr.methodAt (i);
176
177         if (mi.code != null) {
178
179         if (mi.code.numEx() != 0)
180             for (int j = 0; j < mi.code.numEx(); j++) {
181             ExceptionRec er = mi.code.exAt (j);
182
183             if (er.catchType != null)
184                 if (null == classes.get (er.catchType))
185                 add (Jbet.loader.getClass (er.catchType));
186             }
187
188         for (Instruction ins = mi.code.first(); ins != null; ins = ins.next) {
189             if ((ins.usesClass() || ins.usesMethod()) && !ins.classRef().startsWith ("[")) {
190             if (rename.check (ins.classRef()) || !system.check (ins.classRef())) {
191                 if (classes.get (ins.classRef()) == null)
192                 newclasses.add (ins.classRef());
193             }
194             else {
195                 newexterns.add (ins.classRef());
196                 if (ins.descriptor() != null) {
197                 if (ins.descriptor().ret.base == 'L') {
198                     newexterns.add (ins.descriptor().ret.cname);
199                 }
200                 }
201             }
202             }
203         }
204         } else if ((mi.accessFlags & MethodInfo.ACC_NATIVE) != 0) {
205         if (mi.descriptor.ret.base == 'L') {
206             newexterns.add (mi.descriptor.ret.cname);
207         }
208         extern = true;
209         }
210     }
211
212     if (extern) {
213         ci.flags |= PClass.External;
214         externs.put (cr.name(), ci);
215     } else {
216         classes.put (cr.name(), ci);
217
218         for (Iterator i = newclasses.iterator(); i.hasNext(); ) {
219         String JavaDoc n = (String JavaDoc) i.next();
220         if (classes.get (n) == null && externs.get (n) == null) {
221             add (Jbet.loader.getClass (n));
222         }
223         }
224
225         /* Add external classes */
226         for (Iterator i = newexterns.iterator(); i.hasNext(); ) {
227         String JavaDoc n = (String JavaDoc) i.next();
228         PClass ci2 = new PClass();
229
230         ci2.flags = PClass.External;
231         ci2.cr = Jbet.loader.getClass (n);
232         externs.put (n, ci2);
233         }
234     }
235
236     return ci;
237     }
238     //} _util util = new _util();
239

240     /* Create a new ProgramInfo:
241        @param main the class the user runs.
242        @param system specifies which classes are NOT part of the application
243        @param rename classes which are renamed and then added to the application (checked before system)
244
245        finish() must be called after the three-argument constructor
246     */

247
248     public ProgramInfo (ClassInfo main, final ClassFilter systemc) throws ClassFileException
249     {
250     this (main, systemc, ClassFilter.NONE);
251     }
252
253     public ProgramInfo (ClassInfo main, final ClassFilter systemc, final ClassFilter renamec) throws ClassFileException
254     {
255     classes = new Hashtable();
256     externs = new Hashtable();
257     renames = new Hashtable();
258     system = systemc;
259     rename = renamec;
260
261     add (main);
262     mainclass = main.name();
263     }
264
265     public void finish () throws ClassFileException
266     {
267     String JavaDoc n = newPrivateName();
268
269     for (Iterator i = new HashSet (renames.keySet()).iterator(); i.hasNext(); ) {
270         Object JavaDoc z = i.next();
271         if ("java/lang/Object".equals (renames.get (z)))
272         renames.put (z, n + z.toString().replace ('/','$'));
273     }
274
275     Hashtable subs = new Hashtable();
276     for (Iterator i = renames.keySet().iterator(); i.hasNext(); ) {
277         Object JavaDoc z = i.next();
278         subs.put (z.toString(), renames.get (z).toString ());
279     }
280
281     for (Iterator i = renames.keySet().iterator(); i.hasNext(); ) {
282         ClassInfo cr = (ClassInfo) i.next();
283         ClassInfo newcr = new ClassInfo(cr);
284
285         newcr.relocate(subs);
286         newcr.dirty = true;
287         renames.put (cr, newcr);
288
289         Jbet.loader.putClass (newcr);
290     }
291
292     Hashtable oldc = classes;
293     classes = new Hashtable();
294
295     for (Iterator i = renames.keySet().iterator(); i.hasNext(); ) {
296         Object JavaDoc z = i.next();
297         PClass ci = (PClass) oldc.get (z.toString());
298
299         if (ci == null)
300         throw new NullPointerException JavaDoc ("class not in list: " + z + " : " + z.getClass().getName());
301
302         ci.cr = (ClassInfo) renames.get (z);
303
304         classes.put (ci.cr.name(), ci);
305     }
306     }
307
308     public void printinfo (PrintStream JavaDoc out)
309     {
310     out.println ("Main class " + mainclass);
311
312     for (Iterator i = classes.values().iterator(); i.hasNext(); ) {
313         out.println ("intern " + i.next());
314     }
315
316     for (Iterator i = externs.values().iterator(); i.hasNext(); ) {
317         out.println ("extern " + i.next());
318     }
319     }
320
321     public String JavaDoc newPrivateName () {
322     ClassInfo main = getClassI (mainclass).cr;
323     int n = 1;
324     while (null != classes.get (main.name() + "$" + n)) n++;
325
326     return main.name() + "$" + n;
327     }
328
329     public ClassInfo addPrivateClass () {
330     ClassInfo main = getClassI (mainclass).cr;
331     ClassInfo out = new ClassInfo (main.classPathElement, newPrivateName());
332     try {
333         classes.put (out.name(), new PClass (out, this));
334         return out;
335     } catch (ClassFileException e) {
336         throw new IllegalStateException JavaDoc ("could not add new class");
337     }
338     }
339
340     public ClassInfo addPrivateClassFrom (ClassInfo in) throws ClassFileException {
341     Hashtable tmp = new Hashtable();
342     tmp.put (in, newPrivateName());
343     Util.RenameClasses (tmp, true);
344     return (ClassInfo) tmp.get (in);
345     }
346
347     /* return mainclass.<clinit>, creating it if nonexistant. */
348
349     public MethodInfo getclinit () {
350     ClassInfo mc = getClassI(mainclass).cr;
351     MethodInfo mi = mc.findMethod ("<clinit>", Descriptor.Void);
352     if (mi == null) {
353         mi = new MethodInfo ("<clinit>", new Descriptor (Descriptor.Void));
354         mc.addMethod (mi);
355         mi.code = new Snippit();
356         mi.code.push (new Instruction().setReturn());
357     }
358
359     return mi;
360     }
361
362     /* Add a class to be initialized right after main. */
363
364     public void addClinit (String JavaDoc name) {
365     MethodInfo mi = getclinit();
366
367     /* using new doesn't work; the class might be abstract, and
368        newarrays don't run initializers.
369     */

370     mi.code.insertBefore (mi.code.first(), new Instruction().setPop());
371     mi.code.insertBefore (mi.code.first(), new Instruction().setInvokeStatic ("java/lang/Class", "forName",
372                                           new Descriptor ("(Ljava/lang/String;)Ljava/lang/Class;")));
373     mi.code.insertBefore (mi.code.first(), new Instruction().setSpush (name.replace ('/','.')));
374     }
375 }
376
Popular Tags