Mon, 10 Jan 2011 14:57:59 -0800
6992999: fully remove JSR 308 from langtools
Reviewed-by: mcimadamore
1 /*
2 * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.classfile;
28 import java.io.DataOutputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.util.Iterator;
33 /**
34 * See JVMS3, section 4.5.
35 *
36 * <p><b>This is NOT part of any supported API.
37 * If you write code that depends on this, you do so at your own risk.
38 * This code and its internal interfaces are subject to change or
39 * deletion without notice.</b>
40 */
41 public class ConstantPool {
43 public static class InvalidIndex extends ConstantPoolException {
44 private static final long serialVersionUID = -4350294289300939730L;
45 InvalidIndex(int index) {
46 super(index);
47 }
49 @Override
50 public String getMessage() {
51 // i18n
52 return "invalid index #" + index;
53 }
54 }
56 public static class UnexpectedEntry extends ConstantPoolException {
57 private static final long serialVersionUID = 6986335935377933211L;
58 UnexpectedEntry(int index, int expected_tag, int found_tag) {
59 super(index);
60 this.expected_tag = expected_tag;
61 this.found_tag = found_tag;
62 }
64 @Override
65 public String getMessage() {
66 // i18n?
67 return "unexpected entry at #" + index + " -- expected tag " + expected_tag + ", found " + found_tag;
68 }
70 public final int expected_tag;
71 public final int found_tag;
72 }
74 public static class InvalidEntry extends ConstantPoolException {
75 private static final long serialVersionUID = 1000087545585204447L;
76 InvalidEntry(int index, int tag) {
77 super(index);
78 this.tag = tag;
79 }
81 @Override
82 public String getMessage() {
83 // i18n?
84 return "unexpected tag at #" + index + ": " + tag;
85 }
87 public final int tag;
88 }
90 public static class EntryNotFound extends ConstantPoolException {
91 private static final long serialVersionUID = 2885537606468581850L;
92 EntryNotFound(Object value) {
93 super(-1);
94 this.value = value;
95 }
97 @Override
98 public String getMessage() {
99 // i18n?
100 return "value not found: " + value;
101 }
103 public final Object value;
104 }
106 public static final int CONSTANT_Utf8 = 1;
107 public static final int CONSTANT_Integer = 3;
108 public static final int CONSTANT_Float = 4;
109 public static final int CONSTANT_Long = 5;
110 public static final int CONSTANT_Double = 6;
111 public static final int CONSTANT_Class = 7;
112 public static final int CONSTANT_String = 8;
113 public static final int CONSTANT_Fieldref = 9;
114 public static final int CONSTANT_Methodref = 10;
115 public static final int CONSTANT_InterfaceMethodref = 11;
116 public static final int CONSTANT_NameAndType = 12;
118 ConstantPool(ClassReader cr) throws IOException, InvalidEntry {
119 int count = cr.readUnsignedShort();
120 pool = new CPInfo[count];
121 for (int i = 1; i < count; i++) {
122 int tag = cr.readUnsignedByte();
123 switch (tag) {
124 case CONSTANT_Class:
125 pool[i] = new CONSTANT_Class_info(this, cr);
126 break;
128 case CONSTANT_Double:
129 pool[i] = new CONSTANT_Double_info(cr);
130 i++;
131 break;
133 case CONSTANT_Fieldref:
134 pool[i] = new CONSTANT_Fieldref_info(this, cr);
135 break;
137 case CONSTANT_Float:
138 pool[i] = new CONSTANT_Float_info(cr);
139 break;
141 case CONSTANT_Integer:
142 pool[i] = new CONSTANT_Integer_info(cr);
143 break;
145 case CONSTANT_InterfaceMethodref:
146 pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr);
147 break;
149 case CONSTANT_Long:
150 pool[i] = new CONSTANT_Long_info(cr);
151 i++;
152 break;
154 case CONSTANT_Methodref:
155 pool[i] = new CONSTANT_Methodref_info(this, cr);
156 break;
158 case CONSTANT_NameAndType:
159 pool[i] = new CONSTANT_NameAndType_info(this, cr);
160 break;
162 case CONSTANT_String:
163 pool[i] = new CONSTANT_String_info(this, cr);
164 break;
166 case CONSTANT_Utf8:
167 pool[i] = new CONSTANT_Utf8_info(cr);
168 break;
170 default:
171 throw new InvalidEntry(i, tag);
172 }
173 }
174 }
176 public ConstantPool(CPInfo[] pool) {
177 this.pool = pool;
178 }
180 public int size() {
181 return pool.length;
182 }
184 public int byteLength() {
185 int length = 2;
186 for (int i = 1; i < size(); ) {
187 CPInfo cpInfo = pool[i];
188 length += cpInfo.byteLength();
189 i += cpInfo.size();
190 }
191 return length;
192 }
194 public CPInfo get(int index) throws InvalidIndex {
195 if (index <= 0 || index >= pool.length)
196 throw new InvalidIndex(index);
197 CPInfo info = pool[index];
198 if (info == null) {
199 // this occurs for indices referencing the "second half" of an
200 // 8 byte constant, such as CONSTANT_Double or CONSTANT_Long
201 throw new InvalidIndex(index);
202 }
203 return pool[index];
204 }
206 private CPInfo get(int index, int expected_type) throws InvalidIndex, UnexpectedEntry {
207 CPInfo info = get(index);
208 if (info.getTag() != expected_type)
209 throw new UnexpectedEntry(index, expected_type, info.getTag());
210 return info;
211 }
213 public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry {
214 return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8));
215 }
217 public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry {
218 return ((CONSTANT_Class_info) get(index, CONSTANT_Class));
219 }
221 public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry {
222 return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType));
223 }
225 public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry {
226 return getUTF8Info(index).value;
227 }
229 public int getUTF8Index(String value) throws EntryNotFound {
230 for (int i = 1; i < pool.length; i++) {
231 CPInfo info = pool[i];
232 if (info instanceof CONSTANT_Utf8_info &&
233 ((CONSTANT_Utf8_info) info).value.equals(value))
234 return i;
235 }
236 throw new EntryNotFound(value);
237 }
239 public Iterable<CPInfo> entries() {
240 return new Iterable<CPInfo>() {
241 public Iterator<CPInfo> iterator() {
242 return new Iterator<CPInfo>() {
244 public boolean hasNext() {
245 return next < pool.length;
246 }
248 public CPInfo next() {
249 current = pool[next];
250 switch (current.getTag()) {
251 case CONSTANT_Double:
252 case CONSTANT_Long:
253 next += 2;
254 break;
255 default:
256 next += 1;
257 }
258 return current;
259 }
261 public void remove() {
262 throw new UnsupportedOperationException();
263 }
265 private CPInfo current;
266 private int next = 1;
268 };
269 }
270 };
271 }
273 private CPInfo[] pool;
275 public interface Visitor<R,P> {
276 R visitClass(CONSTANT_Class_info info, P p);
277 R visitDouble(CONSTANT_Double_info info, P p);
278 R visitFieldref(CONSTANT_Fieldref_info info, P p);
279 R visitFloat(CONSTANT_Float_info info, P p);
280 R visitInteger(CONSTANT_Integer_info info, P p);
281 R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p);
282 R visitLong(CONSTANT_Long_info info, P p);
283 R visitNameAndType(CONSTANT_NameAndType_info info, P p);
284 R visitMethodref(CONSTANT_Methodref_info info, P p);
285 R visitString(CONSTANT_String_info info, P p);
286 R visitUtf8(CONSTANT_Utf8_info info, P p);
287 }
289 public static abstract class CPInfo {
290 CPInfo() {
291 this.cp = null;
292 }
294 CPInfo(ConstantPool cp) {
295 this.cp = cp;
296 }
298 public abstract int getTag();
300 /** The number of slots in the constant pool used by this entry.
301 * 2 for CONSTANT_Double and CONSTANT_Long; 1 for everything else. */
302 public int size() {
303 return 1;
304 }
306 public abstract int byteLength();
308 public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
310 protected final ConstantPool cp;
311 }
313 public static abstract class CPRefInfo extends CPInfo {
314 protected CPRefInfo(ConstantPool cp, ClassReader cr, int tag) throws IOException {
315 super(cp);
316 this.tag = tag;
317 class_index = cr.readUnsignedShort();
318 name_and_type_index = cr.readUnsignedShort();
319 }
321 protected CPRefInfo(ConstantPool cp, int tag, int class_index, int name_and_type_index) {
322 super(cp);
323 this.tag = tag;
324 this.class_index = class_index;
325 this.name_and_type_index = name_and_type_index;
326 }
328 public int getTag() {
329 return tag;
330 }
332 public int byteLength() {
333 return 5;
334 }
336 public CONSTANT_Class_info getClassInfo() throws ConstantPoolException {
337 return cp.getClassInfo(class_index);
338 }
340 public String getClassName() throws ConstantPoolException {
341 return cp.getClassInfo(class_index).getName();
342 }
344 public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
345 return cp.getNameAndTypeInfo(name_and_type_index);
346 }
348 public final int tag;
349 public final int class_index;
350 public final int name_and_type_index;
351 }
353 public static class CONSTANT_Class_info extends CPInfo {
354 CONSTANT_Class_info(ConstantPool cp, ClassReader cr) throws IOException {
355 super(cp);
356 name_index = cr.readUnsignedShort();
357 }
359 public CONSTANT_Class_info(ConstantPool cp, int name_index) {
360 super(cp);
361 this.name_index = name_index;
362 }
364 public int getTag() {
365 return CONSTANT_Class;
366 }
368 public int byteLength() {
369 return 3;
370 }
372 /**
373 * Get the raw value of the class referenced by this constant pool entry.
374 * This will either be the name of the class, in internal form, or a
375 * descriptor for an array class.
376 * @return the raw value of the class
377 */
378 public String getName() throws ConstantPoolException {
379 return cp.getUTF8Value(name_index);
380 }
382 /**
383 * If this constant pool entry identifies either a class or interface type,
384 * or a possibly multi-dimensional array of a class of interface type,
385 * return the name of the class or interface in internal form. Otherwise,
386 * (i.e. if this is a possibly multi-dimensional array of a primitive type),
387 * return null.
388 * @return the base class or interface name
389 */
390 public String getBaseName() throws ConstantPoolException {
391 String name = getName();
392 if (name.startsWith("[")) {
393 int index = name.indexOf("[L");
394 if (index == -1)
395 return null;
396 return name.substring(index + 2, name.length() - 1);
397 } else
398 return name;
399 }
401 public int getDimensionCount() throws ConstantPoolException {
402 String name = getName();
403 int count = 0;
404 while (name.charAt(count) == '[')
405 count++;
406 return count;
407 }
409 @Override
410 public String toString() {
411 return "CONSTANT_Class_info[name_index: " + name_index + "]";
412 }
414 public <R, D> R accept(Visitor<R, D> visitor, D data) {
415 return visitor.visitClass(this, data);
416 }
418 public final int name_index;
419 }
421 public static class CONSTANT_Double_info extends CPInfo {
422 CONSTANT_Double_info(ClassReader cr) throws IOException {
423 value = cr.readDouble();
424 }
426 public CONSTANT_Double_info(double value) {
427 this.value = value;
428 }
430 public int getTag() {
431 return CONSTANT_Double;
432 }
434 public int byteLength() {
435 return 9;
436 }
438 @Override
439 public int size() {
440 return 2;
441 }
443 @Override
444 public String toString() {
445 return "CONSTANT_Double_info[value: " + value + "]";
446 }
448 public <R, D> R accept(Visitor<R, D> visitor, D data) {
449 return visitor.visitDouble(this, data);
450 }
452 public final double value;
453 }
455 public static class CONSTANT_Fieldref_info extends CPRefInfo {
456 CONSTANT_Fieldref_info(ConstantPool cp, ClassReader cr) throws IOException {
457 super(cp, cr, CONSTANT_Fieldref);
458 }
460 public CONSTANT_Fieldref_info(ConstantPool cp, int class_index, int name_and_type_index) {
461 super(cp, CONSTANT_Fieldref, class_index, name_and_type_index);
462 }
464 @Override
465 public String toString() {
466 return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
467 }
469 public <R, D> R accept(Visitor<R, D> visitor, D data) {
470 return visitor.visitFieldref(this, data);
471 }
472 }
474 public static class CONSTANT_Float_info extends CPInfo {
475 CONSTANT_Float_info(ClassReader cr) throws IOException {
476 value = cr.readFloat();
477 }
479 public CONSTANT_Float_info(float value) {
480 this.value = value;
481 }
483 public int getTag() {
484 return CONSTANT_Float;
485 }
487 public int byteLength() {
488 return 5;
489 }
491 @Override
492 public String toString() {
493 return "CONSTANT_Float_info[value: " + value + "]";
494 }
496 public <R, D> R accept(Visitor<R, D> visitor, D data) {
497 return visitor.visitFloat(this, data);
498 }
500 public final float value;
501 }
503 public static class CONSTANT_Integer_info extends CPInfo {
504 CONSTANT_Integer_info(ClassReader cr) throws IOException {
505 value = cr.readInt();
506 }
508 public CONSTANT_Integer_info(int value) {
509 this.value = value;
510 }
512 public int getTag() {
513 return CONSTANT_Integer;
514 }
516 public int byteLength() {
517 return 5;
518 }
520 @Override
521 public String toString() {
522 return "CONSTANT_Integer_info[value: " + value + "]";
523 }
525 public <R, D> R accept(Visitor<R, D> visitor, D data) {
526 return visitor.visitInteger(this, data);
527 }
529 public final int value;
530 }
532 public static class CONSTANT_InterfaceMethodref_info extends CPRefInfo {
533 CONSTANT_InterfaceMethodref_info(ConstantPool cp, ClassReader cr) throws IOException {
534 super(cp, cr, CONSTANT_InterfaceMethodref);
535 }
537 public CONSTANT_InterfaceMethodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
538 super(cp, CONSTANT_InterfaceMethodref, class_index, name_and_type_index);
539 }
541 @Override
542 public String toString() {
543 return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
544 }
546 public <R, D> R accept(Visitor<R, D> visitor, D data) {
547 return visitor.visitInterfaceMethodref(this, data);
548 }
549 }
551 public static class CONSTANT_Long_info extends CPInfo {
552 CONSTANT_Long_info(ClassReader cr) throws IOException {
553 value = cr.readLong();
554 }
556 public CONSTANT_Long_info(long value) {
557 this.value = value;
558 }
560 public int getTag() {
561 return CONSTANT_Long;
562 }
564 @Override
565 public int size() {
566 return 2;
567 }
569 public int byteLength() {
570 return 9;
571 }
573 @Override
574 public String toString() {
575 return "CONSTANT_Long_info[value: " + value + "]";
576 }
578 public <R, D> R accept(Visitor<R, D> visitor, D data) {
579 return visitor.visitLong(this, data);
580 }
582 public final long value;
583 }
585 public static class CONSTANT_Methodref_info extends CPRefInfo {
586 CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException {
587 super(cp, cr, CONSTANT_Methodref);
588 }
590 public CONSTANT_Methodref_info(ConstantPool cp, int class_index, int name_and_type_index) {
591 super(cp, CONSTANT_Methodref, class_index, name_and_type_index);
592 }
594 @Override
595 public String toString() {
596 return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
597 }
599 public <R, D> R accept(Visitor<R, D> visitor, D data) {
600 return visitor.visitMethodref(this, data);
601 }
602 }
604 public static class CONSTANT_NameAndType_info extends CPInfo {
605 CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException {
606 super(cp);
607 name_index = cr.readUnsignedShort();
608 type_index = cr.readUnsignedShort();
609 }
611 public CONSTANT_NameAndType_info(ConstantPool cp, int name_index, int type_index) {
612 super(cp);
613 this.name_index = name_index;
614 this.type_index = type_index;
615 }
617 public int getTag() {
618 return CONSTANT_NameAndType;
619 }
621 public int byteLength() {
622 return 5;
623 }
625 public String getName() throws ConstantPoolException {
626 return cp.getUTF8Value(name_index);
627 }
629 public String getType() throws ConstantPoolException {
630 return cp.getUTF8Value(type_index);
631 }
633 public <R, D> R accept(Visitor<R, D> visitor, D data) {
634 return visitor.visitNameAndType(this, data);
635 }
637 @Override
638 public String toString() {
639 return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]";
640 }
642 public final int name_index;
643 public final int type_index;
644 }
646 public static class CONSTANT_String_info extends CPInfo {
647 CONSTANT_String_info(ConstantPool cp, ClassReader cr) throws IOException {
648 super(cp);
649 string_index = cr.readUnsignedShort();
650 }
652 public CONSTANT_String_info(ConstantPool cp, int string_index) {
653 super(cp);
654 this.string_index = string_index;
655 }
657 public int getTag() {
658 return CONSTANT_String;
659 }
661 public int byteLength() {
662 return 3;
663 }
665 public String getString() throws ConstantPoolException {
666 return cp.getUTF8Value(string_index);
667 }
669 public <R, D> R accept(Visitor<R, D> visitor, D data) {
670 return visitor.visitString(this, data);
671 }
673 @Override
674 public String toString() {
675 return "CONSTANT_String_info[class_index: " + string_index + "]";
676 }
678 public final int string_index;
679 }
681 public static class CONSTANT_Utf8_info extends CPInfo {
682 CONSTANT_Utf8_info(ClassReader cr) throws IOException {
683 value = cr.readUTF();
684 }
686 public CONSTANT_Utf8_info(String value) {
687 this.value = value;
688 }
690 public int getTag() {
691 return CONSTANT_Utf8;
692 }
694 public int byteLength() {
695 class SizeOutputStream extends OutputStream {
696 @Override
697 public void write(int b) {
698 size++;
699 }
700 int size;
701 }
702 SizeOutputStream sizeOut = new SizeOutputStream();
703 DataOutputStream out = new DataOutputStream(sizeOut);
704 try { out.writeUTF(value); } catch (IOException ignore) { }
705 return 1 + sizeOut.size;
706 }
708 @Override
709 public String toString() {
710 if (value.length() < 32 && isPrintableAscii(value))
711 return "CONSTANT_Utf8_info[value: \"" + value + "\"]";
712 else
713 return "CONSTANT_Utf8_info[value: (" + value.length() + " chars)]";
714 }
716 static boolean isPrintableAscii(String s) {
717 for (int i = 0; i < s.length(); i++) {
718 char c = s.charAt(i);
719 if (c < 32 || c >= 127)
720 return false;
721 }
722 return true;
723 }
725 public <R, D> R accept(Visitor<R, D> visitor, D data) {
726 return visitor.visitUtf8(this, data);
727 }
729 public final String value;
730 }
733 }