001 package serp.bytecode; 002 003 import java.io.*; 004 import java.util.*; 005 006 import serp.bytecode.lowlevel.*; 007 008 /** 009 * A member field or method of a class. 010 * 011 * @author Abe White 012 */ 013 public abstract class BCMember extends Annotated { 014 private BCClass _owner = null; 015 private int _access = Constants.ACCESS_PRIVATE; 016 private int _nameIndex = 0; 017 private int _descriptorIndex = 0; 018 private Collection _attrs = new LinkedList(); 019 020 BCMember(BCClass owner) { 021 _owner = owner; 022 } 023 024 /** 025 * Return the {@link BCClass} that declares this member. 026 */ 027 public BCClass getDeclarer() { 028 return _owner; 029 } 030 031 ///////////////////// 032 // Access operations 033 ///////////////////// 034 035 /** 036 * Return the access flags for this member as a bit array of 037 * ACCESS_XXX constants from {@link Constants}. This can be used to 038 * transfer access flags between members without getting/setting each 039 * possible access flag. Defaults to {@link Constants#ACCESS_PRIVATE} 040 */ 041 public int getAccessFlags() { 042 return _access; 043 } 044 045 /** 046 * Set the access flags for this member as a bit array of 047 * ACCESS_XXX constants from {@link Constants}. This can be used to 048 * transfer access flags between members without getting/setting each 049 * possible access flag. Defaults to {@link Constants#ACCESS_PRIVATE} 050 */ 051 public void setAccessFlags(int access) { 052 _access = access; 053 } 054 055 /** 056 * Manipulate the member access flags. 057 */ 058 public boolean isPublic() { 059 return (getAccessFlags() & Constants.ACCESS_PUBLIC) > 0; 060 } 061 062 /** 063 * Manipulate the member access flags. 064 */ 065 public void makePublic() { 066 setAccessFlags(getAccessFlags() | Constants.ACCESS_PUBLIC); 067 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE); 068 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED); 069 } 070 071 /** 072 * Manipulate the member access flags. 073 */ 074 public boolean isProtected() { 075 return (getAccessFlags() & Constants.ACCESS_PROTECTED) > 0; 076 } 077 078 /** 079 * Manipulate the member access flags. 080 */ 081 public void makeProtected() { 082 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC); 083 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE); 084 setAccessFlags(getAccessFlags() | Constants.ACCESS_PROTECTED); 085 } 086 087 /** 088 * Manipulate the member access flags. 089 */ 090 public boolean isPrivate() { 091 return (getAccessFlags() & Constants.ACCESS_PRIVATE) > 0; 092 } 093 094 /** 095 * Manipulate the member access flags. 096 */ 097 public void makePrivate() { 098 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC); 099 setAccessFlags(getAccessFlags() | Constants.ACCESS_PRIVATE); 100 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED); 101 } 102 103 /** 104 * Manipulate the member access flags. 105 */ 106 public boolean isPackage() { 107 boolean hasAccess = false; 108 hasAccess |= (getAccessFlags() & Constants.ACCESS_PRIVATE) > 0; 109 hasAccess |= (getAccessFlags() & Constants.ACCESS_PROTECTED) > 0; 110 hasAccess |= (getAccessFlags() & Constants.ACCESS_PUBLIC) > 0; 111 return !hasAccess; 112 } 113 114 /** 115 * Manipulate the member access flags. 116 */ 117 public void makePackage() { 118 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC); 119 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE); 120 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED); 121 } 122 123 /** 124 * Manipulate the member access flags. 125 */ 126 public boolean isFinal() { 127 return (getAccessFlags() & Constants.ACCESS_FINAL) > 0; 128 } 129 130 /** 131 * Manipulate the member access flags. 132 */ 133 public void setFinal(boolean on) { 134 if (on) 135 setAccessFlags(getAccessFlags() | Constants.ACCESS_FINAL); 136 else 137 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_FINAL); 138 } 139 140 /** 141 * Manipulate the member access flags. 142 */ 143 public boolean isStatic() { 144 return (getAccessFlags() & Constants.ACCESS_STATIC) > 0; 145 } 146 147 /** 148 * Manipulate the member access flags. 149 */ 150 public void setStatic(boolean on) { 151 if (on) 152 setAccessFlags(getAccessFlags() | Constants.ACCESS_STATIC); 153 else 154 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_STATIC); 155 } 156 157 /** 158 * Manipulate the field access flags. This method also checks the synthetic 159 * member attribute. 160 */ 161 public boolean isSynthetic() { 162 return (getAccessFlags() & Constants.ACCESS_SYNTHETIC) > 0 163 || getAttribute(Constants.ATTR_SYNTHETIC) != null; 164 } 165 166 /** 167 * Manipulate the field access flags. This method also manipulates the 168 * synthetic member attribute. 169 */ 170 public void setSynthetic(boolean on) { 171 if (on) { 172 setAccessFlags(getAccessFlags() | Constants.ACCESS_SYNTHETIC); 173 addAttribute(Constants.ATTR_SYNTHETIC); 174 } else { 175 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_SYNTHETIC); 176 removeAttribute(Constants.ATTR_SYNTHETIC); 177 } 178 } 179 180 ///////////////////////// 181 // Descriptor operations 182 ///////////////////////// 183 184 /** 185 * Return the index in the class {@link ConstantPool} of the 186 * {@link UTF8Entry} holding the name of this member. 187 */ 188 public int getNameIndex() { 189 return _nameIndex; 190 } 191 192 /** 193 * Set the index in the class {@link ConstantPool} of the 194 * {@link UTF8Entry} holding the name of this member. 195 */ 196 public void setNameIndex(int index) { 197 String origName = getName(); 198 _nameIndex = index; 199 // change all the references in the owning class 200 setEntry(origName, getDescriptor()); 201 } 202 203 /** 204 * Return the index in the class {@link ConstantPool} of the 205 * {@link UTF8Entry} holding the descriptor of this member. 206 */ 207 public int getDescriptorIndex() { 208 return _descriptorIndex; 209 } 210 211 /** 212 * Set the index in the class {@link ConstantPool} of the 213 * {@link UTF8Entry} holding the descriptor of this member. 214 */ 215 public void setDescriptorIndex(int index) { 216 String origDesc = getDescriptor(); 217 _descriptorIndex = index; 218 // change all the references in the owning class 219 setEntry(getName(), origDesc); 220 } 221 222 /** 223 * Return the name of this member. 224 */ 225 public String getName() { 226 return ((UTF8Entry) getPool().getEntry(_nameIndex)).getValue(); 227 } 228 229 /** 230 * Set the name of this member. 231 */ 232 public void setName(String name) { 233 String origName = getName(); 234 // reset the name 235 _nameIndex = getPool().findUTF8Entry(name, true); 236 // change all references in the owning class 237 setEntry(origName, getDescriptor()); 238 } 239 240 /** 241 * Return the descriptor of this member, in internal form. 242 */ 243 public String getDescriptor() { 244 return ((UTF8Entry) getPool().getEntry(_descriptorIndex)).getValue(); 245 } 246 247 /** 248 * Set the descriptor of this member. 249 */ 250 public void setDescriptor(String desc) { 251 String origDesc = getDescriptor(); 252 // reset the desc 253 desc = getProject().getNameCache().getInternalForm(desc, true); 254 _descriptorIndex = getPool().findUTF8Entry(desc, true); 255 // change all the references in the owning class 256 setEntry(getName(), origDesc); 257 } 258 259 /** 260 * Resets the {@link ComplexEntry} of the owning class corresponding to 261 * this member. Changes in the member will therefore propogate to all 262 * code in the class. 263 */ 264 private void setEntry(String origName, String origDesc) { 265 // find the entry matching this member, if any 266 String owner = getProject().getNameCache().getInternalForm 267 (_owner.getName(), false); 268 ConstantPool pool = getPool(); 269 int index; 270 if (this instanceof BCField) 271 index = pool.findFieldEntry(origName, origDesc, owner, false); 272 else if (!_owner.isInterface()) 273 index = pool.findMethodEntry(origName, origDesc, owner, false); 274 else 275 index = pool.findInterfaceMethodEntry(origName, origDesc, owner, 276 false); 277 278 // change the entry to match the new info; this is dones so 279 // that refs to the member in code will still be valid after the 280 // change, without changing any other constants that happened to match 281 // the old name and/or descriptor 282 if (index != 0) { 283 ComplexEntry complex = (ComplexEntry) pool.getEntry(index); 284 int ntIndex = pool.findNameAndTypeEntry(getName(), getDescriptor(), 285 true); 286 complex.setNameAndTypeIndex(ntIndex); 287 } 288 } 289 290 /////////////////////// 291 // Convenience methods 292 /////////////////////// 293 294 /** 295 * Convenience method to return deprecation information for the member. 296 * Acts internally through the {@link Attributes} interface. 297 */ 298 public boolean isDeprecated() { 299 return getAttribute(Constants.ATTR_DEPRECATED) != null; 300 } 301 302 /** 303 * Convenience method to set whether this member should be considered 304 * deprecated. Acts internally through the {@link Attributes} interface. 305 */ 306 public void setDeprecated(boolean on) { 307 if (!on) 308 removeAttribute(Constants.ATTR_DEPRECATED); 309 else if (!isDeprecated()) 310 addAttribute(Constants.ATTR_DEPRECATED); 311 } 312 313 //////////////////////////////// 314 // Implementation of Attributes 315 //////////////////////////////// 316 317 public Project getProject() { 318 return _owner.getProject(); 319 } 320 321 public ConstantPool getPool() { 322 return _owner.getPool(); 323 } 324 325 public ClassLoader getClassLoader() { 326 return _owner.getClassLoader(); 327 } 328 329 public boolean isValid() { 330 return _owner != null; 331 } 332 333 Collection getAttributesHolder() { 334 return _attrs; 335 } 336 337 /** 338 * Either this method or {@link #read} must be called prior to use 339 * of this class. The given descriptor must be in internal form. 340 */ 341 void initialize(String name, String descriptor) { 342 _nameIndex = getPool().findUTF8Entry(name, true); 343 _descriptorIndex = getPool().findUTF8Entry(descriptor, true); 344 } 345 346 /////////////////////////////// 347 // Implementation of Annotated 348 /////////////////////////////// 349 350 BCClass getBCClass() { 351 return _owner; 352 } 353 354 /** 355 * Used when this member is deleted from its class. 356 */ 357 void invalidate() { 358 _owner = null; 359 } 360 361 void read(DataInput in) throws IOException { 362 _access = in.readUnsignedShort(); 363 _nameIndex = in.readUnsignedShort(); 364 _descriptorIndex = in.readUnsignedShort(); 365 readAttributes(in); 366 } 367 368 void write(DataOutput out) throws IOException { 369 out.writeShort(_access); 370 out.writeShort(_nameIndex); 371 out.writeShort(_descriptorIndex); 372 writeAttributes(out); 373 } 374 }