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 }