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