1 2 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 43 public class StructureModelManager { 44 45 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; 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 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 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 102 public HashMap getInlineAnnotations(String 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 hash = new Integer (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 configFile) { 164 if (world == null) return; 165 String 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 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 )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 packageName) { 218 List children = node.getChildren(); 219 int dotIndex = packageName.indexOf('.'); 220 if (dotIndex == -1) { 224 if (!node.getChildren().contains(packageName)) { 225 node.addChild(new ProgramElementNode(packageName, ProgramElementNode.Kind.PACKAGE, null)); 226 } 227 } else { 228 String pkgTop = packageName.substring(0, dotIndex); 229 String 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 nextElement = (String )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 308 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 323 public void writeStructureModel(String configFilePath) { 324 try { 325 String filePath = genExternFilePath(configFilePath); 326 ObjectOutputStream s = new ObjectOutputStream(new FileOutputStream(filePath)); 327 s.writeObject(model); 328 s.flush(); 329 } catch (Exception e) { 330 } 332 } 333 334 338 public void readStructureModel(String configFilePath) { 339 try { 340 if (configFilePath == null) { 341 model.setRoot(StructureModel.NO_STRUCTURE); 342 } else { 343 String filePath = genExternFilePath(configFilePath); 344 FileInputStream in = new FileInputStream(filePath); 345 ObjectInputStream s = new ObjectInputStream(in); 346 model = (StructureModel)s.readObject(); 347 } 348 } catch (Exception e) { 349 model.setRoot(StructureModel.NO_STRUCTURE); 351 } finally { 352 notifyListeners(); 353 } 354 } 355 356 private String genExternFilePath(String 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 getDisplayName() { 369 return "structure model update"; 370 } 371 372 public void transformWorld() { 373 structureManager.buildStructureModel((AspectJCompiler)super.getCompiler()); 374 } 375 } 376 377 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 } else if (astObject instanceof MethodDec 410 || astObject instanceof ConstructorDec) { 411 addCodeLevelChildren(astObject, correspondeces, children); 413 } else if (astObject instanceof AdviceDec) { 414 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 |