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