1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 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 */ 21package proguard.shrink; 22 23import proguard.classfile.*; 24import proguard.classfile.constant.*; 25import proguard.classfile.constant.visitor.ConstantVisitor; 26import proguard.classfile.util.SimplifiedVisitor; 27import proguard.classfile.visitor.ClassVisitor; 28 29 30/** 31 * This ClassVisitor recursively marks all interface 32 * classes that are being used in the visited class. 33 * 34 * @see UsageMarker 35 * 36 * @author Eric Lafortune 37 */ 38public class InterfaceUsageMarker 39extends SimplifiedVisitor 40implements ClassVisitor, 41 ConstantVisitor 42{ 43 private final UsageMarker usageMarker; 44 45 // Fields acting as a return parameters for several methods. 46 private boolean used; 47 private boolean anyUsed; 48 49 50 /** 51 * Creates a new InterfaceUsageMarker. 52 * @param usageMarker the usage marker that is used to mark the classes 53 * and class members. 54 */ 55 public InterfaceUsageMarker(UsageMarker usageMarker) 56 { 57 this.usageMarker = usageMarker; 58 } 59 60 61 // Implementations for ClassVisitor. 62 63 public void visitProgramClass(ProgramClass programClass) 64 { 65 boolean classUsed = usageMarker.isUsed(programClass); 66 boolean classPossiblyUsed = usageMarker.isPossiblyUsed(programClass); 67 68 if (classUsed || classPossiblyUsed) 69 { 70 // Check if any interfaces are being used. 71 boolean oldAnyUsed = anyUsed; 72 anyUsed = false; 73 74 programClass.interfaceConstantsAccept(this); 75 76 classUsed |= anyUsed; 77 anyUsed = oldAnyUsed; 78 79 // Is this an interface with a preliminary mark? 80 if (classPossiblyUsed) 81 { 82 // Should it be included now? 83 if (classUsed) 84 { 85 // At least one if this interface's interfaces is being used. 86 // Mark this interface as well. 87 usageMarker.markAsUsed(programClass); 88 89 // Mark this interface's name. 90 programClass.thisClassConstantAccept(this); 91 92 // Mark the superclass (java/lang/Object). 93 programClass.superClassConstantAccept(this); 94 } 95 else 96 { 97 // Unmark this interface, so we don't bother looking at it again. 98 usageMarker.markAsUnused(programClass); 99 } 100 } 101 } 102 103 // The return value. 104 used = classUsed; 105 } 106 107 108 public void visitLibraryClass(LibraryClass libraryClass) 109 { 110 // The return values. 111 used = true; 112 anyUsed = true; 113 } 114 115 116 // Implementations for ConstantVisitor. 117 118 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 119 { 120 boolean classUsed = usageMarker.isUsed(classConstant); 121 122 if (!classUsed) 123 { 124 // The ClassConstant isn't marked as being used yet. But maybe it 125 // should be included as an interface, so check the actual class. 126 classConstant.referencedClassAccept(this); 127 classUsed = used; 128 129 if (classUsed) 130 { 131 // The class is being used. Mark the ClassConstant as being used 132 // as well. 133 usageMarker.markAsUsed(classConstant); 134 135 clazz.constantPoolEntryAccept(classConstant.u2nameIndex, this); 136 } 137 } 138 139 // The return values. 140 used = classUsed; 141 anyUsed |= classUsed; 142 } 143 144 145 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 146 { 147 if (!usageMarker.isUsed(utf8Constant)) 148 { 149 usageMarker.markAsUsed(utf8Constant); 150 } 151 } 152} 153