001 package serp.bytecode;
002
003 import java.io.*;
004 import java.util.*;
005
006 import serp.bytecode.visitor.*;
007
008 /**
009 * Java annotation data.
010 *
011 * @author Abe White
012 */
013 public class Annotations extends Attribute {
014 private final List _annotations = new ArrayList();
015
016 Annotations(int nameIndex, Attributes owner) {
017 super(nameIndex, owner);
018 }
019
020 /**
021 * Whether these annotations are runtime-visible.
022 */
023 public boolean isRuntime() {
024 return getName().equals(Constants.ATTR_RUNTIME_ANNOTATIONS);
025 }
026
027 /**
028 * All declared annotations.
029 */
030 public Annotation[] getAnnotations() {
031 return (Annotation[]) _annotations.toArray
032 (new Annotation[_annotations.size()]);
033 }
034
035 /**
036 * Set the annotations. This method is useful when
037 * importing annotations from another instance.
038 */
039 public void setAnnotations(Annotation[] annos) {
040 clear();
041 if (annos != null)
042 for (int i = 0; i < annos.length; i++)
043 addAnnotation(annos[i]);
044 }
045
046 /**
047 * Return the annotation of the given type, or null if none.
048 */
049 public Annotation getAnnotation(Class type) {
050 return (type == null) ? null : getAnnotation(type.getName());
051 }
052
053 /**
054 * Return the annotation of the given type, or null if none.
055 */
056 public Annotation getAnnotation(BCClass type) {
057 return (type == null) ? null : getAnnotation(type.getName());
058 }
059
060 /**
061 * Return the annotation of the given type, or null if none.
062 */
063 public Annotation getAnnotation(String type) {
064 Annotation anno;
065 for (int i = 0; i < _annotations.size(); i++) {
066 anno = (Annotation) _annotations.get(i);
067 if (anno.getTypeName().equals(type))
068 return anno;
069 }
070 return null;
071 }
072
073 /**
074 * Import an annotation from another instance.
075 *
076 * @return the newly added annotation
077 */
078 public Annotation addAnnotation(Annotation an) {
079 Annotation anno = addAnnotation(an.getTypeName());
080 anno.setProperties(an.getProperties());
081 return anno;
082 }
083
084 /**
085 * Add a new annotation.
086 */
087 public Annotation addAnnotation(Class type) {
088 return addAnnotation(type.getName());
089 }
090
091 /**
092 * Add a new annotation.
093 */
094 public Annotation addAnnotation(BCClass type) {
095 return addAnnotation(type.getName());
096 }
097
098 /**
099 * Add a new annotation.
100 */
101 public Annotation addAnnotation(String type) {
102 Annotation anno = new Annotation(this);
103 anno.setType(type);
104 _annotations.add(anno);
105 return anno;
106 }
107
108 /**
109 * Remove all annotations.
110 */
111 public void clear() {
112 for (int i = 0; i < _annotations.size(); i++)
113 ((Annotation) _annotations.get(i)).invalidate();
114 _annotations.clear();
115 }
116
117 /**
118 * Remove the given annotation.
119 *
120 * @return true if an annotation was removed, false otherwise
121 */
122 public boolean removeAnnotation(Annotation anno) {
123 return anno != null && removeAnnotation(anno.getTypeName());
124 }
125
126 /**
127 * Remove the annotation of the given type.
128 *
129 * @return true if an annotation was removed, false otherwise
130 */
131 public boolean removeAnnotation(Class type) {
132 return type != null && removeAnnotation(type.getName());
133 }
134
135 /**
136 * Remove the annotation of the given type.
137 *
138 * @return true if an annotation was removed, false otherwise
139 */
140 public boolean removeAnnotation(BCClass type) {
141 return type != null && removeAnnotation(type.getName());
142 }
143
144 /**
145 * Remove the annotation of the given type.
146 *
147 * @return true if an annotation was removed, false otherwise
148 */
149 public boolean removeAnnotation(String type) {
150 if (type == null)
151 return false;
152 Annotation anno;
153 for (int i = 0; i < _annotations.size(); i++) {
154 anno = (Annotation) _annotations.get(i);
155 if (anno.getTypeName().equals(type)) {
156 anno.invalidate();
157 _annotations.remove(i);
158 return true;
159 }
160 }
161 return false;
162 }
163
164 int getLength() {
165 int len = 2;
166 for (int i = 0; i < _annotations.size(); i++)
167 len += ((Annotation) _annotations.get(i)).getLength();
168 return len;
169 }
170
171 void read(Attribute other) {
172 setAnnotations(((Annotations) other).getAnnotations());
173 }
174
175 void read(DataInput in, int length) throws IOException {
176 _annotations.clear();
177 int annos = in.readUnsignedShort();
178 Annotation anno;
179 for (int i = 0; i < annos; i++) {
180 anno = new Annotation(this);
181 anno.read(in);
182 _annotations.add(anno);
183 }
184 }
185
186 void write(DataOutput out, int length) throws IOException {
187 out.writeShort(_annotations.size());
188 for (int i = 0; i < _annotations.size(); i++)
189 ((Annotation) _annotations.get(i)).write(out);
190 }
191
192 public void acceptVisit(BCVisitor visit) {
193 visit.enterAnnotations(this);
194 for (int i = 0; i < _annotations.size(); i++)
195 ((Annotation) _annotations.get(i)).acceptVisit(visit);
196 visit.exitAnnotations(this);
197 }
198 }