1 24 25 package org.aspectj.compiler.base.bcg; 26 27 import org.aspectj.compiler.base.bcg.pool.*; 28 29 import java.lang.reflect.Modifier ; 30 31 import java.util.ArrayList ; 32 import java.util.List ; 33 import java.util.HashSet ; 34 import java.util.Iterator ; 35 36 import java.io.IOException ; 37 import java.io.DataOutputStream ; 38 import java.io.DataInputStream ; 39 import java.io.File ; 40 41 import org.aspectj.compiler.base.ast.SourceLocation; 42 import org.aspectj.compiler.base.JavaCompiler; 43 44 import org.aspectj.compiler.base.ast.RefType; 46 import org.aspectj.compiler.base.ast.NameType; 47 import org.aspectj.compiler.base.ast.TypeDec; 48 49 53 55 58 public class ClassfileBuilder { 59 60 private JavaCompiler compiler; 61 public ClassfileBuilder(JavaCompiler compiler) { 62 this.compiler = compiler; 63 } 64 public JavaCompiler getCompiler() { return compiler; } 65 66 69 private int magic = (int)0xcafebabeL; 70 private short minorVersion = 3; 71 private short majorVersion = 45; 72 ConstantPool pool = new ConstantPool(this); 73 private int accessFlags = 0; private Constant thisClass; 75 private Constant superClass; 76 private List interfaces = new ArrayList (); 77 private List fields = new ArrayList (); 78 private List methods = new ArrayList (); 79 private Attributes attributes = new Attributes(pool); 80 81 private List innerTypeDecs = new ArrayList (); 83 84 87 public void addAccessFlags(int newFlags) { 88 accessFlags = accessFlags | newFlags; 89 } 90 public void setClassName(NameType nameType) { 91 thisClass = pool.addClass(nameType); 92 } 93 public void setSuperClassName(NameType nameType) { 94 superClass = pool.addClass(nameType); 95 } 96 public void addInterface(NameType nameType) { 97 interfaces.add(pool.addClass(nameType)); 98 } 99 public FieldBuilder getFieldBuilder() { 100 return new FieldBuilder(this); 101 } 102 public void addField(FieldBuilder maker) { 103 fields.add(maker); 104 } 105 public MethodBuilder getMethodBuilder() { 106 return new MethodBuilder(this); 107 } 108 public void addMethod(MethodBuilder maker) { 109 methods.add(maker); 110 } 111 public void setSynthetic() { 112 attributes.addSyntheticAttribute(); 113 } 114 public void setSourceFile(SourceLocation loc) { 115 sourceFiles = new SourceFile(loc); 116 } 117 public void setSourceDebugExtension(String data) { 118 attributes.addSouceDebugExtensionAttribute(data); 119 } 120 121 124 private HashSet innerClasses = new HashSet (); 125 public void addInnerClassRef(NameType nameType) { 126 if (! innerClasses.contains(nameType)) { 127 innerClasses.add(nameType); 128 attributes.addToInnerClassesAttribute(nameType); 129 } 130 } 131 132 public void delayInnerClassGeneration(TypeDec typeDec) { 133 addInnerClassRef(typeDec.getNameType()); 134 innerTypeDecs.add(typeDec); 135 } 136 137 public void generateBytecodeForDelayedInnerClasses(File outputDir) throws IOException { 138 for (Iterator i = innerTypeDecs.iterator(); i.hasNext(); ) { 139 TypeDec typeDec = (TypeDec) i.next(); 140 typeDec.generateBytecode(outputDir); 141 } 142 } 143 144 147 public void writeTo(DataOutputStream stream) throws IOException { 148 stream.writeInt(magic); 149 stream.writeShort(minorVersion); 150 stream.writeShort(majorVersion); 151 pool.writeTo(stream); 152 stream.writeShort(accessFlags); 153 thisClass.writeIndex(stream); 154 superClass.writeIndex(stream); 155 stream.writeShort((short)interfaces.size()); 156 for (Iterator i = interfaces.iterator(); i.hasNext(); ) { 157 Constant iface = (Constant) i.next(); 158 iface.writeIndex(stream); 159 } 160 stream.writeShort((short)fields.size()); 161 for (Iterator i = fields.iterator(); i.hasNext(); ) { 162 FieldBuilder field = (FieldBuilder) i.next(); 163 field.writeTo(stream); 164 } 165 stream.writeShort((short)methods.size()); 166 for (Iterator i = methods.iterator(); i.hasNext(); ) { 167 MethodBuilder method = (MethodBuilder) i.next(); 168 method.writeTo(stream); 169 } 170 attributes.writeTo(stream); 171 if (compiler.getOptions().bcgtrace) { 172 print(); 173 } 174 } 175 176 179 void print() { 180 display(0, false); 181 System.err.println(); 182 } 183 184 static void between(int indent, boolean inline) { 185 if (inline) { 186 System.err.print(" "); 187 } else { 188 System.err.println(); 189 for (int s=indent; s >= 0; s--) System.err.print(" "); 190 } 191 } 192 193 void display(int indent, boolean inline) { 194 indent += 2; 195 System.err.print("(class "); thisClass.display(0, true); 196 between(indent, inline); 197 System.err.print("(modifiers " + Modifier.toString(accessFlags) + ")"); 198 between(indent, inline); 199 System.err.print("(extends "); superClass.display(0, true); System.err.print(")"); 200 between(indent, inline); 201 System.err.print("(implements"); 202 ConstantPool.display(interfaces, 0, true); 203 System.err.print(")"); 204 between(indent, inline); 205 System.err.print("(members"); 206 for (Iterator i = fields.iterator(); i.hasNext(); ) { 207 FieldBuilder b = (FieldBuilder) i.next(); 208 between(indent + 2, inline); 209 b.display(indent + 2, inline); 210 } 211 for (Iterator i = methods.iterator(); i.hasNext(); ) { 212 MethodBuilder b = (MethodBuilder) i.next(); 213 between(indent + 2, inline); 214 b.display(indent + 2, inline); 215 } 216 System.err.print(")"); 217 between(indent, inline); 218 attributes.display(indent, inline); 219 between(indent, inline); 220 pool.display(indent, inline); 221 System.err.print(")"); 222 } 223 224 227 232 public void resolve() { 233 pool.resolve(); 234 int offset = 0; 235 int fileNumber = 0; 236 for (SourceFile t = sourceFiles; t != null; t = t.next) { 237 int i = t.i; 238 t.offset = offset; 239 t.fileNumber = fileNumber++; 240 offset = offset + i + 1000 - (i % 1000); 241 } 242 for(Iterator i = methods.iterator(); i.hasNext();) { 243 MethodBuilder m = (MethodBuilder)i.next(); 244 m.resolve(); 245 } 246 String simpleName = sourceFiles.getSimpleName(); 247 String s = simpleName; 248 for (SourceFile t = sourceFiles.next; t != null; t = t.next) { 249 s += ";" + t.getFullName() + '[' + (t.offset / 1000) + "k]"; 250 } 251 attributes.addSourceFileAttribute(s); 252 attributes.addSouceDebugExtensionAttribute(createSourceDebugExtensionData(simpleName)); 253 } 254 255 private String createSourceDebugExtensionData(String simpleName) { 256 StringBuffer s = new StringBuffer ("SMAP\n"); 257 s.append(simpleName + "\n"); 258 s.append("AspectJ\n"); 259 260 s.append("*S AspectJ\n"); 262 s.append("*F\n"); 263 for (SourceFile t = sourceFiles; t != null; t = t.next) { 264 if (t.getFileNumber() == 0) continue; 265 if (t.sourcePackage == null) { 266 s.append(t.getFileNumber() + " " + t.getSimpleName() + "\n"); 267 } else { 268 s.append("+ " + t.getFileNumber() + " " + t.getSimpleName() + "\n" 269 + t.getFullName() + "\n"); 270 } 271 } 272 s.append("*L\n"); 273 for (SourceFile t = sourceFiles; t != null; t = t.next) { 274 if (t.getFileNumber() == 0) continue; 275 s.append("1#" + t.getFileNumber() + "," + (t.i) + ":" 276 + (t.offset+1) + ",1\n"); 277 } 278 s.append("*E\n"); 280 return s.toString(); 281 } 282 283 static class SourceFile { 285 SourceFile next = null; 286 final String sourcePackage; 287 final String sourceFile; 288 int fileNumber = 0; 289 int i = 0; 290 int offset = 0; 291 String getSimpleName() { return sourceFile; } 292 String getFullName() { 293 if (sourcePackage == null) return sourceFile; 294 else return sourcePackage.replace('.', '/') + '/' + sourceFile; 295 } 296 SourceFile(SourceLocation loc) { 297 if (loc.hasSource()) { 298 this.sourcePackage = loc.getCompilationUnit().getPackageName(); 299 this.sourceFile = loc.getSourceFile().getName(); 300 } else { 301 this.sourcePackage = null; 302 this.sourceFile = "NoSourceFile"; 303 } 304 } 305 SourceFile(SourceLocation loc, int i) { 306 this(loc); this.i = i; 307 } 308 int getFileNumber() { return fileNumber + 1; } 309 int getOutputLine(int line) { return line + i; } 310 SourceFile get(SourceLocation loc) { 311 String currPackage = loc.getCompilationUnit().getPackageName(); 312 if (((sourcePackage == null) 313 ? currPackage == null 314 : sourcePackage.equals(currPackage)) 315 && sourceFile.equals(loc.getSourceFile().getName())) { 316 int line = loc.getBeginLine(); 317 if (line > i) i = line; 318 return this; 319 } else if (next == null) { 320 next = new SourceFile(loc, loc.getBeginLine()); 321 return next; 322 } else { 323 return next.get(loc); 324 } 325 } 326 } 327 328 SourceFile sourceFiles; 329 330 SourceFile getSourceFile(SourceLocation loc) { 331 if (! loc.hasSource()) return null; return sourceFiles.get(loc); 333 } 334 335 338 void readFrom(DataInputStream stream) throws IOException { 339 int magic = stream.readInt(); 340 minorVersion = (short)stream.readUnsignedShort(); 341 majorVersion = (short)stream.readUnsignedShort(); 342 pool.readFrom(stream); 343 accessFlags = stream.readUnsignedShort(); 344 thisClass = pool.get(stream.readUnsignedShort()); 345 superClass = pool.get(stream.readUnsignedShort()); 346 for (int i = stream.readUnsignedShort(); i > 0; i--) { 347 interfaces.add(pool.get(stream.readUnsignedShort())); 348 } 349 for (int i = stream.readUnsignedShort(); i > 0; i--) { 350 fields.add(getFieldBuilder().readFrom(stream)); 351 } 352 for (int i = stream.readUnsignedShort(); i > 0; i--) { 353 methods.add(getMethodBuilder().readFrom(stream)); 354 } 355 attributes.readFrom(stream); 356 } 357 358 public static void main(String [] args) throws Exception { 359 ClassfileBuilder cfb = new ClassfileBuilder(null); 360 cfb.readFrom(new DataInputStream (new java.io.FileInputStream (args[0]))); 361 cfb.print(); 362 } 363 } 364 | Popular Tags |