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.util.List;
20
21 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
22 import org.apache.commons.compress.harmony.unpack200.bytecode.ClassFileEntry;
23 import org.apache.commons.compress.harmony.unpack200.bytecode.ConstantPoolEntry;
24
25
26
27
28 public class SegmentConstantPool {
29
30 public static final int ALL = 0;
31 public static final int UTF_8 = 1;
32
33 public static final int CP_INT = 2;
34
35
36
37 public static final int CP_FLOAT = 3;
38 public static final int CP_LONG = 4;
39 public static final int CP_DOUBLE = 5;
40 public static final int CP_STRING = 6;
41 public static final int CP_CLASS = 7;
42 public static final int SIGNATURE = 8;
43 public static final int CP_DESCR = 9;
44 public static final int CP_FIELD = 10;
45 public static final int CP_METHOD = 11;
46 public static final int CP_IMETHOD = 12;
47 protected static final String REGEX_MATCH_ALL = ".*";
48 protected static final String INITSTRING = "<init>";
49 protected static final String REGEX_MATCH_INIT = "^" + INITSTRING + ".*";
50
51
52
53
54
55
56
57
58
59
60 protected static boolean regexMatches(final String regexString, final String compareString) {
61 if (REGEX_MATCH_ALL.equals(regexString)) {
62 return true;
63 }
64 if (REGEX_MATCH_INIT.equals(regexString)) {
65 if (compareString.length() < INITSTRING.length()) {
66 return false;
67 }
68 return INITSTRING.equals(compareString.substring(0, INITSTRING.length()));
69 }
70 throw new Error("regex trying to match a pattern I don't know: " + regexString);
71 }
72
73 private final CpBands bands;
74 private final SegmentConstantPoolArrayCache arrayCache = new SegmentConstantPoolArrayCache();
75
76
77
78
79 public SegmentConstantPool(final CpBands bands) {
80 this.bands = bands;
81 }
82
83
84
85
86
87
88
89 public ConstantPoolEntry getClassPoolEntry(final String name) {
90 final String[] classes = bands.getCpClass();
91 final int index = matchSpecificPoolEntryIndex(classes, name, 0);
92 if (index == -1) {
93 return null;
94 }
95 try {
96 return getConstantPoolEntry(CP_CLASS, index);
97 } catch (final Pack200Exception ex) {
98 throw new Error("Error getting class pool entry");
99 }
100 }
101
102
103
104
105
106
107
108
109
110
111
112 public ConstantPoolEntry getClassSpecificPoolEntry(final int cp, final long desiredIndex, final String desiredClassName) throws Pack200Exception {
113 final int index = (int) desiredIndex;
114 int realIndex = -1;
115 String[] array;
116 switch (cp) {
117 case CP_FIELD:
118 array = bands.getCpFieldClass();
119 break;
120 case CP_METHOD:
121 array = bands.getCpMethodClass();
122 break;
123 case CP_IMETHOD:
124 array = bands.getCpIMethodClass();
125 break;
126 default:
127 throw new Error("Don't know how to handle " + cp);
128 }
129 realIndex = matchSpecificPoolEntryIndex(array, desiredClassName, index);
130 return getConstantPoolEntry(cp, realIndex);
131 }
132
133 public ConstantPoolEntry getConstantPoolEntry(final int cp, final long value) throws Pack200Exception {
134 final int index = (int) value;
135 if (index == -1) {
136 return null;
137 }
138 if (index < 0) {
139 throw new Pack200Exception("Cannot have a negative range");
140 }
141 switch (cp) {
142 case UTF_8:
143 return bands.cpUTF8Value(index);
144 case CP_INT:
145 return bands.cpIntegerValue(index);
146 case CP_FLOAT:
147 return bands.cpFloatValue(index);
148 case CP_LONG:
149 return bands.cpLongValue(index);
150 case CP_DOUBLE:
151 return bands.cpDoubleValue(index);
152 case CP_STRING:
153 return bands.cpStringValue(index);
154 case CP_CLASS:
155 return bands.cpClassValue(index);
156 case SIGNATURE:
157 throw new Error("I don't know what to do with signatures yet");
158
159 case CP_DESCR:
160 throw new Error("I don't know what to do with descriptors yet");
161
162
163 case CP_FIELD:
164 return bands.cpFieldValue(index);
165 case CP_METHOD:
166 return bands.cpMethodValue(index);
167 case CP_IMETHOD:
168 return bands.cpIMethodValue(index);
169 default:
170 break;
171 }
172
173 throw new Error("Get value incomplete");
174 }
175
176
177
178
179
180
181
182
183
184
185 public ConstantPoolEntry getInitMethodPoolEntry(final int cp, final long value, final String desiredClassName) throws Pack200Exception {
186 int realIndex = -1;
187 if (cp != CP_METHOD) {
188
189 throw new Error("Nothing but CP_METHOD can be an <init>");
190 }
191 realIndex = matchSpecificPoolEntryIndex(bands.getCpMethodClass(), bands.getCpMethodDescriptor(), desiredClassName, REGEX_MATCH_INIT, (int) value);
192 return getConstantPoolEntry(cp, realIndex);
193 }
194
195 public ClassFileEntry getValue(final int cp, final long value) throws Pack200Exception {
196 final int index = (int) value;
197 if (index == -1) {
198 return null;
199 }
200 if (index < 0) {
201 throw new Pack200Exception("Cannot have a negative range");
202 }
203 switch (cp) {
204 case UTF_8:
205 return bands.cpUTF8Value(index);
206 case CP_INT:
207 return bands.cpIntegerValue(index);
208 case CP_FLOAT:
209 return bands.cpFloatValue(index);
210 case CP_LONG:
211 return bands.cpLongValue(index);
212 case CP_DOUBLE:
213 return bands.cpDoubleValue(index);
214 case CP_STRING:
215 return bands.cpStringValue(index);
216 case CP_CLASS:
217 return bands.cpClassValue(index);
218 case SIGNATURE:
219 return bands.cpSignatureValue(index);
220 case CP_DESCR:
221 return bands.cpNameAndTypeValue(index);
222 default:
223 break;
224 }
225 throw new Error("Tried to get a value I don't know about: " + cp);
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 protected int matchSpecificPoolEntryIndex(final String[] nameArray, final String compareString, final int desiredIndex) {
246 return matchSpecificPoolEntryIndex(nameArray, nameArray, compareString, REGEX_MATCH_ALL, desiredIndex);
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260
261 protected int matchSpecificPoolEntryIndex(final String[] primaryArray, final String[] secondaryArray, final String primaryCompareString,
262 final String secondaryCompareRegex, final int desiredIndex) {
263 int instanceCount = -1;
264 final List<Integer> indexList = arrayCache.indexesForArrayKey(primaryArray, primaryCompareString);
265 if (indexList.isEmpty()) {
266
267 return -1;
268 }
269
270 for (final Integer element : indexList) {
271 final int arrayIndex = element.intValue();
272 if (regexMatches(secondaryCompareRegex, secondaryArray[arrayIndex])) {
273 instanceCount++;
274 if (instanceCount == desiredIndex) {
275 return arrayIndex;
276 }
277 }
278 }
279
280
281 return -1;
282 }
283 }