001 /*
002 * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.classfile;
027
028 import java.io.IOException;
029
030 /**
031 * See JVMS3, section 4.5.
032 *
033 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
034 * you write code that depends on this, you do so at your own risk.
035 * This code and its internal interfaces are subject to change or
036 * deletion without notice.</b>
037 */
038 public class ConstantPool {
039
040 public class InvalidIndex extends ConstantPoolException {
041 private static final long serialVersionUID = -4350294289300939730L;
042 InvalidIndex(int index) {
043 super(index);
044 }
045
046 @Override
047 public String getMessage() {
048 // i18n
049 return "invalid index #" + index;
050 }
051 }
052
053 public class UnexpectedEntry extends ConstantPoolException {
054 private static final long serialVersionUID = 6986335935377933211L;
055 UnexpectedEntry(int index, int expected_tag, int found_tag) {
056 super(index);
057 this.expected_tag = expected_tag;
058 this.found_tag = found_tag;
059 }
060
061 @Override
062 public String getMessage() {
063 // i18n?
064 return "unexpected entry at #" + index + " -- expected tag " + expected_tag + ", found " + found_tag;
065 }
066
067 public final int expected_tag;
068 public final int found_tag;
069 }
070
071 public class InvalidEntry extends ConstantPoolException {
072 private static final long serialVersionUID = 1000087545585204447L;
073 InvalidEntry(int index, int tag) {
074 super(index);
075 this.tag = tag;
076 }
077
078 @Override
079 public String getMessage() {
080 // i18n?
081 return "unexpected tag at #" + index + ": " + tag;
082 }
083
084 public final int tag;
085 }
086
087 public class EntryNotFound extends ConstantPoolException {
088 private static final long serialVersionUID = 2885537606468581850L;
089 EntryNotFound(Object value) {
090 super(-1);
091 this.value = value;
092 }
093
094 @Override
095 public String getMessage() {
096 // i18n?
097 return "value not found: " + value;
098 }
099
100 public final Object value;
101 }
102
103 public static final int CONSTANT_Utf8 = 1;
104 public static final int CONSTANT_Integer = 3;
105 public static final int CONSTANT_Float = 4;
106 public static final int CONSTANT_Long = 5;
107 public static final int CONSTANT_Double = 6;
108 public static final int CONSTANT_Class = 7;
109 public static final int CONSTANT_String = 8;
110 public static final int CONSTANT_Fieldref = 9;
111 public static final int CONSTANT_Methodref = 10;
112 public static final int CONSTANT_InterfaceMethodref = 11;
113 public static final int CONSTANT_NameAndType = 12;
114
115 ConstantPool(ClassReader cr) throws IOException, InvalidEntry {
116 int count = cr.readUnsignedShort();
117 pool = new CPInfo[count];
118 for (int i = 1; i < count; i++) {
119 int tag = cr.readUnsignedByte();
120 switch (tag) {
121 case CONSTANT_Class:
122 pool[i] = new CONSTANT_Class_info(this, cr);
123 break;
124
125 case CONSTANT_Double:
126 pool[i] = new CONSTANT_Double_info(cr);
127 i++;
128 break;
129
130 case CONSTANT_Fieldref:
131 pool[i] = new CONSTANT_Fieldref_info(this, cr);
132 break;
133
134 case CONSTANT_Float:
135 pool[i] = new CONSTANT_Float_info(cr);
136 break;
137
138 case CONSTANT_Integer:
139 pool[i] = new CONSTANT_Integer_info(cr);
140 break;
141
142 case CONSTANT_InterfaceMethodref:
143 pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr);
144 break;
145
146 case CONSTANT_Long:
147 pool[i] = new CONSTANT_Long_info(cr);
148 i++;
149 break;
150
151 case CONSTANT_Methodref:
152 pool[i] = new CONSTANT_Methodref_info(this, cr);
153 break;
154
155 case CONSTANT_NameAndType:
156 pool[i] = new CONSTANT_NameAndType_info(this, cr);
157 break;
158
159 case CONSTANT_String:
160 pool[i] = new CONSTANT_String_info(this, cr);
161 break;
162
163 case CONSTANT_Utf8:
164 pool[i] = new CONSTANT_Utf8_info(cr);
165 break;
166
167 default:
168 throw new InvalidEntry(i, tag);
169 }
170 }
171 }
172
173 public ConstantPool(CPInfo[] pool) {
174 this.pool = pool;
175 }
176
177 public int size() {
178 return pool.length;
179 }
180
181 public CPInfo get(int index) throws InvalidIndex {
182 if (index <= 0 || index >= pool.length)
183 throw new InvalidIndex(index);
184 CPInfo info = pool[index];
185 if (info == null) {
186 // this occurs for indices referencing the "second half" of an
187 // 8 byte constant, such as CONSTANT_Double or CONSTANT_Long
188 throw new InvalidIndex(index);
189 }
190 return pool[index];
191 }
192
193 private CPInfo get(int index, int expected_type) throws InvalidIndex, UnexpectedEntry {
194 CPInfo info = get(index);
195 if (info.getTag() != expected_type)
196 throw new UnexpectedEntry(index, expected_type, info.getTag());
197 return info;
198 }
199
200 public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry {
201 return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8));
202 }
203
204 public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry {
205 return ((CONSTANT_Class_info) get(index, CONSTANT_Class));
206 }
207
208 public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry {
209 return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType));
210 }
211
212 public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry {
213 return getUTF8Info(index).value;
214 }
215
216 public int getUTF8Index(String value) throws EntryNotFound {
217 for (int i = 1; i < pool.length; i++) {
218 CPInfo info = pool[i];
219 if (info instanceof CONSTANT_Utf8_info &&
220 ((CONSTANT_Utf8_info) info).value.equals(value))
221 return i;
222 }
223 throw new EntryNotFound(value);
224 }
225
226 private CPInfo[] pool;
227
228 public interface Visitor<R,P> {
229 R visitClass(CONSTANT_Class_info info, P p);
230 R visitDouble(CONSTANT_Double_info info, P p);
231 R visitFieldref(CONSTANT_Fieldref_info info, P p);
232 R visitFloat(CONSTANT_Float_info info, P p);
233 R visitInteger(CONSTANT_Integer_info info, P p);
234 R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p);
235 R visitLong(CONSTANT_Long_info info, P p);
236 R visitNameAndType(CONSTANT_NameAndType_info info, P p);
237 R visitMethodref(CONSTANT_Methodref_info info, P p);
238 R visitString(CONSTANT_String_info info, P p);
239 R visitUtf8(CONSTANT_Utf8_info info, P p);
240 }
241
242 public static abstract class CPInfo {
243 CPInfo() {
244 this.cp = null;
245 }
246
247 CPInfo(ConstantPool cp) {
248 this.cp = cp;
249 }
250
251 public abstract int getTag();
252
253 public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
254
255 protected final ConstantPool cp;
256 }
257
258 public static abstract class CPRefInfo extends CPInfo {
259 protected CPRefInfo(ConstantPool cp, ClassReader cr, int tag) throws IOException {
260 super(cp);
261 this.tag = tag;
262 class_index = cr.readUnsignedShort();
263 name_and_type_index = cr.readUnsignedShort();
264 }
265
266 protected CPRefInfo(ConstantPool cp, int tag, int class_index, int name_and_type_index) {
267 super(cp);
268 this.tag = tag;
269 this.class_index = class_index;
270 this.name_and_type_index = name_and_type_index;
271 }
272
273 public int getTag() {
274 return tag;
275 }
276
277 public CONSTANT_Class_info getClassInfo() throws ConstantPoolException {
278 return cp.getClassInfo(class_index);
279 }
280
281 public String getClassName() throws ConstantPoolException {
282 return cp.getClassInfo(class_index).getName();
283 }
284
285 public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
286 return cp.getNameAndTypeInfo(name_and_type_index);
287 }
288
289 public final int tag;
290 public final int class_index;
291 public final int name_and_type_index;
292 }
293
294 public static class CONSTANT_Class_info extends CPInfo {
295 CONSTANT_Class_info(ConstantPool cp, ClassReader cr) throws IOException {
296 super(cp);
297 name_index = cr.readUnsignedShort();
298 }
299
300 public CONSTANT_Class_info(ConstantPool cp, int name_index) {
301 super(cp);
302 this.name_index = name_index;
303 }
304
305 public int getTag() {
306 return CONSTANT_Class;
307 }
308
309 public String getName() throws ConstantPoolException {
310 return cp.getUTF8Value(name_index);
311 }
312
313 @Override
314 public String toString() {
315 return "CONSTANT_Class_info[name_index: " + name_index + "]";
316 }
317
318 public <R, D> R accept(Visitor<R, D> visitor, D data) {
319 return visitor.visitClass(this, data);
320 }
321
322 public final int name_index;
323 }
324
325 public static class CONSTANT_Double_info extends CPInfo {
326 CONSTANT_Double_info(ClassReader cr) throws IOException {
327 value = cr.readDouble();
328 }
329
330 public CONSTANT_Double_info(double value) {
331 this.value = value;
332 }
333
334 public int getTag() {
335 return CONSTANT_Double;
336 }
337
338 @Override
339 public String toString() {
340 return "CONSTANT_Double_info[value: " + value + "]";
341 }
342
343 public <R, D> R accept(Visitor<R, D> visitor, D data) {
344 return visitor.visitDouble(this, data);
345 }
346
347 public final double value;
348 }
349
350 public static class CONSTANT_Fieldref_info extends CPRefInfo {
351 CONSTANT_Fieldref_info(ConstantPool cp, ClassReader cr) throws IOException {
352 super(cp, cr, CONSTANT_Fieldref);
353 }
354
355 public CONSTANT_Fieldref_info(ConstantPool cp, int class_index, int name_and_type_index) {
356 super(cp, CONSTANT_Fieldref, class_index, name_and_type_index);
357 }
358
359 @Override
360 public String toString() {
361 return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
362 }
363
364 public <R, D> R accept(Visitor<R, D> visitor, D data) {
365 return visitor.visitFieldref(this, data);
366 }
367 }
368
369 public static class CONSTANT_Float_info extends CPInfo {
370 CONSTANT_Float_info(ClassReader cr) throws IOException {
371 value = cr.readFloat();
372 }
373
374 public CONSTANT_Float_info(float value) {
375 this.value = value;
376 }
377
378 public int getTag() {
379 return CONSTANT_Float;
380 }
381
382 @Override
383 public String toString() {
384 return "CONSTANT_Float_info[value: " + value + "]";
385 }
386
387 public <R, D> R accept(Visitor<R, D> visitor, D data) {
388 return visitor.visitFloat(this, data);
389 }
390
391 public final float value;
392 }
393
394 public static class CONSTANT_Integer_info extends CPInfo {
395 CONSTANT_Integer_info(ClassReader cr) throws IOException {
396 value = cr.readInt();
397 }
398
399 public CONSTANT_Integer_info(int value) {
400 this.value = value;
401 }
402
403 public int getTag() {
404 return CONSTANT_Integer;
405 }
406
407 @Override
408 public String toString() {
409 return "CONSTANT_Integer_info[value: " + value + "]";
410 }
411
412 public <R, D> R accept(Visitor<R, D> visitor, D data) {
413 return visitor.visitInteger(this, data);
414 }
415
416 public final int value;
417 }
418
419 public static class CONSTANT_InterfaceMethodref_info extends CPRefInfo {
420 CONSTANT_InterfaceMethodref_info(ConstantPool cp, ClassReader cr) throws IOException {
421 super(cp, cr, CONSTANT_InterfaceMethodref);
422 }
423
424 public CONSTANT_InterfaceMethodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
425 super(cp, CONSTANT_InterfaceMethodref, class_index, name_and_type_index);
426 }
427
428 @Override
429 public String toString() {
430 return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
431 }
432
433 public <R, D> R accept(Visitor<R, D> visitor, D data) {
434 return visitor.visitInterfaceMethodref(this, data);
435 }
436 }
437
438 public static class CONSTANT_Long_info extends CPInfo {
439 CONSTANT_Long_info(ClassReader cr) throws IOException {
440 value = cr.readLong();
441 }
442
443 public CONSTANT_Long_info(long value) {
444 this.value = value;
445 }
446
447 public int getTag() {
448 return CONSTANT_Long;
449 }
450
451 @Override
452 public String toString() {
453 return "CONSTANT_Long_info[value: " + value + "]";
454 }
455
456 public <R, D> R accept(Visitor<R, D> visitor, D data) {
457 return visitor.visitLong(this, data);
458 }
459
460 public final long value;
461 }
462
463 public static class CONSTANT_Methodref_info extends CPRefInfo {
464 CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException {
465 super(cp, cr, CONSTANT_Methodref);
466 }
467
468 public CONSTANT_Methodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
469 super(cp, CONSTANT_Methodref, class_index, name_and_type_index);
470 }
471
472 @Override
473 public String toString() {
474 return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
475 }
476
477 public <R, D> R accept(Visitor<R, D> visitor, D data) {
478 return visitor.visitMethodref(this, data);
479 }
480 }
481
482 public static class CONSTANT_NameAndType_info extends CPInfo {
483 CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException {
484 super(cp);
485 name_index = cr.readUnsignedShort();
486 type_index = cr.readUnsignedShort();
487 }
488
489 public CONSTANT_NameAndType_info(ConstantPool cp, int name_index, int type_index) {
490 super(cp);
491 this.name_index = name_index;
492 this.type_index = type_index;
493 }
494
495 public int getTag() {
496 return CONSTANT_NameAndType;
497 }
498
499 public String getName() throws ConstantPoolException {
500 return cp.getUTF8Value(name_index);
501 }
502
503 public String getType() throws ConstantPoolException {
504 return cp.getUTF8Value(type_index);
505 }
506
507 public <R, D> R accept(Visitor<R, D> visitor, D data) {
508 return visitor.visitNameAndType(this, data);
509 }
510
511 public final int name_index;
512 public final int type_index;
513 }
514
515 public static class CONSTANT_String_info extends CPInfo {
516 CONSTANT_String_info(ConstantPool cp, ClassReader cr) throws IOException {
517 super(cp);
518 string_index = cr.readUnsignedShort();
519 }
520
521 public CONSTANT_String_info(ConstantPool cp, int string_index) {
522 super(cp);
523 this.string_index = string_index;
524 }
525
526 public int getTag() {
527 return CONSTANT_String;
528 }
529
530 public String getString() throws ConstantPoolException {
531 return cp.getUTF8Value(string_index);
532 }
533
534 public <R, D> R accept(Visitor<R, D> visitor, D data) {
535 return visitor.visitString(this, data);
536 }
537
538 public final int string_index;
539 }
540
541 public static class CONSTANT_Utf8_info extends CPInfo {
542 CONSTANT_Utf8_info(ClassReader cr) throws IOException {
543 value = cr.readUTF();
544 }
545
546 public CONSTANT_Utf8_info(String value) {
547 this.value = value;
548 }
549
550 public int getTag() {
551 return CONSTANT_Utf8;
552 }
553
554 @Override
555 public String toString() {
556 return "CONSTANT_Utf8_info[value: " + value + "]";
557 }
558
559 public <R, D> R accept(Visitor<R, D> visitor, D data) {
560 return visitor.visitUtf8(this, data);
561 }
562
563 public final String value;
564 }
565
566
567 }