1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16 package javassist; 17 18 /** 19 * An instance of <code>CtMember</code> represents a field, a constructor, 20 * or a method. 21 */ 22 public abstract class CtMember { 23 CtMember next; // for internal use 24 protected CtClass declaringClass; 25 26 /* Make a circular link of CtMembers declared in the 27 * same class so that they are garbage-collected together 28 * at the same time. 29 */ 30 static class Cache extends CtMember { 31 protected void extendToString(StringBuffer buffer) {} 32 public boolean hasAnnotation(Class clz) { return false; } 33 public Object getAnnotation(Class clz) 34 throws ClassNotFoundException { return null; } 35 public Object[] getAnnotations() 36 throws ClassNotFoundException { return null; } 37 public byte[] getAttribute(String name) { return null; } 38 public Object[] getAvailableAnnotations() { return null; } 39 public int getModifiers() { return 0; } 40 public String getName() { return null; } 41 public String getSignature() { return null; } 42 public void setAttribute(String name, byte[] data) {} 43 public void setModifiers(int mod) {} 44 45 private CtMember methodTail; 46 private CtMember consTail; // constructor tail 47 private CtMember fieldTail; 48 49 Cache(CtClassType decl) { 50 super(decl); 51 methodTail = this; 52 consTail = this; 53 fieldTail = this; 54 fieldTail.next = this; 55 } 56 57 CtMember methodHead() { return this; } 58 CtMember lastMethod() { return methodTail; } 59 CtMember consHead() { return methodTail; } // may include a static initializer 60 CtMember lastCons() { return consTail; } 61 CtMember fieldHead() { return consTail; } 62 CtMember lastField() { return fieldTail; } 63 64 void addMethod(CtMember method) { 65 method.next = methodTail.next; 66 methodTail.next = method; 67 if (methodTail == consTail) { 68 consTail = method; 69 if (methodTail == fieldTail) 70 fieldTail = method; 71 } 72 73 methodTail = method; 74 } 75 76 /* Both constructors and a class initializer. 77 */ 78 void addConstructor(CtMember cons) { 79 cons.next = consTail.next; 80 consTail.next = cons; 81 if (consTail == fieldTail) 82 fieldTail = cons; 83 84 consTail = cons; 85 } 86 87 void addField(CtMember field) { 88 field.next = this; // or fieldTail.next 89 fieldTail.next = field; 90 fieldTail = field; 91 } 92 93 static int count(CtMember head, CtMember tail) { 94 int n = 0; 95 while (head != tail) { 96 n++; 97 head = head.next; 98 } 99 100 return n; 101 } 102 103 void remove(CtMember mem) { 104 CtMember m = this; 105 CtMember node; 106 while ((node = m.next) != this) { 107 if (node == mem) { 108 m.next = node.next; 109 if (node == methodTail) 110 methodTail = m; 111 112 if (node == consTail) 113 consTail = m; 114 115 if (node == fieldTail) 116 fieldTail = m; 117 118 break; 119 } 120 else 121 m = m.next; 122 } 123 } 124 } 125 126 protected CtMember(CtClass clazz) { 127 declaringClass = clazz; 128 next = null; 129 } 130 131 final CtMember next() { return next; } 132 133 /** 134 * This method is invoked when setName() or replaceClassName() 135 * in CtClass is called. 136 * 137 * @see CtMethod#nameReplaced() 138 */ 139 void nameReplaced() {} 140 141 public String toString() { 142 StringBuffer buffer = new StringBuffer(getClass().getName()); 143 buffer.append("@"); 144 buffer.append(Integer.toHexString(hashCode())); 145 buffer.append("["); 146 buffer.append(Modifier.toString(getModifiers())); 147 extendToString(buffer); 148 buffer.append("]"); 149 return buffer.toString(); 150 } 151 152 /** 153 * Invoked by {@link #toString()} to add to the buffer and provide the 154 * complete value. Subclasses should invoke this method, adding a 155 * space before each token. The modifiers for the member are 156 * provided first; subclasses should provide additional data such 157 * as return type, field or method name, etc. 158 */ 159 protected abstract void extendToString(StringBuffer buffer); 160 161 /** 162 * Returns the class that declares this member. 163 */ 164 public CtClass getDeclaringClass() { return declaringClass; } 165 166 /** 167 * Returns true if this member is accessible from the given class. 168 */ 169 public boolean visibleFrom(CtClass clazz) { 170 int mod = getModifiers(); 171 if (Modifier.isPublic(mod)) 172 return true; 173 else if (Modifier.isPrivate(mod)) 174 return clazz == declaringClass; 175 else { // package or protected 176 String declName = declaringClass.getPackageName(); 177 String fromName = clazz.getPackageName(); 178 boolean visible; 179 if (declName == null) 180 visible = fromName == null; 181 else 182 visible = declName.equals(fromName); 183 184 if (!visible && Modifier.isProtected(mod)) 185 return clazz.subclassOf(declaringClass); 186 187 return visible; 188 } 189 } 190 191 /** 192 * Obtains the modifiers of the member. 193 * 194 * @return modifiers encoded with 195 * <code>javassist.Modifier</code>. 196 * @see Modifier 197 */ 198 public abstract int getModifiers(); 199 200 /** 201 * Sets the encoded modifiers of the member. 202 * 203 * @see Modifier 204 */ 205 public abstract void setModifiers(int mod); 206 207 /** 208 * Returns true if the class has the specified annotation class. 209 * 210 * @param clz the annotation class. 211 * @return <code>true</code> if the annotation is found, otherwise <code>false</code>. 212 * @since 3.11 213 */ 214 public abstract boolean hasAnnotation(Class clz); 215 216 /** 217 * Returns the annotation if the class has the specified annotation class. 218 * For example, if an annotation <code>@Author</code> is associated 219 * with this member, an <code>Author</code> object is returned. 220 * The member values can be obtained by calling methods on 221 * the <code>Author</code> object. 222 * 223 * @param clz the annotation class. 224 * @return the annotation if found, otherwise <code>null</code>. 225 * @since 3.11 226 */ 227 public abstract Object getAnnotation(Class clz) throws ClassNotFoundException; 228 229 /** 230 * Returns the annotations associated with this member. 231 * For example, if an annotation <code>@Author</code> is associated 232 * with this member, the returned array contains an <code>Author</code> 233 * object. The member values can be obtained by calling methods on 234 * the <code>Author</code> object. 235 * 236 * @return an array of annotation-type objects. 237 * @see CtClass#getAnnotations() 238 */ 239 public abstract Object[] getAnnotations() throws ClassNotFoundException; 240 241 /** 242 * Returns the annotations associated with this member. 243 * This method is equivalent to <code>getAnnotations()</code> 244 * except that, if any annotations are not on the classpath, 245 * they are not included in the returned array. 246 * 247 * @return an array of annotation-type objects. 248 * @see #getAnnotations() 249 * @see CtClass#getAvailableAnnotations() 250 * @since 3.3 251 */ 252 public abstract Object[] getAvailableAnnotations(); 253 254 /** 255 * Obtains the name of the member. 256 * 257 * <p>As for constructor names, see <code>getName()</code> 258 * in <code>CtConstructor</code>. 259 * 260 * @see CtConstructor#getName() 261 */ 262 public abstract String getName(); 263 264 /** 265 * Returns the character string representing the signature of the member. 266 * If two members have the same signature (parameter types etc.), 267 * <code>getSignature()</code> returns the same string. 268 */ 269 public abstract String getSignature(); 270 271 /** 272 * Obtains a user-defined attribute with the given name. 273 * If that attribute is not found in the class file, this 274 * method returns null. 275 * 276 * <p>Note that an attribute is a data block specified by 277 * the class file format. 278 * See {@link javassist.bytecode.AttributeInfo}. 279 * 280 * @param name attribute name 281 */ 282 public abstract byte[] getAttribute(String name); 283 284 /** 285 * Adds a user-defined attribute. The attribute is saved in the class file. 286 * 287 * <p>Note that an attribute is a data block specified by 288 * the class file format. 289 * See {@link javassist.bytecode.AttributeInfo}. 290 * 291 * @param name attribute name 292 * @param data attribute value 293 */ 294 public abstract void setAttribute(String name, byte[] data); 295 } 296