1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/javap/src/main/java/org/apidesign/javap/ClassData.java Fri Nov 16 08:08:36 2012 +0100
1.3 @@ -0,0 +1,718 @@
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 + /**
1.334 + * Returns true if it is a class
1.335 + */
1.336 + public boolean isClass() {
1.337 + if((access & ACC_INTERFACE) == 0) return true;
1.338 + return false;
1.339 + }
1.340 +
1.341 + /**
1.342 + * Returns true if it is a interface.
1.343 + */
1.344 + public boolean isInterface(){
1.345 + if((access & ACC_INTERFACE) != 0) return true;
1.346 + return false;
1.347 + }
1.348 +
1.349 + /**
1.350 + * Returns true if this member is public, false otherwise.
1.351 + */
1.352 + public boolean isPublic(){
1.353 + return (access & ACC_PUBLIC) != 0;
1.354 + }
1.355 +
1.356 + /**
1.357 + * Returns the access of this class or interface.
1.358 + */
1.359 + public String[] getAccess(){
1.360 + Vector v = new Vector();
1.361 + if ((access & ACC_PUBLIC) !=0) v.addElement("public");
1.362 + if ((access & ACC_FINAL) !=0) v.addElement("final");
1.363 + if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
1.364 + String[] accflags = new String[v.size()];
1.365 + v.copyInto(accflags);
1.366 + return accflags;
1.367 + }
1.368 +
1.369 + /**
1.370 + * Returns list of innerclasses.
1.371 + */
1.372 + public InnerClassData[] getInnerClasses(){
1.373 + return innerClasses;
1.374 + }
1.375 +
1.376 + /**
1.377 + * Returns list of attributes.
1.378 + */
1.379 + final AttrData[] getAttributes(){
1.380 + return attrs;
1.381 + }
1.382 +
1.383 + public byte[] findAnnotationData(boolean classRetention) {
1.384 + String n = classRetention ?
1.385 + "RuntimeInvisibleAnnotations" : // NOI18N
1.386 + "RuntimeVisibleAnnotations"; // NOI18N
1.387 + return findAttr(n, attrs);
1.388 + }
1.389 +
1.390 + /**
1.391 + * Returns true if superbit is set.
1.392 + */
1.393 + public boolean isSuperSet(){
1.394 + if ((access & ACC_SUPER) !=0) return true;
1.395 + return false;
1.396 + }
1.397 +
1.398 + /**
1.399 + * Returns super class name.
1.400 + */
1.401 + public String getSuperClassName(){
1.402 + String res=null;
1.403 + if (super_class==0) {
1.404 + return res;
1.405 + }
1.406 + int scpx;
1.407 + try {
1.408 + if (tags[super_class]!=CONSTANT_CLASS) {
1.409 + return res; //"<CP["+cpx+"] is not a Class> ";
1.410 + }
1.411 + scpx=((CPX)cpool[super_class]).cpx;
1.412 + } catch (ArrayIndexOutOfBoundsException e) {
1.413 + return res; // "#"+cpx+"// invalid constant pool index";
1.414 + } catch (Throwable e) {
1.415 + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
1.416 + }
1.417 +
1.418 + try {
1.419 + return (String)(cpool[scpx]);
1.420 + } catch (ArrayIndexOutOfBoundsException e) {
1.421 + return res; // "class #"+scpx+"// invalid constant pool index";
1.422 + } catch (ClassCastException e) {
1.423 + return res; // "class #"+scpx+"// invalid constant pool reference";
1.424 + } catch (Throwable e) {
1.425 + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
1.426 + }
1.427 + }
1.428 +
1.429 + /**
1.430 + * Returns list of super interfaces.
1.431 + */
1.432 + public String[] getSuperInterfaces(){
1.433 + String interfacenames[] = new String[interfaces.length];
1.434 + int interfacecpx = -1;
1.435 + for(int i = 0; i < interfaces.length; i++){
1.436 + interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
1.437 + interfacenames[i] = (String)(cpool[interfacecpx]);
1.438 + }
1.439 + return interfacenames;
1.440 + }
1.441 +
1.442 + /**
1.443 + * Returns string at prticular constant pool index.
1.444 + */
1.445 + public String getStringValue(int cpoolx) {
1.446 + try {
1.447 + return ((String)cpool[cpoolx]);
1.448 + } catch (ArrayIndexOutOfBoundsException e) {
1.449 + return "//invalid constant pool index:"+cpoolx;
1.450 + } catch (ClassCastException e) {
1.451 + return "//invalid constant pool ref:"+cpoolx;
1.452 + }
1.453 + }
1.454 +
1.455 + /**
1.456 + * Returns list of field info.
1.457 + */
1.458 + public FieldData[] getFields(){
1.459 + return fields;
1.460 + }
1.461 +
1.462 + /**
1.463 + * Returns list of method info.
1.464 + */
1.465 + public MethodData[] getMethods(){
1.466 + return methods;
1.467 + }
1.468 +
1.469 + /**
1.470 + * Returns constant pool entry at that index.
1.471 + */
1.472 + public CPX2 getCpoolEntry(int cpx){
1.473 + return ((CPX2)(cpool[cpx]));
1.474 + }
1.475 +
1.476 + public Object getCpoolEntryobj(int cpx){
1.477 + return (cpool[cpx]);
1.478 + }
1.479 +
1.480 + /**
1.481 + * Returns index of this class.
1.482 + */
1.483 + public int getthis_cpx(){
1.484 + return this_class;
1.485 + }
1.486 +
1.487 + public String TagString (int tag) {
1.488 + String res=Tables.tagName(tag);
1.489 + if (res==null) return "BOGUS_TAG:"+tag;
1.490 + return res;
1.491 + }
1.492 +
1.493 + /**
1.494 + * Returns string at that index.
1.495 + */
1.496 + public String StringValue(int cpx) {
1.497 + return stringValue(cpx, false);
1.498 + }
1.499 + public String stringValue(int cpx, boolean textual) {
1.500 + if (cpx==0) return "#0";
1.501 + int tag;
1.502 + Object x;
1.503 + String suffix="";
1.504 + try {
1.505 + tag=tags[cpx];
1.506 + x=cpool[cpx];
1.507 + } catch (IndexOutOfBoundsException e) {
1.508 + return "<Incorrect CP index:"+cpx+">";
1.509 + }
1.510 +
1.511 + if (x==null) return "<NULL>";
1.512 + switch (tag) {
1.513 + case CONSTANT_UTF8: {
1.514 + if (!textual) {
1.515 + return (String)x;
1.516 + }
1.517 + StringBuilder sb=new StringBuilder();
1.518 + String s=(String)x;
1.519 + for (int k=0; k<s.length(); k++) {
1.520 + char c=s.charAt(k);
1.521 + switch (c) {
1.522 + case '\\': sb.append('\\').append('\\'); break;
1.523 + case '\t': sb.append('\\').append('t'); break;
1.524 + case '\n': sb.append('\\').append('n'); break;
1.525 + case '\r': sb.append('\\').append('r'); break;
1.526 + case '\"': sb.append('\\').append('\"'); break;
1.527 + default: sb.append(c);
1.528 + }
1.529 + }
1.530 + return sb.toString();
1.531 + }
1.532 + case CONSTANT_DOUBLE: {
1.533 + Double d=(Double)x;
1.534 + String sd=d.toString();
1.535 + if (textual) {
1.536 + return sd;
1.537 + }
1.538 + return sd+"d";
1.539 + }
1.540 + case CONSTANT_FLOAT: {
1.541 + Float f=(Float)x;
1.542 + String sf=(f).toString();
1.543 + if (textual) {
1.544 + return sf;
1.545 + }
1.546 + return sf+"f";
1.547 + }
1.548 + case CONSTANT_LONG: {
1.549 + Long ln = (Long)x;
1.550 + if (textual) {
1.551 + return ln.toString();
1.552 + }
1.553 + return ln.toString()+'l';
1.554 + }
1.555 + case CONSTANT_INTEGER: {
1.556 + Integer in = (Integer)x;
1.557 + return in.toString();
1.558 + }
1.559 + case CONSTANT_CLASS:
1.560 + if (textual) {
1.561 + return "new java_lang_Class"; // XXX temporary JS
1.562 + }
1.563 + return javaName(getClassName(cpx));
1.564 + case CONSTANT_STRING:
1.565 + String sv = stringValue(((CPX)x).cpx, textual);
1.566 + if (textual) {
1.567 + return '"' + sv + '"';
1.568 + } else {
1.569 + return sv;
1.570 + }
1.571 + case CONSTANT_FIELD:
1.572 + case CONSTANT_METHOD:
1.573 + case CONSTANT_INTERFACEMETHOD:
1.574 + //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
1.575 + return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
1.576 +
1.577 + case CONSTANT_NAMEANDTYPE:
1.578 + return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
1.579 + default:
1.580 + return "UnknownTag"; //TBD
1.581 + }
1.582 + }
1.583 +
1.584 + /**
1.585 + * Returns resolved java type name.
1.586 + */
1.587 + public String javaName(String name) {
1.588 + if( name==null) return "null";
1.589 + int len=name.length();
1.590 + if (len==0) return "\"\"";
1.591 + int cc='/';
1.592 + fullname: { // xxx/yyy/zzz
1.593 + int cp;
1.594 + for (int k=0; k<len; k += Character.charCount(cp)) {
1.595 + cp=name.codePointAt(k);
1.596 + if (cc=='/') {
1.597 + if (!isJavaIdentifierStart(cp)) break fullname;
1.598 + } else if (cp!='/') {
1.599 + if (!isJavaIdentifierPart(cp)) break fullname;
1.600 + }
1.601 + cc=cp;
1.602 + }
1.603 + return name;
1.604 + }
1.605 + return "\""+name+"\"";
1.606 + }
1.607 +
1.608 + public String getName(int cpx) {
1.609 + String res;
1.610 + try {
1.611 + return javaName((String)cpool[cpx]); //.replace('/','.');
1.612 + } catch (ArrayIndexOutOfBoundsException e) {
1.613 + return "<invalid constant pool index:"+cpx+">";
1.614 + } catch (ClassCastException e) {
1.615 + return "<invalid constant pool ref:"+cpx+">";
1.616 + }
1.617 + }
1.618 +
1.619 + /**
1.620 + * Returns unqualified class name.
1.621 + */
1.622 + public String getShortClassName(int cpx) {
1.623 + String classname=javaName(getClassName(cpx));
1.624 + pkgPrefixLen=classname.lastIndexOf("/")+1;
1.625 + if (pkgPrefixLen!=0) {
1.626 + pkgPrefix=classname.substring(0,pkgPrefixLen);
1.627 + if (classname.startsWith(pkgPrefix)) {
1.628 + return classname.substring(pkgPrefixLen);
1.629 + }
1.630 + }
1.631 + return classname;
1.632 + }
1.633 +
1.634 + /**
1.635 + * Returns source file name.
1.636 + */
1.637 + public String getSourceName(){
1.638 + return getName(source_cpx);
1.639 + }
1.640 +
1.641 + /**
1.642 + * Returns package name.
1.643 + */
1.644 + public String getPkgName(){
1.645 + String classname=getClassName(this_class);
1.646 + pkgPrefixLen=classname.lastIndexOf("/")+1;
1.647 + if (pkgPrefixLen!=0) {
1.648 + pkgPrefix=classname.substring(0,pkgPrefixLen);
1.649 + return("package "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
1.650 + }else return null;
1.651 + }
1.652 +
1.653 + /**
1.654 + * Returns total constant pool entry count.
1.655 + */
1.656 + public int getCpoolCount(){
1.657 + return cpool_count;
1.658 + }
1.659 +
1.660 + public String StringTag(int cpx) {
1.661 + byte tag=0;
1.662 + String str=null;
1.663 + try {
1.664 + if (cpx==0) throw new IndexOutOfBoundsException();
1.665 + tag=tags[cpx];
1.666 + return TagString(tag);
1.667 + } catch (IndexOutOfBoundsException e) {
1.668 + str="Incorrect CP index:"+cpx;
1.669 + }
1.670 + return str;
1.671 + }
1.672 +
1.673 + /**
1.674 + * Returns minor version of class file.
1.675 + */
1.676 + public int getMinor_version(){
1.677 + return minor_version;
1.678 + }
1.679 +
1.680 + /**
1.681 + * Returns major version of class file.
1.682 + */
1.683 + public int getMajor_version(){
1.684 + return major_version;
1.685 + }
1.686 +
1.687 + private boolean isJavaIdentifierStart(int cp) {
1.688 + return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
1.689 + }
1.690 +
1.691 + private boolean isJavaIdentifierPart(int cp) {
1.692 + return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
1.693 + }
1.694 +
1.695 + public String[] getNameAndType(int indx) {
1.696 + return getNameAndType(indx, 0, new String[2]);
1.697 + }
1.698 +
1.699 + private String[] getNameAndType(int indx, int at, String[] arr) {
1.700 + CPX2 c2 = getCpoolEntry(indx);
1.701 + arr[at] = StringValue(c2.cpx1);
1.702 + arr[at + 1] = StringValue(c2.cpx2);
1.703 + return arr;
1.704 + }
1.705 +
1.706 + public String[] getFieldInfoName(int indx) {
1.707 + CPX2 c2 = getCpoolEntry(indx);
1.708 + String[] arr = new String[3];
1.709 + arr[0] = getClassName(c2.cpx1);
1.710 + return getNameAndType(c2.cpx2, 1, arr);
1.711 + }
1.712 +
1.713 + static byte[] findAttr(String n, AttrData[] attrs) {
1.714 + for (AttrData ad : attrs) {
1.715 + if (n.equals(ad.getAttrName())) {
1.716 + return ad.getData();
1.717 + }
1.718 + }
1.719 + return null;
1.720 + }
1.721 +}