Home | History | Annotate | Download | only in javassist
      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