00001 package de.fub.bytecode.classfile;
00002
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.Repository;
00005 import java.io.*;
00006 import java.util.StringTokenizer;
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 public class JavaClass extends AccessFlags implements Cloneable {
00018 private String file_name;
00019 private String package_name;
00020 private String source_file_name = "<Unknown>";
00021 private int class_name_index;
00022 private int superclass_name_index;
00023 private String class_name;
00024 private String superclass_name;
00025 private int major, minor;
00026 private ConstantPool constant_pool;
00027 private int[] interfaces;
00028 private String[] interface_names;
00029 private Field[] fields;
00030 private Method[] methods;
00031 private Attribute[] attributes;
00032 private byte source = HEAP;
00033
00034 public static final byte HEAP = 1;
00035 public static final byte FILE = 2;
00036 public static final byte ZIP = 3;
00037
00038 static boolean debug = false;
00039 static char sep = '/';
00040
00041 static {
00042
00043 String debug = System.getProperty("JavaClass.debug");
00044
00045 if(debug != null)
00046 JavaClass.debug = new Boolean(debug).booleanValue();
00047
00048
00049 String sep = System.getProperty("file.separator");
00050
00051 if(sep != null)
00052 try {
00053 JavaClass.sep = sep.charAt(0);
00054 } catch(StringIndexOutOfBoundsException e) {}
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 public JavaClass(int class_name_index,
00073 int superclass_name_index,
00074 String file_name,
00075 int major,
00076 int minor,
00077 int access_flags,
00078 ConstantPool constant_pool,
00079 int[] interfaces,
00080 Field[] fields,
00081 Method[] methods,
00082 Attribute[] attributes) {
00083 this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
00084 constant_pool, interfaces, fields, methods, attributes, HEAP);
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 public JavaClass(int class_name_index,
00103 int superclass_name_index,
00104 String file_name,
00105 int major,
00106 int minor,
00107 int access_flags,
00108 ConstantPool constant_pool,
00109 int[] interfaces,
00110 Field[] fields,
00111 Method[] methods,
00112 Attribute[] attributes,
00113 byte source)
00114 {
00115 if(interfaces == null)
00116 interfaces = new int[0];
00117 if(attributes == null)
00118 this.attributes = new Attribute[0];
00119 if(fields == null)
00120 fields = new Field[0];
00121 if(methods == null)
00122 methods = new Method[0];
00123
00124 this.class_name_index = class_name_index;
00125 this.superclass_name_index = superclass_name_index;
00126 this.file_name = file_name;
00127 this.major = major;
00128 this.minor = minor;
00129 this.access_flags = access_flags;
00130 this.constant_pool = constant_pool;
00131 this.interfaces = interfaces;
00132 this.fields = fields;
00133 this.methods = methods;
00134 this.attributes = attributes;
00135 this.source = source;
00136
00137
00138 for(int i=0; i < attributes.length; i++) {
00139 if(attributes[i] instanceof SourceFile) {
00140 source_file_name = ((SourceFile)attributes[i]).getSourceFileName();
00141 break;
00142 }
00143 }
00144
00145
00146 ConstantUtf8 name;
00147
00148
00149
00150
00151
00152 class_name = constant_pool.getConstantString(class_name_index,
00153 Constants.CONSTANT_Class);
00154 class_name = Utility.compactClassName(class_name, false);
00155
00156 int index = class_name.lastIndexOf('.');
00157 if(index < 0)
00158 package_name = "";
00159 else
00160 package_name = class_name.substring(0, index);
00161
00162 if(superclass_name_index > 0) {
00163 superclass_name = constant_pool.getConstantString(superclass_name_index,
00164 Constants.CONSTANT_Class);
00165 superclass_name = Utility.compactClassName(superclass_name, false);
00166 }
00167 else
00168 superclass_name = "java.lang.Object";
00169
00170 interface_names = new String[interfaces.length];
00171 for(int i=0; i < interfaces.length; i++) {
00172 String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
00173 interface_names[i] = Utility.compactClassName(str, false);
00174 }
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 public void accept(Visitor v) {
00184 v.visitJavaClass(this);
00185 }
00186
00187
00188
00189 public JavaClass copy() {
00190 JavaClass c = null;
00191
00192 try {
00193 c = (JavaClass)clone();
00194 } catch(CloneNotSupportedException e) {}
00195
00196 c.constant_pool = constant_pool.copy();
00197 c.interfaces = (int[])interfaces.clone();
00198 c.interface_names = (String[])interface_names.clone();
00199
00200 c.fields = new Field[fields.length];
00201 for(int i=0; i < fields.length; i++)
00202 c.fields[i] = fields[i].copy(c.constant_pool);
00203
00204 c.methods = new Method[methods.length];
00205 for(int i=0; i < methods.length; i++)
00206 c.methods[i] = methods[i].copy(c.constant_pool);
00207
00208 c.attributes = new Attribute[attributes.length];
00209 for(int i=0; i < attributes.length; i++)
00210 c.attributes[i] = attributes[i].copy(c.constant_pool);
00211
00212 return c;
00213 }
00214
00215
00216 static final void Debug(String str) {
00217 if(debug)
00218 System.out.println(str);
00219 }
00220
00221
00222
00223
00224
00225
00226 public void dump(DataOutputStream file) throws IOException
00227 {
00228 file.writeInt(0xcafebabe);
00229 file.writeShort(minor);
00230 file.writeShort(major);
00231
00232 constant_pool.dump(file);
00233
00234 file.writeShort(access_flags);
00235 file.writeShort(class_name_index);
00236 file.writeShort(superclass_name_index);
00237
00238 file.writeShort(interfaces.length);
00239 for(int i=0; i < interfaces.length; i++)
00240 file.writeShort(interfaces[i]);
00241
00242 file.writeShort(fields.length);
00243 for(int i=0; i < fields.length; i++)
00244 fields[i].dump(file);
00245
00246 file.writeShort(methods.length);
00247 for(int i=0; i < methods.length; i++)
00248 methods[i].dump(file);
00249
00250 if(attributes != null) {
00251 file.writeShort(attributes.length);
00252 for(int i=0; i < attributes.length; i++)
00253 attributes[i].dump(file);
00254 }
00255 else
00256 file.writeShort(0);
00257
00258 file.close();
00259 }
00260
00261
00262
00263
00264
00265
00266 public void dump(File file) throws IOException
00267 {
00268 String parent = file.getParent();
00269
00270 if(parent != null) {
00271 File dir = new File(parent);
00272
00273 if(dir != null)
00274 dir.mkdirs();
00275 }
00276
00277 dump(new DataOutputStream(new FileOutputStream(file)));
00278 }
00279
00280
00281
00282
00283
00284
00285 public void dump(OutputStream file) throws IOException {
00286 dump(new DataOutputStream(file));
00287 }
00288
00289
00290
00291
00292
00293
00294 public void dump(String file_name) throws IOException
00295 {
00296 dump(new File(file_name));
00297 }
00298
00299
00300
00301 public Attribute[] getAttributes() { return attributes; }
00302
00303
00304
00305 public byte[] getBytes() {
00306 ByteArrayOutputStream s = new ByteArrayOutputStream();
00307 DataOutputStream ds = new DataOutputStream(s);
00308
00309 try {
00310 dump(ds);
00311 ds.close();
00312 } catch(IOException e) { e.printStackTrace(); }
00313
00314 return s.toByteArray();
00315 }
00316
00317
00318
00319 public String getClassName() { return class_name; }
00320
00321
00322
00323 public int getClassNameIndex() { return class_name_index; }
00324
00325
00326
00327 public ConstantPool getConstantPool() { return constant_pool; }
00328
00329
00330
00331 public Field[] getFields() { return fields; }
00332
00333
00334
00335 public String getFileName() { return file_name; }
00336
00337
00338
00339 public String[] getInterfaceNames() { return interface_names; }
00340
00341
00342
00343 public int[] getInterfaces() { return interfaces; }
00344
00345
00346
00347 public int getMajor() { return major; }
00348
00349
00350
00351 public Method[] getMethods() { return methods; }
00352
00353
00354
00355 public int getMinor() { return minor; }
00356
00357
00358
00359 public String getPackageName() { return package_name; }
00360
00361
00362 public final byte getSource() {
00363 return source;
00364 }
00365
00366
00367
00368 public String getSourceFileName() { return source_file_name; }
00369
00370
00371
00372 public String getSuperclassName() { return superclass_name; }
00373
00374
00375
00376 public int getSuperclassNameIndex() { return superclass_name_index; }
00377 private static final String indent(Object obj) {
00378 StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
00379 StringBuffer buf = new StringBuffer();
00380
00381 while(tok.hasMoreTokens())
00382 buf.append("\t" + tok.nextToken() + "\n");
00383
00384 return buf.toString();
00385 }
00386 public final boolean instanceOf(JavaClass super_class) {
00387 return Repository.instanceOf(this, super_class);
00388 }
00389 public final boolean isClass() {
00390 return (access_flags & Constants.ACC_INTERFACE) == 0;
00391 }
00392 public final boolean isSuper() {
00393 return (access_flags & Constants.ACC_SUPER) != 0;
00394 }
00395
00396
00397
00398 public void setAttributes(Attribute[] attributes) {
00399 this.attributes = attributes;
00400 }
00401
00402
00403
00404 public void setClassName(String class_name) {
00405 this.class_name = class_name;
00406 }
00407
00408
00409
00410 public void setClassNameIndex(int class_name_index) {
00411 this.class_name_index = class_name_index;
00412 }
00413
00414
00415
00416 public void setConstantPool(ConstantPool constant_pool) {
00417 this.constant_pool = constant_pool;
00418 }
00419
00420
00421
00422 public void setFields(Field[] fields) {
00423 this.fields = fields;
00424 }
00425
00426
00427
00428 public void setFileName(String file_name) {
00429 this.file_name = file_name;
00430 }
00431
00432
00433
00434 public void setInterfaceNames(String[] interface_names) {
00435 this.interface_names = interface_names;
00436 }
00437
00438
00439
00440 public void setInterfaces(int[] interfaces) {
00441 this.interfaces = interfaces;
00442 }
00443
00444
00445
00446 public void setMajor(int major) {
00447 this.major = major;
00448 }
00449
00450
00451
00452 public void setMethods(Method[] methods) {
00453 this.methods = methods;
00454 }
00455
00456
00457
00458 public void setMinor(int minor) {
00459 this.minor = minor;
00460 }
00461
00462
00463
00464 public void setSourceFileName(String source_file_name) {
00465 this.source_file_name = source_file_name;
00466 }
00467
00468
00469
00470 public void setSuperclassName(String superclass_name) {
00471 this.superclass_name = superclass_name;
00472 }
00473
00474
00475
00476 public void setSuperclassNameIndex(int superclass_name_index) {
00477 this.superclass_name_index = superclass_name_index;
00478 }
00479
00480
00481
00482 public String toString() {
00483 String access = Utility.accessToString(access_flags, true);
00484 access = access.equals("")? "" : (access + " ");
00485
00486 StringBuffer buf = new StringBuffer(access +
00487 Utility.classOrInterface(access_flags) +
00488 " " +
00489 class_name + " extends " +
00490 Utility.compactClassName(superclass_name,
00491 false) + '\n');
00492 int size = interfaces.length;
00493
00494 if(size > 0) {
00495 buf.append("implements\t\t");
00496
00497 for(int i=0; i < size; i++) {
00498 buf.append(interface_names[i]);
00499 if(i < size - 1)
00500 buf.append(", ");
00501 }
00502
00503 buf.append('\n');
00504 }
00505
00506 buf.append("filename\t\t" + file_name + '\n');
00507 buf.append("compiled from\t\t" + source_file_name + '\n');
00508 buf.append("compiler version\t" + major + "." + minor + '\n');
00509 buf.append("access flags\t\t" + access_flags + '\n');
00510 buf.append("constant pool\t\t" + constant_pool.getLength() + " entries\n");
00511 buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n");
00512
00513 if(attributes.length > 0) {
00514 buf.append("\nAttribute(s):\n");
00515 for(int i=0; i < attributes.length; i++)
00516 buf.append(indent(attributes[i]));
00517 }
00518
00519 if(fields.length > 0) {
00520 buf.append("\n" + fields.length + " fields:\n");
00521 for(int i=0; i < fields.length; i++)
00522 buf.append("\t" + fields[i] + '\n');
00523 }
00524
00525 if(methods.length > 0) {
00526 buf.append("\n" + methods.length + " methods:\n");
00527 for(int i=0; i < methods.length; i++)
00528 buf.append("\t" + methods[i] + '\n');
00529 }
00530
00531 return buf.toString();
00532 }
00533 }