• 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.util;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.visitor.*;
25 
26 /**
27  * This class provides methods to find class members in a given class or in its
28  * hierarchy.
29  *
30  * @author Eric Lafortune
31  */
32 public class MemberFinder
33 extends      SimplifiedVisitor
34 implements   MemberVisitor
35 {
36     private static class MemberFoundException extends RuntimeException {}
37     private static final MemberFoundException MEMBER_FOUND = new MemberFoundException();
38 
39     private Clazz  clazz;
40     private Member member;
41 
42 
43     /**
44      * Finds the field with the given name and descriptor in the given
45      * class or its hierarchy.
46      */
findField(Clazz referencingClass, Clazz clazz, String name, String descriptor)47     public Field findField(Clazz  referencingClass,
48                            Clazz  clazz,
49                            String name,
50                            String descriptor)
51     {
52         return (Field)findMember(referencingClass, clazz, name, descriptor, true);
53     }
54 
55 
56     /**
57      * Finds the method with the given name and descriptor in the given
58      * class or its hierarchy.
59      */
findMethod(Clazz referencingClass, Clazz clazz, String name, String descriptor)60     public Method findMethod(Clazz  referencingClass,
61                              Clazz  clazz,
62                              String name,
63                              String descriptor)
64     {
65         return (Method)findMember(referencingClass, clazz, name, descriptor, false);
66     }
67 
68 
69     /**
70      * Finds the class member with the given name and descriptor in the given
71      * class or its hierarchy.
72      */
findMember(Clazz referencingClass, Clazz clazz, String name, String descriptor, boolean isField)73     public Member findMember(Clazz   referencingClass,
74                              Clazz   clazz,
75                              String  name,
76                              String  descriptor,
77                              boolean isField)
78     {
79         // Organize a search in the hierarchy of superclasses and interfaces.
80         // The class member may be in a different class, if the code was
81         // compiled with "-target 1.2" or higher (the default in JDK 1.4).
82         try
83         {
84             this.clazz  = null;
85             this.member = null;
86             clazz.hierarchyAccept(true, true, true, false, isField ?
87                 (ClassVisitor)new NamedFieldVisitor(name, descriptor,
88                               new MemberClassAccessFilter(referencingClass, this)) :
89                 (ClassVisitor)new NamedMethodVisitor(name, descriptor,
90                               new MemberClassAccessFilter(referencingClass, this)));
91         }
92         catch (MemberFoundException ex)
93         {
94             // We've found the member we were looking for.
95         }
96 
97         return member;
98     }
99 
100 
101     /**
102      * Returns the corresponding class of the most recently found class
103      * member.
104      */
correspondingClass()105     public Clazz correspondingClass()
106     {
107         return clazz;
108     }
109 
110 
111     /**
112      * Returns whether the given method is overridden anywhere down the class
113      * hierarchy.
114      */
isOverriden(Clazz clazz, Method method)115     public boolean isOverriden(Clazz  clazz,
116                                Method method)
117     {
118         String name       = method.getName(clazz);
119         String descriptor = method.getDescriptor(clazz);
120 
121         // Go looking for the method down the class hierarchy.
122         try
123         {
124             this.clazz  = null;
125             this.member = null;
126 
127             clazz.hierarchyAccept(false, false, false, true,
128                 new NamedMethodVisitor(name, descriptor,
129                 new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, this)));
130         }
131         catch (MemberFoundException ex)
132         {
133             // We've found an overriding method.
134             return true;
135         }
136 
137         return false;
138     }
139 
140 
141     /**
142      * Returns whether the given field is shadowed anywhere down the class
143      * hierarchy.
144      */
isShadowed(Clazz clazz, Field field)145     public boolean isShadowed(Clazz clazz,
146                               Field field)
147     {
148         String name       = field.getName(clazz);
149         String descriptor = field.getDescriptor(clazz);
150 
151         // Go looking for the field down the class hierarchy.
152         try
153         {
154             this.clazz  = null;
155             this.member = null;
156             clazz.hierarchyAccept(false, false, false, true,
157                 new NamedFieldVisitor(name, descriptor,
158                 new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, this)));
159         }
160         catch (MemberFoundException ex)
161         {
162             // We've found a shadowing field.
163             return true;
164         }
165 
166         return false;
167     }
168 
169 
170 //    // Implementations for ClassVisitor.
171 //
172 //    private void visitAnyClass(Clazz clazz)
173 //    {
174 //        if (member == null)
175 //        {
176 //            member = isField ?
177 //                (Member)clazz.findField(name, descriptor) :
178 //                (Member)clazz.findMethod(name, descriptor);
179 //
180 //            if (member != null)
181 //            {
182 //                this.clazz = clazz;
183 //            }
184 //        }
185 //    }
186 
187 
188     // Implementations for MemberVisitor.
189 
visitAnyMember(Clazz clazz, Member member)190     public void visitAnyMember(Clazz clazz, Member member)
191     {
192         this.clazz  = clazz;
193         this.member = member;
194 
195         throw MEMBER_FOUND;
196     }
197 }
198