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