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.8.16.
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 Annotation {
039 static class InvalidAnnotation extends AttributeException {
040 private static final long serialVersionUID = -4620480740735772708L;
041 InvalidAnnotation(String msg) {
042 super(msg);
043 }
044 }
045
046 Annotation(ClassReader cr) throws IOException, InvalidAnnotation {
047 type_index = cr.readUnsignedShort();
048 num_element_value_pairs = cr.readUnsignedShort();
049 element_value_pairs = new element_value_pair[num_element_value_pairs];
050 for (int i = 0; i < element_value_pairs.length; i++)
051 element_value_pairs[i] = new element_value_pair(cr);
052 }
053
054 public Annotation(ConstantPool constant_pool,
055 int type_index,
056 element_value_pair[] element_value_pairs) {
057 this.type_index = type_index;
058 num_element_value_pairs = element_value_pairs.length;
059 this.element_value_pairs = element_value_pairs;
060 }
061
062 public int length() {
063 int n = 2 /*type_index*/ + 2 /*num_element_value_pairs*/;
064 for (element_value_pair pair: element_value_pairs)
065 n += pair.length();
066 return n;
067 }
068
069 public final int type_index;
070 public final int num_element_value_pairs;
071 public final element_value_pair element_value_pairs[];
072
073 /**
074 * See JVMS3, section 4.8.16.1.
075 */
076 public static abstract class element_value {
077 public static element_value read(ClassReader cr)
078 throws IOException, InvalidAnnotation {
079 int tag = cr.readUnsignedByte();
080 switch (tag) {
081 case 'B':
082 case 'C':
083 case 'D':
084 case 'F':
085 case 'I':
086 case 'J':
087 case 'S':
088 case 'Z':
089 case 's':
090 return new Primitive_element_value(cr, tag);
091
092 case 'e':
093 return new Enum_element_value(cr, tag);
094
095 case 'c':
096 return new Class_element_value(cr, tag);
097
098 case '@':
099 return new Annotation_element_value(cr, tag);
100
101 case '[':
102 return new Array_element_value(cr, tag);
103
104 default:
105 throw new InvalidAnnotation("unrecognized tag: " + tag);
106 }
107 }
108
109 protected element_value(int tag) {
110 this.tag = tag;
111 }
112
113 public abstract int length();
114
115 public abstract <R,P> R accept(Visitor<R,P> visitor, P p);
116
117 public interface Visitor<R,P> {
118 R visitPrimitive(Primitive_element_value ev, P p);
119 R visitEnum(Enum_element_value ev, P p);
120 R visitClass(Class_element_value ev, P p);
121 R visitAnnotation(Annotation_element_value ev, P p);
122 R visitArray(Array_element_value ev, P p);
123 }
124
125 public final int tag;
126 }
127
128 public static class Primitive_element_value extends element_value {
129 Primitive_element_value(ClassReader cr, int tag) throws IOException {
130 super(tag);
131 const_value_index = cr.readUnsignedShort();
132 }
133
134 @Override
135 public int length() {
136 return 2;
137 }
138
139 public <R,P> R accept(Visitor<R,P> visitor, P p) {
140 return visitor.visitPrimitive(this, p);
141 }
142
143 public final int const_value_index;
144
145 }
146
147 public static class Enum_element_value extends element_value {
148 Enum_element_value(ClassReader cr, int tag) throws IOException {
149 super(tag);
150 type_name_index = cr.readUnsignedShort();
151 const_name_index = cr.readUnsignedShort();
152 }
153
154 @Override
155 public int length() {
156 return 4;
157 }
158
159 public <R,P> R accept(Visitor<R,P> visitor, P p) {
160 return visitor.visitEnum(this, p);
161 }
162
163 public final int type_name_index;
164 public final int const_name_index;
165 }
166
167 public static class Class_element_value extends element_value {
168 Class_element_value(ClassReader cr, int tag) throws IOException {
169 super(tag);
170 class_info_index = cr.readUnsignedShort();
171 }
172
173 @Override
174 public int length() {
175 return 2;
176 }
177
178 public <R,P> R accept(Visitor<R,P> visitor, P p) {
179 return visitor.visitClass(this, p);
180 }
181
182 public final int class_info_index;
183 }
184
185 public static class Annotation_element_value extends element_value {
186 Annotation_element_value(ClassReader cr, int tag)
187 throws IOException, InvalidAnnotation {
188 super(tag);
189 annotation_value = new Annotation(cr);
190 }
191
192 @Override
193 public int length() {
194 return annotation_value.length();
195 }
196
197 public <R,P> R accept(Visitor<R,P> visitor, P p) {
198 return visitor.visitAnnotation(this, p);
199 }
200
201 public final Annotation annotation_value;
202 }
203
204 public static class Array_element_value extends element_value {
205 Array_element_value(ClassReader cr, int tag)
206 throws IOException, InvalidAnnotation {
207 super(tag);
208 num_values = cr.readUnsignedShort();
209 values = new element_value[num_values];
210 for (int i = 0; i < values.length; i++)
211 values[i] = element_value.read(cr);
212 }
213
214 @Override
215 public int length() {
216 int n = 2;
217 for (int i = 0; i < values.length; i++)
218 n += values[i].length();
219 return n;
220 }
221
222 public <R,P> R accept(Visitor<R,P> visitor, P p) {
223 return visitor.visitArray(this, p);
224 }
225
226 public final int num_values;
227 public final element_value[] values;
228 }
229
230 public static class element_value_pair {
231 element_value_pair(ClassReader cr)
232 throws IOException, InvalidAnnotation {
233 element_name_index = cr.readUnsignedShort();
234 value = element_value.read(cr);
235 }
236
237 public int length() {
238 return 2 + value.length();
239 }
240
241 public final int element_name_index;
242 public final element_value value;
243 }
244 }