javap/src/main/java/org/apidesign/javap/ClassData.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 05 Feb 2013 08:48:23 +0100
branchemul
changeset 667 5866e89ef568
parent 303 c12342170235
permissions -rw-r--r--
Test can specify multiple HTTP resources
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
}