1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.harmony.unpack200;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.StringReader;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25
26 import org.apache.commons.compress.harmony.pack200.BHSDCodec;
27 import org.apache.commons.compress.harmony.pack200.Codec;
28 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
29 import org.apache.commons.compress.harmony.unpack200.bytecode.Attribute;
30 import org.apache.commons.compress.harmony.unpack200.bytecode.CPClass;
31 import org.apache.commons.compress.harmony.unpack200.bytecode.CPDouble;
32 import org.apache.commons.compress.harmony.unpack200.bytecode.CPFieldRef;
33 import org.apache.commons.compress.harmony.unpack200.bytecode.CPFloat;
34 import org.apache.commons.compress.harmony.unpack200.bytecode.CPInteger;
35 import org.apache.commons.compress.harmony.unpack200.bytecode.CPInterfaceMethodRef;
36 import org.apache.commons.compress.harmony.unpack200.bytecode.CPLong;
37 import org.apache.commons.compress.harmony.unpack200.bytecode.CPMethodRef;
38 import org.apache.commons.compress.harmony.unpack200.bytecode.CPNameAndType;
39 import org.apache.commons.compress.harmony.unpack200.bytecode.CPString;
40 import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8;
41 import org.apache.commons.compress.harmony.unpack200.bytecode.NewAttribute;
42 import org.apache.commons.compress.utils.ParsingUtils;
43
44
45
46
47 public class NewAttributeBands extends BandSet {
48
49
50
51
52
53 private interface AttributeLayoutElement {
54
55
56
57
58
59
60
61 void addToAttribute(int index, NewAttribute attribute);
62
63
64
65
66
67
68
69
70
71 void readBands(InputStream in, int count) throws IOException, Pack200Exception;
72
73 }
74
75 public class Call extends LayoutElement {
76
77 private final int callableIndex;
78 private Callable callable;
79
80 public Call(final int callableIndex) {
81 this.callableIndex = callableIndex;
82 }
83
84 @Override
85 public void addToAttribute(final int n, final NewAttribute attribute) {
86 callable.addNextToAttribute(attribute);
87 }
88
89 public Callable getCallable() {
90 return callable;
91 }
92
93 public int getCallableIndex() {
94 return callableIndex;
95 }
96
97 @Override
98 public void readBands(final InputStream in, final int count) {
99
100
101
102
103 if (callableIndex > 0) {
104 callable.addCount(count);
105 }
106 }
107
108 public void setCallable(final Callable callable) {
109 this.callable = callable;
110 if (callableIndex < 1) {
111 callable.setBackwardsCallable();
112 }
113 }
114 }
115
116 public static class Callable implements AttributeLayoutElement {
117
118 private final List<LayoutElement> body;
119
120 private boolean isBackwardsCallable;
121
122 private boolean isFirstCallable;
123
124 private int count;
125
126 private int index;
127
128 public Callable(final List<LayoutElement> body) {
129 this.body = body;
130 }
131
132
133
134
135
136
137 public void addCount(final int count) {
138 this.count += count;
139 }
140
141
142
143
144
145
146 public void addNextToAttribute(final NewAttribute attribute) {
147 for (final LayoutElement element : body) {
148 element.addToAttribute(index, attribute);
149 }
150 index++;
151 }
152
153 @Override
154 public void addToAttribute(final int n, final NewAttribute attribute) {
155 if (isFirstCallable) {
156
157 for (final LayoutElement element : body) {
158 element.addToAttribute(index, attribute);
159 }
160 index++;
161 }
162 }
163
164 public List<LayoutElement> getBody() {
165 return body;
166 }
167
168 public boolean isBackwardsCallable() {
169 return isBackwardsCallable;
170 }
171
172 @Override
173 public void readBands(final InputStream in, int count) throws IOException, Pack200Exception {
174 if (isFirstCallable) {
175 count += this.count;
176 } else {
177 count = this.count;
178 }
179 for (final LayoutElement element : body) {
180 element.readBands(in, count);
181 }
182 }
183
184
185
186
187 public void setBackwardsCallable() {
188 this.isBackwardsCallable = true;
189 }
190
191 public void setFirstCallable(final boolean isFirstCallable) {
192 this.isFirstCallable = isFirstCallable;
193 }
194 }
195
196 public class Integral extends LayoutElement {
197
198 private final String tag;
199
200 private int[] band;
201
202 public Integral(final String tag) {
203 this.tag = tag;
204 }
205
206 @Override
207 public void addToAttribute(final int n, final NewAttribute attribute) {
208 int value = band[n];
209 if (tag.equals("B") || tag.equals("FB")) {
210 attribute.addInteger(1, value);
211 } else if (tag.equals("SB")) {
212 attribute.addInteger(1, (byte) value);
213 } else if (tag.equals("H") || tag.equals("FH")) {
214 attribute.addInteger(2, value);
215 } else if (tag.equals("SH")) {
216 attribute.addInteger(2, (short) value);
217 } else if (tag.equals("I") || tag.equals("FI") || tag.equals("SI")) {
218 attribute.addInteger(4, value);
219 } else if (tag.equals("V") || tag.equals("FV") || tag.equals("SV")) {
220
221
222 } else if (tag.startsWith("PO")) {
223 final char uintType = tag.substring(2).toCharArray()[0];
224 final int length = getLength(uintType);
225 attribute.addBCOffset(length, value);
226 } else if (tag.startsWith("P")) {
227 final char uintType = tag.substring(1).toCharArray()[0];
228 final int length = getLength(uintType);
229 attribute.addBCIndex(length, value);
230 } else if (tag.startsWith("OS")) {
231 final char uintType = tag.substring(2).toCharArray()[0];
232 final int length = getLength(uintType);
233 switch (length) {
234 case 1:
235 value = (byte) value;
236 break;
237 case 2:
238 value = (short) value;
239 break;
240 case 4:
241 value = value;
242 break;
243 default:
244 break;
245 }
246 attribute.addBCLength(length, value);
247 } else if (tag.startsWith("O")) {
248 final char uintType = tag.substring(1).toCharArray()[0];
249 final int length = getLength(uintType);
250 attribute.addBCLength(length, value);
251 }
252 }
253
254 public String getTag() {
255 return tag;
256 }
257
258 int getValue(final int index) {
259 return band[index];
260 }
261
262 @Override
263 public void readBands(final InputStream in, final int count) throws IOException, Pack200Exception {
264 band = decodeBandInt(attributeLayout.getName() + "_" + tag, in, getCodec(tag), count);
265 }
266
267 }
268
269 private abstract static class LayoutElement implements AttributeLayoutElement {
270
271 protected int getLength(final char uintType) {
272 int length = 0;
273 switch (uintType) {
274 case 'B':
275 length = 1;
276 break;
277 case 'H':
278 length = 2;
279 break;
280 case 'I':
281 length = 4;
282 break;
283 case 'V':
284 length = 0;
285 break;
286 }
287 return length;
288 }
289 }
290
291
292
293
294 public class Reference extends LayoutElement {
295
296 private final String tag;
297
298 private Object band;
299
300 private final int length;
301
302 public Reference(final String tag) {
303 this.tag = tag;
304 length = getLength(tag.charAt(tag.length() - 1));
305 }
306
307 @Override
308 public void addToAttribute(final int n, final NewAttribute attribute) {
309 if (tag.startsWith("KI")) {
310 attribute.addToBody(length, ((CPInteger[]) band)[n]);
311 } else if (tag.startsWith("KJ")) {
312 attribute.addToBody(length, ((CPLong[]) band)[n]);
313 } else if (tag.startsWith("KF")) {
314 attribute.addToBody(length, ((CPFloat[]) band)[n]);
315 } else if (tag.startsWith("KD")) {
316 attribute.addToBody(length, ((CPDouble[]) band)[n]);
317 } else if (tag.startsWith("KS")) {
318 attribute.addToBody(length, ((CPString[]) band)[n]);
319 } else if (tag.startsWith("RC")) {
320 attribute.addToBody(length, ((CPClass[]) band)[n]);
321 } else if (tag.startsWith("RS")) {
322 attribute.addToBody(length, ((CPUTF8[]) band)[n]);
323 } else if (tag.startsWith("RD")) {
324 attribute.addToBody(length, ((CPNameAndType[]) band)[n]);
325 } else if (tag.startsWith("RF")) {
326 attribute.addToBody(length, ((CPFieldRef[]) band)[n]);
327 } else if (tag.startsWith("RM")) {
328 attribute.addToBody(length, ((CPMethodRef[]) band)[n]);
329 } else if (tag.startsWith("RI")) {
330 attribute.addToBody(length, ((CPInterfaceMethodRef[]) band)[n]);
331 } else if (tag.startsWith("RU")) {
332 attribute.addToBody(length, ((CPUTF8[]) band)[n]);
333 }
334 }
335
336 public String getTag() {
337 return tag;
338 }
339
340 @Override
341 public void readBands(final InputStream in, final int count) throws IOException, Pack200Exception {
342 if (tag.startsWith("KI")) {
343 band = parseCPIntReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
344 } else if (tag.startsWith("KJ")) {
345 band = parseCPLongReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
346 } else if (tag.startsWith("KF")) {
347 band = parseCPFloatReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
348 } else if (tag.startsWith("KD")) {
349 band = parseCPDoubleReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
350 } else if (tag.startsWith("KS")) {
351 band = parseCPStringReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
352 } else if (tag.startsWith("RC")) {
353 band = parseCPClassReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
354 } else if (tag.startsWith("RS")) {
355 band = parseCPSignatureReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
356 } else if (tag.startsWith("RD")) {
357 band = parseCPDescriptorReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
358 } else if (tag.startsWith("RF")) {
359 band = parseCPFieldRefReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
360 } else if (tag.startsWith("RM")) {
361 band = parseCPMethodRefReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
362 } else if (tag.startsWith("RI")) {
363 band = parseCPInterfaceMethodRefReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
364 } else if (tag.startsWith("RU")) {
365 band = parseCPUTF8References(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
366 }
367 }
368
369 }
370
371
372
373
374 public class Replication extends LayoutElement {
375
376 private final Integral countElement;
377
378 private final List<LayoutElement> layoutElements = new ArrayList<>();
379
380 public Replication(final String tag, final String contents) throws IOException {
381 this.countElement = new Integral(tag);
382 final StringReader stream = new StringReader(contents);
383 LayoutElement e;
384 while ((e = readNextLayoutElement(stream)) != null) {
385 layoutElements.add(e);
386 }
387 }
388
389 @Override
390 public void addToAttribute(final int index, final NewAttribute attribute) {
391
392 countElement.addToAttribute(index, attribute);
393
394
395 int offset = 0;
396 for (int i = 0; i < index; i++) {
397 offset += countElement.getValue(i);
398 }
399 final long numElements = countElement.getValue(index);
400 for (int i = offset; i < offset + numElements; i++) {
401 for (final LayoutElement layoutElement : layoutElements) {
402 layoutElement.addToAttribute(i, attribute);
403 }
404 }
405 }
406
407 public Integral getCountElement() {
408 return countElement;
409 }
410
411 public List<LayoutElement> getLayoutElements() {
412 return layoutElements;
413 }
414
415 @Override
416 public void readBands(final InputStream in, final int count) throws IOException, Pack200Exception {
417 countElement.readBands(in, count);
418 int arrayCount = 0;
419 for (int i = 0; i < count; i++) {
420 arrayCount += countElement.getValue(i);
421 }
422 for (final LayoutElement layoutElement : layoutElements) {
423 layoutElement.readBands(in, arrayCount);
424 }
425 }
426 }
427
428
429
430
431 public class Union extends LayoutElement {
432
433 private final Integral unionTag;
434 private final List<UnionCase> unionCases;
435 private final List<LayoutElement> defaultCaseBody;
436 private int[] caseCounts;
437 private int defaultCount;
438
439 public Union(final String tag, final List<UnionCase> unionCases, final List<LayoutElement> body) {
440 this.unionTag = new Integral(tag);
441 this.unionCases = unionCases;
442 this.defaultCaseBody = body;
443 }
444
445 @Override
446 public void addToAttribute(final int n, final NewAttribute attribute) {
447 unionTag.addToAttribute(n, attribute);
448 int offset = 0;
449 final int[] tagBand = unionTag.band;
450 final int tag = unionTag.getValue(n);
451 boolean defaultCase = true;
452 for (final UnionCase unionCase : unionCases) {
453 if (unionCase.hasTag(tag)) {
454 defaultCase = false;
455 for (int j = 0; j < n; j++) {
456 if (unionCase.hasTag(tagBand[j])) {
457 offset++;
458 }
459 }
460 unionCase.addToAttribute(offset, attribute);
461 }
462 }
463 if (defaultCase) {
464
465 int defaultOffset = 0;
466 for (int j = 0; j < n; j++) {
467 boolean found = false;
468 for (final UnionCase unionCase : unionCases) {
469 if (unionCase.hasTag(tagBand[j])) {
470 found = true;
471 }
472 }
473 if (!found) {
474 defaultOffset++;
475 }
476 }
477 if (defaultCaseBody != null) {
478 for (final LayoutElement element : defaultCaseBody) {
479 element.addToAttribute(defaultOffset, attribute);
480 }
481 }
482 }
483 }
484
485 public List<LayoutElement> getDefaultCaseBody() {
486 return defaultCaseBody;
487 }
488
489 public List<UnionCase> getUnionCases() {
490 return unionCases;
491 }
492
493 public Integral getUnionTag() {
494 return unionTag;
495 }
496
497 @Override
498 public void readBands(final InputStream in, final int count) throws IOException, Pack200Exception {
499 unionTag.readBands(in, count);
500 final int[] values = unionTag.band;
501
502 caseCounts = new int[unionCases.size()];
503 for (int i = 0; i < caseCounts.length; i++) {
504 final UnionCase unionCase = unionCases.get(i);
505 for (final int value : values) {
506 if (unionCase.hasTag(value)) {
507 caseCounts[i]++;
508 }
509 }
510 unionCase.readBands(in, caseCounts[i]);
511 }
512
513 for (final int value : values) {
514 boolean found = false;
515 for (final UnionCase unionCase : unionCases) {
516 if (unionCase.hasTag(value)) {
517 found = true;
518 }
519 }
520 if (!found) {
521 defaultCount++;
522 }
523 }
524 if (defaultCaseBody != null) {
525 for (final LayoutElement element : defaultCaseBody) {
526 element.readBands(in, defaultCount);
527 }
528 }
529 }
530
531 }
532
533
534
535
536 public class UnionCase extends LayoutElement {
537
538 private List<LayoutElement> body;
539
540 private final List<Integer> tags;
541
542 public UnionCase(final List<Integer> tags) {
543 this.tags = tags;
544 }
545
546 public UnionCase(final List<Integer> tags, final List<LayoutElement> body) {
547 this.tags = tags;
548 this.body = body;
549 }
550
551 @Override
552 public void addToAttribute(final int index, final NewAttribute attribute) {
553 if (body != null) {
554 for (final LayoutElement element : body) {
555 element.addToAttribute(index, attribute);
556 }
557 }
558 }
559
560 public List<LayoutElement> getBody() {
561 return body == null ? Collections.EMPTY_LIST : body;
562 }
563
564 public boolean hasTag(final int i) {
565 return tags.contains(Integer.valueOf(i));
566 }
567
568 public boolean hasTag(final long l) {
569 return tags.contains(Integer.valueOf((int) l));
570 }
571
572 @Override
573 public void readBands(final InputStream in, final int count) throws IOException, Pack200Exception {
574 if (body != null) {
575 for (final LayoutElement element : body) {
576 element.readBands(in, count);
577 }
578 }
579 }
580 }
581
582 private final AttributeLayout attributeLayout;
583
584 private int backwardsCallCount;
585
586 protected List<AttributeLayoutElement> attributeLayoutElements;
587
588 public NewAttributeBands(final Segment segment, final AttributeLayout attributeLayout) throws IOException {
589 super(segment);
590 this.attributeLayout = attributeLayout;
591 parseLayout();
592 attributeLayout.setBackwardsCallCount(backwardsCallCount);
593 }
594
595 public int getBackwardsCallCount() {
596 return backwardsCallCount;
597 }
598
599
600
601
602
603
604
605 public BHSDCodec getCodec(final String layoutElement) {
606 if (layoutElement.indexOf('O') >= 0) {
607 return Codec.BRANCH5;
608 }
609 if (layoutElement.indexOf('P') >= 0) {
610 return Codec.BCI5;
611 }
612 if (layoutElement.indexOf('S') >= 0 && !layoutElement.contains("KS")
613 && !layoutElement.contains("RS")) {
614 return Codec.SIGNED5;
615 }
616 if (layoutElement.indexOf('B') >= 0) {
617 return Codec.BYTE1;
618 }
619 return Codec.UNSIGNED5;
620 }
621
622
623
624
625
626
627
628
629 private Attribute getOneAttribute(final int index, final List<AttributeLayoutElement> elements) {
630 final NewAttribute attribute = new NewAttribute(segment.getCpBands().cpUTF8Value(attributeLayout.getName()), attributeLayout.getIndex());
631 for (final AttributeLayoutElement element : elements) {
632 element.addToAttribute(index, attribute);
633 }
634 return attribute;
635 }
636
637
638
639
640
641
642
643
644 private StringReader getStreamUpToMatchingBracket(final StringReader stream) throws IOException {
645 final StringBuilder sb = new StringBuilder();
646 int foundBracket = -1;
647 while (foundBracket != 0) {
648 final int read = stream.read();
649 if (read == -1) {
650 break;
651 }
652 final char c = (char) read;
653 if (c == ']') {
654 foundBracket++;
655 }
656 if (c == '[') {
657 foundBracket--;
658 }
659 if (!(foundBracket == 0)) {
660 sb.append(c);
661 }
662 }
663 return new StringReader(sb.toString());
664 }
665
666
667
668
669
670
671
672
673
674
675 public List<Attribute> parseAttributes(final InputStream in, final int occurrenceCount) throws IOException, Pack200Exception {
676 for (final AttributeLayoutElement element : attributeLayoutElements) {
677 element.readBands(in, occurrenceCount);
678 }
679
680 final List<Attribute> attributes = new ArrayList<>(occurrenceCount);
681 for (int i = 0; i < occurrenceCount; i++) {
682 attributes.add(getOneAttribute(i, attributeLayoutElements));
683 }
684 return attributes;
685 }
686
687
688
689
690
691
692 private void parseLayout() throws IOException {
693 if (attributeLayoutElements == null) {
694 attributeLayoutElements = new ArrayList<>();
695 final StringReader stream = new StringReader(attributeLayout.getLayout());
696 AttributeLayoutElement e;
697 while ((e = readNextAttributeElement(stream)) != null) {
698 attributeLayoutElements.add(e);
699 }
700 resolveCalls();
701 }
702 }
703
704
705
706
707
708
709 @Override
710 public void read(final InputStream in) throws IOException, Pack200Exception {
711
712 }
713
714
715
716
717
718
719
720
721 private List<LayoutElement> readBody(final StringReader stream) throws IOException {
722 final List<LayoutElement> layoutElements = new ArrayList<>();
723 LayoutElement e;
724 while ((e = readNextLayoutElement(stream)) != null) {
725 layoutElements.add(e);
726 }
727 return layoutElements;
728 }
729
730 private AttributeLayoutElement readNextAttributeElement(final StringReader stream) throws IOException {
731 stream.mark(1);
732 final int next = stream.read();
733 if (next == -1) {
734 return null;
735 }
736 if (next == '[') {
737 return new Callable(readBody(getStreamUpToMatchingBracket(stream)));
738 }
739 stream.reset();
740 return readNextLayoutElement(stream);
741 }
742
743 private LayoutElement readNextLayoutElement(final StringReader stream) throws IOException {
744 final int nextChar = stream.read();
745 if (nextChar == -1) {
746 return null;
747 }
748 switch (nextChar) {
749
750 case 'B':
751 case 'H':
752 case 'I':
753 case 'V':
754 return new Integral(new String(new char[] { (char) nextChar }));
755 case 'S':
756 case 'F':
757 return new Integral(new String(new char[] { (char) nextChar, (char) stream.read() }));
758 case 'P':
759 stream.mark(1);
760 if (stream.read() != 'O') {
761 stream.reset();
762 return new Integral("P" + (char) stream.read());
763 }
764 return new Integral("PO" + (char) stream.read());
765 case 'O':
766 stream.mark(1);
767 if (stream.read() != 'S') {
768 stream.reset();
769 return new Integral("O" + (char) stream.read());
770 }
771 return new Integral("OS" + (char) stream.read());
772
773
774 case 'N':
775 final char uintType = (char) stream.read();
776 stream.read();
777 final String str = readUpToMatchingBracket(stream);
778 return new Replication("" + uintType, str);
779
780
781 case 'T':
782 String intType = "" + (char) stream.read();
783 if (intType.equals("S")) {
784 intType += (char) stream.read();
785 }
786 final List<UnionCase> unionCases = new ArrayList<>();
787 UnionCase c;
788 while ((c = readNextUnionCase(stream)) != null) {
789 unionCases.add(c);
790 }
791 stream.read();
792 stream.read();
793 stream.read();
794 List<LayoutElement> body = null;
795 stream.mark(1);
796 final char next = (char) stream.read();
797 if (next != ']') {
798 stream.reset();
799 body = readBody(getStreamUpToMatchingBracket(stream));
800 }
801 return new Union(intType, unionCases, body);
802
803
804 case '(':
805 final int number = readNumber(stream).intValue();
806 stream.read();
807 return new Call(number);
808
809 case 'K':
810 case 'R':
811 final StringBuilder string = new StringBuilder("").append((char) nextChar).append((char) stream.read());
812 final char nxt = (char) stream.read();
813 string.append(nxt);
814 if (nxt == 'N') {
815 string.append((char) stream.read());
816 }
817 return new Reference(string.toString());
818 }
819 return null;
820 }
821
822
823
824
825
826
827
828
829 private UnionCase readNextUnionCase(final StringReader stream) throws IOException {
830 stream.mark(2);
831 stream.read();
832 final int next = stream.read();
833 char ch = (char) next;
834 if (ch == ')' || next == -1) {
835 stream.reset();
836 return null;
837 }
838 stream.reset();
839 stream.read();
840 final List<Integer> tags = new ArrayList<>();
841 Integer nextTag;
842 do {
843 nextTag = readNumber(stream);
844 if (nextTag != null) {
845 tags.add(nextTag);
846 stream.read();
847 }
848 } while (nextTag != null);
849 stream.read();
850 stream.mark(1);
851 ch = (char) stream.read();
852 if (ch == ']') {
853 return new UnionCase(tags);
854 }
855 stream.reset();
856 return new UnionCase(tags, readBody(getStreamUpToMatchingBracket(stream)));
857 }
858
859
860
861
862
863
864
865
866 private Integer readNumber(final StringReader stream) throws IOException {
867 stream.mark(1);
868 final char first = (char) stream.read();
869 final boolean negative = first == '-';
870 if (!negative) {
871 stream.reset();
872 }
873 stream.mark(100);
874 int i;
875 int length = 0;
876 while ((i = stream.read()) != -1 && Character.isDigit((char) i)) {
877 length++;
878 }
879 stream.reset();
880 if (length == 0) {
881 return null;
882 }
883 final char[] digits = new char[length];
884 final int read = stream.read(digits);
885 if (read != digits.length) {
886 throw new IOException("Error reading from the input stream");
887 }
888 return ParsingUtils.parseIntValue((negative ? "-" : "") + new String(digits));
889 }
890
891
892
893
894
895
896
897
898 private String readUpToMatchingBracket(final StringReader stream) throws IOException {
899 final StringBuilder sb = new StringBuilder();
900 int foundBracket = -1;
901 while (foundBracket != 0) {
902 final int read = stream.read();
903 if (read == -1) {
904 break;
905 }
906 final char c = (char) read;
907 if (c == ']') {
908 foundBracket++;
909 }
910 if (c == '[') {
911 foundBracket--;
912 }
913 if (!(foundBracket == 0)) {
914 sb.append(c);
915 }
916 }
917 return sb.toString();
918 }
919
920
921
922
923 private void resolveCalls() {
924 int backwardsCalls = 0;
925 for (int i = 0; i < attributeLayoutElements.size(); i++) {
926 final AttributeLayoutElement element = attributeLayoutElements.get(i);
927 if (element instanceof Callable) {
928 final Callable callable = (Callable) element;
929 if (i == 0) {
930 callable.setFirstCallable(true);
931 }
932
933 for (final LayoutElement layoutElement : callable.body) {
934
935 backwardsCalls += resolveCallsForElement(i, callable, layoutElement);
936 }
937 }
938 }
939 backwardsCallCount = backwardsCalls;
940 }
941
942 private int resolveCallsForElement(final int i, final Callable currentCallable, final LayoutElement layoutElement) {
943 int backwardsCalls = 0;
944 if (layoutElement instanceof Call) {
945 final Call call = (Call) layoutElement;
946 int index = call.callableIndex;
947 if (index == 0) {
948 backwardsCalls++;
949 call.setCallable(currentCallable);
950 } else if (index > 0) {
951 for (int k = i + 1; k < attributeLayoutElements.size(); k++) {
952 final AttributeLayoutElement el = attributeLayoutElements.get(k);
953 if (el instanceof Callable) {
954 index--;
955 if (index == 0) {
956 call.setCallable((Callable) el);
957 break;
958 }
959 }
960 }
961 } else {
962 backwardsCalls++;
963 for (int k = i - 1; k >= 0; k--) {
964 final AttributeLayoutElement el = attributeLayoutElements.get(k);
965 if (el instanceof Callable) {
966 index++;
967 if (index == 0) {
968 call.setCallable((Callable) el);
969 break;
970 }
971 }
972 }
973 }
974 } else if (layoutElement instanceof Replication) {
975 final List<LayoutElement> children = ((Replication) layoutElement).layoutElements;
976 for (final LayoutElement child : children) {
977 backwardsCalls += resolveCallsForElement(i, currentCallable, child);
978 }
979 }
980 return backwardsCalls;
981 }
982
983
984
985
986
987
988
989
990 public void setBackwardsCalls(final int[] backwardsCalls) throws IOException {
991 int index = 0;
992 parseLayout();
993 for (final AttributeLayoutElement element : attributeLayoutElements) {
994 if (element instanceof Callable && ((Callable) element).isBackwardsCallable()) {
995 ((Callable) element).addCount(backwardsCalls[index]);
996 index++;
997 }
998 }
999 }
1000
1001 @Override
1002 public void unpack() throws IOException, Pack200Exception {
1003
1004 }
1005
1006 }