KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > cojen > classfile > attribute > Annotation


1 /*
2  * Copyright 2005 Brian S O'Neill
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.cojen.classfile.attribute;
18
19 import java.io.DataInput JavaDoc;
20 import java.io.DataOutput JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.util.Collections JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.LinkedHashMap JavaDoc;
25 import java.util.Map JavaDoc;
26 import org.cojen.classfile.ConstantInfo;
27 import org.cojen.classfile.ConstantPool;
28 import org.cojen.classfile.TypeDesc;
29 import org.cojen.classfile.constant.ConstantClassInfo;
30 import org.cojen.classfile.constant.ConstantDoubleInfo;
31 import org.cojen.classfile.constant.ConstantFloatInfo;
32 import org.cojen.classfile.constant.ConstantIntegerInfo;
33 import org.cojen.classfile.constant.ConstantLongInfo;
34 import org.cojen.classfile.constant.ConstantUTFInfo;
35
36 /**
37  * Defines the annotation structure used by Java 5 annotations attributes.
38  *
39  * @author Brian S O'Neill
40  */

41 public class Annotation {
42
43     /** Member value is represented by a ConstantIntegerInfo */
44     public static final char MEMBER_TAG_BOOLEAN = 'Z';
45     
46     /** Member value is represented by a ConstantIntegerInfo */
47     public static final char MEMBER_TAG_BYTE = 'B';
48     
49     /** Member value is represented by a ConstantIntegerInfo */
50     public static final char MEMBER_TAG_SHORT = 'S';
51     
52     /** Member value is represented by a ConstantIntegerInfo */
53     public static final char MEMBER_TAG_CHAR = 'C';
54     
55     /** Member value is represented by a ConstantIntegerInfo */
56     public static final char MEMBER_TAG_INT = 'I';
57     
58     /** Member value is represented by a ConstantLongInfo */
59     public static final char MEMBER_TAG_LONG = 'J';
60         
61     /** Member value is represented by a ConstantFloatInfo */
62     public static final char MEMBER_TAG_FLOAT = 'F';
63
64     /** Member value is represented by a ConstantDoubleInfo */
65     public static final char MEMBER_TAG_DOUBLE = 'D';
66
67     /** Member value is represented by a ConstantUTFInfo */
68     public static final char MEMBER_TAG_STRING = 's';
69
70     /** Member value is represented by a ConstantClassInfo */
71     public static final char MEMBER_TAG_CLASS = 'c';
72
73     /** Member value is represented by an EnumConstValue */
74     public static final char MEMBER_TAG_ENUM = 'e';
75
76     /** Member value is represented by a MemberValue array */
77     public static final char MEMBER_TAG_ARRAY = '[';
78
79     /** Member value is represented by an Annotation */
80     public static final char MEMBER_TAG_ANNOTATION = '@';
81
82     private final ConstantPool mCp;
83     private ConstantUTFInfo mType;
84     private final Map JavaDoc mMemberValues;
85     
86     public Annotation(ConstantPool cp) {
87         mCp = cp;
88         mMemberValues = new LinkedHashMap JavaDoc(2);
89     }
90     
91     public Annotation(ConstantPool cp, DataInput JavaDoc din) throws IOException JavaDoc {
92         mCp = cp;
93         mType = (ConstantUTFInfo)cp.getConstant(din.readUnsignedShort());
94
95         int memberCount = din.readUnsignedShort();
96         mMemberValues = new LinkedHashMap JavaDoc(memberCount);
97         
98         for (int i=0; i<memberCount; i++) {
99             String JavaDoc name = ((ConstantUTFInfo)cp.getConstant(din.readUnsignedShort())).getValue();
100             mMemberValues.put(name, new MemberValue(cp, din));
101         }
102     }
103     
104     public ConstantUTFInfo getTypeConstant() {
105         return mType;
106     }
107
108     public TypeDesc getType() {
109         return TypeDesc.forDescriptor(mType.getValue());
110     }
111     
112     public void setTypeConstant(ConstantUTFInfo type) {
113         mType = type;
114     }
115     
116     public void setType(TypeDesc type) {
117         setTypeConstant(mCp.addConstantUTF(type.getDescriptor()));
118     }
119
120     /**
121      * Returns an unmodifiable map of member names (String) to MemberValue
122      * objects.
123      */

124     public Map JavaDoc getMemberValues() {
125         return Collections.unmodifiableMap(mMemberValues);
126     }
127     
128     public void putMemberValue(String JavaDoc name, MemberValue mv) {
129         mCp.addConstantUTF(name);
130         mMemberValues.put(name, mv);
131     }
132
133     public void putMemberValue(String JavaDoc name, boolean value) {
134         mCp.addConstantUTF(name);
135         mMemberValues.put(name, makeMemberValue(value));
136     }
137
138     public void putMemberValue(String JavaDoc name, byte value) {
139         mCp.addConstantUTF(name);
140         mMemberValues.put(name, makeMemberValue(value));
141     }
142     
143     public void putMemberValue(String JavaDoc name, short value) {
144         mCp.addConstantUTF(name);
145         mMemberValues.put(name, makeMemberValue(value));
146     }
147
148     public void putMemberValue(String JavaDoc name, char value) {
149         mCp.addConstantUTF(name);
150         mMemberValues.put(name, makeMemberValue(value));
151     }
152
153     public void putMemberValue(String JavaDoc name, int value) {
154         mCp.addConstantUTF(name);
155         mMemberValues.put(name, makeMemberValue(value));
156     }
157
158     public void putMemberValue(String JavaDoc name, long value) {
159         mCp.addConstantUTF(name);
160         mMemberValues.put(name, makeMemberValue(value));
161     }
162
163     public void putMemberValue(String JavaDoc name, float value) {
164         mCp.addConstantUTF(name);
165         mMemberValues.put(name, makeMemberValue(value));
166     }
167
168     public void putMemberValue(String JavaDoc name, double value) {
169         mCp.addConstantUTF(name);
170         mMemberValues.put(name, makeMemberValue(value));
171     }
172
173     public void putMemberValue(String JavaDoc name, String JavaDoc value) {
174         mCp.addConstantUTF(name);
175         mMemberValues.put(name, makeMemberValue(value));
176     }
177
178     public void putMemberValue(String JavaDoc name, TypeDesc value) {
179         mCp.addConstantUTF(name);
180         mMemberValues.put(name, makeMemberValue(value));
181     }
182
183     public void putMemberValue(String JavaDoc name, MemberValue[] value) {
184         mCp.addConstantUTF(name);
185         mMemberValues.put(name, makeMemberValue(value));
186     }
187
188     public void putMemberValue(String JavaDoc name, TypeDesc enumType, String JavaDoc enumName) {
189         mCp.addConstantUTF(name);
190         mMemberValues.put(name, makeMemberValue(enumType, enumName));
191     }
192
193     /**
194      * @see #makeAnnotation
195      */

196     public void putMemberValue(String JavaDoc name, Annotation value) {
197         mCp.addConstantUTF(name);
198         mMemberValues.put(name, makeMemberValue(value));
199     }
200
201     public MemberValue makeMemberValue(boolean value) {
202         return new MemberValue(MEMBER_TAG_BOOLEAN, mCp.addConstantInteger(value ? 1 : 0));
203     }
204
205     public MemberValue makeMemberValue(byte value) {
206         return new MemberValue(MEMBER_TAG_BYTE, mCp.addConstantInteger(value));
207     }
208     
209     public MemberValue makeMemberValue(short value) {
210         return new MemberValue(MEMBER_TAG_SHORT, mCp.addConstantInteger(value));
211     }
212
213     public MemberValue makeMemberValue(char value) {
214         return new MemberValue(MEMBER_TAG_CHAR, mCp.addConstantInteger(value));
215     }
216     
217     public MemberValue makeMemberValue(int value) {
218         return new MemberValue(MEMBER_TAG_INT, mCp.addConstantInteger(value));
219     }
220     
221     public MemberValue makeMemberValue(long value) {
222         return new MemberValue(MEMBER_TAG_LONG, mCp.addConstantLong(value));
223     }
224     
225     public MemberValue makeMemberValue(float value) {
226         return new MemberValue(MEMBER_TAG_FLOAT, mCp.addConstantFloat(value));
227     }
228     
229     public MemberValue makeMemberValue(double value) {
230         return new MemberValue(MEMBER_TAG_DOUBLE, mCp.addConstantDouble(value));
231     }
232     
233     public MemberValue makeMemberValue(String JavaDoc value) {
234         return new MemberValue(MEMBER_TAG_STRING, mCp.addConstantUTF(value));
235     }
236
237     public MemberValue makeMemberValue(TypeDesc value) {
238         return new MemberValue(MEMBER_TAG_CLASS, mCp.addConstantUTF(value.getDescriptor()));
239     }
240     
241     public MemberValue makeMemberValue(TypeDesc enumType, String JavaDoc enumName) {
242         return new MemberValue(MEMBER_TAG_ENUM,
243                                new EnumConstValue(mCp.addConstantUTF(enumType.getDescriptor()),
244                                                   mCp.addConstantUTF(enumName)));
245     }
246
247     public MemberValue makeMemberValue(MemberValue[] value) {
248         return new MemberValue(MEMBER_TAG_ARRAY, value);
249     }
250
251     /**
252      * @see #makeAnnotation
253      */

254     public MemberValue makeMemberValue(Annotation value) {
255         return new MemberValue(MEMBER_TAG_ANNOTATION, value);
256     }
257
258     public Annotation makeAnnotation() {
259         return new Annotation(mCp);
260     }
261
262     public int getLength() {
263         int length = 4;
264         Iterator JavaDoc it = mMemberValues.values().iterator();
265         while (it.hasNext()) {
266             length += 2 + ((MemberValue)it.next()).getLength();
267         }
268         return length;
269     }
270     
271     public void writeTo(DataOutput JavaDoc dout) throws IOException JavaDoc {
272         dout.writeShort(mType.getIndex());
273         int memberCount = mMemberValues.size();
274         dout.writeShort(memberCount);
275         Iterator JavaDoc it = mMemberValues.entrySet().iterator();
276         while (it.hasNext()) {
277             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
278             String JavaDoc name = (String JavaDoc)entry.getKey();
279             MemberValue value = (MemberValue)entry.getValue();
280             dout.writeShort(mCp.addConstantUTF(name).getIndex());
281             value.writeTo(dout);
282         }
283     }
284
285     public static class MemberValue {
286         private final char mTag;
287         private final Object JavaDoc mValue;
288         
289         public MemberValue(char tag, Object JavaDoc value) {
290             switch (mTag = tag) {
291             default:
292                 throw new IllegalArgumentException JavaDoc
293                     ("Illegal annotation member value tag: " + mTag);
294                 
295             case MEMBER_TAG_BOOLEAN:
296             case MEMBER_TAG_BYTE:
297             case MEMBER_TAG_SHORT:
298             case MEMBER_TAG_CHAR:
299             case MEMBER_TAG_INT:
300                 if (value instanceof ConstantIntegerInfo) {
301                     mValue = value;
302                 } else {
303                     throw new IllegalArgumentException JavaDoc("Value must be ConstantIntegerInfo");
304                 }
305                 break;
306
307             case MEMBER_TAG_LONG:
308                 if (value instanceof ConstantLongInfo) {
309                     mValue = value;
310                 } else {
311                     throw new IllegalArgumentException JavaDoc("Value must be ConstantLongInfo");
312                 }
313                 break;
314
315             case MEMBER_TAG_FLOAT:
316                 if (value instanceof ConstantFloatInfo) {
317                     mValue = value;
318                 } else {
319                     throw new IllegalArgumentException JavaDoc("Value must be ConstantFloatInfo");
320                 }
321                 break;
322
323             case MEMBER_TAG_DOUBLE:
324                 if (value instanceof ConstantDoubleInfo) {
325                     mValue = value;
326                 } else {
327                     throw new IllegalArgumentException JavaDoc("Value must be ConstantDoubleInfo");
328                 }
329                 break;
330
331             case MEMBER_TAG_CLASS:
332                 if (value instanceof ConstantUTFInfo) {
333                     mValue = value;
334                 } else {
335                     throw new IllegalArgumentException JavaDoc("Value must be ConstantUTFInfo");
336                 }
337                 break;
338
339             case MEMBER_TAG_STRING:
340                 if (value instanceof ConstantUTFInfo) {
341                     mValue = value;
342                 } else {
343                     throw new IllegalArgumentException JavaDoc("Value must be ConstantUTFInfo");
344                 }
345                 break;
346                 
347             case MEMBER_TAG_ENUM:
348                 if (value instanceof EnumConstValue) {
349                     mValue = value;
350                 } else {
351                     throw new IllegalArgumentException JavaDoc("Value must be EnumConstValue");
352                 }
353                 break;
354                 
355             case MEMBER_TAG_ARRAY:
356                 if (value instanceof MemberValue[]) {
357                     mValue = value;
358                 } else {
359                     throw new IllegalArgumentException JavaDoc("Value must be MemberValue[]");
360                 }
361                 break;
362                 
363             case MEMBER_TAG_ANNOTATION:
364                 if (value instanceof Annotation) {
365                     mValue = value;
366                 } else {
367                     throw new IllegalArgumentException JavaDoc("Value must be Annotation");
368                 }
369                 break;
370             }
371         }
372         
373         public MemberValue(ConstantPool cp, DataInput JavaDoc din) throws IOException JavaDoc {
374             switch (mTag = (char)din.readUnsignedByte()) {
375             default:
376                 throw new IllegalStateException JavaDoc
377                     ("Illegal annotation member value tag: " + mTag);
378                 
379             case MEMBER_TAG_BOOLEAN:
380             case MEMBER_TAG_BYTE:
381             case MEMBER_TAG_SHORT:
382             case MEMBER_TAG_CHAR:
383             case MEMBER_TAG_INT:
384             case MEMBER_TAG_LONG:
385             case MEMBER_TAG_FLOAT:
386             case MEMBER_TAG_DOUBLE:
387             case MEMBER_TAG_CLASS:
388             case MEMBER_TAG_STRING:
389                 mValue = cp.getConstant(din.readUnsignedShort());
390                 break;
391                 
392             case MEMBER_TAG_ENUM:
393                 mValue = new EnumConstValue(cp, din);
394                 break;
395                 
396             case MEMBER_TAG_ARRAY:
397                 int length = din.readUnsignedShort();
398                 MemberValue[] values = new MemberValue[length];
399                 for (int i=0; i<length; i++) {
400                     values[i] = new MemberValue(cp, din);
401                 }
402                 mValue = values;
403                 break;
404                 
405             case MEMBER_TAG_ANNOTATION:
406                 mValue = new Annotation(cp, din);
407                 break;
408             }
409         }
410         
411         public char getTag() {
412             return mTag;
413         }
414         
415         public Object JavaDoc getValue() {
416             return mValue;
417         }
418         
419         public int getLength() {
420             switch (mTag) {
421             default:
422                 return 1;
423
424             case MEMBER_TAG_BOOLEAN:
425             case MEMBER_TAG_BYTE:
426             case MEMBER_TAG_SHORT:
427             case MEMBER_TAG_CHAR:
428             case MEMBER_TAG_INT:
429             case MEMBER_TAG_LONG:
430             case MEMBER_TAG_FLOAT:
431             case MEMBER_TAG_DOUBLE:
432             case MEMBER_TAG_CLASS:
433             case MEMBER_TAG_STRING:
434                 return 3;
435                 
436             case MEMBER_TAG_ENUM:
437                 return 1 + ((EnumConstValue)mValue).getLength();
438                 
439             case MEMBER_TAG_ARRAY: {
440                 MemberValue[] values = (MemberValue[])mValue;
441                 int length = 3;
442                 for (int i=0; i<values.length; i++) {
443                     length += values[i].getLength();
444                 }
445                 return length;
446             }
447                 
448             case MEMBER_TAG_ANNOTATION:
449                 return 1 + ((Annotation)mValue).getLength();
450             }
451         }
452         
453         public void writeTo(DataOutput JavaDoc dout) throws IOException JavaDoc {
454             dout.writeByte(mTag);
455
456             switch (mTag) {
457             case MEMBER_TAG_BOOLEAN:
458             case MEMBER_TAG_BYTE:
459             case MEMBER_TAG_SHORT:
460             case MEMBER_TAG_CHAR:
461             case MEMBER_TAG_INT:
462             case MEMBER_TAG_LONG:
463             case MEMBER_TAG_FLOAT:
464             case MEMBER_TAG_DOUBLE:
465             case MEMBER_TAG_CLASS:
466             case MEMBER_TAG_STRING:
467                 dout.writeShort(((ConstantInfo)mValue).getIndex());
468                 break;
469                 
470             case MEMBER_TAG_ENUM:
471                 ((EnumConstValue)mValue).writeTo(dout);
472                 break;
473                 
474             case MEMBER_TAG_ARRAY:
475                 MemberValue[] values = (MemberValue[])mValue;
476                 dout.writeShort(values.length);
477                 for (int i=0; i<values.length; i++) {
478                     values[i].writeTo(dout);
479                 }
480                 break;
481                 
482             case MEMBER_TAG_ANNOTATION:
483                 ((Annotation)mValue).writeTo(dout);
484                 break;
485             }
486         }
487     }
488     
489     public static class EnumConstValue {
490         private final ConstantUTFInfo mTypeName;
491         private final ConstantUTFInfo mConstName;
492
493         public EnumConstValue(ConstantUTFInfo typeName, ConstantUTFInfo constName) {
494             mTypeName = typeName;
495             mConstName = constName;
496         }
497
498         public EnumConstValue(ConstantPool cp, DataInput JavaDoc din) throws IOException JavaDoc {
499             mTypeName = (ConstantUTFInfo)cp.getConstant(din.readUnsignedShort());
500             mConstName = (ConstantUTFInfo)cp.getConstant(din.readUnsignedShort());
501         }
502
503         public ConstantUTFInfo getTypeName() {
504             return mTypeName;
505         }
506
507         public ConstantUTFInfo getConstName() {
508             return mConstName;
509         }
510
511         public int getLength() {
512             return 4;
513         }
514         
515         public void writeTo(DataOutput JavaDoc dout) throws IOException JavaDoc {
516             dout.writeShort(mTypeName.getIndex());
517             dout.writeShort(mConstName.getIndex());
518         }
519     }
520 }
521
Popular Tags