rt/javap/src/main/java/org/apidesign/javap/ClassData.java
changeset 772 d382dacfd73f
parent 355 eea0065bcc1a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/javap/src/main/java/org/apidesign/javap/ClassData.java	Tue Feb 26 16:54:16 2013 +0100
     1.3 @@ -0,0 +1,713 @@
     1.4 +/*
     1.5 + * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +
    1.30 +package org.apidesign.javap;
    1.31 +
    1.32 +import java.io.*;
    1.33 +
    1.34 +/**
    1.35 + * Central data repository of the Java Disassembler.
    1.36 + * Stores all the information in java class file.
    1.37 + *
    1.38 + * @author  Sucheta Dambalkar (Adopted code from jdis)
    1.39 + */
    1.40 +public final class ClassData implements RuntimeConstants {
    1.41 +
    1.42 +    private int magic;
    1.43 +    private int minor_version;
    1.44 +    private int major_version;
    1.45 +    private int cpool_count;
    1.46 +    private Object cpool[];
    1.47 +    private int access;
    1.48 +    private int this_class = 0;;
    1.49 +    private int super_class;
    1.50 +    private int interfaces_count;
    1.51 +    private int[] interfaces = new int[0];;
    1.52 +    private int fields_count;
    1.53 +    private FieldData[] fields;
    1.54 +    private int methods_count;
    1.55 +    private MethodData[] methods;
    1.56 +    private InnerClassData[] innerClasses;
    1.57 +    private int attributes_count;
    1.58 +    private AttrData[] attrs;
    1.59 +    private String classname;
    1.60 +    private String superclassname;
    1.61 +    private int source_cpx=0;
    1.62 +    private byte tags[];
    1.63 +    private Hashtable indexHashAscii = new Hashtable();
    1.64 +    private String pkgPrefix="";
    1.65 +    private int pkgPrefixLen=0;
    1.66 +
    1.67 +    /**
    1.68 +     * Read classfile to disassemble.
    1.69 +     */
    1.70 +    public ClassData(InputStream infile) throws IOException {
    1.71 +        this.read(new DataInputStream(infile));
    1.72 +    }
    1.73 +
    1.74 +    /**
    1.75 +     * Reads and stores class file information.
    1.76 +     */
    1.77 +    public void read(DataInputStream in) throws IOException {
    1.78 +        // Read the header
    1.79 +        magic = in.readInt();
    1.80 +        if (magic != JAVA_MAGIC) {
    1.81 +            throw new ClassFormatError("wrong magic: " +
    1.82 +                                       toHex(magic) + ", expected " +
    1.83 +                                       toHex(JAVA_MAGIC));
    1.84 +        }
    1.85 +        minor_version = in.readShort();
    1.86 +        major_version = in.readShort();
    1.87 +        if (major_version != JAVA_VERSION) {
    1.88 +        }
    1.89 +
    1.90 +        // Read the constant pool
    1.91 +        readCP(in);
    1.92 +        access = in.readUnsignedShort();
    1.93 +        this_class = in.readUnsignedShort();
    1.94 +        super_class = in.readUnsignedShort();
    1.95 +
    1.96 +        //Read interfaces.
    1.97 +        interfaces_count = in.readUnsignedShort();
    1.98 +        if(interfaces_count > 0){
    1.99 +            interfaces = new int[interfaces_count];
   1.100 +        }
   1.101 +        for (int i = 0; i < interfaces_count; i++) {
   1.102 +            interfaces[i]=in.readShort();
   1.103 +        }
   1.104 +
   1.105 +        // Read the fields
   1.106 +        readFields(in);
   1.107 +
   1.108 +        // Read the methods
   1.109 +        readMethods(in);
   1.110 +
   1.111 +        // Read the attributes
   1.112 +        attributes_count = in.readUnsignedShort();
   1.113 +        attrs=new AttrData[attributes_count];
   1.114 +        for (int k = 0; k < attributes_count; k++) {
   1.115 +            int name_cpx=in.readUnsignedShort();
   1.116 +            if (getTag(name_cpx)==CONSTANT_UTF8
   1.117 +                && getString(name_cpx).equals("SourceFile")
   1.118 +                ){      if (in.readInt()!=2)
   1.119 +                    throw new ClassFormatError("invalid attr length");
   1.120 +                source_cpx=in.readUnsignedShort();
   1.121 +                AttrData attr=new AttrData(this);
   1.122 +                attr.read(name_cpx);
   1.123 +                attrs[k]=attr;
   1.124 +
   1.125 +            } else if (getTag(name_cpx)==CONSTANT_UTF8
   1.126 +                       && getString(name_cpx).equals("InnerClasses")
   1.127 +                       ){       int length=in.readInt();
   1.128 +                       int num=in.readUnsignedShort();
   1.129 +                       if (2+num*8 != length)
   1.130 +                           throw new ClassFormatError("invalid attr length");
   1.131 +                       innerClasses=new InnerClassData[num];
   1.132 +                       for (int j = 0; j < num; j++) {
   1.133 +                           InnerClassData innerClass=new InnerClassData(this);
   1.134 +                           innerClass.read(in);
   1.135 +                           innerClasses[j]=innerClass;
   1.136 +                       }
   1.137 +                       AttrData attr=new AttrData(this);
   1.138 +                       attr.read(name_cpx);
   1.139 +                       attrs[k]=attr;
   1.140 +            } else {
   1.141 +                AttrData attr=new AttrData(this);
   1.142 +                attr.read(name_cpx, in);
   1.143 +                attrs[k]=attr;
   1.144 +            }
   1.145 +        }
   1.146 +        in.close();
   1.147 +    } // end ClassData.read()
   1.148 +
   1.149 +    /**
   1.150 +     * Reads and stores constant pool info.
   1.151 +     */
   1.152 +    void readCP(DataInputStream in) throws IOException {
   1.153 +        cpool_count = in.readUnsignedShort();
   1.154 +        tags = new byte[cpool_count];
   1.155 +        cpool = new Object[cpool_count];
   1.156 +        for (int i = 1; i < cpool_count; i++) {
   1.157 +            byte tag = in.readByte();
   1.158 +
   1.159 +            switch(tags[i] = tag) {
   1.160 +            case CONSTANT_UTF8:
   1.161 +                String str=in.readUTF();
   1.162 +                indexHashAscii.put(cpool[i] = str, new Integer(i));
   1.163 +                break;
   1.164 +            case CONSTANT_INTEGER:
   1.165 +                cpool[i] = new Integer(in.readInt());
   1.166 +                break;
   1.167 +            case CONSTANT_FLOAT:
   1.168 +                cpool[i] = new Float(in.readFloat());
   1.169 +                break;
   1.170 +            case CONSTANT_LONG:
   1.171 +                cpool[i++] = new Long(in.readLong());
   1.172 +                break;
   1.173 +            case CONSTANT_DOUBLE:
   1.174 +                cpool[i++] = new Double(in.readDouble());
   1.175 +                break;
   1.176 +            case CONSTANT_CLASS:
   1.177 +            case CONSTANT_STRING:
   1.178 +                cpool[i] = new CPX(in.readUnsignedShort());
   1.179 +                break;
   1.180 +
   1.181 +            case CONSTANT_FIELD:
   1.182 +            case CONSTANT_METHOD:
   1.183 +            case CONSTANT_INTERFACEMETHOD:
   1.184 +            case CONSTANT_NAMEANDTYPE:
   1.185 +                cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
   1.186 +                break;
   1.187 +
   1.188 +            case 0:
   1.189 +            default:
   1.190 +                throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
   1.191 +            }
   1.192 +        }
   1.193 +    }
   1.194 +
   1.195 +    /**
   1.196 +     * Reads and strores field info.
   1.197 +     */
   1.198 +    protected void readFields(DataInputStream in) throws IOException {
   1.199 +        int fields_count = in.readUnsignedShort();
   1.200 +        fields=new FieldData[fields_count];
   1.201 +        for (int k = 0; k < fields_count; k++) {
   1.202 +            FieldData field=new FieldData(this);
   1.203 +            field.read(in);
   1.204 +            fields[k]=field;
   1.205 +        }
   1.206 +    }
   1.207 +
   1.208 +    /**
   1.209 +     * Reads and strores Method info.
   1.210 +     */
   1.211 +    protected void readMethods(DataInputStream in) throws IOException {
   1.212 +        int methods_count = in.readUnsignedShort();
   1.213 +        methods=new MethodData[methods_count];
   1.214 +        for (int k = 0; k < methods_count ; k++) {
   1.215 +            MethodData method=new MethodData(this);
   1.216 +            method.read(in);
   1.217 +            methods[k]=method;
   1.218 +        }
   1.219 +    }
   1.220 +
   1.221 +    /**
   1.222 +     * get a string
   1.223 +     */
   1.224 +    public String getString(int n) {
   1.225 +        if (n == 0) {
   1.226 +            return null; 
   1.227 +        } else {
   1.228 +            return (String)cpool[n];
   1.229 +        }
   1.230 +    }
   1.231 +
   1.232 +    /**
   1.233 +     * get the type of constant given an index
   1.234 +     */
   1.235 +    public byte getTag(int n) {
   1.236 +        try{
   1.237 +            return tags[n];
   1.238 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.239 +            return (byte)100;
   1.240 +        }
   1.241 +    }
   1.242 +
   1.243 +    static final String hexString="0123456789ABCDEF";
   1.244 +
   1.245 +    public static char hexTable[]=hexString.toCharArray();
   1.246 +
   1.247 +    static String toHex(long val, int width) {
   1.248 +        StringBuffer s = new StringBuffer();
   1.249 +        for (int i=width-1; i>=0; i--)
   1.250 +            s.append(hexTable[((int)(val>>(4*i)))&0xF]);
   1.251 +        return "0x"+s.toString();
   1.252 +    }
   1.253 +
   1.254 +    static String toHex(long val) {
   1.255 +        int width;
   1.256 +        for (width=16; width>0; width--) {
   1.257 +            if ((val>>(width-1)*4)!=0) break;
   1.258 +        }
   1.259 +        return toHex(val, width);
   1.260 +    }
   1.261 +
   1.262 +    static String toHex(int val) {
   1.263 +        int width;
   1.264 +        for (width=8; width>0; width--) {
   1.265 +            if ((val>>(width-1)*4)!=0) break;
   1.266 +        }
   1.267 +        return toHex(val, width);
   1.268 +    }
   1.269 +
   1.270 +    /**
   1.271 +     * Returns the name of this class.
   1.272 +     */
   1.273 +    public String getClassName() {
   1.274 +        String res=null;
   1.275 +        if (this_class==0) {
   1.276 +            return res;
   1.277 +        }
   1.278 +        int tcpx;
   1.279 +        try {
   1.280 +            if (tags[this_class]!=CONSTANT_CLASS) {
   1.281 +                return res; //"<CP["+cpx+"] is not a Class> ";
   1.282 +            }
   1.283 +            tcpx=((CPX)cpool[this_class]).cpx;
   1.284 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.285 +            return res; // "#"+cpx+"// invalid constant pool index";
   1.286 +        } catch (Throwable e) {
   1.287 +            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
   1.288 +        }
   1.289 +
   1.290 +        try {
   1.291 +            return (String)(cpool[tcpx]);
   1.292 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.293 +            return  res; // "class #"+scpx+"// invalid constant pool index";
   1.294 +        } catch (ClassCastException e) {
   1.295 +            return  res; // "class #"+scpx+"// invalid constant pool reference";
   1.296 +        } catch (Throwable e) {
   1.297 +            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
   1.298 +        }
   1.299 +
   1.300 +    }
   1.301 +
   1.302 +    /**
   1.303 +     * Returns the name of class at perticular index.
   1.304 +     */
   1.305 +    public String getClassName(int cpx) {
   1.306 +        String res="#"+cpx;
   1.307 +        if (cpx==0) {
   1.308 +            return res;
   1.309 +        }
   1.310 +        int scpx;
   1.311 +        try {
   1.312 +            if (tags[cpx]!=CONSTANT_CLASS) {
   1.313 +                return res; //"<CP["+cpx+"] is not a Class> ";
   1.314 +            }
   1.315 +            scpx=((CPX)cpool[cpx]).cpx;
   1.316 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.317 +            return res; // "#"+cpx+"// invalid constant pool index";
   1.318 +        } catch (Throwable e) {
   1.319 +            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
   1.320 +        }
   1.321 +        res="#"+scpx;
   1.322 +        try {
   1.323 +            return (String)(cpool[scpx]);
   1.324 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.325 +            return  res; // "class #"+scpx+"// invalid constant pool index";
   1.326 +        } catch (ClassCastException e) {
   1.327 +            return  res; // "class #"+scpx+"// invalid constant pool reference";
   1.328 +        } catch (Throwable e) {
   1.329 +            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
   1.330 +        }
   1.331 +    }
   1.332 +    
   1.333 +    public int getAccessFlags() {
   1.334 +        return access;
   1.335 +    }
   1.336 +
   1.337 +    /**
   1.338 +     * Returns true if it is a class
   1.339 +     */
   1.340 +    public boolean isClass() {
   1.341 +        if((access & ACC_INTERFACE) == 0) return true;
   1.342 +        return false;
   1.343 +    }
   1.344 +
   1.345 +    /**
   1.346 +     * Returns true if it is a interface.
   1.347 +     */
   1.348 +    public boolean isInterface(){
   1.349 +        if((access & ACC_INTERFACE) != 0) return true;
   1.350 +        return false;
   1.351 +    }
   1.352 +
   1.353 +    /**
   1.354 +     * Returns true if this member is public, false otherwise.
   1.355 +     */
   1.356 +    public boolean isPublic(){
   1.357 +        return (access & ACC_PUBLIC) != 0;
   1.358 +    }
   1.359 +
   1.360 +    /**
   1.361 +     * Returns the access of this class or interface.
   1.362 +     */
   1.363 +    public String[] getAccess(){
   1.364 +        Vector v = new Vector();
   1.365 +        if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
   1.366 +        if ((access & ACC_FINAL)    !=0) v.addElement("final");
   1.367 +        if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
   1.368 +        String[] accflags = new String[v.size()];
   1.369 +        v.copyInto(accflags);
   1.370 +        return accflags;
   1.371 +    }
   1.372 +
   1.373 +    /**
   1.374 +     * Returns list of innerclasses.
   1.375 +     */
   1.376 +    public InnerClassData[] getInnerClasses(){
   1.377 +        return innerClasses;
   1.378 +    }
   1.379 +
   1.380 +    /**
   1.381 +     * Returns list of attributes.
   1.382 +     */
   1.383 +    final AttrData[] getAttributes(){
   1.384 +        return attrs;
   1.385 +    }
   1.386 +    
   1.387 +    public byte[] findAnnotationData(boolean classRetention) {
   1.388 +        String n = classRetention ?
   1.389 +            "RuntimeInvisibleAnnotations" : // NOI18N
   1.390 +            "RuntimeVisibleAnnotations"; // NOI18N
   1.391 +        return findAttr(n, attrs);
   1.392 +    }
   1.393 +
   1.394 +    /**
   1.395 +     * Returns true if superbit is set.
   1.396 +     */
   1.397 +    public boolean isSuperSet(){
   1.398 +        if ((access & ACC_SUPER)   !=0) return true;
   1.399 +        return false;
   1.400 +    }
   1.401 +
   1.402 +    /**
   1.403 +     * Returns super class name.
   1.404 +     */
   1.405 +    public String getSuperClassName(){
   1.406 +        String res=null;
   1.407 +        if (super_class==0) {
   1.408 +            return res;
   1.409 +        }
   1.410 +        int scpx;
   1.411 +        try {
   1.412 +            if (tags[super_class]!=CONSTANT_CLASS) {
   1.413 +                return res; //"<CP["+cpx+"] is not a Class> ";
   1.414 +            }
   1.415 +            scpx=((CPX)cpool[super_class]).cpx;
   1.416 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.417 +            return res; // "#"+cpx+"// invalid constant pool index";
   1.418 +        } catch (Throwable e) {
   1.419 +            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
   1.420 +        }
   1.421 +
   1.422 +        try {
   1.423 +            return (String)(cpool[scpx]);
   1.424 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.425 +            return  res; // "class #"+scpx+"// invalid constant pool index";
   1.426 +        } catch (ClassCastException e) {
   1.427 +            return  res; // "class #"+scpx+"// invalid constant pool reference";
   1.428 +        } catch (Throwable e) {
   1.429 +            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
   1.430 +        }
   1.431 +    }
   1.432 +
   1.433 +    /**
   1.434 +     * Returns list of super interfaces.
   1.435 +     */
   1.436 +    public String[] getSuperInterfaces(){
   1.437 +        String interfacenames[] = new String[interfaces.length];
   1.438 +        int interfacecpx = -1;
   1.439 +        for(int i = 0; i < interfaces.length; i++){
   1.440 +            interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
   1.441 +            interfacenames[i] = (String)(cpool[interfacecpx]);
   1.442 +        }
   1.443 +        return interfacenames;
   1.444 +    }
   1.445 +
   1.446 +    /**
   1.447 +     * Returns string at prticular constant pool index.
   1.448 +     */
   1.449 +    public String getStringValue(int cpoolx) {
   1.450 +        try {
   1.451 +            return ((String)cpool[cpoolx]);
   1.452 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.453 +            return "//invalid constant pool index:"+cpoolx;
   1.454 +        } catch (ClassCastException e) {
   1.455 +            return "//invalid constant pool ref:"+cpoolx;
   1.456 +        }
   1.457 +    }
   1.458 +
   1.459 +    /**
   1.460 +     * Returns list of field info.
   1.461 +     */
   1.462 +    public  FieldData[] getFields(){
   1.463 +        return fields;
   1.464 +    }
   1.465 +
   1.466 +    /**
   1.467 +     * Returns list of method info.
   1.468 +     */
   1.469 +    public  MethodData[] getMethods(){
   1.470 +        return methods;
   1.471 +    }
   1.472 +
   1.473 +    /**
   1.474 +     * Returns constant pool entry at that index.
   1.475 +     */
   1.476 +    public CPX2 getCpoolEntry(int cpx){
   1.477 +        return ((CPX2)(cpool[cpx]));
   1.478 +    }
   1.479 +
   1.480 +    public Object getCpoolEntryobj(int cpx){
   1.481 +        return (cpool[cpx]);
   1.482 +    }
   1.483 +
   1.484 +    /**
   1.485 +     * Returns index of this class.
   1.486 +     */
   1.487 +    public int getthis_cpx(){
   1.488 +        return this_class;
   1.489 +    }
   1.490 +
   1.491 +    /**
   1.492 +     * Returns string at that index.
   1.493 +     */
   1.494 +    public String StringValue(int cpx) {
   1.495 +        return stringValue(cpx, false);
   1.496 +    }
   1.497 +    public String stringValue(int cpx, boolean textual) {
   1.498 +        return stringValue(cpx, textual, null);
   1.499 +    }
   1.500 +    public String stringValue(int cpx, String[] classRefs) {
   1.501 +        return stringValue(cpx, true, classRefs);
   1.502 +    }
   1.503 +    private String stringValue(int cpx, boolean textual, String[] refs) {
   1.504 +        if (cpx==0) return "#0";
   1.505 +        int tag;
   1.506 +        Object x;
   1.507 +        String suffix="";
   1.508 +        try {
   1.509 +            tag=tags[cpx];
   1.510 +            x=cpool[cpx];
   1.511 +        } catch (IndexOutOfBoundsException e) {
   1.512 +            return "<Incorrect CP index:"+cpx+">";
   1.513 +        }
   1.514 +
   1.515 +        if (x==null) return "<NULL>";
   1.516 +        switch (tag) {
   1.517 +        case CONSTANT_UTF8: {
   1.518 +            if (!textual) {
   1.519 +                return (String)x;
   1.520 +            }
   1.521 +            StringBuilder sb=new StringBuilder();
   1.522 +            String s=(String)x;
   1.523 +            for (int k=0; k<s.length(); k++) {
   1.524 +                char c=s.charAt(k);
   1.525 +                switch (c) {
   1.526 +                case '\\': sb.append('\\').append('\\'); break;
   1.527 +                case '\t': sb.append('\\').append('t'); break;
   1.528 +                case '\n': sb.append('\\').append('n'); break;
   1.529 +                case '\r': sb.append('\\').append('r'); break;
   1.530 +                case '\"': sb.append('\\').append('\"'); break;
   1.531 +                default: sb.append(c);
   1.532 +                }
   1.533 +            }
   1.534 +            return sb.toString();
   1.535 +        }
   1.536 +        case CONSTANT_DOUBLE: {
   1.537 +            Double d=(Double)x;
   1.538 +            String sd=d.toString();
   1.539 +            if (textual) {
   1.540 +                return sd;
   1.541 +            }
   1.542 +            return sd+"d";
   1.543 +        }
   1.544 +        case CONSTANT_FLOAT: {
   1.545 +            Float f=(Float)x;
   1.546 +            String sf=(f).toString();
   1.547 +            if (textual) {
   1.548 +                return sf;
   1.549 +            }
   1.550 +            return sf+"f";
   1.551 +        }
   1.552 +        case CONSTANT_LONG: {
   1.553 +            Long ln = (Long)x;
   1.554 +            if (textual) {
   1.555 +                return ln.toString();
   1.556 +            }
   1.557 +            return ln.toString()+'l';
   1.558 +        }
   1.559 +        case CONSTANT_INTEGER: {
   1.560 +            Integer in = (Integer)x;
   1.561 +            return in.toString();
   1.562 +        }
   1.563 +        case CONSTANT_CLASS:
   1.564 +            String jn = getClassName(cpx);
   1.565 +            if (textual) {
   1.566 +                if (refs != null) {
   1.567 +                    refs[0] = jn;
   1.568 +                }
   1.569 +                return jn;
   1.570 +            }
   1.571 +            return javaName(jn);
   1.572 +        case CONSTANT_STRING:
   1.573 +            String sv = stringValue(((CPX)x).cpx, textual);
   1.574 +            if (textual) {
   1.575 +                return '"' + sv + '"';
   1.576 +            } else {
   1.577 +                return sv;
   1.578 +            }
   1.579 +        case CONSTANT_FIELD:
   1.580 +        case CONSTANT_METHOD:
   1.581 +        case CONSTANT_INTERFACEMETHOD:
   1.582 +            //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
   1.583 +             return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
   1.584 +
   1.585 +        case CONSTANT_NAMEANDTYPE:
   1.586 +            return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
   1.587 +        default:
   1.588 +            return "UnknownTag"; //TBD
   1.589 +        }
   1.590 +    }
   1.591 +
   1.592 +    /**
   1.593 +     * Returns resolved java type name.
   1.594 +     */
   1.595 +    public String javaName(String name) {
   1.596 +        if( name==null) return "null";
   1.597 +        int len=name.length();
   1.598 +        if (len==0) return "\"\"";
   1.599 +        int cc='/';
   1.600 +    fullname: { // xxx/yyy/zzz
   1.601 +            int cp;
   1.602 +            for (int k=0; k<len; k += Character.charCount(cp)) {
   1.603 +                cp=name.codePointAt(k);
   1.604 +                if (cc=='/') {
   1.605 +                    if (!isJavaIdentifierStart(cp)) break fullname;
   1.606 +                } else if (cp!='/') {
   1.607 +                    if (!isJavaIdentifierPart(cp)) break fullname;
   1.608 +                }
   1.609 +                cc=cp;
   1.610 +            }
   1.611 +            return name;
   1.612 +        }
   1.613 +        return "\""+name+"\"";
   1.614 +    }
   1.615 +
   1.616 +    public String getName(int cpx) {
   1.617 +        String res;
   1.618 +        try {
   1.619 +            return javaName((String)cpool[cpx]); //.replace('/','.');
   1.620 +        } catch (ArrayIndexOutOfBoundsException e) {
   1.621 +            return "<invalid constant pool index:"+cpx+">";
   1.622 +        } catch (ClassCastException e) {
   1.623 +            return "<invalid constant pool ref:"+cpx+">";
   1.624 +        }
   1.625 +    }
   1.626 +
   1.627 +    /**
   1.628 +     * Returns unqualified class name.
   1.629 +     */
   1.630 +    public String getShortClassName(int cpx) {
   1.631 +        String classname=javaName(getClassName(cpx));
   1.632 +        pkgPrefixLen=classname.lastIndexOf("/")+1;
   1.633 +        if (pkgPrefixLen!=0) {
   1.634 +            pkgPrefix=classname.substring(0,pkgPrefixLen);
   1.635 +            if (classname.startsWith(pkgPrefix)) {
   1.636 +                return classname.substring(pkgPrefixLen);
   1.637 +            }
   1.638 +        }
   1.639 +        return classname;
   1.640 +    }
   1.641 +
   1.642 +    /**
   1.643 +     * Returns source file name.
   1.644 +     */
   1.645 +    public String getSourceName(){
   1.646 +        return getName(source_cpx);
   1.647 +    }
   1.648 +
   1.649 +    /**
   1.650 +     * Returns package name.
   1.651 +     */
   1.652 +    public String getPkgName(){
   1.653 +        String classname=getClassName(this_class);
   1.654 +        pkgPrefixLen=classname.lastIndexOf("/")+1;
   1.655 +        if (pkgPrefixLen!=0) {
   1.656 +            pkgPrefix=classname.substring(0,pkgPrefixLen);
   1.657 +            return("package  "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
   1.658 +        }else return null;
   1.659 +    }
   1.660 +
   1.661 +    /**
   1.662 +     * Returns total constant pool entry count.
   1.663 +     */
   1.664 +    public int getCpoolCount(){
   1.665 +        return cpool_count;
   1.666 +    }
   1.667 +
   1.668 +    /**
   1.669 +     * Returns minor version of class file.
   1.670 +     */
   1.671 +    public int getMinor_version(){
   1.672 +        return minor_version;
   1.673 +    }
   1.674 +
   1.675 +    /**
   1.676 +     * Returns major version of class file.
   1.677 +     */
   1.678 +    public int getMajor_version(){
   1.679 +        return major_version;
   1.680 +    }
   1.681 +
   1.682 +    private boolean isJavaIdentifierStart(int cp) {
   1.683 +        return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
   1.684 +    }
   1.685 +
   1.686 +    private boolean isJavaIdentifierPart(int cp) {
   1.687 +        return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
   1.688 +    }
   1.689 +
   1.690 +    public String[] getNameAndType(int indx) {
   1.691 +        return getNameAndType(indx, 0, new String[2]);
   1.692 +    }
   1.693 +    
   1.694 +    private String[] getNameAndType(int indx, int at, String[] arr) {
   1.695 +        CPX2 c2 = getCpoolEntry(indx);
   1.696 +        arr[at] = StringValue(c2.cpx1);
   1.697 +        arr[at + 1] = StringValue(c2.cpx2);
   1.698 +        return arr;
   1.699 +    }
   1.700 +
   1.701 +    public String[] getFieldInfoName(int indx) {
   1.702 +        CPX2 c2 = getCpoolEntry(indx);
   1.703 +        String[] arr = new String[3];
   1.704 +        arr[0] = getClassName(c2.cpx1);
   1.705 +        return getNameAndType(c2.cpx2, 1, arr);
   1.706 +    }
   1.707 +
   1.708 +    static byte[] findAttr(String n, AttrData[] attrs) {
   1.709 +        for (AttrData ad : attrs) {
   1.710 +            if (n.equals(ad.getAttrName())) {
   1.711 +                return ad.getData();
   1.712 +            }
   1.713 +        }
   1.714 +        return null;
   1.715 +    }
   1.716 +}