langtools/src/jdk.compiler/share/classes/com/sun/tools/classfile/ConstantPool.java
changeset 30848 c275389a3680
parent 30842 b02fa8bb730c
parent 30847 9385b9c8506b
child 30849 fcfa8eb95c23
equal deleted inserted replaced
30842:b02fa8bb730c 30848:c275389a3680
     1 /*
       
     2  * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.tools.classfile;
       
    27 
       
    28 import java.io.DataOutputStream;
       
    29 import java.io.IOException;
       
    30 import java.io.OutputStream;
       
    31 import java.util.Iterator;
       
    32 
       
    33 /**
       
    34  * See JVMS, section 4.5.
       
    35  *
       
    36  *  <p><b>This is NOT part of any supported API.
       
    37  *  If you write code that depends on this, you do so at your own risk.
       
    38  *  This code and its internal interfaces are subject to change or
       
    39  *  deletion without notice.</b>
       
    40  */
       
    41 public class ConstantPool {
       
    42 
       
    43     public static class InvalidIndex extends ConstantPoolException {
       
    44         private static final long serialVersionUID = -4350294289300939730L;
       
    45         InvalidIndex(int index) {
       
    46             super(index);
       
    47         }
       
    48 
       
    49         @Override
       
    50         public String getMessage() {
       
    51             // i18n
       
    52             return "invalid index #" + index;
       
    53         }
       
    54     }
       
    55 
       
    56     public static class UnexpectedEntry extends ConstantPoolException {
       
    57         private static final long serialVersionUID = 6986335935377933211L;
       
    58         UnexpectedEntry(int index, int expected_tag, int found_tag) {
       
    59             super(index);
       
    60             this.expected_tag = expected_tag;
       
    61             this.found_tag = found_tag;
       
    62         }
       
    63 
       
    64         @Override
       
    65         public String getMessage() {
       
    66             // i18n?
       
    67             return "unexpected entry at #" + index + " -- expected tag " + expected_tag + ", found " + found_tag;
       
    68         }
       
    69 
       
    70         public final int expected_tag;
       
    71         public final int found_tag;
       
    72     }
       
    73 
       
    74     public static class InvalidEntry extends ConstantPoolException {
       
    75         private static final long serialVersionUID = 1000087545585204447L;
       
    76         InvalidEntry(int index, int tag) {
       
    77             super(index);
       
    78             this.tag = tag;
       
    79         }
       
    80 
       
    81         @Override
       
    82         public String getMessage() {
       
    83             // i18n?
       
    84             return "unexpected tag at #" + index + ": " + tag;
       
    85         }
       
    86 
       
    87         public final int tag;
       
    88     }
       
    89 
       
    90     public static class EntryNotFound extends ConstantPoolException {
       
    91         private static final long serialVersionUID = 2885537606468581850L;
       
    92         EntryNotFound(Object value) {
       
    93             super(-1);
       
    94             this.value = value;
       
    95         }
       
    96 
       
    97         @Override
       
    98         public String getMessage() {
       
    99             // i18n?
       
   100             return "value not found: " + value;
       
   101         }
       
   102 
       
   103         public final Object value;
       
   104     }
       
   105 
       
   106     public static final int CONSTANT_Utf8 = 1;
       
   107     public static final int CONSTANT_Integer = 3;
       
   108     public static final int CONSTANT_Float = 4;
       
   109     public static final int CONSTANT_Long = 5;
       
   110     public static final int CONSTANT_Double = 6;
       
   111     public static final int CONSTANT_Class = 7;
       
   112     public static final int CONSTANT_String = 8;
       
   113     public static final int CONSTANT_Fieldref = 9;
       
   114     public static final int CONSTANT_Methodref = 10;
       
   115     public static final int CONSTANT_InterfaceMethodref = 11;
       
   116     public static final int CONSTANT_NameAndType = 12;
       
   117     public static final int CONSTANT_MethodHandle = 15;
       
   118     public static final int CONSTANT_MethodType = 16;
       
   119     public static final int CONSTANT_InvokeDynamic = 18;
       
   120 
       
   121     public static enum RefKind {
       
   122         REF_getField(1, "getfield"),
       
   123         REF_getStatic(2, "getstatic"),
       
   124         REF_putField(3, "putfield"),
       
   125         REF_putStatic(4, "putstatic"),
       
   126         REF_invokeVirtual(5, "invokevirtual"),
       
   127         REF_invokeStatic(6, "invokestatic"),
       
   128         REF_invokeSpecial(7, "invokespecial"),
       
   129         REF_newInvokeSpecial(8, "newinvokespecial"),
       
   130         REF_invokeInterface(9, "invokeinterface");
       
   131 
       
   132         public final int tag;
       
   133         public final String name;
       
   134 
       
   135         RefKind(int tag, String name) {
       
   136             this.tag = tag;
       
   137             this.name = name;
       
   138         }
       
   139 
       
   140         static RefKind getRefkind(int tag) {
       
   141             switch(tag) {
       
   142                 case 1:
       
   143                     return REF_getField;
       
   144                 case 2:
       
   145                     return REF_getStatic;
       
   146                 case 3:
       
   147                     return REF_putField;
       
   148                 case 4:
       
   149                     return REF_putStatic;
       
   150                 case 5:
       
   151                     return REF_invokeVirtual;
       
   152                 case 6:
       
   153                     return REF_invokeStatic;
       
   154                 case 7:
       
   155                     return REF_invokeSpecial;
       
   156                 case 8:
       
   157                     return REF_newInvokeSpecial;
       
   158                 case 9:
       
   159                     return REF_invokeInterface;
       
   160                 default:
       
   161                     return null;
       
   162             }
       
   163         }
       
   164     }
       
   165 
       
   166     ConstantPool(ClassReader cr) throws IOException, InvalidEntry {
       
   167         int count = cr.readUnsignedShort();
       
   168         pool = new CPInfo[count];
       
   169         for (int i = 1; i < count; i++) {
       
   170             int tag = cr.readUnsignedByte();
       
   171             switch (tag) {
       
   172             case CONSTANT_Class:
       
   173                 pool[i] = new CONSTANT_Class_info(this, cr);
       
   174                 break;
       
   175 
       
   176             case CONSTANT_Double:
       
   177                 pool[i] = new CONSTANT_Double_info(cr);
       
   178                 i++;
       
   179                 break;
       
   180 
       
   181             case CONSTANT_Fieldref:
       
   182                 pool[i] = new CONSTANT_Fieldref_info(this, cr);
       
   183                 break;
       
   184 
       
   185             case CONSTANT_Float:
       
   186                 pool[i] = new CONSTANT_Float_info(cr);
       
   187                 break;
       
   188 
       
   189             case CONSTANT_Integer:
       
   190                 pool[i] = new CONSTANT_Integer_info(cr);
       
   191                 break;
       
   192 
       
   193             case CONSTANT_InterfaceMethodref:
       
   194                 pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr);
       
   195                 break;
       
   196 
       
   197             case CONSTANT_InvokeDynamic:
       
   198                 pool[i] = new CONSTANT_InvokeDynamic_info(this, cr);
       
   199                 break;
       
   200 
       
   201             case CONSTANT_Long:
       
   202                 pool[i] = new CONSTANT_Long_info(cr);
       
   203                 i++;
       
   204                 break;
       
   205 
       
   206             case CONSTANT_MethodHandle:
       
   207                 pool[i] = new CONSTANT_MethodHandle_info(this, cr);
       
   208                 break;
       
   209 
       
   210             case CONSTANT_MethodType:
       
   211                 pool[i] = new CONSTANT_MethodType_info(this, cr);
       
   212                 break;
       
   213 
       
   214             case CONSTANT_Methodref:
       
   215                 pool[i] = new CONSTANT_Methodref_info(this, cr);
       
   216                 break;
       
   217 
       
   218             case CONSTANT_NameAndType:
       
   219                 pool[i] = new CONSTANT_NameAndType_info(this, cr);
       
   220                 break;
       
   221 
       
   222             case CONSTANT_String:
       
   223                 pool[i] = new CONSTANT_String_info(this, cr);
       
   224                 break;
       
   225 
       
   226             case CONSTANT_Utf8:
       
   227                 pool[i] = new CONSTANT_Utf8_info(cr);
       
   228                 break;
       
   229 
       
   230             default:
       
   231                 throw new InvalidEntry(i, tag);
       
   232             }
       
   233         }
       
   234     }
       
   235 
       
   236     public ConstantPool(CPInfo[] pool) {
       
   237         this.pool = pool;
       
   238     }
       
   239 
       
   240     public int size() {
       
   241         return pool.length;
       
   242     }
       
   243 
       
   244     public int byteLength() {
       
   245         int length = 2;
       
   246         for (int i = 1; i < size(); ) {
       
   247             CPInfo cpInfo = pool[i];
       
   248             length += cpInfo.byteLength();
       
   249             i += cpInfo.size();
       
   250         }
       
   251         return length;
       
   252     }
       
   253 
       
   254     public CPInfo get(int index) throws InvalidIndex {
       
   255         if (index <= 0 || index >= pool.length)
       
   256             throw new InvalidIndex(index);
       
   257         CPInfo info = pool[index];
       
   258         if (info == null) {
       
   259             // this occurs for indices referencing the "second half" of an
       
   260             // 8 byte constant, such as CONSTANT_Double or CONSTANT_Long
       
   261             throw new InvalidIndex(index);
       
   262         }
       
   263         return pool[index];
       
   264     }
       
   265 
       
   266     private CPInfo get(int index, int expected_type) throws InvalidIndex, UnexpectedEntry {
       
   267         CPInfo info = get(index);
       
   268         if (info.getTag() != expected_type)
       
   269             throw new UnexpectedEntry(index, expected_type, info.getTag());
       
   270         return info;
       
   271     }
       
   272 
       
   273     public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry {
       
   274         return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8));
       
   275     }
       
   276 
       
   277     public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry {
       
   278         return ((CONSTANT_Class_info) get(index, CONSTANT_Class));
       
   279     }
       
   280 
       
   281     public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry {
       
   282         return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType));
       
   283     }
       
   284 
       
   285     public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry {
       
   286         return getUTF8Info(index).value;
       
   287     }
       
   288 
       
   289     public int getUTF8Index(String value) throws EntryNotFound {
       
   290         for (int i = 1; i < pool.length; i++) {
       
   291             CPInfo info = pool[i];
       
   292             if (info instanceof CONSTANT_Utf8_info &&
       
   293                     ((CONSTANT_Utf8_info) info).value.equals(value))
       
   294                 return i;
       
   295         }
       
   296         throw new EntryNotFound(value);
       
   297     }
       
   298 
       
   299     public Iterable<CPInfo> entries() {
       
   300         return new Iterable<CPInfo>() {
       
   301             public Iterator<CPInfo> iterator() {
       
   302                 return new Iterator<CPInfo>() {
       
   303 
       
   304                     public boolean hasNext() {
       
   305                         return next < pool.length;
       
   306                     }
       
   307 
       
   308                     public CPInfo next() {
       
   309                         current = pool[next];
       
   310                         switch (current.getTag()) {
       
   311                             case CONSTANT_Double:
       
   312                             case CONSTANT_Long:
       
   313                                 next += 2;
       
   314                                 break;
       
   315                             default:
       
   316                                 next += 1;
       
   317                         }
       
   318                         return current;
       
   319                     }
       
   320 
       
   321                     public void remove() {
       
   322                         throw new UnsupportedOperationException();
       
   323                     }
       
   324 
       
   325                     private CPInfo current;
       
   326                     private int next = 1;
       
   327 
       
   328                 };
       
   329             }
       
   330         };
       
   331     }
       
   332 
       
   333     private CPInfo[] pool;
       
   334 
       
   335     public interface Visitor<R,P> {
       
   336         R visitClass(CONSTANT_Class_info info, P p);
       
   337         R visitDouble(CONSTANT_Double_info info, P p);
       
   338         R visitFieldref(CONSTANT_Fieldref_info info, P p);
       
   339         R visitFloat(CONSTANT_Float_info info, P p);
       
   340         R visitInteger(CONSTANT_Integer_info info, P p);
       
   341         R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p);
       
   342         R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p);
       
   343         R visitLong(CONSTANT_Long_info info, P p);
       
   344         R visitNameAndType(CONSTANT_NameAndType_info info, P p);
       
   345         R visitMethodref(CONSTANT_Methodref_info info, P p);
       
   346         R visitMethodHandle(CONSTANT_MethodHandle_info info, P p);
       
   347         R visitMethodType(CONSTANT_MethodType_info info, P p);
       
   348         R visitString(CONSTANT_String_info info, P p);
       
   349         R visitUtf8(CONSTANT_Utf8_info info, P p);
       
   350     }
       
   351 
       
   352     public static abstract class CPInfo {
       
   353         CPInfo() {
       
   354             this.cp = null;
       
   355         }
       
   356 
       
   357         CPInfo(ConstantPool cp) {
       
   358             this.cp = cp;
       
   359         }
       
   360 
       
   361         public abstract int getTag();
       
   362 
       
   363         /** The number of slots in the constant pool used by this entry.
       
   364          * 2 for CONSTANT_Double and CONSTANT_Long; 1 for everything else. */
       
   365         public int size() {
       
   366             return 1;
       
   367         }
       
   368 
       
   369         public abstract int byteLength();
       
   370 
       
   371         public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
       
   372 
       
   373         protected final ConstantPool cp;
       
   374     }
       
   375 
       
   376     public static abstract class CPRefInfo extends CPInfo {
       
   377         protected CPRefInfo(ConstantPool cp, ClassReader cr, int tag) throws IOException {
       
   378             super(cp);
       
   379             this.tag = tag;
       
   380             class_index = cr.readUnsignedShort();
       
   381             name_and_type_index = cr.readUnsignedShort();
       
   382         }
       
   383 
       
   384         protected CPRefInfo(ConstantPool cp, int tag, int class_index, int name_and_type_index) {
       
   385             super(cp);
       
   386             this.tag = tag;
       
   387             this.class_index = class_index;
       
   388             this.name_and_type_index = name_and_type_index;
       
   389         }
       
   390 
       
   391         public int getTag() {
       
   392             return tag;
       
   393         }
       
   394 
       
   395         public int byteLength() {
       
   396             return 5;
       
   397         }
       
   398 
       
   399         public CONSTANT_Class_info getClassInfo() throws ConstantPoolException {
       
   400             return cp.getClassInfo(class_index);
       
   401         }
       
   402 
       
   403         public String getClassName() throws ConstantPoolException {
       
   404             return cp.getClassInfo(class_index).getName();
       
   405         }
       
   406 
       
   407         public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
       
   408             return cp.getNameAndTypeInfo(name_and_type_index);
       
   409         }
       
   410 
       
   411         public final int tag;
       
   412         public final int class_index;
       
   413         public final int name_and_type_index;
       
   414     }
       
   415 
       
   416     public static class CONSTANT_Class_info extends CPInfo {
       
   417         CONSTANT_Class_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   418             super(cp);
       
   419             name_index = cr.readUnsignedShort();
       
   420         }
       
   421 
       
   422         public CONSTANT_Class_info(ConstantPool cp, int name_index) {
       
   423             super(cp);
       
   424             this.name_index = name_index;
       
   425         }
       
   426 
       
   427         public int getTag() {
       
   428             return CONSTANT_Class;
       
   429         }
       
   430 
       
   431         public int  byteLength() {
       
   432             return 3;
       
   433         }
       
   434 
       
   435         /**
       
   436          * Get the raw value of the class referenced by this constant pool entry.
       
   437          * This will either be the name of the class, in internal form, or a
       
   438          * descriptor for an array class.
       
   439          * @return the raw value of the class
       
   440          */
       
   441         public String getName() throws ConstantPoolException {
       
   442             return cp.getUTF8Value(name_index);
       
   443         }
       
   444 
       
   445         /**
       
   446          * If this constant pool entry identifies either a class or interface type,
       
   447          * or a possibly multi-dimensional array of a class of interface type,
       
   448          * return the name of the class or interface in internal form. Otherwise,
       
   449          * (i.e. if this is a possibly multi-dimensional array of a primitive type),
       
   450          * return null.
       
   451          * @return the base class or interface name
       
   452          */
       
   453         public String getBaseName() throws ConstantPoolException {
       
   454             String name = getName();
       
   455             if (name.startsWith("[")) {
       
   456                 int index = name.indexOf("[L");
       
   457                 if (index == -1)
       
   458                     return null;
       
   459                 return name.substring(index + 2, name.length() - 1);
       
   460             } else
       
   461                 return name;
       
   462         }
       
   463 
       
   464         public int getDimensionCount() throws ConstantPoolException {
       
   465             String name = getName();
       
   466             int count = 0;
       
   467             while (name.charAt(count) == '[')
       
   468                 count++;
       
   469             return count;
       
   470         }
       
   471 
       
   472         @Override
       
   473         public String toString() {
       
   474             return "CONSTANT_Class_info[name_index: " + name_index + "]";
       
   475         }
       
   476 
       
   477         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   478             return visitor.visitClass(this, data);
       
   479         }
       
   480 
       
   481         public final int name_index;
       
   482     }
       
   483 
       
   484     public static class CONSTANT_Double_info extends CPInfo {
       
   485         CONSTANT_Double_info(ClassReader cr) throws IOException {
       
   486             value = cr.readDouble();
       
   487         }
       
   488 
       
   489         public CONSTANT_Double_info(double value) {
       
   490             this.value = value;
       
   491         }
       
   492 
       
   493         public int getTag() {
       
   494             return CONSTANT_Double;
       
   495         }
       
   496 
       
   497         public int  byteLength() {
       
   498             return 9;
       
   499         }
       
   500 
       
   501         @Override
       
   502         public int size() {
       
   503             return 2;
       
   504         }
       
   505 
       
   506         @Override
       
   507         public String toString() {
       
   508             return "CONSTANT_Double_info[value: " + value + "]";
       
   509         }
       
   510 
       
   511         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   512             return visitor.visitDouble(this, data);
       
   513         }
       
   514 
       
   515         public final double value;
       
   516     }
       
   517 
       
   518     public static class CONSTANT_Fieldref_info extends CPRefInfo {
       
   519         CONSTANT_Fieldref_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   520             super(cp, cr, CONSTANT_Fieldref);
       
   521         }
       
   522 
       
   523         public CONSTANT_Fieldref_info(ConstantPool cp, int class_index, int name_and_type_index) {
       
   524             super(cp, CONSTANT_Fieldref, class_index, name_and_type_index);
       
   525         }
       
   526 
       
   527         @Override
       
   528         public String toString() {
       
   529             return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
       
   530         }
       
   531 
       
   532         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   533             return visitor.visitFieldref(this, data);
       
   534         }
       
   535     }
       
   536 
       
   537     public static class CONSTANT_Float_info extends CPInfo {
       
   538         CONSTANT_Float_info(ClassReader cr) throws IOException {
       
   539             value = cr.readFloat();
       
   540         }
       
   541 
       
   542         public CONSTANT_Float_info(float value) {
       
   543             this.value = value;
       
   544         }
       
   545 
       
   546         public int getTag() {
       
   547             return CONSTANT_Float;
       
   548         }
       
   549 
       
   550         public int byteLength() {
       
   551             return 5;
       
   552         }
       
   553 
       
   554         @Override
       
   555         public String toString() {
       
   556             return "CONSTANT_Float_info[value: " + value + "]";
       
   557         }
       
   558 
       
   559         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   560             return visitor.visitFloat(this, data);
       
   561         }
       
   562 
       
   563         public final float value;
       
   564     }
       
   565 
       
   566     public static class CONSTANT_Integer_info extends CPInfo {
       
   567         CONSTANT_Integer_info(ClassReader cr) throws IOException {
       
   568             value = cr.readInt();
       
   569         }
       
   570 
       
   571         public CONSTANT_Integer_info(int value) {
       
   572             this.value = value;
       
   573         }
       
   574 
       
   575         public int getTag() {
       
   576             return CONSTANT_Integer;
       
   577         }
       
   578 
       
   579         public int byteLength() {
       
   580             return 5;
       
   581         }
       
   582 
       
   583         @Override
       
   584         public String toString() {
       
   585             return "CONSTANT_Integer_info[value: " + value + "]";
       
   586         }
       
   587 
       
   588         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   589             return visitor.visitInteger(this, data);
       
   590         }
       
   591 
       
   592         public final int value;
       
   593     }
       
   594 
       
   595     public static class CONSTANT_InterfaceMethodref_info extends CPRefInfo {
       
   596         CONSTANT_InterfaceMethodref_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   597             super(cp, cr, CONSTANT_InterfaceMethodref);
       
   598         }
       
   599 
       
   600         public CONSTANT_InterfaceMethodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
       
   601             super(cp, CONSTANT_InterfaceMethodref, class_index, name_and_type_index);
       
   602         }
       
   603 
       
   604         @Override
       
   605         public String toString() {
       
   606             return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
       
   607         }
       
   608 
       
   609         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   610             return visitor.visitInterfaceMethodref(this, data);
       
   611         }
       
   612     }
       
   613 
       
   614     public static class CONSTANT_InvokeDynamic_info extends CPInfo {
       
   615         CONSTANT_InvokeDynamic_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   616             super(cp);
       
   617             bootstrap_method_attr_index = cr.readUnsignedShort();
       
   618             name_and_type_index = cr.readUnsignedShort();
       
   619         }
       
   620 
       
   621         public CONSTANT_InvokeDynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) {
       
   622             super(cp);
       
   623             this.bootstrap_method_attr_index = bootstrap_method_index;
       
   624             this.name_and_type_index = name_and_type_index;
       
   625         }
       
   626 
       
   627         public int getTag() {
       
   628             return CONSTANT_InvokeDynamic;
       
   629         }
       
   630 
       
   631         public int byteLength() {
       
   632             return 5;
       
   633         }
       
   634 
       
   635         @Override
       
   636         public String toString() {
       
   637             return "CONSTANT_InvokeDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]";
       
   638         }
       
   639 
       
   640         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   641             return visitor.visitInvokeDynamic(this, data);
       
   642         }
       
   643 
       
   644         public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
       
   645             return cp.getNameAndTypeInfo(name_and_type_index);
       
   646         }
       
   647 
       
   648         public final int bootstrap_method_attr_index;
       
   649         public final int name_and_type_index;
       
   650     }
       
   651 
       
   652     public static class CONSTANT_Long_info extends CPInfo {
       
   653         CONSTANT_Long_info(ClassReader cr) throws IOException {
       
   654             value = cr.readLong();
       
   655         }
       
   656 
       
   657         public CONSTANT_Long_info(long value) {
       
   658             this.value = value;
       
   659         }
       
   660 
       
   661         public int getTag() {
       
   662             return CONSTANT_Long;
       
   663         }
       
   664 
       
   665         @Override
       
   666         public int size() {
       
   667             return 2;
       
   668         }
       
   669 
       
   670         public int byteLength() {
       
   671             return 9;
       
   672         }
       
   673 
       
   674         @Override
       
   675         public String toString() {
       
   676             return "CONSTANT_Long_info[value: " + value + "]";
       
   677         }
       
   678 
       
   679         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   680             return visitor.visitLong(this, data);
       
   681         }
       
   682 
       
   683         public final long value;
       
   684     }
       
   685 
       
   686     public static class CONSTANT_MethodHandle_info extends CPInfo {
       
   687         CONSTANT_MethodHandle_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   688             super(cp);
       
   689             reference_kind =  RefKind.getRefkind(cr.readUnsignedByte());
       
   690             reference_index = cr.readUnsignedShort();
       
   691         }
       
   692 
       
   693         public CONSTANT_MethodHandle_info(ConstantPool cp, RefKind ref_kind, int member_index) {
       
   694             super(cp);
       
   695             this.reference_kind = ref_kind;
       
   696             this.reference_index = member_index;
       
   697         }
       
   698 
       
   699         public int getTag() {
       
   700             return CONSTANT_MethodHandle;
       
   701         }
       
   702 
       
   703         public int byteLength() {
       
   704             return 4;
       
   705         }
       
   706 
       
   707         @Override
       
   708         public String toString() {
       
   709             return "CONSTANT_MethodHandle_info[ref_kind: " + reference_kind + ", member_index: " + reference_index + "]";
       
   710         }
       
   711 
       
   712         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   713             return visitor.visitMethodHandle(this, data);
       
   714         }
       
   715 
       
   716         public CPRefInfo getCPRefInfo() throws ConstantPoolException {
       
   717             int expected = CONSTANT_Methodref;
       
   718             int actual = cp.get(reference_index).getTag();
       
   719             // allow these tag types also:
       
   720             switch (actual) {
       
   721                 case CONSTANT_Fieldref:
       
   722                 case CONSTANT_InterfaceMethodref:
       
   723                     expected = actual;
       
   724             }
       
   725             return (CPRefInfo) cp.get(reference_index, expected);
       
   726         }
       
   727 
       
   728         public final RefKind reference_kind;
       
   729         public final int reference_index;
       
   730     }
       
   731 
       
   732     public static class CONSTANT_MethodType_info extends CPInfo {
       
   733         CONSTANT_MethodType_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   734             super(cp);
       
   735             descriptor_index = cr.readUnsignedShort();
       
   736         }
       
   737 
       
   738         public CONSTANT_MethodType_info(ConstantPool cp, int signature_index) {
       
   739             super(cp);
       
   740             this.descriptor_index = signature_index;
       
   741         }
       
   742 
       
   743         public int getTag() {
       
   744             return CONSTANT_MethodType;
       
   745         }
       
   746 
       
   747         public int byteLength() {
       
   748             return 3;
       
   749         }
       
   750 
       
   751         @Override
       
   752         public String toString() {
       
   753             return "CONSTANT_MethodType_info[signature_index: " + descriptor_index + "]";
       
   754         }
       
   755 
       
   756         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   757             return visitor.visitMethodType(this, data);
       
   758         }
       
   759 
       
   760         public String getType() throws ConstantPoolException {
       
   761             return cp.getUTF8Value(descriptor_index);
       
   762         }
       
   763 
       
   764         public final int descriptor_index;
       
   765     }
       
   766 
       
   767     public static class CONSTANT_Methodref_info extends CPRefInfo {
       
   768         CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   769             super(cp, cr, CONSTANT_Methodref);
       
   770         }
       
   771 
       
   772         public CONSTANT_Methodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
       
   773             super(cp, CONSTANT_Methodref, class_index, name_and_type_index);
       
   774         }
       
   775 
       
   776         @Override
       
   777         public String toString() {
       
   778             return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
       
   779         }
       
   780 
       
   781         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   782             return visitor.visitMethodref(this, data);
       
   783         }
       
   784     }
       
   785 
       
   786     public static class CONSTANT_NameAndType_info extends CPInfo {
       
   787         CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   788             super(cp);
       
   789             name_index = cr.readUnsignedShort();
       
   790             type_index = cr.readUnsignedShort();
       
   791         }
       
   792 
       
   793         public CONSTANT_NameAndType_info(ConstantPool cp, int name_index, int type_index) {
       
   794             super(cp);
       
   795             this.name_index = name_index;
       
   796             this.type_index = type_index;
       
   797         }
       
   798 
       
   799         public int getTag() {
       
   800             return CONSTANT_NameAndType;
       
   801         }
       
   802 
       
   803         public int byteLength() {
       
   804             return 5;
       
   805         }
       
   806 
       
   807         public String getName() throws ConstantPoolException {
       
   808             return cp.getUTF8Value(name_index);
       
   809         }
       
   810 
       
   811         public String getType() throws ConstantPoolException {
       
   812             return cp.getUTF8Value(type_index);
       
   813         }
       
   814 
       
   815         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   816             return visitor.visitNameAndType(this, data);
       
   817         }
       
   818 
       
   819         @Override
       
   820         public String toString() {
       
   821             return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]";
       
   822         }
       
   823 
       
   824         public final int name_index;
       
   825         public final int type_index;
       
   826     }
       
   827 
       
   828     public static class CONSTANT_String_info extends CPInfo {
       
   829         CONSTANT_String_info(ConstantPool cp, ClassReader cr) throws IOException {
       
   830             super(cp);
       
   831             string_index = cr.readUnsignedShort();
       
   832         }
       
   833 
       
   834         public CONSTANT_String_info(ConstantPool cp, int string_index) {
       
   835             super(cp);
       
   836             this.string_index = string_index;
       
   837         }
       
   838 
       
   839         public int getTag() {
       
   840             return CONSTANT_String;
       
   841         }
       
   842 
       
   843         public int byteLength() {
       
   844             return 3;
       
   845         }
       
   846 
       
   847         public String getString() throws ConstantPoolException {
       
   848             return cp.getUTF8Value(string_index);
       
   849         }
       
   850 
       
   851         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   852             return visitor.visitString(this, data);
       
   853         }
       
   854 
       
   855         @Override
       
   856         public String toString() {
       
   857             return "CONSTANT_String_info[class_index: " + string_index + "]";
       
   858         }
       
   859 
       
   860         public final int string_index;
       
   861     }
       
   862 
       
   863     public static class CONSTANT_Utf8_info extends CPInfo {
       
   864         CONSTANT_Utf8_info(ClassReader cr) throws IOException {
       
   865             value = cr.readUTF();
       
   866         }
       
   867 
       
   868         public CONSTANT_Utf8_info(String value) {
       
   869             this.value = value;
       
   870         }
       
   871 
       
   872         public int getTag() {
       
   873             return CONSTANT_Utf8;
       
   874         }
       
   875 
       
   876         public int byteLength() {
       
   877             class SizeOutputStream extends OutputStream {
       
   878                 @Override
       
   879                 public void write(int b) {
       
   880                     size++;
       
   881                 }
       
   882                 int size;
       
   883             }
       
   884             SizeOutputStream sizeOut = new SizeOutputStream();
       
   885             DataOutputStream out = new DataOutputStream(sizeOut);
       
   886             try { out.writeUTF(value); } catch (IOException ignore) { }
       
   887             return 1 + sizeOut.size;
       
   888         }
       
   889 
       
   890         @Override
       
   891         public String toString() {
       
   892             if (value.length() < 32 && isPrintableAscii(value))
       
   893                 return "CONSTANT_Utf8_info[value: \"" + value + "\"]";
       
   894             else
       
   895                 return "CONSTANT_Utf8_info[value: (" + value.length() + " chars)]";
       
   896         }
       
   897 
       
   898         static boolean isPrintableAscii(String s) {
       
   899             for (int i = 0; i < s.length(); i++) {
       
   900                 char c = s.charAt(i);
       
   901                 if (c < 32 || c >= 127)
       
   902                     return false;
       
   903             }
       
   904             return true;
       
   905         }
       
   906 
       
   907         public <R, D> R accept(Visitor<R, D> visitor, D data) {
       
   908             return visitor.visitUtf8(this, data);
       
   909         }
       
   910 
       
   911         public final String value;
       
   912     }
       
   913 
       
   914 }