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