KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > yworks > yguard > obf > classfile > ConstantPool


1 /**
2  * YGuard -- an obfuscation library for Java(TM) classfiles.
3  *
4  * Original Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
5  * Modifications Copyright (c) 2002 yWorks GmbH (yguard@yworks.com)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * The author may be contacted at yguard@yworks.com
22  *
23  * Java and all Java-based marks are trademarks or registered
24  * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
25  */

26 package com.yworks.yguard.obf.classfile;
27
28 import java.io.*;
29 import java.util.*;
30
31 /**
32  * A representation of the data in a Java class-file's Constant Pool.
33  * Constant Pool entries are managed by reference counting.
34  *
35  * @author Mark Welsh
36  */

37 public class ConstantPool
38 {
39     // Constants -------------------------------------------------------------
40

41
42     // Fields ----------------------------------------------------------------
43
private ClassFile myClassFile;
44     private Vector pool;
45
46
47     // Class Methods ---------------------------------------------------------
48

49
50     // Instance Methods ------------------------------------------------------
51
/** Ctor, which initializes Constant Pool using an array of CpInfo. */
52     public ConstantPool(ClassFile classFile, CpInfo[] cpInfo)
53     {
54         myClassFile = classFile;
55         int length = cpInfo.length;
56         pool = new Vector(length);
57         pool.setSize(length);
58         for (int i = 0; i < length; i++)
59         {
60             pool.setElementAt(cpInfo[i], i);
61         }
62     }
63
64     /** Return an Enumeration of all Constant Pool entries. */
65     public Enumeration elements()
66     {
67         return pool.elements();
68     }
69
70     /** Return the Constant Pool length. */
71     public int length()
72     {
73         return pool.size();
74     }
75
76     /** Return the specified Constant Pool entry. */
77     public CpInfo getCpEntry(int i)
78     {
79         if (i < pool.size())
80         {
81             return (CpInfo)pool.elementAt(i);
82         }
83         throw new IndexOutOfBoundsException JavaDoc("Constant Pool index out of range.");
84     }
85
86     /** Set the reference count for each element, using references from the owning ClassFile. */
87     public void updateRefCount()
88     {
89         // Reset all reference counts to zero
90
walkPool(new PoolAction() {
91             public void defaultAction(CpInfo cpInfo) {cpInfo.resetRefCount();}
92         });
93
94         // Count the direct references to Utf8 entries
95
myClassFile.markUtf8Refs(this);
96
97         // Count the direct references to NameAndType entries
98
myClassFile.markNTRefs(this);
99
100         // Go through pool, clearing the Utf8 entries which have no references
101
walkPool(new PoolAction() {
102             public void utf8Action(Utf8CpInfo cpInfo) {if (cpInfo.getRefCount() == 0) cpInfo.clearString();}
103         });
104     }
105
106     /** Increment the reference count for the specified element. */
107     public void incRefCount(int i)
108     {
109         CpInfo cpInfo = (CpInfo)pool.elementAt(i);
110         if (cpInfo == null)
111         {
112             // This can happen for JDK1.2 code so remove - 981123
113
//throw new Exception("Illegal access to a Constant Pool element.");
114
}
115         else
116         {
117             cpInfo.incRefCount();
118         }
119     }
120
121     /** Remap a specified Utf8 entry to the given value and return its new index. */
122     public int remapUtf8To(String JavaDoc newString, int oldIndex)
123     {
124         decRefCount(oldIndex);
125         return addUtf8Entry(newString);
126     }
127
128     /** Decrement the reference count for the specified element, blanking if Utf and refs are zero. */
129     public void decRefCount(int i)
130     {
131         CpInfo cpInfo = (CpInfo)pool.elementAt(i);
132         if (cpInfo == null)
133         {
134             // This can happen for JDK1.2 code so remove - 981123
135
//throw new Exception("Illegal access to a Constant Pool element.");
136
}
137         else
138         {
139             cpInfo.decRefCount();
140         }
141     }
142
143     /** Add an entry to the constant pool and return its index. */
144     public int addEntry(CpInfo entry)
145     {
146         int oldLength = pool.size();
147         pool.setSize(oldLength + 1);
148         pool.setElementAt(entry, oldLength);
149         return oldLength;
150     }
151
152     // Add a string to the constant pool and return its index
153
private int addUtf8Entry(String JavaDoc s)
154     {
155         // Search pool for the string. If found, just increment the reference count and return the index
156
for (int i = 0; i < pool.size(); i++)
157         {
158             Object JavaDoc o = pool.elementAt(i);
159             if (o instanceof Utf8CpInfo)
160             {
161                 Utf8CpInfo entry = (Utf8CpInfo)o;
162                 if (entry.getString().equals(s))
163                 {
164                     entry.incRefCount();
165                     return i;
166                 }
167             }
168         }
169
170         // No luck, so try to overwrite an old, blanked entry
171
for (int i = 0; i < pool.size(); i++)
172         {
173             Object JavaDoc o = pool.elementAt(i);
174             if (o instanceof Utf8CpInfo)
175             {
176                 Utf8CpInfo entry = (Utf8CpInfo)o;
177                 if (entry.getRefCount() == 0)
178                 {
179                     entry.setString(s);
180                     entry.incRefCount();
181                     return i;
182                 }
183             }
184         }
185
186         // Still no luck, so append a fresh Utf8CpInfo entry to the pool
187
return addEntry(new Utf8CpInfo(s));
188     }
189
190     // Data walker
191
class PoolAction {public void utf8Action(Utf8CpInfo cpInfo) {defaultAction(cpInfo);}
192                       public void defaultAction(CpInfo cpInfo) {}}
193     private void walkPool(PoolAction pa)
194     {
195         for (Enumeration enumeration = pool.elements(); enumeration.hasMoreElements(); )
196         {
197             Object JavaDoc o = enumeration.nextElement();
198             if (o instanceof Utf8CpInfo)
199             {
200                 pa.utf8Action((Utf8CpInfo)o);
201             }
202             else if (o instanceof CpInfo)
203             {
204                 pa.defaultAction((CpInfo)o);
205             }
206         }
207     }
208 }
209
Popular Tags