Home | History | Annotate | Download | only in bytecode
      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.bytecode;
     17 
     18 import java.io.DataInputStream;
     19 import java.io.DataOutputStream;
     20 import java.io.IOException;
     21 import java.util.List;
     22 import java.util.ArrayList;
     23 
     24 /**
     25  * <code>field_info</code> structure.
     26  *
     27  * @see javassist.CtField#getFieldInfo()
     28  */
     29 public final class FieldInfo {
     30     ConstPool constPool;
     31     int accessFlags;
     32     int name;
     33     String cachedName;
     34     String cachedType;
     35     int descriptor;
     36     ArrayList attribute;       // may be null.
     37 
     38     private FieldInfo(ConstPool cp) {
     39         constPool = cp;
     40         accessFlags = 0;
     41         attribute = null;
     42     }
     43 
     44     /**
     45      * Constructs a <code>field_info</code> structure.
     46      *
     47      * @param cp                a constant pool table
     48      * @param fieldName         field name
     49      * @param desc              field descriptor
     50      *
     51      * @see Descriptor
     52      */
     53     public FieldInfo(ConstPool cp, String fieldName, String desc) {
     54         this(cp);
     55         name = cp.addUtf8Info(fieldName);
     56         cachedName = fieldName;
     57         descriptor = cp.addUtf8Info(desc);
     58     }
     59 
     60     FieldInfo(ConstPool cp, DataInputStream in) throws IOException {
     61         this(cp);
     62         read(in);
     63     }
     64 
     65     /**
     66      * Returns a string representation of the object.
     67      */
     68     public String toString() {
     69         return getName() + " " + getDescriptor();
     70     }
     71 
     72     /**
     73      * Copies all constant pool items to a given new constant pool
     74      * and replaces the original items with the new ones.
     75      * This is used for garbage collecting the items of removed fields
     76      * and methods.
     77      *
     78      * @param cp    the destination
     79      */
     80     void compact(ConstPool cp) {
     81         name = cp.addUtf8Info(getName());
     82         descriptor = cp.addUtf8Info(getDescriptor());
     83         attribute = AttributeInfo.copyAll(attribute, cp);
     84         constPool = cp;
     85     }
     86 
     87     void prune(ConstPool cp) {
     88         ArrayList newAttributes = new ArrayList();
     89         AttributeInfo invisibleAnnotations
     90             = getAttribute(AnnotationsAttribute.invisibleTag);
     91         if (invisibleAnnotations != null) {
     92             invisibleAnnotations = invisibleAnnotations.copy(cp, null);
     93             newAttributes.add(invisibleAnnotations);
     94          }
     95 
     96         AttributeInfo visibleAnnotations
     97             = getAttribute(AnnotationsAttribute.visibleTag);
     98         if (visibleAnnotations != null) {
     99             visibleAnnotations = visibleAnnotations.copy(cp, null);
    100             newAttributes.add(visibleAnnotations);
    101         }
    102 
    103         AttributeInfo signature
    104             = getAttribute(SignatureAttribute.tag);
    105         if (signature != null) {
    106             signature = signature.copy(cp, null);
    107             newAttributes.add(signature);
    108         }
    109 
    110         int index = getConstantValue();
    111         if (index != 0) {
    112             index = constPool.copy(index, cp, null);
    113             newAttributes.add(new ConstantAttribute(cp, index));
    114         }
    115 
    116         attribute = newAttributes;
    117         name = cp.addUtf8Info(getName());
    118         descriptor = cp.addUtf8Info(getDescriptor());
    119         constPool = cp;
    120     }
    121 
    122     /**
    123      * Returns the constant pool table used
    124      * by this <code>field_info</code>.
    125      */
    126     public ConstPool getConstPool() {
    127         return constPool;
    128     }
    129 
    130     /**
    131      * Returns the field name.
    132      */
    133     public String getName() {
    134        if (cachedName == null)
    135            cachedName = constPool.getUtf8Info(name);
    136 
    137        return cachedName;
    138     }
    139 
    140     /**
    141      * Sets the field name.
    142      */
    143     public void setName(String newName) {
    144         name = constPool.addUtf8Info(newName);
    145         cachedName = newName;
    146     }
    147 
    148     /**
    149      * Returns the access flags.
    150      *
    151      * @see AccessFlag
    152      */
    153     public int getAccessFlags() {
    154         return accessFlags;
    155     }
    156 
    157     /**
    158      * Sets the access flags.
    159      *
    160      * @see AccessFlag
    161      */
    162     public void setAccessFlags(int acc) {
    163         accessFlags = acc;
    164     }
    165 
    166     /**
    167      * Returns the field descriptor.
    168      *
    169      * @see Descriptor
    170      */
    171     public String getDescriptor() {
    172         return constPool.getUtf8Info(descriptor);
    173     }
    174 
    175     /**
    176      * Sets the field descriptor.
    177      *
    178      * @see Descriptor
    179      */
    180     public void setDescriptor(String desc) {
    181         if (!desc.equals(getDescriptor()))
    182             descriptor = constPool.addUtf8Info(desc);
    183     }
    184 
    185     /**
    186      * Finds a ConstantValue attribute and returns the index into
    187      * the <code>constant_pool</code> table.
    188      *
    189      * @return 0    if a ConstantValue attribute is not found.
    190      */
    191     public int getConstantValue() {
    192         if ((accessFlags & AccessFlag.STATIC) == 0)
    193             return 0;
    194 
    195         ConstantAttribute attr
    196             = (ConstantAttribute)getAttribute(ConstantAttribute.tag);
    197         if (attr == null)
    198             return 0;
    199         else
    200             return attr.getConstantValue();
    201     }
    202 
    203     /**
    204      * Returns all the attributes.    The returned <code>List</code> object
    205      * is shared with this object.  If you add a new attribute to the list,
    206      * the attribute is also added to the field represented by this
    207      * object.  If you remove an attribute from the list, it is also removed
    208      * from the field.
    209      *
    210      * @return a list of <code>AttributeInfo</code> objects.
    211      * @see AttributeInfo
    212      */
    213     public List getAttributes() {
    214         if (attribute == null)
    215             attribute = new ArrayList();
    216 
    217         return attribute;
    218     }
    219 
    220     /**
    221      * Returns the attribute with the specified name.
    222      * It returns null if the specified attribute is not found.
    223      *
    224      * @param name      attribute name
    225      * @see #getAttributes()
    226      */
    227     public AttributeInfo getAttribute(String name) {
    228         return AttributeInfo.lookup(attribute, name);
    229     }
    230 
    231     /**
    232      * Appends an attribute.  If there is already an attribute with
    233      * the same name, the new one substitutes for it.
    234      *
    235      * @see #getAttributes()
    236      */
    237     public void addAttribute(AttributeInfo info) {
    238         if (attribute == null)
    239             attribute = new ArrayList();
    240 
    241         AttributeInfo.remove(attribute, info.getName());
    242         attribute.add(info);
    243     }
    244 
    245     private void read(DataInputStream in) throws IOException {
    246         accessFlags = in.readUnsignedShort();
    247         name = in.readUnsignedShort();
    248         descriptor = in.readUnsignedShort();
    249         int n = in.readUnsignedShort();
    250         attribute = new ArrayList();
    251         for (int i = 0; i < n; ++i)
    252             attribute.add(AttributeInfo.read(constPool, in));
    253     }
    254 
    255     void write(DataOutputStream out) throws IOException {
    256         out.writeShort(accessFlags);
    257         out.writeShort(name);
    258         out.writeShort(descriptor);
    259         if (attribute == null)
    260             out.writeShort(0);
    261         else {
    262             out.writeShort(attribute.size());
    263             AttributeInfo.writeAll(attribute, out);
    264         }
    265     }
    266 }
    267