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