001 package serp.bytecode; 002 003 import java.io.*; 004 005 import serp.bytecode.lowlevel.*; 006 import serp.bytecode.visitor.*; 007 import serp.util.*; 008 009 /** 010 * Any referenced class that is not a package member is represented by 011 * this structure. This includes member classes and interfaces. 012 * 013 * @author Abe White 014 */ 015 public class InnerClass implements BCEntity, VisitAcceptor { 016 private int _index = 0; 017 private int _nameIndex = 0; 018 private int _ownerIndex = 0; 019 private int _access = Constants.ACCESS_PRIVATE; 020 private InnerClasses _owner = null; 021 022 InnerClass(InnerClasses owner) { 023 _owner = owner; 024 } 025 026 /** 027 * Inner classes are stored in an {@link InnerClasses} attribute. 028 */ 029 public InnerClasses getOwner() { 030 return _owner; 031 } 032 033 void invalidate() { 034 _owner = null; 035 } 036 037 ///////////////////// 038 // Access operations 039 ///////////////////// 040 041 /** 042 * Return the access flags of the inner class. 043 */ 044 public int getAccessFlags() { 045 return _access; 046 } 047 048 /** 049 * Set the access flags of the inner class. 050 */ 051 public void setAccessFlags(int accessFlags) { 052 _access = accessFlags; 053 } 054 055 /** 056 * Manipulate the inner class access flags. 057 */ 058 public boolean isPublic() { 059 return (getAccessFlags() & Constants.ACCESS_PUBLIC) > 0; 060 } 061 062 /** 063 * Manipulate the inner class 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 inner class access flags. 073 */ 074 public boolean isProtected() { 075 return (getAccessFlags() & Constants.ACCESS_PROTECTED) > 0; 076 } 077 078 /** 079 * Manipulate the inner class 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 inner class access flags. 089 */ 090 public boolean isPrivate() { 091 return (getAccessFlags() & Constants.ACCESS_PRIVATE) > 0; 092 } 093 094 /** 095 * Manipulate the inner class 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 inner class access flags. 105 */ 106 public boolean isFinal() { 107 return (getAccessFlags() & Constants.ACCESS_FINAL) > 0; 108 } 109 110 /** 111 * Manipulate the inner class access flags. 112 */ 113 public void setFinal(boolean on) { 114 if (on) 115 setAccessFlags(getAccessFlags() | Constants.ACCESS_FINAL); 116 else 117 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_FINAL); 118 } 119 120 /** 121 * Manipulate the inner class access flags. 122 */ 123 public boolean isStatic() { 124 return (getAccessFlags() & Constants.ACCESS_STATIC) > 0; 125 } 126 127 /** 128 * Manipulate the inner class access flags. 129 */ 130 public void setStatic(boolean on) { 131 if (on) 132 setAccessFlags(getAccessFlags() | Constants.ACCESS_STATIC); 133 else 134 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_STATIC); 135 } 136 137 /** 138 * Manipulate the class access flags. 139 */ 140 public boolean isInterface() { 141 return (getAccessFlags() & Constants.ACCESS_INTERFACE) > 0; 142 } 143 144 /** 145 * Manipulate the class access flags. 146 */ 147 public void setInterface(boolean on) { 148 if (on) { 149 setAccessFlags(getAccessFlags() | Constants.ACCESS_INTERFACE); 150 setAbstract(true); 151 } else 152 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_INTERFACE); 153 } 154 155 /** 156 * Manipulate the class access flags. 157 */ 158 public boolean isAbstract() { 159 return (getAccessFlags() & Constants.ACCESS_ABSTRACT) > 0; 160 } 161 162 /** 163 * Manipulate the class access flags. 164 */ 165 public void setAbstract(boolean on) { 166 if (on) 167 setAccessFlags(getAccessFlags() | Constants.ACCESS_INTERFACE); 168 else 169 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_INTERFACE); 170 } 171 172 /** 173 * Manipulate the inner class access flags. 174 */ 175 public boolean isSynthetic() { 176 return (getAccessFlags() & Constants.ACCESS_SYNTHETIC) > 0; 177 } 178 179 /** 180 * Manipulate the inner class access flags. 181 */ 182 public void setSynthetic(boolean on) { 183 if (on) 184 setAccessFlags(getAccessFlags() | Constants.ACCESS_SYNTHETIC); 185 else 186 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_SYNTHETIC); 187 } 188 189 /** 190 * Manipulate the inner class access flags. 191 */ 192 public boolean isAnnotation() { 193 return (getAccessFlags() & Constants.ACCESS_ANNOTATION) > 0; 194 } 195 196 /** 197 * Manipulate the inner class access flags. Setting to true also makes this 198 * an interface. 199 */ 200 public void setAnnotation(boolean on) { 201 if (on) { 202 setAccessFlags(getAccessFlags() | Constants.ACCESS_ANNOTATION); 203 setAccessFlags(getAccessFlags() | Constants.ACCESS_INTERFACE); 204 } else 205 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_ANNOTATION); 206 } 207 208 /** 209 * Manipulate the inner class access flags. 210 */ 211 public boolean isEnum() { 212 return (getAccessFlags() & Constants.ACCESS_ENUM) > 0; 213 } 214 215 /** 216 * Manipulate the inner class access flags. 217 */ 218 public void setEnum(boolean on) { 219 if (on) 220 setAccessFlags(getAccessFlags() | Constants.ACCESS_ENUM); 221 else 222 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_ENUM); 223 } 224 225 //////////////////////////////// 226 // Name, type, owner operations 227 //////////////////////////////// 228 229 /** 230 * Return the {@link ConstantPool} index of the {@link UTF8Entry} that 231 * describes the simple name this class is referred to in source, or 232 * 0 for anonymous classes. 233 */ 234 public int getNameIndex() { 235 return _nameIndex; 236 } 237 238 /** 239 * Set the {@link ConstantPool} index of the {@link UTF8Entry} that 240 * describes the simple name this class is referred to in source, or 241 * 0 for anonymous classes. 242 */ 243 public void setNameIndex(int nameIndex) { 244 _nameIndex = nameIndex; 245 } 246 247 /** 248 * Return the simple name of this inner class, or null if anonymous. 249 */ 250 public String getName() { 251 if (getNameIndex() == 0) 252 return null; 253 return ((UTF8Entry) getPool().getEntry(getNameIndex())).getValue(); 254 } 255 256 /** 257 * Set the simple name of this inner class. 258 */ 259 public void setName(String name) { 260 if (name == null) 261 setNameIndex(0); 262 else 263 setNameIndex(getPool().findUTF8Entry(name, true)); 264 } 265 266 /** 267 * Return the {@link ConstantPool} index of the {@link ClassEntry} that 268 * describes this class, or 0 if none. 269 */ 270 public int getTypeIndex() { 271 return _index; 272 } 273 274 /** 275 * Set the {@link ConstantPool} index of the {@link ClassEntry} that 276 * describes this class. 277 */ 278 public void setTypeIndex(int index) { 279 _index = index; 280 } 281 282 /** 283 * Return the full name of the inner class, or null if unset. 284 */ 285 public String getTypeName() { 286 if (getTypeIndex() == 0) 287 return null; 288 ClassEntry entry = (ClassEntry) getPool().getEntry(getTypeIndex()); 289 return getProject().getNameCache().getExternalForm(entry.getNameEntry(). 290 getValue(), false); 291 } 292 293 /** 294 * Return the type of the inner class. 295 * If the type has not been set, this method will return null. 296 */ 297 public Class getType() { 298 String type = getTypeName(); 299 if (type == null) 300 return null; 301 return Strings.toClass(type, getClassLoader()); 302 } 303 304 /** 305 * Return the type for this instruction. 306 * If the type has not been set, this method will return null. 307 */ 308 public BCClass getTypeBC() { 309 String type = getTypeName(); 310 if (type == null) 311 return null; 312 return getProject().loadClass(type, getClassLoader()); 313 } 314 315 /** 316 * Set the type of this inner class. 317 */ 318 public void setType(String type) { 319 if (type == null) 320 setTypeIndex(0); 321 else { 322 type = getProject().getNameCache().getInternalForm(type, false); 323 setTypeIndex(getPool().findClassEntry(type, true)); 324 } 325 } 326 327 /** 328 * Set the type of this inner class. 329 */ 330 public void setType(Class type) { 331 if (type == null) 332 setType((String) null); 333 else 334 setType(type.getName()); 335 } 336 337 /** 338 * Set the type of this inner class. 339 */ 340 public void setType(BCClass type) { 341 if (type == null) 342 setType((String) null); 343 else 344 setType(type.getName()); 345 } 346 347 /** 348 * Return the {@link ConstantPool} index of the {@link ClassEntry} that 349 * describes the declaring class, or 0 if this class is not a member class. 350 */ 351 public int getDeclarerIndex() { 352 return _ownerIndex; 353 } 354 355 /** 356 * Set the {@link ConstantPool} index of the {@link ClassEntry} that 357 * describes the declaring class, or 0 if this class is not a member class. 358 */ 359 public void setDeclarerIndex(int ownerIndex) { 360 _ownerIndex = ownerIndex; 361 } 362 363 /** 364 * Return the full name of the declaring class, or null if unset/not a 365 * member. 366 */ 367 public String getDeclarerName() { 368 if (getDeclarerIndex() == 0) 369 return null; 370 ClassEntry entry = (ClassEntry) getPool().getEntry(getDeclarerIndex()); 371 return getProject().getNameCache().getExternalForm(entry.getNameEntry(). 372 getValue(), false); 373 } 374 375 /** 376 * Return the type of the declaring class. 377 * If the type has not been set or the class is not a member, this method 378 * will return null. 379 */ 380 public Class getDeclarerType() { 381 String type = getDeclarerName(); 382 if (type == null) 383 return null; 384 return Strings.toClass(type, getClassLoader()); 385 } 386 387 /** 388 * Return the type for this instruction. 389 * If the type has not been set or the class is not a member, this method 390 * will return null. 391 */ 392 public BCClass getDeclarerBC() { 393 String type = getDeclarerName(); 394 if (type == null) 395 return null; 396 return getProject().loadClass(type, getClassLoader()); 397 } 398 399 /** 400 * Set the type of this declaring class. 401 */ 402 public void setDeclarer(String type) { 403 if (type == null) 404 setDeclarerIndex(0); 405 else { 406 type = getProject().getNameCache().getInternalForm(type, false); 407 setDeclarerIndex(getPool().findClassEntry(type, true)); 408 } 409 } 410 411 /** 412 * Set the type of this declaring class. 413 */ 414 public void setDeclarer(Class type) { 415 if (type == null) 416 setDeclarer((String) null); 417 else 418 setDeclarer(type.getName()); 419 } 420 421 /** 422 * Set the type of this declaring class. 423 */ 424 public void setDeclarer(BCClass type) { 425 if (type == null) 426 setDeclarer((String) null); 427 else 428 setDeclarer(type.getName()); 429 } 430 431 /////////////////////////// 432 // BCEntity implementation 433 /////////////////////////// 434 435 public Project getProject() { 436 return _owner.getProject(); 437 } 438 439 public ConstantPool getPool() { 440 return _owner.getPool(); 441 } 442 443 public ClassLoader getClassLoader() { 444 return _owner.getClassLoader(); 445 } 446 447 public boolean isValid() { 448 return _owner != null; 449 } 450 451 public void acceptVisit(BCVisitor visit) { 452 visit.enterInnerClass(this); 453 visit.exitInnerClass(this); 454 } 455 456 ////////////////// 457 // I/O operations 458 ////////////////// 459 460 void read(DataInput in) throws IOException { 461 setTypeIndex(in.readUnsignedShort()); 462 setDeclarerIndex(in.readUnsignedShort()); 463 setNameIndex(in.readUnsignedShort()); 464 setAccessFlags(in.readUnsignedShort()); 465 } 466 467 void write(DataOutput out) throws IOException { 468 out.writeShort(getTypeIndex()); 469 out.writeShort(getDeclarerIndex()); 470 out.writeShort(getNameIndex()); 471 out.writeShort(getAccessFlags()); 472 } 473 }