summaryrefslogtreecommitdiff
path: root/src/proguard/classfile/editor/ConstantPoolEditor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/classfile/editor/ConstantPoolEditor.java')
-rw-r--r--src/proguard/classfile/editor/ConstantPoolEditor.java665
1 files changed, 665 insertions, 0 deletions
diff --git a/src/proguard/classfile/editor/ConstantPoolEditor.java b/src/proguard/classfile/editor/ConstantPoolEditor.java
new file mode 100644
index 0000000..8663dee
--- /dev/null
+++ b/src/proguard/classfile/editor/ConstantPoolEditor.java
@@ -0,0 +1,665 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package proguard.classfile.editor;
+
+import proguard.classfile.*;
+import proguard.classfile.constant.*;
+
+/**
+ * This class can add constant pool entries to a given class.
+ *
+ * @author Eric Lafortune
+ */
+public class ConstantPoolEditor
+{
+ private static final boolean DEBUG = false;
+
+ private ProgramClass targetClass;
+
+
+ /**
+ * Creates a new ConstantPoolEditor that will edit constants in the given
+ * target class.
+ */
+ public ConstantPoolEditor(ProgramClass targetClass)
+ {
+ this.targetClass = targetClass;
+ }
+
+
+ /**
+ * Finds or creates a IntegerConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the Utf8Constant.
+ */
+ public int addIntegerConstant(int value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Integer)
+ {
+ IntegerConstant integerConstant = (IntegerConstant)constant;
+ if (integerConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new IntegerConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a LongConstant constant pool entry with the given value.
+ * @return the constant pool index of the LongConstant.
+ */
+ public int addLongConstant(long value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Long)
+ {
+ LongConstant longConstant = (LongConstant)constant;
+ if (longConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new LongConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a FloatConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the FloatConstant.
+ */
+ public int addFloatConstant(float value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Float)
+ {
+ FloatConstant floatConstant = (FloatConstant)constant;
+ if (floatConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new FloatConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a DoubleConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the DoubleConstant.
+ */
+ public int addDoubleConstant(double value)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Double)
+ {
+ DoubleConstant doubleConstant = (DoubleConstant)constant;
+ if (doubleConstant.getValue() == value)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new DoubleConstant(value));
+ }
+
+
+ /**
+ * Finds or creates a StringConstant constant pool entry with the given
+ * value.
+ * @return the constant pool index of the StringConstant.
+ */
+ public int addStringConstant(String string,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_String)
+ {
+ StringConstant stringConstant = (StringConstant)constant;
+ if (stringConstant.getString(targetClass).equals(string))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new StringConstant(addUtf8Constant(string),
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry for the given
+ * class and field.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(referencedClass.getName(),
+ referencedMember.getName(referencedClass),
+ referencedMember.getDescriptor(referencedClass),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class name, field name, and descriptor.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(String className,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(className,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class name, field name, and descriptor.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(String className,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(addClassConstant(className, referencedClass),
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class constant pool entry index, field name, and descriptor.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(int classIndex,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addFieldrefConstant(classIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a FieldrefConstant constant pool entry with the given
+ * class constant pool entry index and name and type constant pool entry
+ * index.
+ * @return the constant pool index of the FieldrefConstant.
+ */
+ public int addFieldrefConstant(int classIndex,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Fieldref)
+ {
+ FieldrefConstant fieldrefConstant = (FieldrefConstant)constant;
+ if (fieldrefConstant.u2classIndex == classIndex &&
+ fieldrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new FieldrefConstant(classIndex,
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class name, method name, and descriptor.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(String className,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(className,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class name, method name, and descriptor.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(String className,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(addClassConstant(className, referencedClass),
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry for the
+ * given class and method.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(referencedClass.getName(),
+ referencedMember.getName(referencedClass),
+ referencedMember.getDescriptor(referencedClass),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class constant pool entry index, method name, and descriptor.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(int classIndex,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addInterfaceMethodrefConstant(classIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a InterfaceMethodrefConstant constant pool entry with the
+ * given class constant pool entry index and name and type constant pool
+ * entry index.
+ * @return the constant pool index of the InterfaceMethodrefConstant.
+ */
+ public int addInterfaceMethodrefConstant(int classIndex,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_InterfaceMethodref)
+ {
+ InterfaceMethodrefConstant methodrefConstant = (InterfaceMethodrefConstant)constant;
+ if (methodrefConstant.u2classIndex == classIndex &&
+ methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new InterfaceMethodrefConstant(classIndex,
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry for the given
+ * class and method.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(referencedClass.getName(),
+ referencedMember.getName(referencedClass),
+ referencedMember.getDescriptor(referencedClass),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class name, method name, and descriptor.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(String className,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(className,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class name, method name, and descriptor.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(String className,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(addClassConstant(className, referencedClass),
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class constant pool entry index, method name, and descriptor.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(int classIndex,
+ String name,
+ String descriptor,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ return addMethodrefConstant(classIndex,
+ addNameAndTypeConstant(name, descriptor),
+ referencedClass,
+ referencedMember);
+ }
+
+
+ /**
+ * Finds or creates a MethodrefConstant constant pool entry with the given
+ * class constant pool entry index and name and type constant pool entry
+ * index.
+ * @return the constant pool index of the MethodrefConstant.
+ */
+ public int addMethodrefConstant(int classIndex,
+ int nameAndTypeIndex,
+ Clazz referencedClass,
+ Member referencedMember)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Methodref)
+ {
+ MethodrefConstant methodrefConstant = (MethodrefConstant)constant;
+ if (methodrefConstant.u2classIndex == classIndex &&
+ methodrefConstant.u2nameAndTypeIndex == nameAndTypeIndex)
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new MethodrefConstant(classIndex,
+ nameAndTypeIndex,
+ referencedClass,
+ referencedMember));
+ }
+
+
+ /**
+ * Finds or creates a ClassConstant constant pool entry for the given class.
+ * @return the constant pool index of the ClassConstant.
+ */
+ public int addClassConstant(Clazz referencedClass)
+ {
+ return addClassConstant(referencedClass.getName(),
+ referencedClass);
+ }
+
+
+ /**
+ * Finds or creates a ClassConstant constant pool entry with the given name.
+ * @return the constant pool index of the ClassConstant.
+ */
+ public int addClassConstant(String name,
+ Clazz referencedClass)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Class)
+ {
+ ClassConstant classConstant = (ClassConstant)constant;
+ if (classConstant.getName(targetClass).equals(name))
+ {
+ return index;
+ }
+ }
+ }
+
+ int nameIndex = addUtf8Constant(name);
+
+ return addConstant(new ClassConstant(nameIndex, referencedClass));
+ }
+
+
+ /**
+ * Finds or creates a NameAndTypeConstant constant pool entry with the given
+ * name and type.
+ * @return the constant pool index of the NameAndTypeConstant.
+ */
+ public int addNameAndTypeConstant(String name,
+ String type)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_NameAndType)
+ {
+ NameAndTypeConstant nameAndTypeConstant = (NameAndTypeConstant)constant;
+ if (nameAndTypeConstant.getName(targetClass).equals(name) &&
+ nameAndTypeConstant.getType(targetClass).equals(type))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new NameAndTypeConstant(addUtf8Constant(name),
+ addUtf8Constant(type)));
+ }
+
+
+ /**
+ * Finds or creates a Utf8Constant constant pool entry for the given string.
+ * @return the constant pool index of the Utf8Constant.
+ */
+ public int addUtf8Constant(String string)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Check if the entry already exists.
+ for (int index = 1; index < constantPoolCount; index++)
+ {
+ Constant constant = constantPool[index];
+
+ if (constant != null &&
+ constant.getTag() == ClassConstants.CONSTANT_Utf8)
+ {
+ Utf8Constant utf8Constant = (Utf8Constant)constant;
+ if (utf8Constant.getString().equals(string))
+ {
+ return index;
+ }
+ }
+ }
+
+ return addConstant(new Utf8Constant(string));
+ }
+
+
+ /**
+ * Adds a given constant pool entry to the end of the constant pool/
+ * @return the constant pool index for the added entry.
+ */
+ public int addConstant(Constant constant)
+ {
+ int constantPoolCount = targetClass.u2constantPoolCount;
+ Constant[] constantPool = targetClass.constantPool;
+
+ // Make sure there is enough space for another constant pool entry.
+ if (constantPool.length < constantPoolCount+2)
+ {
+ targetClass.constantPool = new Constant[constantPoolCount+2];
+ System.arraycopy(constantPool, 0,
+ targetClass.constantPool, 0,
+ constantPoolCount);
+ constantPool = targetClass.constantPool;
+ }
+
+ if (DEBUG)
+ {
+ System.out.println(targetClass.getName()+": adding ["+constant.getClass().getName()+"] at index "+targetClass.u2constantPoolCount);
+ }
+
+ // Create a new Utf8Constant for the given string.
+ constantPool[targetClass.u2constantPoolCount++] = constant;
+
+ // Long constants and double constants take up two entries in the
+ // constant pool.
+ int tag = constant.getTag();
+ if (tag == ClassConstants.CONSTANT_Long ||
+ tag == ClassConstants.CONSTANT_Double)
+ {
+ constantPool[targetClass.u2constantPoolCount++] = null;
+ }
+
+ return constantPoolCount;
+ }
+}