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.

AjBuildManager.java 42KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.core.builder;
  13. import java.io.BufferedOutputStream;
  14. import java.io.ByteArrayOutputStream;
  15. import java.io.File;
  16. import java.io.FileFilter;
  17. import java.io.FileInputStream;
  18. import java.io.IOException;
  19. import java.io.OutputStream;
  20. import java.io.PrintStream;
  21. import java.util.ArrayList;
  22. import java.util.Collection;
  23. import java.util.HashMap;
  24. import java.util.Iterator;
  25. import java.util.LinkedList;
  26. import java.util.List;
  27. import java.util.Locale;
  28. import java.util.Map;
  29. import java.util.jar.Attributes;
  30. import java.util.jar.JarFile;
  31. import java.util.jar.JarInputStream;
  32. import java.util.jar.JarOutputStream;
  33. import java.util.jar.Manifest;
  34. import java.util.zip.ZipEntry;
  35. import org.aspectj.ajdt.internal.compiler.AjCompilerAdapter;
  36. import org.aspectj.ajdt.internal.compiler.IBinarySourceProvider;
  37. import org.aspectj.ajdt.internal.compiler.ICompilerAdapter;
  38. import org.aspectj.ajdt.internal.compiler.ICompilerAdapterFactory;
  39. import org.aspectj.ajdt.internal.compiler.IIntermediateResultsRequestor;
  40. import org.aspectj.ajdt.internal.compiler.IOutputClassFileNameProvider;
  41. import org.aspectj.ajdt.internal.compiler.InterimCompilationResult;
  42. import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
  43. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  44. import org.aspectj.ajdt.internal.compiler.problem.AjProblemReporter;
  45. import org.aspectj.asm.AsmManager;
  46. import org.aspectj.asm.IHierarchy;
  47. import org.aspectj.asm.IProgramElement;
  48. import org.aspectj.asm.internal.ProgramElement;
  49. import org.aspectj.bridge.AbortException;
  50. import org.aspectj.bridge.CountingMessageHandler;
  51. import org.aspectj.bridge.IMessage;
  52. import org.aspectj.bridge.IMessageHandler;
  53. import org.aspectj.bridge.IProgressListener;
  54. import org.aspectj.bridge.Message;
  55. import org.aspectj.bridge.MessageUtil;
  56. import org.aspectj.bridge.SourceLocation;
  57. import org.aspectj.bridge.Version;
  58. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  59. import org.aspectj.bridge.context.ContextFormatter;
  60. import org.aspectj.bridge.context.ContextToken;
  61. import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
  62. import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
  63. import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
  64. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  65. import org.aspectj.org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
  66. import org.aspectj.org.eclipse.jdt.internal.compiler.ICompilerRequestor;
  67. import org.aspectj.org.eclipse.jdt.internal.compiler.IProblemFactory;
  68. import org.aspectj.org.eclipse.jdt.internal.compiler.batch.ClasspathDirectory;
  69. import org.aspectj.org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
  70. import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem;
  71. import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
  72. import org.aspectj.org.eclipse.jdt.internal.compiler.env.INameEnvironment;
  73. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
  74. import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
  75. import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
  76. import org.aspectj.org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
  77. import org.aspectj.util.FileUtil;
  78. import org.aspectj.weaver.Dump;
  79. import org.aspectj.weaver.ResolvedType;
  80. import org.aspectj.weaver.World;
  81. import org.aspectj.weaver.bcel.BcelWeaver;
  82. import org.aspectj.weaver.bcel.BcelWorld;
  83. import org.aspectj.weaver.bcel.UnwovenClassFile;
  84. import org.eclipse.core.runtime.OperationCanceledException;
  85. //import org.aspectj.org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
  86. public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourceProvider,ICompilerAdapterFactory {
  87. private static final String CANT_WRITE_RESULT = "unable to write compilation result";
  88. private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
  89. static final boolean COPY_INPATH_DIR_RESOURCES = false;
  90. static final boolean FAIL_IF_RUNTIME_NOT_FOUND = false;
  91. private static final FileFilter binarySourceFilter =
  92. new FileFilter() {
  93. public boolean accept(File f) {
  94. return f.getName().endsWith(".class");
  95. }};
  96. /**
  97. * This builder is static so that it can be subclassed and reset. However, note
  98. * that there is only one builder present, so if two extendsion reset it, only
  99. * the latter will get used.
  100. */
  101. private static AsmHierarchyBuilder asmHierarchyBuilder = new AsmHierarchyBuilder();
  102. static {
  103. CompilationAndWeavingContext.registerFormatter(
  104. CompilationAndWeavingContext.BATCH_BUILD, new AjBuildContexFormatter());
  105. CompilationAndWeavingContext.registerFormatter(
  106. CompilationAndWeavingContext.INCREMENTAL_BUILD, new AjBuildContexFormatter());
  107. }
  108. private IProgressListener progressListener = null;
  109. private int compiledCount;
  110. private int sourceFileCount;
  111. private JarOutputStream zos;
  112. private boolean batchCompile = true;
  113. private INameEnvironment environment;
  114. private Map /* String -> List<UCF>*/ binarySourcesForTheNextCompile = new HashMap();
  115. // FIXME asc should this really be in here?
  116. private IHierarchy structureModel;
  117. public AjBuildConfig buildConfig;
  118. private List aspectNames = new LinkedList();
  119. AjState state = new AjState(this);
  120. public BcelWeaver getWeaver() { return state.getWeaver();}
  121. public BcelWorld getBcelWorld() { return state.getBcelWorld();}
  122. public CountingMessageHandler handler;
  123. public AjBuildManager(IMessageHandler holder) {
  124. super();
  125. this.handler = CountingMessageHandler.makeCountingMessageHandler(holder);
  126. }
  127. /** @return true if we should generate a model as a side-effect */
  128. public boolean doGenerateModel() {
  129. return buildConfig.isGenerateModelMode();
  130. }
  131. public boolean batchBuild(
  132. AjBuildConfig buildConfig,
  133. IMessageHandler baseHandler)
  134. throws IOException, AbortException {
  135. return doBuild(buildConfig, baseHandler, true);
  136. }
  137. public boolean incrementalBuild(
  138. AjBuildConfig buildConfig,
  139. IMessageHandler baseHandler)
  140. throws IOException, AbortException {
  141. return doBuild(buildConfig, baseHandler, false);
  142. }
  143. /** @throws AbortException if check for runtime fails */
  144. protected boolean doBuild(
  145. AjBuildConfig buildConfig,
  146. IMessageHandler baseHandler,
  147. boolean batch) throws IOException, AbortException {
  148. boolean ret = true;
  149. batchCompile = batch;
  150. int phase = batch ? CompilationAndWeavingContext.BATCH_BUILD : CompilationAndWeavingContext.INCREMENTAL_BUILD;
  151. ContextToken ct = CompilationAndWeavingContext.enteringPhase(phase ,buildConfig);
  152. try {
  153. if (batch) {
  154. this.state = new AjState(this);
  155. }
  156. boolean canIncremental = state.prepareForNextBuild(buildConfig);
  157. if (!canIncremental && !batch) { // retry as batch?
  158. CompilationAndWeavingContext.leavingPhase(ct);
  159. return doBuild(buildConfig, baseHandler, true);
  160. }
  161. this.handler =
  162. CountingMessageHandler.makeCountingMessageHandler(baseHandler);
  163. // XXX duplicate, no? remove?
  164. String check = checkRtJar(buildConfig);
  165. if (check != null) {
  166. if (FAIL_IF_RUNTIME_NOT_FOUND) {
  167. MessageUtil.error(handler, check);
  168. CompilationAndWeavingContext.leavingPhase(ct);
  169. return false;
  170. } else {
  171. MessageUtil.warn(handler, check);
  172. }
  173. }
  174. // if (batch) {
  175. setBuildConfig(buildConfig);
  176. //}
  177. if (batch || !AsmManager.attemptIncrementalModelRepairs) {
  178. // if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
  179. setupModel(buildConfig);
  180. // }
  181. }
  182. if (batch) {
  183. initBcelWorld(handler);
  184. }
  185. if (handler.hasErrors()) {
  186. CompilationAndWeavingContext.leavingPhase(ct);
  187. return false;
  188. }
  189. if (buildConfig.getOutputJar() != null) {
  190. if (!openOutputStream(buildConfig.getOutputJar())) {
  191. CompilationAndWeavingContext.leavingPhase(ct);
  192. return false;
  193. }
  194. }
  195. if (batch) {
  196. // System.err.println("XXXX batch: " + buildConfig.getFiles());
  197. if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
  198. getWorld().setModel(AsmManager.getDefault().getHierarchy());
  199. // in incremental build, only get updated model?
  200. }
  201. binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true);
  202. performCompilation(buildConfig.getFiles());
  203. if (handler.hasErrors()) {
  204. CompilationAndWeavingContext.leavingPhase(ct);
  205. return false;
  206. }
  207. if (AsmManager.isReporting())
  208. AsmManager.getDefault().reportModelInfo("After a batch build");
  209. } else {
  210. // done already?
  211. // if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode()) {
  212. // bcelWorld.setModel(StructureModelManager.INSTANCE.getStructureModel());
  213. // }
  214. // System.err.println("XXXX start inc ");
  215. binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(true);
  216. List files = state.getFilesToCompile(true);
  217. if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode())
  218. if (AsmManager.attemptIncrementalModelRepairs)
  219. AsmManager.getDefault().processDelta(files,state.addedFiles,state.deletedFiles);
  220. boolean hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
  221. for (int i = 0; (i < 5) && hereWeGoAgain; i++) {
  222. // System.err.println("XXXX inc: " + files);
  223. performCompilation(files);
  224. if (handler.hasErrors() || (progressListener!=null && progressListener.isCancelledRequested())) {
  225. CompilationAndWeavingContext.leavingPhase(ct);
  226. return false;
  227. }
  228. binarySourcesForTheNextCompile = state.getBinaryFilesToCompile(false);
  229. files = state.getFilesToCompile(false);
  230. hereWeGoAgain = !(files.isEmpty() && binarySourcesForTheNextCompile.isEmpty());
  231. // TODO Andy - Needs some thought here...
  232. // I think here we might want to pass empty addedFiles/deletedFiles as they were
  233. // dealt with on the first call to processDelta - we are going through this loop
  234. // again because in compiling something we found something else we needed to
  235. // rebuild. But what case causes this?
  236. if (hereWeGoAgain)
  237. if (buildConfig.isEmacsSymMode() || buildConfig.isGenerateModelMode())
  238. if (AsmManager.attemptIncrementalModelRepairs)
  239. AsmManager.getDefault().processDelta(files,state.addedFiles,state.deletedFiles);
  240. }
  241. if (!files.isEmpty()) {
  242. CompilationAndWeavingContext.leavingPhase(ct);
  243. return batchBuild(buildConfig, baseHandler);
  244. } else {
  245. if (AsmManager.isReporting())
  246. AsmManager.getDefault().reportModelInfo("After an incremental build");
  247. }
  248. }
  249. // XXX not in Mik's incremental
  250. if (buildConfig.isEmacsSymMode()) {
  251. new org.aspectj.ajdt.internal.core.builder.EmacsStructureModelManager().externalizeModel();
  252. }
  253. // have to tell state we succeeded or next is not incremental
  254. state.successfulCompile(buildConfig,batch);
  255. copyResourcesToDestination();
  256. if (buildConfig.getOutxmlName() != null) {
  257. writeOutxmlFile();
  258. }
  259. /*boolean weaved = *///weaveAndGenerateClassFiles();
  260. // if not weaved, then no-op build, no model changes
  261. // but always returns true
  262. // XXX weaved not in Mik's incremental
  263. if (buildConfig.isGenerateModelMode()) {
  264. AsmManager.getDefault().fireModelUpdated();
  265. }
  266. CompilationAndWeavingContext.leavingPhase(ct);
  267. } finally {
  268. if (zos != null) {
  269. closeOutputStream(buildConfig.getOutputJar());
  270. }
  271. ret = !handler.hasErrors();
  272. getBcelWorld().tidyUp();
  273. // bug 59895, don't release reference to handler as may be needed by a nested call
  274. //handler = null;
  275. }
  276. return ret;
  277. }
  278. private boolean openOutputStream(File outJar) {
  279. try {
  280. OutputStream os = FileUtil.makeOutputStream(buildConfig.getOutputJar());
  281. zos = new JarOutputStream(os,getWeaver().getManifest(true));
  282. } catch (IOException ex) {
  283. IMessage message =
  284. new Message("Unable to open outjar "
  285. + outJar.getPath()
  286. + "(" + ex.getMessage()
  287. + ")",
  288. new SourceLocation(outJar,0),
  289. true);
  290. handler.handleMessage(message);
  291. return false;
  292. }
  293. return true;
  294. }
  295. private void closeOutputStream(File outJar) {
  296. try {
  297. if (zos != null) zos.close();
  298. zos = null;
  299. /* Ensure we don't write an incomplete JAR bug-71339 */
  300. if (handler.hasErrors()) {
  301. outJar.delete();
  302. }
  303. } catch (IOException ex) {
  304. IMessage message =
  305. new Message("Unable to write outjar "
  306. + outJar.getPath()
  307. + "(" + ex.getMessage()
  308. + ")",
  309. new SourceLocation(outJar,0),
  310. true);
  311. handler.handleMessage(message);
  312. }
  313. }
  314. private void copyResourcesToDestination() throws IOException {
  315. // resources that we need to copy are contained in the injars and inpath only
  316. for (Iterator i = buildConfig.getInJars().iterator(); i.hasNext(); ) {
  317. File inJar = (File)i.next();
  318. copyResourcesFromJarFile(inJar);
  319. }
  320. for (Iterator i = buildConfig.getInpath().iterator(); i.hasNext(); ) {
  321. File inPathElement = (File)i.next();
  322. if (inPathElement.isDirectory()) {
  323. copyResourcesFromDirectory(inPathElement);
  324. } else {
  325. copyResourcesFromJarFile(inPathElement);
  326. }
  327. }
  328. if (buildConfig.getSourcePathResources() != null) {
  329. for (Iterator i = buildConfig.getSourcePathResources().keySet().iterator(); i.hasNext(); ) {
  330. String resource = (String)i.next();
  331. File from = (File)buildConfig.getSourcePathResources().get(resource);
  332. copyResourcesFromFile(from,resource,from);
  333. }
  334. }
  335. writeManifest();
  336. }
  337. private void copyResourcesFromJarFile(File jarFile) throws IOException {
  338. JarInputStream inStream = null;
  339. try {
  340. inStream = new JarInputStream(new FileInputStream(jarFile));
  341. while (true) {
  342. ZipEntry entry = inStream.getNextEntry();
  343. if (entry == null) break;
  344. String filename = entry.getName();
  345. // System.out.println("? copyResourcesFromJarFile() filename='" + filename +"'");
  346. if (!entry.isDirectory() && acceptResource(filename)) {
  347. byte[] bytes = FileUtil.readAsByteArray(inStream);
  348. writeResource(filename,bytes,jarFile);
  349. }
  350. inStream.closeEntry();
  351. }
  352. } finally {
  353. if (inStream != null) inStream.close();
  354. }
  355. }
  356. private void copyResourcesFromDirectory(File dir) throws IOException {
  357. if (!COPY_INPATH_DIR_RESOURCES) return;
  358. // Get a list of all files (i.e. everything that isnt a directory)
  359. File[] files = FileUtil.listFiles(dir,new FileFilter() {
  360. public boolean accept(File f) {
  361. boolean accept = !(f.isDirectory() || f.getName().endsWith(".class")) ;
  362. return accept;
  363. }
  364. });
  365. // For each file, add it either as a real .class file or as a resource
  366. for (int i = 0; i < files.length; i++) {
  367. // ASSERT: files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath()
  368. // or we are in trouble...
  369. String filename = files[i].getAbsolutePath().substring(
  370. dir.getAbsolutePath().length()+1);
  371. copyResourcesFromFile(files[i],filename,dir);
  372. }
  373. }
  374. private void copyResourcesFromFile(File f,String filename,File src) throws IOException {
  375. if (!acceptResource(filename)) return;
  376. FileInputStream fis = null;
  377. try {
  378. fis = new FileInputStream(f);
  379. byte[] bytes = FileUtil.readAsByteArray(fis);
  380. // String relativePath = files[i].getPath();
  381. writeResource(filename,bytes,src);
  382. } finally {
  383. if (fis != null) fis.close();
  384. }
  385. }
  386. private void writeResource(String filename, byte[] content, File srcLocation) throws IOException {
  387. if (state.resources.contains(filename)) {
  388. IMessage msg = new Message("duplicate resource: '" + filename + "'",
  389. IMessage.WARNING,
  390. null,
  391. new SourceLocation(srcLocation,0));
  392. handler.handleMessage(msg);
  393. return;
  394. }
  395. if (zos != null) {
  396. ZipEntry newEntry = new ZipEntry(filename); //??? get compression scheme right
  397. zos.putNextEntry(newEntry);
  398. zos.write(content);
  399. zos.closeEntry();
  400. } else {
  401. OutputStream fos =
  402. FileUtil.makeOutputStream(new File(buildConfig.getOutputDir(),filename));
  403. fos.write(content);
  404. fos.close();
  405. }
  406. state.resources.add(filename);
  407. }
  408. /*
  409. * If we are writing to an output directory copy the manifest but only
  410. * if we already have one
  411. */
  412. private void writeManifest () throws IOException {
  413. Manifest manifest = getWeaver().getManifest(false);
  414. if (manifest != null && zos == null) {
  415. OutputStream fos =
  416. FileUtil.makeOutputStream(new File(buildConfig.getOutputDir(),MANIFEST_NAME));
  417. manifest.write(fos);
  418. fos.close();
  419. }
  420. }
  421. private boolean acceptResource(String resourceName) {
  422. if (
  423. (resourceName.startsWith("CVS/")) ||
  424. (resourceName.indexOf("/CVS/") != -1) ||
  425. (resourceName.endsWith("/CVS")) ||
  426. (resourceName.endsWith(".class")) ||
  427. (resourceName.toUpperCase().equals(MANIFEST_NAME))
  428. )
  429. {
  430. return false;
  431. } else {
  432. return true;
  433. }
  434. }
  435. private void writeOutxmlFile () throws IOException {
  436. String filename = buildConfig.getOutxmlName();
  437. // System.err.println("? AjBuildManager.writeOutxmlFile() outxml=" + filename);
  438. // System.err.println("? AjBuildManager.writeOutxmlFile() outputDir=" + buildConfig.getOutputDir());
  439. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  440. PrintStream ps = new PrintStream(baos);
  441. ps.println("<aspectj>");
  442. ps.println("<aspects>");
  443. for (Iterator i = aspectNames.iterator(); i.hasNext();) {
  444. String name = (String)i.next();
  445. ps.println("<aspect name=\"" + name + "\"/>");
  446. }
  447. ps.println("</aspects>");
  448. ps.println("</aspectj>");
  449. ps.println();
  450. ps.close();
  451. if (zos != null) {
  452. ZipEntry newEntry = new ZipEntry(filename);
  453. zos.putNextEntry(newEntry);
  454. zos.write(baos.toByteArray());
  455. zos.closeEntry();
  456. } else {
  457. OutputStream fos =
  458. FileUtil.makeOutputStream(new File(buildConfig.getOutputDir(),filename));
  459. fos.write(baos.toByteArray());
  460. fos.close();
  461. }
  462. }
  463. // public static void dumprels() {
  464. // IRelationshipMap irm = AsmManager.getDefault().getRelationshipMap();
  465. // int ctr = 1;
  466. // Set entries = irm.getEntries();
  467. // for (Iterator iter = entries.iterator(); iter.hasNext();) {
  468. // String hid = (String) iter.next();
  469. // List rels = irm.get(hid);
  470. // for (Iterator iterator = rels.iterator(); iterator.hasNext();) {
  471. // IRelationship ir = (IRelationship) iterator.next();
  472. // List targets = ir.getTargets();
  473. // for (Iterator iterator2 = targets.iterator();
  474. // iterator2.hasNext();
  475. // ) {
  476. // String thid = (String) iterator2.next();
  477. // System.err.println("Hid:"+(ctr++)+":(targets="+targets.size()+") "+hid+" ("+ir.getName()+") "+thid);
  478. // }
  479. // }
  480. // }
  481. // }
  482. /**
  483. * Responsible for managing the ASM model between builds. Contains the policy for
  484. * maintaining the persistance of elements in the model.
  485. *
  486. * This code is driven before each 'fresh' (batch) build to create
  487. * a new model.
  488. */
  489. private void setupModel(AjBuildConfig config) {
  490. AsmManager.setCreatingModel(config.isEmacsSymMode() || config.isGenerateModelMode());
  491. if (!AsmManager.isCreatingModel()) return;
  492. AsmManager.getDefault().createNewASM();
  493. // AsmManager.getDefault().getRelationshipMap().clear();
  494. IHierarchy model = AsmManager.getDefault().getHierarchy();
  495. String rootLabel = "<root>";
  496. IProgramElement.Kind kind = IProgramElement.Kind.FILE_JAVA;
  497. if (buildConfig.getConfigFile() != null) {
  498. rootLabel = buildConfig.getConfigFile().getName();
  499. model.setConfigFile(buildConfig.getConfigFile().getAbsolutePath());
  500. kind = IProgramElement.Kind.FILE_LST;
  501. }
  502. model.setRoot(new ProgramElement(rootLabel, kind, new ArrayList()));
  503. model.setFileMap(new HashMap());
  504. setStructureModel(model);
  505. state.setStructureModel(model);
  506. state.setRelationshipMap(AsmManager.getDefault().getRelationshipMap());
  507. }
  508. //
  509. // private void dumplist(List l) {
  510. // System.err.println("---- "+l.size());
  511. // for (int i =0 ;i<l.size();i++) System.err.println(i+"\t "+l.get(i));
  512. // }
  513. // private void accumulateFileNodes(IProgramElement ipe,List store) {
  514. // if (ipe.getKind()==IProgramElement.Kind.FILE_JAVA ||
  515. // ipe.getKind()==IProgramElement.Kind.FILE_ASPECTJ) {
  516. // if (!ipe.getName().equals("<root>")) {
  517. // store.add(ipe);
  518. // return;
  519. // }
  520. // }
  521. // for (Iterator i = ipe.getChildren().iterator();i.hasNext();) {
  522. // accumulateFileNodes((IProgramElement)i.next(),store);
  523. // }
  524. // }
  525. /** init only on initial batch compile? no file-specific options */
  526. private void initBcelWorld(IMessageHandler handler) throws IOException {
  527. List cp = buildConfig.getBootclasspath();
  528. cp.addAll(buildConfig.getClasspath());
  529. BcelWorld bcelWorld = new BcelWorld(cp, handler, null);
  530. bcelWorld.setBehaveInJava5Way(buildConfig.getBehaveInJava5Way());
  531. bcelWorld.setXnoInline(buildConfig.isXnoInline());
  532. bcelWorld.setXlazyTjp(buildConfig.isXlazyTjp());
  533. bcelWorld.setXHasMemberSupportEnabled(buildConfig.isXHasMemberEnabled());
  534. bcelWorld.setPinpointMode(buildConfig.isXdevPinpoint());
  535. BcelWeaver bcelWeaver = new BcelWeaver(bcelWorld);
  536. state.setWorld(bcelWorld);
  537. state.setWeaver(bcelWeaver);
  538. state.binarySourceFiles = new HashMap();
  539. for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) {
  540. File f = (File) i.next();
  541. bcelWeaver.addLibraryJarFile(f);
  542. }
  543. // String lintMode = buildConfig.getLintMode();
  544. if (buildConfig.getLintMode().equals(AjBuildConfig.AJLINT_DEFAULT)) {
  545. bcelWorld.getLint().loadDefaultProperties();
  546. } else {
  547. bcelWorld.getLint().setAll(buildConfig.getLintMode());
  548. }
  549. if (buildConfig.getLintSpecFile() != null) {
  550. bcelWorld.getLint().setFromProperties(buildConfig.getLintSpecFile());
  551. }
  552. //??? incremental issues
  553. for (Iterator i = buildConfig.getInJars().iterator(); i.hasNext(); ) {
  554. File inJar = (File)i.next();
  555. List unwovenClasses = bcelWeaver.addJarFile(inJar, buildConfig.getOutputDir(),false);
  556. state.binarySourceFiles.put(inJar.getPath(), unwovenClasses);
  557. }
  558. for (Iterator i = buildConfig.getInpath().iterator(); i.hasNext(); ) {
  559. File inPathElement = (File)i.next();
  560. if (!inPathElement.isDirectory()) {
  561. // its a jar file on the inpath
  562. // the weaver method can actually handle dirs, but we don't call it, see next block
  563. List unwovenClasses = bcelWeaver.addJarFile(inPathElement,buildConfig.getOutputDir(),true);
  564. state.binarySourceFiles.put(inPathElement.getPath(),unwovenClasses);
  565. } else {
  566. // add each class file in an in-dir individually, this gives us the best error reporting
  567. // (they are like 'source' files then), and enables a cleaner incremental treatment of
  568. // class file changes in indirs.
  569. File[] binSrcs = FileUtil.listFiles(inPathElement, binarySourceFilter);
  570. for (int j = 0; j < binSrcs.length; j++) {
  571. UnwovenClassFile ucf =
  572. bcelWeaver.addClassFile(binSrcs[j], inPathElement, buildConfig.getOutputDir());
  573. List ucfl = new ArrayList();
  574. ucfl.add(ucf);
  575. state.binarySourceFiles.put(binSrcs[j].getPath(),ucfl);
  576. }
  577. }
  578. }
  579. bcelWeaver.setReweavableMode(buildConfig.isXNotReweavable());
  580. //check for org.aspectj.runtime.JoinPoint
  581. ResolvedType joinPoint = bcelWorld.resolve("org.aspectj.lang.JoinPoint");
  582. if (joinPoint.isMissing()) {
  583. IMessage message =
  584. new Message("classpath error: unable to find org.aspectj.lang.JoinPoint (check that aspectjrt.jar is in your classpath)",
  585. null,
  586. true);
  587. handler.handleMessage(message);
  588. }
  589. }
  590. public World getWorld() {
  591. return getBcelWorld();
  592. }
  593. void addAspectClassFilesToWeaver(List addedClassFiles) throws IOException {
  594. for (Iterator i = addedClassFiles.iterator(); i.hasNext(); ) {
  595. UnwovenClassFile classFile = (UnwovenClassFile) i.next();
  596. getWeaver().addClassFile(classFile);
  597. }
  598. }
  599. // public boolean weaveAndGenerateClassFiles() throws IOException {
  600. // handler.handleMessage(MessageUtil.info("weaving"));
  601. // if (progressListener != null) progressListener.setText("weaving aspects");
  602. // bcelWeaver.setProgressListener(progressListener, 0.5, 0.5/state.addedClassFiles.size());
  603. // //!!! doesn't provide intermediate progress during weaving
  604. // // XXX add all aspects even during incremental builds?
  605. // addAspectClassFilesToWeaver(state.addedClassFiles);
  606. // if (buildConfig.isNoWeave()) {
  607. // if (buildConfig.getOutputJar() != null) {
  608. // bcelWeaver.dumpUnwoven(buildConfig.getOutputJar());
  609. // } else {
  610. // bcelWeaver.dumpUnwoven();
  611. // bcelWeaver.dumpResourcesToOutPath();
  612. // }
  613. // } else {
  614. // if (buildConfig.getOutputJar() != null) {
  615. // bcelWeaver.weave(buildConfig.getOutputJar());
  616. // } else {
  617. // bcelWeaver.weave();
  618. // bcelWeaver.dumpResourcesToOutPath();
  619. // }
  620. // }
  621. // if (progressListener != null) progressListener.setProgress(1.0);
  622. // return true;
  623. // //return messageAdapter.getErrorCount() == 0; //!javaBuilder.notifier.anyErrors();
  624. // }
  625. public FileSystem getLibraryAccess(String[] classpaths, String[] filenames) {
  626. String defaultEncoding = buildConfig.getOptions().defaultEncoding;
  627. if ("".equals(defaultEncoding)) //$NON-NLS-1$
  628. defaultEncoding = null; //$NON-NLS-1$
  629. // Bug 46671: We need an array as long as the number of elements in the classpath - *even though* not every
  630. // element of the classpath is likely to be a directory. If we ensure every element of the array is set to
  631. // only look for BINARY, then we make sure that for any classpath element that is a directory, we won't build
  632. // a classpathDirectory object that will attempt to look for source when it can't find binary.
  633. int[] classpathModes = new int[classpaths.length];
  634. for (int i =0 ;i<classpaths.length;i++) classpathModes[i]=ClasspathDirectory.BINARY;
  635. return new FileSystem(classpaths, filenames, defaultEncoding,classpathModes);
  636. }
  637. public IProblemFactory getProblemFactory() {
  638. return new DefaultProblemFactory(Locale.getDefault());
  639. }
  640. /*
  641. * Build the set of compilation source units
  642. */
  643. public CompilationUnit[] getCompilationUnits(String[] filenames, String[] encodings) {
  644. int fileCount = filenames.length;
  645. CompilationUnit[] units = new CompilationUnit[fileCount];
  646. // HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
  647. String defaultEncoding = buildConfig.getOptions().defaultEncoding;
  648. if ("".equals(defaultEncoding)) //$NON-NLS-1$
  649. defaultEncoding = null; //$NON-NLS-1$
  650. for (int i = 0; i < fileCount; i++) {
  651. String encoding = encodings[i];
  652. if (encoding == null)
  653. encoding = defaultEncoding;
  654. units[i] = new CompilationUnit(null, filenames[i], encoding);
  655. }
  656. return units;
  657. }
  658. public String extractDestinationPathFromSourceFile(CompilationResult result) {
  659. ICompilationUnit compilationUnit = result.compilationUnit;
  660. if (compilationUnit != null) {
  661. char[] fileName = compilationUnit.getFileName();
  662. int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
  663. if (lastIndex == -1) {
  664. return System.getProperty("user.dir"); //$NON-NLS-1$
  665. }
  666. return new String(CharOperation.subarray(fileName, 0, lastIndex));
  667. }
  668. return System.getProperty("user.dir"); //$NON-NLS-1$
  669. }
  670. public void performCompilation(List files) {
  671. if (progressListener != null) {
  672. compiledCount=0;
  673. sourceFileCount = files.size();
  674. progressListener.setText("compiling source files");
  675. }
  676. //System.err.println("got files: " + files);
  677. String[] filenames = new String[files.size()];
  678. String[] encodings = new String[files.size()];
  679. //System.err.println("filename: " + this.filenames);
  680. for (int i=0; i < files.size(); i++) {
  681. filenames[i] = ((File)files.get(i)).getPath();
  682. }
  683. List cps = buildConfig.getFullClasspath();
  684. Dump.saveFullClasspath(cps);
  685. String[] classpaths = new String[cps.size()];
  686. for (int i=0; i < cps.size(); i++) {
  687. classpaths[i] = (String)cps.get(i);
  688. }
  689. //System.out.println("compiling");
  690. environment = getLibraryAccess(classpaths, filenames);
  691. if (!state.classesFromName.isEmpty()) {
  692. environment = new StatefulNameEnvironment(environment, state.classesFromName);
  693. }
  694. org.aspectj.ajdt.internal.compiler.CompilerAdapter.setCompilerAdapterFactory(this);
  695. org.aspectj.org.eclipse.jdt.internal.compiler.Compiler compiler =
  696. new org.aspectj.org.eclipse.jdt.internal.compiler.Compiler(environment,
  697. DefaultErrorHandlingPolicies.proceedWithAllProblems(),
  698. buildConfig.getOptions().getMap(),
  699. getBatchRequestor(),
  700. getProblemFactory());
  701. CompilerOptions options = compiler.options;
  702. options.produceReferenceInfo = true; //TODO turn off when not needed
  703. try {
  704. compiler.compile(getCompilationUnits(filenames, encodings));
  705. } catch (OperationCanceledException oce) {
  706. handler.handleMessage(new Message("build cancelled:"+oce.getMessage(),IMessage.WARNING,null,null));
  707. }
  708. // cleanup
  709. environment.cleanup();
  710. environment = null;
  711. }
  712. /*
  713. * Answer the component to which will be handed back compilation results from the compiler
  714. */
  715. public IIntermediateResultsRequestor getInterimResultRequestor() {
  716. return new IIntermediateResultsRequestor() {
  717. public void acceptResult(InterimCompilationResult result) {
  718. if (progressListener != null) {
  719. compiledCount++;
  720. progressListener.setProgress((compiledCount/2.0)/sourceFileCount);
  721. progressListener.setText("compiled: " + result.fileName());
  722. }
  723. state.noteResult(result);
  724. if (progressListener!=null && progressListener.isCancelledRequested()) {
  725. throw new AbortCompilation(true,
  726. new OperationCanceledException("Compilation cancelled as requested"));
  727. }
  728. }
  729. };
  730. }
  731. public ICompilerRequestor getBatchRequestor() {
  732. return new ICompilerRequestor() {
  733. public void acceptResult(CompilationResult unitResult) {
  734. // end of compile, must now write the results to the output destination
  735. // this is either a jar file or a file in a directory
  736. if (!(unitResult.hasErrors() && !proceedOnError())) {
  737. Collection classFiles = unitResult.compiledTypes.values();
  738. boolean shouldAddAspectName = (buildConfig.getOutxmlName() != null);
  739. for (Iterator iter = classFiles.iterator(); iter.hasNext();) {
  740. ClassFile classFile = (ClassFile) iter.next();
  741. String filename = new String(classFile.fileName());
  742. String classname = filename.replace('/', '.');
  743. filename = filename.replace('/', File.separatorChar) + ".class";
  744. try {
  745. if (buildConfig.getOutputJar() == null) {
  746. writeDirectoryEntry(unitResult, classFile,filename);
  747. } else {
  748. writeZipEntry(classFile,filename);
  749. }
  750. if (shouldAddAspectName) addAspectName(classname);
  751. } catch (IOException ex) {
  752. IMessage message = EclipseAdapterUtils.makeErrorMessage(
  753. new String(unitResult.fileName),
  754. CANT_WRITE_RESULT,
  755. ex);
  756. handler.handleMessage(message);
  757. }
  758. }
  759. }
  760. if (unitResult.hasProblems() || unitResult.hasTasks()) {
  761. IProblem[] problems = unitResult.getAllProblems();
  762. for (int i=0; i < problems.length; i++) {
  763. IMessage message =
  764. EclipseAdapterUtils.makeMessage(unitResult.compilationUnit, problems[i]);
  765. handler.handleMessage(message);
  766. }
  767. }
  768. }
  769. private void writeDirectoryEntry(
  770. CompilationResult unitResult,
  771. ClassFile classFile,
  772. String filename)
  773. throws IOException {
  774. File destinationPath = buildConfig.getOutputDir();
  775. String outFile;
  776. if (destinationPath == null) {
  777. outFile = new File(filename).getName();
  778. outFile = new File(extractDestinationPathFromSourceFile(unitResult), outFile).getPath();
  779. } else {
  780. outFile = new File(destinationPath, filename).getPath();
  781. }
  782. BufferedOutputStream os =
  783. FileUtil.makeOutputStream(new File(outFile));
  784. os.write(classFile.getBytes());
  785. os.close();
  786. }
  787. private void writeZipEntry(ClassFile classFile, String name)
  788. throws IOException {
  789. name = name.replace(File.separatorChar,'/');
  790. ZipEntry newEntry = new ZipEntry(name); //??? get compression scheme right
  791. zos.putNextEntry(newEntry);
  792. zos.write(classFile.getBytes());
  793. zos.closeEntry();
  794. }
  795. private void addAspectName (String name) {
  796. BcelWorld world = getBcelWorld();
  797. ResolvedType type = world.resolve(name);
  798. // System.err.println("? writeAspectName() type=" + type);
  799. if (type.isAspect()) {
  800. aspectNames.add(name);
  801. }
  802. }
  803. };
  804. }
  805. protected boolean proceedOnError() {
  806. return buildConfig.getProceedOnError();
  807. }
  808. // public void noteClassFiles(AjCompiler.InterimResult result) {
  809. // if (result == null) return;
  810. // CompilationResult unitResult = result.result;
  811. // String sourceFileName = result.fileName();
  812. // if (!(unitResult.hasErrors() && !proceedOnError())) {
  813. // List unwovenClassFiles = new ArrayList();
  814. // Enumeration classFiles = unitResult.compiledTypes.elements();
  815. // while (classFiles.hasMoreElements()) {
  816. // ClassFile classFile = (ClassFile) classFiles.nextElement();
  817. // String filename = new String(classFile.fileName());
  818. // filename = filename.replace('/', File.separatorChar) + ".class";
  819. //
  820. // File destinationPath = buildConfig.getOutputDir();
  821. // if (destinationPath == null) {
  822. // filename = new File(filename).getName();
  823. // filename = new File(extractDestinationPathFromSourceFile(unitResult), filename).getPath();
  824. // } else {
  825. // filename = new File(destinationPath, filename).getPath();
  826. // }
  827. //
  828. // //System.out.println("classfile: " + filename);
  829. // unwovenClassFiles.add(new UnwovenClassFile(filename, classFile.getBytes()));
  830. // }
  831. // state.noteClassesFromFile(unitResult, sourceFileName, unwovenClassFiles);
  832. //// System.out.println("file: " + sourceFileName);
  833. //// for (int i=0; i < unitResult.simpleNameReferences.length; i++) {
  834. //// System.out.println("simple: " + new String(unitResult.simpleNameReferences[i]));
  835. //// }
  836. //// for (int i=0; i < unitResult.qualifiedReferences.length; i++) {
  837. //// System.out.println("qualified: " +
  838. //// new String(CharOperation.concatWith(unitResult.qualifiedReferences[i], '/')));
  839. //// }
  840. // } else {
  841. // state.noteClassesFromFile(null, sourceFileName, Collections.EMPTY_LIST);
  842. // }
  843. // }
  844. //
  845. private void setBuildConfig(AjBuildConfig buildConfig) {
  846. this.buildConfig = buildConfig;
  847. handler.reset();
  848. }
  849. String makeClasspathString(AjBuildConfig buildConfig) {
  850. if (buildConfig == null || buildConfig.getFullClasspath() == null) return "";
  851. StringBuffer buf = new StringBuffer();
  852. boolean first = true;
  853. for (Iterator it = buildConfig.getFullClasspath().iterator(); it.hasNext(); ) {
  854. if (first) { first = false; }
  855. else { buf.append(File.pathSeparator); }
  856. buf.append(it.next().toString());
  857. }
  858. return buf.toString();
  859. }
  860. /**
  861. * This will return null if aspectjrt.jar is present and has the correct version.
  862. * Otherwise it will return a string message indicating the problem.
  863. */
  864. public String checkRtJar(AjBuildConfig buildConfig) {
  865. // omitting dev info
  866. if (Version.text.equals(Version.DEVELOPMENT)) {
  867. // in the development version we can't do this test usefully
  868. // MessageUtil.info(holder, "running development version of aspectj compiler");
  869. return null;
  870. }
  871. if (buildConfig == null || buildConfig.getFullClasspath() == null) return "no classpath specified";
  872. for (Iterator it = buildConfig.getFullClasspath().iterator(); it.hasNext(); ) {
  873. File p = new File( (String)it.next() );
  874. if (p.isFile() && p.getName().equals("aspectjrt.jar")) {
  875. try {
  876. String version = null;
  877. Manifest manifest = new JarFile(p).getManifest();
  878. if (manifest == null) {
  879. return "no manifest found in " + p.getAbsolutePath() +
  880. ", expected " + Version.text;
  881. }
  882. Attributes attr = manifest.getAttributes("org/aspectj/lang/");
  883. if (null != attr) {
  884. version = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
  885. if (null != version) {
  886. version = version.trim();
  887. }
  888. }
  889. // assume that users of development aspectjrt.jar know what they're doing
  890. if (Version.DEVELOPMENT.equals(version)) {
  891. // MessageUtil.info(holder,
  892. // "running with development version of aspectjrt.jar in " +
  893. // p.getAbsolutePath());
  894. return null;
  895. } else if (!Version.text.equals(version)) {
  896. return "bad version number found in " + p.getAbsolutePath() +
  897. " expected " + Version.text + " found " + version;
  898. }
  899. } catch (IOException ioe) {
  900. return "bad jar file found in " + p.getAbsolutePath() + " error: " + ioe;
  901. }
  902. return null;
  903. } else {
  904. // might want to catch other classpath errors
  905. }
  906. }
  907. return "couldn't find aspectjrt.jar on classpath, checked: " + makeClasspathString(buildConfig);
  908. }
  909. public String toString() {
  910. StringBuffer buf = new StringBuffer();
  911. buf.append("AjBuildManager(");
  912. buf.append(")");
  913. return buf.toString();
  914. }
  915. public void setStructureModel(IHierarchy structureModel) {
  916. this.structureModel = structureModel;
  917. }
  918. /**
  919. * Returns null if there is no structure model
  920. */
  921. public IHierarchy getStructureModel() {
  922. return structureModel;
  923. }
  924. public IProgressListener getProgressListener() {
  925. return progressListener;
  926. }
  927. public void setProgressListener(IProgressListener progressListener) {
  928. this.progressListener = progressListener;
  929. }
  930. /* (non-Javadoc)
  931. * @see org.aspectj.ajdt.internal.compiler.AjCompiler.IOutputClassFileNameProvider#getOutputClassFileName(char[])
  932. */
  933. public String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result) {
  934. String filename = new String(eclipseClassFileName);
  935. filename = filename.replace('/', File.separatorChar) + ".class";
  936. File destinationPath = buildConfig.getOutputDir();
  937. String outFile;
  938. if (destinationPath == null) {
  939. outFile = new File(filename).getName();
  940. outFile = new File(extractDestinationPathFromSourceFile(result), outFile).getPath();
  941. } else {
  942. outFile = new File(destinationPath, filename).getPath();
  943. }
  944. return outFile;
  945. }
  946. /* (non-Javadoc)
  947. * @see org.eclipse.jdt.internal.compiler.ICompilerAdapterFactory#getAdapter(org.eclipse.jdt.internal.compiler.Compiler)
  948. */
  949. public ICompilerAdapter getAdapter(org.aspectj.org.eclipse.jdt.internal.compiler.Compiler forCompiler) {
  950. // complete compiler config and return a suitable adapter...
  951. AjProblemReporter pr =
  952. new AjProblemReporter(DefaultErrorHandlingPolicies.proceedWithAllProblems(),
  953. forCompiler.options, getProblemFactory());
  954. forCompiler.problemReporter = pr;
  955. AjLookupEnvironment le =
  956. new AjLookupEnvironment(forCompiler, forCompiler.options, pr, environment);
  957. EclipseFactory factory = new EclipseFactory(le,this);
  958. le.factory = factory;
  959. pr.factory = factory;
  960. forCompiler.lookupEnvironment = le;
  961. forCompiler.parser =
  962. new Parser(
  963. pr,
  964. forCompiler.options.parseLiteralExpressionsAsConstants);
  965. return new AjCompilerAdapter(forCompiler,batchCompile,getBcelWorld(),getWeaver(),
  966. factory,
  967. getInterimResultRequestor(),
  968. progressListener,
  969. this, // IOutputFilenameProvider
  970. this, // IBinarySourceProvider
  971. state.binarySourceFiles,
  972. state.resultsFromFile.values(),
  973. buildConfig.isNoWeave(),
  974. buildConfig.getProceedOnError(),
  975. buildConfig.isNoAtAspectJAnnotationProcessing());
  976. }
  977. /* (non-Javadoc)
  978. * @see org.aspectj.ajdt.internal.compiler.IBinarySourceProvider#getBinarySourcesForThisWeave()
  979. */
  980. public Map getBinarySourcesForThisWeave() {
  981. return binarySourcesForTheNextCompile;
  982. }
  983. public static AsmHierarchyBuilder getAsmHierarchyBuilder() {
  984. return asmHierarchyBuilder;
  985. }
  986. /**
  987. * Override the the default hierarchy builder.
  988. */
  989. public static void setAsmHierarchyBuilder(AsmHierarchyBuilder newBuilder) {
  990. asmHierarchyBuilder = newBuilder;
  991. }
  992. public AjState getState() {
  993. return state;
  994. }
  995. public void setState(AjState buildState) {
  996. state = buildState;
  997. }
  998. private static class AjBuildContexFormatter implements ContextFormatter {
  999. public String formatEntry(int phaseId, Object data) {
  1000. StringBuffer sb = new StringBuffer();
  1001. if (phaseId == CompilationAndWeavingContext.BATCH_BUILD) {
  1002. sb.append("batch building ");
  1003. } else {
  1004. sb.append("incrementally building ");
  1005. }
  1006. AjBuildConfig config = (AjBuildConfig) data;
  1007. List classpath = config.getClasspath();
  1008. sb.append("with classpath: ");
  1009. for (Iterator iter = classpath.iterator(); iter.hasNext();) {
  1010. sb.append(iter.next().toString());
  1011. sb.append(File.pathSeparator);
  1012. }
  1013. return sb.toString();
  1014. }
  1015. }
  1016. }