KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > asm > StructureModelManager


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

25
26 package org.aspectj.asm;
27
28 import java.util.*;
29 import java.io.*;
30 import org.aspectj.compiler.base.*;
31 import org.aspectj.compiler.base.ast.*;
32 import org.aspectj.compiler.base.ast.Type;
33 import org.aspectj.compiler.base.cst.*;
34 import org.aspectj.compiler.base.parser.*;
35 import org.aspectj.compiler.crosscuts.*;
36 import org.aspectj.compiler.crosscuts.ast.*;
37 import org.aspectj.asm.internal.*;
38 import org.aspectj.asm.associations.*;
39
40 /**
41  * @author Mik Kersten
42  */

43 public class StructureModelManager {
44     
45     /**
46      * Singleton instance.
47      */

48     public static StructureModelManager INSTANCE = new StructureModelManager();
49     private boolean shouldSaveModel = true;
50     protected StructureModel model = new StructureModel();
51     private List structureListeners = new ArrayList();
52     private List associations = new ArrayList();
53     
54     public static Correspondences correspondences = null; // HACK: remove this
55

56     protected StructureModelManager() {
57         associations.add(new Advice());
58         associations.add(new Introduction());
59         associations.add(new Inheritance());
60         associations.add(new Reference());
61     }
62
63     public StructureModel getStructureModel() {
64         return model;
65     }
66
67     public StructureNode buildStructureModel(AspectJCompiler compiler) {
68         try {
69             StructureNodeFactory.clear();
70             StructureModelManager.correspondences = compiler.getCorrespondences();
71             World world = compiler.getWorld();
72             String JavaDoc configFile = compiler.getBuildConfigFile();
73     
74             buildProgramStructurePass(world, configFile);
75             buildRelationsPass(model.getRoot());
76             notifyListeners();
77     
78             if (configFile != null && shouldSaveModel) {
79                 writeStructureModel(configFile);
80             }
81             model.setConfigFile(configFile);
82             
83             clearAstObjectReferences(model);
84         } catch (Throwable JavaDoc t) {
85             System.err.println("AspectJ ASM Error: could not buld structure model.");
86             t.printStackTrace();
87         } finally {
88             return model.getRoot();
89         }
90     }
91
92     public void fireModelUpdated() {
93         notifyListeners();
94         if (model.getConfigFile() != null) {
95             writeStructureModel(model.getConfigFile());
96         }
97     }
98
99     /**
100      * Constructs map each time it's called.
101      */

102     public HashMap getInlineAnnotations(String JavaDoc sourceFile, boolean showSubMember, boolean showMemberAndType) {
103         if (!model.isValid()) return null;
104         
105         HashMap annotations = new HashMap();
106         StructureNode node = model.findRootNodeForSourceFile(sourceFile);
107         if (node == StructureModel.NO_STRUCTURE) {
108             return null;
109         } else {
110             ProgramElementNode fileNode = (ProgramElementNode)node;
111             ArrayList peNodes = new ArrayList();
112             getAllStructureChildren(fileNode, peNodes, showSubMember, showMemberAndType);
113             for (Iterator it = peNodes.iterator(); it.hasNext(); ) {
114                 ProgramElementNode peNode = (ProgramElementNode)it.next();
115                 List entries = new ArrayList();
116                 entries.add(peNode);
117                 Integer JavaDoc hash = new Integer JavaDoc(peNode.getSourceLocation().getLineNumber());
118                 List existingEntry = (List)annotations.get(hash);
119                 if (existingEntry != null) {
120                     entries.addAll(existingEntry);
121                 }
122                 annotations.put(hash, entries);
123             }
124             return annotations;
125         }
126     }
127
128     private void getAllStructureChildren(ProgramElementNode node, List result, boolean showSubMember, boolean showMemberAndType) {
129         List children = node.getChildren();
130         for (Iterator it = children.iterator(); it.hasNext(); ) {
131             StructureNode next = (StructureNode)it.next();
132             if (next instanceof ProgramElementNode) {
133                 ProgramElementNode pNode = (ProgramElementNode)next;
134                 if (pNode != null
135                     && ((pNode.isCode() && showSubMember) || (!pNode.isCode() && showMemberAndType))
136                     && pNode.getRelations() != null
137                     && pNode.getRelations().size() > 0) {
138                     result.add(next);
139                 }
140                 getAllStructureChildren((ProgramElementNode)next, result, showSubMember, showMemberAndType);
141             }
142         }
143     }
144
145     public void addListener(StructureModelListener listener) {
146         structureListeners.add(listener);
147     }
148
149     public void removeStructureListener(StructureModelListener listener) {
150         structureListeners.remove(listener);
151     }
152
153     private void notifyListeners() {
154         for (Iterator it = structureListeners.iterator(); it.hasNext(); ) {
155             ((StructureModelListener)it.next()).modelUpdated(model);
156         }
157     }
158
159     public List getAssociations() {
160         return associations;
161     }
162
163     private void buildProgramStructurePass(World world, String JavaDoc configFile) {
164         if (world == null) return;
165         String JavaDoc rootName = "<model root>";
166         if (configFile != null) {
167             rootName = new File(configFile).getName();
168         }
169         List files = new ArrayList();
170         HashMap modelFileMap = new HashMap();
171         for (Iterator it = world.getCompilationUnits().iterator(); it.hasNext(); ) {
172             CompilationUnit compilationUnit = (CompilationUnit)it.next();
173             ProgramElementNode fileNode = makeProgramElementNode(compilationUnit, correspondences);
174             files.add(fileNode);
175             modelFileMap.put(compilationUnit.getSourceFileName().replace('\\', '/'), fileNode);
176         }
177         model.setFileMap(modelFileMap);
178         model.setRoot(mapFilesIntoPackages(rootName));
179     }
180
181     private void clearAstObjectReferences(StructureModel model) {
182         ModelWalker walker = new ModelWalker() {
183             public void preProcess(StructureNode node) {
184                 if (node.getChildren() == null) return;
185                 for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
186                     StructureNode childNode = (StructureNode)it.next();
187                     if (childNode instanceof ProgramElementNode) {
188                         ((ProgramElementNode)childNode).clearAstObject();
189                     }
190                 }
191             }
192         };
193         model.getRoot().walk(walker);
194     }
195
196
197     private StructureNode mapFilesIntoPackages(String JavaDoc rootName) {
198         StructureNode root = new ProgramElementNode(rootName, ProgramElementNode.Kind.PROJECT, null);
199         ArrayList packages = new ArrayList();
200         Set fileSet = model.getFileMap().entrySet();
201         TreeSet packageSet = new TreeSet();
202         for (Iterator it = fileSet.iterator(); it.hasNext(); ) {
203             ProgramElementNode peNode = (ProgramElementNode)((Map.Entry)it.next()).getValue();
204             if (peNode.getPackageName() != null) {
205                 packageSet.add(peNode.getPackageName());
206             }
207         }
208         for (Iterator it2 = packageSet.iterator(); it2.hasNext(); ) {
209             addPackageToRoot(root, (String JavaDoc)it2.next());
210         }
211         for (Iterator it3 = fileSet.iterator(); it3.hasNext(); ) {
212             addFileToPackage(root, (ProgramElementNode)((Map.Entry)it3.next()).getValue());
213         }
214         return root;
215     }
216
217     private void addPackageToRoot(StructureNode node, String JavaDoc packageName) {
218         List children = node.getChildren();
219         int dotIndex = packageName.indexOf('.');
220 // if (packageName == "") {
221
// node.addChild();
222
// } else
223
if (dotIndex == -1) {
224             if (!node.getChildren().contains(packageName)) {
225                 node.addChild(new ProgramElementNode(packageName, ProgramElementNode.Kind.PACKAGE, null));
226             }
227         } else {
228             String JavaDoc pkgTop = packageName.substring(0, dotIndex);
229             String JavaDoc pkgRest = packageName.substring(dotIndex+1, packageName.length());
230             boolean added =false;
231             for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
232                 StructureNode child = (StructureNode)it.next();
233                 if (child.getName().equals(pkgTop)) {
234                     addPackageToRoot(child, pkgRest);
235                     added = true;
236                 }
237             }
238             if (!added) {
239                 StructureNode newChild = new ProgramElementNode(pkgTop, ProgramElementNode.Kind.PACKAGE, null);
240                 node.addChild(newChild);
241                 addPackageToRoot(newChild, pkgRest);
242             }
243         }
244     }
245
246     private void addFileToPackage(StructureNode root, ProgramElementNode fileNode) {
247         if (fileNode.getPackageName() == null) {
248             root.addChild(fileNode);
249         } else {
250             addFileToPackageHelper(root, fileNode, new StringTokenizer(fileNode.getPackageName(), "."));
251         }
252     }
253
254     private void addFileToPackageHelper(StructureNode root, ProgramElementNode fileNode, StringTokenizer pkgPath) {
255         if (pkgPath == null) {
256             root.addChild(fileNode);
257         } else {
258             while (pkgPath.hasMoreElements()) {
259                 String JavaDoc nextElement = (String JavaDoc)pkgPath.nextElement();
260                 for (Iterator it = root.getChildren().iterator(); it.hasNext(); ) {
261                     StructureNode pkgNode = (StructureNode)it.next();
262                     if (pkgNode.getName().equals(nextElement)) {
263                         if (!pkgPath.hasMoreElements()) {
264                             pkgNode.addChild(fileNode);
265                         } else {
266                             addFileToPackageHelper(pkgNode, fileNode, pkgPath);
267                         }
268                     }
269                 }
270             }
271         }
272     }
273
274     private void buildRelationsPass(StructureNode node) {
275         if (node instanceof ProgramElementNode) {
276             ProgramElementNode peNode = (ProgramElementNode)node;
277             List relations = new ArrayList();
278             for (Iterator it = associations.iterator(); it.hasNext(); ) {
279                 Association association = (Association)it.next();
280                 if (peNode.getAstObject() != null) {
281                     relations.addAll(association.getRelationNodes(peNode.getAstObject()));
282                 }
283             }
284             peNode.setRelations(relations);
285         }
286         List children = node.getChildren();
287         if (children != null) {
288             for (Iterator it = children.iterator(); it.hasNext(); ) {
289                 buildRelationsPass((StructureNode)it.next());
290             }
291         }
292     }
293
294 // private StructureNode findFileNode(String filePath, StructureNode node) {
295
// if (node == null) return node;
296
// for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
297
// StructureNode child = (StructureNode)it.next();
298
// if (child instanceof ProgramElementNode &&
299
// ((ProgramElementNode)child).getSourceLocation().getSourceFilePath().replace('\\', '/').equals(filePath)) {
300
// return child;
301
// } else {
302
// findFileNode(filePath, child);
303
// }
304
// }
305
// return StructureModel.NO_STRUCTURE;
306
// }
307

