1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.jdo.impl.enhancer.classfile;
20
21 import java.io.*;
22 import java.util.Vector;
23 import java.util.Stack;
24 import java.util.Arrays;
25 import java.util.Comparator;
26 import java.util.Enumeration;
27 import java.util.NoSuchElementException;
28
29 /***
30 * A list of attributes within a class file.
31 * These lists occur in several places within a class file
32 * - at class level
33 * - at method level
34 * - at field level
35 * - at attribute level
36 */
37 public class AttributeVector {
38
39
40 private ClassAttribute attributes[] = null;
41
42 /***
43 * Returns the i'th attribute in the array
44 */
45 private ClassAttribute attrAt(int i) {
46 return attributes[i];
47 }
48
49 /***
50 * Construct an empty AttributeVector
51 */
52 public AttributeVector() { }
53
54 /***
55 * Add an element to the vector
56 */
57 public void addElement(ClassAttribute attr) {
58 if (attributes == null)
59 attributes = new ClassAttribute[1];
60 else {
61 ClassAttribute newAttributes[] = new ClassAttribute[attributes.length+1];
62 System.arraycopy(attributes, 0, newAttributes, 0, attributes.length);
63 attributes = newAttributes;
64 }
65 attributes[attributes.length-1] = attr;
66 }
67
68 public Enumeration elements() {
69 class AttributeVectorEnumeration implements Enumeration {
70 private ClassAttribute[] attributes;
71 private int current = 0;
72
73 AttributeVectorEnumeration(ClassAttribute attrs[]) {
74 attributes = attrs;
75 }
76
77 public boolean hasMoreElements() {
78 return attributes != null && current < attributes.length;
79 }
80 public Object nextElement() {
81 if (!hasMoreElements())
82 throw new NoSuchElementException();
83 return attributes[current++];
84 }
85 }
86
87 return new AttributeVectorEnumeration(attributes);
88 }
89
90 /***
91 * Look for an attribute of a specific name
92 */
93 public ClassAttribute findAttribute(String attrName) {
94 Enumeration e = elements();
95 while (e.hasMoreElements()) {
96 ClassAttribute attr = (ClassAttribute) e.nextElement();
97 if (attr.attrName().asString().equals(attrName))
98 return attr;
99 }
100 return null;
101 }
102
103 /***
104 * Compares this instance with another for structural equality.
105 */
106
107 public boolean isEqual(Stack msg, Object obj) {
108 if (!(obj instanceof AttributeVector)) {
109 msg.push("obj/obj.getClass() = "
110 + (obj == null ? null : obj.getClass()));
111 msg.push("this.getClass() = "
112 + this.getClass());
113 return false;
114 }
115 AttributeVector other = (AttributeVector)obj;
116
117 if (this.attributes.length != other.attributes.length) {
118 msg.push("attributes.length "
119 + String.valueOf(other.attributes.length));
120 msg.push("attributes.length "
121 + String.valueOf(this.attributes.length));
122 return false;
123 }
124
125
126 class ClassAttributeComparator implements Comparator {
127 public int compare(Object o1, Object o2) {
128 ClassAttribute a1 = (ClassAttribute)o1;
129 ClassAttribute a2 = (ClassAttribute)o2;
130 String s1 = a1.attrName().asString();
131 String s2 = a2.attrName().asString();
132 return s1.compareTo(s2);
133 }
134 }
135 ClassAttributeComparator comparator = new ClassAttributeComparator();
136 ClassAttribute[] thisAttributes
137 = (ClassAttribute[])this.attributes.clone();
138 ClassAttribute[] otherAttributes
139 = (ClassAttribute[])other.attributes.clone();
140 Arrays.sort(thisAttributes, comparator);
141 Arrays.sort(otherAttributes, comparator);
142 for (int i = 0; i < attributes.length; i++) {
143 ClassAttribute a1 = thisAttributes[i];
144 ClassAttribute a2 = otherAttributes[i];
145 if (!a1.isEqual(msg, a2)) {
146 msg.push("attributes[i] = " + String.valueOf(a2));
147 msg.push("attributes[i] = " + String.valueOf(a1));
148 return false;
149 }
150 }
151 return true;
152 }
153
154 /***
155 * General attribute reader
156 */
157 static AttributeVector readAttributes(
158 DataInputStream data, ConstantPool constantPool)
159 throws IOException {
160 AttributeVector attribs = new AttributeVector();
161 int n_attrs = data.readUnsignedShort();
162 while (n_attrs-- > 0) {
163 attribs.addElement(ClassAttribute.read(data, constantPool));
164 }
165 return attribs;
166 }
167
168 /***
169 * ClassMethod attribute reader
170 */
171 static AttributeVector readAttributes(
172 DataInputStream data, CodeEnv codeEnv)
173 throws IOException {
174 AttributeVector attribs = new AttributeVector();
175 int n_attrs = data.readUnsignedShort();
176 while (n_attrs-- > 0) {
177 attribs.addElement(ClassAttribute.read(data, codeEnv));
178 }
179 return attribs;
180 }
181
182 /***
183 * Write the attributes to the output stream
184 */
185 void write(DataOutputStream out) throws IOException {
186 if (attributes == null) {
187 out.writeShort(0);
188 } else {
189 out.writeShort(attributes.length);
190 for (int i=0; i<attributes.length; i++)
191 attributes[i].write(out);
192 }
193 }
194
195 /***
196 * Print a description of the attributes
197 */
198 void print(PrintStream out, int indent) {
199 if (attributes != null) {
200 for (int i=0; i<attributes.length; i++)
201 attributes[i].print(out, indent);
202 }
203 }
204
205 /***
206 * Print a brief summary of the attributes
207 */
208
209 void summarize(PrintStream out, int indent) {
210 ClassPrint.spaces(out, indent);
211 out.println((attributes == null ? 0 : attributes.length) +
212 " attributes");
213 }
214 }