Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

AjBuildManager.java 53KB

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