jjg@46: /*
ksrini@826: * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
jjg@46: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@46: *
jjg@46: * This code is free software; you can redistribute it and/or modify it
jjg@46: * under the terms of the GNU General Public License version 2 only, as
ohair@554: * published by the Free Software Foundation. Oracle designates this
jjg@46: * particular file as subject to the "Classpath" exception as provided
ohair@554: * by Oracle in the LICENSE file that accompanied this code.
jjg@46: *
jjg@46: * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@46: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@46: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@46: * version 2 for more details (a copy is included in the LICENSE file that
jjg@46: * accompanied this code).
jjg@46: *
jjg@46: * You should have received a copy of the GNU General Public License version
jjg@46: * 2 along with this work; if not, write to the Free Software Foundation,
jjg@46: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@46: *
ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554: * or visit www.oracle.com if you need additional information or have any
ohair@554: * questions.
jjg@46: */
jjg@46:
jjg@46: package com.sun.tools.classfile;
jjg@46:
jjg@345: import java.io.DataOutputStream;
jjg@46: import java.io.IOException;
jjg@345: import java.io.OutputStream;
jjg@282: import java.util.Iterator;
jjg@46:
jjg@46: /**
jjh@972: * See JVMS, section 4.5.
jjg@46: *
jjg@581: *
This is NOT part of any supported API.
jjg@581: * If you write code that depends on this, you do so at your own risk.
jjg@46: * This code and its internal interfaces are subject to change or
jjg@46: * deletion without notice.
jjg@46: */
jjg@46: public class ConstantPool {
jjg@46:
jjg@513: public static class InvalidIndex extends ConstantPoolException {
jjg@198: private static final long serialVersionUID = -4350294289300939730L;
jjg@46: InvalidIndex(int index) {
jjg@46: super(index);
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String getMessage() {
jjg@46: // i18n
jjg@46: return "invalid index #" + index;
jjg@46: }
jjg@46: }
jjg@46:
jjg@513: public static class UnexpectedEntry extends ConstantPoolException {
jjg@198: private static final long serialVersionUID = 6986335935377933211L;
jjg@46: UnexpectedEntry(int index, int expected_tag, int found_tag) {
jjg@46: super(index);
jjg@46: this.expected_tag = expected_tag;
jjg@46: this.found_tag = found_tag;
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String getMessage() {
jjg@46: // i18n?
jjg@46: return "unexpected entry at #" + index + " -- expected tag " + expected_tag + ", found " + found_tag;
jjg@46: }
jjg@46:
jjg@46: public final int expected_tag;
jjg@46: public final int found_tag;
jjg@46: }
jjg@46:
jjg@513: public static class InvalidEntry extends ConstantPoolException {
jjg@198: private static final long serialVersionUID = 1000087545585204447L;
jjg@46: InvalidEntry(int index, int tag) {
jjg@46: super(index);
jjg@46: this.tag = tag;
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String getMessage() {
jjg@46: // i18n?
jjg@46: return "unexpected tag at #" + index + ": " + tag;
jjg@46: }
jjg@46:
jjg@46: public final int tag;
jjg@46: }
jjg@46:
jjg@513: public static class EntryNotFound extends ConstantPoolException {
jjg@198: private static final long serialVersionUID = 2885537606468581850L;
jjg@46: EntryNotFound(Object value) {
jjg@46: super(-1);
jjg@46: this.value = value;
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String getMessage() {
jjg@46: // i18n?
jjg@46: return "value not found: " + value;
jjg@46: }
jjg@46:
jjg@46: public final Object value;
jjg@46: }
jjg@46:
jjg@46: public static final int CONSTANT_Utf8 = 1;
jjg@46: public static final int CONSTANT_Integer = 3;
jjg@46: public static final int CONSTANT_Float = 4;
jjg@46: public static final int CONSTANT_Long = 5;
jjg@46: public static final int CONSTANT_Double = 6;
jjg@46: public static final int CONSTANT_Class = 7;
jjg@46: public static final int CONSTANT_String = 8;
jjg@46: public static final int CONSTANT_Fieldref = 9;
jjg@46: public static final int CONSTANT_Methodref = 10;
jjg@46: public static final int CONSTANT_InterfaceMethodref = 11;
jjg@46: public static final int CONSTANT_NameAndType = 12;
ksrini@826: public static final int CONSTANT_MethodHandle = 15;
ksrini@826: public static final int CONSTANT_MethodType = 16;
ksrini@826: public static final int CONSTANT_InvokeDynamic = 18;
ksrini@826:
ksrini@826: public static enum RefKind {
ksrini@826: REF_getField(1, "getfield"),
ksrini@826: REF_getStatic(2, "getstatic"),
ksrini@826: REF_putField(3, "putfield"),
ksrini@826: REF_putStatic(4, "putstatic"),
ksrini@826: REF_invokeVirtual(5, "invokevirtual"),
ksrini@826: REF_invokeStatic(6, "invokestatic"),
ksrini@826: REF_invokeSpecial(7, "invokespecial"),
ksrini@826: REF_newInvokeSpecial(8, "newinvokespecial"),
ksrini@826: REF_invokeInterface(9, "invokeinterface");
ksrini@826:
ksrini@826: public final int tag;
ksrini@826: public final String name;
ksrini@826:
ksrini@826: RefKind(int tag, String name) {
ksrini@826: this.tag = tag;
ksrini@826: this.name = name;
ksrini@826: }
ksrini@826:
ksrini@826: static RefKind getRefkind(int tag) {
ksrini@826: switch(tag) {
ksrini@826: case 1:
ksrini@826: return REF_getField;
ksrini@826: case 2:
ksrini@826: return REF_getStatic;
ksrini@826: case 3:
ksrini@826: return REF_putField;
ksrini@826: case 4:
ksrini@826: return REF_putStatic;
ksrini@826: case 5:
ksrini@826: return REF_invokeVirtual;
ksrini@826: case 6:
ksrini@826: return REF_invokeStatic;
ksrini@826: case 7:
ksrini@826: return REF_invokeSpecial;
ksrini@826: case 8:
ksrini@826: return REF_newInvokeSpecial;
ksrini@826: case 9:
ksrini@826: return REF_invokeInterface;
ksrini@826: default:
ksrini@826: return null;
ksrini@826: }
ksrini@826: }
ksrini@826: }
jjg@46:
jjg@46: ConstantPool(ClassReader cr) throws IOException, InvalidEntry {
jjg@46: int count = cr.readUnsignedShort();
jjg@46: pool = new CPInfo[count];
jjg@46: for (int i = 1; i < count; i++) {
jjg@46: int tag = cr.readUnsignedByte();
jjg@46: switch (tag) {
jjg@46: case CONSTANT_Class:
jjg@46: pool[i] = new CONSTANT_Class_info(this, cr);
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_Double:
jjg@46: pool[i] = new CONSTANT_Double_info(cr);
jjg@46: i++;
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_Fieldref:
jjg@46: pool[i] = new CONSTANT_Fieldref_info(this, cr);
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_Float:
jjg@46: pool[i] = new CONSTANT_Float_info(cr);
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_Integer:
jjg@46: pool[i] = new CONSTANT_Integer_info(cr);
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_InterfaceMethodref:
jjg@46: pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr);
jjg@46: break;
jjg@46:
ksrini@826: case CONSTANT_InvokeDynamic:
ksrini@826: pool[i] = new CONSTANT_InvokeDynamic_info(this, cr);
ksrini@826: break;
ksrini@826:
jjg@46: case CONSTANT_Long:
jjg@46: pool[i] = new CONSTANT_Long_info(cr);
jjg@46: i++;
jjg@46: break;
jjg@46:
ksrini@826: case CONSTANT_MethodHandle:
ksrini@826: pool[i] = new CONSTANT_MethodHandle_info(this, cr);
ksrini@826: break;
ksrini@826:
ksrini@826: case CONSTANT_MethodType:
ksrini@826: pool[i] = new CONSTANT_MethodType_info(this, cr);
ksrini@826: break;
ksrini@826:
jjg@46: case CONSTANT_Methodref:
jjg@46: pool[i] = new CONSTANT_Methodref_info(this, cr);
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_NameAndType:
jjg@46: pool[i] = new CONSTANT_NameAndType_info(this, cr);
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_String:
jjg@52: pool[i] = new CONSTANT_String_info(this, cr);
jjg@46: break;
jjg@46:
jjg@46: case CONSTANT_Utf8:
jjg@46: pool[i] = new CONSTANT_Utf8_info(cr);
jjg@46: break;
jjg@46:
jjg@46: default:
jjg@46: throw new InvalidEntry(i, tag);
jjg@46: }
jjg@46: }
jjg@46: }
jjg@46:
jjg@46: public ConstantPool(CPInfo[] pool) {
jjg@46: this.pool = pool;
jjg@46: }
jjg@46:
jjg@46: public int size() {
jjg@46: return pool.length;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: int length = 2;
jjg@345: for (int i = 1; i < size(); ) {
jjg@345: CPInfo cpInfo = pool[i];
jjg@345: length += cpInfo.byteLength();
jjg@345: i += cpInfo.size();
jjg@345: }
jjg@345: return length;
jjg@345: }
jjg@345:
jjg@46: public CPInfo get(int index) throws InvalidIndex {
jjg@46: if (index <= 0 || index >= pool.length)
jjg@46: throw new InvalidIndex(index);
jjg@46: CPInfo info = pool[index];
jjg@46: if (info == null) {
jjg@46: // this occurs for indices referencing the "second half" of an
jjg@46: // 8 byte constant, such as CONSTANT_Double or CONSTANT_Long
jjg@46: throw new InvalidIndex(index);
jjg@46: }
jjg@46: return pool[index];
jjg@46: }
jjg@46:
jjg@46: private CPInfo get(int index, int expected_type) throws InvalidIndex, UnexpectedEntry {
jjg@46: CPInfo info = get(index);
jjg@46: if (info.getTag() != expected_type)
jjg@46: throw new UnexpectedEntry(index, expected_type, info.getTag());
jjg@46: return info;
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry {
jjg@46: return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8));
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry {
jjg@46: return ((CONSTANT_Class_info) get(index, CONSTANT_Class));
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry {
jjg@46: return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType));
jjg@46: }
jjg@46:
jjg@46: public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry {
jjg@46: return getUTF8Info(index).value;
jjg@46: }
jjg@46:
jjg@46: public int getUTF8Index(String value) throws EntryNotFound {
jjg@46: for (int i = 1; i < pool.length; i++) {
jjg@46: CPInfo info = pool[i];
jjg@46: if (info instanceof CONSTANT_Utf8_info &&
jjg@46: ((CONSTANT_Utf8_info) info).value.equals(value))
jjg@46: return i;
jjg@46: }
jjg@46: throw new EntryNotFound(value);
jjg@46: }
jjg@46:
jjg@282: public Iterable entries() {
jjg@282: return new Iterable() {
jjg@282: public Iterator iterator() {
jjg@282: return new Iterator() {
jjg@282:
jjg@282: public boolean hasNext() {
jjg@282: return next < pool.length;
jjg@282: }
jjg@282:
jjg@282: public CPInfo next() {
jjg@282: current = pool[next];
jjg@282: switch (current.getTag()) {
jjg@282: case CONSTANT_Double:
jjg@282: case CONSTANT_Long:
jjg@282: next += 2;
jjg@282: break;
jjg@282: default:
jjg@282: next += 1;
jjg@282: }
jjg@282: return current;
jjg@282: }
jjg@282:
jjg@282: public void remove() {
jjg@282: throw new UnsupportedOperationException();
jjg@282: }
jjg@282:
jjg@282: private CPInfo current;
jjg@282: private int next = 1;
jjg@282:
jjg@282: };
jjg@282: }
jjg@282: };
jjg@282: }
jjg@282:
jjg@46: private CPInfo[] pool;
jjg@46:
jjg@46: public interface Visitor {
jjg@46: R visitClass(CONSTANT_Class_info info, P p);
jjg@46: R visitDouble(CONSTANT_Double_info info, P p);
jjg@46: R visitFieldref(CONSTANT_Fieldref_info info, P p);
jjg@46: R visitFloat(CONSTANT_Float_info info, P p);
jjg@46: R visitInteger(CONSTANT_Integer_info info, P p);
jjg@46: R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p);
ksrini@826: R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p);
jjg@46: R visitLong(CONSTANT_Long_info info, P p);
jjg@46: R visitNameAndType(CONSTANT_NameAndType_info info, P p);
jjg@46: R visitMethodref(CONSTANT_Methodref_info info, P p);
ksrini@826: R visitMethodHandle(CONSTANT_MethodHandle_info info, P p);
ksrini@826: R visitMethodType(CONSTANT_MethodType_info info, P p);
jjg@46: R visitString(CONSTANT_String_info info, P p);
jjg@46: R visitUtf8(CONSTANT_Utf8_info info, P p);
jjg@46: }
jjg@46:
jjg@46: public static abstract class CPInfo {
jjg@46: CPInfo() {
jjg@46: this.cp = null;
jjg@46: }
jjg@46:
jjg@46: CPInfo(ConstantPool cp) {
jjg@46: this.cp = cp;
jjg@46: }
jjg@46:
jjg@46: public abstract int getTag();
jjg@46:
jjg@282: /** The number of slots in the constant pool used by this entry.
jjg@282: * 2 for CONSTANT_Double and CONSTANT_Long; 1 for everything else. */
jjg@282: public int size() {
jjg@282: return 1;
jjg@282: }
jjg@282:
jjg@345: public abstract int byteLength();
jjg@345:
jjg@46: public abstract R accept(Visitor visitor, D data);
jjg@46:
jjg@46: protected final ConstantPool cp;
jjg@46: }
jjg@46:
jjg@46: public static abstract class CPRefInfo extends CPInfo {
jjg@46: protected CPRefInfo(ConstantPool cp, ClassReader cr, int tag) throws IOException {
jjg@46: super(cp);
jjg@46: this.tag = tag;
jjg@46: class_index = cr.readUnsignedShort();
jjg@46: name_and_type_index = cr.readUnsignedShort();
jjg@46: }
jjg@46:
jjg@46: protected CPRefInfo(ConstantPool cp, int tag, int class_index, int name_and_type_index) {
jjg@46: super(cp);
jjg@46: this.tag = tag;
jjg@46: this.class_index = class_index;
jjg@46: this.name_and_type_index = name_and_type_index;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return tag;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: return 5;
jjg@345: }
jjg@345:
jjg@46: public CONSTANT_Class_info getClassInfo() throws ConstantPoolException {
jjg@46: return cp.getClassInfo(class_index);
jjg@46: }
jjg@46:
jjg@46: public String getClassName() throws ConstantPoolException {
jjg@46: return cp.getClassInfo(class_index).getName();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
jjg@46: return cp.getNameAndTypeInfo(name_and_type_index);
jjg@46: }
jjg@46:
jjg@46: public final int tag;
jjg@46: public final int class_index;
jjg@46: public final int name_and_type_index;
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_Class_info extends CPInfo {
jjg@46: CONSTANT_Class_info(ConstantPool cp, ClassReader cr) throws IOException {
jjg@46: super(cp);
jjg@46: name_index = cr.readUnsignedShort();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Class_info(ConstantPool cp, int name_index) {
jjg@46: super(cp);
jjg@46: this.name_index = name_index;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_Class;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: return 3;
jjg@345: }
jjg@345:
jjg@422: /**
jjg@422: * Get the raw value of the class referenced by this constant pool entry.
jjg@422: * This will either be the name of the class, in internal form, or a
jjg@422: * descriptor for an array class.
jjg@422: * @return the raw value of the class
jjg@422: */
jjg@46: public String getName() throws ConstantPoolException {
jjg@46: return cp.getUTF8Value(name_index);
jjg@46: }
jjg@46:
jjg@422: /**
jjg@422: * If this constant pool entry identifies either a class or interface type,
jjg@422: * or a possibly multi-dimensional array of a class of interface type,
jjg@422: * return the name of the class or interface in internal form. Otherwise,
jjg@422: * (i.e. if this is a possibly multi-dimensional array of a primitive type),
jjg@422: * return null.
jjg@422: * @return the base class or interface name
jjg@422: */
jjg@281: public String getBaseName() throws ConstantPoolException {
jjg@281: String name = getName();
jjg@422: if (name.startsWith("[")) {
jjg@422: int index = name.indexOf("[L");
jjg@422: if (index == -1)
jjg@422: return null;
jjg@422: return name.substring(index + 2, name.length() - 1);
jjg@422: } else
jjg@422: return name;
jjg@281: }
jjg@281:
jjg@281: public int getDimensionCount() throws ConstantPoolException {
jjg@281: String name = getName();
jjg@281: int count = 0;
jjg@281: while (name.charAt(count) == '[')
jjg@281: count++;
jjg@281: return count;
jjg@281: }
jjg@281:
jjg@46: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_Class_info[name_index: " + name_index + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitClass(this, data);
jjg@46: }
jjg@46:
jjg@46: public final int name_index;
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_Double_info extends CPInfo {
jjg@46: CONSTANT_Double_info(ClassReader cr) throws IOException {
jjg@46: value = cr.readDouble();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Double_info(double value) {
jjg@46: this.value = value;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_Double;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: return 9;
jjg@345: }
jjg@345:
jjg@46: @Override
jjg@282: public int size() {
jjg@282: return 2;
jjg@282: }
jjg@282:
jjg@282: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_Double_info[value: " + value + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitDouble(this, data);
jjg@46: }
jjg@46:
jjg@46: public final double value;
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_Fieldref_info extends CPRefInfo {
jjg@46: CONSTANT_Fieldref_info(ConstantPool cp, ClassReader cr) throws IOException {
jjg@46: super(cp, cr, CONSTANT_Fieldref);
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Fieldref_info(ConstantPool cp, int class_index, int name_and_type_index) {
jjg@46: super(cp, CONSTANT_Fieldref, class_index, name_and_type_index);
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitFieldref(this, data);
jjg@46: }
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_Float_info extends CPInfo {
jjg@46: CONSTANT_Float_info(ClassReader cr) throws IOException {
jjg@46: value = cr.readFloat();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Float_info(float value) {
jjg@46: this.value = value;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_Float;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: return 5;
jjg@345: }
jjg@345:
jjg@46: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_Float_info[value: " + value + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitFloat(this, data);
jjg@46: }
jjg@46:
jjg@46: public final float value;
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_Integer_info extends CPInfo {
jjg@46: CONSTANT_Integer_info(ClassReader cr) throws IOException {
jjg@46: value = cr.readInt();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Integer_info(int value) {
jjg@46: this.value = value;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_Integer;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: return 5;
jjg@345: }
jjg@345:
jjg@46: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_Integer_info[value: " + value + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitInteger(this, data);
jjg@46: }
jjg@46:
jjg@46: public final int value;
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_InterfaceMethodref_info extends CPRefInfo {
jjg@46: CONSTANT_InterfaceMethodref_info(ConstantPool cp, ClassReader cr) throws IOException {
jjg@46: super(cp, cr, CONSTANT_InterfaceMethodref);
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_InterfaceMethodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
jjg@46: super(cp, CONSTANT_InterfaceMethodref, class_index, name_and_type_index);
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitInterfaceMethodref(this, data);
jjg@46: }
jjg@46: }
jjg@46:
ksrini@826: public static class CONSTANT_InvokeDynamic_info extends CPInfo {
ksrini@826: CONSTANT_InvokeDynamic_info(ConstantPool cp, ClassReader cr) throws IOException {
ksrini@826: super(cp);
ksrini@826: bootstrap_method_attr_index = cr.readUnsignedShort();
ksrini@826: name_and_type_index = cr.readUnsignedShort();
ksrini@826: }
ksrini@826:
ksrini@826: public CONSTANT_InvokeDynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) {
ksrini@826: super(cp);
ksrini@826: this.bootstrap_method_attr_index = bootstrap_method_index;
ksrini@826: this.name_and_type_index = name_and_type_index;
ksrini@826: }
ksrini@826:
ksrini@826: public int getTag() {
ksrini@826: return CONSTANT_InvokeDynamic;
ksrini@826: }
ksrini@826:
ksrini@826: public int byteLength() {
ksrini@826: return 5;
ksrini@826: }
ksrini@826:
ksrini@826: @Override
ksrini@826: public String toString() {
ksrini@826: return "CONSTANT_InvokeDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]";
ksrini@826: }
ksrini@826:
ksrini@826: public R accept(Visitor visitor, D data) {
ksrini@826: return visitor.visitInvokeDynamic(this, data);
ksrini@826: }
ksrini@826:
ksrini@826: public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
ksrini@826: return cp.getNameAndTypeInfo(name_and_type_index);
ksrini@826: }
ksrini@826:
ksrini@826: public final int bootstrap_method_attr_index;
ksrini@826: public final int name_and_type_index;
ksrini@826: }
ksrini@826:
jjg@46: public static class CONSTANT_Long_info extends CPInfo {
jjg@46: CONSTANT_Long_info(ClassReader cr) throws IOException {
jjg@46: value = cr.readLong();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Long_info(long value) {
jjg@46: this.value = value;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_Long;
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@282: public int size() {
jjg@282: return 2;
jjg@282: }
jjg@282:
jjg@345: public int byteLength() {
jjg@345: return 9;
jjg@345: }
jjg@345:
jjg@282: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_Long_info[value: " + value + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitLong(this, data);
jjg@46: }
jjg@46:
jjg@46: public final long value;
jjg@46: }
jjg@46:
ksrini@826: public static class CONSTANT_MethodHandle_info extends CPInfo {
ksrini@826: CONSTANT_MethodHandle_info(ConstantPool cp, ClassReader cr) throws IOException {
ksrini@826: super(cp);
ksrini@826: reference_kind = RefKind.getRefkind(cr.readUnsignedByte());
ksrini@826: reference_index = cr.readUnsignedShort();
ksrini@826: }
ksrini@826:
ksrini@826: public CONSTANT_MethodHandle_info(ConstantPool cp, RefKind ref_kind, int member_index) {
ksrini@826: super(cp);
ksrini@826: this.reference_kind = ref_kind;
ksrini@826: this.reference_index = member_index;
ksrini@826: }
ksrini@826:
ksrini@826: public int getTag() {
ksrini@826: return CONSTANT_MethodHandle;
ksrini@826: }
ksrini@826:
ksrini@826: public int byteLength() {
ksrini@826: return 4;
ksrini@826: }
ksrini@826:
ksrini@826: @Override
ksrini@826: public String toString() {
ksrini@826: return "CONSTANT_MethodHandle_info[ref_kind: " + reference_kind + ", member_index: " + reference_index + "]";
ksrini@826: }
ksrini@826:
ksrini@826: public R accept(Visitor visitor, D data) {
ksrini@826: return visitor.visitMethodHandle(this, data);
ksrini@826: }
ksrini@826:
ksrini@826: public CPRefInfo getCPRefInfo() throws ConstantPoolException {
ksrini@826: int expected = CONSTANT_Methodref;
ksrini@826: int actual = cp.get(reference_index).getTag();
ksrini@826: // allow these tag types also:
ksrini@826: switch (actual) {
ksrini@826: case CONSTANT_Fieldref:
ksrini@826: case CONSTANT_InterfaceMethodref:
ksrini@826: expected = actual;
ksrini@826: }
ksrini@826: return (CPRefInfo) cp.get(reference_index, expected);
ksrini@826: }
ksrini@826:
ksrini@826: public final RefKind reference_kind;
ksrini@826: public final int reference_index;
ksrini@826: }
ksrini@826:
ksrini@826: public static class CONSTANT_MethodType_info extends CPInfo {
ksrini@826: CONSTANT_MethodType_info(ConstantPool cp, ClassReader cr) throws IOException {
ksrini@826: super(cp);
ksrini@826: descriptor_index = cr.readUnsignedShort();
ksrini@826: }
ksrini@826:
ksrini@826: public CONSTANT_MethodType_info(ConstantPool cp, int signature_index) {
ksrini@826: super(cp);
ksrini@826: this.descriptor_index = signature_index;
ksrini@826: }
ksrini@826:
ksrini@826: public int getTag() {
ksrini@826: return CONSTANT_MethodType;
ksrini@826: }
ksrini@826:
ksrini@826: public int byteLength() {
ksrini@826: return 3;
ksrini@826: }
ksrini@826:
ksrini@826: @Override
ksrini@826: public String toString() {
ksrini@826: return "CONSTANT_MethodType_info[signature_index: " + descriptor_index + "]";
ksrini@826: }
ksrini@826:
ksrini@826: public R accept(Visitor visitor, D data) {
ksrini@826: return visitor.visitMethodType(this, data);
ksrini@826: }
ksrini@826:
ksrini@826: public String getType() throws ConstantPoolException {
ksrini@826: return cp.getUTF8Value(descriptor_index);
ksrini@826: }
ksrini@826:
ksrini@826: public final int descriptor_index;
ksrini@826: }
ksrini@826:
jjg@46: public static class CONSTANT_Methodref_info extends CPRefInfo {
jjg@46: CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException {
jjg@46: super(cp, cr, CONSTANT_Methodref);
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Methodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
jjg@46: super(cp, CONSTANT_Methodref, class_index, name_and_type_index);
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String toString() {
jjg@46: return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitMethodref(this, data);
jjg@46: }
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_NameAndType_info extends CPInfo {
jjg@46: CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException {
jjg@46: super(cp);
jjg@46: name_index = cr.readUnsignedShort();
jjg@46: type_index = cr.readUnsignedShort();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_NameAndType_info(ConstantPool cp, int name_index, int type_index) {
jjg@46: super(cp);
jjg@46: this.name_index = name_index;
jjg@46: this.type_index = type_index;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_NameAndType;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: return 5;
jjg@345: }
jjg@345:
jjg@46: public String getName() throws ConstantPoolException {
jjg@46: return cp.getUTF8Value(name_index);
jjg@46: }
jjg@46:
jjg@46: public String getType() throws ConstantPoolException {
jjg@46: return cp.getUTF8Value(type_index);
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitNameAndType(this, data);
jjg@46: }
jjg@46:
jjg@300: @Override
jjg@300: public String toString() {
jjg@300: return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]";
jjg@300: }
jjg@300:
jjg@46: public final int name_index;
jjg@46: public final int type_index;
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_String_info extends CPInfo {
jjg@52: CONSTANT_String_info(ConstantPool cp, ClassReader cr) throws IOException {
jjg@52: super(cp);
jjg@46: string_index = cr.readUnsignedShort();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_String_info(ConstantPool cp, int string_index) {
jjg@46: super(cp);
jjg@46: this.string_index = string_index;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_String;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: return 3;
jjg@345: }
jjg@345:
jjg@46: public String getString() throws ConstantPoolException {
jjg@46: return cp.getUTF8Value(string_index);
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitString(this, data);
jjg@46: }
jjg@46:
jjg@300: @Override
jjg@300: public String toString() {
jjg@300: return "CONSTANT_String_info[class_index: " + string_index + "]";
jjg@300: }
jjg@300:
jjg@46: public final int string_index;
jjg@46: }
jjg@46:
jjg@46: public static class CONSTANT_Utf8_info extends CPInfo {
jjg@46: CONSTANT_Utf8_info(ClassReader cr) throws IOException {
jjg@46: value = cr.readUTF();
jjg@46: }
jjg@46:
jjg@46: public CONSTANT_Utf8_info(String value) {
jjg@46: this.value = value;
jjg@46: }
jjg@46:
jjg@46: public int getTag() {
jjg@46: return CONSTANT_Utf8;
jjg@46: }
jjg@46:
jjg@345: public int byteLength() {
jjg@345: class SizeOutputStream extends OutputStream {
jjg@345: @Override
jjg@513: public void write(int b) {
jjg@345: size++;
jjg@345: }
jjg@345: int size;
jjg@345: }
jjg@345: SizeOutputStream sizeOut = new SizeOutputStream();
jjg@345: DataOutputStream out = new DataOutputStream(sizeOut);
jjg@345: try { out.writeUTF(value); } catch (IOException ignore) { }
jjg@345: return 1 + sizeOut.size;
jjg@345: }
jjg@345:
jjg@46: @Override
jjg@46: public String toString() {
jjg@300: if (value.length() < 32 && isPrintableAscii(value))
jjg@300: return "CONSTANT_Utf8_info[value: \"" + value + "\"]";
jjg@300: else
jjg@300: return "CONSTANT_Utf8_info[value: (" + value.length() + " chars)]";
jjg@300: }
jjg@300:
jjg@300: static boolean isPrintableAscii(String s) {
jjg@300: for (int i = 0; i < s.length(); i++) {
jjg@300: char c = s.charAt(i);
jjg@300: if (c < 32 || c >= 127)
jjg@300: return false;
jjg@300: }
jjg@300: return true;
jjg@46: }
jjg@46:
jjg@46: public R accept(Visitor visitor, D data) {
jjg@46: return visitor.visitUtf8(this, data);
jjg@46: }
jjg@46:
jjg@46: public final String value;
jjg@46: }
jjg@46:
jjg@46: }