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