| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.bcel.generic; |
| |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.apache.bcel.Const; |
| import org.apache.bcel.classfile.Constant; |
| import org.apache.bcel.classfile.ConstantCP; |
| import org.apache.bcel.classfile.ConstantClass; |
| import org.apache.bcel.classfile.ConstantDouble; |
| import org.apache.bcel.classfile.ConstantDynamic; |
| import org.apache.bcel.classfile.ConstantFieldref; |
| import org.apache.bcel.classfile.ConstantFloat; |
| import org.apache.bcel.classfile.ConstantInteger; |
| import org.apache.bcel.classfile.ConstantInterfaceMethodref; |
| import org.apache.bcel.classfile.ConstantInvokeDynamic; |
| import org.apache.bcel.classfile.ConstantLong; |
| import org.apache.bcel.classfile.ConstantMethodref; |
| import org.apache.bcel.classfile.ConstantNameAndType; |
| import org.apache.bcel.classfile.ConstantPool; |
| import org.apache.bcel.classfile.ConstantString; |
| import org.apache.bcel.classfile.ConstantUtf8; |
| import org.apache.bcel.classfile.Utility; |
| |
| /** |
| * This class is used to build up a constant pool. The user adds constants via 'addXXX' methods, 'addString', 'addClass', and so on. These methods return an |
| * index into the constant pool. Finally, 'getFinalConstantPool()' returns the constant pool built up. Intermediate versions of the constant pool can be |
| * obtained with 'getConstantPool()'. A constant pool has capacity for Constants.MAX_SHORT entries. Note that the first (0) is used by the JVM and that Double |
| * and Long constants need two slots. |
| * |
| * @see Constant |
| */ |
| public class ConstantPoolGen { |
| |
| private static final int DEFAULT_BUFFER_SIZE = 256; |
| |
| private static final String METHODREF_DELIM = ":"; |
| |
| private static final String IMETHODREF_DELIM = "#"; |
| |
| private static final String FIELDREF_DELIM = "&"; |
| |
| private static final String NAT_DELIM = "%"; // Name and Type |
| |
| /** |
| * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter |
| */ |
| @Deprecated |
| protected int size; |
| |
| /** |
| * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter |
| */ |
| @Deprecated |
| protected Constant[] constants; |
| |
| /** |
| * @deprecated (since 6.0) will be made private; do not access directly, use getSize() |
| */ |
| @Deprecated |
| protected int index = 1; // First entry (0) used by JVM |
| |
| private final Map<String, Integer> stringTable = new HashMap<>(); |
| |
| private final Map<String, Integer> classTable = new HashMap<>(); |
| |
| private final Map<String, Integer> utf8Table = new HashMap<>(); |
| |
| private final Map<String, Integer> natTable = new HashMap<>(); |
| |
| private final Map<String, Integer> cpTable = new HashMap<>(); |
| |
| /** |
| * Constructs a new empty constant pool. |
| */ |
| public ConstantPoolGen() { |
| size = DEFAULT_BUFFER_SIZE; |
| constants = new Constant[size]; |
| } |
| |
| /** |
| * Constructs a new instance with the given array of constants. |
| * |
| * @param cs array of given constants, new ones will be appended. |
| */ |
| public ConstantPoolGen(final Constant[] cs) { |
| final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE); |
| |
| size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), Const.MAX_CP_ENTRIES + 1); |
| constants = Arrays.copyOf(cs, size); |
| |
| if (cs.length > 0) { |
| index = cs.length; |
| } |
| |
| for (int i = 1; i < index; i++) { |
| final Constant c = constants[i]; |
| if (c instanceof ConstantString) { |
| final ConstantString s = (ConstantString) c; |
| final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; |
| final String key = u8.getBytes(); |
| if (!stringTable.containsKey(key)) { |
| stringTable.put(key, Integer.valueOf(i)); |
| } |
| } else if (c instanceof ConstantClass) { |
| final ConstantClass s = (ConstantClass) c; |
| final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; |
| final String key = u8.getBytes(); |
| if (!classTable.containsKey(key)) { |
| classTable.put(key, Integer.valueOf(i)); |
| } |
| } else if (c instanceof ConstantNameAndType) { |
| final ConstantNameAndType n = (ConstantNameAndType) c; |
| final ConstantUtf8 u8NameIdx = (ConstantUtf8) constants[n.getNameIndex()]; |
| final ConstantUtf8 u8SigIdx = (ConstantUtf8) constants[n.getSignatureIndex()]; |
| |
| sb.append(u8NameIdx.getBytes()); |
| sb.append(NAT_DELIM); |
| sb.append(u8SigIdx.getBytes()); |
| final String key = sb.toString(); |
| sb.delete(0, sb.length()); |
| |
| if (!natTable.containsKey(key)) { |
| natTable.put(key, Integer.valueOf(i)); |
| } |
| } else if (c instanceof ConstantUtf8) { |
| final ConstantUtf8 u = (ConstantUtf8) c; |
| final String key = u.getBytes(); |
| if (!utf8Table.containsKey(key)) { |
| utf8Table.put(key, Integer.valueOf(i)); |
| } |
| } else if (c instanceof ConstantCP) { |
| final ConstantCP m = (ConstantCP) c; |
| final String className; |
| ConstantUtf8 u8; |
| |
| if (c instanceof ConstantInvokeDynamic) { |
| className = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex()); |
| } else if (c instanceof ConstantDynamic) { |
| className = Integer.toString(((ConstantDynamic) m).getBootstrapMethodAttrIndex()); |
| } else { |
| final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; |
| u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; |
| className = Utility.pathToPackage(u8.getBytes()); |
| } |
| |
| final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; |
| u8 = (ConstantUtf8) constants[n.getNameIndex()]; |
| final String methodName = u8.getBytes(); |
| u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; |
| final String signature = u8.getBytes(); |
| |
| // Since name cannot begin with digit, we can use METHODREF_DELIM without fear of duplicates |
| String delim = METHODREF_DELIM; |
| if (c instanceof ConstantInterfaceMethodref) { |
| delim = IMETHODREF_DELIM; |
| } else if (c instanceof ConstantFieldref) { |
| delim = FIELDREF_DELIM; |
| } |
| |
| sb.append(className); |
| sb.append(delim); |
| sb.append(methodName); |
| sb.append(delim); |
| sb.append(signature); |
| final String key = sb.toString(); |
| sb.delete(0, sb.length()); |
| |
| if (!cpTable.containsKey(key)) { |
| cpTable.put(key, Integer.valueOf(i)); |
| } |
| } |
| // else if (c == null) { // entries may be null |
| // // nothing to do |
| // } else if (c instanceof ConstantInteger) { |
| // // nothing to do |
| // } else if (c instanceof ConstantLong) { |
| // // nothing to do |
| // } else if (c instanceof ConstantFloat) { |
| // // nothing to do |
| // } else if (c instanceof ConstantDouble) { |
| // // nothing to do |
| // } else if (c instanceof org.apache.bcel.classfile.ConstantMethodType) { |
| // // TODO should this be handled somehow? |
| // } else if (c instanceof org.apache.bcel.classfile.ConstantMethodHandle) { |
| // // TODO should this be handled somehow? |
| // } else if (c instanceof org.apache.bcel.classfile.ConstantModule) { |
| // // TODO should this be handled somehow? |
| // } else if (c instanceof org.apache.bcel.classfile.ConstantPackage) { |
| // // TODO should this be handled somehow? |
| // } else { |
| // // Not helpful, should throw an exception. |
| // assert false : "Unexpected constant type: " + c.getClass().getName(); |
| // } |
| } |
| } |
| |
| /** |
| * Constructs a new instance with the given constant pool. |
| * |
| * @param cp the constant pool. |
| */ |
| public ConstantPoolGen(final ConstantPool cp) { |
| this(cp.getConstantPool()); |
| } |
| |
| /** |
| * Add a reference to an array class (for example, String[][]) as needed by MULTIANEWARRAY instruction, for example, to the ConstantPool. |
| * |
| * @param type type of array class. |
| * @return index of entry. |
| */ |
| public int addArrayClass(final ArrayType type) { |
| return addClass_(type.getSignature()); |
| } |
| |
| /** |
| * Add a new Class reference to the ConstantPool for a given type. |
| * |
| * @param type Class to add. |
| * @return index of entry. |
| */ |
| public int addClass(final ObjectType type) { |
| return addClass(type.getClassName()); |
| } |
| |
| /** |
| * Add a new Class reference to the ConstantPool, if it is not already in there. |
| * |
| * @param str Class to add. |
| * @return index of entry. |
| */ |
| public int addClass(final String str) { |
| return addClass_(Utility.packageToPath(str)); |
| } |
| |
| private int addClass_(final String clazz) { |
| final int cpRet; |
| if ((cpRet = lookupClass(clazz)) != -1) { |
| return cpRet; // Already in CP |
| } |
| adjustSize(); |
| final ConstantClass c = new ConstantClass(addUtf8(clazz)); |
| final int ret = index; |
| constants[index++] = c; |
| return computeIfAbsent(classTable, clazz, ret); |
| } |
| |
| /** |
| * Adds a constant from another ConstantPool and returns the new index. |
| * |
| * @param constant The constant to add. |
| * @param cpGen Source pool. |
| * @return index of entry. |
| */ |
| public int addConstant(final Constant constant, final ConstantPoolGen cpGen) { |
| final Constant[] constants = cpGen.getConstantPool().getConstantPool(); |
| switch (constant.getTag()) { |
| case Const.CONSTANT_String: { |
| final ConstantString s = (ConstantString) constant; |
| final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; |
| return addString(u8.getBytes()); |
| } |
| case Const.CONSTANT_Class: { |
| final ConstantClass s = (ConstantClass) constant; |
| final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; |
| return addClass(u8.getBytes()); |
| } |
| case Const.CONSTANT_NameAndType: { |
| final ConstantNameAndType n = (ConstantNameAndType) constant; |
| final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; |
| final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; |
| return addNameAndType(u8.getBytes(), u8_2.getBytes()); |
| } |
| case Const.CONSTANT_Utf8: |
| return addUtf8(((ConstantUtf8) constant).getBytes()); |
| case Const.CONSTANT_Double: |
| return addDouble(((ConstantDouble) constant).getBytes()); |
| case Const.CONSTANT_Float: |
| return addFloat(((ConstantFloat) constant).getBytes()); |
| case Const.CONSTANT_Long: |
| return addLong(((ConstantLong) constant).getBytes()); |
| case Const.CONSTANT_Integer: |
| return addInteger(((ConstantInteger) constant).getBytes()); |
| case Const.CONSTANT_InterfaceMethodref: |
| case Const.CONSTANT_Methodref: |
| case Const.CONSTANT_Fieldref: { |
| final ConstantCP m = (ConstantCP) constant; |
| final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; |
| final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; |
| ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; |
| final String className = Utility.pathToPackage(u8.getBytes()); |
| u8 = (ConstantUtf8) constants[n.getNameIndex()]; |
| final String name = u8.getBytes(); |
| u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; |
| final String signature = u8.getBytes(); |
| switch (constant.getTag()) { |
| case Const.CONSTANT_InterfaceMethodref: |
| return addInterfaceMethodref(className, name, signature); |
| case Const.CONSTANT_Methodref: |
| return addMethodref(className, name, signature); |
| case Const.CONSTANT_Fieldref: |
| return addFieldref(className, name, signature); |
| default: // Never reached |
| throw new IllegalArgumentException("Unknown constant type " + constant); |
| } |
| } |
| default: // Never reached |
| throw new IllegalArgumentException("Unknown constant type " + constant); |
| } |
| } |
| |
| /** |
| * Add a new double constant to the ConstantPool, if it is not already in there. |
| * |
| * @param n Double number to add. |
| * @return index of entry. |
| */ |
| public int addDouble(final double n) { |
| int ret; |
| if ((ret = lookupDouble(n)) != -1) { |
| return ret; // Already in CP |
| } |
| adjustSize(); |
| ret = index; |
| constants[index] = new ConstantDouble(n); |
| index += 2; // Wastes one entry according to spec |
| return ret; |
| } |
| |
| /** |
| * Add a new Fieldref constant to the ConstantPool, if it is not already in there. |
| * |
| * @param className class name string to add. |
| * @param fieldName field name string to add. |
| * @param signature signature string to add. |
| * @return index of entry. |
| */ |
| public int addFieldref(final String className, final String fieldName, final String signature) { |
| final int cpRet; |
| if ((cpRet = lookupFieldref(className, fieldName, signature)) != -1) { |
| return cpRet; // Already in CP |
| } |
| adjustSize(); |
| final int classIndex = addClass(className); |
| final int nameAndTypeIndex = addNameAndType(fieldName, signature); |
| final int ret = index; |
| constants[index++] = new ConstantFieldref(classIndex, nameAndTypeIndex); |
| return computeIfAbsent(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature, ret); |
| } |
| |
| /** |
| * Add a new Float constant to the ConstantPool, if it is not already in there. |
| * |
| * @param n Float number to add. |
| * @return index of entry. |
| */ |
| public int addFloat(final float n) { |
| int ret; |
| if ((ret = lookupFloat(n)) != -1) { |
| return ret; // Already in CP |
| } |
| adjustSize(); |
| ret = index; |
| constants[index++] = new ConstantFloat(n); |
| return ret; |
| } |
| |
| /** |
| * Add a new Integer constant to the ConstantPool, if it is not already in there. |
| * |
| * @param n integer number to add. |
| * @return index of entry. |
| */ |
| public int addInteger(final int n) { |
| int ret; |
| if ((ret = lookupInteger(n)) != -1) { |
| return ret; // Already in CP |
| } |
| adjustSize(); |
| ret = index; |
| constants[index++] = new ConstantInteger(n); |
| return ret; |
| } |
| |
| /** |
| * Adds a new InterfaceMethodref constant to the ConstantPool. |
| * |
| * @param method the method to add. |
| * @return index of entry. |
| */ |
| public int addInterfaceMethodref(final MethodGen method) { |
| return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); |
| } |
| |
| /** |
| * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already in there. |
| * |
| * @param className class name string to add. |
| * @param methodName method name string to add. |
| * @param signature signature string to add. |
| * @return index of entry. |
| */ |
| public int addInterfaceMethodref(final String className, final String methodName, final String signature) { |
| final int cpRet; |
| if ((cpRet = lookupInterfaceMethodref(className, methodName, signature)) != -1) { |
| return cpRet; // Already in CP |
| } |
| adjustSize(); |
| final int classIndex = addClass(className); |
| final int nameAndTypeIndex = addNameAndType(methodName, signature); |
| final int ret = index; |
| constants[index++] = new ConstantInterfaceMethodref(classIndex, nameAndTypeIndex); |
| return computeIfAbsent(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature, ret); |
| } |
| |
| /** |
| * Add a new long constant to the ConstantPool, if it is not already in there. |
| * |
| * @param n Long number to add. |
| * @return index of entry. |
| */ |
| public int addLong(final long n) { |
| int ret; |
| if ((ret = lookupLong(n)) != -1) { |
| return ret; // Already in CP |
| } |
| adjustSize(); |
| ret = index; |
| constants[index] = new ConstantLong(n); |
| index += 2; // Wastes one entry according to spec |
| return ret; |
| } |
| |
| /** |
| * Adds a new Methodref constant to the ConstantPool. |
| * |
| * @param method the method to add. |
| * @return index of entry. |
| */ |
| public int addMethodref(final MethodGen method) { |
| return addMethodref(method.getClassName(), method.getName(), method.getSignature()); |
| } |
| |
| /** |
| * Add a new Methodref constant to the ConstantPool, if it is not already in there. |
| * |
| * @param className class name string to add. |
| * @param methodName method name string to add. |
| * @param signature method signature string to add. |
| * @return index of entry. |
| */ |
| public int addMethodref(final String className, final String methodName, final String signature) { |
| final int cpRet; |
| if ((cpRet = lookupMethodref(className, methodName, signature)) != -1) { |
| return cpRet; // Already in CP |
| } |
| adjustSize(); |
| final int nameAndTypeIndex = addNameAndType(methodName, signature); |
| final int classIndex = addClass(className); |
| final int ret = index; |
| constants[index++] = new ConstantMethodref(classIndex, nameAndTypeIndex); |
| return computeIfAbsent(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature, ret); |
| } |
| |
| /** |
| * Add a new NameAndType constant to the ConstantPool if it is not already in there. |
| * |
| * @param name Name string to add. |
| * @param signature signature string to add. |
| * @return index of entry. |
| */ |
| public int addNameAndType(final String name, final String signature) { |
| int ret; |
| if ((ret = lookupNameAndType(name, signature)) != -1) { |
| return ret; // Already in CP |
| } |
| adjustSize(); |
| final int nameIndex = addUtf8(name); |
| final int signatureIndex = addUtf8(signature); |
| ret = index; |
| constants[index++] = new ConstantNameAndType(nameIndex, signatureIndex); |
| return computeIfAbsent(natTable, name + NAT_DELIM + signature, ret); |
| } |
| |
| /** |
| * Add a new String constant to the ConstantPool, if it is not already in there. |
| * |
| * @param str String to add. |
| * @return index of entry. |
| */ |
| public int addString(final String str) { |
| int ret; |
| if ((ret = lookupString(str)) != -1) { |
| return ret; // Already in CP |
| } |
| final int utf8 = addUtf8(str); |
| adjustSize(); |
| final ConstantString s = new ConstantString(utf8); |
| ret = index; |
| constants[index++] = s; |
| return computeIfAbsent(stringTable, str, ret); |
| } |
| |
| /** |
| * Add a new Utf8 constant to the ConstantPool, if it is not already in there. |
| * |
| * @param n Utf8 string to add. |
| * @return index of entry. |
| */ |
| public int addUtf8(final String n) { |
| int ret; |
| if ((ret = lookupUtf8(n)) != -1) { |
| return ret; // Already in CP |
| } |
| adjustSize(); |
| ret = index; |
| constants[index++] = new ConstantUtf8(n); |
| return computeIfAbsent(utf8Table, n, ret); |
| } |
| |
| /** |
| * Resize internal array of constants. |
| */ |
| protected void adjustSize() { |
| // 3 extra spaces are needed as some entries may take 3 slots |
| if (index + 3 >= Const.MAX_CP_ENTRIES + 1) { |
| throw new IllegalStateException("The number of constants " + (index + 3) |
| + " is over the size of the constant pool: " |
| + Const.MAX_CP_ENTRIES); |
| } |
| |
| if (index + 3 >= size) { |
| final Constant[] tmp = constants; |
| size *= 2; |
| // the constant array shall not exceed the size of the constant pool |
| size = Math.min(size, Const.MAX_CP_ENTRIES + 1); |
| constants = new Constant[size]; |
| System.arraycopy(tmp, 0, constants, 0, index); |
| } |
| } |
| |
| private int computeIfAbsent(final Map<String, Integer> map, final String key, final int value) { |
| return map.computeIfAbsent(key, k -> Integer.valueOf(value)); |
| } |
| |
| /** |
| * Gets a constant pool entry at the specified index. |
| * |
| * @param i index in constant pool. |
| * @return constant pool entry at index i. |
| */ |
| public Constant getConstant(final int i) { |
| return constants[i]; |
| } |
| |
| /** |
| * Gets the intermediate constant pool. |
| * |
| * @return intermediate constant pool. |
| */ |
| public ConstantPool getConstantPool() { |
| return new ConstantPool(constants); |
| } |
| |
| /** |
| * Gets the constant pool with proper length. |
| * |
| * @return constant pool with proper length. |
| */ |
| public ConstantPool getFinalConstantPool() { |
| return new ConstantPool(Arrays.copyOf(constants, index)); |
| } |
| |
| private int getIndex(final Map<String, Integer> map, final String key) { |
| return toIndex(map.get(key)); |
| } |
| |
| /** |
| * Gets the current size of constant pool. |
| * |
| * @return current size of constant pool. |
| */ |
| public int getSize() { |
| return index; |
| } |
| |
| /** |
| * Look for ConstantClass in ConstantPool named 'str'. |
| * |
| * @param str String to search for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupClass(final String str) { |
| return getIndex(classTable, Utility.packageToPath(str)); |
| } |
| |
| /** |
| * Look for ConstantDouble in ConstantPool. |
| * |
| * @param n Double number to look for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupDouble(final double n) { |
| final long bits = Double.doubleToLongBits(n); |
| for (int i = 1; i < index; i++) { |
| if (constants[i] instanceof ConstantDouble) { |
| final ConstantDouble c = (ConstantDouble) constants[i]; |
| if (Double.doubleToLongBits(c.getBytes()) == bits) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Look for ConstantFieldref in ConstantPool. |
| * |
| * @param className Where to find method. |
| * @param fieldName Guess what. |
| * @param signature return and argument types. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupFieldref(final String className, final String fieldName, final String signature) { |
| return getIndex(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature); |
| } |
| |
| /** |
| * Look for ConstantFloat in ConstantPool. |
| * |
| * @param n Float number to look for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupFloat(final float n) { |
| final int bits = Float.floatToIntBits(n); |
| for (int i = 1; i < index; i++) { |
| if (constants[i] instanceof ConstantFloat) { |
| final ConstantFloat c = (ConstantFloat) constants[i]; |
| if (Float.floatToIntBits(c.getBytes()) == bits) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Look for ConstantInteger in ConstantPool. |
| * |
| * @param n integer number to look for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupInteger(final int n) { |
| for (int i = 1; i < index; i++) { |
| if (constants[i] instanceof ConstantInteger) { |
| final ConstantInteger c = (ConstantInteger) constants[i]; |
| if (c.getBytes() == n) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Looks up an InterfaceMethodref in the ConstantPool. |
| * |
| * @param method the method to look for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupInterfaceMethodref(final MethodGen method) { |
| return lookupInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); |
| } |
| |
| /** |
| * Look for ConstantInterfaceMethodref in ConstantPool. |
| * |
| * @param className Where to find method. |
| * @param methodName Guess what. |
| * @param signature return and argument types. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupInterfaceMethodref(final String className, final String methodName, final String signature) { |
| return getIndex(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature); |
| } |
| |
| /** |
| * Look for ConstantLong in ConstantPool. |
| * |
| * @param n Long number to look for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupLong(final long n) { |
| for (int i = 1; i < index; i++) { |
| if (constants[i] instanceof ConstantLong) { |
| final ConstantLong c = (ConstantLong) constants[i]; |
| if (c.getBytes() == n) { |
| return i; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Looks up a Methodref in the ConstantPool. |
| * |
| * @param method the method to look for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupMethodref(final MethodGen method) { |
| return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); |
| } |
| |
| /** |
| * Look for ConstantMethodref in ConstantPool. |
| * |
| * @param className Where to find method. |
| * @param methodName Guess what. |
| * @param signature return and argument types. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupMethodref(final String className, final String methodName, final String signature) { |
| return getIndex(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature); |
| } |
| |
| /** |
| * Look for ConstantNameAndType in ConstantPool. |
| * |
| * @param name of variable/method. |
| * @param signature of variable/method. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupNameAndType(final String name, final String signature) { |
| return getIndex(natTable, name + NAT_DELIM + signature); |
| } |
| |
| /** |
| * Look for ConstantString in ConstantPool containing String 'str'. |
| * |
| * @param str String to search for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupString(final String str) { |
| return getIndex(stringTable, str); |
| } |
| |
| /** |
| * Look for ConstantUtf8 in ConstantPool. |
| * |
| * @param n Utf8 string to look for. |
| * @return index on success, -1 otherwise. |
| */ |
| public int lookupUtf8(final String n) { |
| return getIndex(utf8Table, n); |
| } |
| |
| /** |
| * Use with care! |
| * |
| * @param i index in constant pool. |
| * @param c new constant pool entry at index i. |
| */ |
| public void setConstant(final int i, final Constant c) { |
| constants[i] = c; |
| } |
| |
| private int toIndex(final Integer index) { |
| return index != null ? index.intValue() : -1; |
| } |
| |
| /** |
| * @return String representation. |
| */ |
| @Override |
| public String toString() { |
| final StringBuilder buf = new StringBuilder(); |
| for (int i = 1; i < index; i++) { |
| buf.append(i).append(")").append(constants[i]).append("\n"); |
| } |
| return buf.toString(); |
| } |
| } |