1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.data;
18
19
20
21
22
23
24
25
26 import java.io.DataOutputStream;
27 import java.io.IOException;
28
29 import org.apache.bcel.Const;
30 import org.apache.bcel.classfile.ClassFormatException;
31 import org.apache.bcel.classfile.Constant;
32 import org.apache.bcel.classfile.ConstantCP;
33 import org.apache.bcel.classfile.ConstantClass;
34 import org.apache.bcel.classfile.ConstantDouble;
35 import org.apache.bcel.classfile.ConstantFloat;
36 import org.apache.bcel.classfile.ConstantInteger;
37 import org.apache.bcel.classfile.ConstantInvokeDynamic;
38 import org.apache.bcel.classfile.ConstantLong;
39 import org.apache.bcel.classfile.ConstantMethodHandle;
40 import org.apache.bcel.classfile.ConstantMethodType;
41 import org.apache.bcel.classfile.ConstantModule;
42 import org.apache.bcel.classfile.ConstantNameAndType;
43 import org.apache.bcel.classfile.ConstantPackage;
44 import org.apache.bcel.classfile.ConstantString;
45 import org.apache.bcel.classfile.ConstantUtf8;
46 import org.apache.bcel.classfile.Node;
47 import org.apache.bcel.classfile.Utility;
48
49
50
51
52
53
54
55
56
57
58 public abstract class ConstantPoolX implements Cloneable, Node {
59
60 private static String escape(final String str) {
61 final int len = str.length();
62 final StringBuilder buf = new StringBuilder(len + 5);
63 final char[] ch = str.toCharArray();
64 for (int i = 0; i < len; i++) {
65 switch (ch[i]) {
66 case '\n':
67 buf.append("\\n");
68 break;
69 case '\r':
70 buf.append("\\r");
71 break;
72 case '\t':
73 buf.append("\\t");
74 break;
75 case '\b':
76 buf.append("\\b");
77 break;
78 case '"':
79 buf.append("\\\"");
80 break;
81 default:
82 buf.append(ch[i]);
83 }
84 }
85 return buf.toString();
86 }
87
88 private Constant[] constantPool;
89
90
91
92
93
94
95
96 public String constantToString(Constant c) throws ClassFormatException {
97 String str;
98 int i;
99 final byte tag = c.getTag();
100 switch (tag) {
101 case Const.CONSTANT_Class:
102 i = ((ConstantClass) c).getNameIndex();
103 c = getConstant(i, Const.CONSTANT_Utf8);
104 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
105 break;
106 case Const.CONSTANT_String:
107 i = ((ConstantString) c).getStringIndex();
108 c = getConstant(i, Const.CONSTANT_Utf8);
109 str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
110 break;
111 case Const.CONSTANT_Utf8:
112 str = ((ConstantUtf8) c).getBytes();
113 break;
114 case Const.CONSTANT_Double:
115 str = String.valueOf(((ConstantDouble) c).getBytes());
116 break;
117 case Const.CONSTANT_Float:
118 str = String.valueOf(((ConstantFloat) c).getBytes());
119 break;
120 case Const.CONSTANT_Long:
121 str = String.valueOf(((ConstantLong) c).getBytes());
122 break;
123 case Const.CONSTANT_Integer:
124 str = String.valueOf(((ConstantInteger) c).getBytes());
125 break;
126 case Const.CONSTANT_NameAndType:
127 str = constantToString(((ConstantNameAndType) c).getNameIndex(), Const.CONSTANT_Utf8) + " "
128 + constantToString(((ConstantNameAndType) c).getSignatureIndex(), Const.CONSTANT_Utf8);
129 break;
130 case Const.CONSTANT_InterfaceMethodref:
131 case Const.CONSTANT_Methodref:
132 case Const.CONSTANT_Fieldref:
133 str = constantToString(((ConstantCP) c).getClassIndex(), Const.CONSTANT_Class) + "."
134 + constantToString(((ConstantCP) c).getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
135 break;
136 case Const.CONSTANT_MethodHandle:
137
138
139 final ConstantMethodHandle cmh = (ConstantMethodHandle) c;
140 str = Const.getMethodHandleName(cmh.getReferenceKind()) + " "
141 + constantToString(cmh.getReferenceIndex(), getConstant(cmh.getReferenceIndex()).getTag());
142 break;
143 case Const.CONSTANT_MethodType:
144 final ConstantMethodType cmt = (ConstantMethodType) c;
145 str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8);
146 break;
147 case Const.CONSTANT_InvokeDynamic:
148 final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c;
149 str = cid.getBootstrapMethodAttrIndex() + ":" + constantToString(cid.getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
150 break;
151 case Const.CONSTANT_Module:
152 i = ((ConstantModule) c).getNameIndex();
153 c = getConstant(i, Const.CONSTANT_Utf8);
154 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
155 break;
156 case Const.CONSTANT_Package:
157 i = ((ConstantPackage) c).getNameIndex();
158 c = getConstant(i, Const.CONSTANT_Utf8);
159 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
160 break;
161 default:
162 throw new IllegalArgumentException("Unknown constant type " + tag);
163 }
164 return str;
165 }
166
167
168
169
170
171
172
173
174 public String constantToString(final int index, final byte tag) throws ClassFormatException {
175 final Constant c = getConstant(index, tag);
176 return constantToString(c);
177 }
178
179
180
181
182
183
184
185 public void dump(final DataOutputStream file) throws IOException {
186 file.writeShort(constantPool.length);
187 for (int i = 1; i < constantPool.length; i++) {
188 if (constantPool[i] != null) {
189 constantPool[i].dump(file);
190 }
191 }
192 }
193
194
195
196
197
198
199
200
201 public Constant getConstant(final int index) {
202 if (index >= constantPool.length || index < 0) {
203 throw new ClassFormatException("Invalid constant pool reference: " + index + ". Constant pool size is: " + constantPool.length);
204 }
205 return constantPool[index];
206 }
207
208
209
210
211
212
213
214
215
216
217 public Constant getConstant(final int index, final byte tag) throws ClassFormatException {
218 Constant c;
219 c = getConstant(index);
220 if (c == null) {
221 throw new ClassFormatException("Constant pool at index " + index + " is null.");
222 }
223 if (c.getTag() != tag) {
224 throw new ClassFormatException("Expected class '" + Const.getConstantName(tag) + "' at index " + index + " and got " + c);
225 }
226 return c;
227 }
228
229
230
231
232
233 public Constant[] getConstantPool() {
234 return constantPool;
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249 public String getConstantString(final int index, final byte tag) throws ClassFormatException {
250 Constant c;
251 int i;
252 c = getConstant(index, tag);
253
254
255
256
257
258 switch (tag) {
259 case Const.CONSTANT_Class:
260 i = ((ConstantClass) c).getNameIndex();
261 break;
262 case Const.CONSTANT_String:
263 i = ((ConstantString) c).getStringIndex();
264 break;
265 case Const.CONSTANT_Module:
266 i = ((ConstantModule) c).getNameIndex();
267 break;
268 case Const.CONSTANT_Package:
269 i = ((ConstantPackage) c).getNameIndex();
270 break;
271 default:
272 throw new IllegalArgumentException("getConstantString called with illegal tag " + tag);
273 }
274
275 c = getConstant(i, Const.CONSTANT_Utf8);
276 return ((ConstantUtf8) c).getBytes();
277 }
278
279
280
281
282 public int getLength() {
283 return constantPool == null ? 0 : constantPool.length;
284 }
285
286
287
288
289 public void setConstant(final int index, final Constant constant) {
290 constantPool[index] = constant;
291 }
292
293
294
295
296 public void setConstantPool(final Constant[] constantPool) {
297 this.constantPool = constantPool;
298 }
299
300
301
302
303 @Override
304 public String toString() {
305 final StringBuilder buf = new StringBuilder();
306 for (int i = 1; i < constantPool.length; i++) {
307 buf.append(i).append(")").append(constantPool[i]).append("\n");
308 }
309 return buf.toString();
310 }
311
312 }