KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > base > bcg > ClassfileBuilder


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

24
25 package org.aspectj.compiler.base.bcg;
26
27 import org.aspectj.compiler.base.bcg.pool.*;
28
29 import java.lang.reflect.Modifier JavaDoc;
30
31 import java.util.ArrayList JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35
36 import java.io.IOException JavaDoc;
37 import java.io.DataOutputStream JavaDoc;
38 import java.io.DataInputStream JavaDoc;
39 import java.io.File JavaDoc;
40
41 import org.aspectj.compiler.base.ast.SourceLocation;
42 import org.aspectj.compiler.base.JavaCompiler;
43
44 // XXX annoying big modularity violation.
45
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 //XXX JBuilder's compiler doesn't really understand inner classes well enough
50
//XXX for this to work, so we use the semi-qualified name below
51
//XXX but look at ForStmt.java for some interesting caveats... ?????????????
52

53 //import org.aspectj.compiler.base.bcg.ConstantPool.Constant;
54

55 /** Lifecycle: creation, addition of everything, output to file,
56     processing of inner classes. It is an error for these steps to
57     occur out of order, but this is not currently checked. */

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     // ------------------------------
67
// state
68

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; // 0x0020; // ACC_SUPER
74
private Constant thisClass;
75     private Constant superClass;
76     private /* Constant */ List JavaDoc interfaces = new ArrayList JavaDoc();
77     private /* FieldBuilder */ List JavaDoc fields = new ArrayList JavaDoc();
78     private /* MethodBuilder */ List JavaDoc methods = new ArrayList JavaDoc();
79     private Attributes attributes = new Attributes(pool);
80
81     // used for delaying generation of inner types until we've closed our port.
82
private /* TypeDec */ List JavaDoc innerTypeDecs = new ArrayList JavaDoc();
83
84     // ------------------------------
85
// building methods
86

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 JavaDoc data) {
118         attributes.addSouceDebugExtensionAttribute(data);
119     }
120
121     // ------------------------------
122
// irritating inner class stuff
123

124     private /* NameType */ HashSet JavaDoc innerClasses = new HashSet JavaDoc();
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 JavaDoc outputDir) throws IOException JavaDoc {
138         for (Iterator JavaDoc i = innerTypeDecs.iterator(); i.hasNext(); ) {
139             TypeDec typeDec = (TypeDec) i.next();
140             typeDec.generateBytecode(outputDir);
141         }
142     }
143
144     // ------------------------------
145
// output methods
146

147     public void writeTo(DataOutputStream JavaDoc stream) throws IOException JavaDoc {
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 JavaDoc 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 JavaDoc 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 JavaDoc 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     // ------------------------------
177
// debugging printing
178

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 JavaDoc 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 JavaDoc 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     // ------------------------------
225
// line number table resolution
226

227     // we need to resolve stuff for the line number table and local
228
// variable table. Before resolution, the LineNumberTable holds
229
// maximum lines. Afterward, it holds offsets. The Local
230
// Variable table attribute is simply created at this time.
231

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 JavaDoc i = methods.iterator(); i.hasNext();) {
243             MethodBuilder m = (MethodBuilder)i.next();
244             m.resolve();
245         }
246         String JavaDoc simpleName = sourceFiles.getSimpleName();
247         String JavaDoc 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 JavaDoc createSourceDebugExtensionData(String JavaDoc simpleName) {
256         StringBuffer JavaDoc s = new StringBuffer JavaDoc("SMAP\n");
257         s.append(simpleName + "\n");
258         s.append("AspectJ\n");
259
260         //if (sourceFiles.next != null && sourceFiles.getFileNumber() != 0) {
261
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         //}
279
s.append("*E\n");
280         return s.toString();
281     }
282
283     // this class is shared by CodeBuilder
284
static class SourceFile {
285         SourceFile next = null;
286         final String JavaDoc sourcePackage;
287         final String JavaDoc sourceFile;
288         int fileNumber = 0;
289         int i = 0;
290         int offset = 0;
291         String JavaDoc getSimpleName() { return sourceFile; }
292         String JavaDoc 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 JavaDoc 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; // ??? is this right?
332
return sourceFiles.get(loc);
333     }
334
335     // ------------------------------
336
// disassembly methods
337

338     void readFrom(DataInputStream JavaDoc stream) throws IOException JavaDoc {
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 JavaDoc[] args) throws Exception JavaDoc {
359         ClassfileBuilder cfb = new ClassfileBuilder(null);
360         cfb.readFrom(new DataInputStream JavaDoc(new java.io.FileInputStream JavaDoc(args[0])));
361         cfb.print();
362     }
363 }
364
Popular Tags