308     /**
309      * TODO: avoid the childrenNodes list traversal?
310      */

311     private ProgramElementNode makeProgramElementNode(ASTObject astObject, Correspondences correspondences) {
312         List children = new ArrayList();
313         List childNodes = CompositionHierarchy.makeChildren(astObject, correspondences);
314         for (Iterator it = childNodes.iterator(); it.hasNext(); ) {
315             children.add(makeProgramElementNode((ASTObject)it.next(), correspondences));
316         }
317         return StructureNodeFactory.makeNode(astObject, null, children);
318     }
319
320     /**
321      * Fails silently.
322      */

323     public void writeStructureModel(String JavaDoc configFilePath) {
324         try {
325             String JavaDoc filePath = genExternFilePath(configFilePath);
326             ObjectOutputStream s = new ObjectOutputStream(new FileOutputStream(filePath));
327             s.writeObject(model);
328             s.flush();
329         } catch (Exception JavaDoc e) {
330             // ignore
331
}
332     }
333   
334     /**
335      * @todo add proper handling of bad paths/suffixes/etc
336      * @param configFilePath path to an ".lst" file
337      */

338     public void readStructureModel(String JavaDoc configFilePath) {
339         try {
340             if (configFilePath == null) {
341                 model.setRoot(StructureModel.NO_STRUCTURE);
342             } else {
343                 String JavaDoc filePath = genExternFilePath(configFilePath);
344                 FileInputStream in = new FileInputStream(filePath);
345                 ObjectInputStream s = new ObjectInputStream(in);
346                 model = (StructureModel)s.readObject();
347             }
348         } catch (Exception JavaDoc e) {
349             //System.err.println("AJDE Message: could not read structure model: " + e);
350
model.setRoot(StructureModel.NO_STRUCTURE);
351         } finally {
352             notifyListeners();
353         }
354     }
355
356     private String JavaDoc genExternFilePath(String JavaDoc configFilePath) {
357         return configFilePath.substring(0, configFilePath.lastIndexOf(".lst")) + ".ajsym";
358     }
359
360     public static class UpdateStructurePass extends AbstractCompilerPass {
361         private StructureModelManager structureManager = null;
362
363         public UpdateStructurePass(JavaCompiler jc, StructureModelManager structureManager) {
364             super(jc);
365             this.structureManager = structureManager;
366         }
367
368         public String JavaDoc getDisplayName() {
369             return "structure model update";
370         }
371
372         public void transformWorld() {
373             structureManager.buildStructureModel((AspectJCompiler)super.getCompiler());
374         }
375     }
376
377     /**
378      * Will not add InitializerDec(s) because these are assumed to be equivalent to
379      * TypeDecs in the structure.
380      */

