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

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