• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard.classfile;
22 
23 import proguard.classfile.attribute.Attribute;
24 import proguard.classfile.attribute.visitor.AttributeVisitor;
25 import proguard.classfile.constant.*;
26 import proguard.classfile.constant.visitor.ConstantVisitor;
27 import proguard.classfile.util.ClassSubHierarchyInitializer;
28 import proguard.classfile.visitor.*;
29 
30 /**
31  * This Clazz is a complete representation of the data in a Java class.
32  *
33  * @author Eric Lafortune
34  */
35 public class ProgramClass implements Clazz
36 {
37     public int             u4magic;
38     public int             u4version;
39     public int             u2constantPoolCount;
40     public Constant[]      constantPool;
41     public int             u2accessFlags;
42     public int             u2thisClass;
43     public int             u2superClass;
44     public int             u2interfacesCount;
45     public int[]           u2interfaces;
46     public int             u2fieldsCount;
47     public ProgramField[]  fields;
48     public int             u2methodsCount;
49     public ProgramMethod[] methods;
50     public int             u2attributesCount;
51     public Attribute[]     attributes;
52 
53     /**
54      * An extra field pointing to the subclasses of this class.
55      * This field is filled out by the {@link ClassSubHierarchyInitializer}.
56      */
57     public Clazz[] subClasses;
58 
59     /**
60      * An extra field in which visitors can store information.
61      */
62     public Object visitorInfo;
63 
64 
65     /**
66      * Creates an uninitialized ProgramClass.
67      */
ProgramClass()68     public ProgramClass() {}
69 
70 
71     /**
72      * Returns the Constant at the given index in the constant pool.
73      */
getConstant(int constantIndex)74     public Constant getConstant(int constantIndex)
75     {
76         return constantPool[constantIndex];
77     }
78 
79 
80     // Implementations for Clazz.
81 
getAccessFlags()82     public int getAccessFlags()
83     {
84         return u2accessFlags;
85     }
86 
getName()87     public String getName()
88     {
89         return getClassName(u2thisClass);
90     }
91 
getSuperName()92     public String getSuperName()
93     {
94         return u2superClass == 0 ? null : getClassName(u2superClass);
95     }
96 
getInterfaceCount()97     public int getInterfaceCount()
98     {
99         return u2interfacesCount;
100     }
101 
getInterfaceName(int index)102     public String getInterfaceName(int index)
103     {
104         return getClassName(u2interfaces[index]);
105     }
106 
getTag(int constantIndex)107     public int getTag(int constantIndex)
108     {
109         return constantPool[constantIndex].getTag();
110     }
111 
getString(int constantIndex)112     public String getString(int constantIndex)
113     {
114         try
115         {
116             return ((Utf8Constant)constantPool[constantIndex]).getString();
117         }
118         catch (ClassCastException ex)
119         {
120             new ClassPrinter().visitProgramClass(this);
121             throw new ClassCastException("Expected Utf8Constant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
122         }
123     }
124 
getStringString(int constantIndex)125     public String getStringString(int constantIndex)
126     {
127         try
128         {
129             return ((StringConstant)constantPool[constantIndex]).getString(this);
130         }
131         catch (ClassCastException ex)
132         {
133             throw new ClassCastException("Expected StringConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
134         }
135     }
136 
getClassName(int constantIndex)137     public String getClassName(int constantIndex)
138     {
139         try
140         {
141             return ((ClassConstant)constantPool[constantIndex]).getName(this);
142         }
143         catch (ClassCastException ex)
144         {
145             throw new ClassCastException("Expected ClassConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
146         }
147     }
148 
getName(int constantIndex)149     public String getName(int constantIndex)
150     {
151         try
152         {
153             return ((NameAndTypeConstant)constantPool[constantIndex]).getName(this);
154         }
155         catch (ClassCastException ex)
156         {
157             throw new ClassCastException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
158         }
159     }
160 
getType(int constantIndex)161     public String getType(int constantIndex)
162     {
163         try
164         {
165             return ((NameAndTypeConstant)constantPool[constantIndex]).getType(this);
166         }
167         catch (ClassCastException ex)
168         {
169             throw new ClassCastException("Expected NameAndTypeConstant at index ["+constantIndex+"] in class ["+getName()+"], found ["+ex.getMessage()+"]");
170         }
171     }
172 
173 
addSubClass(Clazz clazz)174     public void addSubClass(Clazz clazz)
175     {
176         if (subClasses == null)
177         {
178             subClasses = new Clazz[1];
179         }
180         else
181         {
182             // Copy the old elements into new larger array.
183             Clazz[] temp = new Clazz[subClasses.length+1];
184             System.arraycopy(subClasses, 0, temp, 0, subClasses.length);
185             subClasses = temp;
186         }
187 
188         subClasses[subClasses.length-1] = clazz;
189     }
190 
191 
getSuperClass()192     public Clazz getSuperClass()
193     {
194         return u2superClass != 0 ?
195             ((ClassConstant)constantPool[u2superClass]).referencedClass :
196             null;
197     }
198 
199 
getInterface(int index)200     public Clazz getInterface(int index)
201     {
202         return ((ClassConstant)constantPool[u2interfaces[index]]).referencedClass;
203     }
204 
205 
extends_(Clazz clazz)206     public boolean extends_(Clazz clazz)
207     {
208         if (this.equals(clazz))
209         {
210             return true;
211         }
212 
213         Clazz superClass = getSuperClass();
214         return superClass != null &&
215                superClass.extends_(clazz);
216     }
217 
218 
extendsOrImplements(Clazz clazz)219     public boolean extendsOrImplements(Clazz clazz)
220     {
221         if (this.equals(clazz))
222         {
223             return true;
224         }
225 
226         Clazz superClass = getSuperClass();
227         if (superClass != null &&
228             superClass.extendsOrImplements(clazz))
229         {
230             return true;
231         }
232 
233         for (int index = 0; index < u2interfacesCount; index++)
234         {
235             Clazz interfaceClass = getInterface(index);
236             if (interfaceClass != null &&
237                 interfaceClass.extendsOrImplements(clazz))
238             {
239                 return true;
240             }
241         }
242 
243         return false;
244     }
245 
246 
findField(String name, String descriptor)247     public Field findField(String name, String descriptor)
248     {
249         for (int index = 0; index < u2fieldsCount; index++)
250         {
251             Field field = fields[index];
252             if ((name       == null || field.getName(this).equals(name)) &&
253                 (descriptor == null || field.getDescriptor(this).equals(descriptor)))
254             {
255                 return field;
256             }
257         }
258 
259         return null;
260     }
261 
262 
findMethod(String name, String descriptor)263     public Method findMethod(String name, String descriptor)
264     {
265         for (int index = 0; index < u2methodsCount; index++)
266         {
267             Method method = methods[index];
268             if ((name       == null || method.getName(this).equals(name)) &&
269                 (descriptor == null || method.getDescriptor(this).equals(descriptor)))
270             {
271                 return method;
272             }
273         }
274 
275         return null;
276     }
277 
278 
accept(ClassVisitor classVisitor)279     public void accept(ClassVisitor classVisitor)
280     {
281         classVisitor.visitProgramClass(this);
282     }
283 
284 
hierarchyAccept(boolean visitThisClass, boolean visitSuperClass, boolean visitInterfaces, boolean visitSubclasses, ClassVisitor classVisitor)285     public void hierarchyAccept(boolean      visitThisClass,
286                                 boolean      visitSuperClass,
287                                 boolean      visitInterfaces,
288                                 boolean      visitSubclasses,
289                                 ClassVisitor classVisitor)
290     {
291         // First visit the current classfile.
292         if (visitThisClass)
293         {
294             accept(classVisitor);
295         }
296 
297         // Then visit its superclass, recursively.
298         if (visitSuperClass)
299         {
300             Clazz superClass = getSuperClass();
301             if (superClass != null)
302             {
303                 superClass.hierarchyAccept(true,
304                                            true,
305                                            visitInterfaces,
306                                            false,
307                                            classVisitor);
308             }
309         }
310 
311         // Then visit its interfaces, recursively.
312         if (visitInterfaces)
313         {
314             // Visit the interfaces of the superclasses, if we haven't done so yet.
315             if (!visitSuperClass)
316             {
317                 Clazz superClass = getSuperClass();
318                 if (superClass != null)
319                 {
320                     superClass.hierarchyAccept(false,
321                                                false,
322                                                true,
323                                                false,
324                                                classVisitor);
325                 }
326             }
327 
328             // Visit the interfaces.
329             for (int index = 0; index < u2interfacesCount; index++)
330             {
331                 Clazz interfaceClass = getInterface(index);
332                 if (interfaceClass != null)
333                 {
334                     interfaceClass.hierarchyAccept(true,
335                                                    false,
336                                                    true,
337                                                    false,
338                                                    classVisitor);
339                 }
340             }
341         }
342 
343         // Then visit its subclasses, recursively.
344         if (visitSubclasses)
345         {
346             if (subClasses != null)
347             {
348                 for (int index = 0; index < subClasses.length; index++)
349                 {
350                     Clazz subClass = subClasses[index];
351                     subClass.hierarchyAccept(true,
352                                              false,
353                                              false,
354                                              true,
355                                              classVisitor);
356                 }
357             }
358         }
359     }
360 
361 
subclassesAccept(ClassVisitor classVisitor)362     public void subclassesAccept(ClassVisitor classVisitor)
363     {
364         if (subClasses != null)
365         {
366             for (int index = 0; index < subClasses.length; index++)
367             {
368                 subClasses[index].accept(classVisitor);
369             }
370         }
371     }
372 
373 
constantPoolEntriesAccept(ConstantVisitor constantVisitor)374     public void constantPoolEntriesAccept(ConstantVisitor constantVisitor)
375     {
376         for (int index = 1; index < u2constantPoolCount; index++)
377         {
378             if (constantPool[index] != null)
379             {
380                 constantPool[index].accept(this, constantVisitor);
381             }
382         }
383     }
384 
385 
constantPoolEntryAccept(int index, ConstantVisitor constantVisitor)386     public void constantPoolEntryAccept(int index, ConstantVisitor constantVisitor)
387     {
388         constantPool[index].accept(this, constantVisitor);
389     }
390 
391 
thisClassConstantAccept(ConstantVisitor constantVisitor)392     public void thisClassConstantAccept(ConstantVisitor constantVisitor)
393     {
394         constantPool[u2thisClass].accept(this, constantVisitor);
395     }
396 
397 
superClassConstantAccept(ConstantVisitor constantVisitor)398     public void superClassConstantAccept(ConstantVisitor constantVisitor)
399     {
400         if (u2superClass != 0)
401         {
402             constantPool[u2superClass].accept(this, constantVisitor);
403         }
404     }
405 
406 
interfaceConstantsAccept(ConstantVisitor constantVisitor)407     public void interfaceConstantsAccept(ConstantVisitor constantVisitor)
408     {
409         for (int index = 0; index < u2interfacesCount; index++)
410         {
411             constantPool[u2interfaces[index]].accept(this, constantVisitor);
412         }
413     }
414 
415 
fieldsAccept(MemberVisitor memberVisitor)416     public void fieldsAccept(MemberVisitor memberVisitor)
417     {
418         for (int index = 0; index < u2fieldsCount; index++)
419         {
420             fields[index].accept(this, memberVisitor);
421         }
422     }
423 
424 
fieldAccept(String name, String descriptor, MemberVisitor memberVisitor)425     public void fieldAccept(String name, String descriptor, MemberVisitor memberVisitor)
426     {
427         Field field = findField(name, descriptor);
428         if (field != null)
429         {
430             field.accept(this, memberVisitor);
431         }
432     }
433 
434 
methodsAccept(MemberVisitor memberVisitor)435     public void methodsAccept(MemberVisitor memberVisitor)
436     {
437         for (int index = 0; index < u2methodsCount; index++)
438         {
439             methods[index].accept(this, memberVisitor);
440         }
441     }
442 
443 
methodAccept(String name, String descriptor, MemberVisitor memberVisitor)444     public void methodAccept(String name, String descriptor, MemberVisitor memberVisitor)
445     {
446         Method method = findMethod(name, descriptor);
447         if (method != null)
448         {
449             method.accept(this, memberVisitor);
450         }
451     }
452 
453 
mayHaveImplementations(Method method)454     public boolean mayHaveImplementations(Method method)
455     {
456         return
457             (u2accessFlags & ClassConstants.INTERNAL_ACC_FINAL) == 0 &&
458             (method == null ||
459              ((method.getAccessFlags() & (ClassConstants.INTERNAL_ACC_PRIVATE |
460                                           ClassConstants.INTERNAL_ACC_STATIC  |
461                                           ClassConstants.INTERNAL_ACC_FINAL)) == 0 &&
462               !method.getName(this).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)));
463     }
464 
465 
attributesAccept(AttributeVisitor attributeVisitor)466     public void attributesAccept(AttributeVisitor attributeVisitor)
467     {
468         for (int index = 0; index < u2attributesCount; index++)
469         {
470             attributes[index].accept(this, attributeVisitor);
471         }
472     }
473 
474 
475     // Implementations for VisitorAccepter.
476 
getVisitorInfo()477     public Object getVisitorInfo()
478     {
479         return visitorInfo;
480     }
481 
setVisitorInfo(Object visitorInfo)482     public void setVisitorInfo(Object visitorInfo)
483     {
484         this.visitorInfo = visitorInfo;
485     }
486 
487 
488     // Implementations for Object.
489 
toString()490     public String toString()
491     {
492         return "ProgramClass("+getName()+")";
493     }
494 }
495