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.

Ajc2.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  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 org.apache.tools.ant.*;
  14. import org.apache.tools.ant.types.*;
  15. import org.apache.tools.ant.taskdefs.*;
  16. import org.apache.tools.ant.util.JavaEnvUtils;
  17. import java.io.*;
  18. import java.util.List;
  19. import java.util.ArrayList;
  20. import java.util.StringTokenizer;
  21. /**
  22. * Ant task for the AspectJ compiler -- AJC.
  23. * List (.lst) files are passed in as includes.
  24. *
  25. * This task was developed by the <a href="http://aspectj.org">AspectJ Project</a>
  26. *
  27. * @author <a href="mailto:palm@parc.xerox.com">Jeffrey Palm</a>
  28. * @see org.aspectj.tools.ant.taskdefs.compilers.Ajc
  29. */
  30. public class Ajc2 extends Javac {
  31. /**
  32. * The name of the adapter we use.
  33. */
  34. public final static String ADAPTER_CLASS =
  35. "org.aspectj.tools.ant.taskdefs.compilers.Ajc";
  36. /* ----------------------------------------------------------------------
  37. * Attribute members
  38. * ----------------------------------------------------------------------
  39. */
  40. /**
  41. * How many concurrent threads to use for compilation,
  42. * defaults to 0 -- multi-threading disabled.
  43. */
  44. private Integer threads;
  45. /**
  46. * Don't generate any comments into the woven code.
  47. */
  48. private boolean nocomments;
  49. /**
  50. * Don't generate .ajsym or .ajsline files.
  51. */
  52. private boolean nosymbols;
  53. /**
  54. * Generate regular Java code into <workingdir>.
  55. */
  56. private boolean preprocess;
  57. /**
  58. * Specify where to place intermediate .java files <dir>
  59. * defaults to ./ajworkingdir.
  60. */
  61. private File workingdir;
  62. /**
  63. * The file is a line-delimited list of arguments
  64. * these arguments are inserted into the argument list
  65. */
  66. private List argfiles;
  67. /* ----------------------------------------------------------------------
  68. * Misc. members
  69. * ----------------------------------------------------------------------
  70. */
  71. /**
  72. * Whether we have used the <code>excludes</code> attribute.
  73. */
  74. private boolean haveExcludes = false;
  75. /**
  76. * Whether we have used the <code>includes</code> attribute.
  77. */
  78. private boolean haveIncludes = false;
  79. /**
  80. * Whether we have used the <code>excludes</code> attribute.
  81. * @return Whether we have used the <code>excludes</code> attribute.
  82. */
  83. protected boolean hasExcludes() {
  84. return haveExcludes;
  85. }
  86. /**
  87. * Whether we have used the <code>includes</code> attribute.
  88. * @return Whether we have used the <code>includes</code> attribute.
  89. */
  90. protected boolean hasIncludes() {
  91. return haveIncludes;
  92. }
  93. /* ----------------------------------------------------------------------
  94. * Attribute access methods
  95. * ----------------------------------------------------------------------
  96. */
  97. /**
  98. * Sets the number of threads.
  99. *
  100. * @param threads the number of threads.
  101. * @see Ajc2#threads
  102. */
  103. public void setThreads(Integer threads) {
  104. this.threads = threads;
  105. }
  106. /**
  107. * Returns the number of threads.
  108. *
  109. * @return the number of threads.
  110. * @see Ajc2#threads
  111. */
  112. public Integer getThreads() {
  113. return threads;
  114. }
  115. /**
  116. * Set the <code>-nocomments</code> flag.
  117. *
  118. * @param nocomments true turns on the flag.
  119. * @see Ajc2#nocomments
  120. */
  121. public void setNocomments(boolean nocomments) {
  122. this.nocomments = nocomments;
  123. }
  124. /**
  125. * Returns if the <code>-nocomments</code> flag is turned on.
  126. *
  127. * @return <code>true</code> if the <code>-nocomments</code> flag is on.
  128. * @see Ajc2#nocomments
  129. */
  130. public boolean getNocomments() {
  131. return nocomments;
  132. }
  133. /**
  134. * Set the <code>-nosymbols</code> flag.
  135. *
  136. * @param nosymbols true turns on the flag.
  137. * @see Ajc2#nosymbols
  138. */
  139. public void setNosymbols(boolean nosymbols) {
  140. this.nosymbols = nosymbols;
  141. }
  142. /**
  143. * Returns if the <code>-nosymbols</code> flag is turned on.
  144. *
  145. * @return <code>true</code> if the <code>-nosymbols</code> flag is on.
  146. * @see Ajc2#nosymbols
  147. */
  148. public boolean getNosymbols() {
  149. return nosymbols;
  150. }
  151. /**
  152. * Set the <code>-preprocess</code> flag.
  153. *
  154. * @param preprocess <code>true</code> turns on the <code>-preprocess</code> flag.
  155. * @see Ajc2#preprocess
  156. */
  157. public void setPreprocess(boolean preprocess) {
  158. this.preprocess = preprocess;
  159. }
  160. /**
  161. * Returns if the <code>-preprocess</code> flag is turned on.
  162. *
  163. * @return <code>true</code> if the <code>-preprocess</code> flag is on.
  164. * @see Ajc2#preprocess
  165. */
  166. public boolean getPreprocess() {
  167. return preprocess;
  168. }
  169. /**
  170. * Sets the workingdir.
  171. *
  172. * @param workingdir the new workingdir.
  173. * @see Ajc2#workingdir
  174. */
  175. public void setWorkingdir(File workingdir) {
  176. this.workingdir = workingdir;
  177. }
  178. /**
  179. * Returns the current workingdir.
  180. *
  181. * @return the current workingdir.
  182. * @see Ajc2#workingdir
  183. */
  184. public File getWorkingdir() {
  185. return workingdir;
  186. }
  187. /**
  188. * Sets the the argument files by the comma-delimited String passed in.
  189. *
  190. * @param argfiles comma-delimited String contained argument files.
  191. */
  192. public void setArgfiles(String argfiles) {
  193. StringTokenizer tok = new StringTokenizer(argfiles, ",");
  194. while (tok.hasMoreTokens()) {
  195. File argfile = project.resolveFile(tok.nextToken());
  196. if (argfile != null && argfile.exists() && !argfile.isDirectory()) {
  197. createArgfile().setFile(argfile);
  198. }
  199. }
  200. }
  201. /**
  202. * Creates a nested <code>Argfile</code>, add it to the list
  203. * <code>argfiles</code>, and returns the new <code>Argfile</code>
  204. * instance.
  205. *
  206. * @return a new <code>Argfile</code> instance.
  207. */
  208. public Argfile createArgfile() {
  209. Argfile argfile = new Argfile();
  210. if (argfiles == null) {
  211. argfiles = new ArrayList();
  212. }
  213. argfiles.add(argfile);
  214. return argfile;
  215. }
  216. /**
  217. * Returns the java.util.List of argfiles.
  218. * This could be <code>null</code>.
  219. *
  220. * @return the list of argfiles.
  221. */
  222. public List getArgfiles() {
  223. return argfiles;
  224. }
  225. /**
  226. * A simple class with one member -- <code>file</code> -- that
  227. * represents an argument file.
  228. */
  229. public static class Argfile {
  230. private File file;
  231. public void setFile(File file) { this.file = file; }
  232. public File getFile() { return file; }
  233. public String toString() { return file.getAbsolutePath(); }
  234. }
  235. /* ----------------------------------------------------------------------
  236. * Misc. methods
  237. * ----------------------------------------------------------------------
  238. */
  239. /* Leaving the includes blank in the Javac task defaults to including all.
  240. * In Ajc, if the user specifies an argfile, but leaves the includes and
  241. * excludes blank that person probably meant to just includes to argfile.
  242. * So, we keep track of whether includes and/or excludes have been explicitly
  243. * used with the have{In,Ex}cludes members, and setting these flags
  244. * in the create... and set... methods.
  245. *
  246. * When constructing the compileList, if both haveIncludes and haveExcludes
  247. * are false, but the user has specified an argfile, then we set includes
  248. * to '!**' before adding the contents of the argfile.
  249. */
  250. /**
  251. * Override Javac.createInclude() to set <code>haveIncludes</code>
  252. * to <code>true</code>.
  253. *
  254. * @return new PatternSet.NameEntry to be added to the include list.
  255. * @see org.apache.tools.ant.taskdefs.Javac#createInclude()
  256. */
  257. public PatternSet.NameEntry createInclude() {
  258. haveIncludes = true;
  259. return super.createInclude();
  260. }
  261. /**
  262. * Override Javac.createExclude() to set <code>haveExcludes</code>
  263. * to <code>true</code>.
  264. *
  265. * @return new PatternSet.NameEntry to be added to the exclude list.
  266. * @see org.apache.tools.ant.taskdefs.Javac#createExclude()
  267. */
  268. public PatternSet.NameEntry createExclude() {
  269. haveExcludes = true;
  270. return super.createExclude();
  271. }
  272. /**
  273. * Override Javac.setIncludes(String) to set <code>haveIncludes</code>
  274. * to <code>true</code>.
  275. *
  276. * @param includes Comma-separated list of includes.
  277. * @see org.apache.tools.ant.taskdefs.Javac#setIncludes(java.lang.String)
  278. */
  279. public void setIncludes(String includes) {
  280. haveIncludes = true;
  281. super.setIncludes(includes);
  282. }
  283. /**
  284. * Override Javac.setExcludes(String) to set <code>haveExcludes</code>
  285. * to <code>true</code>.
  286. *
  287. * @param excludes Comma-separated list of excludes.
  288. * @see org.apache.tools.ant.taskdefs.Javac#setExcludes(java.lang.String)
  289. */
  290. public void setExcludes(String excludes) {
  291. haveExcludes = true;
  292. super.setExcludes(excludes);
  293. }
  294. public String getAdapterClass() {
  295. return ADAPTER_CLASS;
  296. }
  297. public final void execute() throws BuildException {
  298. prepare();
  299. executeAfterPrepare();
  300. }
  301. /**
  302. * Executes by first setting the <code>build.compiler</code> property
  303. * to AjcCompiler, then invokes the super.execute() method.
  304. *
  305. * @throws org.apache.tools.ant.BuildException
  306. * @see org.apache.tools.ant.taskdefs.Javac#execute()
  307. */
  308. public void executeAfterPrepare() throws BuildException {
  309. // Save the old build.compiler property
  310. String oldBuildCompiler = project.getProperty("build.compiler");
  311. // If oldBuildCompiler is null try to resolve it
  312. if (oldBuildCompiler == null) {
  313. String javaVersion = JavaEnvUtils.getJavaVersion();
  314. if (javaVersion.equals(JavaEnvUtils.JAVA_1_0)) {
  315. // Cannot happen
  316. } else if (javaVersion.equals(JavaEnvUtils.JAVA_1_1)) {
  317. oldBuildCompiler = "classic";
  318. } else if (javaVersion.equals(JavaEnvUtils.JAVA_1_2)) {
  319. oldBuildCompiler = "classic";
  320. } else if (javaVersion.equals(JavaEnvUtils.JAVA_1_3)) {
  321. oldBuildCompiler = "modern";
  322. }
  323. }
  324. // Set the new adapter
  325. project.setProperty("build.compiler", getAdapterClass());
  326. BuildException caught = null;
  327. try {
  328. super.execute();
  329. } catch (BuildException be) {
  330. caught = be;
  331. } finally {
  332. // Reset to the old compiler
  333. if (oldBuildCompiler != null) {
  334. project.setProperty("build.compiler", oldBuildCompiler);
  335. }
  336. }
  337. // If we caught an exception executing throw it
  338. if (caught != null) {
  339. throw caught;
  340. }
  341. }
  342. /**
  343. * Guaranteed to be called before doing real execute.
  344. */
  345. public void prepare() {
  346. if (argfiles != null && !haveIncludes &&
  347. !haveExcludes && getSrcdir() == null) {
  348. useDefaultSrcdir();
  349. }
  350. }
  351. protected final void useDefaultSrcdir() {
  352. setSrcdir(new Path(project, "."));
  353. }
  354. /**
  355. * Overrides Javac.scanDir(..) so that it doesn't check dependencies.
  356. *
  357. * @see org.apache.tools.ant.taskdefs.Javac#scanDir
  358. */
  359. protected void scanDir(File srcDir, File destDir, String files[]) {
  360. List newFiles = new ArrayList();
  361. // Add the files listed in the argfiles to the includes
  362. List newIncludes = new ArrayList();
  363. List newArguments = new ArrayList();
  364. if (argfiles != null) {
  365. for (Object o : argfiles) {
  366. File argfile = ((Argfile) o).getFile();
  367. expandArgfile(argfile, newIncludes, newArguments);
  368. }
  369. }
  370. // If there aren't any includes, but we've used an argfile then we should
  371. // set the includes to be the one's found in newIncludes
  372. // If we do this, we need to re-read files from the directory scanner
  373. if (!haveIncludes && !haveExcludes && argfiles != null) {
  374. log("Setting includes to '!**'", Project.MSG_VERBOSE);
  375. setIncludes("!**");
  376. //files = getDirectoryScanner(srcDir).getIncludedFiles();
  377. }
  378. // Otherwise we want to add all .java files to the compileList
  379. else {
  380. for (String file : files) {
  381. File newFile = new File(srcDir, file);
  382. if (newFile != null &&
  383. newFile.exists() &&
  384. newFile.getName().endsWith(".java")) {
  385. newFiles.add(newFile);
  386. }
  387. }
  388. }
  389. // Add the new included files
  390. for (Object newInclude : newIncludes) {
  391. newFiles.add((File) newInclude);
  392. }
  393. // This is the same behavior found in Javac
  394. int newFileSize = newFiles.size();
  395. if (newFileSize > 0) {
  396. File[] newCompileList = new File[compileList.length + newFileSize];
  397. System.arraycopy(compileList, 0, newCompileList, 0, compileList.length);
  398. System.arraycopy(newFiles.toArray(), 0, newCompileList,
  399. compileList.length, newFileSize);
  400. compileList = newCompileList;
  401. }
  402. }
  403. private void expandArgfile(File argfile, List includes, List arguments) {
  404. log("argfile:" + argfile, Project.MSG_VERBOSE);
  405. // All paths are relative to the parent
  406. File parent = argfile.getParentFile();
  407. // Sanity check
  408. if (parent == null || !parent.exists() || !parent.isDirectory()) {
  409. return;
  410. }
  411. // Read the file
  412. BufferedReader in = null;
  413. try {
  414. in = new BufferedReader(new FileReader(argfile));
  415. String line;
  416. while ((line = in.readLine()) != null) {
  417. line = line.trim();
  418. // Skip blank lines
  419. if ("".equals(line)) {
  420. continue;
  421. }
  422. // Allow '#' and '//' line comments
  423. int isharp = line.indexOf("#");
  424. if (isharp != -1) {
  425. line = line.substring(0, isharp);
  426. }
  427. // int istar = -1;
  428. // Argument
  429. if (line.startsWith("-")) {
  430. arguments.add(line);
  431. }
  432. // If there are stars we'll try to resolve the file here
  433. else if (line.contains("*")) {
  434. log("The argfile line '" + line + "' is invalid",
  435. Project.MSG_WARN);
  436. }
  437. // Another argfile
  438. else if (line.startsWith("@")) {
  439. String newArgfileName = line.substring(1);
  440. File newArgfile = new File(parent, newArgfileName);
  441. expandArgfile(newArgfile, includes, arguments);
  442. }
  443. // Source file
  444. else {
  445. File newfile = new File(line);
  446. if (!newfile.isAbsolute()) {
  447. newfile = new File(parent, line);
  448. }
  449. if (newfile != null && newfile.exists() &&
  450. !newfile.isDirectory() &&
  451. newfile.getName().endsWith(".java")) {
  452. includes.add(newfile);
  453. }
  454. }
  455. }
  456. } catch (IOException ioe) {
  457. log("trouble with argfile: " + argfile + ":" + ioe, Project.MSG_ERR);
  458. } finally {
  459. try {
  460. if (in != null) {
  461. in.close();
  462. }
  463. } catch (IOException ioe2) {
  464. }
  465. }
  466. }
  467. }