You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AsmManager.java 44KB

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
15 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
15 years ago
21 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
15 years ago
14 years ago
13 years ago
13 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
13 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
14 years ago
14 years ago
14 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. /* *******************************************************************
  2. * Copyright (c) 2003 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Mik Kersten initial implementation
  11. * Andy Clement incremental support and switch on/off state
  12. * ******************************************************************/
  13. package org.aspectj.asm;
  14. import java.io.BufferedWriter;
  15. import java.io.EOFException;
  16. import java.io.File;
  17. import java.io.FileInputStream;
  18. import java.io.FileNotFoundException;
  19. import java.io.FileOutputStream;
  20. import java.io.FileWriter;
  21. import java.io.IOException;
  22. import java.io.ObjectInputStream;
  23. import java.io.ObjectOutputStream;
  24. import java.io.Writer;
  25. import java.util.ArrayList;
  26. import java.util.Collection;
  27. import java.util.Enumeration;
  28. import java.util.HashMap;
  29. import java.util.HashSet;
  30. import java.util.Hashtable;
  31. import java.util.Iterator;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Properties;
  35. import java.util.Set;
  36. import org.aspectj.asm.internal.AspectJElementHierarchy;
  37. import org.aspectj.asm.internal.HandleProviderDelimiter;
  38. import org.aspectj.asm.internal.JDTLikeHandleProvider;
  39. import org.aspectj.asm.internal.RelationshipMap;
  40. import org.aspectj.bridge.ISourceLocation;
  41. import org.aspectj.util.IStructureModel;
  42. /**
  43. * The Abstract Structure Model (ASM) represents the containment hierarchy and crosscutting structure map for AspectJ programs. It
  44. * is used by IDE views such as the document outline, and by other tools such as ajdoc to show both AspectJ declarations and
  45. * crosscutting links, such as which advice affects which join point shadows.
  46. *
  47. * @author Mik Kersten
  48. * @author Andy Clement
  49. */
  50. public class AsmManager implements IStructureModel {
  51. // For testing ONLY
  52. public static boolean recordingLastActiveStructureModel = true;
  53. public static AsmManager lastActiveStructureModel;
  54. public static boolean forceSingletonBehaviour = false;
  55. // SECRETAPI asc pull the secret options together into a system API you lazy fool
  56. public static boolean attemptIncrementalModelRepairs = false;
  57. // Dumping the model is expensive
  58. public static boolean dumpModelPostBuild = false;
  59. // For offline debugging, you can now ask for the AsmManager to
  60. // dump the model - see the method setReporting()
  61. private static boolean dumpModel = false;
  62. private static boolean dumpRelationships = false;
  63. private static boolean dumpDeltaProcessing = false;
  64. private static IModelFilter modelFilter = null;
  65. private static String dumpFilename = "";
  66. private static boolean reporting = false;
  67. private static boolean completingTypeBindings = false;
  68. private final List<IHierarchyListener> structureListeners = new ArrayList<IHierarchyListener>();
  69. // The model is 'manipulated' by the AjBuildManager.setupModel() code which
  70. // trashes all the
  71. // fields when setting up a new model for a batch build.
  72. // Due to the requirements of incremental compilation we need to tie some of
  73. // the info
  74. // below to the AjState for a compilation and recover it if switching
  75. // between projects.
  76. protected IHierarchy hierarchy;
  77. /*
  78. * Map from String > String - it maps absolute paths for inpath dirs/jars to workspace relative paths suitable for handle
  79. * inclusion
  80. */
  81. protected Map<File, String> inpathMap;
  82. private IRelationshipMap mapper;
  83. private IElementHandleProvider handleProvider;
  84. private final CanonicalFilePathMap canonicalFilePathMap = new CanonicalFilePathMap();
  85. // Record the Set<File> for which the model has been modified during the
  86. // last incremental build
  87. private final Set<File> lastBuildChanges = new HashSet<File>();
  88. // Record the Set<File> of aspects that wove the files listed in lastBuildChanges
  89. final Set<File> aspectsWeavingInLastBuild = new HashSet<File>();
  90. // static {
  91. // setReporting("c:/model.nfo",true,true,true,true);
  92. // }
  93. private AsmManager() {
  94. }
  95. public static AsmManager createNewStructureModel(Map<File, String> inpathMap) {
  96. if (forceSingletonBehaviour && lastActiveStructureModel != null) {
  97. return lastActiveStructureModel;
  98. }
  99. AsmManager asm = new AsmManager();
  100. asm.inpathMap = inpathMap;
  101. asm.hierarchy = new AspectJElementHierarchy(asm);
  102. asm.mapper = new RelationshipMap();
  103. asm.handleProvider = new JDTLikeHandleProvider(asm);
  104. // call initialize on the handleProvider when we create a new ASM
  105. // to give handleProviders the chance to reset any state
  106. asm.handleProvider.initialize();
  107. asm.resetDeltaProcessing();
  108. setLastActiveStructureModel(asm);
  109. return asm;
  110. }
  111. public IHierarchy getHierarchy() {
  112. return hierarchy;
  113. }
  114. public IRelationshipMap getRelationshipMap() {
  115. return mapper;
  116. }
  117. public void fireModelUpdated() {
  118. notifyListeners();
  119. if (dumpModelPostBuild && hierarchy.getConfigFile() != null) {
  120. writeStructureModel(hierarchy.getConfigFile());
  121. }
  122. }
  123. /**
  124. * Constructs map each time it's called.
  125. */
  126. public HashMap<Integer, List<IProgramElement>> getInlineAnnotations(String sourceFile, boolean showSubMember,
  127. boolean showMemberAndType) {
  128. if (!hierarchy.isValid()) {
  129. return null;
  130. }
  131. HashMap<Integer, List<IProgramElement>> annotations = new HashMap<Integer, List<IProgramElement>>();
  132. IProgramElement node = hierarchy.findElementForSourceFile(sourceFile);
  133. if (node == IHierarchy.NO_STRUCTURE) {
  134. return null;
  135. } else {
  136. IProgramElement fileNode = node;
  137. ArrayList<IProgramElement> peNodes = new ArrayList<IProgramElement>();
  138. getAllStructureChildren(fileNode, peNodes, showSubMember, showMemberAndType);
  139. for (Iterator<IProgramElement> it = peNodes.iterator(); it.hasNext();) {
  140. IProgramElement peNode = it.next();
  141. List<IProgramElement> entries = new ArrayList<IProgramElement>();
  142. entries.add(peNode);
  143. ISourceLocation sourceLoc = peNode.getSourceLocation();
  144. if (null != sourceLoc) {
  145. Integer hash = new Integer(sourceLoc.getLine());
  146. List<IProgramElement> existingEntry = annotations.get(hash);
  147. if (existingEntry != null) {
  148. entries.addAll(existingEntry);
  149. }
  150. annotations.put(hash, entries);
  151. }
  152. }
  153. return annotations;
  154. }
  155. }
  156. private void getAllStructureChildren(IProgramElement node, List<IProgramElement> result, boolean showSubMember,
  157. boolean showMemberAndType) {
  158. List<IProgramElement> children = node.getChildren();
  159. if (node.getChildren() == null) {
  160. return;
  161. }
  162. for (IProgramElement next : children) {
  163. List<IRelationship> rels = mapper.get(next);
  164. if (next != null
  165. && ((next.getKind() == IProgramElement.Kind.CODE && showSubMember) || (next.getKind() != IProgramElement.Kind.CODE && showMemberAndType))
  166. && rels != null && rels.size() > 0) {
  167. result.add(next);
  168. }
  169. getAllStructureChildren(next, result, showSubMember, showMemberAndType);
  170. }
  171. }
  172. public void addListener(IHierarchyListener listener) {
  173. structureListeners.add(listener);
  174. }
  175. public void removeStructureListener(IHierarchyListener listener) {
  176. structureListeners.remove(listener);
  177. }
  178. // this shouldn't be needed - but none of the people that add listeners
  179. // in the test suite ever remove them. AMC added this to be called in
  180. // setup() so that the test cases would cease leaking listeners and go
  181. // back to executing at a reasonable speed.
  182. public void removeAllListeners() {
  183. structureListeners.clear();
  184. }
  185. private void notifyListeners() {
  186. for (IHierarchyListener listener : structureListeners) {
  187. listener.elementsUpdated(hierarchy);
  188. }
  189. }
  190. public IElementHandleProvider getHandleProvider() {
  191. return handleProvider;
  192. }
  193. public void setHandleProvider(IElementHandleProvider handleProvider) {
  194. this.handleProvider = handleProvider;
  195. }
  196. public void writeStructureModel(String configFilePath) {
  197. try {
  198. String filePath = genExternFilePath(configFilePath);
  199. FileOutputStream fos = new FileOutputStream(filePath);
  200. ObjectOutputStream s = new ObjectOutputStream(fos);
  201. s.writeObject(hierarchy); // Store the program element tree
  202. s.writeObject(mapper); // Store the relationships
  203. s.flush();
  204. fos.flush();
  205. fos.close();
  206. s.close();
  207. } catch (IOException e) {
  208. // System.err.println("AsmManager: Unable to write structure model: "
  209. // +configFilePath+" because of:");
  210. // e.printStackTrace();
  211. }
  212. }
  213. /**
  214. * @param configFilePath path to an ".lst" file
  215. */
  216. public void readStructureModel(String configFilePath) {
  217. boolean hierarchyReadOK = false;
  218. try {
  219. if (configFilePath == null) {
  220. hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
  221. } else {
  222. String filePath = genExternFilePath(configFilePath);
  223. FileInputStream in = new FileInputStream(filePath);
  224. ObjectInputStream s = new ObjectInputStream(in);
  225. hierarchy = (AspectJElementHierarchy) s.readObject();
  226. ((AspectJElementHierarchy) hierarchy).setAsmManager(this);
  227. hierarchyReadOK = true;
  228. mapper = (RelationshipMap) s.readObject();
  229. }
  230. } catch (FileNotFoundException fnfe) {
  231. // That is OK
  232. hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
  233. } catch (EOFException eofe) {
  234. // Might be an old format sym file that is missing its relationships
  235. if (!hierarchyReadOK) {
  236. System.err.println("AsmManager: Unable to read structure model: " + configFilePath + " because of:");
  237. eofe.printStackTrace();
  238. hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
  239. }
  240. } catch (Exception e) {
  241. // System.err.println("AsmManager: Unable to read structure model: "+
  242. // configFilePath+" because of:");
  243. // e.printStackTrace();
  244. hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
  245. } finally {
  246. notifyListeners();
  247. }
  248. }
  249. private String genExternFilePath(String configFilePath) {
  250. // sometimes don't have ".lst"
  251. if (configFilePath.lastIndexOf(".lst") != -1) {
  252. configFilePath = configFilePath.substring(0, configFilePath.lastIndexOf(".lst"));
  253. }
  254. return configFilePath + ".ajsym";
  255. }
  256. public String getCanonicalFilePath(File f) {
  257. return canonicalFilePathMap.get(f);
  258. }
  259. public CanonicalFilePathMap getCanonicalFilePathMap() {
  260. return canonicalFilePathMap;
  261. }
  262. private static class CanonicalFilePathMap {
  263. private static final int MAX_SIZE = 4000;
  264. private final Map<String, String> pathMap = new HashMap<String, String>(20);
  265. // // guards to ensure correctness and liveness
  266. // private boolean cacheInUse = false;
  267. // private boolean stopRequested = false;
  268. //
  269. // private synchronized boolean isCacheInUse() {
  270. // return cacheInUse;
  271. // }
  272. //
  273. // private synchronized void setCacheInUse(boolean val) {
  274. // cacheInUse = val;
  275. // if (val) {
  276. // notifyAll();
  277. // }
  278. // }
  279. //
  280. // private synchronized boolean isStopRequested() {
  281. // return stopRequested;
  282. // }
  283. //
  284. // private synchronized void requestStop() {
  285. // stopRequested = true;
  286. // }
  287. //
  288. // /**
  289. // * Begin prepopulating the map by adding an entry from
  290. // * file.getPath -> file.getCanonicalPath for each file in
  291. // * the list. Do this on a background thread.
  292. // * @param files
  293. // */
  294. // public void prepopulate(final List files) {
  295. // stopRequested = false;
  296. // setCacheInUse(false);
  297. // if (pathMap.size() > MAX_SIZE) {
  298. // pathMap.clear();
  299. // }
  300. // new Thread() {
  301. // public void run() {
  302. // System.out.println("Starting cache population: " +
  303. // System.currentTimeMillis());
  304. // Iterator it = files.iterator();
  305. // while (!isStopRequested() && it.hasNext()) {
  306. // File f = (File)it.next();
  307. // if (pathMap.get(f.getPath()) == null) {
  308. // // may reuse cache across compiles from ides...
  309. // try {
  310. // pathMap.put(f.getPath(),f.getCanonicalPath());
  311. // } catch (IOException ex) {
  312. // pathMap.put(f.getPath(),f.getPath());
  313. // }
  314. // }
  315. // }
  316. // System.out.println("Cached " + files.size());
  317. // setCacheInUse(true);
  318. // System.out.println("Cache populated: " + System.currentTimeMillis());
  319. // }
  320. // }.start();
  321. // }
  322. //
  323. // /**
  324. // * Stop pre-populating the cache - our customers are ready to use it.
  325. // * If there are any cache misses from this point on, we'll populate
  326. // the
  327. // * cache as we go.
  328. // * The handover is done this way to ensure that only one thread is
  329. // ever
  330. // * accessing the cache, and that we minimize synchronization.
  331. // */
  332. // public synchronized void handover() {
  333. // if (!isCacheInUse()) {
  334. // requestStop();
  335. // try {
  336. // while (!isCacheInUse()) wait();
  337. // } catch (InterruptedException intEx) { } // just continue
  338. // }
  339. // }
  340. public String get(File f) {
  341. // if (!cacheInUse) { // unsynchronized test - should never be
  342. // parallel
  343. // // threads at this point
  344. // throw new IllegalStateException(
  345. // "Must take ownership of cache before using by calling " +
  346. // "handover()");
  347. // }
  348. String ret = pathMap.get(f.getPath());
  349. if (ret == null) {
  350. try {
  351. ret = f.getCanonicalPath();
  352. } catch (IOException ioEx) {
  353. ret = f.getPath();
  354. }
  355. pathMap.put(f.getPath(), ret);
  356. if (pathMap.size() > MAX_SIZE) {
  357. pathMap.clear();
  358. }
  359. }
  360. return ret;
  361. }
  362. }
  363. // SECRETAPI
  364. public static void setReporting(String filename, boolean dModel, boolean dRels, boolean dDeltaProcessing, boolean deletefile) {
  365. reporting = true;
  366. dumpModel = dModel;
  367. dumpRelationships = dRels;
  368. dumpDeltaProcessing = dDeltaProcessing;
  369. if (deletefile) {
  370. new File(filename).delete();
  371. }
  372. dumpFilename = filename;
  373. }
  374. public static void setReporting(String filename, boolean dModel, boolean dRels, boolean dDeltaProcessing, boolean deletefile,
  375. IModelFilter aFilter) {
  376. setReporting(filename, dModel, dRels, dDeltaProcessing, deletefile);
  377. modelFilter = aFilter;
  378. }
  379. public static boolean isReporting() {
  380. return reporting;
  381. }
  382. public static void setDontReport() {
  383. reporting = false;
  384. dumpDeltaProcessing = false;
  385. dumpModel = false;
  386. dumpRelationships = false;
  387. }
  388. // NB. If the format of this report changes then the model tests
  389. // (@see org.aspectj.systemtest.model.ModelTestCase) will fail in
  390. // their comparison. The tests are assuming that both the model
  391. // and relationship map are reported and as a consequence single
  392. // testcases test that both the model and relationship map are correct.
  393. public void reportModelInfo(String reasonForReport) {
  394. if (!dumpModel && !dumpRelationships) {
  395. return;
  396. }
  397. try {
  398. FileWriter fw = new FileWriter(dumpFilename, true);
  399. BufferedWriter bw = new BufferedWriter(fw);
  400. if (dumpModel) {
  401. bw.write("=== MODEL STATUS REPORT ========= " + reasonForReport + "\n");
  402. dumptree(bw, hierarchy.getRoot(), 0);
  403. bw.write("=== END OF MODEL REPORT =========\n");
  404. }
  405. if (dumpRelationships) {
  406. bw.write("=== RELATIONSHIPS REPORT ========= " + reasonForReport + "\n");
  407. dumprels(bw);
  408. bw.write("=== END OF RELATIONSHIPS REPORT ==\n");
  409. }
  410. Properties p = summarizeModel().getProperties();
  411. Enumeration<Object> pkeyenum = p.keys();
  412. bw.write("=== Properties of the model and relationships map =====\n");
  413. while (pkeyenum.hasMoreElements()) {
  414. String pkey = (String) pkeyenum.nextElement();
  415. bw.write(pkey + "=" + p.getProperty(pkey) + "\n");
  416. }
  417. bw.flush();
  418. fw.close();
  419. } catch (IOException e) {
  420. System.err.println("InternalError: Unable to report model information:");
  421. e.printStackTrace();
  422. }
  423. }
  424. public static void dumptree(Writer w, IProgramElement node, int indent) throws IOException {
  425. for (int i = 0; i < indent; i++) {
  426. w.write(" ");
  427. }
  428. String loc = "";
  429. if (node != null) {
  430. if (node.getSourceLocation() != null) {
  431. loc = node.getSourceLocation().toString();
  432. if (modelFilter != null) {
  433. loc = modelFilter.processFilelocation(loc);
  434. }
  435. }
  436. }
  437. w.write(node + " [" + (node == null ? "null" : node.getKind().toString()) + "] " + loc + "\n");
  438. if (node != null) {
  439. for (IProgramElement child : node.getChildren()) {
  440. dumptree(w, child, indent + 2);
  441. }
  442. }
  443. }
  444. public static void dumptree(IProgramElement node, int indent) throws IOException {
  445. for (int i = 0; i < indent; i++) {
  446. System.out.print(" ");
  447. }
  448. String loc = "";
  449. if (node != null) {
  450. if (node.getSourceLocation() != null) {
  451. loc = node.getSourceLocation().toString();
  452. }
  453. }
  454. System.out.println(node + " [" + (node == null ? "null" : node.getKind().toString()) + "] " + loc);
  455. if (node != null) {
  456. for (IProgramElement child : node.getChildren()) {
  457. dumptree(child, indent + 2);
  458. }
  459. }
  460. }
  461. public void dumprels(Writer w) throws IOException {
  462. int ctr = 1;
  463. Set<String> entries = mapper.getEntries();
  464. for (String hid : entries) {
  465. List<IRelationship> rels = mapper.get(hid);
  466. for (IRelationship ir : rels) {
  467. List<String> targets = ir.getTargets();
  468. for (String thid : targets) {
  469. StringBuffer sb = new StringBuffer();
  470. if (modelFilter == null || modelFilter.wantsHandleIds()) {
  471. sb.append("Hid:" + (ctr++) + ":");
  472. }
  473. sb.append("(targets=" + targets.size() + ") " + hid + " (" + ir.getName() + ") " + thid + "\n");
  474. w.write(sb.toString());
  475. }
  476. }
  477. }
  478. }
  479. private void dumprelsStderr(String key) {
  480. System.err.println("Relationships dump follows: " + key);
  481. int ctr = 1;
  482. Set<String> entries = mapper.getEntries();
  483. for (String hid : entries) {
  484. for (IRelationship ir : mapper.get(hid)) {
  485. List<String> targets = ir.getTargets();
  486. for (String thid : targets) {
  487. System.err.println("Hid:" + (ctr++) + ":(targets=" + targets.size() + ") " + hid + " (" + ir.getName() + ") "
  488. + thid);
  489. }
  490. }
  491. }
  492. System.err.println("End of relationships dump for: " + key);
  493. }
  494. // ===================== DELTA PROCESSING CODE ============== start
  495. // ==========//
  496. /**
  497. * Removes the hierarchy structure for the specified files from the structure model. Returns true if it deleted anything
  498. */
  499. public boolean removeStructureModelForFiles(Writer fw, Collection<File> files) throws IOException {
  500. boolean modelModified = false;
  501. Set<String> deletedNodes = new HashSet<String>();
  502. for (File fileForCompilation : files) {
  503. String correctedPath = getCanonicalFilePath(fileForCompilation);
  504. IProgramElement progElem = (IProgramElement) hierarchy.findInFileMap(correctedPath);
  505. if (progElem != null) {
  506. // Found it, let's remove it
  507. if (dumpDeltaProcessing) {
  508. fw.write("Deleting " + progElem + " node for file " + fileForCompilation + "\n");
  509. }
  510. removeNode(progElem);
  511. lastBuildChanges.add(fileForCompilation);
  512. deletedNodes.add(getCanonicalFilePath(progElem.getSourceLocation().getSourceFile()));
  513. if (!hierarchy.removeFromFileMap(correctedPath)) {
  514. throw new RuntimeException("Whilst repairing model, couldn't remove entry for file: " + correctedPath
  515. + " from the filemap");
  516. }
  517. modelModified = true;
  518. }
  519. }
  520. if (modelModified) {
  521. hierarchy.updateHandleMap(deletedNodes);
  522. }
  523. return modelModified;
  524. }
  525. public void processDelta(Collection<File> files_tobecompiled, Set<File> files_added, Set<File> files_deleted) {
  526. try {
  527. Writer fw = null;
  528. // Are we recording this ?
  529. if (dumpDeltaProcessing) {
  530. FileWriter filew = new FileWriter(dumpFilename, true);
  531. fw = new BufferedWriter(filew);
  532. fw.write("=== Processing delta changes for the model ===\n");
  533. fw.write("Files for compilation:#" + files_tobecompiled.size() + ":" + files_tobecompiled + "\n");
  534. fw.write("Files added :#" + files_added.size() + ":" + files_added + "\n");
  535. fw.write("Files deleted :#" + files_deleted.size() + ":" + files_deleted + "\n");
  536. }
  537. long stime = System.currentTimeMillis();
  538. // Let's remove all the files that are deleted on this compile
  539. removeStructureModelForFiles(fw, files_deleted);
  540. long etime1 = System.currentTimeMillis(); // etime1-stime = time to
  541. // fix up the model
  542. repairRelationships(fw);
  543. long etime2 = System.currentTimeMillis(); // etime2-stime = time to
  544. // repair the
  545. // relationship map
  546. removeStructureModelForFiles(fw, files_tobecompiled);
  547. if (dumpDeltaProcessing) {
  548. fw.write("===== Delta Processing timing ==========\n");
  549. fw.write("Hierarchy=" + (etime1 - stime) + "ms Relationshipmap=" + (etime2 - etime1) + "ms\n");
  550. fw.write("===== Traversal ========================\n");
  551. // fw.write("Source handles processed="+srchandlecounter+"\n");
  552. // fw.write("Target handles processed="+tgthandlecounter+"\n");
  553. fw.write("========================================\n");
  554. fw.flush();
  555. fw.close();
  556. }
  557. reportModelInfo("After delta processing");
  558. } catch (IOException e) {
  559. e.printStackTrace();
  560. }
  561. }
  562. private String getTypeNameFromHandle(String handle, Map<String, String> cache) {
  563. try {
  564. String typename = cache.get(handle);
  565. if (typename != null) {
  566. return typename;
  567. }
  568. // inpath handle - but for which type?
  569. // let's do it the slow way, we can optimize this with a cache perhaps
  570. int hasPackage = handle.indexOf(HandleProviderDelimiter.PACKAGEFRAGMENT.getDelimiter());
  571. int typeLocation = handle.indexOf(HandleProviderDelimiter.TYPE.getDelimiter());
  572. if (typeLocation == -1) {
  573. typeLocation = handle.indexOf(HandleProviderDelimiter.ASPECT_TYPE.getDelimiter());
  574. }
  575. if (typeLocation == -1) {
  576. // unexpected - time to give up
  577. return "";
  578. }
  579. StringBuffer qualifiedTypeNameFromHandle = new StringBuffer();
  580. if (hasPackage != -1) {
  581. int classfileLoc = handle.indexOf(HandleProviderDelimiter.CLASSFILE.getDelimiter(), hasPackage);
  582. qualifiedTypeNameFromHandle.append(handle.substring(hasPackage + 1, classfileLoc));
  583. qualifiedTypeNameFromHandle.append('.');
  584. }
  585. qualifiedTypeNameFromHandle.append(handle.substring(typeLocation + 1));
  586. typename = qualifiedTypeNameFromHandle.toString();
  587. cache.put(handle, typename);
  588. return typename;
  589. } catch (StringIndexOutOfBoundsException sioobe) {
  590. // debug for 330170
  591. System.err.println("Handle processing problem, the handle is: " + handle);
  592. sioobe.printStackTrace(System.err);
  593. return "";
  594. }
  595. }
  596. /**
  597. * two kinds of relationships
  598. *
  599. * A affects B B affectedBy A
  600. *
  601. * Both of these relationships are added when 'B' is modified. Concrete examples are 'advises/advisedby' or
  602. * 'annotates/annotatedby'.
  603. *
  604. * What we need to do is when 'B' is going to be woven, remove all relationships that may reoccur when it is woven. So - remove
  605. * 'affects' relationships where the target is 'B', remove all 'affectedBy' relationships where the source is 'B'.
  606. *
  607. */
  608. public void removeRelationshipsTargettingThisType(String typename) {
  609. boolean debug = false;
  610. if (debug) {
  611. System.err.println(">>removeRelationshipsTargettingThisType " + typename);
  612. }
  613. String pkg = null;
  614. String type = typename;
  615. int lastSep = typename.lastIndexOf('.');
  616. if (lastSep != -1) {
  617. pkg = typename.substring(0, lastSep);
  618. type = typename.substring(lastSep + 1);
  619. }
  620. boolean didsomething = false;
  621. IProgramElement typeNode = hierarchy.findElementForType(pkg, type);
  622. // Reasons for that being null:
  623. // 1. the file has fundamental errors and so doesn't exist in the model
  624. // (-proceedOnError probably forced us to weave)
  625. if (typeNode == null) {
  626. return;
  627. }
  628. Set<String> sourcesToRemove = new HashSet<String>();
  629. Map<String, String> handleToTypenameCache = new HashMap<String, String>();
  630. // Iterate over the source handles in the relationships map, the aim
  631. // here is to remove any 'affected by'
  632. // relationships where the source of the relationship is the specified
  633. // type (since it will be readded
  634. // when the type is woven)
  635. Set<String> sourcehandlesSet = mapper.getEntries();
  636. List<IRelationship> relationshipsToRemove = new ArrayList<IRelationship>();
  637. for (String hid : sourcehandlesSet) {
  638. if (isPhantomHandle(hid)) {
  639. // inpath handle - but for which type?
  640. // TODO promote cache for reuse during one whole model update
  641. if (!getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
  642. continue;
  643. }
  644. }
  645. IProgramElement sourceElement = hierarchy.getElement(hid);
  646. if (sourceElement == null || sameType(hid, sourceElement, typeNode)) {
  647. // worth continuing as there may be a relationship to remove
  648. relationshipsToRemove.clear();
  649. List<IRelationship> relationships = mapper.get(hid);
  650. for (IRelationship relationship : relationships) {
  651. if (relationship.getKind() == IRelationship.Kind.USES_POINTCUT) {
  652. continue; // these relationships are added at compile
  653. }
  654. // time, argh
  655. if (relationship.isAffects()) {
  656. continue; // we want 'affected by' relationships - (e.g.
  657. }
  658. // advised by)
  659. relationshipsToRemove.add(relationship); // all the relationships can
  660. // be removed, regardless of
  661. // the target(s)
  662. }
  663. // Now, were any relationships emptied during that processing
  664. // and so need removing for this source handle
  665. if (relationshipsToRemove.size() > 0) {
  666. didsomething = true;
  667. if (relationshipsToRemove.size() == relationships.size()) {
  668. sourcesToRemove.add(hid);
  669. } else {
  670. for (int i = 0; i < relationshipsToRemove.size(); i++) {
  671. relationships.remove(relationshipsToRemove.get(i));
  672. }
  673. }
  674. }
  675. }
  676. }
  677. // Remove sources that have no valid relationships any more
  678. for (String hid : sourcesToRemove) {
  679. // System.err.println(
  680. // " source handle: all relationships have gone for "+hid);
  681. mapper.removeAll(hid);
  682. IProgramElement ipe = hierarchy.getElement(hid);
  683. if (ipe != null) {
  684. // If the relationship was hanging off a 'code' node, delete it.
  685. if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
  686. if (debug) {
  687. System.err.println(" source handle: it was code node, removing that as well... code=" + ipe + " parent="
  688. + ipe.getParent());
  689. }
  690. removeSingleNode(ipe);
  691. }
  692. }
  693. }
  694. if (debug) {
  695. dumprelsStderr("after processing 'affectedby'");
  696. }
  697. if (didsomething) { // did we do anything?
  698. sourcesToRemove.clear();
  699. // removing 'affects' relationships
  700. if (debug) {
  701. dumprelsStderr("before processing 'affects'");
  702. }
  703. // Iterate over the source handles in the relationships map
  704. sourcehandlesSet = mapper.getEntries();
  705. for (String hid : sourcehandlesSet) {
  706. relationshipsToRemove.clear();
  707. List<IRelationship> relationships = mapper.get(hid);
  708. for (IRelationship rel : relationships) {
  709. if (rel.getKind() == IRelationship.Kind.USES_POINTCUT) {
  710. continue; // these relationships are added at compile
  711. }
  712. // time, argh
  713. if (!rel.isAffects()) {
  714. continue;
  715. }
  716. List<String> targets = rel.getTargets();
  717. List<String> targetsToRemove = new ArrayList<String>();
  718. // find targets that target the type we are interested in,
  719. // they need removing
  720. for (String targethid : targets) {
  721. if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
  722. continue;
  723. }
  724. // Does this point to the same type?
  725. IProgramElement existingTarget = hierarchy.getElement(targethid);
  726. if (existingTarget == null || sameType(targethid, existingTarget, typeNode)) {
  727. targetsToRemove.add(targethid);
  728. }
  729. }
  730. if (targetsToRemove.size() != 0) {
  731. if (targetsToRemove.size() == targets.size()) {
  732. relationshipsToRemove.add(rel);
  733. } else {
  734. // Remove all the targets that are no longer valid
  735. for (String togo : targetsToRemove) {
  736. targets.remove(togo);
  737. }
  738. }
  739. }
  740. }
  741. // Now, were any relationships emptied during that processing
  742. // and so need removing for this source handle
  743. if (relationshipsToRemove.size() > 0) {
  744. // Are we removing *all* of the relationships for this
  745. // source handle?
  746. if (relationshipsToRemove.size() == relationships.size()) {
  747. sourcesToRemove.add(hid);
  748. } else {
  749. for (int i = 0; i < relationshipsToRemove.size(); i++) {
  750. relationships.remove(relationshipsToRemove.get(i));
  751. }
  752. }
  753. }
  754. }
  755. // Remove sources that have no valid relationships any more
  756. for (String hid : sourcesToRemove) {
  757. // System.err.println(
  758. // " source handle: all relationships have gone for "+hid);
  759. mapper.removeAll(hid);
  760. IProgramElement ipe = hierarchy.getElement(hid);
  761. if (ipe != null) {
  762. // If the relationship was hanging off a 'code' node, delete
  763. // it.
  764. if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
  765. if (debug) {
  766. System.err.println(" source handle: it was code node, removing that as well... code=" + ipe
  767. + " parent=" + ipe.getParent());
  768. }
  769. removeSingleNode(ipe);
  770. }
  771. }
  772. }
  773. if (debug) {
  774. dumprelsStderr("after processing 'affects'");
  775. }
  776. }
  777. if (debug) {
  778. System.err.println("<<removeRelationshipsTargettingThisFile");
  779. }
  780. }
  781. /**
  782. * Return true if the target element is in the type specified.
  783. */
  784. private boolean sameType(String hid, IProgramElement target, IProgramElement type) {
  785. IProgramElement containingType = target;
  786. if (target == null) {
  787. throw new RuntimeException("target can't be null!");
  788. }
  789. if (type == null) {
  790. throw new RuntimeException("type can't be null!");
  791. }
  792. if (target.getKind().isSourceFile() || target.getKind().isFile()) { // isFile() covers pr263487
  793. // @AJ aspect with broken relationship endpoint - we couldn't find
  794. // the real
  795. // endpoint (the declare parents or ITD or similar) so defaulted to
  796. // the
  797. // first line of the source file...
  798. // FRAGILE
  799. // Let's assume the worst, and that it is the same type if the
  800. // source files
  801. // are the same. This will break for multiple top level types in a
  802. // file...
  803. if (target.getSourceLocation() == null) {
  804. return false; // these four possibilities should really be FIXED
  805. }
  806. // so we don't have this situation
  807. if (type.getSourceLocation() == null) {
  808. return false;
  809. }
  810. if (target.getSourceLocation().getSourceFile() == null) {
  811. return false;
  812. }
  813. if (type.getSourceLocation().getSourceFile() == null) {
  814. return false;
  815. }
  816. return (target.getSourceLocation().getSourceFile().equals(type.getSourceLocation().getSourceFile()));
  817. }
  818. try {
  819. while (!containingType.getKind().isType()) {
  820. containingType = containingType.getParent();
  821. }
  822. } catch (Throwable t) {
  823. // Example:
  824. // java.lang.RuntimeException: Exception whilst walking up from target X.class kind=(file)
  825. // hid=(=importProb/binaries<x(X.class)
  826. throw new RuntimeException("Exception whilst walking up from target " + target.toLabelString() + " kind=("
  827. + target.getKind() + ") hid=(" + target.getHandleIdentifier() + ")", t);
  828. }
  829. return (type.equals(containingType));
  830. }
  831. /**
  832. * @param handle a JDT like handle, following the form described in AsmRelationshipProvider.findOrFakeUpNode
  833. * @return true if the handle contains ';' - the char indicating that it is a phantom handle
  834. */
  835. private boolean isPhantomHandle(String handle) {
  836. int phantomMarker = handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter());
  837. return phantomMarker != -1
  838. && handle.charAt(phantomMarker - 1) == HandleProviderDelimiter.PACKAGEFRAGMENTROOT.getDelimiter();
  839. }
  840. /**
  841. * Go through all the relationships in the model, if any endpoints no longer exist (the node it points to has been deleted from
  842. * the model) then delete the relationship.
  843. */
  844. private void repairRelationships(Writer fw) {
  845. try {
  846. // IHierarchy model = AsmManager.getDefault().getHierarchy();
  847. // TODO Speed this code up by making this assumption:
  848. // the only piece of the handle that is interesting is the file
  849. // name. We are working at file granularity, if the
  850. // file does not exist (i.e. its not in the filemap) then any handle
  851. // inside that file cannot exist.
  852. if (dumpDeltaProcessing) {
  853. fw.write("Repairing relationships map:\n");
  854. }
  855. // Now sort out the relationships map
  856. // IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
  857. Set<String> sourcesToRemove = new HashSet<String>();
  858. Set<String> nonExistingHandles = new HashSet<String>(); // Cache of handles that we
  859. // *know* are invalid
  860. int srchandlecounter = 0;
  861. int tgthandlecounter = 0;
  862. // Iterate over the source handles in the relationships map
  863. Set<String> keyset = mapper.getEntries(); // These are source handles
  864. for (String hid : keyset) {
  865. srchandlecounter++;
  866. // Do we already know this handle points to nowhere?
  867. if (nonExistingHandles.contains(hid)) {
  868. sourcesToRemove.add(hid);
  869. } else if (!isPhantomHandle(hid)) {
  870. // We better check if it actually exists
  871. IProgramElement existingElement = hierarchy.getElement(hid);
  872. if (dumpDeltaProcessing) {
  873. fw.write("Looking for handle [" + hid + "] in model, found: " + existingElement + "\n");
  874. }
  875. // Did we find it?
  876. if (existingElement == null) {
  877. // No, so delete this relationship
  878. sourcesToRemove.add(hid);
  879. nonExistingHandles.add(hid); // Speed up a bit you swine
  880. } else {
  881. // Ok, so the source is valid, what about the targets?
  882. List<IRelationship> relationships = mapper.get(hid);
  883. List<IRelationship> relationshipsToRemove = new ArrayList<IRelationship>();
  884. // Iterate through the relationships against this source
  885. // handle
  886. for (Iterator<IRelationship> reliter = relationships.iterator(); reliter.hasNext();) {
  887. IRelationship rel = reliter.next();
  888. List<String> targets = rel.getTargets();
  889. List<String> targetsToRemove = new ArrayList<String>();
  890. // Iterate through the targets for this relationship
  891. for (Iterator<String> targetIter = targets.iterator(); targetIter.hasNext();) {
  892. String targethid = targetIter.next();
  893. tgthandlecounter++;
  894. // Do we already know it doesn't exist?
  895. if (nonExistingHandles.contains(targethid)) {
  896. if (dumpDeltaProcessing) {
  897. fw.write("Target handle [" + targethid + "] for srchid[" + hid + "]rel[" + rel.getName()
  898. + "] does not exist\n");
  899. }
  900. targetsToRemove.add(targethid);
  901. } else if (!isPhantomHandle(targethid)) {
  902. // We better check
  903. IProgramElement existingTarget = hierarchy.getElement(targethid);
  904. if (existingTarget == null) {
  905. if (dumpDeltaProcessing) {
  906. fw.write("Target handle [" + targethid + "] for srchid[" + hid + "]rel["
  907. + rel.getName() + "] does not exist\n");
  908. }
  909. targetsToRemove.add(targethid);
  910. nonExistingHandles.add(targethid);
  911. }
  912. }
  913. }
  914. // Do we have some targets that need removing?
  915. if (targetsToRemove.size() != 0) {
  916. // Are we removing *all* of the targets for this
  917. // relationship (i.e. removing the relationship)
  918. if (targetsToRemove.size() == targets.size()) {
  919. if (dumpDeltaProcessing) {
  920. fw.write("No targets remain for srchid[" + hid + "] rel[" + rel.getName()
  921. + "]: removing it\n");
  922. }
  923. relationshipsToRemove.add(rel);
  924. } else {
  925. // Remove all the targets that are no longer
  926. // valid
  927. for (String togo : targetsToRemove) {
  928. targets.remove(togo);
  929. }
  930. // Should have already been caught above,
  931. // but lets double check ...
  932. if (targets.size() == 0) {
  933. if (dumpDeltaProcessing) {
  934. fw.write("No targets remain for srchid[" + hid + "] rel[" + rel.getName()
  935. + "]: removing it\n");
  936. }
  937. relationshipsToRemove.add(rel); // TODO
  938. // Should
  939. // only
  940. // remove
  941. // this
  942. // relationship
  943. // for
  944. // the
  945. // srchid
  946. // ?
  947. }
  948. }
  949. }
  950. }
  951. // Now, were any relationships emptied during that
  952. // processing and so need removing for this source
  953. // handle
  954. if (relationshipsToRemove.size() > 0) {
  955. // Are we removing *all* of the relationships for
  956. // this source handle?
  957. if (relationshipsToRemove.size() == relationships.size()) {
  958. // We know they are all going to go, so just
  959. // delete the source handle.
  960. sourcesToRemove.add(hid);
  961. } else {
  962. // MEMORY LEAK - we don't remove the
  963. // relationships !!
  964. for (int i = 0; i < relationshipsToRemove.size(); i++) {
  965. IRelationship irel = relationshipsToRemove.get(i);
  966. verifyAssumption(mapper.remove(hid, irel), "Failed to remove relationship " + irel.getName()
  967. + " for shid " + hid);
  968. }
  969. List<IRelationship> rels = mapper.get(hid);
  970. if (rels == null || rels.size() == 0) {
  971. sourcesToRemove.add(hid);
  972. }
  973. }
  974. }
  975. }
  976. }
  977. }
  978. // Remove sources that have no valid relationships any more
  979. for (Iterator<String> srciter = sourcesToRemove.iterator(); srciter.hasNext();) {
  980. String hid = srciter.next();
  981. mapper.removeAll(hid);
  982. IProgramElement ipe = hierarchy.getElement(hid);
  983. if (ipe != null) {
  984. // If the relationship was hanging off a 'code' node, delete
  985. // it.
  986. if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
  987. // System.err.println("Deleting code node");
  988. removeSingleNode(ipe);
  989. }
  990. }
  991. }
  992. } catch (IOException ioe) {
  993. System.err.println("Failed to repair relationships:");
  994. ioe.printStackTrace();
  995. }
  996. }
  997. /**
  998. * Removes a specified program element from the structure model. We go to the parent of the program element, ask for all its
  999. * children and remove the node we want to delete from the list of children.
  1000. */
  1001. private void removeSingleNode(IProgramElement progElem) {
  1002. if (progElem == null) {
  1003. throw new IllegalStateException("AsmManager.removeNode(): programElement unexpectedly null");
  1004. }
  1005. boolean deleteOK = false;
  1006. IProgramElement parent = progElem.getParent();
  1007. List<IProgramElement> kids = parent.getChildren();
  1008. for (int i = 0, max = kids.size(); i < max; i++) {
  1009. if (kids.get(i).equals(progElem)) {
  1010. kids.remove(i);
  1011. deleteOK = true;
  1012. break;
  1013. }
  1014. }
  1015. if (!deleteOK) {
  1016. System.err.println("unexpectedly failed to delete node from model. hid=" + progElem.getHandleIdentifier());
  1017. }
  1018. }
  1019. /**
  1020. * Removes a specified program element from the structure model. Two processing stages:
  1021. * <p>
  1022. * First: We go to the parent of the program element, ask for all its children and remove the node we want to delete from the
  1023. * list of children.
  1024. * <p>
  1025. * Second:We check if that parent has any other children. If it has no other children and it is either a CODE node or a PACKAGE
  1026. * node, we delete it too.
  1027. */
  1028. private void removeNode(IProgramElement progElem) {
  1029. // StringBuffer flightrecorder = new StringBuffer();
  1030. try {
  1031. // flightrecorder.append("In removeNode, about to chuck away: "+
  1032. // progElem+"\n");
  1033. if (progElem == null) {
  1034. throw new IllegalStateException("AsmManager.removeNode(): programElement unexpectedly null");
  1035. }
  1036. // boolean deleteOK = false;
  1037. IProgramElement parent = progElem.getParent();
  1038. // flightrecorder.append("Parent of it is "+parent+"\n");
  1039. List<IProgramElement> kids = parent.getChildren();
  1040. // flightrecorder.append("Which has "+kids.size()+" kids\n");
  1041. for (int i = 0; i < kids.size(); i++) {
  1042. // flightrecorder.append("Comparing with "+kids.get(i)+"\n");
  1043. if (kids.get(i).equals(progElem)) {
  1044. kids.remove(i);
  1045. // flightrecorder.append("Removing it\n");
  1046. // deleteOK=true;
  1047. break;
  1048. }
  1049. }
  1050. // verifyAssumption(deleteOK,flightrecorder.toString());
  1051. // Are there any kids left for this node?
  1052. if (parent.getChildren().size() == 0
  1053. && parent.getParent() != null
  1054. && (parent.getKind().equals(IProgramElement.Kind.CODE) || parent.getKind().equals(IProgramElement.Kind.PACKAGE))) {
  1055. // This node is on its own, we should trim it too *as long as
  1056. // its not a structural node* which we currently check by
  1057. // making sure its a code node
  1058. // We should trim if it
  1059. // System.err.println("Deleting parent:"+parent);
  1060. removeNode(parent);
  1061. }
  1062. } catch (NullPointerException npe) {
  1063. // Occurred when commenting out other 2 ras classes in wsif??
  1064. // reproducable?
  1065. // System.err.println(flightrecorder.toString());
  1066. npe.printStackTrace();
  1067. }
  1068. }
  1069. public static void verifyAssumption(boolean b, String info) {
  1070. if (!b) {
  1071. System.err.println("=========== ASSERTION IS NOT TRUE =========v");
  1072. System.err.println(info);
  1073. Thread.dumpStack();
  1074. System.err.println("=========== ASSERTION IS NOT TRUE =========^");
  1075. throw new RuntimeException("Assertion is false");
  1076. }
  1077. }
  1078. public static void verifyAssumption(boolean b) {
  1079. if (!b) {
  1080. Thread.dumpStack();
  1081. throw new RuntimeException("Assertion is false");
  1082. }
  1083. }
  1084. // ===================== DELTA PROCESSING CODE ============== end
  1085. // ==========//
  1086. /**
  1087. * A ModelInfo object captures basic information about the structure model. It is used for testing and producing debug info.
  1088. */
  1089. public static class ModelInfo {
  1090. private final Hashtable<String, Integer> nodeTypeCount = new Hashtable<String, Integer>();
  1091. private final Properties extraProperties = new Properties();
  1092. private ModelInfo(IHierarchy hierarchy, IRelationshipMap relationshipMap) {
  1093. IProgramElement ipe = hierarchy.getRoot();
  1094. walkModel(ipe);
  1095. recordStat("FileMapSize", new Integer(hierarchy.getFileMapEntrySet().size()).toString());
  1096. recordStat("RelationshipMapSize", new Integer(relationshipMap.getEntries().size()).toString());
  1097. }
  1098. private void walkModel(IProgramElement ipe) {
  1099. countNode(ipe);
  1100. for (IProgramElement child : ipe.getChildren()) {
  1101. walkModel(child);
  1102. }
  1103. }
  1104. private void countNode(IProgramElement ipe) {
  1105. String node = ipe.getKind().toString();
  1106. Integer ctr = nodeTypeCount.get(node);
  1107. if (ctr == null) {
  1108. nodeTypeCount.put(node, new Integer(1));
  1109. } else {
  1110. ctr = new Integer(ctr.intValue() + 1);
  1111. nodeTypeCount.put(node, ctr);
  1112. }
  1113. }
  1114. public String toString() {
  1115. StringBuffer sb = new StringBuffer();
  1116. sb.append("Model node summary:\n");
  1117. Enumeration<String> nodeKeys = nodeTypeCount.keys();
  1118. while (nodeKeys.hasMoreElements()) {
  1119. String key = nodeKeys.nextElement();
  1120. Integer ct = nodeTypeCount.get(key);
  1121. sb.append(key + "=" + ct + "\n");
  1122. }
  1123. sb.append("Model stats:\n");
  1124. Enumeration<Object> ks = extraProperties.keys();
  1125. while (ks.hasMoreElements()) {
  1126. String k = (String) ks.nextElement();
  1127. String v = extraProperties.getProperty(k);
  1128. sb.append(k + "=" + v + "\n");
  1129. }
  1130. return sb.toString();
  1131. }
  1132. public Properties getProperties() {
  1133. Properties p = new Properties();
  1134. for (Map.Entry<String, Integer> entry : nodeTypeCount.entrySet()) {
  1135. p.setProperty(entry.getKey(), entry.getValue().toString());
  1136. }
  1137. p.putAll(extraProperties);
  1138. return p;
  1139. }
  1140. public void recordStat(String string, String string2) {
  1141. extraProperties.setProperty(string, string2);
  1142. }
  1143. }
  1144. public ModelInfo summarizeModel() {
  1145. return new ModelInfo(getHierarchy(), getRelationshipMap());
  1146. }
  1147. /**
  1148. * Set to indicate whether we are currently building a structure model, should be set up front.
  1149. */
  1150. // public static void setCreatingModel(boolean b) {
  1151. // creatingModel = b;
  1152. // }
  1153. //
  1154. // /**
  1155. // * returns true if we are currently generating a structure model, enables guarding of expensive operations on an empty/null
  1156. // * model.
  1157. // */
  1158. // public static boolean isCreatingModel() {
  1159. // return creatingModel;
  1160. // }
  1161. public static void setCompletingTypeBindings(boolean b) {
  1162. completingTypeBindings = b;
  1163. }
  1164. public static boolean isCompletingTypeBindings() {
  1165. return completingTypeBindings;
  1166. }
  1167. // public void setRelationshipMap(IRelationshipMap irm) {
  1168. // mapper = irm;
  1169. // }
  1170. //
  1171. // public void setHierarchy(IHierarchy ih) {
  1172. // hierarchy = ih;
  1173. // }
  1174. public void resetDeltaProcessing() {
  1175. lastBuildChanges.clear();
  1176. aspectsWeavingInLastBuild.clear();
  1177. }
  1178. /**
  1179. * @return the Set of files for which the structure model was modified (they may have been removed or otherwise rebuilt). Set is
  1180. * empty for a full build.
  1181. */
  1182. public Set<File> getModelChangesOnLastBuild() {
  1183. return lastBuildChanges;
  1184. }
  1185. /**
  1186. * @return the Set of aspects that wove files on the last build (either incremental or full build)
  1187. */
  1188. public Set<File> getAspectsWeavingFilesOnLastBuild() {
  1189. return aspectsWeavingInLastBuild;
  1190. }
  1191. public void addAspectInEffectThisBuild(File f) {
  1192. aspectsWeavingInLastBuild.add(f);
  1193. }
  1194. public static void setLastActiveStructureModel(AsmManager structureModel) {
  1195. if (recordingLastActiveStructureModel) {
  1196. lastActiveStructureModel = structureModel;
  1197. }
  1198. }
  1199. public String getHandleElementForInpath(String binaryPath) {
  1200. return inpathMap.get(new File(binaryPath));
  1201. }
  1202. }