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 FieldInfo(ConstPool cp)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 */ FieldInfo(ConstPool cp, String fieldName, String desc)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 FieldInfo(ConstPool cp, DataInputStream in)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 */ toString()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 */ compact(ConstPool cp)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 prune(ConstPool cp)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 */ getConstPool()126 public ConstPool getConstPool() { 127 return constPool; 128 } 129 130 /** 131 * Returns the field name. 132 */ getName()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 */ setName(String newName)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 */ getAccessFlags()153 public int getAccessFlags() { 154 return accessFlags; 155 } 156 157 /** 158 * Sets the access flags. 159 * 160 * @see AccessFlag 161 */ setAccessFlags(int acc)162 public void setAccessFlags(int acc) { 163 accessFlags = acc; 164 } 165 166 /** 167 * Returns the field descriptor. 168 * 169 * @see Descriptor 170 */ getDescriptor()171 public String getDescriptor() { 172 return constPool.getUtf8Info(descriptor); 173 } 174 175 /** 176 * Sets the field descriptor. 177 * 178 * @see Descriptor 179 */ setDescriptor(String desc)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 */ getConstantValue()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 */ getAttributes()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 */ getAttribute(String name)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 */ addAttribute(AttributeInfo info)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 read(DataInputStream in)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 write(DataOutputStream out)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