KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > javaguard > classfile > ConstantPool


1 /**
2  * JavaGuard -- an obfuscation package for Java classfiles.
3  *
4  * Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
5  * Copyright (c) 2002 Thorsten Heit (theit@gmx.de)
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 theit@gmx.de.
22  *
23  *
24  * $Id: ConstantPool.java,v 1.3 2002/05/11 19:38:20 glurk Exp $
25  */

26 package net.sf.javaguard.classfile;
27
28 import java.util.Iterator JavaDoc;
29 import java.util.Vector JavaDoc;
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 <a HREF="mailto:theit@gmx.de">Thorsten Heit</a>
36  * @author <a HREF="mailto:markw@retrologic.com">Mark Welsh</a>
37  */

38 public class ConstantPool {
39   /** Holds the owning class file. */
40   private ClassFile classFile;
41   /** Stores the elements of the current constant pool. */
42   private Vector JavaDoc poolVector;
43   
44   
45   
46   
47   /** Initialize the constant pool using an array of CpInfo objects.
48    * @param classFile the class file the pool belongs to
49    * @param cpInfo array of objects to store in the constant pool
50    */

51   public ConstantPool(ClassFile classFile, CpInfo[] cpInfo) {
52     setClassFile(classFile);
53     int length = cpInfo.length;
54     Vector JavaDoc vec = new Vector JavaDoc(length);
55     vec.setSize(length);
56     for (int i = 0; i < length; i++) {
57       vec.setElementAt(cpInfo[i], i);
58     }
59     setPool(vec);
60   }
61   
62   
63   
64   
65   /** Return an iteration of all entries in the constant pool.
66    * @return iterator of all entries in the constant pool
67    */

68   public Iterator JavaDoc iterator() {
69     return getPool().iterator();
70   }
71   
72   
73   /** Return the length of the constant pool.
74    * @return length of the constant pool
75    */

76   public int length() {
77     return getPool().size();
78   }
79   
80   
81   
82   
83   /** Return the specified constant pool entry.
84    * @param index the index in the constant pool
85    * @return the specified constant pool entry
86    * @throws ArrayIndexOutOfBoundsException if the index is invalid
87    */

88   public CpInfo getCpEntry(int index)
89   throws ArrayIndexOutOfBoundsException JavaDoc {
90     if (index < getPool().size()) {
91       return (CpInfo) getPool().elementAt(index);
92     }
93     throw new ArrayIndexOutOfBoundsException JavaDoc("Constant Pool index out of range.");
94   }
95   
96   
97   
98   
99   /** Set the reference count for each element, using the references from the
100    * owning ClassFile.
101    */

102   public void updateRefCount() {
103     // Reset all reference counts to zero
104
walkPool(new PoolAction() {
105       public void defaultAction(CpInfo cpInfo) {
106         cpInfo.resetRefCount();
107       }
108     });
109     
110     // Count the direct references to Utf8 entries
111
getClassFile().markUtf8Refs(this);
112     
113     // Count the direct references to NameAndType entries
114
getClassFile().markNTRefs(this);
115     
116     // Go through pool, clearing the Utf8 entries which have no references
117
walkPool(new PoolAction() {
118       public void utf8Action(Utf8CpInfo cpInfo) {
119         if (0 == cpInfo.getRefCount()) {
120           cpInfo.clearString();
121         }
122       }
123     });
124   }
125   
126   
127   
128   
129   /** Increment the reference count for the specified element.
130    * @param index the index of the element in the constant pool
131    * @throws ArrayIndexOutOfBoundsException if the index is invalid
132    */

133   public void incRefCount(int index)
134   throws ArrayIndexOutOfBoundsException JavaDoc {
135     if (index < getPool().size()) {
136       CpInfo cpInfo = (CpInfo) getPool().elementAt(index);
137       if (null != cpInfo) {
138         cpInfo.incRefCount();
139       } else {
140         throw new IllegalStateException JavaDoc("Illegal access to a Constant Pool element.");
141       }
142     } else {
143       throw new ArrayIndexOutOfBoundsException JavaDoc("Constant Pool index out of range.");
144     }
145   }
146   
147   
148   
149   
150   /** Decrement the reference count for the specified element, blanking if Utf
151    * and refs are zero.
152    * @param index the index of the element in the constant pool
153    * @throws ArrayIndexOutOfBoundsException if the index is invalid
154    */

155   public void decRefCount(int index)
156   throws ArrayIndexOutOfBoundsException JavaDoc {
157     if (index < getPool().size()) {
158       CpInfo cpInfo = (CpInfo) getPool().elementAt(index);
159       if (null != cpInfo) {
160         cpInfo.decRefCount();
161       } else {
162         throw new IllegalStateException JavaDoc("Illegal access to a Constant Pool element.");
163       }
164     } else {
165       throw new ArrayIndexOutOfBoundsException JavaDoc("Constant Pool index out of range.");
166     }
167   }
168   
169   
170   
171   
172   /** Remap a specified Utf8 entry to the given value and return its new index.
173    * @param newString the new Utf8 string
174    * @param oldIndex the old index in the constant pool
175    * @return new index in the constant pool
176    */

177   public int remapUtf8To(String JavaDoc newString, int oldIndex) {
178     decRefCount(oldIndex);
179     return addUtf8Entry(newString);
180   }
181   
182   
183   
184   
185   /** Add an entry to the constant pool and return its index.
186    * @param entry the new entry for the constant pool
187    * @return the index of the entry in the constant pool
188    */

189   public int addEntry(CpInfo entry) {
190     int oldLength = getPool().size();
191     getPool().setSize(oldLength + 1);
192     getPool().setElementAt(entry, oldLength);
193     return oldLength;
194   }
195   
196   
197   
198   
199   /** Add a string to the constant pool and return its index.
200    * @param str the new string to add to the constant pool
201    * @return the index of the entry in the constant pool
202    */

203   private int addUtf8Entry(String JavaDoc str) {
204     // Search the pool for the string. If found, just increment the reference
205
// count and return the index
206
for (int i = 0; i < getPool().size(); i++) {
207       Object JavaDoc obj = getPool().elementAt(i);
208       if (obj instanceof Utf8CpInfo) {
209         Utf8CpInfo entry = (Utf8CpInfo) obj;
210         if (entry.getString().equals(str)) {
211           entry.incRefCount();
212           return i;
213         }
214       }
215     }
216     
217     // No luck, so try to overwrite an old, blanked entry
218
for (int i = 0; i < getPool().size(); i++) {
219       Object JavaDoc obj = getPool().elementAt(i);
220       if (obj instanceof Utf8CpInfo) {
221         Utf8CpInfo entry = (Utf8CpInfo) obj;
222         if (0 == entry.getRefCount()) {
223           entry.setString(str);
224           entry.incRefCount();
225           return i;
226         }
227       }
228     }
229     
230     // Still no luck, so append a fresh Utf8CpInfo entry to the pool
231
return addEntry(new Utf8CpInfo(str));
232   }
233   
234   
235   
236   
237   /** Walk through the constant pool and apply an action to each pool element.
238    * @param pa the pool action for each element
239    */

240   private void walkPool(PoolAction pa) {
241     for (int i=0; i<getPool().size(); i++) {
242       Object JavaDoc obj = getPool().elementAt(i);
243       if (null != obj) {
244         if (obj instanceof Utf8CpInfo) {
245           pa.utf8Action((Utf8CpInfo) obj);
246         } else if (obj instanceof CpInfo) {
247           pa.defaultAction((CpInfo) obj);
248         }
249       }
250     }
251   }
252   
253   
254   
255   
256   /** Stores the class file the constant pool belongs to.
257    * @param classFile the class file the constant pool belongs to
258    * @see #getClassFile
259    */

260   private void setClassFile(ClassFile classFile) {
261     this.classFile = classFile;
262   }
263   
264   
265   /** Returns the class file the constant pool belongs to.
266    * @return class file of the constant pool
267    * @see #setClassFile
268    */

269   private ClassFile getClassFile() {
270     return this.classFile;
271   }
272   
273   
274   
275   
276   /** Sets the vector that contains the pool entries.
277    * @param vec the vector that contains the pool entries
278    * @see #getPool
279    */

280   private void setPool(Vector JavaDoc vec) {
281     this.poolVector = vec;
282   }
283   
284   
285   /** Returns the vector that contains the pool entries.
286    * @return vector that contains the pool entries.
287    * @see #setPool
288    */

289   private Vector JavaDoc getPool() {
290     return poolVector;
291   }
292 }
293
Popular Tags