381     private static class CompositionHierarchy {
382        static List makeChildren(ASTObject astObject, Correspondences correspondeces) {
383             List children = new ArrayList();
384             
385             if (astObject instanceof CompilationUnit) {
386                 List definedTypes = ((CompilationUnit)astObject).getDefinedTypes();
387                 for (Iterator it = definedTypes.iterator(); it.hasNext(); ) {
388                     TypeDec typeDec = (TypeDec)it.next();
389                     children.add(typeDec);
390                 }
391             } else if (astObject instanceof TypeDec) {
392                 addCodeLevelChildren(astObject, correspondeces, children);
393
394                 TypeDec typeDec = (TypeDec)astObject;
395                 List decs = typeDec.getBody().getList();
396                 for (Iterator it = decs.iterator(); it.hasNext(); ) {
397                     Dec bodyDec = (Dec)it.next();
398                     if (bodyDec != null && !(bodyDec instanceof InitializerDec)) {
399                         if (!bodyDec.isSynthetic()) {
400                             if (bodyDec.getBeginLine() != bodyDec.getDeclaringType().getCorrespondingDec().getBeginLine()) {
401                                 children.add(bodyDec);
402                             }
403                         }
404                     }
405                 }
406                 
407             } else if (astObject instanceof FieldDec) {
408                 // initializer children get put on type decs
409
} else if (astObject instanceof MethodDec
410                 || astObject instanceof ConstructorDec) {
411                 // HACK: this should not use the "affects" correspondeces db
412
addCodeLevelChildren(astObject, correspondeces, children);
413             } else if (astObject instanceof AdviceDec) {
414                 // HACK: this should not use the "affects" correspondeces db
415
Set affectsSet = correspondeces.getAffects(astObject);
416                 if (affectsSet != null && affectsSet.size() > 0) {
417                     for (Iterator it = affectsSet.iterator(); it.hasNext(); ) {
418                         ASTObject stmtDec = (ASTObject)it.next();
419                         if ( (astObject.getSourceFileName().equals(stmtDec.getSourceFileName()))
420                             && (astObject.getBeginLine() < stmtDec.getBeginLine())
421                             && (astObject.getEndLine() > stmtDec.getEndLine())) {
422                             children.add(stmtDec);
423                         }
424                     }
425                 }
426             }
427             
428            return children;
429         }
430         private static void addCodeLevelChildren(
431             ASTObject astObject,
432             Correspondences correspondeces,
433             List children) {
434             Set affectsSet = correspondeces.getAffects(astObject);
435             if (affectsSet != null && affectsSet.size() > 0) {
436                 for (Iterator it = affectsSet.iterator(); it.hasNext(); ) {
437                     ASTObject stmtDec = (ASTObject)it.next();
438                     children.add(stmtDec);
439                 }
440             }
441         }
442     }
443     
444     public void setShouldSaveModel(boolean shouldSaveModel) {
445         this.shouldSaveModel = shouldSaveModel;
446     }
447 }
448
449
Popular Tags