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