javap/src/main/java/org/apidesign/javap/ClassData.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
parent 303 c12342170235
permissions -rw-r--r--
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
jtulach@144
     1
/*
jtulach@144
     2
 * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
jtulach@144
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jtulach@144
     4
 *
jtulach@144
     5
 * This code is free software; you can redistribute it and/or modify it
jtulach@144
     6
 * under the terms of the GNU General Public License version 2 only, as
jtulach@144
     7
 * published by the Free Software Foundation.  Oracle designates this
jtulach@144
     8
 * particular file as subject to the "Classpath" exception as provided
jtulach@144
     9
 * by Oracle in the LICENSE file that accompanied this code.
jtulach@144
    10
 *
jtulach@144
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
jtulach@144
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jtulach@144
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jtulach@144
    14
 * version 2 for more details (a copy is included in the LICENSE file that
jtulach@144
    15
 * accompanied this code).
jtulach@144
    16
 *
jtulach@144
    17
 * You should have received a copy of the GNU General Public License version
jtulach@144
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
jtulach@144
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jtulach@144
    20
 *
jtulach@144
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jtulach@144
    22
 * or visit www.oracle.com if you need additional information or have any
jtulach@144
    23
 * questions.
jtulach@144
    24
 */
jtulach@144
    25
jtulach@144
    26
jtulach@167
    27
package org.apidesign.javap;
jtulach@144
    28
jtulach@144
    29
import java.io.*;
jtulach@144
    30
jtulach@144
    31
/**
jtulach@144
    32
 * Central data repository of the Java Disassembler.
jtulach@144
    33
 * Stores all the information in java class file.
jtulach@144
    34
 *
jtulach@144
    35
 * @author  Sucheta Dambalkar (Adopted code from jdis)
jtulach@144
    36
 */
jaroslav@151
    37
