private void renameString(Hashtable classNameMap, CONSTANT_Index_info cii) {

    int index = cii.getI1();

    String name = nameIndexToString(index);
    String newName = (String) classNameMap.get(name);
    if (newName != null) {

      doRenameString(index, newName);

      return;
    }

    // have to look for arrays
    if (cii.getTag() == VMDescriptor.CONSTANT_Class) {

      if (name.charAt(0) == '[') {
        int classOffset = name.indexOf('L') + 1;

        String baseClassName = name.substring(classOffset, name.length() - 1);

        newName = (String) classNameMap.get(baseClassName);

        if (newName != null) {

          String newArrayClassName = name.substring(0, classOffset) + newName + ";";

          doRenameString(index, newArrayClassName);
        }
      }
    }
  }
  public Enumeration getStrings() {
    HashSet strings = new HashSet(30, 0.8f);

    int size = cptEntries.size();
    for (int i = 1; i < size; i++) {
      ConstantPoolEntry cpe = getEntry(i);

      if ((cpe == null) || (cpe.getTag() != VMDescriptor.CONSTANT_String)) continue;

      CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;

      strings.add(nameIndexToString(cii.getI1()));
    }

    return java.util.Collections.enumeration(strings);
  }
  public void renameClassElements(Hashtable classNameMap, Hashtable memberNameMap) {

    // this & super class
    renameString(classNameMap, (CONSTANT_Index_info) getEntry(this_class));
    renameString(classNameMap, (CONSTANT_Index_info) getEntry(super_class));

    // implemented interfaces
    // handled by Class entries below

    // classes & Strings
    // descriptors
    int size = cptEntries.size();
    for (int i = 1; i < size; i++) {
      ConstantPoolEntry cpe = getEntry(i);

      if (cpe == null) continue;

      switch (cpe.getTag()) {
        case VMDescriptor.CONSTANT_String:
        case VMDescriptor.CONSTANT_Class:
          {
            CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
            renameString(classNameMap, cii);
            break;
          }
        case VMDescriptor.CONSTANT_NameAndType:
          {
            CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;
            String newDescriptor = newDescriptor(classNameMap, nameIndexToString(cii.getI2()));
            if (newDescriptor != null) {
              doRenameString(cii.getI2(), newDescriptor);
            }
            break;
          }

        default:
          continue;
      }
    }

    // System.out.println("Starting Fields");

    // now the methods & fields, only descriptors at this time
    renameMembers(getFields(), classNameMap, memberNameMap);

    renameMembers(getMethods(), classNameMap, memberNameMap);
  }
  /** Add an index reference. */
  private int addIndexReference(int tag, int i1, int i2) {

    // search for the item using the pre-allocated object
    searchIndex.set(tag, i1, i2);

    ConstantPoolEntry item = findMatchingEntry(searchIndex);

    if (item == null) {
      item = new CONSTANT_Index_info(tag, i1, i2);
      addEntry(item.getKey(), item);
    }

    return item.getIndex();
  }
  protected int findIndexIndex(int tag, int i1, int i2) {
    CONSTANT_Index_info item = findIndexEntry(tag, i1, i2);
    if (item == null) return -1;

    return item.getIndex();
  }
  /*
  	public ClassMember findReference(int classIndex, int nameAndTypeIndex) {

  		CONSTANT_Index_info item = findIndexEntry(VMDescriptor.CONSTANT_Methodref,
  				classIndex, nameAndTypeIndex);

  		if (item == null) {

  			item = findIndexEntry(VMDescriptor.CONSTANT_InterfaceMethodref,
  				classIndex, nameAndTypeIndex);

  			if (item == null) {
  				item = findIndexEntry(VMDescriptor.CONSTANT_Fieldref,
  					classIndex, nameAndTypeIndex);

  				if (item == null)
  					return null;

  			}
  		}

  		return new ReferenceMember(this, item);
  	}
  */
  protected CONSTANT_Index_info findIndexEntry(int tag, int i1, int i2) {
    // search for the item using the pre-allocated object
    searchIndex.set(tag, i1, i2);

    return (CONSTANT_Index_info) findMatchingEntry(searchIndex);
  }
  /** Return the class name for an index to a CONSTANT_Class_info. */
  protected String className(int classIndex) {
    CONSTANT_Index_info ci = (CONSTANT_Index_info) getEntry(classIndex);

    return nameIndexToString(ci.getI1()).replace('/', '.');
  }