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

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