1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2013 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.classfile.editor; 22 23import proguard.classfile.*; 24import proguard.classfile.constant.*; 25import proguard.classfile.constant.visitor.ConstantVisitor; 26import proguard.util.ListUtil; 27 28/** 29 * This ConstantVisitor adds all constants that it visits to the constant pool 30 * of a given target class. 31 * 32 * @author Eric Lafortune 33 */ 34public class ConstantAdder 35implements ConstantVisitor 36{ 37 private final ConstantPoolEditor constantPoolEditor; 38 39 private int constantIndex; 40 41 42 /** 43 * Creates a new ConstantAdder that will copy constants into the given 44 * target class. 45 */ 46 public ConstantAdder(ProgramClass targetClass) 47 { 48 constantPoolEditor = new ConstantPoolEditor(targetClass); 49 } 50 51 52 /** 53 * Adds a copy of the specified constant in the given class and returns 54 * its index. If the specified index is 0, the returned value is 0 too. 55 */ 56 public int addConstant(Clazz clazz, int constantIndex) 57 { 58 clazz.constantPoolEntryAccept(constantIndex, this); 59 60 return this.constantIndex; 61 } 62 63 64 /** 65 * Adds a copy of the given constant in the given class and returns 66 * its index. 67 */ 68 public int addConstant(Clazz clazz, Constant constant) 69 { 70 constant.accept(clazz, this); 71 72 return this.constantIndex; 73 } 74 75 76 /** 77 * Returns the index of the most recently created constant in the constant 78 * pool of the target class. 79 */ 80 public int getConstantIndex() 81 { 82 return constantIndex; 83 } 84 85 86 // Implementations for ConstantVisitor. 87 88 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 89 { 90 constantIndex = 91 constantPoolEditor.addIntegerConstant(integerConstant.getValue()); 92 } 93 94 95 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 96 { 97 constantIndex = 98 constantPoolEditor.addLongConstant(longConstant.getValue()); 99 } 100 101 102 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 103 { 104 constantIndex = 105 constantPoolEditor.addFloatConstant(floatConstant.getValue()); 106 } 107 108 109 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 110 { 111 constantIndex = 112 constantPoolEditor.addDoubleConstant(doubleConstant.getValue()); 113 } 114 115 116 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 117 { 118 constantIndex = 119 constantPoolEditor.addStringConstant(stringConstant.getString(clazz), 120 stringConstant.referencedClass, 121 stringConstant.referencedMember); 122 } 123 124 125 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 126 { 127 constantIndex = 128 constantPoolEditor.addUtf8Constant(utf8Constant.getString()); 129 } 130 131 132 public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) 133 { 134 // First add the name and type constant. 135 clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this); 136 137 // Copy the referenced classes. 138 Clazz[] referencedClasses = invokeDynamicConstant.referencedClasses; 139 Clazz[] referencedClassesCopy = null; 140 if (referencedClasses != null) 141 { 142 referencedClassesCopy = new Clazz[referencedClasses.length]; 143 System.arraycopy(referencedClasses, 0, 144 referencedClassesCopy, 0, 145 referencedClasses.length); 146 } 147 148 // Then add the actual invoke dynamic constant. 149 constantIndex = 150 constantPoolEditor.addInvokeDynamicConstant(invokeDynamicConstant.getBootstrapMethodAttributeIndex(), 151 constantIndex, 152 referencedClassesCopy); 153 } 154 155 156 public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) 157 { 158 // First add the field ref, interface method ref, or method ref 159 // constant. 160 clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this); 161 162 // Then add the actual method handle constant. 163 constantIndex = 164 constantPoolEditor.addMethodHandleConstant(methodHandleConstant.getReferenceKind(), 165 constantIndex); 166 } 167 168 169 public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) 170 { 171 // First add the referenced class constant, with its own referenced class. 172 clazz.constantPoolEntryAccept(fieldrefConstant.u2classIndex, this); 173 174 // Then add the actual field reference constant, with its referenced 175 // class and class member. 176 constantIndex = 177 constantPoolEditor.addFieldrefConstant(constantIndex, 178 fieldrefConstant.getName(clazz), 179 fieldrefConstant.getType(clazz), 180 fieldrefConstant.referencedClass, 181 fieldrefConstant.referencedMember); 182 } 183 184 185 public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) 186 { 187 // First add the referenced class constant, with its own referenced class. 188 clazz.constantPoolEntryAccept(interfaceMethodrefConstant.u2classIndex, this); 189 190 // Then add the actual interface method reference constant, with its 191 // referenced class and class member. 192 constantIndex = 193 constantPoolEditor.addInterfaceMethodrefConstant(constantIndex, 194 interfaceMethodrefConstant.getName(clazz), 195 interfaceMethodrefConstant.getType(clazz), 196 interfaceMethodrefConstant.referencedClass, 197 interfaceMethodrefConstant.referencedMember); 198 } 199 200 201 public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant) 202 { 203 // First add the referenced class constant, with its own referenced class. 204 clazz.constantPoolEntryAccept(methodrefConstant.u2classIndex, this); 205 206 // Then add the actual method reference constant, with its referenced 207 // class and class member. 208 constantIndex = 209 constantPoolEditor.addMethodrefConstant(constantIndex, 210 methodrefConstant.getName(clazz), 211 methodrefConstant.getType(clazz), 212 methodrefConstant.referencedClass, 213 methodrefConstant.referencedMember); 214 } 215 216 217 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 218 { 219 // Add the class constant, with its referenced class.. 220 constantIndex = 221 constantPoolEditor.addClassConstant(classConstant.getName(clazz), 222 classConstant.referencedClass); 223 } 224 225 226 public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) 227 { 228 constantIndex = 229 constantPoolEditor.addMethodTypeConstant(methodTypeConstant.getType(clazz)); 230 } 231 232 233 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 234 { 235 constantIndex = 236 constantPoolEditor.addNameAndTypeConstant(nameAndTypeConstant.getName(clazz), 237 nameAndTypeConstant.getType(clazz)); 238 } 239} 240