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.

AjcTask.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /* *******************************************************************
  2. * Copyright (c) 2001-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC).
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Common Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/cpl-v10.html
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.tools.ant.taskdefs;
  14. import java.io.File;
  15. import java.util.ArrayList;
  16. import java.util.Arrays;
  17. import java.util.Collections;
  18. import java.util.Iterator;
  19. import java.util.List;
  20. import java.util.StringTokenizer;
  21. import java.util.Vector;
  22. import org.apache.tools.ant.BuildException;
  23. import org.apache.tools.ant.Location;
  24. import org.apache.tools.ant.taskdefs.MatchingTask;
  25. import org.apache.tools.ant.types.Commandline;
  26. import org.apache.tools.ant.types.Path;
  27. import org.apache.tools.ant.types.Reference;
  28. import org.aspectj.bridge.CountingMessageHandler;
  29. import org.aspectj.bridge.IMessage;
  30. import org.aspectj.bridge.IMessageHandler;
  31. import org.aspectj.bridge.IMessageHolder;
  32. import org.aspectj.bridge.MessageHandler;
  33. import org.aspectj.tools.ajc.Main;
  34. import org.aspectj.tools.ajc.Main.MessagePrinter;
  35. /**
  36. * This runs the AspectJ 1.1 compiler.
  37. * @since AspectJ 1.1, Ant 1.5
  38. */
  39. public class AjcTask extends MatchingTask {
  40. /** @return true if readable and ends with [.java|.aj] */
  41. protected static boolean isSrcFile(File file) {
  42. return ((null != file) && file.canRead()
  43. && (file.getName().endsWith(".java")
  44. || file.getName().endsWith(".aj")));
  45. }
  46. /** valid -X[...] options other than -Xlint variants */
  47. private static final List VALID_XOPTIONS;
  48. /** valid warning (-warn:[...]) variants */
  49. private static final List VALID_WARNINGS;
  50. /** valid debugging (-g:[...]) variants */
  51. private static final List VALID_DEBUG;
  52. /**
  53. * -Xlint variants (error, warning, ignore)
  54. * @see org.aspectj.weaver.Lint
  55. */
  56. private static final List VALID_XLINT;
  57. // /** -Xlint variants
  58. // * @see org.aspectj.weaver.Lint
  59. // */
  60. // private static final List VALID_XLINT_TAGS;
  61. static {
  62. String[] xs = new String[]
  63. { "serializableAspects", "incrementalFile"
  64. //, "targetNearSource", "OcodeSize",
  65. };
  66. VALID_XOPTIONS = Collections.unmodifiableList(Arrays.asList(xs));
  67. xs = new String[]
  68. {"constructorName", "packageDefaultMethod", "deprecation",
  69. "maskedCatchBlocks", "unusedLocals", "unusedArguments",
  70. "unusedImports", "syntheticAccess", "assertIdentifier" };
  71. VALID_WARNINGS = Collections.unmodifiableList(Arrays.asList(xs));
  72. xs = new String[] {"none", "lines", "vars", "source" };
  73. VALID_DEBUG = Collections.unmodifiableList(Arrays.asList(xs));
  74. xs = new String[] { "error", "warning", "ignore"};
  75. VALID_XLINT = Collections.unmodifiableList(Arrays.asList(xs));
  76. // xs = new String[]
  77. // { "invalidAbsoluteTypeName", "invalidWildcardTypeName",
  78. // "unresolvableMember" };
  79. // VALID_XLINT_TAGS = Collections.unmodifiableList(Arrays.asList(xs));
  80. }
  81. // ---------------------------- state and Ant interface thereto
  82. // ------- single entries dumped into cmd
  83. protected Commandline cmd;
  84. // ------- lists resolved in addListArgs() at execute() time
  85. private Path srcdir;
  86. private Path injars;
  87. private Path classpath;
  88. private Path aspectpath;
  89. private Path bootclasspath; // XXX supported?
  90. private List argfiles;
  91. private List ignored;
  92. private Path sourceRoots;
  93. // also note MatchingTask grabs source files...
  94. // ------- interpreted here
  95. private boolean verbose;
  96. private boolean failonerror;
  97. AjcTask() {
  98. reset();
  99. }
  100. /** to use this same Task more than once */
  101. public void reset() {
  102. cmd = new Commandline();
  103. srcdir = null;
  104. injars = null;
  105. classpath = null;
  106. aspectpath = null;
  107. bootclasspath = null;
  108. argfiles = null;
  109. ignored = new ArrayList();
  110. sourceRoots = null;
  111. }
  112. // ---- private, but delegates of all public setters
  113. protected void addFlag(String flag, boolean doAdd) {
  114. if (doAdd) {
  115. cmd.addArguments(new String[] {flag});
  116. }
  117. }
  118. protected void ignore(String ignored) {
  119. this.ignored.add(ignored + " at " + getLocation());
  120. }
  121. protected void addFlagged(String flag, String argument) {
  122. cmd.addArguments(new String[] {flag, argument});
  123. }
  124. protected String validCommaList(String list, List valid, String label) {
  125. return validCommaList(list, valid, label, valid.size());
  126. }
  127. protected String validCommaList(String list, List valid, String label, int max) {
  128. StringBuffer result = new StringBuffer();
  129. StringTokenizer st = new StringTokenizer(list, ",");
  130. int num = 0;
  131. while (st.hasMoreTokens()) {
  132. String token = st.nextToken().trim();
  133. num++;
  134. if (num > max) {
  135. ignore("too many entries for -"
  136. + label
  137. + ": "
  138. + token);
  139. break;
  140. }
  141. if (!valid.contains(token)) {
  142. ignore("bad commaList entry for -"
  143. + label
  144. + ": "
  145. + token);
  146. } else {
  147. if (0 < result.length()) {
  148. result.append(",");
  149. }
  150. result.append(token);
  151. }
  152. }
  153. return (0 == result.length() ? null : result.toString());
  154. }
  155. // -------------- Ant interface
  156. public void setIncremental(boolean incremental) {
  157. addFlag("-incremental", incremental);
  158. }
  159. public void setHelp(boolean help) {
  160. addFlag("-help", help);
  161. }
  162. public void setVersion(boolean version) {
  163. addFlag("-version", version);
  164. }
  165. public void setNoweave(boolean noweave) {
  166. addFlag("-noweave", noweave);
  167. }
  168. public void setNowarn(boolean nowarn) {
  169. addFlag("-nowarn", nowarn);
  170. }
  171. public void setDeprecation(boolean deprecation) {
  172. addFlag("-deprecation", deprecation);
  173. }
  174. public void setWarn(String warnings) {
  175. warnings = validCommaList(warnings, VALID_WARNINGS, "warn");
  176. addFlag("-warn:" + warnings, (null != warnings));
  177. }
  178. public void setDebug(boolean debug) {
  179. addFlag("-g", debug);
  180. }
  181. public void setDebugLevel(String level) {
  182. level = validCommaList(level, VALID_DEBUG, "g");
  183. addFlag("-g:" + level, (null != level));
  184. }
  185. public void setEmacssym(boolean emacssym) {
  186. addFlag("-emacssym", emacssym);
  187. }
  188. /**
  189. * -Xlint - set default level of -Xlint messages to warning
  190. * (same as </code>-Xlint:warning</code>)
  191. */
  192. public void setXlintwarnings(boolean xlintwarnings) {
  193. addFlag("-Xlint", xlintwarnings);
  194. }
  195. /** -Xlint:{error|warning|info} - set default level for -Xlint messages
  196. * @param xlint the String with one of error, warning, ignored
  197. */
  198. public void setXlint(String xlint) {
  199. xlint = validCommaList(xlint, VALID_XLINT, "Xlint", 1);
  200. addFlag("-Xlint:" + xlint, (null != xlint));
  201. }
  202. /**
  203. * -Xlint:file={lint.properties} - enable or disable specific forms
  204. * of -Xlint messages based on a lint properties file
  205. * (default is
  206. * <code>org/aspectj/weaver/XLintDefault.properties</code>)
  207. * @param xlintFile the File with lint properties
  208. */
  209. public void setXlintfile(File xlintFile) {
  210. String flag = "-Xlintfile:" + xlintFile.getAbsolutePath();
  211. addFlag(flag, true);
  212. }
  213. public void setPreserveAllLocals(boolean preserveAllLocals) {
  214. addFlag("-preserveAllLocals", preserveAllLocals);
  215. }
  216. public void setNoImportError(boolean noImportError) {
  217. addFlag("-noImportError", noImportError);
  218. }
  219. public void setEncoding(String encoding) { // XXX encoding unvalidated
  220. addFlagged("-encoding", encoding);
  221. }
  222. public void setLog(File file) {
  223. addFlagged("-log", file.getAbsolutePath());
  224. }
  225. public void setProceedOnError(boolean proceedOnError) {
  226. addFlag("-proceedOnError", proceedOnError);
  227. }
  228. public void setVerbose(boolean verbose) {
  229. addFlag("-verbose", verbose);
  230. this.verbose = verbose;
  231. }
  232. public void setReferenceInfo(boolean referenceInfo) {
  233. addFlag("-referenceInfo", referenceInfo);
  234. }
  235. public void setProgress(boolean progress) {
  236. addFlag("-progress", progress);
  237. }
  238. public void setTime(boolean time) {
  239. addFlag("-time", time);
  240. }
  241. public void setNoExit(boolean noExit) {
  242. addFlag("-noExit", noExit);
  243. }
  244. public void setFailonerror(boolean failonerror) {
  245. this.failonerror = failonerror;
  246. }
  247. // ----------------
  248. public void setTagFile(File file) {
  249. addFlagged(Main.CommandController.TAG_FILE_OPTION,
  250. file.getAbsolutePath());
  251. }
  252. public void setOutjar(File file) {
  253. addFlagged("-outjar", file.getAbsolutePath());
  254. }
  255. public void setDestdir(File dir) {
  256. addFlagged("-d", dir.getAbsolutePath());
  257. }
  258. public void setTarget(String either11or12) {
  259. if ("1.1".equals(either11or12)) {
  260. addFlagged("-target", "1.1");
  261. } else if ("1.2".equals(either11or12)) {
  262. addFlagged("-target", "1.2");
  263. } else {
  264. ignore("-target " + either11or12);
  265. }
  266. }
  267. /**
  268. * Language compliance level.
  269. * If not set explicitly, eclipse default holds.
  270. * @param either13or14 either "1.3" or "1.4"
  271. */
  272. public void setCompliance(String either13or14) {
  273. if ("1.3".equals(either13or14)) {
  274. addFlag("-1.3", true);
  275. } else if ("1.4".equals(either13or14)) {
  276. addFlag("-1.4", true);
  277. } else {
  278. ignore(either13or14 + "[compliance]");
  279. }
  280. }
  281. /**
  282. * Source compliance level.
  283. * If not set explicitly, eclipse default holds.
  284. * @param either13or14 either "1.3" or "1.4"
  285. */
  286. public void setSource(String either13or14) {
  287. if ("1.3".equals(either13or14)) {
  288. addFlagged("-source", "1.3");
  289. } else if ("1.4".equals(either13or14)) {
  290. addFlagged("-source", "1.4");
  291. } else {
  292. ignore("-source " + either13or14);
  293. }
  294. }
  295. //---------------------- accumulate these lists
  296. public void setSourceRootsList(String commaList) {
  297. StringTokenizer st = new StringTokenizer(commaList, ",");
  298. while (st.hasMoreTokens()) {
  299. String token = st.nextToken().trim();
  300. if (0 == token.length()) {
  301. ignore("empty source root found");
  302. }
  303. File srcRoot = new File(token);
  304. if (srcRoot.canRead() && srcRoot.isDirectory()) {
  305. Path path = new Path(getProject(), srcRoot.getPath());
  306. setSourceRoots(path);
  307. } else {
  308. ignore("source root not found: " + srcRoot);
  309. }
  310. }
  311. }
  312. public void setSourceRoots(Path roots) {
  313. if (this.sourceRoots == null) {
  314. this.sourceRoots = roots;
  315. } else {
  316. this.sourceRoots.append(roots);
  317. }
  318. }
  319. public Path createSourceRoots() {
  320. if (sourceRoots == null) {
  321. sourceRoots = new Path(project);
  322. }
  323. return sourceRoots.createPath();
  324. }
  325. public void setClasspath(Path classpath) {
  326. if (this.classpath == null) {
  327. this.classpath = classpath;
  328. } else {
  329. this.classpath.append(classpath);
  330. }
  331. }
  332. public Path createClasspath() {
  333. if (classpath == null) {
  334. classpath = new Path(project);
  335. }
  336. return classpath.createPath();
  337. }
  338. public void setInjars(Path injars) {
  339. if (this.injars == null) {
  340. this.injars = injars;
  341. } else {
  342. this.injars.append(injars);
  343. }
  344. }
  345. public Path createInjars() {
  346. if (injars == null) {
  347. injars = new Path(project);
  348. }
  349. return injars.createPath();
  350. }
  351. public void setAspectpath(Path aspectpath) {
  352. if (this.aspectpath == null) {
  353. this.aspectpath = aspectpath;
  354. } else {
  355. this.aspectpath.append(aspectpath);
  356. }
  357. }
  358. public Path createSrc() {
  359. return createSrcdir();
  360. }
  361. public Path createSrcdir() {
  362. if (srcdir == null) {
  363. srcdir = new Path(project);
  364. }
  365. return srcdir.createPath();
  366. }
  367. public Path createAspectpath() {
  368. if (aspectpath == null) {
  369. aspectpath = new Path(project);
  370. }
  371. return aspectpath.createPath();
  372. }
  373. public void setClasspathref(Reference classpathref) {
  374. createClasspath().setRefid(classpathref);
  375. }
  376. public void setBootclasspath(Path bootclasspath) {
  377. if (this.bootclasspath == null) {
  378. this.bootclasspath = bootclasspath;
  379. } else {
  380. this.bootclasspath.append(bootclasspath);
  381. }
  382. }
  383. public Path createBootclasspath() {
  384. if (bootclasspath == null) {
  385. bootclasspath = new Path(project);
  386. }
  387. return bootclasspath.createPath();
  388. }
  389. public void setBootclasspathref(Reference bootclasspathref) {
  390. createBootclasspath().setRefid(bootclasspathref);
  391. }
  392. public void setArgfile(File argfile) { // ajc-only eajc-also docDone
  393. if (argfiles == null) {
  394. argfiles = new Vector();
  395. }
  396. argfiles.add(argfile);
  397. }
  398. public void setArgfiles(String argfiles) { // ajc-only eajc-also docDone
  399. StringTokenizer tok = new StringTokenizer(argfiles, ", ", false);
  400. if (tok.hasMoreTokens() && this.argfiles == null) {
  401. this.argfiles = new Vector();
  402. }
  403. while (tok.hasMoreTokens()) {
  404. this.argfiles.add(project.resolveFile(tok.nextToken().trim()));
  405. }
  406. }
  407. public void setX(String input) { // ajc-only eajc-also docDone
  408. StringTokenizer tokens = new StringTokenizer(input, ",", false);
  409. while (tokens.hasMoreTokens()) {
  410. String token = tokens.nextToken().trim();
  411. if (1 < token.length()) {
  412. if (VALID_XOPTIONS.contains(token)) {
  413. addFlag("-X" + token, true);
  414. } else {
  415. ignore("-X" + token);
  416. }
  417. }
  418. }
  419. }
  420. // ---------------------------- test state and interface thereto
  421. private IMessageHolder messageHolder;
  422. void setMessageHolder(IMessageHolder holder) {
  423. this.messageHolder = holder;
  424. }
  425. /**
  426. * Setup custom message handling.
  427. * @param className the String fully-qualified-name of a class
  428. * reachable from this object's class loader,
  429. * implementing IMessageHolder, and
  430. * having a public no-argument constructor.
  431. */
  432. public void setMessageHolderClass(String className) {
  433. try {
  434. Class mclass = Class.forName(className);
  435. IMessageHolder holder = (IMessageHolder) mclass.newInstance();
  436. setMessageHolder(holder);
  437. } catch (Throwable t) { // XXX better message
  438. ignore("unable to load message holder class " + className
  439. + t.getClass().getName() + ": " + t.getMessage());
  440. }
  441. }
  442. // ------------------------------ run
  443. /**
  444. * Compile using ajc per settings.
  445. * This prints the messages in verbose or terse form
  446. * unless an IMessageHolder was set using setMessageHolder.
  447. * @exception BuildException if the compilation has problems
  448. * or if there were compiler errors and failonerror is true.
  449. */
  450. public void execute() throws BuildException {
  451. IMessageHolder holder = messageHolder;
  452. int numPreviousErrors;
  453. if (null == holder) {
  454. MessageHandler mhandler = new MessageHandler(true);
  455. final IMessageHandler delegate
  456. = verbose ? MessagePrinter.VERBOSE: MessagePrinter.TERSE;
  457. mhandler.setInterceptor(delegate);
  458. holder = mhandler;
  459. numPreviousErrors = 0;
  460. } else {
  461. numPreviousErrors = holder.numMessages(IMessage.ERROR, true);
  462. }
  463. try {
  464. if (0 < ignored.size()) {
  465. for (Iterator iter = ignored.iterator(); iter.hasNext();) {
  466. log("ignored: " + iter.next(), project.MSG_INFO);
  467. }
  468. }
  469. Main main = new Main();
  470. main.setHolder(holder);
  471. addListArgs();
  472. String[] args = cmd.getArguments();
  473. if (verbose) {
  474. log("ajc " + Arrays.asList(args), project.MSG_VERBOSE);
  475. }
  476. main.runMain(args, false);
  477. if (failonerror) {
  478. int errs = holder.numMessages(IMessage.ERROR, true);
  479. errs -= numPreviousErrors;
  480. if (0 < errs) {
  481. // errors should already be printed by interceptor
  482. throw new BuildException(errs + " errors");
  483. }
  484. }
  485. } catch (BuildException e) {
  486. throw e;
  487. } catch (Throwable x) {
  488. throw new BuildException("Thrown: ", x);
  489. }
  490. }
  491. // ------------------------------ setup and reporting
  492. /**
  493. * @return String[] of command-line arguments
  494. * @throws BuildException if tagFile or sourceRoots invalid
  495. */
  496. protected void addListArgs() throws BuildException {
  497. if (classpath != null) {
  498. addFlagged("-classpath", classpath.toString());
  499. }
  500. if (aspectpath != null) {
  501. addFlagged("-aspectpath", aspectpath.toString());
  502. }
  503. if (bootclasspath != null) {
  504. addFlagged("-bootclasspath", bootclasspath.toString());
  505. }
  506. if (injars != null) {
  507. addFlagged("-injars", injars.toString());
  508. }
  509. if (sourceRoots != null) {
  510. addFlagged("-sourceroots", sourceRoots.toString());
  511. }
  512. int numargfiles = 0;
  513. if (argfiles != null) {
  514. for (Iterator i = argfiles.iterator(); i.hasNext();) {
  515. String name = i.next()+"";
  516. File argfile = project.resolveFile(name);
  517. if (check(argfile, name, false, location)) {
  518. addFlagged("-argfile", argfile.getAbsolutePath());
  519. numargfiles++;
  520. }
  521. }
  522. }
  523. int numSources = 0;
  524. if (srcdir != null) {
  525. // todo: ignore any srcdir if any argfiles and no explicit includes
  526. String[] dirs = srcdir.list();
  527. for (int i = 0; i < dirs.length; i++) {
  528. File dir = project.resolveFile(dirs[i]);
  529. check(dir, dirs[i], true, location);
  530. String[] files = getDirectoryScanner(dir).getIncludedFiles();
  531. for (int j = 0; j < files.length; j++) {
  532. File file = new File(dir, files[j]);
  533. if (isSrcFile(file)) {
  534. cmd.createArgument().setFile(file);
  535. numSources++;
  536. }
  537. }
  538. }
  539. }
  540. }
  541. protected final boolean check(File file, String name,
  542. boolean isDir, Location loc) {
  543. loc = loc != null ? loc : location;
  544. if (file == null) {
  545. throw new BuildException(name + " is null!", loc);
  546. }
  547. if (!file.exists()) {
  548. throw new BuildException(file + " doesn't exist!", loc);
  549. }
  550. if (isDir ^ file.isDirectory()) {
  551. String e = file + " should" + (isDir ? "" : "n't") +
  552. " be a directory!";
  553. throw new BuildException(e, loc);
  554. }
  555. return true;
  556. }
  557. }