• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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