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 */ 21 package proguard.classfile.util; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.CodeAttribute; 25 import proguard.classfile.attribute.annotation.*; 26 import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor; 27 import proguard.classfile.attribute.visitor.AllAttributeVisitor; 28 import proguard.classfile.constant.*; 29 import proguard.classfile.constant.visitor.ConstantVisitor; 30 import proguard.classfile.instruction.*; 31 import proguard.classfile.instruction.visitor.*; 32 import proguard.classfile.visitor.MemberVisitor; 33 34 /** 35 * This ElementValueVisitor initializes the field references of the 36 * EnumConstantElementValue instances that it visits. 37 * 38 * @author Eric Lafortune 39 */ 40 public class EnumFieldReferenceInitializer 41 extends SimplifiedVisitor 42 implements ElementValueVisitor, 43 InstructionVisitor, 44 ConstantVisitor 45 { 46 //* 47 private static final boolean DEBUG = false; 48 /*/ 49 private static boolean DEBUG = true; 50 //*/ 51 52 private MemberVisitor enumFieldFinder = new AllAttributeVisitor( 53 new AllInstructionVisitor(this)); 54 55 // Fields acting as parameters and return values for the visitors. 56 private String enumTypeName; 57 private String enumConstantName; 58 private boolean enumConstantNameFound; 59 private Clazz referencedEnumClass; 60 private Field referencedEnumField; 61 62 63 // Implementations for ElementValueVisitor. 64 visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)65 public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {} 66 67 visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)68 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 69 { 70 71 if (enumConstantElementValue.referencedClasses != null && 72 enumConstantElementValue.referencedClasses.length > 0) 73 { 74 referencedEnumClass = enumConstantElementValue.referencedClasses[0]; 75 if (referencedEnumClass != null) 76 { 77 // Try to find the enum field through the static enum 78 // initialization code (at least for program classes). 79 enumTypeName = enumConstantElementValue.getTypeName(clazz); 80 enumConstantName = enumConstantElementValue.getConstantName(clazz); 81 referencedEnumField = null; 82 referencedEnumClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT, 83 ClassConstants.METHOD_TYPE_CLINIT, 84 enumFieldFinder); 85 86 // Otherwise try to find the enum field through its name. 87 // The constant name could be different from the field name, if 88 // the latter is already obfuscated. 89 if (referencedEnumField == null) 90 { 91 referencedEnumField = 92 referencedEnumClass.findField(enumConstantName, 93 enumTypeName); 94 } 95 96 if (DEBUG) 97 { 98 System.out.println("EnumFieldReferenceInitializer: ["+referencedEnumClass.getName()+"."+enumConstantName+"] -> "+referencedEnumField); 99 } 100 101 enumConstantElementValue.referencedField = referencedEnumField; 102 } 103 } 104 } 105 106 107 // Implementations for InstructionVisitor. 108 visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)109 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 110 111 visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)112 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 113 { 114 switch (constantInstruction.opcode) 115 { 116 case InstructionConstants.OP_LDC: 117 case InstructionConstants.OP_LDC_W: 118 case InstructionConstants.OP_PUTSTATIC: 119 clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); 120 break; 121 } 122 } 123 124 125 // Implementations for ConstantVisitor. 126 visitAnyConstant(Clazz clazz, Constant constant)127 public void visitAnyConstant(Clazz clazz, Constant constant) {} 128 129 visitStringConstant(Clazz clazz, StringConstant stringConstant)130 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 131 { 132 enumConstantNameFound = 133 enumConstantName.equals(stringConstant.getString(clazz)); 134 } 135 136 visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)137 public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) 138 { 139 if (enumConstantNameFound) 140 { 141 if (enumTypeName.equals(fieldrefConstant.getType(clazz))) 142 { 143 referencedEnumField = (Field)fieldrefConstant.referencedMember; 144 } 145 146 enumConstantNameFound = false; 147 } 148 } 149 }