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.Arrays;
25 import java.util.List;
26
27 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
28
29
30
31
32 public class LocalVariableTableAttribute extends BCIRenumberedAttribute {
33
34 private static CPUTF8 attributeName;
35
36 public static void setAttributeName(final CPUTF8 cpUTF8Value) {
37 attributeName = cpUTF8Value;
38 }
39
40 private final int localVariableTableLength;
41 private final int[] startPcs;
42 private final int[] lengths;
43 private int[] nameIndexes;
44 private int[] descriptorIndexes;
45 private final int[] indexes;
46 private final CPUTF8[] names;
47 private final CPUTF8[] descriptors;
48
49 private int codeLength;
50
51 public LocalVariableTableAttribute(final int localVariableTableLength, final int[] startPcs, final int[] lengths, final CPUTF8[] names,
52 final CPUTF8[] descriptors, final int[] indexes) {
53 super(attributeName);
54 this.localVariableTableLength = localVariableTableLength;
55 this.startPcs = startPcs;
56 this.lengths = lengths;
57 this.names = names;
58 this.descriptors = descriptors;
59 this.indexes = indexes;
60 }
61
62 @Override
63 protected int getLength() {
64 return 2 + 10 * localVariableTableLength;
65 }
66
67 @Override
68 protected ClassFileEntry[] getNestedClassFileEntries() {
69 final List<CPUTF8> nestedEntries = new ArrayList<>();
70 nestedEntries.add(getAttributeName());
71 for (int i = 0; i < localVariableTableLength; i++) {
72 nestedEntries.add(names[i]);
73 nestedEntries.add(descriptors[i]);
74 }
75 return nestedEntries.toArray(NONE);
76 }
77
78 @Override
79 protected int[] getStartPCs() {
80 return startPcs;
81 }
82
83
84
85
86
87
88 @Override
89 public void renumber(final List<Integer> byteCodeOffsets) throws Pack200Exception {
90
91
92 final int[] unrenumberedStartPcs = Arrays.copyOf(startPcs, startPcs.length);
93
94
95 super.renumber(byteCodeOffsets);
96
97
98
99
100
101
102
103
104
105 final int maxSize = codeLength;
106
107
108
109 for (int index = 0; index < lengths.length; index++) {
110 final int startPc = startPcs[index];
111 int revisedLength = -1;
112 final int encodedLength = lengths[index];
113
114
115 final int indexOfStartPC = unrenumberedStartPcs[index];
116
117
118 final int stopIndex = indexOfStartPC + encodedLength;
119 if (stopIndex < 0) {
120 throw new Pack200Exception("Error renumbering bytecode indexes");
121 }
122
123
124
125 if (stopIndex == byteCodeOffsets.size()) {
126
127 revisedLength = maxSize - startPc;
128 } else {
129
130 final int stopValue = byteCodeOffsets.get(stopIndex).intValue();
131 revisedLength = stopValue - startPc;
132 }
133 lengths[index] = revisedLength;
134 }
135 }
136
137 @Override
138 protected void resolve(final ClassConstantPool pool) {
139 super.resolve(pool);
140 nameIndexes = new int[localVariableTableLength];
141 descriptorIndexes = new int[localVariableTableLength];
142 for (int i = 0; i < localVariableTableLength; i++) {
143 names[i].resolve(pool);
144 descriptors[i].resolve(pool);
145 nameIndexes[i] = pool.indexOf(names[i]);
146 descriptorIndexes[i] = pool.indexOf(descriptors[i]);
147 }
148 }
149
150 public void setCodeLength(final int length) {
151 codeLength = length;
152 }
153
154 @Override
155 public String toString() {
156 return "LocalVariableTable: " + +localVariableTableLength + " variables";
157 }
158
159 @Override
160 protected void writeBody(final DataOutputStream dos) throws IOException {
161 dos.writeShort(localVariableTableLength);
162 for (int i = 0; i < localVariableTableLength; i++) {
163 dos.writeShort(startPcs[i]);
164 dos.writeShort(lengths[i]);
165 dos.writeShort(nameIndexes[i]);
166 dos.writeShort(descriptorIndexes[i]);
167 dos.writeShort(indexes[i]);
168 }
169 }
170 }