| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2000 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, if |
| * any, must include the following acknowlegement: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowlegement may appear in the software itself, |
| * if and wherever such third-party acknowlegements normally appear. |
| * |
| * 4. The names "The Jakarta Project", "Ant", and "Apache Software |
| * Foundation" must not be used to endorse or promote products derived |
| * from this software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache" |
| * nor may "Apache" appear in their names without prior written |
| * permission of the Apache Group. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| package org.apache.tools.ant.taskdefs.optional.depend.constantpool; |
| |
| import java.io.*; |
| import java.util.*; |
| |
| /** |
| * The constant pool of a Java class. |
| * |
| * The constant pool is a collection of constants used in a Java class file. It stores |
| * strings, constant values, class names, method names, field names etc. |
| * |
| * @see <a href="http://java.sun.com/docs/books/vmspec/">The Java Virtual Machine Specification</a> |
| * |
| * @author Conor MacNeill |
| */ |
| public class ConstantPool { |
| |
| /** |
| * The entries in the constant pool. |
| */ |
| private Vector entries; |
| |
| /** |
| * A Hashtable of UTF8 entries - used to get constant pool indexes of the UTF8 values quickly |
| */ |
| private Hashtable utf8Indexes; |
| |
| /** |
| * Initialise the constant pool. |
| */ |
| public ConstantPool() { |
| entries = new Vector(); |
| |
| // The zero index is never present in the constant pool itself so |
| // we add a null entry for it |
| entries.addElement(null); |
| |
| utf8Indexes = new Hashtable(); |
| } |
| |
| /** |
| * Read the constant pool from a class input stream. |
| * |
| * @param classStream the DataInputStream of a class file. |
| * |
| * @throws IOException if there is a problem reading the constant pool |
| * from the stream |
| */ |
| public void read(DataInputStream classStream) throws IOException { |
| int numEntries = classStream.readUnsignedShort(); |
| |
| for (int i = 1; i < numEntries; ) { |
| ConstantPoolEntry nextEntry = ConstantPoolEntry.readEntry(classStream); |
| |
| i += nextEntry.getNumEntries(); |
| |
| addEntry(nextEntry); |
| } |
| } |
| |
| /** |
| * Get the size of the constant pool. |
| */ |
| public int size() { |
| return entries.size(); |
| } |
| |
| /** |
| * Add an entry to the constant pool. |
| * |
| * @param entry the new entry to be added to the constant pool. |
| * |
| * @return the index into the constant pool at which the entry is stored. |
| */ |
| public int addEntry(ConstantPoolEntry entry) { |
| int index = entries.size(); |
| |
| entries.addElement(entry); |
| |
| int numSlots = entry.getNumEntries(); |
| |
| // add null entries for any additional slots required. |
| for (int j = 0; j < numSlots - 1; ++j) { |
| entries.addElement(null); |
| } |
| |
| if (entry instanceof Utf8CPInfo) { |
| Utf8CPInfo utf8Info = (Utf8CPInfo) entry; |
| |
| utf8Indexes.put(utf8Info.getValue(), new Integer(index)); |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Resolve the entries in the constant pool. |
| * |
| * Resolution of the constant pool involves transforming indexes to |
| * other constant pool entries into the actual data for that entry. |
| */ |
| public void resolve() { |
| for (Enumeration i = entries.elements(); i.hasMoreElements(); ) { |
| ConstantPoolEntry poolInfo = (ConstantPoolEntry) i.nextElement(); |
| |
| if (poolInfo != null &&!poolInfo.isResolved()) { |
| poolInfo.resolve(this); |
| } |
| } |
| } |
| |
| |
| /** |
| * Get an constant pool entry at a particular index. |
| * |
| * @param index the index into the constant pool. |
| * |
| * @return the constant pool entry at that index. |
| */ |
| public ConstantPoolEntry getEntry(int index) { |
| return (ConstantPoolEntry) entries.elementAt(index); |
| } |
| |
| /** |
| * Get the index of a given UTF8 constant pool entry. |
| * |
| * @param value the string value of the UTF8 entry. |
| * |
| * @return the index at which the given string occurs in the |
| * constant pool or -1 if the value does not occur. |
| */ |
| public int getUTF8Entry(String value) { |
| int index = -1; |
| Integer indexInteger = (Integer) utf8Indexes.get(value); |
| |
| if (indexInteger != null) { |
| index = indexInteger.intValue(); |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Get the index of a given CONSTANT_Class entry in the constant pool. |
| * |
| * @param className the name of the class for which the class entry index is required. |
| * |
| * @return the index at which the given class entry occurs in the |
| * constant pool or -1 if the value does not occur. |
| */ |
| public int getClassEntry(String className) { |
| int index = -1; |
| |
| for (int i = 0; i < entries.size() && index == -1; ++i) { |
| Object element = entries.elementAt(i); |
| |
| if (element instanceof ClassCPInfo) { |
| ClassCPInfo classinfo = (ClassCPInfo) element; |
| |
| if (classinfo.getClassName().equals(className)) { |
| index = i; |
| } |
| } |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Get the index of a given constant value entry in the constant pool. |
| * |
| * @param constantValue the constant value for which the index is required. |
| * |
| * @return the index at which the given value entry occurs in the |
| * constant pool or -1 if the value does not occur. |
| */ |
| public int getConstantEntry(Object constantValue) { |
| int index = -1; |
| |
| for (int i = 0; i < entries.size() && index == -1; ++i) { |
| Object element = entries.elementAt(i); |
| |
| if (element instanceof ConstantCPInfo) { |
| ConstantCPInfo constantEntry = (ConstantCPInfo) element; |
| |
| if (constantEntry.getValue().equals(constantValue)) { |
| index = i; |
| } |
| } |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Get the index of a given CONSTANT_MethodRef entry in the constant pool. |
| * |
| * @param methodClassName the name of the class which contains the method |
| * being referenced. |
| * @param methodName the name of the method being referenced. |
| * @param methodType the type descriptor of the metho dbeing referenced. |
| * |
| * @return the index at which the given method ref entry occurs in the |
| * constant pool or -1 if the value does not occur. |
| */ |
| public int getMethodRefEntry(String methodClassName, String methodName, String methodType) { |
| int index = -1; |
| |
| for (int i = 0; i < entries.size() && index == -1; ++i) { |
| Object element = entries.elementAt(i); |
| |
| if (element instanceof MethodRefCPInfo) { |
| MethodRefCPInfo methodRefEntry = (MethodRefCPInfo) element; |
| |
| if (methodRefEntry.getMethodClassName().equals(methodClassName) |
| && methodRefEntry.getMethodName().equals(methodName) && methodRefEntry.getMethodType().equals(methodType)) { |
| index = i; |
| } |
| } |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Get the index of a given CONSTANT_InterfaceMethodRef entry in the constant pool. |
| * |
| * @param interfaceMethodClassName the name of the interface which contains the method |
| * being referenced. |
| * @param interfaceMethodName the name of the method being referenced. |
| * @param interfaceMethodType the type descriptor of the metho dbeing referenced. |
| * |
| * @return the index at which the given method ref entry occurs in the |
| * constant pool or -1 if the value does not occur. |
| */ |
| public int getInterfaceMethodRefEntry(String interfaceMethodClassName, String interfaceMethodName, String interfaceMethodType) { |
| int index = -1; |
| |
| for (int i = 0; i < entries.size() && index == -1; ++i) { |
| Object element = entries.elementAt(i); |
| |
| if (element instanceof InterfaceMethodRefCPInfo) { |
| InterfaceMethodRefCPInfo interfaceMethodRefEntry = (InterfaceMethodRefCPInfo) element; |
| |
| if (interfaceMethodRefEntry.getInterfaceMethodClassName().equals(interfaceMethodClassName) |
| && interfaceMethodRefEntry.getInterfaceMethodName().equals(interfaceMethodName) |
| && interfaceMethodRefEntry.getInterfaceMethodType().equals(interfaceMethodType)) { |
| index = i; |
| } |
| } |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Get the index of a given CONSTANT_FieldRef entry in the constant pool. |
| * |
| * @param fieldClassName the name of the class which contains the field |
| * being referenced. |
| * @param fieldName the name of the field being referenced. |
| * @param fieldType the type descriptor of the field being referenced. |
| * |
| * @return the index at which the given field ref entry occurs in the |
| * constant pool or -1 if the value does not occur. |
| */ |
| public int getFieldRefEntry(String fieldClassName, String fieldName, String fieldType) { |
| int index = -1; |
| |
| for (int i = 0; i < entries.size() && index == -1; ++i) { |
| Object element = entries.elementAt(i); |
| |
| if (element instanceof FieldRefCPInfo) { |
| FieldRefCPInfo fieldRefEntry = (FieldRefCPInfo) element; |
| |
| if (fieldRefEntry.getFieldClassName().equals(fieldClassName) && fieldRefEntry.getFieldName().equals(fieldName) |
| && fieldRefEntry.getFieldType().equals(fieldType)) { |
| index = i; |
| } |
| } |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Get the index of a given CONSTANT_NameAndType entry in the constant pool. |
| * |
| * @param name the name |
| * @param type the type |
| * |
| * @return the index at which the given NameAndType entry occurs in the |
| * constant pool or -1 if the value does not occur. |
| */ |
| public int getNameAndTypeEntry(String name, String type) { |
| int index = -1; |
| |
| for (int i = 0; i < entries.size() && index == -1; ++i) { |
| Object element = entries.elementAt(i); |
| |
| if (element instanceof NameAndTypeCPInfo) { |
| NameAndTypeCPInfo nameAndTypeEntry = (NameAndTypeCPInfo) element; |
| |
| if (nameAndTypeEntry.getName().equals(name) && nameAndTypeEntry.getType().equals(type)) { |
| index = i; |
| } |
| } |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Dump the constant pool to a string. |
| * |
| * @return the constant pool entries as strings |
| */ |
| public String toString() { |
| StringBuffer sb = new StringBuffer("\n"); |
| int size = entries.size(); |
| |
| for (int i = 0; i < size; ++i) { |
| sb.append("[" + i + "] = " + getEntry(i) + "\n"); |
| } |
| |
| return sb.toString(); |
| } |
| |
| } |
| |