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 48KB

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