001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.optimize.info;
022:
023: import proguard.classfile.*;
024: import proguard.classfile.constant.*;
025: import proguard.classfile.constant.visitor.ConstantVisitor;
026: import proguard.classfile.util.SimplifiedVisitor;
027: import proguard.classfile.visitor.*;
028:
029: /**
030: * This ClassVisitor marks all class members that can not be made private in the
031: * classes that it visits, and in the classes to which they refer.
032: *
033: * @author Eric Lafortune
034: */
035: public class NonPrivateMemberMarker extends SimplifiedVisitor implements
036: ClassVisitor, ConstantVisitor, MemberVisitor {
037: private final MethodImplementationFilter filteredMethodMarker = new MethodImplementationFilter(
038: this );
039:
040: // Implementations for ClassVisitor.
041:
042: public void visitProgramClass(ProgramClass programClass) {
043: // Mark all referenced class members in different classes.
044: programClass.constantPoolEntriesAccept(this );
045:
046: // Explicitly mark the <clinit> method.
047: programClass.methodAccept(
048: ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
049: ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, this );
050:
051: // Explicitly mark the parameterless <init> method.
052: programClass.methodAccept(
053: ClassConstants.INTERNAL_METHOD_NAME_INIT,
054: ClassConstants.INTERNAL_METHOD_TYPE_INIT, this );
055:
056: // Mark all methods that may have implementations.
057: programClass.methodsAccept(filteredMethodMarker);
058: }
059:
060: public void visitLibraryClass(LibraryClass libraryClass) {
061: // Go over all methods.
062: libraryClass.methodsAccept(this );
063: }
064:
065: // Implementations for ConstantVisitor.
066:
067: public void visitAnyConstant(Clazz clazz, Constant constant) {
068: }
069:
070: public void visitStringConstant(Clazz clazz,
071: StringConstant stringConstant) {
072: Clazz referencedClass = stringConstant.referencedClass;
073:
074: // Is it refering to another class or class member?
075: if (referencedClass != null && !referencedClass.equals(clazz)) {
076: // The referenced class member, if any, can never be made private.
077: stringConstant.referencedMemberAccept(this );
078: }
079: }
080:
081: public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) {
082: Clazz referencedClass = refConstant.referencedClass;
083:
084: // Is it refering to a class member in another class?
085: // The class member might be in another class, or
086: // it may be referenced through another class.
087: if (referencedClass != null
088: && !referencedClass.equals(clazz)
089: || !refConstant.getClassName(clazz).equals(
090: clazz.getName())) {
091: // The referenced class member can never be made private.
092: refConstant.referencedMemberAccept(this );
093: }
094: }
095:
096: // Implementations for MemberVisitor.
097:
098: public void visitProgramField(ProgramClass programClass,
099: ProgramField programField) {
100: markCanNotBeMadePrivate(programField);
101: }
102:
103: public void visitLibraryField(LibraryClass libraryClass,
104: LibraryField libraryField) {
105: markCanNotBeMadePrivate(libraryField);
106: }
107:
108: public void visitProgramMethod(ProgramClass programClass,
109: ProgramMethod programMethod) {
110: markCanNotBeMadePrivate(programMethod);
111: }
112:
113: public void visitLibraryMethod(LibraryClass libraryClass,
114: LibraryMethod libraryMethod) {
115: markCanNotBeMadePrivate(libraryMethod);
116: }
117:
118: // Small utility methods.
119:
120: private static void markCanNotBeMadePrivate(Field field) {
121: FieldOptimizationInfo info = FieldOptimizationInfo
122: .getFieldOptimizationInfo(field);
123: if (info != null) {
124: info.setCanNotBeMadePrivate();
125: }
126: }
127:
128: /**
129: * Returns whether the given field can be made private.
130: */
131: public static boolean canBeMadePrivate(Field field) {
132: FieldOptimizationInfo info = FieldOptimizationInfo
133: .getFieldOptimizationInfo(field);
134: return info != null && info.canBeMadePrivate();
135: }
136:
137: private static void markCanNotBeMadePrivate(Method method) {
138: MethodOptimizationInfo info = MethodOptimizationInfo
139: .getMethodOptimizationInfo(method);
140: if (info != null) {
141: info.setCanNotBeMadePrivate();
142: }
143: }
144:
145: /**
146: * Returns whether the given method can be made private.
147: */
148: public static boolean canBeMadePrivate(Method method) {
149: MethodOptimizationInfo info = MethodOptimizationInfo
150: .getMethodOptimizationInfo(method);
151: return info != null && info.canBeMadePrivate();
152: }
153: }
|