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.

Ajc10.java 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /* *******************************************************************
  2. * Copyright (c) 2000-2001 Xerox Corporation.
  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.tools.ant.taskdefs;
  13. import java.io.File;
  14. import java.util.Arrays;
  15. import java.util.Collections;
  16. import java.util.HashSet;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Set;
  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.Project;
  25. import org.apache.tools.ant.taskdefs.MatchingTask;
  26. import org.apache.tools.ant.types.Commandline;
  27. import org.apache.tools.ant.types.Path;
  28. import org.apache.tools.ant.types.Reference;
  29. import org.aspectj.bridge.AbortException;
  30. import org.aspectj.bridge.IMessage;
  31. import org.aspectj.bridge.IMessageHandler;
  32. import org.aspectj.bridge.IMessageHolder;
  33. import org.aspectj.bridge.MessageHandler;
  34. import org.aspectj.tools.ajc.Main;
  35. import org.aspectj.tools.ajc.Main.MessagePrinter;
  36. import org.aspectj.util.FileUtil;
  37. /**
  38. * Main taskdef class for the AspectJ 1.0 compiler, <code>ajc</code>.
  39. * See the README and examples/build.xml for more information.
  40. */
  41. public class Ajc10 extends MatchingTask {
  42. private static final List<String> VALID_XOPTIONS;
  43. static {
  44. String[] xs = new String[]
  45. { "lint", "serializableAspects", "targetNearSource", "OcodeSize",
  46. "incrementalFile" };
  47. VALID_XOPTIONS = Collections.unmodifiableList(Arrays.asList(xs));
  48. }
  49. //protected boolean version;
  50. protected boolean source14;
  51. protected Set ignoredOptions;
  52. protected Commandline cmd;
  53. protected Commandline vmcmd;
  54. private int threads = -1;
  55. private File destdir;
  56. private File workingdir;
  57. private Path internalclasspath;
  58. private Path classpath;
  59. private Path bootclasspath;
  60. private Path extdirs;
  61. private Path srcdir;
  62. private List argfiles;
  63. private boolean fork;
  64. private boolean failonerror;
  65. private boolean verbose;
  66. private String encoding;
  67. private String source;
  68. public Ajc10() {
  69. reset();
  70. }
  71. // ------------------------- options
  72. // find option types and whether ignored:
  73. // sed -n '/void set/p' Ajc.java | sed 's/.*\/\/ //' | sort -u
  74. // sed -n '/ignoredOptions/d;/ignored/p' Ajc.java
  75. // each option may be "ignored" and is one+ of:
  76. // ajc-old used to be an ajc option
  77. // ajc-only only an option for ajc, not javac
  78. // ajc-taskdef only only an option for ajc taskdef, not ajc
  79. // javac-also also an option in javac
  80. // eajc-also
  81. // ------------------------- options in order per ajc output
  82. public void setVerbose(boolean verbose) { // javac-also eajc-also docDone
  83. setif(verbose, "-verbose");
  84. this.verbose = verbose;
  85. }
  86. public void setVersion(boolean version) { // javac-also eajc-also docDone
  87. // let the compiler handle it
  88. if (version) {
  89. setif(true, "-version");
  90. }
  91. //this.version = version;
  92. }
  93. public void setNocomments(boolean nocomments) { // ajc-only not-eajc docDone
  94. if (nocomments) {
  95. ignore("-nocomments");
  96. }
  97. //setif(nocomments, "-nocomments");
  98. }
  99. public void setEmacssym(boolean input) { // ajc-only eajc-also docDone
  100. setif(input, "-emacssym");
  101. }
  102. public void setUsejavac(boolean input) { // ajc-only not-eajc docDone
  103. if (input) {
  104. ignore("-usejavac");
  105. }
  106. //setif(input, "-usejavac");
  107. }
  108. public void setPreprocess(boolean preprocess) { // ajc-only not-eajc docDone
  109. if (preprocess) {
  110. ignore("-preprocess");
  111. //setif(preprocess, "-preprocess");
  112. }
  113. }
  114. public void setWorkingdir(String workingdir) { // ajc-only not-eajc ocDone
  115. ignore("-workingdir");
  116. //this.workingdir = project.resolveFile(workingdir);
  117. }
  118. public void setDestdir(String destdir) { // javac-also eajc-also docDone
  119. this.destdir = project.resolveFile(destdir);
  120. }
  121. public void setOptimize(boolean optimize) { // javac-also ignored docDone
  122. setif(optimize, "-O");
  123. }
  124. public void setClasspath(Path classpath) { // javac-also eajc-also docDone
  125. if (this.classpath == null) {
  126. this.classpath = classpath;
  127. } else {
  128. this.classpath.append(classpath);
  129. }
  130. }
  131. public Path createClasspath() { // javac-also docDone
  132. if (classpath == null) {
  133. classpath = new Path(project);
  134. }
  135. return classpath.createPath();
  136. }
  137. public void setClasspathref(Reference classpathref) { // javac-also docDone
  138. createClasspath().setRefid(classpathref);
  139. }
  140. public void setBootclasspath(Path bootclasspath) { // javac-also not-eajc docDone
  141. ignore("bootclasspath"); // XXX may jury-rig
  142. // if (this.bootclasspath == null) {
  143. // this.bootclasspath = bootclasspath;
  144. // } else {
  145. // this.bootclasspath.append(bootclasspath);
  146. // }
  147. }
  148. public Path createBootclasspath() { // javac-also not-eajc docDone
  149. ignore("bootclasspath"); // XXX may jury-rig
  150. if (bootclasspath == null) {
  151. bootclasspath = new Path(project);
  152. }
  153. return bootclasspath.createPath();
  154. }
  155. public void setBootclasspathref(Reference bootclasspathref) { // javac-also not-eajc docDone
  156. ignore("bootclasspath"); // XXX may jury-rig
  157. // createBootclasspath().setRefid(bootclasspathref);
  158. }
  159. public void setExtdirs(Path extdirs) { // javac-also not-eajc docDone
  160. ignore("-extdirs");
  161. // if (this.extdirs == null) {
  162. // this.extdirs = extdirs;
  163. // } else {
  164. // this.extdirs.append(extdirs);
  165. // }
  166. }
  167. public Path createExtdirs() { // javac-also not-eajc docDone
  168. ignore("-extdirs");
  169. if (extdirs == null) {
  170. extdirs = new Path(project);
  171. }
  172. return extdirs.createPath();
  173. }
  174. public void setArgfile(File argfile) { // ajc-only eajc-also docDone
  175. if (argfiles == null) {
  176. argfiles = new Vector();
  177. }
  178. argfiles.add(argfile);
  179. }
  180. public void setArgfiles(String argfiles) { // ajc-only eajc-also docDone
  181. StringTokenizer tok = new StringTokenizer(argfiles, ", ", false);
  182. if (tok.hasMoreTokens() && this.argfiles == null) {
  183. this.argfiles = new Vector();
  184. }
  185. while (tok.hasMoreTokens()) {
  186. this.argfiles.add(project.resolveFile(tok.nextToken().trim()));
  187. }
  188. }
  189. public void setEncoding(String encoding) { // ignored eajc-also docDone
  190. // XXX add support
  191. //ignore("encoding");
  192. this.encoding = encoding;
  193. }
  194. public void setSource(String input) { // javac-also (Ant 1.4) eajc-also docDone
  195. source = input;
  196. //source14 = "1.4".equals(input); // XXX todo
  197. }
  198. public void setLenient(boolean input) { // ajc-only not-eajc docDone
  199. ignore("-lenient");
  200. //setif(input, "-lenient");
  201. }
  202. public void setStrict(boolean input) { // ajc-only not-eajc docDone
  203. ignore("-strict");
  204. //setif(input, "-strict");
  205. }
  206. public void setPorting(boolean input) { // ajc-only not-eajc docDone
  207. ignore("-porting");
  208. //setif(input, "-porting");
  209. }
  210. public void setX(String input) { // ajc-only eajc-also docDone
  211. StringTokenizer tokens = new StringTokenizer(input, ",", false);
  212. while (tokens.hasMoreTokens()) {
  213. String token = tokens.nextToken().trim();
  214. if (1 < token.length()) {
  215. if (VALID_XOPTIONS.contains(token)) {
  216. setif(true, "-X" + token);
  217. } else {
  218. ignore("-X" + token);
  219. }
  220. }
  221. }
  222. }
  223. // ------------------------- vestigial
  224. public void setThreads(int threads) { // ajc-old docDone ignored
  225. ignore("-threads");
  226. //this.threads = threads;
  227. }
  228. public void setDumpstack(boolean dumpstack) { // ajc-old
  229. ignore("-dumpstack");
  230. //setif(dumpstack, "-dumpstack");
  231. }
  232. // ------------------------- specific to taskdef
  233. public void setInternalclasspath(Path internalclasspath) { // ajc-taskdef only
  234. if (this.internalclasspath == null) {
  235. this.internalclasspath = internalclasspath;
  236. } else {
  237. this.internalclasspath.append(internalclasspath);
  238. }
  239. }
  240. public Path createInternalclasspath() { // ajc-taskdef only
  241. if (internalclasspath == null) {
  242. internalclasspath = new Path(project);
  243. }
  244. return internalclasspath.createPath();
  245. }
  246. public void setInternalclasspathref(Reference internalclasspathref) { // ajc-taskdef only
  247. createInternalclasspath().setRefid(internalclasspathref);
  248. }
  249. public void setSrcdir(Path srcdir) { // javac-also eajc-also docDone
  250. if (this.srcdir == null) {
  251. this.srcdir = srcdir;
  252. } else {
  253. this.srcdir.append(srcdir);
  254. }
  255. }
  256. public Path createSrc() { // javac-also eajc-also docDone
  257. return createSrcdir();
  258. }
  259. public Path createSrcdir() { // javac-also eajc-also docDone
  260. if (srcdir == null) {
  261. srcdir = new Path(project);
  262. }
  263. return srcdir.createPath();
  264. }
  265. public void setFork(boolean fork) { // ajc-only not-eajc docDone
  266. ignore("fork");
  267. //this.fork = fork;
  268. }
  269. public void setFailonerror(boolean failonerror) { // javac-also docDone
  270. this.failonerror = failonerror;
  271. }
  272. public void setMaxmemory(String max) { // ajc-taskdef only docDone
  273. ignore("-maxmemory");
  274. // we do not run under 1.1 anyway...
  275. // createJvmarg().setValue((Project.getJavaVersion().
  276. // startsWith("1.1") ?
  277. // "-mx" : "-Xmx") +max);
  278. }
  279. public void setJvmarg(String input) { // ajc-taskdef only docDone
  280. ignore("jvmarg"); // XXX fork
  281. //vmcmd.createArgument().setValue(input);
  282. }
  283. public Commandline.Argument createJvmarg() { // ajc-taskdef only docDone
  284. ignore("jvmarg"); // XXX fork
  285. return vmcmd.createArgument();
  286. }
  287. // ------------------------- javac task compatibility
  288. public void setNosymbols(boolean nosymbols) { // todo remove?
  289. ignore("-nosymbols");
  290. //setif(nosymbols, "-nosymbols");
  291. }
  292. public void setDebug(boolean debug) { // javac-also eajc-also docDone
  293. setif(debug, "-g"); // todo: changed from -debug
  294. }
  295. public void setDeprecation(boolean deprecation) { // javac-also eajc-also docDone
  296. setif(deprecation, "-deprecation"); // XXX eajc: also "warn:deprecation"
  297. }
  298. // ------------------------- javac task compatibility - ignored
  299. public void setTarget(String target) { // javac-also ignored docDone
  300. ignore("target"); // todo: ajc accepts but doesn't use - pass in?
  301. }
  302. public void setDepend(String depend) { // javac-also ignored docDone
  303. ignore("depend");
  304. }
  305. public void setIncludeantruntime(boolean includeAntruntime) { // javac-also ignored docDone
  306. ignore("includeantruntime");
  307. }
  308. public void setIncludejavaruntime(boolean includeJavaruntime ) { // javac-also ignored docDone
  309. ignore("includeJavaruntime");
  310. }
  311. // ------------------------- other state methods
  312. protected final void ignore(String attribute) {
  313. ignoredOptions.add(attribute);
  314. }
  315. public void backdoorSetFile(File file) {
  316. if (null != file) {
  317. cmd.createArgument().setFile(file);
  318. }
  319. }
  320. /** reset variables to permit gc */
  321. public void reset() {
  322. //version = false;
  323. source14 = false;
  324. ignoredOptions = new HashSet();
  325. cmd = new Commandline();
  326. vmcmd = new Commandline();
  327. threads = -1;
  328. destdir = null;
  329. workingdir = null;
  330. internalclasspath = null;
  331. classpath = null;
  332. bootclasspath = null;
  333. extdirs = null;
  334. srcdir = null;
  335. argfiles = null;
  336. fork = false;
  337. failonerror = true;
  338. encoding = null;
  339. source = null;
  340. }
  341. protected final void setif(boolean b, String flag) {
  342. if (b) cmd.createArgument().setValue(flag);
  343. }
  344. // ------------------------- operational methods
  345. @Override
  346. public void execute() throws BuildException {
  347. if (srcdir == null && argfiles == null) {
  348. throw new BuildException("one of srcdir or argfiles must be set!",
  349. location);
  350. }
  351. // if (threads != -1) {
  352. // cmd.createArgument().setValue("-threads");
  353. // cmd.createArgument().setValue(threads+"");
  354. // }
  355. // if (workingdir != null) {
  356. // cmd.createArgument().setValue("-workingdir");
  357. // cmd.createArgument().setFile(workingdir);
  358. // }
  359. if (destdir != null) {
  360. cmd.createArgument().setValue("-d");
  361. cmd.createArgument().setFile(destdir);
  362. }
  363. if (classpath != null) {
  364. cmd.createArgument().setValue("-classpath");
  365. cmd.createArgument().setPath(classpath);
  366. }
  367. if (bootclasspath != null) {
  368. cmd.createArgument().setValue("-bootclasspath");
  369. cmd.createArgument().setPath(bootclasspath);
  370. }
  371. if (extdirs != null) {
  372. cmd.createArgument().setValue("-extdirs");
  373. cmd.createArgument().setPath(extdirs);
  374. }
  375. if (null != encoding) {
  376. cmd.createArgument().setValue("-encoding");
  377. cmd.createArgument().setValue(encoding);
  378. }
  379. if (null != source) {
  380. cmd.createArgument().setValue("-source");
  381. cmd.createArgument().setValue(source);
  382. }
  383. int numargfiles = 0;
  384. if (argfiles != null) {
  385. for (Iterator i = argfiles.iterator(); i.hasNext();) {
  386. String name = i.next()+"";
  387. File argfile = project.resolveFile(name);
  388. if (check(argfile, name, false, location)) {
  389. cmd.createArgument().setValue("-argfile");
  390. cmd.createArgument().setFile(argfile);
  391. numargfiles++;
  392. }
  393. }
  394. }
  395. int numfiles = 0;
  396. if (srcdir != null) {
  397. // todo: ignore any srcdir if any argfiles and no explicit includes
  398. String[] dirs = srcdir.list();
  399. for (int i = 0; i < dirs.length; i++) {
  400. File dir = project.resolveFile(dirs[i]);
  401. check(dir, dirs[i], true, location);
  402. String[] files = getDirectoryScanner(dir).getIncludedFiles();
  403. for (int j = 0; j < files.length; j++) {
  404. File file = new File(dir, files[j]);
  405. if (FileUtil.hasSourceSuffix(file)) {
  406. cmd.createArgument().setFile(file);
  407. numfiles++;
  408. }
  409. }
  410. }
  411. }
  412. if ((null != ignoredOptions) && (ignoredOptions.size() > 0)) {
  413. log("The following attributes were ignored " + ignoredOptions,
  414. Project.MSG_WARN);
  415. if (ignoredOptions.contains("-preprocess")) {
  416. throw new BuildException("preprocess no longer supported");
  417. }
  418. }
  419. log("Compiling " + numfiles + " source and " +
  420. + numargfiles + " arg files"
  421. + (null == destdir ? "" : " to " + destdir.getPath()), Project.MSG_INFO);
  422. // here is the actual invocation
  423. //int result = (fork || (internalclasspath != null)) ? fork() : spoon();
  424. if (fork || (internalclasspath != null)) {
  425. log("WARNING: fork not supported", Project.MSG_WARN);
  426. }
  427. int result = spoon();
  428. if (result != 0) {
  429. String msg = "Compilation error: " + result;
  430. if (failonerror) {
  431. reset();
  432. throw new BuildException(msg);
  433. } else {
  434. log(msg, Project.MSG_WARN);
  435. }
  436. }
  437. reset(); // see throw above
  438. }
  439. // now leaving version to compiler - remove
  440. // protected void version(Path classpath) {
  441. // try {
  442. // Class main = findClass("org.aspectj.tools.ajc.Main",
  443. // classpath);
  444. // Method printVersion = main.getDeclaredMethod("printVersion",
  445. // new Class[]{});
  446. // printVersion.setAccessible(true);
  447. // printVersion.invoke(main.newInstance(), new Object[]{});
  448. // } catch (Exception e) {}
  449. // }
  450. //
  451. // protected Class findClass(String classname, Path classpathPath) {
  452. // String classpath = (classpathPath != null ?
  453. // classpathPath+"" : "").trim();
  454. // if (classpath.length() == 0) {
  455. // try {
  456. // return Class.forName(classname);
  457. // } catch (ClassNotFoundException e){}
  458. // }
  459. // List urls = new ArrayList();
  460. // for (StringTokenizer t = new StringTokenizer(classpath,
  461. // File.pathSeparator);
  462. // t.hasMoreTokens();) {
  463. // File f = new File(t.nextToken().trim());
  464. // try {
  465. // if (f.exists()) {
  466. // URL url = f.toURL();
  467. // if (url != null) urls.add(url);
  468. // }
  469. // } catch (MalformedURLException e) {}
  470. // }
  471. // if (urls.size() == 0) return null;
  472. // try {
  473. // return new URLClassLoader((URL[])urls.toArray
  474. // (new URL[urls.size()]),
  475. // null).loadClass(classname);
  476. // } catch (ClassNotFoundException e) {}
  477. // return null;
  478. // }
  479. // unused now, but leave in
  480. // protected int fork() throws BuildException {
  481. // Java java = (Java)project.createTask("java");
  482. // java.setTaskName(getTaskName());
  483. // Path compileClasspath;
  484. // if (internalclasspath != null) {
  485. // compileClasspath = internalclasspath;
  486. // compileClasspath.append(Path.systemClasspath);
  487. // } else {
  488. // compileClasspath = Path.systemClasspath;
  489. // }
  490. // //if (version) version(compileClasspath);
  491. // java.setClasspath(compileClasspath);
  492. // java.setClassname(FALSE_MAIN);
  493. // String[] args;
  494. // args = cmd.getArguments();
  495. // for (int i = 0; i < args.length; i++) {
  496. // java.createArg().setValue(args[i]);
  497. // }
  498. // args = vmcmd.getArguments();
  499. // for (int i = 0; i < args.length; i++) {
  500. // java.createJvmarg().setValue(args[i]);
  501. // }
  502. // java.setFork(fork);
  503. // // java handles its own verbose logging when forking
  504. // return java.executeJava();
  505. // }
  506. /** utility to render String[] for logging */
  507. public static String render(String[] args) {
  508. if (null == args) return "";
  509. StringBuffer sb = new StringBuffer();
  510. for (int i = 0; i < args.length; i++) {
  511. sb.append(args[i]);
  512. sb.append(" ");
  513. }
  514. return sb.toString();
  515. }
  516. protected int spoon() throws BuildException {
  517. //if (version) version(null);
  518. int result = -1;
  519. final IMessageHolder holder;
  520. {
  521. MessageHandler handler = new MessageHandler();
  522. if (!verbose) {
  523. handler.ignore(IMessage.INFO);
  524. }
  525. final IMessageHandler delegate
  526. = verbose ? MessagePrinter.VERBOSE: MessagePrinter.TERSE;
  527. handler.setInterceptor(delegate);
  528. holder = handler;
  529. }
  530. try {
  531. String[] args = cmd.getCommandline();
  532. // XXX avoid rendering if not verbosely logging?
  533. log("Running in-process using "
  534. + Ajc10.render(cmd.getCommandline()), Project.MSG_VERBOSE);
  535. Main main = new Main();
  536. main.run(args, holder);
  537. int errs = holder.numMessages(IMessage.ERROR, true);
  538. if (0 < errs) {
  539. result = 1;
  540. } else {
  541. result = 0;
  542. }
  543. } catch (Throwable t) {
  544. while (t instanceof AbortException) {
  545. // check for "just quit -- message printed already"
  546. if (((AbortException)t).isSilent()) {
  547. t = null;
  548. break;
  549. }
  550. IMessage m = ((AbortException) t).getIMessage();
  551. if (null == m) {
  552. break;
  553. } else {
  554. Throwable tt = m.getThrown();
  555. if (null != tt) {
  556. t = tt;
  557. } else {
  558. break;
  559. }
  560. }
  561. }
  562. if (null != t) {
  563. // t.printStackTrace(); // let recipient print
  564. throw new BuildException("Compiler failure", t, location);
  565. }
  566. } finally {
  567. // now printing messages as we go, above
  568. // IMessage.Kind level = (verbose ? IMessage.INFO : IMessage.WARNING);
  569. // if (0 < holder.numMessages(level, true)) {
  570. // final String prefix = "";
  571. // final boolean printSummary = false;
  572. // MessageUtil.print(System.err,
  573. // holder,
  574. // prefix,
  575. // MessageUtil.MESSAGE_ALL,
  576. // (verbose ? MessageUtil.PICK_INFO_PLUS : MessageUtil.PICK_WARNING_PLUS),
  577. // printSummary);
  578. // }
  579. }
  580. return result;
  581. }
  582. protected final boolean check(File file, String name,
  583. boolean isDir, Location loc) {
  584. loc = loc != null ? loc : location;
  585. if (file == null) {
  586. throw new BuildException(name + " is null!", loc);
  587. }
  588. if (!file.exists()) {
  589. throw new BuildException(file + "doesn't exist!", loc);
  590. }
  591. if (isDir ^ file.isDirectory()) {
  592. String e = file + " should" + (isDir ? "" : "n't") +
  593. " be a directory!";
  594. throw new BuildException(e, loc);
  595. }
  596. return true;
  597. }
  598. }