001: /* ===========================================================================
002: * $RCSfile: ConstantPool.java,v $
003: * ===========================================================================
004: *
005: * RetroGuard -- an obfuscation package for Java classfiles.
006: *
007: * Copyright (c) 1998-2006 Mark Welsh (markw@retrologic.com)
008: *
009: * This program can be redistributed and/or modified under the terms of the
010: * Version 2 of the GNU General Public License as published by the Free
011: * Software Foundation.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: */
019:
020: package COM.rl.obf.classfile;
021:
022: import java.io.*;
023: import java.util.*;
024: import COM.rl.util.*;
025:
026: /**
027: * A representation of the data in a Java class-file's Constant Pool.
028: * Constant Pool entries are managed by reference counting.
029: *
030: * @author Mark Welsh
031: */
032: public class ConstantPool {
033: // Constants -------------------------------------------------------------
034:
035: // Fields ----------------------------------------------------------------
036: private ClassFile myClassFile;
037: private Vector pool;
038:
039: // Class Methods ---------------------------------------------------------
040:
041: // Instance Methods ------------------------------------------------------
042: /** Ctor, which initializes Constant Pool using an array of CpInfo. */
043: public ConstantPool(ClassFile classFile, CpInfo[] cpInfo)
044: throws Exception {
045: myClassFile = classFile;
046: int length = cpInfo.length;
047: pool = new Vector(length);
048: pool.setSize(length);
049: for (int i = 0; i < length; i++) {
050: pool.setElementAt(cpInfo[i], i);
051: }
052: }
053:
054: /** Return an Enumeration of all Constant Pool entries. */
055: public Enumeration elements() {
056: return pool.elements();
057: }
058:
059: /** Return the Constant Pool length. */
060: public int length() {
061: return pool.size();
062: }
063:
064: /** Return the specified Constant Pool entry. */
065: public CpInfo getCpEntry(int i) throws Exception {
066: if (i < pool.size()) {
067: return (CpInfo) pool.elementAt(i);
068: }
069: throw new Exception("Constant Pool index out of range.");
070: }
071:
072: /** Set the reference count for each element, using references from the owning ClassFile. */
073: public void updateRefCount() throws Exception {
074: // Reset all reference counts to zero
075: walkPool(new PoolAction() {
076: public void defaultAction(CpInfo cpInfo) throws Exception {
077: cpInfo.resetRefCount();
078: }
079: });
080:
081: // Count the direct references to Utf8 entries
082: myClassFile.markUtf8Refs(this );
083:
084: // Count the direct references to NameAndType entries
085: myClassFile.markNTRefs(this );
086:
087: // Go through pool, clearing the Utf8 entries which have no references
088: walkPool(new PoolAction() {
089: public void utf8Action(Utf8CpInfo cpInfo) throws Exception {
090: if (cpInfo.getRefCount() == 0)
091: cpInfo.clearString();
092: }
093: });
094: }
095:
096: /** Increment the reference count for the specified element. */
097: public void incRefCount(int i) throws Exception {
098: CpInfo cpInfo = (CpInfo) pool.elementAt(i);
099: if (cpInfo == null) {
100: // This can happen for JDK1.2 code so remove - 981123
101: //throw new Exception("Illegal access to a Constant Pool element.");
102: } else {
103: cpInfo.incRefCount();
104: }
105: }
106:
107: /** Remap a specified Utf8 entry to the given value and return its new index. */
108: public int remapUtf8To(String newString, int oldIndex)
109: throws Exception {
110: decRefCount(oldIndex);
111: return addUtf8Entry(newString);
112: }
113:
114: /** Decrement the reference count for the specified element, blanking if Utf and refs are zero. */
115: public void decRefCount(int i) throws Exception {
116: CpInfo cpInfo = (CpInfo) pool.elementAt(i);
117: if (cpInfo == null) {
118: // This can happen for JDK1.2 code so remove - 981123
119: //throw new Exception("Illegal access to a Constant Pool element.");
120: } else {
121: cpInfo.decRefCount();
122: }
123: }
124:
125: /** Add an entry to the constant pool and return its index. */
126: public int addEntry(CpInfo entry) throws Exception {
127: // Try to replace an old, blanked Utf8 entry
128: int index = pool.size();
129: pool.setSize(index + 1);
130: pool.setElementAt(entry, index);
131: return index;
132: }
133:
134: /** Add a string to the constant pool and return its index. */
135: protected int addUtf8Entry(String s) throws Exception {
136: // Search pool for the string. If found, just increment the reference count and return the index
137: for (int i = 0; i < pool.size(); i++) {
138: Object o = pool.elementAt(i);
139: if (o instanceof Utf8CpInfo) {
140: Utf8CpInfo entry = (Utf8CpInfo) o;
141: if (entry.getString().equals(s)) {
142: entry.incRefCount();
143: return i;
144: }
145: }
146: }
147:
148: // No luck, so try to overwrite an old, blanked entry
149: for (int i = 0; i < pool.size(); i++) {
150: Object o = pool.elementAt(i);
151: if (o instanceof Utf8CpInfo) {
152: Utf8CpInfo entry = (Utf8CpInfo) o;
153: if (entry.getRefCount() == 0) {
154: entry.setString(s);
155: entry.incRefCount();
156: return i;
157: }
158: }
159: }
160:
161: // Still no luck, so append a fresh Utf8CpInfo entry to the pool
162: return addEntry(new Utf8CpInfo(s));
163: }
164:
165: // Data walker
166: class PoolAction {
167: public void utf8Action(Utf8CpInfo cpInfo) throws Exception {
168: defaultAction(cpInfo);
169: }
170:
171: public void defaultAction(CpInfo cpInfo) throws Exception {
172: }
173: }
174:
175: private void walkPool(PoolAction pa) throws Exception {
176: for (Enumeration enm = pool.elements(); enm.hasMoreElements();) {
177: Object o = enm.nextElement();
178: if (o instanceof Utf8CpInfo) {
179: pa.utf8Action((Utf8CpInfo) o);
180: } else if (o instanceof CpInfo) {
181: pa.defaultAction((CpInfo) o);
182: }
183: }
184: }
185: }
|