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.

AntBuilder.java 27KB

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  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. * Xerox/PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.internal.tools.ant.taskdefs;
  13. import java.io.File;
  14. import java.io.FileWriter;
  15. import java.io.IOException;
  16. import java.lang.reflect.Method;
  17. import java.net.URL;
  18. import java.net.URLClassLoader;
  19. import java.util.ArrayList;
  20. import java.util.Arrays;
  21. import java.util.Collection;
  22. import java.util.HashMap;
  23. import java.util.Hashtable;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Map;
  27. import org.apache.tools.ant.BuildException;
  28. import org.apache.tools.ant.Project;
  29. import org.apache.tools.ant.Target;
  30. import org.apache.tools.ant.Task;
  31. import org.apache.tools.ant.taskdefs.Copy;
  32. import org.apache.tools.ant.taskdefs.Javac;
  33. import org.apache.tools.ant.taskdefs.Zip;
  34. import org.apache.tools.ant.types.FileSet;
  35. import org.apache.tools.ant.types.Path;
  36. import org.apache.tools.ant.types.ZipFileSet;
  37. import org.aspectj.internal.tools.build.BuildSpec;
  38. import org.aspectj.internal.tools.build.Builder;
  39. import org.aspectj.internal.tools.build.Messager;
  40. import org.aspectj.internal.tools.build.Module;
  41. import org.aspectj.internal.tools.build.Result;
  42. import org.aspectj.internal.tools.build.Util;
  43. /**
  44. * Implement Builder in Ant.
  45. */
  46. public class AntBuilder extends Builder {
  47. private static final boolean FORCE_FORK_FOR_LIBRARIES = false;
  48. /**
  49. * Factory for a Builder.
  50. *
  51. * @param config the String configuration, where only substrings "verbose" and "useEclipseCompiles" are significant
  52. * @param project the owning Project for all tasks (not null)
  53. * @param tempDir the File path to a temporary dir for side effects (may be null)
  54. * @return a Builder for this project and configuration
  55. */
  56. public static Builder getBuilder(String config, Project project, File tempDir) {
  57. boolean useEclipseCompiles = false;
  58. boolean verbose = false;
  59. if (null != config) {
  60. if (-1 != config.indexOf("useEclipseCompiles")) {
  61. useEclipseCompiles = true;
  62. }
  63. if (-1 != config.indexOf("verbose")) {
  64. verbose = true;
  65. }
  66. }
  67. // Messager handler = new Messager(); // debugging
  68. Messager handler = new ProjectMessager(project);
  69. Builder result = new ProductBuilder(project, tempDir, useEclipseCompiles, handler);
  70. if (verbose) {
  71. result.setVerbose(true);
  72. }
  73. return result;
  74. }
  75. private static String resultToTargetName(Result result) {
  76. return result.getName();
  77. }
  78. /**
  79. * Ensure targets exist for this module and all antecedants, so topoSort can work.
  80. */
  81. private static void makeTargetsForResult(final Result result, final Hashtable<String,Target> targets) {
  82. final String resultTargetName = resultToTargetName(result);
  83. Target target = targets.get(resultTargetName);
  84. if (null == target) {
  85. // first add the target
  86. target = new Target();
  87. target.setName(resultTargetName);
  88. Result[] reqs = result.getRequired();
  89. StringBuffer depends = new StringBuffer();
  90. boolean first = true;
  91. for (int i = 0; i < reqs.length; i++) {
  92. Result reqResult = reqs[i];
  93. if (!first) {
  94. depends.append(",");
  95. } else {
  96. first = false;
  97. }
  98. depends.append(resultToTargetName(reqResult));
  99. }
  100. if (0 < depends.length()) {
  101. target.setDepends(depends.toString());
  102. }
  103. targets.put(resultTargetName, target);
  104. // then recursively add any required results
  105. for (int i = 0; i < reqs.length; i++) {
  106. Result reqResult = reqs[i];
  107. makeTargetsForResult(reqResult, targets);
  108. }
  109. }
  110. }
  111. private final Project project;
  112. protected AntBuilder(Project project, File tempDir, boolean useEclipseCompiles, Messager handler) {
  113. super(tempDir, useEclipseCompiles, handler);
  114. this.project = project;
  115. Util.iaxIfNull(project, "project");
  116. }
  117. /**
  118. * Initialize task with project and "ajbuild-" + name as name. (Using bm- prefix distinguishes these tasks from tasks found in
  119. * the build script.)
  120. *
  121. * @param task the Task to initialize - not null
  122. * @param name the String name suffix for the task
  123. * @return true unless some error
  124. */
  125. protected boolean setupTask(Task task, String name) {
  126. task.setProject(project);
  127. task.setTaskName("ajbuild-" + name);
  128. return true;
  129. }
  130. /**
  131. * Copy file, optionally filtering. (Filters set in project.)
  132. *
  133. * @param fromFile the readable File source to copy
  134. * @param toFile the writable File destination file
  135. * @param boolean filter if true, enable filtering
  136. * @see org.aspectj.internal.tools.build.Builder#copyFile(File, File, boolean)
  137. */
  138. @Override
  139. protected boolean copyFile(File fromFile, File toFile, boolean filter) {
  140. Copy copy = makeCopyTask(filter);
  141. copy.setFile(fromFile);
  142. copy.setTofile(toFile);
  143. executeTask(copy);
  144. return true;
  145. }
  146. /**
  147. * (Filters set in project.)
  148. *
  149. * @see org.aspectj.internal.tools.ant.taskdefs.Builder#copyFiles(File, File, String, String, boolean)
  150. */
  151. @Override
  152. protected boolean copyFiles(File fromDir, File toDir, String includes, String excludes, boolean filter) {
  153. Copy copy = makeCopyTask(filter);
  154. copy.setTodir(toDir);
  155. FileSet fileset = new FileSet();
  156. fileset.setDir(fromDir);
  157. if (null != includes) {
  158. fileset.setIncludes(includes);
  159. }
  160. if (null != excludes) {
  161. fileset.setExcludes(excludes);
  162. }
  163. copy.addFileset(fileset);
  164. executeTask(copy);
  165. return false;
  166. }
  167. protected void copyFileset(File toDir, FileSet fileSet, boolean filter) {
  168. Copy copy = makeCopyTask(filter);
  169. copy.addFileset(fileSet);
  170. copy.setTodir(toDir);
  171. executeTask(copy);
  172. }
  173. /**
  174. * @param filter if FILTER_ON, use filters
  175. */
  176. protected Copy makeCopyTask(boolean filter) {
  177. Copy copy = new Copy();
  178. setupTask(copy, "copy");
  179. if (FILTER_ON == filter) {
  180. copy.setFiltering(true);
  181. }
  182. return copy;
  183. }
  184. protected void dumpMinFile(Result result, File classesDir, List<String> errors) {
  185. String name = result.getName() + "-empty";
  186. File minFile = new File(classesDir, name);
  187. FileWriter fw = null;
  188. try {
  189. fw = new FileWriter(minFile);
  190. fw.write(name);
  191. } catch (IOException e) {
  192. errors.add("IOException writing " + name + " to " + minFile + ": " + Util.renderException(e));
  193. } finally {
  194. Util.close(fw);
  195. }
  196. }
  197. @Override
  198. protected boolean compile(Result result, File classesDir, boolean useExistingClasses, List<String> errors) {
  199. if (!classesDir.exists() && !classesDir.mkdirs()) {
  200. errors.add("compile - unable to create " + classesDir);
  201. return false;
  202. }
  203. if (useExistingClasses) {
  204. return true;
  205. }
  206. // -- source paths
  207. Path path = new Path(project);
  208. boolean hasSourceDirectories = false;
  209. boolean isJava5Compile = false;
  210. boolean isJava8Compile = false;
  211. for (File file: result.getSrcDirs()) {
  212. path.createPathElement().setLocation(file);
  213. if (!isJava5Compile
  214. && (Util.Constants.JAVA5_SRC.equals(file.getName()) ||
  215. Util.Constants.JAVA5_TESTSRC.equals(file.getName()) ||
  216. new File(file.getParent(), ".isJava5").exists())) {
  217. isJava5Compile = true;
  218. }
  219. if (new File(file.getParent(),".isJava8").exists()) {
  220. isJava8Compile = true;
  221. }
  222. if (!hasSourceDirectories) {
  223. hasSourceDirectories = true;
  224. }
  225. }
  226. if (!hasSourceDirectories) {
  227. return true; // nothing to compile - ok
  228. }
  229. // XXX test whether build.compiler property takes effect automatically
  230. // I suspect it requires the proper adapter setup.
  231. Javac javac = new Javac();
  232. setupTask(javac, "javac");
  233. javac.setIncludeantruntime(false);
  234. javac.setDestdir(classesDir);
  235. javac.setSrcdir(path);
  236. javac.setVerbose(verbose);
  237. path = null;
  238. // -- classpath
  239. Path classpath = new Path(project);
  240. boolean hasLibraries = setupClasspath(result, classpath);
  241. if (hasLibraries && FORCE_FORK_FOR_LIBRARIES) {
  242. javac.setFork(true); // otherwise never releases library jars
  243. // can we build under 1.4, but fork javac 1.5 compile?
  244. }
  245. // also fork if using 1.5?
  246. // -- set output directory
  247. classpath.createPathElement().setLocation(classesDir);
  248. javac.setClasspath(classpath);
  249. // misc
  250. javac.setDebug(true);
  251. if (isJava8Compile) {
  252. javac.setSource("1.8");
  253. javac.setTarget("1.8");
  254. } else if (isJava5Compile) {
  255. // *cough*
  256. javac.setSource("1.6");
  257. javac.setTarget("1.6");
  258. } else {
  259. javac.setTarget("1.1"); // 1.1 class files - Javac in 1.4 uses 1.4
  260. javac.setSource("1.3");
  261. }
  262. // compile
  263. boolean passed = false;
  264. BuildException failure = null;
  265. try {
  266. passed = executeTask(AspectJSupport.wrapIfNeeded(result, javac));
  267. } catch (BuildException e) {
  268. failure = e;
  269. } catch (Error e) {
  270. failure = new BuildException(e);
  271. } catch (RuntimeException e) {
  272. failure = new BuildException(e);
  273. } finally {
  274. if (!passed) {
  275. String args = "" + Arrays.asList(javac.getCurrentCompilerArgs());
  276. if ("[]".equals(args)) {
  277. args = "{" + result.toLongString() + "}";
  278. }
  279. String m = "BuildException compiling " + result.toLongString() + args
  280. + (null == failure ? "" : ": " + Util.renderException(failure));
  281. // debuglog System.err.println(m);
  282. errors.add(m);
  283. }
  284. javac.init(); // be nice to let go of classpath libraries...
  285. }
  286. return passed;
  287. }
  288. public boolean setupClasspath(Result result, Path classpath) { // XXX fix test access
  289. boolean hasLibraries = false;
  290. // required libraries
  291. for (Iterator iter = result.getLibJars().iterator(); iter.hasNext();) {
  292. File file = (File) iter.next();
  293. classpath.createPathElement().setLocation(file);
  294. if (!hasLibraries) {
  295. hasLibraries = true;
  296. }
  297. }
  298. // Westodo Kind kind = result.getKind();
  299. Result[] reqs = result.getRequired();
  300. // required modules and their exported libraries
  301. for (int i = 0; i < reqs.length; i++) {
  302. Result requiredResult = reqs[i];
  303. classpath.createPathElement().setLocation(requiredResult.getOutputFile());
  304. if (!hasLibraries) {
  305. hasLibraries = true;
  306. }
  307. // also put on classpath libraries exported from required module
  308. // XXX exported modules not supported
  309. for (Iterator iterator = requiredResult.getExportedLibJars().iterator(); iterator.hasNext();) {
  310. classpath.createPathElement().setLocation((File) iterator.next());
  311. }
  312. }
  313. return hasLibraries;
  314. }
  315. /**
  316. * Merge classes directory and any merge jars into module jar with any specified manifest file. META-INF directories are
  317. * excluded.
  318. */
  319. @Override
  320. protected boolean assemble(Result result, File classesDir, List<String> errors) {
  321. if (!buildingEnabled) {
  322. return false;
  323. }
  324. if (!result.outOfDate()) {
  325. return true;
  326. }
  327. // ---- zip result up
  328. Zip zip = new Zip();
  329. setupTask(zip, "zip");
  330. zip.setDestFile(result.getOutputFile());
  331. ZipFileSet zipfileset = null;
  332. // -- merge any resources in any of the src directories
  333. for (Iterator iter = result.getSrcDirs().iterator(); iter.hasNext();) {
  334. File srcDir = (File) iter.next();
  335. zipfileset = new ZipFileSet();
  336. zipfileset.setProject(project);
  337. zipfileset.setDir(srcDir);
  338. zipfileset.setIncludes(RESOURCE_PATTERN);
  339. zip.addZipfileset(zipfileset);
  340. }
  341. final Module module = result.getModule();
  342. File metaInfDir = new File(classesDir, "META-INF");
  343. Util.deleteContents(metaInfDir);
  344. // -- manifest
  345. File manifest = new File(module.moduleDir, module.name + ".mf.txt"); // XXXFileLiteral
  346. if (Util.canReadFile(manifest)) {
  347. if (Util.canReadDir(metaInfDir) || metaInfDir.mkdirs()) {
  348. // Jar spec requires a MANIFEST.MF not a manifest.mf
  349. copyFile(manifest, new File(metaInfDir, "MANIFEST.MF"), FILTER_ON); // XXXFileLiteral
  350. } else {
  351. errors.add("have manifest, but unable to create " + metaInfDir);
  352. return false;
  353. }
  354. }
  355. zipfileset = new ZipFileSet();
  356. zipfileset.setProject(project);
  357. zipfileset.setDir(classesDir);
  358. zipfileset.setIncludes("**/*");
  359. zip.addZipfileset(zipfileset);
  360. File[] contents = classesDir.listFiles();
  361. if ((null == contents) || (0 == contents.length)) {
  362. // *something* to zip up
  363. dumpMinFile(result, classesDir, errors);
  364. }
  365. try {
  366. handler.log("assemble " + module + " in " + result.getOutputFile());
  367. return executeTask(zip)
  368. // zip returns true when it doesn't create zipfile
  369. // because there are no entries to add, so verify done
  370. && Util.canReadFile(result.getOutputFile());
  371. } catch (BuildException e) {
  372. errors.add("BuildException zipping " + module + ": " + e.getMessage());
  373. return false;
  374. } finally {
  375. result.clearOutOfDate();
  376. }
  377. }
  378. /**
  379. * @see org.aspectj.internal.tools.build.Builder#buildAntecedants(Module)
  380. */
  381. @Override
  382. protected Result[] getAntecedantResults(Result moduleResult) {
  383. Hashtable<String,Target> targets = new Hashtable<String, Target>();
  384. makeTargetsForResult(moduleResult, targets);
  385. String targetName = resultToTargetName(moduleResult);
  386. // bug: doc says topoSort returns String, but returns Target
  387. Collection<Target> result = project.topoSort(targetName, targets);
  388. // fyi, we don't rely on topoSort to detect cycles - see buildAll
  389. int size = result.size();
  390. if (0 == result.size()) {
  391. return new Result[0];
  392. }
  393. ArrayList<String> toReturn = new ArrayList<String>();
  394. for (Iterator<Target> iter = result.iterator(); iter.hasNext();) {
  395. Target target = iter.next();
  396. String name = target.getName();
  397. if (null == name) {
  398. throw new Error("null name?");
  399. } else {
  400. toReturn.add(name);
  401. }
  402. }
  403. // topoSort always returns target name
  404. if ((1 == size) && targetName.equals(toReturn.get(0)) && !moduleResult.outOfDate()) {
  405. return new Result[0];
  406. }
  407. return Result.getResults(toReturn.toArray(new String[0]));
  408. }
  409. /**
  410. * Generate Module.assembledJar with merge of itself and all antecedants
  411. */
  412. @Override
  413. protected boolean assembleAll(Result result, Messager handler) {
  414. if (!buildingEnabled) {
  415. return false;
  416. }
  417. if (!result.outOfDate()) {
  418. return true;
  419. }
  420. Util.iaxIfNull(result, "result");
  421. Util.iaxIfNull(handler, "handler");
  422. if (!result.getKind().isAssembly()) {
  423. throw new IllegalStateException("not assembly: " + result);
  424. }
  425. // ---- zip result up
  426. Zip zip = new Zip();
  427. setupTask(zip, "zip");
  428. zip.setDestFile(result.getOutputFile());
  429. ZipFileSet zipfileset = null;
  430. final Module module = result.getModule();
  431. List<File> known = result.findJarRequirements();
  432. removeLibraryFilesToSkip(module, known);
  433. // -- merge any antecedents, less any manifest
  434. for (File jarFile: known) {
  435. zipfileset = new ZipFileSet();
  436. zipfileset.setProject(project);
  437. zipfileset.setSrc(jarFile);
  438. zipfileset.setIncludes("**/*");
  439. String name = jarFile.getName();
  440. name = name.substring(0, name.length() - 4); // ".jar".length()
  441. // required includes self - exclude manifest from others
  442. if (!module.name.equals(name)) {
  443. zipfileset.setExcludes("META-INF/MANIFEST.MF"); // XXXFileLiteral
  444. zipfileset.setExcludes("META-INF/manifest.mf");
  445. zipfileset.setExcludes("meta-inf/manifest.mf");
  446. zipfileset.setExcludes("meta-inf/MANIFEST.MF");
  447. }
  448. zip.addZipfileset(zipfileset);
  449. }
  450. try {
  451. handler.log("assembling all " + module + " in " + result.getOutputFile());
  452. if (verbose) {
  453. handler.log("knownAntecedants: " + known);
  454. }
  455. return executeTask(zip);
  456. } catch (BuildException e) {
  457. handler.logException("BuildException zipping " + module, e);
  458. return false;
  459. } finally {
  460. result.clearOutOfDate();
  461. }
  462. }
  463. /**
  464. * @see org.aspectj.internal.tools.ant.taskdefs.Builder#buildInstaller(BuildSpec, String)
  465. */
  466. @Override
  467. protected boolean buildInstaller(BuildSpec buildSpec, String targDirPath) {
  468. return false;
  469. }
  470. /** task.execute() and any advice */
  471. protected boolean executeTask(Task task) {
  472. if (!buildingEnabled) {
  473. return false;
  474. }
  475. task.execute();
  476. return true;
  477. }
  478. /**
  479. * Support for compiling basic AspectJ projects. Projects may only compile all (and only) their source directories; aspectpath,
  480. * inpath, etc. are not supported. To load the compiler, this assumes the user has either defined a project property
  481. * "aspectj.home" or that there exists <code>{module-dir}/lib/aspectj/lib/aspectj[tools|rt].jar</code>.
  482. */
  483. static class AspectJSupport {
  484. static final String AJCTASK = "org.aspectj.tools.ant.taskdefs.AjcTask";
  485. static final String ASPECTJRT_JAR_VARIABLE = "ASPECTJRT_LIB";
  486. static final String LIBASPECTJ_RPATH = "/lib/aspectj";
  487. static final Map nameToAspectjrtjar = new HashMap();
  488. static final String NONE = "NONE";
  489. /**
  490. * If this module should be compiled with AspectJ, return a task to do so.
  491. *
  492. * @param module the Module to compile
  493. * @param javac the Javac compile commands
  494. * @return javac or a Task to compile with AspectJ if needed
  495. */
  496. static Task wrapIfNeeded(Result result, Javac javac) {
  497. final Project project = javac.getProject();
  498. Path runtimeJar = null;
  499. final Module module = result.getModule();
  500. if (runtimeJarOnClasspath(result)) {
  501. // yes aspectjrt.jar on classpath
  502. } else if (result.getClasspathVariables().contains(ASPECTJRT_JAR_VARIABLE)) {
  503. // yes, in variables - find aspectjrt.jar to add to classpath
  504. runtimeJar = getAspectJLib(project, module, "aspectjrt.jar");
  505. } else {
  506. // no
  507. // System.out.println("javac " + result + " " + javac.getClasspath());
  508. return javac;
  509. }
  510. // System.out.println("aspectj " + result + " " + javac.getClasspath());
  511. Path aspectjtoolsJar = getAspectJLib(project, module, "aspectjtools.jar");
  512. return aspectJTask(javac, aspectjtoolsJar, runtimeJar);
  513. }
  514. /** @return true if aspectjrt.jar is on classpath */
  515. private static boolean runtimeJarOnClasspath(Result result) {
  516. for (File file: result.getLibJars()) {
  517. if ("aspectjrt.jar".equals(file.getName())) {
  518. return true;
  519. }
  520. }
  521. return false;
  522. }
  523. static Path getAspectJLib(Project project, Module module, String name) {
  524. Path result = null;
  525. String[] libDirNames = { "aspectj.home", "ASPECTJ_HOME", LIBASPECTJ_RPATH };
  526. String[] libDirs = new String[libDirNames.length];
  527. for (int i = 0; i < libDirNames.length; i++) {
  528. if (LIBASPECTJ_RPATH == libDirNames[i]) {
  529. libDirs[i] = module.getFullPath(LIBASPECTJ_RPATH);
  530. } else {
  531. libDirs[i] = project.getProperty(libDirNames[i]);
  532. }
  533. if (null != libDirs[i]) {
  534. libDirs[i] = Util.path(libDirs[i], "lib");
  535. result = new Path(project, Util.path(libDirs[i], name));
  536. String path = result.toString();
  537. if (new File(path).canRead()) {
  538. return result;
  539. }
  540. }
  541. }
  542. String m = "unable to find " + name + " in " + Arrays.asList(libDirs);
  543. throw new BuildException(m);
  544. }
  545. /**
  546. * Wrap AspectJ compiler as Task. Only works for javac-like source compilation of everything under srcDir. Written
  547. * reflectively to compile in the build module, which can't depend on the whole tree.
  548. *
  549. * @param javac the Javac specification
  550. * @param toolsJar the Path to the aspectjtools.jar
  551. * @param runtimeJar the Path to the aspectjrt.jar
  552. * @return javac or another Task invoking the AspectJ compiler
  553. */
  554. @SuppressWarnings("unchecked")
  555. static Task aspectJTask(Javac javac, Path toolsJar, Path runtimeJar) {
  556. Object task = null;
  557. String url = null;
  558. try {
  559. url = "file:" + toolsJar.toString().replace('\\', '/');
  560. URL[] cp = new URL[] { new URL(url) };
  561. ClassLoader parent = Task.class.getClassLoader();
  562. ClassLoader loader = new URLClassLoader(cp, parent);
  563. Class c = loader.loadClass(AJCTASK);
  564. task = c.newInstance();
  565. // Westodo Project project = javac.getProject();
  566. Method m = c.getMethod("setupAjc", new Class[] { Javac.class });
  567. m.invoke(task, new Object[] { javac });
  568. m = c.getMethod("setFork", new Class[] { boolean.class });
  569. m.invoke(task, new Object[] { Boolean.TRUE });
  570. m = c.getMethod("setForkclasspath", new Class[] { Path.class });
  571. m.invoke(task, new Object[] { toolsJar });
  572. m = c.getMethod("setSourceRoots", new Class[] { Path.class });
  573. m.invoke(task, new Object[] { javac.getSrcdir() });
  574. if (null != runtimeJar) {
  575. m = c.getMethod("setClasspath", new Class[] { Path.class });
  576. m.invoke(task, new Object[] { runtimeJar });
  577. }
  578. } catch (BuildException e) {
  579. throw e;
  580. } catch (Throwable t) {
  581. StringBuffer sb = new StringBuffer();
  582. sb.append("classpath=");
  583. sb.append(url);
  584. throw new BuildException(sb.toString(), t);
  585. }
  586. return (Task) task;
  587. }
  588. private AspectJSupport() {
  589. throw new Error("no instances");
  590. }
  591. }
  592. }
  593. // finally caught by failing to comply with proper ant initialization
  594. // /**
  595. // * Build a module that has a build script.
  596. // * @param buildSpec the module to build
  597. // * @param buildScript the script file
  598. // * @throws BuildException if build fails
  599. // */
  600. // private void buildByScript(BuildSpec buildSpec, File buildScript)
  601. // throws BuildException {
  602. // Ant ant = new Ant();
  603. // ant.setProject(getProject());
  604. // ant.setAntfile(buildScript.getAbsolutePath());
  605. // ant.setDescription("building module " + buildSpec.module);
  606. // ant.setDir(buildScript.getParentFile());
  607. // ant.setInheritAll(true);
  608. // ant.setInheritRefs(false);
  609. // ant.setLocation(getLocation());
  610. // ant.setOwningTarget(getOwningTarget());
  611. // // by convention, for build.xml, use module name to publish
  612. // ant.setTarget(buildSpec.module);
  613. // ant.setTaskName("ant");
  614. // loadAntProperties(ant, buildSpec);
  615. // ant.execute();
  616. // }
  617. //
  618. // /** override definitions */
  619. // private void loadAntProperties(Ant ant, BuildSpec buildSpec) {
  620. // Property property = ant.createProperty();
  621. // property.setName(BuildSpec.baseDir_NAME);
  622. // property.setFile(buildSpec.baseDir);
  623. // property = ant.createProperty();
  624. // property.setName(buildSpec.distDir_NAME);
  625. // property.setFile(buildSpec.distDir);
  626. // property = ant.createProperty();
  627. // property.setName(BuildSpec.tempDir_NAME);
  628. // property.setFile(buildSpec.tempDir);
  629. // property = ant.createProperty();
  630. // property.setName(BuildSpec.jarDir_NAME);
  631. // property.setFile(buildSpec.jarDir);
  632. // property = ant.createProperty();
  633. // property.setName(BuildSpec.stagingDir_NAME);
  634. // property.setFile(buildSpec.stagingDir);
  635. // }
  636. /**
  637. * Segregate product-building API's from module-building APIs for clarity. These are called by the superclass if the BuildSpec
  638. * warrants. XXX extremely brittle/arbitrary assumptions.
  639. *
  640. * @see BuildModule for assumptions
  641. */
  642. class ProductBuilder extends AntBuilder {
  643. private static String getProductInstallResourcesSrc(BuildSpec buildSpec) {
  644. final String resourcesName = "installer-resources"; // XXXFileLiteral
  645. File dir = buildSpec.productDir.getParentFile();
  646. if (null == dir) {
  647. return Util.path(new String[] { "..", "..", resourcesName });
  648. }
  649. dir = dir.getParentFile();
  650. if (null == dir) {
  651. return Util.path("..", resourcesName);
  652. } else {
  653. dir = new File(dir, resourcesName);
  654. return dir.getPath();
  655. }
  656. }
  657. private static String getProductInstallerFileName(BuildSpec buildSpec) { // XXXFileLiteral
  658. return "aspectj-" + buildSpec.productDir.getName() + "-" + Util.shortVersion(buildSpec.version) + ".jar";
  659. }
  660. /**
  661. * Calculate name of main, typically InitialCap, and hence installer class.
  662. *
  663. * @return $$installer$$.org.aspectj." + ProductName + "Installer"
  664. */
  665. private static String getProductInstallerMainClass(BuildSpec buildSpec) {
  666. String productName = buildSpec.productDir.getName();
  667. String initial = productName.substring(0, 1).toUpperCase();
  668. productName = initial + productName.substring(1);
  669. return "$installer$.org.aspectj." + productName + "Installer"; // XXXNameLiteral
  670. }
  671. /** @see Builder.getBuilder(String, Project, File) */
  672. ProductBuilder(Project project, File tempDir, boolean useEclipseCompiles, Messager handler) {
  673. super(project, tempDir, useEclipseCompiles, handler);
  674. }
  675. /**
  676. * Delegate for super.buildProduct(..) template method.
  677. */
  678. @Override
  679. protected boolean copyBinaries(BuildSpec buildSpec, File distDir, File targDir, String excludes) {
  680. Copy copy = makeCopyTask(false);
  681. copy.setTodir(targDir);
  682. FileSet fileset = new FileSet();
  683. fileset.setDir(distDir);
  684. fileset.setIncludes(Builder.BINARY_SOURCE_PATTERN);
  685. if (null != excludes) {
  686. fileset.setExcludes(excludes);
  687. }
  688. copy.addFileset(fileset);
  689. return executeTask(copy);
  690. }
  691. /**
  692. * Delegate for super.buildProduct(..) template method.
  693. */
  694. @Override
  695. protected boolean copyNonBinaries(BuildSpec buildSpec, File distDir, File targDir) {
  696. // filter-copy everything but the binaries
  697. Copy copy = makeCopyTask(true);
  698. copy.setTodir(targDir);
  699. Util.iaxIfNotCanReadDir(distDir, "product dist directory");
  700. FileSet fileset = new FileSet();
  701. fileset.setDir(distDir);
  702. fileset.setExcludes(Builder.BINARY_SOURCE_PATTERN);
  703. copy.addFileset(fileset);
  704. return executeTask(copy);
  705. }
  706. @Override
  707. protected boolean buildInstaller(BuildSpec buildSpec, String targDirPath) {
  708. if (buildSpec.verbose) {
  709. handler.log("creating installer for " + buildSpec);
  710. }
  711. AJInstaller installer = new AJInstaller();
  712. setupTask(installer, "installer");
  713. installer.setBasedir(targDirPath);
  714. // installer.setCompress();
  715. File installSrcDir = new File(buildSpec.productDir, "install"); // XXXFileLiteral
  716. Util.iaxIfNotCanReadDir(installSrcDir, "installSrcDir");
  717. installer.setHtmlSrc(installSrcDir.getPath());
  718. String resourcePath = getProductInstallResourcesSrc(buildSpec);
  719. File resourceSrcDir = new File(resourcePath);
  720. Util.iaxIfNotCanReadDir(resourceSrcDir, "resourceSrcDir");
  721. installer.setResourcesSrc(resourcePath);
  722. String name = getProductInstallerFileName(buildSpec);
  723. File outFile = new File(buildSpec.jarDir, name);
  724. installer.setZipfile(outFile.getPath());
  725. installer.setMainclass(getProductInstallerMainClass(buildSpec));
  726. installer.setInstallerclassjar(getBuildJar(buildSpec));
  727. return executeTask(installer);
  728. // -- test installer XXX
  729. // create text setup file
  730. // run installer with setup file
  731. // cleanup installed product
  732. }
  733. private String getBuildJar(BuildSpec buildSpec) {
  734. return buildSpec.baseDir.getPath() + "/lib/build/build.jar"; // XXX
  735. }
  736. // private Module moduleForReplaceFile(File replaceFile, Modules modules) {
  737. // String jarName = moduleAliasFor(replaceFile.getName().toLowerCase());
  738. // if (jarName.endsWith(".jar") || jarName.endsWith(".zip")) { // XXXFileLiteral
  739. // jarName = jarName.substring(0, jarName.length()-4);
  740. // } else {
  741. // throw new IllegalArgumentException("can only replace .[jar|zip]");
  742. // }
  743. // boolean assembleAll = jarName.endsWith("-all");
  744. // String name = (!assembleAll ? jarName : jarName.substring(0, jarName.length()-4));
  745. // return modules.getModule(name);
  746. // }
  747. //
  748. }
  749. class ProjectMessager extends Messager {
  750. private final Project project;
  751. public ProjectMessager(Project project) {
  752. Util.iaxIfNull(project, "project");
  753. this.project = project;
  754. }
  755. @Override
  756. public boolean log(String s) {
  757. project.log(s);
  758. return true;
  759. }
  760. @Override
  761. public boolean error(String s) {
  762. project.log(s, Project.MSG_ERR);
  763. return true;
  764. }
  765. @Override
  766. public boolean logException(String context, Throwable thrown) {
  767. project.log(context + Util.renderException(thrown), Project.MSG_ERR);
  768. return true;
  769. }
  770. }