1 32 33 package com.jeantessier.classreader; 34 35 import java.io.*; 36 import java.util.*; 37 38 import org.apache.log4j.*; 39 40 public class Classfile implements Deprecatable, Visitable { 41 public static final int ACC_PUBLIC = 0x0001; 42 public static final int ACC_FINAL = 0x0010; 43 public static final int ACC_SUPER = 0x0020; 44 public static final int ACC_INTERFACE = 0x0200; 45 public static final int ACC_ABSTRACT = 0x0400; 46 47 private ClassfileLoader loader; 48 49 private int magicNumber; 50 private int minorVersion; 51 private int majorVersion; 52 private ConstantPool constantPool; 53 private int accessFlag; 54 private int classIndex; 55 private int superclassIndex; 56 private Map interfaces = new TreeMap(); 57 private Map fields = new TreeMap(); 58 private Map methods = new TreeMap(); 59 private Collection attributes = new LinkedList(); 60 61 65 public Classfile(ClassfileLoader loader, DataInputStream in) throws IOException { 66 this.loader = loader; 67 68 magicNumber = in.readInt(); 69 Logger.getLogger(getClass()).debug("magic number = " + magicNumber); 70 71 if (magicNumber != 0xCAFEBABE) { 72 throw new IOException("Bad magic number"); 73 } 74 75 minorVersion = in.readUnsignedShort(); 77 Logger.getLogger(getClass()).debug("minor version = " + minorVersion); 78 majorVersion = in.readUnsignedShort(); 79 Logger.getLogger(getClass()).debug("major version = " + majorVersion); 80 81 Logger.getLogger(getClass()).debug("Reading the constant pool ..."); 83 constantPool = new ConstantPool(this, in); 84 Logger.getLogger(getClass()).debug(constantPool); 85 86 accessFlag = in.readUnsignedShort(); 88 Logger.getLogger(getClass()).debug("accessFlag = " + accessFlag); 89 90 classIndex = in.readUnsignedShort(); 92 Logger.getLogger(getClass()).debug("thisClass = " + classIndex + " (" + getClassName() + ")"); 93 94 superclassIndex = in.readUnsignedShort(); 96 Logger.getLogger(getClass()).debug("superclass = " + superclassIndex + " (" + getSuperclassName() + ")"); 97 98 int interfaceCount = in.readUnsignedShort(); 100 Logger.getLogger(getClass()).debug("Reading " + interfaceCount + " interface(s)"); 101 for (int i=0; i<interfaceCount; i++) { 102 Class_info interfaceInfo = (Class_info) constantPool.get(in.readUnsignedShort()); 103 Logger.getLogger(getClass()).debug(" " + interfaceInfo.getName()); 104 interfaces.put(interfaceInfo.getName(), interfaceInfo); 105 } 106 107 int fieldCount = in.readUnsignedShort(); 109 Logger.getLogger(getClass()).debug("Reading " + fieldCount + " field(s)"); 110 for (int i=0; i<fieldCount; i++) { 111 Logger.getLogger(getClass()).debug("Field " + i + ":"); 112 Field_info fieldInfo = new Field_info(this, in); 113 fields.put(fieldInfo.getName(), fieldInfo); 114 } 115 116 int methodCount = in.readUnsignedShort(); 118 Logger.getLogger(getClass()).debug("Reading " + methodCount + " method(s)"); 119 for (int i=0; i<methodCount; i++) { 120 Logger.getLogger(getClass()).debug("Method " + i + ":"); 121 Method_info methodInfo = new Method_info(this, in); 122 methods.put(methodInfo.getSignature(), methodInfo); 123 } 124 125 int attributeCount = in.readUnsignedShort(); 127 Logger.getLogger(getClass()).debug("Reading " + attributeCount + " class attribute(s)"); 128 for (int i=0; i<attributeCount; i++) { 129 Logger.getLogger(getClass()).debug("Attribute " + i + ":"); 130 attributes.add(AttributeFactory.create(this, this, in)); 131 } 132 } 133 134 public ClassfileLoader getLoader() { 135 return loader; 136 } 137 138 public int getMagicNumber() { 139 return magicNumber; 140 } 141 142 public int getMinorVersion() { 143 return minorVersion; 144 } 145 146 public int getMajorVersion() { 147 return majorVersion; 148 } 149 150 public ConstantPool getConstantPool() { 151 return constantPool; 152 } 153 154 public int getAccessFlag() { 155 return accessFlag; 156 } 157 158 public int getClassIndex() { 159 return classIndex; 160 } 161 162 public Class_info getRawClass() { 163 return (Class_info) getConstantPool().get(getClassIndex()); 164 } 165 166 public String getClassName() { 167 return getRawClass().toString(); 168 } 169 170 public int getSuperclassIndex() { 171 return superclassIndex; 172 } 173 174 public Class_info getRawSuperclass() { 175 return (Class_info) getConstantPool().get(getSuperclassIndex()); 176 } 177 178 public String getSuperclassName() { 179 String result = ""; 180 181 if (getSuperclassIndex() != 0) { 182 result = getRawSuperclass().toString(); 183 } 184 185 return result; 186 } 187 188 public Class_info getInterface(String name) { 189 return (Class_info) interfaces.get(name); 190 } 191 192 public Collection getAllInterfaces() { 193 return interfaces.values(); 194 } 195 196 public Collection getAllFields() { 197 return fields.values(); 198 } 199 200 public Field_info getField(String name) { 201 return (Field_info) fields.get(name); 202 } 203 204 public Field_info locateField(String name) { 205 Field_info result = getField(name); 206 207 if (result == null) { 208 Classfile classfile = getLoader().getClassfile(getSuperclassName()); 209 if (classfile != null) { 210 Field_info attempt = classfile.locateField(name); 211 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) { 212 result = attempt; 213 } 214 } 215 } 216 217 Iterator i = getAllInterfaces().iterator(); 218 while (result == null && i.hasNext()) { 219 Classfile classfile = getLoader().getClassfile(i.next().toString()); 220 if (classfile != null) { 221 Field_info attempt = classfile.locateField(name); 222 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) { 223 result = attempt; 224 } 225 } 226 } 227 228 return result; 229 } 230 231 public Collection getAllMethods() { 232 return methods.values(); 233 } 234 235 public Method_info getMethod(String signature) { 236 return (Method_info) methods.get(signature); 237 } 238 239 public Method_info locateMethod(String signature) { 240 Method_info result = getMethod(signature); 241 242 if (result == null) { 243 Classfile classfile = getLoader().getClassfile(getSuperclassName()); 244 if (classfile != null) { 245 Method_info attempt = classfile.locateMethod(signature); 246 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) { 247 result = attempt; 248 } 249 } 250 } 251 252 Iterator i = getAllInterfaces().iterator(); 253 while (result == null && i.hasNext()) { 254 Classfile classfile = getLoader().getClassfile(i.next().toString()); 255 if (classfile != null) { 256 Method_info attempt = classfile.locateMethod(signature); 257 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) { 258 result = attempt; 259 } 260 } 261 } 262 263 return result; 264 } 265 266 public Collection getAttributes() { 267 return attributes; 268 } 269 270 public boolean isPublic() { 271 return (getAccessFlag() & ACC_PUBLIC) != 0; 272 } 273 274 public boolean isPackage() { 275 return (getAccessFlag() & ACC_PUBLIC) == 0; 276 } 277 278 public boolean isFinal() { 279 return (getAccessFlag() & ACC_FINAL) != 0; 280 } 281 282 public boolean isSuper() { 283 return (getAccessFlag() & ACC_SUPER) != 0; 284 } 285 286 public boolean isInterface() { 287 return (getAccessFlag() & ACC_INTERFACE) != 0; 288 } 289 290 public boolean isAbstract() { 291 return (getAccessFlag() & ACC_ABSTRACT) != 0; 292 } 293 294 public boolean isSynthetic() { 295 boolean result = false; 296 297 Iterator i = getAttributes().iterator(); 298 while (!result && i.hasNext()) { 299 result = i.next() instanceof Synthetic_attribute; 300 } 301 302 return result; 303 } 304 305 public boolean isDeprecated() { 306 boolean result = false; 307 308 Iterator i = getAttributes().iterator(); 309 while (!result && i.hasNext()) { 310 result = i.next() instanceof Deprecated_attribute; 311 } 312 313 return result; 314 } 315 316 public String getDeclaration() { 317 StringBuffer result = new StringBuffer (); 318 319 if (isPublic()) result.append("public "); 320 if (isFinal()) result.append("final "); 321 322 if (isInterface()) { 323 result.append("interface ").append(getClassName()); 324 325 if (getAllInterfaces().size() != 0) { 326 result.append(" extends "); 327 Iterator i = getAllInterfaces().iterator(); 328 while (i.hasNext()) { 329 result.append(i.next()); 330 if (i.hasNext()) { 331 result.append(", "); 332 } 333 } 334 } 335 } else { 336 if (isAbstract()) result.append("abstract "); 337 result.append("class ").append(getClassName()); 338 339 if (getSuperclassIndex() != 0) { 340 result.append(" extends ").append(getSuperclassName()); 341 } 342 343 if (getAllInterfaces().size() != 0) { 344 result.append(" implements "); 345 Iterator i = getAllInterfaces().iterator(); 346 while (i.hasNext()) { 347 result.append(i.next()); 348 if (i.hasNext()) { 349 result.append(", "); 350 } 351 } 352 } 353 } 354 355 return result.toString(); 356 } 357 358 public void accept(Visitor visitor) { 359 visitor.visitClassfile(this); 360 } 361 362 public String toString() { 363 return getClassName(); 364 } 365 } 366 | Popular Tags |