|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.org.apache.bcel.internal.generic; |
|
|
|
import java.util.ArrayList; |
|
import java.util.List; |
|
|
|
import com.sun.org.apache.bcel.internal.Const; |
|
import com.sun.org.apache.bcel.internal.classfile.AccessFlags; |
|
import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; |
|
import com.sun.org.apache.bcel.internal.classfile.Annotations; |
|
import com.sun.org.apache.bcel.internal.classfile.Attribute; |
|
import com.sun.org.apache.bcel.internal.classfile.ConstantPool; |
|
import com.sun.org.apache.bcel.internal.classfile.Field; |
|
import com.sun.org.apache.bcel.internal.classfile.JavaClass; |
|
import com.sun.org.apache.bcel.internal.classfile.Method; |
|
import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleAnnotations; |
|
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleAnnotations; |
|
import com.sun.org.apache.bcel.internal.classfile.SourceFile; |
|
import com.sun.org.apache.bcel.internal.util.BCELComparator; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class ClassGen extends AccessFlags implements Cloneable { |
|
|
|
|
|
*/ |
|
private String class_name; |
|
private String super_class_name; |
|
private final String file_name; |
|
private int class_name_index = -1; |
|
private int superclass_name_index = -1; |
|
private int major = Const.MAJOR; |
|
private int minor = Const.MINOR; |
|
private ConstantPoolGen cp; |
|
|
|
private final List<Field> field_vec = new ArrayList<>(); |
|
private final List<Method> method_vec = new ArrayList<>(); |
|
private final List<Attribute> attribute_vec = new ArrayList<>(); |
|
private final List<String> interface_vec = new ArrayList<>(); |
|
private final List<AnnotationEntryGen> annotation_vec = new ArrayList<>(); |
|
|
|
private static BCELComparator _cmp = new BCELComparator() { |
|
|
|
@Override |
|
public boolean equals(final Object o1, final Object o2) { |
|
final ClassGen THIS = (ClassGen) o1; |
|
final ClassGen THAT = (ClassGen) o2; |
|
return THIS.getClassName().equals(THAT.getClassName()); |
|
} |
|
|
|
@Override |
|
public int hashCode(final Object o) { |
|
final ClassGen THIS = (ClassGen) o; |
|
return THIS.getClassName().hashCode(); |
|
} |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ClassGen(final String class_name, final String super_class_name, final String file_name, final int access_flags, |
|
final String[] interfaces, final ConstantPoolGen cp) { |
|
super(access_flags); |
|
this.class_name = class_name; |
|
this.super_class_name = super_class_name; |
|
this.file_name = file_name; |
|
this.cp = cp; |
|
|
|
if (file_name != null) { |
|
addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, cp.addUtf8(file_name), cp |
|
.getConstantPool())); |
|
} |
|
class_name_index = cp.addClass(class_name); |
|
superclass_name_index = cp.addClass(super_class_name); |
|
if (interfaces != null) { |
|
for (final String interface1 : interfaces) { |
|
addInterface(interface1); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ClassGen(final String class_name, final String super_class_name, final String file_name, final int access_flags, |
|
final String[] interfaces) { |
|
this(class_name, super_class_name, file_name, access_flags, interfaces, |
|
new ConstantPoolGen()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ClassGen(final JavaClass clazz) { |
|
super(clazz.getAccessFlags()); |
|
class_name_index = clazz.getClassNameIndex(); |
|
superclass_name_index = clazz.getSuperclassNameIndex(); |
|
class_name = clazz.getClassName(); |
|
super_class_name = clazz.getSuperclassName(); |
|
file_name = clazz.getSourceFileName(); |
|
cp = new ConstantPoolGen(clazz.getConstantPool()); |
|
major = clazz.getMajor(); |
|
minor = clazz.getMinor(); |
|
final Attribute[] attributes = clazz.getAttributes(); |
|
|
|
final AnnotationEntryGen[] annotations = unpackAnnotations(attributes); |
|
final Method[] methods = clazz.getMethods(); |
|
final Field[] fields = clazz.getFields(); |
|
final String[] interfaces = clazz.getInterfaceNames(); |
|
for (final String interface1 : interfaces) { |
|
addInterface(interface1); |
|
} |
|
for (final Attribute attribute : attributes) { |
|
if (!(attribute instanceof Annotations)) { |
|
addAttribute(attribute); |
|
} |
|
} |
|
for (final AnnotationEntryGen annotation : annotations) { |
|
addAnnotationEntry(annotation); |
|
} |
|
for (final Method method : methods) { |
|
addMethod(method); |
|
} |
|
for (final Field field : fields) { |
|
addField(field); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) { |
|
final List<AnnotationEntryGen> annotationGenObjs = new ArrayList<>(); |
|
for (final Attribute attr : attrs) { |
|
if (attr instanceof RuntimeVisibleAnnotations) { |
|
final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; |
|
final AnnotationEntry[] annos = rva.getAnnotationEntries(); |
|
for (final AnnotationEntry a : annos) { |
|
annotationGenObjs.add(new AnnotationEntryGen(a, |
|
getConstantPool(), false)); |
|
} |
|
} else if (attr instanceof RuntimeInvisibleAnnotations) { |
|
final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; |
|
final AnnotationEntry[] annos = ria.getAnnotationEntries(); |
|
for (final AnnotationEntry a : annos) { |
|
annotationGenObjs.add(new AnnotationEntryGen(a, |
|
getConstantPool(), false)); |
|
} |
|
} |
|
} |
|
return annotationGenObjs.toArray(new AnnotationEntryGen[annotationGenObjs.size()]); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public JavaClass getJavaClass() { |
|
final int[] interfaces = getInterfaces(); |
|
final Field[] fields = getFields(); |
|
final Method[] methods = getMethods(); |
|
Attribute[] attributes; |
|
if (annotation_vec.isEmpty()) { |
|
attributes = getAttributes(); |
|
} else { |
|
|
|
final Attribute[] annAttributes = AnnotationEntryGen.getAnnotationAttributes(cp, getAnnotationEntries()); |
|
attributes = new Attribute[attribute_vec.size() + annAttributes.length]; |
|
attribute_vec.toArray(attributes); |
|
System.arraycopy(annAttributes, 0, attributes, attribute_vec.size(), annAttributes.length); |
|
} |
|
|
|
final ConstantPool _cp = this.cp.getFinalConstantPool(); |
|
return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor, |
|
super.getAccessFlags(), _cp, interfaces, fields, methods, attributes); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final void addInterface(final String name) { |
|
interface_vec.add(name); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void removeInterface(final String name) { |
|
interface_vec.remove(name); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public int getMajor() { |
|
return major; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setMajor(final int major) { |
|
this.major = major; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setMinor(final int minor) { |
|
this.minor = minor; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public int getMinor() { |
|
return minor; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final void addAttribute(final Attribute a) { |
|
attribute_vec.add(a); |
|
} |
|
|
|
public final void addAnnotationEntry(final AnnotationEntryGen a) { |
|
annotation_vec.add(a); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final void addMethod(final Method m) { |
|
method_vec.add(m); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void addEmptyConstructor(final int access_flags) { |
|
final InstructionList il = new InstructionList(); |
|
il.append(InstructionConst.THIS); |
|
il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, "<init>", "()V"))); |
|
il.append(InstructionConst.RETURN); |
|
final MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>", |
|
class_name, il, cp); |
|
mg.setMaxStack(1); |
|
addMethod(mg.getMethod()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final void addField(final Field f) { |
|
field_vec.add(f); |
|
} |
|
|
|
public boolean containsField(final Field f) { |
|
return field_vec.contains(f); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Field containsField(final String name) { |
|
for (final Field f : field_vec) { |
|
if (f.getName().equals(name)) { |
|
return f; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Method containsMethod(final String name, final String signature) { |
|
for (final Method m : method_vec) { |
|
if (m.getName().equals(name) && m.getSignature().equals(signature)) { |
|
return m; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void removeAttribute(final Attribute a) { |
|
attribute_vec.remove(a); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void removeMethod(final Method m) { |
|
method_vec.remove(m); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void replaceMethod(final Method old, final Method new_) { |
|
if (new_ == null) { |
|
throw new ClassGenException("Replacement method must not be null"); |
|
} |
|
final int i = method_vec.indexOf(old); |
|
if (i < 0) { |
|
method_vec.add(new_); |
|
} else { |
|
method_vec.set(i, new_); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void replaceField(final Field old, final Field new_) { |
|
if (new_ == null) { |
|
throw new ClassGenException("Replacement method must not be null"); |
|
} |
|
final int i = field_vec.indexOf(old); |
|
if (i < 0) { |
|
field_vec.add(new_); |
|
} else { |
|
field_vec.set(i, new_); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void removeField(final Field f) { |
|
field_vec.remove(f); |
|
} |
|
|
|
public String getClassName() { |
|
return class_name; |
|
} |
|
|
|
public String getSuperclassName() { |
|
return super_class_name; |
|
} |
|
|
|
public String getFileName() { |
|
return file_name; |
|
} |
|
|
|
public void setClassName(final String name) { |
|
class_name = name.replace('/', '.'); |
|
class_name_index = cp.addClass(name); |
|
} |
|
|
|
public void setSuperclassName(final String name) { |
|
super_class_name = name.replace('/', '.'); |
|
superclass_name_index = cp.addClass(name); |
|
} |
|
|
|
public Method[] getMethods() { |
|
return method_vec.toArray(new Method[method_vec.size()]); |
|
} |
|
|
|
public void setMethods(final Method[] methods) { |
|
method_vec.clear(); |
|
for (final Method method : methods) { |
|
addMethod(method); |
|
} |
|
} |
|
|
|
public void setMethodAt(final Method method, final int pos) { |
|
method_vec.set(pos, method); |
|
} |
|
|
|
public Method getMethodAt(final int pos) { |
|
return method_vec.get(pos); |
|
} |
|
|
|
public String[] getInterfaceNames() { |
|
final int size = interface_vec.size(); |
|
final String[] interfaces = new String[size]; |
|
interface_vec.toArray(interfaces); |
|
return interfaces; |
|
} |
|
|
|
public int[] getInterfaces() { |
|
final int size = interface_vec.size(); |
|
final int[] interfaces = new int[size]; |
|
for (int i = 0; i < size; i++) { |
|
interfaces[i] = cp.addClass(interface_vec.get(i)); |
|
} |
|
return interfaces; |
|
} |
|
|
|
public Field[] getFields() { |
|
return field_vec.toArray(new Field[field_vec.size()]); |
|
} |
|
|
|
public Attribute[] getAttributes() { |
|
return attribute_vec.toArray(new Attribute[attribute_vec.size()]); |
|
} |
|
|
|
|
|
public AnnotationEntryGen[] getAnnotationEntries() { |
|
return annotation_vec.toArray(new AnnotationEntryGen[annotation_vec.size()]); |
|
} |
|
|
|
public ConstantPoolGen getConstantPool() { |
|
return cp; |
|
} |
|
|
|
public void setConstantPool(final ConstantPoolGen constant_pool) { |
|
cp = constant_pool; |
|
} |
|
|
|
public void setClassNameIndex(final int class_name_index) { |
|
this.class_name_index = class_name_index; |
|
class_name = cp.getConstantPool().getConstantString(class_name_index, |
|
Const.CONSTANT_Class).replace('/', '.'); |
|
} |
|
|
|
public void setSuperclassNameIndex(final int superclass_name_index) { |
|
this.superclass_name_index = superclass_name_index; |
|
super_class_name = cp.getConstantPool().getConstantString(superclass_name_index, |
|
Const.CONSTANT_Class).replace('/', '.'); |
|
} |
|
|
|
public int getSuperclassNameIndex() { |
|
return superclass_name_index; |
|
} |
|
|
|
public int getClassNameIndex() { |
|
return class_name_index; |
|
} |
|
|
|
private List<ClassObserver> observers; |
|
|
|
|
|
|
|
*/ |
|
public void addObserver(final ClassObserver o) { |
|
if (observers == null) { |
|
observers = new ArrayList<>(); |
|
} |
|
observers.add(o); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void removeObserver(final ClassObserver o) { |
|
if (observers != null) { |
|
observers.remove(o); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void update() { |
|
if (observers != null) { |
|
for (final ClassObserver observer : observers) { |
|
observer.notify(this); |
|
} |
|
} |
|
} |
|
|
|
@Override |
|
public Object clone() { |
|
try { |
|
return super.clone(); |
|
} catch (final CloneNotSupportedException e) { |
|
throw new Error("Clone Not Supported"); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static BCELComparator getComparator() { |
|
return _cmp; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void setComparator(final BCELComparator comparator) { |
|
_cmp = comparator; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public boolean equals(final Object obj) { |
|
return _cmp.equals(this, obj); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public int hashCode() { |
|
return _cmp.hashCode(this); |
|
} |
|
} |