public final class ClassData implements RuntimeConstants {
jtulach@144
    38
jtulach@144
    39
    private int magic;
jtulach@144
    40
    private int minor_version;
jtulach@144
    41
    private int major_version;
jtulach@144
    42
    private int cpool_count;
jtulach@144
    43
    private Object cpool[];
jtulach@144
    44
    private int access;
jtulach@144
    45
    private int this_class = 0;;
jtulach@144
    46
    private int super_class;
jtulach@144
    47
    private int interfaces_count;
jtulach@144
    48
    private int[] interfaces = new int[0];;
jtulach@144
    49
    private int fields_count;
jtulach@144
    50
    private FieldData[] fields;
jtulach@144
    51
    private int methods_count;
jtulach@144
    52
    private MethodData[] methods;
jtulach@144
    53
    private InnerClassData[] innerClasses;
jtulach@144
    54
    private int attributes_count;
jtulach@144
    55
    private AttrData[] attrs;
jtulach@144
    56
    private String classname;
jtulach@144
    57
    private String superclassname;
jtulach@144
    58
    private int source_cpx=0;
jtulach@144
    59
    private byte tags[];
jtulach@144
    60
    private Hashtable indexHashAscii = new Hashtable();
jtulach@144
    61
    private String pkgPrefix="";
jtulach@144
    62
    private int pkgPrefixLen=0;
jtulach@144
    63
jtulach@144
    64
    /**
jtulach@144
    65
     * Read classfile to disassemble.
jtulach@144
    66
     */
jaroslav@149
    67
    public ClassData(InputStream infile) throws IOException {
jaroslav@149
    68
        this.read(new DataInputStream(infile));
jtulach@144
    69
    }
jtulach@144
    70
jtulach@144
    71
    /**
jtulach@144
    72
     * Reads and stores class file information.
jtulach@144
    73
     */
jtulach@144
    74
    public void read(DataInputStream in) throws IOException {
jtulach@144
    75
        // Read the header
jtulach@144
    76
        magic = in.readInt();
jtulach@144
    77
        if (magic != JAVA_MAGIC) {
jtulach@144
    78
            throw new ClassFormatError("wrong magic: " +
jtulach@144
    79
                                       toHex(magic) + ", expected " +
jtulach@144
    80
                                       toHex(JAVA_MAGIC));
jtulach@144
    81
        }
jtulach@144
    82
        minor_version = in.readShort();
jtulach@144
    83
        major_version = in.readShort();
jtulach@144
    84
        if (major_version != JAVA_VERSION) {
jtulach@144
    85
        }
jtulach@144
    86
jtulach@144
    87
        // Read the constant pool
jtulach@144
    88
        readCP(in);
jtulach@144
    89
        access = in.readUnsignedShort();
jtulach@144
    90
        this_class = in.readUnsignedShort();
jtulach@144
    91
        super_class = in.readUnsignedShort();
jtulach@144
    92
jtulach@144
    93
        //Read interfaces.
jtulach@144
    94
        interfaces_count = in.readUnsignedShort();
jtulach@144
    95
        if(interfaces_count > 0){
jtulach@144
    96
            interfaces = new int[interfaces_count];
jtulach@144
    97
        }
jtulach@144
    98
        for (int i = 0; i < interfaces_count; i++) {
jtulach@144
    99
            interfaces[i]=in.readShort();
jtulach@144
   100
        }
jtulach@144
   101
jtulach@144
   102
        // Read the fields
jtulach@144
   103
        readFields(in);
jtulach@144
   104
jtulach@144
   105
        // Read the methods
jtulach@144
   106
        readMethods(in);
jtulach@144
   107
jtulach@144
   108
        // Read the attributes
jtulach@144
   109
        attributes_count = in.readUnsignedShort();
jtulach@144
   110
        attrs=new AttrData[attributes_count];
jtulach@144
   111
        for (int k = 0; k < attributes_count; k++) {
jtulach@144
   112
            int name_cpx=in.readUnsignedShort();
jtulach@144
   113
            if (getTag(name_cpx)==CONSTANT_UTF8
jtulach@144
   114
                && getString(name_cpx).equals("SourceFile")
jtulach@144
   115
                ){      if (in.readInt()!=2)
jtulach@144
   116
                    throw new ClassFormatError("invalid attr length");
jtulach@144
   117
                source_cpx=in.readUnsignedShort();
jtulach@144
   118
                AttrData attr=new AttrData(this);
jtulach@144
   119
                attr.read(name_cpx);
jtulach@144
   120
                attrs[k]=attr;
jtulach@144
   121
jtulach@144
   122
            } else if (getTag(name_cpx)==CONSTANT_UTF8
jtulach@144
   123
                       && getString(name_cpx).equals("InnerClasses")
jtulach@144
   124
                       ){       int length=in.readInt();
jtulach@144
   125
                       int num=in.readUnsignedShort();
jtulach@144
   126
                       if (2+num*8 != length)
jtulach@144
   127
                           throw new ClassFormatError("invalid attr length");
jtulach@144
   128
                       innerClasses=new InnerClassData[num];
jtulach@144
   129
                       for (int j = 0; j < num; j++) {
jtulach@144
   130
                           InnerClassData innerClass=new InnerClassData(this);
jtulach@144
   131
                           innerClass.read(in);
jtulach@144
   132
                           innerClasses[j]=innerClass;
jtulach@144
   133
                       }
jtulach@144
   134
                       AttrData attr=new AttrData(this);
jtulach@144
   135
                       attr.read(name_cpx);
jtulach@144
   136
                       attrs[k]=attr;
jtulach@144
   137
            } else {
jtulach@144
   138
                AttrData attr=new AttrData(this);
jtulach@144
   139
                attr.read(name_cpx, in);
jtulach@144
   140
                attrs[k]=attr;
jtulach@144
   141
            }
jtulach@144
   142
        }
jtulach@144
   143
        in.close();
jtulach@144
   144
    } // end ClassData.read()
jtulach@144
   145
jtulach@144
   146
    /**
jtulach@144
   147
     * Reads and stores constant pool info.
jtulach@144
   148
     */
jtulach@144
   149
    void readCP(DataInputStream in) throws IOException {
jtulach@144
   150
        cpool_count = in.readUnsignedShort();
jtulach@144
   151
        tags = new byte[cpool_count];
jtulach@144
   152
        cpool = new Object[cpool_count];
jtulach@144
   153
        for (int i = 1; i < cpool_count; i++) {
jtulach@144
   154
            byte tag = in.readByte();
jtulach@144
   155
jtulach@144
   156
            switch(tags[i] = tag) {
jtulach@144
   157
            case CONSTANT_UTF8:
jtulach@144
   158
                String str=in.readUTF();
jtulach@144
   159
                indexHashAscii.put(cpool[i] = str, new Integer(i));
jtulach@144
   160
                break;
jtulach@144
   161
            case CONSTANT_INTEGER:
jtulach@144
   162
                cpool[i] = new Integer(in.readInt());
jtulach@144
   163
                break;
jtulach@144
   164
            case CONSTANT_FLOAT:
jtulach@144
   165
                cpool[i] = new Float(in.readFloat());
jtulach@144
   166
                break;
jtulach@144
   167
            case CONSTANT_LONG:
jtulach@144
   168
                cpool[i++] = new Long(in.readLong());
jtulach@144
   169
                break;
jtulach@144
   170
            case CONSTANT_DOUBLE:
jtulach@144
   171
                cpool[i++] = new Double(in.readDouble());
jtulach@144
   172
                break;
jtulach@144
   173
            case CONSTANT_CLASS:
jtulach@144
   174
            case CONSTANT_STRING:
jtulach@144
   175
                cpool[i] = new CPX(in.readUnsignedShort());
jtulach@144
   176
                break;
jtulach@144
   177
jtulach@144
   178
            case CONSTANT_FIELD:
jtulach@144
   179
            case CONSTANT_METHOD:
jtulach@144
   180
            case CONSTANT_INTERFACEMETHOD:
jtulach@144
   181
            case CONSTANT_NAMEANDTYPE:
jtulach@144
   182
                cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
jtulach@144
   183
                break;
jtulach@144
   184
jtulach@144
   185
            case 0:
jtulach@144
   186
            default:
jtulach@144
   187
                throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
jtulach@144
   188
            }
jtulach@144
   189
        }
jtulach@144
   190
    }
jtulach@144
   191
jtulach@144
   192
    /**
jtulach@144
   193
     * Reads and strores field info.
jtulach@144
   194
     */
jtulach@144
   195
    protected void readFields(DataInputStream in) throws IOException {
jtulach@144
   196
        int fields_count = in.readUnsignedShort();
jtulach@144
   197
        fields=new FieldData[fields_count];
jtulach@144
   198
        for (int k = 0; k < fields_count; k++) {
jtulach@144
   199
            FieldData field=new FieldData(this);
jtulach@144
   200
            field.read(in);
jtulach@144
   201
            fields[k]=field;
jtulach@144
   202
        }
jtulach@144
   203
    }
jtulach@144
   204
jtulach@144
   205
    /**
jtulach@144
   206
     * Reads and strores Method info.
jtulach@144
   207
     */
jtulach@144
   208
    protected void readMethods(DataInputStream in) throws IOException {
jtulach@144
   209
        int methods_count = in.readUnsignedShort();
jtulach@144
   210
        methods=new MethodData[methods_count];
jtulach@144
   211
        for (int k = 0; k < methods_count ; k++) {
jtulach@144
   212
            MethodData method=new MethodData(this);
jtulach@144
   213
            method.read(in);
jtulach@144
   214
            methods[k]=method;
jtulach@144
   215
        }
jtulach@144
   216
    }
jtulach@144
   217
jtulach@144
   218
    /**
jtulach@144
   219
     * get a string
jtulach@144
   220
     */
jtulach@144
   221
    public String getString(int n) {
jaroslav@151
   222
        if (n == 0) {
jaroslav@151
   223
            return null; 
jaroslav@151
   224
        } else {
jaroslav@151
   225
            return (String)cpool[n];
jaroslav@151
   226
        }
jtulach@144
   227
    }
jtulach@144
   228
jtulach@144
   229
    /**
jtulach@144
   230
     * get the type of constant given an index
jtulach@144
   231
     */
jtulach@144
   232
    public byte getTag(int n) {
jtulach@144
   233
        try{
jtulach@144
   234
            return tags[n];
jtulach@144
   235
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   236
            return (byte)100;
jtulach@144
   237
        }
jtulach@144
   238
    }
jtulach@144
   239
jtulach@144
   240
    static final String hexString="0123456789ABCDEF";
jtulach@144
   241
jtulach@144
   242
    public static char hexTable[]=hexString.toCharArray();
jtulach@144
   243
jtulach@144
   244
    static String toHex(long val, int width) {
jtulach@144
   245
        StringBuffer s = new StringBuffer();
jtulach@144
   246
        for (int i=width-1; i>=0; i--)
jtulach@144
   247
            s.append(hexTable[((int)(val>>(4*i)))&0xF]);
jtulach@144
   248
        return "0x"+s.toString();
jtulach@144
   249
    }
jtulach@144
   250
jtulach@144
   251
    static String toHex(long val) {
jtulach@144
   252
        int width;
jtulach@144
   253
        for (width=16; width>0; width--) {
jtulach@144
   254
            if ((val>>(width-1)*4)!=0) break;
jtulach@144
   255
        }
jtulach@144
   256
        return toHex(val, width);
jtulach@144
   257
    }
jtulach@144
   258
jtulach@144
   259
    static String toHex(int val) {
jtulach@144
   260
        int width;
jtulach@144
   261
        for (width=8; width>0; width--) {
jtulach@144
   262
            if ((val>>(width-1)*4)!=0) break;
jtulach@144
   263
        }
jtulach@144
   264
        return toHex(val, width);
jtulach@144
   265
    }
jtulach@144
   266
jtulach@144
   267
    /**
jtulach@144
   268
     * Returns the name of this class.
jtulach@144
   269
     */
jtulach@144
   270
    public String getClassName() {
jtulach@144
   271
        String res=null;
jtulach@144
   272
        if (this_class==0) {
jtulach@144
   273
            return res;
jtulach@144
   274
        }
jtulach@144
   275
        int tcpx;
jtulach@144
   276
        try {
jtulach@144
   277
            if (tags[this_class]!=CONSTANT_CLASS) {
jtulach@144
   278
                return res; //"<CP["+cpx+"] is not a Class> ";
jtulach@144
   279
            }
jtulach@144
   280
            tcpx=((CPX)cpool[this_class]).cpx;
jtulach@144
   281
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   282
            return res; // "#"+cpx+"// invalid constant pool index";
jtulach@144
   283
        } catch (Throwable e) {
jtulach@144
   284
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   285
        }
jtulach@144
   286
jtulach@144
   287
        try {
jtulach@144
   288
            return (String)(cpool[tcpx]);
jtulach@144
   289
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   290
            return  res; // "class #"+scpx+"// invalid constant pool index";
jtulach@144
   291
        } catch (ClassCastException e) {
jtulach@144
   292
            return  res; // "class #"+scpx+"// invalid constant pool reference";
jtulach@144
   293
        } catch (Throwable e) {
jtulach@144
   294
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   295
        }
jtulach@144
   296
jtulach@144
   297
    }
jtulach@144
   298
jtulach@144
   299
    /**
jtulach@144
   300
     * Returns the name of class at perticular index.
jtulach@144
   301
     */
jtulach@144
   302
    public String getClassName(int cpx) {
jtulach@144
   303
        String res="#"+cpx;
jtulach@144
   304
        if (cpx==0) {
jtulach@144
   305
            return res;
jtulach@144
   306
        }
jtulach@144
   307
        int scpx;
jtulach@144
   308
        try {
jtulach@144
   309
            if (tags[cpx]!=CONSTANT_CLASS) {
jtulach@144
   310
                return res; //"<CP["+cpx+"] is not a Class> ";
jtulach@144
   311
            }
jtulach@144
   312
            scpx=((CPX)cpool[cpx]).cpx;
jtulach@144
   313
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   314
            return res; // "#"+cpx+"// invalid constant pool index";
jtulach@144
   315
        } catch (Throwable e) {
jtulach@144
   316
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   317
        }
jtulach@144
   318
        res="#"+scpx;
jtulach@144
   319
        try {
jtulach@144
   320
            return (String)(cpool[scpx]);
jtulach@144
   321
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   322
            return  res; // "class #"+scpx+"// invalid constant pool index";
jtulach@144
   323
        } catch (ClassCastException e) {
jtulach@144
   324
            return  res; // "class #"+scpx+"// invalid constant pool reference";
jtulach@144
   325
        } catch (Throwable e) {
jtulach@144
   326
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   327
        }
jtulach@144
   328
    }
jaroslav@355
   329
    
jaroslav@355
   330
    public int getAccessFlags() {
jaroslav@355
   331
        return access;
jaroslav@355
   332
    }
jtulach@144
   333
jtulach@144
   334
    /**
jtulach@144
   335
     * Returns true if it is a class
jtulach@144
   336
     */
jtulach@144
   337
    public boolean isClass() {
jtulach@144
   338
        if((access & ACC_INTERFACE) == 0) return true;
jtulach@144
   339
        return false;
jtulach@144
   340
    }
jtulach@144
   341
jtulach@144
   342
    /**
jtulach@144
   343
     * Returns true if it is a interface.
jtulach@144
   344
     */
jtulach@144
   345
    public boolean isInterface(){
jtulach@144
   346
        if((access & ACC_INTERFACE) != 0) return true;
jtulach@144
   347
        return false;
jtulach@144
   348
    }
jtulach@144
   349
jtulach@144
   350
    /**
jtulach@144
   351
     * Returns true if this member is public, false otherwise.
jtulach@144
   352
     */
jtulach@144
   353
    public boolean isPublic(){
jtulach@144
   354
        return (access & ACC_PUBLIC) != 0;
jtulach@144
   355
    }
jtulach@144
   356
jtulach@144
   357
    /**
jtulach@144
   358
     * Returns the access of this class or interface.
jtulach@144
   359
     */
jtulach@144
   360
    public String[] getAccess(){
jtulach@144
   361
        Vector v = new Vector();
jtulach@144
   362
        if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
jtulach@144
   363
        if ((access & ACC_FINAL)    !=0) v.addElement("final");
jtulach@144
   364
        if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
jtulach@144
   365
        String[] accflags = new String[v.size()];
jtulach@144
   366
        v.copyInto(accflags);
jtulach@144
   367
        return accflags;
jtulach@144
   368
    }
jtulach@144
   369
jtulach@144
   370
    /**
jtulach@144
   371
     * Returns list of innerclasses.
jtulach@144
   372
     */
jtulach@144
   373
    public InnerClassData[] getInnerClasses(){
jtulach@144
   374
        return innerClasses;
jtulach@144
   375
    }
jtulach@144
   376
jtulach@144
   377
    /**
jtulach@144
   378
     * Returns list of attributes.
jtulach@144
   379
     */
jaroslav@152
   380
    final AttrData[] getAttributes(){
jtulach@144
   381
        return attrs;
jtulach@144
   382
    }
jaroslav@152
   383
    
jaroslav@152
   384
    public byte[] findAnnotationData(boolean classRetention) {
jaroslav@152
   385
        String n = classRetention ?
jaroslav@152
   386
            "RuntimeInvisibleAnnotations" : // NOI18N
jaroslav@152
   387
            "RuntimeVisibleAnnotations"; // NOI18N
jaroslav@152
   388
        return findAttr(n, attrs);
jaroslav@152
   389
    }
jtulach@144
   390
jtulach@144
   391
    /**
jtulach@144
   392
     * Returns true if superbit is set.
jtulach@144
   393
     */
jtulach@144
   394
    public boolean isSuperSet(){
jtulach@144
   395
        if ((access & ACC_SUPER)   !=0) return true;
jtulach@144
   396
        return false;
jtulach@144
   397
    }
jtulach@144
   398
jtulach@144
   399
    /**
jtulach@144
   400
     * Returns super class name.
jtulach@144
   401
     */
jtulach@144
   402
    public String getSuperClassName(){
jtulach@144
   403
        String res=null;
jtulach@144
   404
        if (super_class==0) {
jtulach@144
   405
            return res;
jtulach@144
   406
        }
jtulach@144
   407
        int scpx;
jtulach@144
   408
        try {
jtulach@144
   409
            if (tags[super_class]!=CONSTANT_CLASS) {
jtulach@144
   410
                return res; //"<CP["+cpx+"] is not a Class> ";
jtulach@144
   411
            }
jtulach@144
   412
            scpx=((CPX)cpool[super_class]).cpx;
jtulach@144
   413
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   414
            return res; // "#"+cpx+"// invalid constant pool index";
jtulach@144
   415
        } catch (Throwable e) {
jtulach@144
   416
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   417
        }
jtulach@144
   418
jtulach@144
   419
        try {
jtulach@144
   420
            return (String)(cpool[scpx]);
jtulach@144
   421
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   422
            return  res; // "class #"+scpx+"// invalid constant pool index";
jtulach@144
   423
        } catch (ClassCastException e) {
jtulach@144
   424
            return  res; // "class #"+scpx+"// invalid constant pool reference";
jtulach@144
   425
        } catch (Throwable e) {
jtulach@144
   426
            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
jtulach@144
   427
        }
jtulach@144
   428
    }
jtulach@144
   429
jtulach@144
   430
    /**
jtulach@144
   431
     * Returns list of super interfaces.
jtulach@144
   432
     */
jtulach@144
   433
    public String[] getSuperInterfaces(){
jtulach@144
   434
        String interfacenames[] = new String[interfaces.length];
jtulach@144
   435
        int interfacecpx = -1;
jtulach@144
   436
        for(int i = 0; i < interfaces.length; i++){
jtulach@144
   437
            interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
jtulach@144
   438
            interfacenames[i] = (String)(cpool[interfacecpx]);
jtulach@144
   439
        }
jtulach@144
   440
        return interfacenames;
jtulach@144
   441
    }
jtulach@144
   442
jtulach@144
   443
    /**
jtulach@144
   444
     * Returns string at prticular constant pool index.
jtulach@144
   445
     */
jtulach@144
   446
    public String getStringValue(int cpoolx) {
jtulach@144
   447
        try {
jtulach@144
   448
            return ((String)cpool[cpoolx]);
jtulach@144
   449
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   450
            return "//invalid constant pool index:"+cpoolx;
jtulach@144
   451
        } catch (ClassCastException e) {
jtulach@144
   452
            return "//invalid constant pool ref:"+cpoolx;
jtulach@144
   453
        }
jtulach@144
   454
    }
jtulach@144
   455
jtulach@144
   456
    /**
jtulach@144
   457
     * Returns list of field info.
jtulach@144
   458
     */
jtulach@144
   459
    public  FieldData[] getFields(){
jtulach@144
   460
        return fields;
jtulach@144
   461
    }
jtulach@144
   462
jtulach@144
   463
    /**
jtulach@144
   464
     * Returns list of method info.
jtulach@144
   465
     */
jtulach@144
   466
    public  MethodData[] getMethods(){
jtulach@144
   467
        return methods;
jtulach@144
   468
    }
jtulach@144
   469
jtulach@144
   470
    /**
jtulach@144
   471
     * Returns constant pool entry at that index.
jtulach@144
   472
     */
jtulach@144
   473
    public CPX2 getCpoolEntry(int cpx){
jtulach@144
   474
        return ((CPX2)(cpool[cpx]));
jtulach@144
   475
    }
jtulach@144
   476
jtulach@144
   477
    public Object getCpoolEntryobj(int cpx){
jtulach@144
   478
        return (cpool[cpx]);
jtulach@144
   479
    }
jtulach@144
   480
jtulach@144
   481
    /**
jtulach@144
   482
     * Returns index of this class.
jtulach@144
   483
     */
jtulach@144
   484
    public int getthis_cpx(){
jtulach@144
   485
        return this_class;
jtulach@144
   486
    }
jtulach@144
   487
jtulach@144
   488
    /**
jtulach@144
   489
     * Returns string at that index.
jtulach@144
   490
     */
jtulach@144
   491
    public String StringValue(int cpx) {
jaroslav@151
   492
        return stringValue(cpx, false);
jaroslav@151
   493
    }
jaroslav@151
   494
    public String stringValue(int cpx, boolean textual) {
jaroslav@230
   495
        return stringValue(cpx, textual, null);
jaroslav@230
   496
    }
jaroslav@230
   497
    public String stringValue(int cpx, String[] classRefs) {
jaroslav@230
   498
        return stringValue(cpx, true, classRefs);
jaroslav@230
   499
    }
jaroslav@230
   500
    private String stringValue(int cpx, boolean textual, String[] refs) {
jtulach@144
   501
        if (cpx==0) return "#0";
jtulach@144
   502
        int tag;
jtulach@144
   503
        Object x;
jtulach@144
   504
        String suffix="";
jtulach@144
   505
        try {
jtulach@144
   506
            tag=tags[cpx];
jtulach@144
   507
            x=cpool[cpx];
jtulach@144
   508
        } catch (IndexOutOfBoundsException e) {
jtulach@144
   509
            return "<Incorrect CP index:"+cpx+">";
jtulach@144
   510
        }
jtulach@144
   511
jtulach@144
   512
        if (x==null) return "<NULL>";
jtulach@144
   513
        switch (tag) {
jtulach@144
   514
        case CONSTANT_UTF8: {
jtulach@161
   515
            if (!textual) {
jtulach@161
   516
                return (String)x;
jtulach@161
   517
            }
jtulach@157
   518
            StringBuilder sb=new StringBuilder();
jtulach@144
   519
            String s=(String)x;
jtulach@144
   520
            for (int k=0; k<s.length(); k++) {
jtulach@144
   521
                char c=s.charAt(k);
jtulach@144
   522
                switch (c) {
jtulach@157
   523
                case '\\': sb.append('\\').append('\\'); break;
jtulach@144
   524
                case '\t': sb.append('\\').append('t'); break;
jtulach@144
   525
                case '\n': sb.append('\\').append('n'); break;
jtulach@144
   526
                case '\r': sb.append('\\').append('r'); break;
jtulach@144
   527
                case '\"': sb.append('\\').append('\"'); break;
jtulach@144
   528
                default: sb.append(c);
jtulach@144
   529
                }
jtulach@144
   530
            }
jtulach@144
   531
            return sb.toString();
jtulach@144
   532
        }
jtulach@144
   533
        case CONSTANT_DOUBLE: {
jtulach@144
   534
            Double d=(Double)x;
jtulach@144
   535
            String sd=d.toString();
jaroslav@151
   536
            if (textual) {
jaroslav@151
   537
                return sd;
jaroslav@151
   538
            }
jtulach@144
   539
            return sd+"d";
jtulach@144
   540
        }
jtulach@144
   541
        case CONSTANT_FLOAT: {
jtulach@144
   542
            Float f=(Float)x;
jtulach@144
   543
            String sf=(f).toString();
jaroslav@151
   544
            if (textual) {
jaroslav@151
   545
                return sf;
jaroslav@151
   546
            }
jtulach@144
   547
            return sf+"f";
jtulach@144
   548
        }
jtulach@144
   549
        case CONSTANT_LONG: {
jtulach@144
   550
            Long ln = (Long)x;
jaroslav@151
   551
            if (textual) {
jaroslav@151
   552
                return ln.toString();
jaroslav@151
   553
            }
jtulach@144
   554
            return ln.toString()+'l';
jtulach@144
   555
        }
jtulach@144
   556
        case CONSTANT_INTEGER: {
jtulach@144
   557
            Integer in = (Integer)x;
jtulach@144
   558
            return in.toString();
jtulach@144
   559
        }
jtulach@144
   560
        case CONSTANT_CLASS:
jaroslav@303
   561
            String jn = getClassName(cpx);
jaroslav@151
   562
            if (textual) {
jaroslav@230
   563
                if (refs != null) {
jaroslav@230
   564
                    refs[0] = jn;
jaroslav@230
   565
                }
jaroslav@274
   566
                return jn;
jaroslav@151
   567
            }
jaroslav@303
   568
            return javaName(jn);
jtulach@144
   569
        case CONSTANT_STRING:
jtulach@161
   570
            String sv = stringValue(((CPX)x).cpx, textual);
jaroslav@151
   571
            if (textual) {
jaroslav@151
   572
                return '"' + sv + '"';
jaroslav@151
   573
            } else {
jaroslav@151
   574
                return sv;
jaroslav@151
   575
            }
jtulach@144
   576
        case CONSTANT_FIELD:
jtulach@144
   577
        case CONSTANT_METHOD:
jtulach@144
   578
        case CONSTANT_INTERFACEMETHOD:
jtulach@144
   579
            //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
jtulach@144
   580
             return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
jtulach@144
   581
jtulach@144
   582
        case CONSTANT_NAMEANDTYPE:
jtulach@144
   583
            return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
jtulach@144
   584
        default:
jtulach@144
   585
            return "UnknownTag"; //TBD
jtulach@144
   586
        }
jtulach@144
   587
    }
jtulach@144
   588
jtulach@144
   589
    /**
jtulach@144
   590
     * Returns resolved java type name.
jtulach@144
   591
     */
jtulach@144
   592
    public String javaName(String name) {
jtulach@144
   593
        if( name==null) return "null";
jtulach@144
   594
        int len=name.length();
jtulach@144
   595
        if (len==0) return "\"\"";
jtulach@144
   596
        int cc='/';
jtulach@144
   597
    fullname: { // xxx/yyy/zzz
jtulach@144
   598
            int cp;
jtulach@144
   599
            for (int k=0; k<len; k += Character.charCount(cp)) {
jtulach@144
   600
                cp=name.codePointAt(k);
jtulach@144
   601
                if (cc=='/') {
jaroslav@149
   602
                    if (!isJavaIdentifierStart(cp)) break fullname;
jtulach@144
   603
                } else if (cp!='/') {
jaroslav@149
   604
                    if (!isJavaIdentifierPart(cp)) break fullname;
jtulach@144
   605
                }
jtulach@144
   606
                cc=cp;
jtulach@144
   607
            }
jtulach@144
   608
            return name;
jtulach@144
   609
        }
jtulach@144
   610
        return "\""+name+"\"";
jtulach@144
   611
    }
jtulach@144
   612
jtulach@144
   613
    public String getName(int cpx) {
jtulach@144
   614
        String res;
jtulach@144
   615
        try {
jtulach@144
   616
            return javaName((String)cpool[cpx]); //.replace('/','.');
jtulach@144
   617
        } catch (ArrayIndexOutOfBoundsException e) {
jtulach@144
   618
            return "<invalid constant pool index:"+cpx+">";
jtulach@144
   619
        } catch (ClassCastException e) {
jtulach@144
   620
            return "<invalid constant pool ref:"+cpx+">";
jtulach@144
   621
        }
jtulach@144
   622
    }
jtulach@144
   623
jtulach@144
   624
    /**
jtulach@144
   625
     * Returns unqualified class name.
jtulach@144
   626
     */
jtulach@144
   627
    public String getShortClassName(int cpx) {
jtulach@144
   628
        String classname=javaName(getClassName(cpx));
jtulach@144
   629
        pkgPrefixLen=classname.lastIndexOf("/")+1;
jtulach@144
   630
        if (pkgPrefixLen!=0) {
jtulach@144
   631
            pkgPrefix=classname.substring(0,pkgPrefixLen);
jtulach@144
   632
            if (classname.startsWith(pkgPrefix)) {
jtulach@144
   633
                return classname.substring(pkgPrefixLen);
jtulach@144
   634
            }
jtulach@144
   635
        }
jtulach@144
   636
        return classname;
jtulach@144
   637
    }
jtulach@144
   638
jtulach@144
   639
    /**
jtulach@144
   640
     * Returns source file name.
jtulach@144
   641
     */
jtulach@144
   642
    public String getSourceName(){
jtulach@144
   643
        return getName(source_cpx);
jtulach@144
   644
    }
jtulach@144
   645
jtulach@144
   646
    /**
jtulach@144
   647
     * Returns package name.
jtulach@144
   648
     */
jtulach@144
   649
    public String getPkgName(){
jtulach@144
   650
        String classname=getClassName(this_class);
jtulach@144
   651
        pkgPrefixLen=classname.lastIndexOf("/")+1;
jtulach@144
   652
        if (pkgPrefixLen!=0) {
jtulach@144
   653
            pkgPrefix=classname.substring(0,pkgPrefixLen);
jtulach@144
   654
            return("package  "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
jtulach@144
   655
        }else return null;
jtulach@144
   656
    }
jtulach@144
   657
jtulach@144
   658
    /**
jtulach@144
   659
     * Returns total constant pool entry count.
jtulach@144
   660
     */
jtulach@144
   661
    public int getCpoolCount(){
jtulach@144
   662
        return cpool_count;
jtulach@144
   663
    }
jtulach@144
   664
jtulach@144
   665
    /**
jtulach@144
   666
     * Returns minor version of class file.
jtulach@144
   667
     */
jtulach@144
   668
    public int getMinor_version(){
jtulach@144
   669
        return minor_version;
jtulach@144
   670
    }
jtulach@144
   671
jtulach@144
   672
    /**
jtulach@144
   673
     * Returns major version of class file.
jtulach@144
   674
     */
jtulach@144
   675
    public int getMajor_version(){
jtulach@144
   676
        return major_version;
jtulach@144
   677
    }
jaroslav@149
   678
jaroslav@149
   679
    private boolean isJavaIdentifierStart(int cp) {
jaroslav@149
   680
        return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
jaroslav@149
   681
    }
jaroslav@149
   682
jaroslav@149
   683
    private boolean isJavaIdentifierPart(int cp) {
jaroslav@149
   684
        return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
jaroslav@149
   685
    }
jaroslav@151
   686
jaroslav@151
   687
    public String[] getNameAndType(int indx) {
jaroslav@151
   688
        return getNameAndType(indx, 0, new String[2]);
jaroslav@151
   689
    }
jaroslav@151
   690
    
jaroslav@151
   691
    private String[] getNameAndType(int indx, int at, String[] arr) {
jaroslav@151
   692
        CPX2 c2 = getCpoolEntry(indx);
jaroslav@151
   693
        arr[at] = StringValue(c2.cpx1);
jaroslav@151
   694
        arr[at + 1] = StringValue(c2.cpx2);
jaroslav@151
   695
        return arr;
jaroslav@151
   696
    }
jaroslav@151
   697
jaroslav@151
   698
    public String[] getFieldInfoName(int indx) {
jaroslav@151
   699
        CPX2 c2 = getCpoolEntry(indx);
jaroslav@151
   700
        String[] arr = new String[3];
jaroslav@151
   701
        arr[0] = getClassName(c2.cpx1);
jaroslav@151
   702
        return getNameAndType(c2.cpx2, 1, arr);
jaroslav@151
   703
    }
jaroslav@152
   704
jaroslav@152
   705
    static byte[] findAttr(String n, AttrData[] attrs) {
jaroslav@152
   706
        for (AttrData ad : attrs) {
jaroslav@152
   707
            if (n.equals(ad.getAttrName())) {
jaroslav@152
   708
                return ad.getData();
jaroslav@152
   709
            }
jaroslav@152
   710
        }
jaroslav@152
   711
        return null;
jaroslav@152
   712
    }
jtulach@144
   713
}