001 package serp.bytecode;
002
003 import java.io.*;
004 import java.lang.reflect.*;
005 import java.util.*;
006
007 import serp.bytecode.lowlevel.*;
008 import serp.bytecode.visitor.*;
009 import serp.util.*;
010
011 /**
012 * In bytecode attributes are used to represent anything that is not
013 * part of the class structure. This includes the source file name, code of
014 * methods, the line number table, etc. All attributes contain at a minimum
015 * an immutable name that also determines the attribute's type.
016 *
017 * @author Abe White
018 */
019 public abstract class Attribute extends Attributes implements VisitAcceptor {
020 private int _nameIndex = 0;
021 private Attributes _owner = null;
022
023 Attribute(int nameIndex, Attributes owner) {
024 _owner = owner;
025 _nameIndex = nameIndex;
026 }
027
028 /**
029 * Create an attribute of the appropriate type based on the
030 * the attribute name.
031 */
032 static Attribute create(String name, Attributes owner) {
033 // special case for annotations
034 int nameIndex = owner.getPool().findUTF8Entry(name, true);
035 if ("RuntimeVisibleAnnotations".equals(name)
036 || "RuntimeInvisibleAnnotations".equals(name))
037 return new Annotations(nameIndex, owner);
038
039 try {
040 Class type = Class.forName("serp.bytecode." + name);
041 Constructor cons = type.getDeclaredConstructor(new Class[] {
042 int.class, Attributes.class
043 });
044 return (Attribute) cons.newInstance(new Object[] {
045 Numbers.valueOf(nameIndex), owner
046 });
047 } catch (Throwable t) {
048 return new UnknownAttribute(nameIndex, owner);
049 }
050 }
051
052 /**
053 * Return the {@link Attributes} that owns this attribute. The entity
054 * might be a {@link BCClass}, {@link BCField}, {@link BCMethod}, or other
055 * attribute.
056 */
057 public Attributes getOwner() {
058 return _owner;
059 }
060
061 /**
062 * Return the index in the {@link ConstantPool} of the {@link UTF8Entry}
063 * holding the name of this attribute.
064 */
065 public int getNameIndex() {
066 return _nameIndex;
067 }
068
069 /**
070 * Return the name of this attribute.
071 */
072 public String getName() {
073 return ((UTF8Entry) getPool().getEntry(_nameIndex)).getValue();
074 }
075
076 public Project getProject() {
077 return _owner.getProject();
078 }
079
080 public ConstantPool getPool() {
081 return _owner.getPool();
082 }
083
084 public ClassLoader getClassLoader() {
085 return _owner.getClassLoader();
086 }
087
088 public boolean isValid() {
089 return _owner != null;
090 }
091
092 Collection getAttributesHolder() {
093 return Collections.EMPTY_LIST;
094 }
095
096 /**
097 * Invalidate this attribute.
098 */
099 void invalidate() {
100 _owner = null;
101 }
102
103 /**
104 * Return the length of the bytecode representation of this attribute
105 * in bytes, excluding the name index.
106 */
107 int getLength() {
108 return 0;
109 }
110
111 /**
112 * Copy the information from the given attribute to this one. Does
113 * nothing by default.
114 */
115 void read(Attribute other) {
116 }
117
118 /**
119 * Read the attribute bytecode from the given stream, up to length
120 * bytes, excluding the name index. Does nothing by default.
121 */
122 void read(DataInput in, int length) throws IOException {
123 }
124
125 /**
126 * Write the attribute bytecode to the given stream, up to length bytes,
127 * excluding the name index. Does nothing by default.
128 */
129 void write(DataOutput out, int length) throws IOException {
130 }
131 }