• 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.editor;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.constant.*;
25 import proguard.classfile.constant.visitor.ConstantVisitor;
26 import proguard.classfile.util.*;
27 import proguard.classfile.visitor.*;
28 
29 /**
30  * This ConstantVisitor fixes the access modifiers of all classes and class
31  * members that are referenced by the constants that it visits.
32  *
33  * @author Eric Lafortune
34  */
35 public class AccessFixer
36 extends      SimplifiedVisitor
37 implements   ConstantVisitor,
38              ClassVisitor,
39              MemberVisitor
40 {
41     private MyReferencedClassFinder referencedClassFinder = new MyReferencedClassFinder();
42 
43     private Clazz referencingClass;
44     private Clazz referencedClass;
45 
46 
47     // Implementations for ConstantVisitor.
48 
visitAnyConstant(Clazz clazz, Constant constant)49     public void visitAnyConstant(Clazz clazz, Constant constant) {}
50 
51 
visitStringConstant(Clazz clazz, StringConstant stringConstant)52     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
53     {
54         referencingClass = clazz;
55         referencedClass  = stringConstant.referencedClass;
56 
57         // Make sure the access flags of the referenced class or class member,
58         // if any, are acceptable.
59         stringConstant.referencedClassAccept(this);
60         stringConstant.referencedMemberAccept(this);
61     }
62 
63 
visitAnyRefConstant(Clazz clazz, RefConstant refConstant)64     public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
65     {
66         referencingClass = clazz;
67 
68         // Remember the specified class, since it might be different from
69         // the referenced class that acutally contains the class member.
70         clazz.constantPoolEntryAccept(refConstant.u2classIndex, referencedClassFinder);
71 
72         // Make sure the access flags of the referenced class member are
73         // acceptable.
74         refConstant.referencedMemberAccept(this);
75     }
76 
77 
visitClassConstant(Clazz clazz, ClassConstant classConstant)78     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
79     {
80         referencingClass = clazz;
81 
82         // Make sure the access flags of the referenced class are acceptable.
83         classConstant.referencedClassAccept(this);
84     }
85 
86 
87     // Implementations for ClassVisitor.
88 
visitLibraryClass(LibraryClass libraryClass)89     public void visitLibraryClass(LibraryClass libraryClass) {}
90 
91 
visitProgramClass(ProgramClass programClass)92     public void visitProgramClass(ProgramClass programClass)
93     {
94         int currentAccessFlags  = programClass.getAccessFlags();
95         int currentAccessLevel  = AccessUtil.accessLevel(currentAccessFlags);
96 
97         // Compute the required access level.
98         Clazz referencingClass = this.referencingClass;
99         int requiredAccessLevel =
100             inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE :
101                                                             AccessUtil.PUBLIC;
102 
103         // Fix the class access flags if necessary.
104         if (currentAccessLevel < requiredAccessLevel)
105         {
106             programClass.u2accessFlags =
107                 AccessUtil.replaceAccessFlags(currentAccessFlags,
108                                               AccessUtil.accessFlags(requiredAccessLevel));
109         }
110     }
111 
112 
113     // Implementations for MemberVisitor.
114 
visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)115     public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {}
116 
117 
visitProgramMember(ProgramClass programClass, ProgramMember programMember)118     public void visitProgramMember(ProgramClass programClass, ProgramMember programMember)
119     {
120         int currentAccessFlags  = programMember.getAccessFlags();
121         int currentAccessLevel  = AccessUtil.accessLevel(currentAccessFlags);
122 
123         // Compute the required access level.
124         int requiredAccessLevel =
125             programClass.equals(referencingClass)         ? AccessUtil.PRIVATE         :
126             inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE :
127             referencedClass.extends_(referencingClass) &&
128             referencingClass.extends_(programClass)       ? AccessUtil.PROTECTED       :
129                                                             AccessUtil.PUBLIC;
130 
131         // Fix the class member access flags if necessary.
132         if (currentAccessLevel < requiredAccessLevel)
133         {
134             programMember.u2accessFlags =
135                 AccessUtil.replaceAccessFlags(currentAccessFlags,
136                                               AccessUtil.accessFlags(requiredAccessLevel));
137         }
138     }
139 
140 
141     /**
142      * This ConstantVisitor returns the referenced class of the class constant
143      * that it visits.
144      */
145     private class MyReferencedClassFinder
146     extends       SimplifiedVisitor
147     implements    ConstantVisitor
148     {
149         // Implementations for ConstantVisitor.
visitClassConstant(Clazz clazz, ClassConstant classConstant)150         public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
151         {
152             referencedClass = classConstant.referencedClass;
153         }
154     }
155 
156 
157     // Small utility methods.
158 
inSamePackage(ProgramClass class1, Clazz class2)159     private boolean inSamePackage(ProgramClass class1, Clazz class2)
160     {
161         return ClassUtil.internalPackageName(class1.getName()).equals(
162                ClassUtil.internalPackageName(class2.getName()));
163     }
164 }
165