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    }