View Javadoc

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          // special case for annotations
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 }