View Javadoc

1   package serp.bytecode;
2   
3   import java.io.*;
4   import java.util.*;
5   
6   import serp.bytecode.lowlevel.*;
7   import serp.bytecode.visitor.*;
8   
9   /***
10   * Abstract superclass for all bytecode entities that hold attributes.
11   *
12   * @author Abe White
13   */
14  public abstract class Attributes implements BCEntity {
15      /***
16       * Return all the attributes owned by this entity.
17       *
18       * @return all owned attributes, or empty array if none
19       */
20      public Attribute[] getAttributes() {
21          Collection attrs = getAttributesHolder();
22          return (Attribute[]) attrs.toArray(new Attribute[attrs.size()]);
23      }
24  
25      /***
26       * Return the attribute with the given name. If multiple attributes
27       * share the name, which is returned is undefined.
28       */
29      public Attribute getAttribute(String name) {
30          Collection attrs = getAttributesHolder();
31          Attribute attr;
32          for (Iterator itr = attrs.iterator(); itr.hasNext();) {
33              attr = (Attribute) itr.next();
34              if (attr.getName().equals(name))
35                  return attr;
36          }
37          return null;
38      }
39  
40      /***
41       * Return all attributes with the given name.
42       *
43       * @return the matching attributes, or empty array if none
44       */
45      public Attribute[] getAttributes(String name) {
46          List matches = new LinkedList();
47          Collection attrs = getAttributesHolder();
48          Attribute attr;
49          for (Iterator itr = attrs.iterator(); itr.hasNext();) {
50              attr = (Attribute) itr.next();
51              if (attr.getName().equals(name))
52                  matches.add(attr);
53          }
54          return (Attribute[]) matches.toArray(new Attribute[matches.size()]);
55      }
56  
57      /***
58       * Set the attributes for this entity; this method is useful for importing
59       * all attributes from another entity. Set to null or empty array if none.
60       */
61      public void setAttributes(Attribute[] attrs) {
62          clearAttributes();
63          if (attrs != null) 
64              for (int i = 0; i < attrs.length; i++)
65                  addAttribute(attrs[i]);
66      }
67  
68      /***
69       * Import an attribute from another entity, or make a copy of one
70       * on this entity.
71       */
72      public Attribute addAttribute(Attribute attr) {
73          Attribute newAttr = addAttribute(attr.getName());
74          newAttr.read(attr);
75          return newAttr;
76      }
77  
78      /***
79       * Add an attribute of the given type.
80       */
81      public Attribute addAttribute(String name) {
82          Attribute attr = Attribute.create(name, this);
83          getAttributesHolder().add(attr);
84          return attr;
85      }
86  
87      /***
88       * Clear all attributes from this entity.
89       */
90      public void clearAttributes() {
91          Collection attrs = getAttributesHolder();
92          Attribute attr;
93          for (Iterator itr = attrs.iterator(); itr.hasNext();) {
94              attr = (Attribute) itr.next();
95              itr.remove();
96              attr.invalidate();
97          }
98      }
99  
100     /***
101      * Remove all attributes with the given name from this entity.
102      *
103      * @return true if an attribute was removed, false otherwise
104      */
105     public boolean removeAttribute(String name) {
106         return removeAttribute(getAttribute(name));
107     }
108 
109     /***
110      * Remove the given attribute. After being removed, the attribute
111      * is invalid, and the result of any operations on it are undefined.
112      *
113      * @return true if the attribute was removed, false otherwise
114      */
115     public boolean removeAttribute(Attribute attribute) {
116         if ((attribute == null) || !getAttributesHolder().remove(attribute))
117             return false;
118         attribute.invalidate();
119         return true;
120     }
121 
122     /***
123      * Convenience method to be called by BCEntities when being visited
124      * by a {@link BCVisitor}; this method will allow the visitor to visit all
125      * attributes of this entity.
126      */
127     void visitAttributes(BCVisitor visit) {
128         Attribute attr;
129         for (Iterator itr = getAttributesHolder().iterator(); itr.hasNext();) {
130             attr = (Attribute) itr.next();
131             visit.enterAttribute(attr);
132             attr.acceptVisit(visit);
133             visit.exitAttribute(attr);
134         }
135     }
136 
137     /***
138      * Build the attribute list from the given stream.
139      * Relies on the ability of attributes to read themselves, and
140      * requires access to the constant pool, which must already by read.
141      */
142     void readAttributes(DataInput in) throws IOException {
143         Collection attrs = getAttributesHolder();
144         attrs.clear();
145 
146         Attribute attribute;
147         String name;
148         for (int i = in.readUnsignedShort(); i > 0; i--) {
149             name = ((UTF8Entry) getPool().getEntry(in.readUnsignedShort())).
150                 getValue();
151             attribute = addAttribute(name);
152             attribute.read(in, in.readInt());
153         }
154     }
155 
156     /***
157      * Writes all the owned attributes to the given stream.
158      * Relies on the ability of attributes to write themselves.
159      */
160     void writeAttributes(DataOutput out) throws IOException {
161         Collection attrs = getAttributesHolder();
162         out.writeShort(attrs.size());
163 
164         Attribute attribute;
165         int length;
166         for (Iterator itr = attrs.iterator(); itr.hasNext();) {
167             attribute = (Attribute) itr.next();
168             out.writeShort(attribute.getNameIndex());
169             length = attribute.getLength();
170             out.writeInt(length);
171             attribute.write(out, length);
172         }
173     }
174 
175     /***
176      * Return the collection used to hold the attributes of this entity.
177      */
178     abstract Collection getAttributesHolder();
179 }