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