1 package serp.bytecode;
2
3 import java.io.*;
4 import java.lang.reflect.*;
5 import java.util.*;
6
7 import serp.bytecode.lowlevel.*;
8 import serp.bytecode.visitor.*;
9 import serp.util.*;
10
11 /***
12 * In bytecode attributes are used to represent anything that is not
13 * part of the class structure. This includes the source file name, code of
14 * methods, the line number table, etc. All attributes contain at a minimum
15 * an immutable name that also determines the attribute's type.
16 *
17 * @author Abe White
18 */
19 public abstract class Attribute extends Attributes implements VisitAcceptor {
20 private int _nameIndex = 0;
21 private Attributes _owner = null;
22
23 Attribute(int nameIndex, Attributes owner) {
24 _owner = owner;
25 _nameIndex = nameIndex;
26 }
27
28 /***
29 * Create an attribute of the appropriate type based on the
30 * the attribute name.
31 */
32 static Attribute create(String name, Attributes owner) {
33
34 int nameIndex = owner.getPool().findUTF8Entry(name, true);
35 if ("RuntimeVisibleAnnotations".equals(name)
36 || "RuntimeInvisibleAnnotations".equals(name))
37 return new Annotations(nameIndex, owner);
38
39 try {
40 Class type = Class.forName("serp.bytecode." + name);
41 Constructor cons = type.getDeclaredConstructor(new Class[] {
42 int.class, Attributes.class
43 });
44 return (Attribute) cons.newInstance(new Object[] {
45 Numbers.valueOf(nameIndex), owner
46 });
47 } catch (Throwable t) {
48 return new UnknownAttribute(nameIndex, owner);
49 }
50 }
51
52 /***
53 * Return the {@link Attributes} that owns this attribute. The entity
54 * might be a {@link BCClass}, {@link BCField}, {@link BCMethod}, or other
55 * attribute.
56 */
57 public Attributes getOwner() {
58 return _owner;
59 }
60
61 /***
62 * Return the index in the {@link ConstantPool} of the {@link UTF8Entry}
63 * holding the name of this attribute.
64 */
65 public int getNameIndex() {
66 return _nameIndex;
67 }
68
69 /***
70 * Return the name of this attribute.
71 */
72 public String getName() {
73 return ((UTF8Entry) getPool().getEntry(_nameIndex)).getValue();
74 }
75
76 public Project getProject() {
77 return _owner.getProject();
78 }
79
80 public ConstantPool getPool() {
81 return _owner.getPool();
82 }
83
84 public ClassLoader getClassLoader() {
85 return _owner.getClassLoader();
86 }
87
88 public boolean isValid() {
89 return _owner != null;
90 }
91
92 Collection getAttributesHolder() {
93 return Collections.EMPTY_LIST;
94 }
95
96 /***
97 * Invalidate this attribute.
98 */
99 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 }