1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.harmony.unpack200.bytecode;
20
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25
26
27
28
29 public abstract class AnnotationsAttribute extends Attribute {
30
31
32
33
34 public static class Annotation {
35
36 private final int numPairs;
37 private final CPUTF8[] elementNames;
38 private final ElementValue[] elementValues;
39 private final CPUTF8 type;
40
41
42 private int typeIndex;
43 private int[] nameIndexes;
44
45
46
47
48
49
50
51
52
53 public Annotation(final int numPairs, final CPUTF8 type, final CPUTF8[] elementNames, final ElementValue[] elementValues) {
54 this.numPairs = numPairs;
55 this.type = type;
56 this.elementNames = elementNames;
57 this.elementValues = elementValues;
58 }
59
60
61
62
63
64
65 public List<Object> getClassFileEntries() {
66 final List<Object> entries = new ArrayList<>();
67 for (int i = 0; i < elementNames.length; i++) {
68 entries.add(elementNames[i]);
69 entries.addAll(elementValues[i].getClassFileEntries());
70 }
71 entries.add(type);
72 return entries;
73 }
74
75
76
77
78
79
80 public int getLength() {
81 int length = 4;
82 for (int i = 0; i < numPairs; i++) {
83 length += 2;
84 length += elementValues[i].getLength();
85 }
86 return length;
87 }
88
89
90
91
92
93
94 public void resolve(final ClassConstantPool pool) {
95 type.resolve(pool);
96 typeIndex = pool.indexOf(type);
97 nameIndexes = new int[numPairs];
98 for (int i = 0; i < elementNames.length; i++) {
99 elementNames[i].resolve(pool);
100 nameIndexes[i] = pool.indexOf(elementNames[i]);
101 elementValues[i].resolve(pool);
102 }
103 }
104
105
106
107
108
109
110
111 public void writeBody(final DataOutputStream dos) throws IOException {
112 dos.writeShort(typeIndex);
113 dos.writeShort(numPairs);
114 for (int i = 0; i < numPairs; i++) {
115 dos.writeShort(nameIndexes[i]);
116 elementValues[i].writeBody(dos);
117 }
118 }
119 }
120
121
122
123
124 public static class ElementValue {
125
126 private final Object value;
127 private final int tag;
128
129
130 private int constantValueIndex = -1;
131
132
133
134
135
136
137
138 public ElementValue(final int tag, final Object value) {
139 this.tag = tag;
140 this.value = value;
141 }
142
143
144
145
146
147
148 public List<Object> getClassFileEntries() {
149 final List<Object> entries = new ArrayList<>(1);
150 if (value instanceof CPNameAndType) {
151
152 entries.add(((CPNameAndType) value).name);
153 entries.add(((CPNameAndType) value).descriptor);
154 } else if (value instanceof ClassFileEntry) {
155
156 entries.add(value);
157 } else if (value instanceof ElementValue[]) {
158 final ElementValue[] values = (ElementValue[]) value;
159 for (final ElementValue value2 : values) {
160 entries.addAll(value2.getClassFileEntries());
161 }
162 } else if (value instanceof Annotation) {
163 entries.addAll(((Annotation) value).getClassFileEntries());
164 }
165 return entries;
166 }
167
168
169
170
171
172
173 public int getLength() {
174 switch (tag) {
175 case 'B':
176 case 'C':
177 case 'D':
178 case 'F':
179 case 'I':
180 case 'J':
181 case 'S':
182 case 'Z':
183 case 'c':
184 case 's':
185 return 3;
186 case 'e':
187 return 5;
188 case '[':
189 int length = 3;
190 final ElementValue[] nestedValues = (ElementValue[]) value;
191 for (final ElementValue nestedValue : nestedValues) {
192 length += nestedValue.getLength();
193 }
194 return length;
195 case '@':
196 return 1 + ((Annotation) value).getLength();
197 }
198 return 0;
199 }
200
201
202
203
204
205
206 public void resolve(final ClassConstantPool pool) {
207 if (value instanceof CPConstant) {
208 ((CPConstant) value).resolve(pool);
209 constantValueIndex = pool.indexOf((CPConstant) value);
210 } else if (value instanceof CPClass) {
211 ((CPClass) value).resolve(pool);
212 constantValueIndex = pool.indexOf((CPClass) value);
213 } else if (value instanceof CPUTF8) {
214 ((CPUTF8) value).resolve(pool);
215 constantValueIndex = pool.indexOf((CPUTF8) value);
216 } else if (value instanceof CPNameAndType) {
217 ((CPNameAndType) value).resolve(pool);
218 } else if (value instanceof Annotation) {
219 ((Annotation) value).resolve(pool);
220 } else if (value instanceof ElementValue[]) {
221 final ElementValue[] nestedValues = (ElementValue[]) value;
222 for (final ElementValue nestedValue : nestedValues) {
223 nestedValue.resolve(pool);
224 }
225 }
226 }
227
228
229
230
231
232
233
234 public void writeBody(final DataOutputStream dos) throws IOException {
235 dos.writeByte(tag);
236 if (constantValueIndex != -1) {
237 dos.writeShort(constantValueIndex);
238 } else if (value instanceof CPNameAndType) {
239 ((CPNameAndType) value).writeBody(dos);
240 } else if (value instanceof Annotation) {
241 ((Annotation) value).writeBody(dos);
242 } else if (value instanceof ElementValue[]) {
243 final ElementValue[] nestedValues = (ElementValue[]) value;
244 dos.writeShort(nestedValues.length);
245 for (final ElementValue nestedValue : nestedValues) {
246 nestedValue.writeBody(dos);
247 }
248 } else {
249 throw new Error("");
250 }
251 }
252 }
253
254
255
256
257
258
259 public AnnotationsAttribute(final CPUTF8 attributeName) {
260 super(attributeName);
261 }
262
263 }