private final Type.Class[] interfaces;
private final short minor;
private final short major;
- final int flags;
private final Vector fields = new Vector();
public final Vector methods = new Vector();
- private final AttrGen attributes;
-
static String flagsToString(int flags, boolean isClass) {
StringBuffer sb = new StringBuffer(32);
if ((flags & PUBLIC) != 0) sb.append("public ");
for(int i=0; i<interfaces.length; i++) sb.append((i==0?" ":", ")+interfaces[i].debugToString());
sb.append(" {");
sb.append(" // v"+major+"."+minor);
- ConstantPool.Utf8Key sourceFile = (ConstantPool.Utf8Key) attributes.get("SourceFile");
+ ConstantPool.Utf8Key sourceFile = (ConstantPool.Utf8Key) attrs.get("SourceFile");
if (sourceFile != null) sb.append(" from " + sourceFile.s);
sb.append("\n");
for(int i=0; i<fields.size(); i++) {
public ClassFile(Type.Class thisType, Type.Class superType, int flags) { this(thisType, superType, flags, null); }
public ClassFile(Type.Class thisType, Type.Class superType, int flags, Type.Class[] interfaces) {
- thisType.super();
+ thisType.super(flags, new AttrGen());
this.thisType = thisType;
- if((flags & ~(PUBLIC|FINAL|SUPER|INTERFACE|ABSTRACT)) != 0)
- throw new IllegalArgumentException("invalid flags");
this.superType = superType;
this.interfaces = interfaces;
- this.flags = flags;
this.minor = 3;
this.major = 45;
- this.attributes = new AttrGen();
}
/** Adds a new method to this class
/** Sets the source value of the SourceFile attribute of this class
@param sourceFile The string to be uses as the SourceFile of this class
*/
- public void setSourceFile(String sourceFile) { attributes.put("SourceFile", new ConstantPool.Utf8Key(sourceFile)); }
+ public void setSourceFile(String sourceFile) { attrs.put("SourceFile", new ConstantPool.Utf8Key(sourceFile)); }
/** Writes the classfile data to the file specifed
@see ClassFile#dump(OutputStream)
if(interfaces != null) for(int i=0;i<interfaces.length;i++) cp.add(interfaces[i]);
for(int i=0;i<methods.size();i++) ((MethodGen)methods.elementAt(i)).finish(cp);
for(int i=0;i<fields.size();i++) ((FieldGen)fields.elementAt(i)).finish(cp);
- attributes.finish(cp);
+ attrs.finish(cp);
cp.optimize();
cp.seal();
o.writeShort(methods.size()); // methods_count
for(int i=0;i<methods.size();i++) ((MethodGen)methods.elementAt(i)).dump(o,cp); // methods
- attributes.dump(o,cp); // attributes
+ attrs.dump(o,cp); // attributes
}
public static ClassFile read(String s) throws IOException { return read(new File(s)); }
}
private ClassFile(int magic, short minor, short major, ConstantPool cp, short flags,
Type.Class thisType, DataInput i, boolean ssa) throws IOException {
- thisType.super();
+ thisType.super(flags, null);
if (magic != 0xcafebabe) throw new ClassReadExn("invalid magic: " + Long.toString(0xffffffffL & magic, 16));
this.minor = minor;
this.major = major;
- this.flags = flags;
- if((flags & ~(PUBLIC|FINAL|SUPER|INTERFACE|ABSTRACT)) != 0)
- throw new ClassReadExn("invalid flags: " + Integer.toString(flags,16));
this.thisType = thisType;
superType = (Type.Class) cp.getKeyByIndex(i.readShort());
interfaces = new Type.Class[i.readShort()];
for(int j=0; j<interfaces.length; j++) interfaces[j] = (Type.Class) cp.getKeyByIndex(i.readShort());
int numFields = i.readShort();
- for(int j=0; j<numFields; j++) fields.addElement(new FieldGen(this, i, cp));
+ for(int j=0; j<numFields; j++) fields.addElement(new FieldGen(this.getType(), i, cp));
int numMethods = i.readShort();
for(int j=0; j<numMethods; j++) methods.addElement(ssa
? new JSSA(this.getType(), i, cp)
: new MethodGen(this.getType(), i, cp));
- attributes = new AttrGen(i, cp);
+ readAttributes(i, cp);
// FEATURE: Support these
// NOTE: Until we can support them properly we HAVE to delete them,
// they'll be incorrect after we rewrite the constant pool, etc
- attributes.remove("InnerClasses");
+ attrs.remove("InnerClasses");
}
/** Thrown when class generation fails for a reason not under the control of the user
/** Class representing a field in a generated classfile
@see ClassFile#addField */
public class FieldGen extends Type.Class.Field.Body {
- private final ClassFile.AttrGen attrs;
StringBuffer debugToString(StringBuffer sb) {
sb.append(ClassFile.flagsToString(flags, false));
sb.append(getField().getType().debugToString());
sb.append(" ");
sb.append(getField().getName());
- if(attrs.contains("ConstantValue"))
- sb.append(" = \"").append(attrs.get("ConstantValue")).append("\"");
+ if (attrs.contains("ConstantValue")) sb.append(" = \"").append(attrs.get("ConstantValue")).append("\"");
sb.append(";");
return sb;
}
- FieldGen(ClassFile cf, DataInput in, ConstantPool cp) throws IOException {
+ FieldGen(Type.Class c, DataInput in, ConstantPool cp) throws IOException {
this(in.readShort(),
- cf.getType().field(cp.getUtf8KeyByIndex(in.readShort()),
- Type.fromDescriptor(cp.getUtf8KeyByIndex(in.readShort()))));
+ c.field(cp.getUtf8KeyByIndex(in.readShort()),
+ Type.fromDescriptor(cp.getUtf8KeyByIndex(in.readShort()))),
+ new ClassFile.AttrGen(in, cp));
}
- private FieldGen(int flags, Type.Class.Field field) { this(field, flags); }
+ private FieldGen(int flags, Type.Class.Field field, ClassFile.AttrGen attrs) { this(field, flags, attrs); }
FieldGen(Type.Class.Field field, int flags) { this(field, flags, new ClassFile.AttrGen()); }
- FieldGen(Type.Class.Field field, int flags, ClassFile.AttrGen attrs) {
- field.super(flags);
- this.attrs = attrs;
- }
+ FieldGen(Type.Class.Field field, int flags, ClassFile.AttrGen attrs) { field.super(flags, attrs); }
/** Sets the ContantValue attribute for this field.
@param val The value to set this field to. Must be an Integer, Long, Float, Double, or String */
--- /dev/null
+package org.ibex.classgen;
+import java.io.*;
+
+public abstract class HasAttributes extends HasFlags {
+ public ClassFile.AttrGen attrs;
+ public HasAttributes(int flags, ClassFile.AttrGen attrs) { super(flags); this.attrs = attrs; }
+ public void readAttributes(DataInput i, ConstantPool cp) throws IOException { attrs = new ClassFile.AttrGen(i, cp); }
+}
package org.ibex.classgen;
public abstract class HasFlags implements CGConst {
- public abstract int getFlags();
+
+ public HasFlags(int flags) { this.flags = flags; }
+
+ public final int flags;
+ public int getFlags() { return flags; }
public boolean isPublic() { return (getFlags() & PUBLIC) != 0; }
public boolean isPrivate() { return (getFlags() & PRIVATE) != 0; }
public boolean isProtected() { return (getFlags() & PROTECTED) != 0; }
public boolean isStatic() { return (getFlags() & STATIC) != 0; }
public boolean isFinal() { return (getFlags() & FINAL) != 0; }
+ public boolean isInterface() { return (getFlags() & INTERFACE) != 0; }
public boolean isAbstract() { return (getFlags() & ABSTRACT) != 0; }
public boolean isNative() { return (getFlags() & NATIVE) != 0; }
- public boolean isConcrete() { return !isAbstract() && !isNative(); }
+ public boolean isConcrete() { return !isAbstract() && !isNative() && !isInterface(); }
public boolean isVolatile() { return (getFlags() & VOLATILE) != 0; }
public boolean isTransient() { return (getFlags() & TRANSIENT) != 0; }
/** A class representing a method in a generated classfile
@see ClassFile#addMethod */
-public class MethodGen extends Type.Class.Method.Body implements CGConst {
+public class MethodGen extends Type.Class.Method.Body {
private final static boolean EMIT_NOPS = false;
private static final int NO_CODE = -1;
public final Type.Class.Method method;
- private final int flags;
- private final ClassFile.AttrGen attrs;
private final ClassFile.AttrGen codeAttrs;
private final Vector exnTable = new Vector();
private final Hashtable thrownExceptions = new Hashtable();
// Constructors //////////////////////////////////////////////////////////////////////////////
MethodGen(Type.Class.Method method, int flags) {
- method.super();
- if ((flags & ~VALID_METHOD_FLAGS) != 0) throw new IllegalArgumentException("invalid flags");
+ method.super(flags, new ClassFile.AttrGen());
this.method = method;
- this.flags = flags;
-
- attrs = new ClassFile.AttrGen();
codeAttrs = new ClassFile.AttrGen();
-
- if (((flags & INTERFACE) != 0) || (flags & (ABSTRACT|NATIVE)) != 0) size = capacity = -1;
-
+ if (!isConcrete()) size = capacity = -1;
maxLocals = Math.max(method.getNumArgs() + (flags&STATIC)==0 ? 1 : 0, 4);
}
this(flags, name, c.method(name+cp.getUtf8KeyByIndex(in.readShort())), c, in, cp); }
private MethodGen(short flags, String name, Type.Class.Method m,
Type.Class c, DataInput in, ConstantPool cp) throws IOException {
- m.super();
- this.flags = flags;
- if ((flags & ~VALID_METHOD_FLAGS) != 0) throw new ClassFile.ClassReadExn("invalid flags");
+ m.super(flags, new ClassFile.AttrGen(in,cp));
this.method = m;
- this.attrs = new ClassFile.AttrGen(in,cp);
- if ((flags & (NATIVE|ABSTRACT))==0) {
+ if (isConcrete()) {
byte[] codeAttr = (byte[]) attrs.get("Code");
if (codeAttr == null) throw new ClassFile.ClassReadExn("code attr expected");
DataInputStream ci = new DataInputStream(new ByteArrayInputStream(codeAttr));
return a;
}
- public Field field(String name, Type type) { return new Field(name, type); }
- public abstract class Body extends HasFlags {
+ public abstract class Body extends HasAttributes {
+ public Body(int flags, ClassFile.AttrGen attrs) {
+ super(flags, attrs);
+ if ((flags & ~(PUBLIC|FINAL|SUPER|INTERFACE|ABSTRACT)) != 0)
+ throw new IllegalArgumentException("invalid flags: " + Integer.toString(flags,16));
+ }
}
+ public Field field(String name, Type type) { return new Field(name, type); }
+
public Method method(String name, Type returnType, Type[] argTypes) { return new Method(name, returnType, argTypes); }
public Method method(String leftCrap, String rightCrap) { return method(leftCrap+rightCrap); }
public String getTypeDescriptor() { return type.getDescriptor(); }
public Type getType() { return type; }
public String debugToString() { return getDeclaringClass().debugToString()+"."+name+"["+type.debugToString()+"]"; }
- public class Body extends HasFlags {
- public final int flags;
- public Body(int flags) {
+ public class Body extends HasAttributes {
+ public Field getField() { return Field.this; }
+ public Body(int flags, ClassFile.AttrGen attrs) {
+ super(flags, attrs);
if ((flags & ~VALID_FIELD_FLAGS) != 0) throw new IllegalArgumentException("invalid flags");
- this.flags = flags;
}
- public int getFlags() { return flags; }
- public Field getField() { return Field.this; }
}
}
sb.append(returnType.getDescriptor());
return sb.toString();
}
- public abstract class Body extends HasFlags {
+ public abstract class Body extends HasAttributes {
public abstract java.util.Hashtable getThrownExceptions();
public abstract void debugBodyToString(StringBuffer sb);
+ public Body(int flags, ClassFile.AttrGen attrs) {
+ super(flags, attrs);
+ if ((flags & ~VALID_METHOD_FLAGS) != 0) throw new IllegalArgumentException("invalid flags");
+ }
public void debugToString(StringBuffer sb, String constructorName) {
int flags = getFlags();
sb.append(" ").append(ClassFile.flagsToString(flags,false));