1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.commons.compress.harmony.pack200;
21
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.util.ArrayList;
25 import java.util.Iterator;
26 import java.util.List;
27
28
29
30
31 public class MetadataBandGroup extends BandSet {
32
33 public static final int CONTEXT_CLASS = 0;
34 public static final int CONTEXT_FIELD = 1;
35 public static final int CONTEXT_METHOD = 2;
36
37 private final String type;
38 private int numBackwardsCalls;
39
40 public IntList param_NB = new IntList();
41 public IntList anno_N = new IntList();
42 public List<CPSignature> type_RS = new ArrayList<>();
43 public IntList pair_N = new IntList();
44 public List<CPUTF8> name_RU = new ArrayList<>();
45 public List<String> T = new ArrayList<>();
46 public List<CPConstant<?>> caseI_KI = new ArrayList<>();
47 public List<CPConstant<?>> caseD_KD = new ArrayList<>();
48 public List<CPConstant<?>> caseF_KF = new ArrayList<>();
49 public List<CPConstant<?>> caseJ_KJ = new ArrayList<>();
50 public List<CPSignature> casec_RS = new ArrayList<>();
51 public List<CPSignature> caseet_RS = new ArrayList<>();
52 public List<CPUTF8> caseec_RU = new ArrayList<>();
53 public List<CPUTF8> cases_RU = new ArrayList<>();
54 public IntList casearray_N = new IntList();
55 public List<CPSignature> nesttype_RS = new ArrayList<>();
56 public IntList nestpair_N = new IntList();
57 public List<CPUTF8> nestname_RU = new ArrayList<>();
58
59 private final CpBands cpBands;
60 private final int context;
61
62
63
64
65
66
67
68
69
70
71 public MetadataBandGroup(final String type, final int context, final CpBands cpBands, final SegmentHeader segmentHeader, final int effort) {
72 super(effort, segmentHeader);
73 this.type = type;
74 this.cpBands = cpBands;
75 this.context = context;
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90 public void addAnnotation(final String desc, final List<String> nameRU, final List<String> tags, final List<Object> values, final List<Integer> caseArrayN,
91 final List<String> nestTypeRS, final List<String> nestNameRU, final List<Integer> nestPairN) {
92 type_RS.add(cpBands.getCPSignature(desc));
93 pair_N.add(nameRU.size());
94 nameRU.forEach(name -> name_RU.add(cpBands.getCPUtf8(name)));
95
96 final Iterator<Object> valuesIterator = values.iterator();
97 for (final String tag : tags) {
98 T.add(tag);
99 switch (tag) {
100 case "B":
101 case "C":
102 case "I":
103 case "S":
104 case "Z": {
105 caseI_KI.add(cpBands.getConstant(valuesIterator.next()));
106 break;
107 }
108 case "D": {
109 caseD_KD.add(cpBands.getConstant(valuesIterator.next()));
110 break;
111 }
112 case "F": {
113 caseF_KF.add(cpBands.getConstant(valuesIterator.next()));
114 break;
115 }
116 case "J": {
117 caseJ_KJ.add(cpBands.getConstant(valuesIterator.next()));
118 break;
119 }
120 case "c": {
121 casec_RS.add(cpBands.getCPSignature(nextString(valuesIterator)));
122 break;
123 }
124 case "e": {
125 caseet_RS.add(cpBands.getCPSignature(nextString(valuesIterator)));
126 caseec_RU.add(cpBands.getCPUtf8(nextString(valuesIterator)));
127 break;
128 }
129 case "s": {
130 cases_RU.add(cpBands.getCPUtf8(nextString(valuesIterator)));
131 break;
132 }
133 }
134
135 }
136 for (final Integer element : caseArrayN) {
137 final int arraySize = element.intValue();
138 casearray_N.add(arraySize);
139 numBackwardsCalls += arraySize;
140 }
141 nestTypeRS.forEach(element -> nesttype_RS.add(cpBands.getCPSignature(element)));
142 nestNameRU.forEach(element -> nestname_RU.add(cpBands.getCPUtf8(element)));
143 for (final Integer numPairs : nestPairN) {
144 nestpair_N.add(numPairs.intValue());
145 numBackwardsCalls += numPairs.intValue();
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public void addParameterAnnotation(final int numParams, final int[] annoN, final IntList pairN, final List<String> typeRS, final List<String> nameRU,
165 final List<String> tags, final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
166 final List<Integer> nestPairN) {
167 param_NB.add(numParams);
168 for (final int element : annoN) {
169 anno_N.add(element);
170 }
171 pair_N.addAll(pairN);
172 typeRS.forEach(desc -> type_RS.add(cpBands.getCPSignature(desc)));
173 nameRU.forEach(name -> name_RU.add(cpBands.getCPUtf8(name)));
174 final Iterator<Object> valuesIterator = values.iterator();
175 for (final String tag : tags) {
176 T.add(tag);
177 switch (tag) {
178 case "B":
179 case "C":
180 case "I":
181 case "S":
182 case "Z": {
183 caseI_KI.add(cpBands.getConstant(valuesIterator.next()));
184 break;
185 }
186 case "D": {
187 caseD_KD.add(cpBands.getConstant(valuesIterator.next()));
188 break;
189 }
190 case "F": {
191 caseF_KF.add(cpBands.getConstant(valuesIterator.next()));
192 break;
193 }
194 case "J": {
195 caseJ_KJ.add(cpBands.getConstant(valuesIterator.next()));
196 break;
197 }
198 case "c": {
199 casec_RS.add(cpBands.getCPSignature(nextString(valuesIterator)));
200 break;
201 }
202 case "e": {
203 caseet_RS.add(cpBands.getCPSignature(nextString(valuesIterator)));
204 caseec_RU.add(cpBands.getCPUtf8(nextString(valuesIterator)));
205 break;
206 }
207 case "s": {
208 cases_RU.add(cpBands.getCPUtf8(nextString(valuesIterator)));
209 break;
210 }
211 }
212
213 }
214 for (final Integer element : caseArrayN) {
215 final int arraySize = element.intValue();
216 casearray_N.add(arraySize);
217 numBackwardsCalls += arraySize;
218 }
219 nestTypeRS.forEach(type -> nesttype_RS.add(cpBands.getCPSignature(type)));
220 nestNameRU.forEach(name -> nestname_RU.add(cpBands.getCPUtf8(name)));
221 for (final Integer numPairs : nestPairN) {
222 nestpair_N.add(numPairs.intValue());
223 numBackwardsCalls += numPairs.intValue();
224 }
225 }
226
227
228
229
230
231
232 public boolean hasContent() {
233 return type_RS.size() > 0;
234 }
235
236 public void incrementAnnoN() {
237 anno_N.increment(anno_N.size() - 1);
238 }
239
240 public void newEntryInAnnoN() {
241 anno_N.add(1);
242 }
243
244 private String nextString(final Iterator<Object> valuesIterator) {
245 return (String) valuesIterator.next();
246 }
247
248 public int numBackwardsCalls() {
249 return numBackwardsCalls;
250 }
251
252
253
254
255
256
257 @Override
258 public void pack(final OutputStream out) throws IOException, Pack200Exception {
259 PackingUtils.log("Writing metadata band group...");
260 if (hasContent()) {
261 final String contextStr;
262 if (context == CONTEXT_CLASS) {
263 contextStr = "Class";
264 } else if (context == CONTEXT_FIELD) {
265 contextStr = "Field";
266 } else {
267 contextStr = "Method";
268 }
269 byte[] encodedBand;
270 if (!type.equals("AD")) {
271 if (type.indexOf('P') != -1) {
272
273 encodedBand = encodeBandInt(contextStr + "_" + type + " param_NB", param_NB.toArray(), Codec.BYTE1);
274 out.write(encodedBand);
275 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " anno_N[" + param_NB.size() + "]");
276 }
277 encodedBand = encodeBandInt(contextStr + "_" + type + " anno_N", anno_N.toArray(), Codec.UNSIGNED5);
278 out.write(encodedBand);
279 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " anno_N[" + anno_N.size() + "]");
280
281 encodedBand = encodeBandInt(contextStr + "_" + type + " type_RS", cpEntryListToArray(type_RS), Codec.UNSIGNED5);
282 out.write(encodedBand);
283 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " type_RS[" + type_RS.size() + "]");
284
285 encodedBand = encodeBandInt(contextStr + "_" + type + " pair_N", pair_N.toArray(), Codec.UNSIGNED5);
286 out.write(encodedBand);
287 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " pair_N[" + pair_N.size() + "]");
288
289 encodedBand = encodeBandInt(contextStr + "_" + type + " name_RU", cpEntryListToArray(name_RU), Codec.UNSIGNED5);
290 out.write(encodedBand);
291 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " name_RU[" + name_RU.size() + "]");
292 }
293 encodedBand = encodeBandInt(contextStr + "_" + type + " T", tagListToArray(T), Codec.BYTE1);
294 out.write(encodedBand);
295 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " T[" + T.size() + "]");
296
297 encodedBand = encodeBandInt(contextStr + "_" + type + " caseI_KI", cpEntryListToArray(caseI_KI), Codec.UNSIGNED5);
298 out.write(encodedBand);
299 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " caseI_KI[" + caseI_KI.size() + "]");
300
301 encodedBand = encodeBandInt(contextStr + "_" + type + " caseD_KD", cpEntryListToArray(caseD_KD), Codec.UNSIGNED5);
302 out.write(encodedBand);
303 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " caseD_KD[" + caseD_KD.size() + "]");
304
305 encodedBand = encodeBandInt(contextStr + "_" + type + " caseF_KF", cpEntryListToArray(caseF_KF), Codec.UNSIGNED5);
306 out.write(encodedBand);
307 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " caseF_KF[" + caseF_KF.size() + "]");
308
309 encodedBand = encodeBandInt(contextStr + "_" + type + " caseJ_KJ", cpEntryListToArray(caseJ_KJ), Codec.UNSIGNED5);
310 out.write(encodedBand);
311 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " caseJ_KJ[" + caseJ_KJ.size() + "]");
312
313 encodedBand = encodeBandInt(contextStr + "_" + type + " casec_RS", cpEntryListToArray(casec_RS), Codec.UNSIGNED5);
314 out.write(encodedBand);
315 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " casec_RS[" + casec_RS.size() + "]");
316
317 encodedBand = encodeBandInt(contextStr + "_" + type + " caseet_RS", cpEntryListToArray(caseet_RS), Codec.UNSIGNED5);
318 out.write(encodedBand);
319 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " caseet_RS[" + caseet_RS.size() + "]");
320
321 encodedBand = encodeBandInt(contextStr + "_" + type + " caseec_RU", cpEntryListToArray(caseec_RU), Codec.UNSIGNED5);
322 out.write(encodedBand);
323 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " caseec_RU[" + caseec_RU.size() + "]");
324
325 encodedBand = encodeBandInt(contextStr + "_" + type + " cases_RU", cpEntryListToArray(cases_RU), Codec.UNSIGNED5);
326 out.write(encodedBand);
327 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " cases_RU[" + cases_RU.size() + "]");
328
329 encodedBand = encodeBandInt(contextStr + "_" + type + " casearray_N", casearray_N.toArray(), Codec.UNSIGNED5);
330 out.write(encodedBand);
331 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " casearray_N[" + casearray_N.size() + "]");
332
333 encodedBand = encodeBandInt(contextStr + "_" + type + " nesttype_RS", cpEntryListToArray(nesttype_RS), Codec.UNSIGNED5);
334 out.write(encodedBand);
335 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " nesttype_RS[" + nesttype_RS.size() + "]");
336
337 encodedBand = encodeBandInt(contextStr + "_" + type + " nestpair_N", nestpair_N.toArray(), Codec.UNSIGNED5);
338 out.write(encodedBand);
339 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " nestpair_N[" + nestpair_N.size() + "]");
340
341 encodedBand = encodeBandInt(contextStr + "_" + type + " nestname_RU", cpEntryListToArray(nestname_RU), Codec.UNSIGNED5);
342 out.write(encodedBand);
343 PackingUtils.log("Wrote " + encodedBand.length + " bytes from " + contextStr + "_" + type + " nestname_RU[" + nestname_RU.size() + "]");
344 }
345 }
346
347
348
349
350 public void removeLatest() {
351 final int latest = anno_N.remove(anno_N.size() - 1);
352 for (int i = 0; i < latest; i++) {
353 type_RS.remove(type_RS.size() - 1);
354 final int pairs = pair_N.remove(pair_N.size() - 1);
355 for (int j = 0; j < pairs; j++) {
356 removeOnePair();
357 }
358 }
359 }
360
361
362
363
364 private void removeOnePair() {
365 final String tag = T.remove(T.size() - 1);
366 switch (tag) {
367 case "B":
368 case "C":
369 case "I":
370 case "S":
371 case "Z":
372 caseI_KI.remove(caseI_KI.size() - 1);
373 break;
374 case "D":
375 caseD_KD.remove(caseD_KD.size() - 1);
376 break;
377 case "F":
378 caseF_KF.remove(caseF_KF.size() - 1);
379 break;
380 case "J":
381 caseJ_KJ.remove(caseJ_KJ.size() - 1);
382 break;
383 case "e":
384 caseet_RS.remove(caseet_RS.size() - 1);
385 caseec_RU.remove(caseet_RS.size() - 1);
386 break;
387 case "s":
388 cases_RU.remove(cases_RU.size() - 1);
389 break;
390 case "[":
391 final int arraySize = casearray_N.remove(casearray_N.size() - 1);
392 numBackwardsCalls -= arraySize;
393 for (int k = 0; k < arraySize; k++) {
394 removeOnePair();
395 }
396 break;
397 case "@":
398 nesttype_RS.remove(nesttype_RS.size() - 1);
399 final int numPairs = nestpair_N.remove(nestpair_N.size() - 1);
400 numBackwardsCalls -= numPairs;
401 for (int i = 0; i < numPairs; i++) {
402 removeOnePair();
403 }
404 break;
405 }
406 }
407
408 private int[] tagListToArray(final List<String> list) {
409 return list.stream().mapToInt(s -> s.charAt(0)).toArray();
410 }
411
412 }