001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.taskdefs.optional.depend.constantpool;
019:
020: import java.io.DataInputStream;
021: import java.io.IOException;
022: import java.util.Enumeration;
023: import java.util.Hashtable;
024: import java.util.Vector;
025:
026: /**
027: * The constant pool of a Java class. The constant pool is a collection of
028: * constants used in a Java class file. It stores strings, constant values,
029: * class names, method names, field names etc.
030: *
031: * @see <a href="http://java.sun.com/docs/books/vmspec/">The Java Virtual
032: * Machine Specification</a>
033: */
034: public class ConstantPool {
035:
036: /** The entries in the constant pool. */
037: private Vector entries;
038:
039: /**
040: * A Hashtable of UTF8 entries - used to get constant pool indexes of
041: * the UTF8 values quickly
042: */
043: private Hashtable utf8Indexes;
044:
045: /** Initialise the constant pool. */
046: public ConstantPool() {
047: entries = new Vector();
048:
049: // The zero index is never present in the constant pool itself so
050: // we add a null entry for it
051: entries.addElement(null);
052:
053: utf8Indexes = new Hashtable();
054: }
055:
056: /**
057: * Read the constant pool from a class input stream.
058: *
059: * @param classStream the DataInputStream of a class file.
060: * @exception IOException if there is a problem reading the constant pool
061: * from the stream
062: */
063: public void read(DataInputStream classStream) throws IOException {
064: int numEntries = classStream.readUnsignedShort();
065:
066: for (int i = 1; i < numEntries;) {
067: ConstantPoolEntry nextEntry = ConstantPoolEntry
068: .readEntry(classStream);
069:
070: i += nextEntry.getNumEntries();
071:
072: addEntry(nextEntry);
073: }
074: }
075:
076: /**
077: * Get the size of the constant pool.
078: *
079: * @return the size of the constant pool
080: */
081: public int size() {
082: return entries.size();
083: }
084:
085: /**
086: * Add an entry to the constant pool.
087: *
088: * @param entry the new entry to be added to the constant pool.
089: * @return the index into the constant pool at which the entry is
090: * stored.
091: */
092: public int addEntry(ConstantPoolEntry entry) {
093: int index = entries.size();
094:
095: entries.addElement(entry);
096:
097: int numSlots = entry.getNumEntries();
098:
099: // add null entries for any additional slots required.
100: for (int j = 0; j < numSlots - 1; ++j) {
101: entries.addElement(null);
102: }
103:
104: if (entry instanceof Utf8CPInfo) {
105: Utf8CPInfo utf8Info = (Utf8CPInfo) entry;
106:
107: utf8Indexes.put(utf8Info.getValue(), new Integer(index));
108: }
109:
110: return index;
111: }
112:
113: /**
114: * Resolve the entries in the constant pool. Resolution of the constant
115: * pool involves transforming indexes to other constant pool entries
116: * into the actual data for that entry.
117: */
118: public void resolve() {
119: for (Enumeration i = entries.elements(); i.hasMoreElements();) {
120: ConstantPoolEntry poolInfo = (ConstantPoolEntry) i
121: .nextElement();
122:
123: if (poolInfo != null && !poolInfo.isResolved()) {
124: poolInfo.resolve(this );
125: }
126: }
127: }
128:
129: /**
130: * Get an constant pool entry at a particular index.
131: *
132: * @param index the index into the constant pool.
133: * @return the constant pool entry at that index.
134: */
135: public ConstantPoolEntry getEntry(int index) {
136: return (ConstantPoolEntry) entries.elementAt(index);
137: }
138:
139: /**
140: * Get the index of a given UTF8 constant pool entry.
141: *
142: * @param value the string value of the UTF8 entry.
143: * @return the index at which the given string occurs in the constant
144: * pool or -1 if the value does not occur.
145: */
146: public int getUTF8Entry(String value) {
147: int index = -1;
148: Integer indexInteger = (Integer) utf8Indexes.get(value);
149:
150: if (indexInteger != null) {
151: index = indexInteger.intValue();
152: }
153:
154: return index;
155: }
156:
157: /**
158: * Get the index of a given CONSTANT_CLASS entry in the constant pool.
159: *
160: * @param className the name of the class for which the class entry
161: * index is required.
162: * @return the index at which the given class entry occurs in the
163: * constant pool or -1 if the value does not occur.
164: */
165: public int getClassEntry(String className) {
166: int index = -1;
167:
168: for (int i = 0; i < entries.size() && index == -1; ++i) {
169: Object element = entries.elementAt(i);
170:
171: if (element instanceof ClassCPInfo) {
172: ClassCPInfo classinfo = (ClassCPInfo) element;
173:
174: if (classinfo.getClassName().equals(className)) {
175: index = i;
176: }
177: }
178: }
179:
180: return index;
181: }
182:
183: /**
184: * Get the index of a given constant value entry in the constant pool.
185: *
186: * @param constantValue the constant value for which the index is
187: * required.
188: * @return the index at which the given value entry occurs in the
189: * constant pool or -1 if the value does not occur.
190: */
191: public int getConstantEntry(Object constantValue) {
192: int index = -1;
193:
194: for (int i = 0; i < entries.size() && index == -1; ++i) {
195: Object element = entries.elementAt(i);
196:
197: if (element instanceof ConstantCPInfo) {
198: ConstantCPInfo constantEntry = (ConstantCPInfo) element;
199:
200: if (constantEntry.getValue().equals(constantValue)) {
201: index = i;
202: }
203: }
204: }
205:
206: return index;
207: }
208:
209: /**
210: * Get the index of a given CONSTANT_METHODREF entry in the constant
211: * pool.
212: *
213: * @param methodClassName the name of the class which contains the
214: * method being referenced.
215: * @param methodName the name of the method being referenced.
216: * @param methodType the type descriptor of the method being referenced.
217: * @return the index at which the given method ref entry occurs in the
218: * constant pool or -1 if the value does not occur.
219: */
220: public int getMethodRefEntry(String methodClassName,
221: String methodName, String methodType) {
222: int index = -1;
223:
224: for (int i = 0; i < entries.size() && index == -1; ++i) {
225: Object element = entries.elementAt(i);
226:
227: if (element instanceof MethodRefCPInfo) {
228: MethodRefCPInfo methodRefEntry = (MethodRefCPInfo) element;
229:
230: if (methodRefEntry.getMethodClassName().equals(
231: methodClassName)
232: && methodRefEntry.getMethodName().equals(
233: methodName)
234: && methodRefEntry.getMethodType().equals(
235: methodType)) {
236: index = i;
237: }
238: }
239: }
240:
241: return index;
242: }
243:
244: /**
245: * Get the index of a given CONSTANT_INTERFACEMETHODREF entry in the
246: * constant pool.
247: *
248: * @param interfaceMethodClassName the name of the interface which
249: * contains the method being referenced.
250: * @param interfaceMethodName the name of the method being referenced.
251: * @param interfaceMethodType the type descriptor of the method being
252: * referenced.
253: * @return the index at which the given method ref entry occurs in the
254: * constant pool or -1 if the value does not occur.
255: */
256: public int getInterfaceMethodRefEntry(
257: String interfaceMethodClassName,
258: String interfaceMethodName, String interfaceMethodType) {
259: int index = -1;
260:
261: for (int i = 0; i < entries.size() && index == -1; ++i) {
262: Object element = entries.elementAt(i);
263:
264: if (element instanceof InterfaceMethodRefCPInfo) {
265: InterfaceMethodRefCPInfo interfaceMethodRefEntry = (InterfaceMethodRefCPInfo) element;
266:
267: if (interfaceMethodRefEntry
268: .getInterfaceMethodClassName().equals(
269: interfaceMethodClassName)
270: && interfaceMethodRefEntry
271: .getInterfaceMethodName().equals(
272: interfaceMethodName)
273: && interfaceMethodRefEntry
274: .getInterfaceMethodType().equals(
275: interfaceMethodType)) {
276: index = i;
277: }
278: }
279: }
280:
281: return index;
282: }
283:
284: /**
285: * Get the index of a given CONSTANT_FIELDREF entry in the constant
286: * pool.
287: *
288: * @param fieldClassName the name of the class which contains the field
289: * being referenced.
290: * @param fieldName the name of the field being referenced.
291: * @param fieldType the type descriptor of the field being referenced.
292: * @return the index at which the given field ref entry occurs in the
293: * constant pool or -1 if the value does not occur.
294: */
295: public int getFieldRefEntry(String fieldClassName,
296: String fieldName, String fieldType) {
297: int index = -1;
298:
299: for (int i = 0; i < entries.size() && index == -1; ++i) {
300: Object element = entries.elementAt(i);
301:
302: if (element instanceof FieldRefCPInfo) {
303: FieldRefCPInfo fieldRefEntry = (FieldRefCPInfo) element;
304:
305: if (fieldRefEntry.getFieldClassName().equals(
306: fieldClassName)
307: && fieldRefEntry.getFieldName().equals(
308: fieldName)
309: && fieldRefEntry.getFieldType().equals(
310: fieldType)) {
311: index = i;
312: }
313: }
314: }
315:
316: return index;
317: }
318:
319: /**
320: * Get the index of a given CONSTANT_NAMEANDTYPE entry in the constant
321: * pool.
322: *
323: * @param name the name
324: * @param type the type
325: * @return the index at which the given NameAndType entry occurs in the
326: * constant pool or -1 if the value does not occur.
327: */
328: public int getNameAndTypeEntry(String name, String type) {
329: int index = -1;
330:
331: for (int i = 0; i < entries.size() && index == -1; ++i) {
332: Object element = entries.elementAt(i);
333:
334: if (element instanceof NameAndTypeCPInfo) {
335: NameAndTypeCPInfo nameAndTypeEntry = (NameAndTypeCPInfo) element;
336:
337: if (nameAndTypeEntry.getName().equals(name)
338: && nameAndTypeEntry.getType().equals(type)) {
339: index = i;
340: }
341: }
342: }
343:
344: return index;
345: }
346:
347: /**
348: * Dump the constant pool to a string.
349: *
350: * @return the constant pool entries as strings
351: */
352: public String toString() {
353: StringBuffer sb = new StringBuffer("\n");
354: int size = entries.size();
355:
356: for (int i = 0; i < size; ++i) {
357: sb.append("[" + i + "] = " + getEntry(i) + "\n");
358: }
359:
360: return sb.toString();
361: }
362:
363: }
|