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

21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
20 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
20 jaren geleden
20 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815
  1. /* *******************************************************************
  2. * Copyright (c) 2001-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC)
  4. * 2003 Contributors.
  5. * All rights reserved.
  6. * This program and the accompanying materials are made available
  7. * under the terms of the Common Public License v1.0
  8. * which accompanies this distribution and is available at
  9. * http://www.eclipse.org/legal/cpl-v10.html
  10. *
  11. * Contributors:
  12. * Xerox/PARC initial implementation
  13. * ******************************************************************/
  14. package org.aspectj.tools.ant.taskdefs;
  15. import java.io.*;
  16. import java.util.*;
  17. import org.apache.tools.ant.*;
  18. import org.apache.tools.ant.taskdefs.*;
  19. import org.apache.tools.ant.types.*;
  20. import org.aspectj.bridge.*;
  21. import org.aspectj.tools.ajc.Main;
  22. import org.aspectj.tools.ajc.Main.MessagePrinter;
  23. import org.aspectj.util.*;
  24. /**
  25. * This runs the AspectJ 1.1 compiler,
  26. * supporting all the command-line options.
  27. * In 1.1.1, ajc copies resources from input jars,
  28. * but you can copy resources from the source directories
  29. * using sourceRootCopyFilter.
  30. * When not forking, things will be copied as needed
  31. * for each iterative compile,
  32. * but when forking things are only copied at the
  33. * completion of a successful compile.
  34. * <p>
  35. * See the development environment guide for
  36. * usage documentation.
  37. *
  38. * @since AspectJ 1.1, Ant 1.5
  39. */
  40. public class AjcTask extends MatchingTask {
  41. /*
  42. * This task mainly converts ant specification for ajc,
  43. * verbosely ignoring improper input.
  44. * It also has some special features for non-obvious clients:
  45. * (1) Javac compiler adapter supported in
  46. * <code>setupAjc(AjcTask, Javac, File)</code>
  47. * and
  48. * <code>readArguments(String[])</code>;
  49. * (2) testing is supported by
  50. * (a) permitting the same specification to be re-run
  51. * with added flags (settings once made cannot be
  52. * removed); and
  53. * (b) permitting recycling the task with
  54. * <code>reset()</code> (untested).
  55. *
  56. * The parts that do more than convert ant specs are
  57. * (a) code for forking;
  58. * (b) code for copying resources.
  59. *
  60. * If you maintain/upgrade this task, keep in mind:
  61. * (1) changes to the semantics of ajc (new options, new
  62. * values permitted, etc.) will have to be reflected here.
  63. * (2) the clients:
  64. * the iajc ant script, Javac compiler adapter,
  65. * maven clients of iajc, and testing code.
  66. */
  67. // XXX move static methods after static initializer
  68. /**
  69. * This method extracts javac arguments to ajc,
  70. * and add arguments to make ajc behave more like javac
  71. * in copying resources.
  72. * <p>
  73. * Pass ajc-specific options using compilerarg sub-element:
  74. * <pre>
  75. * &lt;javac srcdir="src">
  76. * &lt;compilerarg compiler="..." line="-argfile src/args.lst"/>
  77. * &lt;javac>
  78. * </pre>
  79. * Some javac arguments are not supported in this component (yet):
  80. * <pre>
  81. * String memoryInitialSize;
  82. * boolean includeAntRuntime = true;
  83. * boolean includeJavaRuntime = false;
  84. * </pre>
  85. * Other javac arguments are not supported in ajc 1.1:
  86. * <pre>
  87. * boolean optimize;
  88. * String forkedExecutable;
  89. * FacadeTaskHelper facade;
  90. * boolean depend;
  91. * String debugLevel;
  92. * Path compileSourcepath;
  93. * </pre>
  94. * @param javac the Javac command to implement (not null)
  95. * @param ajc the AjcTask to adapt (not null)
  96. * @param destDir the File class destination directory (may be null)
  97. * @return null if no error, or String error otherwise
  98. */
  99. public String setupAjc(Javac javac) {
  100. if (null == javac) {
  101. return "null javac";
  102. }
  103. AjcTask ajc = this;
  104. // no null checks b/c AjcTask handles null input gracefully
  105. ajc.setProject(javac.getProject());
  106. ajc.setLocation(javac.getLocation());
  107. ajc.setTaskName("javac-iajc");
  108. ajc.setDebug(javac.getDebug());
  109. ajc.setDeprecation(javac.getDeprecation());
  110. ajc.setFailonerror(javac.getFailonerror());
  111. final boolean fork = javac.isForkedJavac();
  112. ajc.setFork(fork);
  113. if (fork) {
  114. ajc.setMaxmem(javac.getMemoryMaximumSize());
  115. }
  116. ajc.setNowarn(javac.getNowarn());
  117. ajc.setListFileArgs(javac.getListfiles());
  118. ajc.setVerbose(javac.getVerbose());
  119. ajc.setTarget(javac.getTarget());
  120. ajc.setSource(javac.getSource());
  121. ajc.setEncoding(javac.getEncoding());
  122. File javacDestDir = javac.getDestdir();
  123. if (null != javacDestDir) {
  124. ajc.setDestdir(javacDestDir);
  125. // filter requires dest dir
  126. // mimic Javac task's behavior in copying resources,
  127. ajc.setSourceRootCopyFilter("**/CVS/*,**/*.java,**/*.aj");
  128. }
  129. ajc.setBootclasspath(javac.getBootclasspath());
  130. ajc.setExtdirs(javac.getExtdirs());
  131. ajc.setClasspath(javac.getClasspath());
  132. // ignore srcDir -- all files picked up in recalculated file list
  133. // ajc.setSrcDir(javac.getSrcdir());
  134. ajc.addFiles(javac.getFileList());
  135. // arguments can override the filter, add to paths, override options
  136. ajc.readArguments(javac.getCurrentCompilerArgs());
  137. return null;
  138. }
  139. /**
  140. * Find aspectjtools.jar on the task or system classpath.
  141. * Accept <code>aspectj{-}tools{...}.jar</code>
  142. * mainly to support build systems using maven-style
  143. * re-naming
  144. * (e.g., <code>aspectj-tools-1.1.0.jar</code>.
  145. * Note that we search the task classpath first,
  146. * though an entry on the system classpath would be loaded first,
  147. * because it seems more correct as the more specific one.
  148. * @return readable File for aspectjtools.jar, or null if not found.
  149. */
  150. public static File findAspectjtoolsJar() {
  151. File result = null;
  152. ClassLoader loader = AjcTask.class.getClassLoader();
  153. if (loader instanceof AntClassLoader) {
  154. AntClassLoader taskLoader = (AntClassLoader) loader;
  155. String cp = taskLoader.getClasspath();
  156. String[] cps = LangUtil.splitClasspath(cp);
  157. for (int i = 0; (i < cps.length) && (null == result); i++) {
  158. result = isAspectjtoolsjar(cps[i]);
  159. }
  160. }
  161. if (null == result) {
  162. final Path classpath = Path.systemClasspath;
  163. final String[] paths = classpath.list();
  164. for (int i = 0; (i < paths.length) && (null == result); i++) {
  165. result = isAspectjtoolsjar(paths[i]);
  166. }
  167. }
  168. return (null == result? null : result.getAbsoluteFile());
  169. }
  170. /** @return File if readable jar with aspectj tools name, or null */
  171. private static File isAspectjtoolsjar(String path) {
  172. if (null == path) {
  173. return null;
  174. }
  175. final String prefix = "aspectj";
  176. final String infix = "tools";
  177. final String altInfix = "-tools";
  178. final String suffix = ".jar";
  179. final int prefixLength = 7; // prefix.length();
  180. final int minLength = 16;
  181. // prefixLength + infix.length() + suffix.length();
  182. if (!path.endsWith(suffix)) {
  183. return null;
  184. }
  185. int loc = path.lastIndexOf(prefix);
  186. if ((-1 != loc) && ((loc + minLength) <= path.length())) {
  187. String rest = path.substring(loc+prefixLength);
  188. if (-1 != rest.indexOf(File.pathSeparator)) {
  189. return null;
  190. }
  191. if (rest.startsWith(infix)
  192. || rest.startsWith(altInfix)) {
  193. File result = new File(path);
  194. if (result.canRead() && result.isFile()) {
  195. return result;
  196. }
  197. }
  198. }
  199. return null;
  200. }
  201. /**
  202. * Maximum length (in chars) of command line
  203. * before converting to an argfile when forking
  204. */
  205. private static final int MAX_COMMANDLINE = 4096;
  206. private static final File DEFAULT_DESTDIR = new File(".") {
  207. public String toString() {
  208. return "(no destination dir specified)";
  209. }
  210. };
  211. /** do not throw BuildException on fail/abort message with usage */
  212. private static final String USAGE_SUBSTRING = "AspectJ-specific options";
  213. /** valid -X[...] options other than -Xlint variants */
  214. private static final List VALID_XOPTIONS;
  215. /** valid warning (-warn:[...]) variants */
  216. private static final List VALID_WARNINGS;
  217. /** valid debugging (-g:[...]) variants */
  218. private static final List VALID_DEBUG;
  219. /**
  220. * -Xlint variants (error, warning, ignore)
  221. * @see org.aspectj.weaver.Lint
  222. */
  223. private static final List VALID_XLINT;
  224. public static final String COMMAND_EDITOR_NAME
  225. = AjcTask.class.getName() + ".COMMAND_EDITOR";
  226. private static final ICommandEditor COMMAND_EDITOR;
  227. static {
  228. String[] xs = new String[]
  229. { "serializableAspects", "incrementalFile"
  230. //, "targetNearSource", "OcodeSize",
  231. };
  232. VALID_XOPTIONS = Collections.unmodifiableList(Arrays.asList(xs));
  233. xs = new String[]
  234. {"constructorName", "packageDefaultMethod", "deprecation",
  235. "maskedCatchBlocks", "unusedLocals", "unusedArguments",
  236. "unusedImports", "syntheticAccess", "assertIdentifier", "none" };
  237. VALID_WARNINGS = Collections.unmodifiableList(Arrays.asList(xs));
  238. xs = new String[] {"none", "lines", "vars", "source" };
  239. VALID_DEBUG = Collections.unmodifiableList(Arrays.asList(xs));
  240. xs = new String[] { "error", "warning", "ignore"};
  241. VALID_XLINT = Collections.unmodifiableList(Arrays.asList(xs));
  242. ICommandEditor editor = null;
  243. try {
  244. String editorClassName = System.getProperty(COMMAND_EDITOR_NAME);
  245. if (null != editorClassName) {
  246. ClassLoader cl = AjcTask.class.getClassLoader();
  247. Class editorClass = cl.loadClass(editorClassName);
  248. editor = (ICommandEditor) editorClass.newInstance();
  249. }
  250. } catch (Throwable t) {
  251. System.err.println("Warning: unable to load command editor");
  252. t.printStackTrace(System.err);
  253. }
  254. COMMAND_EDITOR = editor;
  255. }
  256. // ---------------------------- state and Ant interface thereto
  257. private boolean verbose;
  258. private boolean listFileArgs;
  259. private boolean failonerror;
  260. private boolean fork;
  261. private String maxMem;
  262. // ------- single entries dumped into cmd
  263. protected GuardedCommand cmd;
  264. // ------- lists resolved in addListArgs() at execute() time
  265. private Path srcdir;
  266. private Path injars;
  267. private Path inpath;
  268. private Path classpath;
  269. private Path bootclasspath;
  270. private Path forkclasspath;
  271. private Path extdirs;
  272. private Path aspectpath;
  273. private Path argfiles;
  274. private List ignored;
  275. private Path sourceRoots;
  276. private File xweaveDir;
  277. // ----- added by adapter - integrate better?
  278. private List /* File */ adapterFiles;
  279. private String[] adapterArguments;
  280. private IMessageHolder messageHolder;
  281. private ICommandEditor commandEditor;
  282. // -------- resource-copying
  283. /** true if copying injar non-.class files to the output jar */
  284. private boolean copyInjars;
  285. private boolean copyInpath;
  286. /** non-null if copying all source root files but the filtered ones */
  287. private String sourceRootCopyFilter;
  288. /** directory sink for classes */
  289. private File destDir;
  290. /** zip file sink for classes */
  291. private File outjar;
  292. /** track whether we've supplied any temp outjar */
  293. private boolean outjarFixedup;
  294. /**
  295. * When possibly copying resources to the output jar,
  296. * pass ajc a fake output jar to copy from,
  297. * so we don't change the modification time of the output jar
  298. * when copying injars/inpath into the actual outjar.
  299. */
  300. private File tmpOutjar;
  301. private boolean executing;
  302. /** non-null only while executing in same vm */
  303. private Main main;
  304. /** true only when executing in other vm */
  305. private boolean executingInOtherVM;
  306. /** true if -incremental */
  307. private boolean inIncrementalMode;
  308. /** true if -XincrementalFile (i.e, setTagFile)*/
  309. private boolean inIncrementalFileMode;
  310. // also note MatchingTask grabs source files...
  311. public AjcTask() {
  312. reset();
  313. }
  314. /** to use this same Task more than once (testing) */
  315. public void reset() { // XXX possible to reset MatchingTask?
  316. // need declare for "all fields initialized in ..."
  317. adapterArguments = null;
  318. adapterFiles = new ArrayList();
  319. argfiles = null;
  320. executing = false;
  321. aspectpath = null;
  322. bootclasspath = null;
  323. classpath = null;
  324. cmd = new GuardedCommand();
  325. copyInjars = false;
  326. copyInpath = false;
  327. destDir = DEFAULT_DESTDIR;
  328. executing = false;
  329. executingInOtherVM = false;
  330. extdirs = null;
  331. failonerror = true; // non-standard default
  332. forkclasspath = null;
  333. inIncrementalMode = false;
  334. inIncrementalFileMode = false;
  335. ignored = new ArrayList();
  336. injars = null;
  337. inpath = null;
  338. listFileArgs = false;
  339. maxMem = null;
  340. messageHolder = null;
  341. outjar = null;
  342. sourceRootCopyFilter = null;
  343. sourceRoots = null;
  344. srcdir = null;
  345. tmpOutjar = null;
  346. verbose = false;
  347. xweaveDir = null;
  348. }
  349. protected void ignore(String ignored) {
  350. this.ignored.add(ignored + " at " + getLocation());
  351. }
  352. //---------------------- option values
  353. // used by entries with internal commas
  354. protected String validCommaList(String list, List valid, String label) {
  355. return validCommaList(list, valid, label, valid.size());
  356. }
  357. protected String validCommaList(String list, List valid, String label, int max) {
  358. StringBuffer result = new StringBuffer();
  359. StringTokenizer st = new StringTokenizer(list, ",");
  360. int num = 0;
  361. while (st.hasMoreTokens()) {
  362. String token = st.nextToken().trim();
  363. num++;
  364. if (num > max) {
  365. ignore("too many entries for -"
  366. + label
  367. + ": "
  368. + token);
  369. break;
  370. }
  371. if (!valid.contains(token)) {
  372. ignore("bad commaList entry for -"
  373. + label
  374. + ": "
  375. + token);
  376. } else {
  377. if (0 < result.length()) {
  378. result.append(",");
  379. }
  380. result.append(token);
  381. }
  382. }
  383. return (0 == result.length() ? null : result.toString());
  384. }
  385. public void setIncremental(boolean incremental) {
  386. cmd.addFlag("-incremental", incremental);
  387. inIncrementalMode = incremental;
  388. }
  389. public void setHelp(boolean help) {
  390. cmd.addFlag("-help", help);
  391. }
  392. public void setVersion(boolean version) {
  393. cmd.addFlag("-version", version);
  394. }
  395. public void setXNoweave(boolean noweave) {
  396. cmd.addFlag("-XnoWeave", noweave);
  397. }
  398. public void setNowarn(boolean nowarn) {
  399. cmd.addFlag("-nowarn", nowarn);
  400. }
  401. public void setDeprecation(boolean deprecation) {
  402. cmd.addFlag("-deprecation", deprecation);
  403. }
  404. public void setWarn(String warnings) {
  405. warnings = validCommaList(warnings, VALID_WARNINGS, "warn");
  406. cmd.addFlag("-warn:" + warnings, (null != warnings));
  407. }
  408. public void setDebug(boolean debug) {
  409. cmd.addFlag("-g", debug);
  410. }
  411. public void setDebugLevel(String level) {
  412. level = validCommaList(level, VALID_DEBUG, "g");
  413. cmd.addFlag("-g:" + level, (null != level));
  414. }
  415. public void setEmacssym(boolean emacssym) {
  416. cmd.addFlag("-emacssym", emacssym);
  417. }
  418. /**
  419. * -Xlint - set default level of -Xlint messages to warning
  420. * (same as </code>-Xlint:warning</code>)
  421. */
  422. public void setXlintwarnings(boolean xlintwarnings) {
  423. cmd.addFlag("-Xlint", xlintwarnings);
  424. }
  425. /** -Xlint:{error|warning|info} - set default level for -Xlint messages
  426. * @param xlint the String with one of error, warning, ignored
  427. */
  428. public void setXlint(String xlint) {
  429. xlint = validCommaList(xlint, VALID_XLINT, "Xlint", 1);
  430. cmd.addFlag("-Xlint:" + xlint, (null != xlint));
  431. }
  432. /**
  433. * -Xlintfile {lint.properties} - enable or disable specific forms
  434. * of -Xlint messages based on a lint properties file
  435. * (default is
  436. * <code>org/aspectj/weaver/XLintDefault.properties</code>)
  437. * @param xlintFile the File with lint properties
  438. */
  439. public void setXlintfile(File xlintFile) {
  440. cmd.addFlagged("-Xlintfile", xlintFile.getAbsolutePath());
  441. }
  442. public void setPreserveAllLocals(boolean preserveAllLocals) {
  443. cmd.addFlag("-preserveAllLocals", preserveAllLocals);
  444. }
  445. public void setNoImportError(boolean noImportError) {
  446. cmd.addFlag("-warn:-unusedImport", noImportError);
  447. }
  448. public void setEncoding(String encoding) {
  449. cmd.addFlagged("-encoding", encoding);
  450. }
  451. public void setLog(File file) {
  452. cmd.addFlagged("-log", file.getAbsolutePath());
  453. }
  454. public void setProceedOnError(boolean proceedOnError) {
  455. cmd.addFlag("-proceedOnError", proceedOnError);
  456. }
  457. public void setVerbose(boolean verbose) {
  458. cmd.addFlag("-verbose", verbose);
  459. this.verbose = verbose;
  460. }
  461. public void setListFileArgs(boolean listFileArgs) {
  462. this.listFileArgs = listFileArgs;
  463. }
  464. public void setReferenceInfo(boolean referenceInfo) {
  465. cmd.addFlag("-referenceInfo", referenceInfo);
  466. }
  467. public void setProgress(boolean progress) {
  468. cmd.addFlag("-progress", progress);
  469. }
  470. public void setTime(boolean time) {
  471. cmd.addFlag("-time", time);
  472. }
  473. public void setNoExit(boolean noExit) {
  474. cmd.addFlag("-noExit", noExit);
  475. }
  476. public void setFailonerror(boolean failonerror) {
  477. this.failonerror = failonerror;
  478. }
  479. /**
  480. * @return true if fork was set
  481. */
  482. public boolean isForked() {
  483. return fork;
  484. }
  485. public void setFork(boolean fork) {
  486. this.fork = fork;
  487. }
  488. public void setMaxmem(String maxMem) {
  489. this.maxMem = maxMem;
  490. }
  491. // ----------------
  492. public void setTagFile(File file) {
  493. inIncrementalMode = true;
  494. cmd.addFlagged(Main.CommandController.TAG_FILE_OPTION,
  495. file.getAbsolutePath());
  496. inIncrementalFileMode = true;
  497. }
  498. public void setOutjar(File file) {
  499. if (DEFAULT_DESTDIR != destDir) {
  500. String e = "specifying both output jar ("
  501. + file
  502. + ") and destination dir ("
  503. + destDir
  504. + ")";
  505. throw new BuildException(e);
  506. }
  507. outjar = file;
  508. outjarFixedup = false;
  509. tmpOutjar = null;
  510. }
  511. public void setDestdir(File dir) {
  512. if (null != outjar) {
  513. String e = "specifying both output jar ("
  514. + outjar
  515. + ") and destination dir ("
  516. + dir
  517. + ")";
  518. throw new BuildException(e);
  519. }
  520. cmd.addFlagged("-d", dir.getAbsolutePath());
  521. destDir = dir;
  522. }
  523. public void setTarget(String either11or12) {
  524. if ("1.1".equals(either11or12)) {
  525. cmd.addFlagged("-target", "1.1");
  526. } else if ("1.2".equals(either11or12)) {
  527. cmd.addFlagged("-target", "1.2");
  528. } else if (null != either11or12){
  529. ignore("-target " + either11or12);
  530. }
  531. }
  532. /**
  533. * Language compliance level.
  534. * If not set explicitly, eclipse default holds.
  535. * @param either13or14 either "1.3" or "1.4"
  536. */
  537. public void setCompliance(String either13or14) {
  538. if ("1.3".equals(either13or14)) {
  539. cmd.addFlag("-1.3", true);
  540. } else if ("1.4".equals(either13or14)) {
  541. cmd.addFlag("-1.4", true);
  542. // } else if ("1.5".equals(either13or14)) {
  543. // cmd.addFlag("-1.5", true);
  544. } else if (null != either13or14) {
  545. ignore(either13or14 + "[compliance]");
  546. }
  547. }
  548. /**
  549. * Source compliance level.
  550. * If not set explicitly, eclipse default holds.
  551. * @param either13or14 either "1.3" or "1.4"
  552. */
  553. public void setSource(String either13or14) {
  554. if ("1.3".equals(either13or14)) {
  555. cmd.addFlagged("-source", "1.3");
  556. } else if ("1.4".equals(either13or14)) {
  557. cmd.addFlagged("-source", "1.4");
  558. } else if (null != either13or14) {
  559. ignore("-source " + either13or14);
  560. }
  561. }
  562. /**
  563. * Flag to copy all non-.class contents of injars
  564. * to outjar after compile completes.
  565. * Requires both injars and outjar.
  566. * @param doCopy
  567. */
  568. public void setCopyInjars(boolean doCopy){
  569. ignore("copyInJars");
  570. log("copyInjars not required since 1.1.1.\n", Project.MSG_WARN);
  571. //this.copyInjars = doCopy;
  572. }
  573. /**
  574. * Option to copy all files from
  575. * all source root directories
  576. * except those specified here.
  577. * If this is specified and sourceroots are specified,
  578. * then this will copy all files except
  579. * those specified in the filter pattern.
  580. * Requires sourceroots.
  581. *
  582. * @param filter a String acceptable as an excludes
  583. * filter for an Ant Zip fileset.
  584. */
  585. public void setSourceRootCopyFilter(String filter){
  586. this.sourceRootCopyFilter = filter;
  587. }
  588. public void setX(String input) { // ajc-only eajc-also docDone
  589. StringTokenizer tokens = new StringTokenizer(input, ",", false);
  590. while (tokens.hasMoreTokens()) {
  591. String token = tokens.nextToken().trim();
  592. if (1 < token.length()) {
  593. if (VALID_XOPTIONS.contains(token)) {
  594. cmd.addFlag("-X" + token, true);
  595. } else {
  596. ignore("-X" + token);
  597. }
  598. }
  599. }
  600. }
  601. /** direct API for testing */
  602. public void setMessageHolder(IMessageHolder holder) {
  603. this.messageHolder = holder;
  604. }
  605. /**
  606. * Setup custom message handling.
  607. * @param className the String fully-qualified-name of a class
  608. * reachable from this object's class loader,
  609. * implementing IMessageHolder, and
  610. * having a public no-argument constructor.
  611. * @throws BuildException if unable to create instance of className
  612. */
  613. public void setMessageHolderClass(String className) {
  614. try {
  615. Class mclass = Class.forName(className);
  616. IMessageHolder holder = (IMessageHolder) mclass.newInstance();
  617. setMessageHolder(holder);
  618. } catch (Throwable t) {
  619. String m = "unable to instantiate message holder: " + className;
  620. throw new BuildException(m, t);
  621. }
  622. }
  623. /** direct API for testing */
  624. public void setCommandEditor(ICommandEditor editor) {
  625. this.commandEditor = editor;
  626. }
  627. /**
  628. * Setup command-line filter.
  629. * To do this staticly, define the environment variable
  630. * <code>org.aspectj.tools.ant.taskdefs.AjcTask.COMMAND_EDITOR</code>
  631. * with the <code>className</code> parameter.
  632. * @param className the String fully-qualified-name of a class
  633. * reachable from this object's class loader,
  634. * implementing ICommandEditor, and
  635. * having a public no-argument constructor.
  636. * @throws BuildException if unable to create instance of className
  637. */
  638. public void setCommandEditorClass(String className) { // skip Ant interface?
  639. try {
  640. Class mclass = Class.forName(className);
  641. setCommandEditor((ICommandEditor) mclass.newInstance());
  642. } catch (Throwable t) {
  643. String m = "unable to instantiate command editor: " + className;
  644. throw new BuildException(m, t);
  645. }
  646. }
  647. //---------------------- Path lists
  648. /**
  649. * Add path elements to source path and return result.
  650. * Elements are added even if they do not exist.
  651. * @param source the Path to add to - may be null
  652. * @param toAdd the Path to add - may be null
  653. * @return the (never-null) Path that results
  654. */
  655. protected Path incPath(Path source, Path toAdd) {
  656. if (null == source) {
  657. source = new Path(project);
  658. }
  659. if (null != toAdd) {
  660. source.append(toAdd);
  661. }
  662. return source;
  663. }
  664. public void setSourcerootsref(Reference ref) {
  665. createSourceRoots().setRefid(ref);
  666. }
  667. public void setSourceRoots(Path roots) {
  668. sourceRoots = incPath(sourceRoots, roots);
  669. }
  670. public Path createSourceRoots() {
  671. if (sourceRoots == null) {
  672. sourceRoots = new Path(project);
  673. }
  674. return sourceRoots.createPath();
  675. }
  676. public void setXWeaveDir(File file) {
  677. if ((null != file) && file.isDirectory()
  678. && file.canRead()) {
  679. xweaveDir = file;
  680. }
  681. }
  682. public void setInjarsref(Reference ref) {
  683. createInjars().setRefid(ref);
  684. }
  685. public void setInpathref(Reference ref) {
  686. createInpath().setRefid(ref);
  687. }
  688. public void setInjars(Path path) {
  689. injars = incPath(injars, path);
  690. }
  691. public void setInpath(Path path) {
  692. inpath = incPath(inpath,path);
  693. }
  694. public Path createInjars() {
  695. if (injars == null) {
  696. injars = new Path(project);
  697. }
  698. return injars.createPath();
  699. }
  700. public Path createInpath() {
  701. if (inpath == null) {
  702. inpath = new Path(project);
  703. }
  704. return inpath.createPath();
  705. }
  706. public void setClasspath(Path path) {
  707. classpath = incPath(classpath, path);
  708. }
  709. public void setClasspathref(Reference classpathref) {
  710. createClasspath().setRefid(classpathref);
  711. }
  712. public Path createClasspath() {
  713. if (classpath == null) {
  714. classpath = new Path(project);
  715. }
  716. return classpath.createPath();
  717. }
  718. public void setBootclasspath(Path path) {
  719. bootclasspath = incPath(bootclasspath, path);
  720. }
  721. public void setBootclasspathref(Reference bootclasspathref) {
  722. createBootclasspath().setRefid(bootclasspathref);
  723. }
  724. public Path createBootclasspath() {
  725. if (bootclasspath == null) {
  726. bootclasspath = new Path(project);
  727. }
  728. return bootclasspath.createPath();
  729. }
  730. public void setForkclasspath(Path path) {
  731. forkclasspath = incPath(forkclasspath, path);
  732. }
  733. public void setForkclasspathref(Reference forkclasspathref) {
  734. createForkclasspath().setRefid(forkclasspathref);
  735. }
  736. public Path createForkclasspath() {
  737. if (forkclasspath == null) {
  738. forkclasspath = new Path(project);
  739. }
  740. return forkclasspath.createPath();
  741. }
  742. public void setExtdirs(Path path) {
  743. extdirs = incPath(extdirs, path);
  744. }
  745. public void setExtdirsref(Reference ref) {
  746. createExtdirs().setRefid(ref);
  747. }
  748. public Path createExtdirs() {
  749. if (extdirs == null) {
  750. extdirs = new Path(project);
  751. }
  752. return extdirs.createPath();
  753. }
  754. public void setAspectpathref(Reference ref) {
  755. createAspectpath().setRefid(ref);
  756. }
  757. public void setAspectpath(Path path) {
  758. aspectpath = incPath(aspectpath, path);
  759. }
  760. public Path createAspectpath() {
  761. if (aspectpath == null) {
  762. aspectpath = new Path(project);
  763. }
  764. return aspectpath.createPath();
  765. }
  766. public void setSrcDir(Path path) {
  767. srcdir = incPath(srcdir, path);
  768. }
  769. public Path createSrc() {
  770. return createSrcdir();
  771. }
  772. public Path createSrcdir() {
  773. if (srcdir == null) {
  774. srcdir = new Path(project);
  775. }
  776. return srcdir.createPath();
  777. }
  778. /** @return true if in incremental mode (command-line or file) */
  779. public boolean isInIncrementalMode() {
  780. return inIncrementalMode;
  781. }
  782. /** @return true if in incremental file mode */
  783. public boolean isInIncrementalFileMode() {
  784. return inIncrementalFileMode;
  785. }
  786. public void setArgfilesref(Reference ref) {
  787. createArgfiles().setRefid(ref);
  788. }
  789. public void setArgfiles(Path path) { // ajc-only eajc-also docDone
  790. argfiles = incPath(argfiles, path);
  791. }
  792. public Path createArgfiles() {
  793. if (argfiles == null) {
  794. argfiles = new Path(project);
  795. }
  796. return argfiles.createPath();
  797. }
  798. // ------------------------------ run
  799. /**
  800. * Compile using ajc per settings.
  801. * @exception BuildException if the compilation has problems
  802. * or if there were compiler errors and failonerror is true.
  803. */
  804. public void execute() throws BuildException {
  805. if (executing) {
  806. throw new IllegalStateException("already executing");
  807. } else {
  808. executing = true;
  809. }
  810. setupOptions();
  811. verifyOptions();
  812. try {
  813. String[] args = makeCommand();
  814. if (verbose || listFileArgs) { // XXX if listFileArgs, only do that
  815. log("ajc " + Arrays.asList(args), Project.MSG_VERBOSE);
  816. }
  817. if (!fork) {
  818. executeInSameVM(args);
  819. } else { // when forking, Adapter handles failonerror
  820. executeInOtherVM(args);
  821. }
  822. } catch (BuildException e) {
  823. throw e;
  824. } catch (Throwable x) {
  825. System.err.println(Main.renderExceptionForUser(x));
  826. throw new BuildException("IGNORE -- See "
  827. + LangUtil.unqualifiedClassName(x)
  828. + " rendered to System.err");
  829. } finally {
  830. executing = false;
  831. if (null != tmpOutjar) {
  832. tmpOutjar.delete();
  833. }
  834. }
  835. }
  836. /**
  837. * Halt processing.
  838. * This tells main in the same vm to quit.
  839. * It fails when running in forked mode.
  840. * @return true if not in forked mode
  841. * and main has quit or been told to quit
  842. */
  843. public boolean quit() {
  844. if (executingInOtherVM) {
  845. return false;
  846. }
  847. Main me = main;
  848. if (null != me) {
  849. me.quit();
  850. }
  851. return true;
  852. }
  853. // package-private for testing
  854. String[] makeCommand() {
  855. ArrayList result = new ArrayList();
  856. if (0 < ignored.size()) {
  857. for (Iterator iter = ignored.iterator(); iter.hasNext();) {
  858. log("ignored: " + iter.next(), Project.MSG_INFO);
  859. }
  860. }
  861. // when copying resources, use temp jar for class output
  862. // then copy temp jar contents and resources to output jar
  863. if ((null != outjar) && !outjarFixedup) {
  864. if (copyInjars || copyInpath || (null != sourceRootCopyFilter)) {
  865. String path = outjar.getAbsolutePath();
  866. int len = FileUtil.zipSuffixLength(path);
  867. if (len < 1) {
  868. log("not copying resources - weird outjar: " + path);
  869. } else {
  870. path = path.substring(0, path.length()-len) + ".tmp.jar";
  871. tmpOutjar = new File(path);
  872. }
  873. }
  874. if (null == tmpOutjar) {
  875. cmd.addFlagged("-outjar", outjar.getAbsolutePath());
  876. } else {
  877. cmd.addFlagged("-outjar", tmpOutjar.getAbsolutePath());
  878. }
  879. outjarFixedup = true;
  880. }
  881. result.addAll(cmd.extractArguments());
  882. addListArgs(result);
  883. String[] command = (String[]) result.toArray(new String[0]);
  884. if (null != commandEditor) {
  885. command = commandEditor.editCommand(command);
  886. } else if (null != COMMAND_EDITOR) {
  887. command = COMMAND_EDITOR.editCommand(command);
  888. }
  889. return command;
  890. }
  891. /**
  892. * Create any pseudo-options required to implement
  893. * some of the macro options
  894. * @throws BuildException if options conflict
  895. */
  896. protected void setupOptions() {
  897. if (null != xweaveDir) {
  898. if (DEFAULT_DESTDIR != destDir) {
  899. throw new BuildException("weaveDir forces destdir");
  900. }
  901. if (null != outjar) {
  902. throw new BuildException("weaveDir forces outjar");
  903. }
  904. if (null != injars) {
  905. throw new BuildException("weaveDir incompatible with injars now");
  906. }
  907. if (null != inpath) {
  908. throw new BuildException("weaveDir incompatible with inpath now");
  909. }
  910. File injar = zipDirectory(xweaveDir);
  911. setInjars(new Path(getProject(), injar.getAbsolutePath()));
  912. setDestdir(xweaveDir);
  913. }
  914. }
  915. protected File zipDirectory(File dir) {
  916. File tempDir = new File(".");
  917. try {
  918. tempDir = File.createTempFile("AjcTest", ".tmp");
  919. tempDir.mkdirs();
  920. tempDir.deleteOnExit(); // XXX remove zip explicitly..
  921. } catch (IOException e) {
  922. // ignore
  923. }
  924. // File result = new File(tempDir,
  925. String filename = "AjcTask-"
  926. + System.currentTimeMillis()
  927. + ".zip";
  928. File result = new File(filename);
  929. Zip zip = new Zip();
  930. zip.setProject(getProject());
  931. zip.setDestFile(result);
  932. zip.setTaskName(getTaskName() + " - zip");
  933. FileSet fileset = new FileSet();
  934. fileset.setDir(dir);
  935. zip.addFileset(fileset);
  936. zip.execute();
  937. Delete delete = new Delete();
  938. delete.setProject(getProject());
  939. delete.setTaskName(getTaskName() + " - delete");
  940. delete.setDir(dir);
  941. delete.execute();
  942. Mkdir mkdir = new Mkdir();
  943. mkdir.setProject(getProject());
  944. mkdir.setTaskName(getTaskName() + " - mkdir");
  945. mkdir.setDir(dir);
  946. mkdir.execute();
  947. return result;
  948. }
  949. /**
  950. * @throw BuildException if options conflict
  951. */
  952. protected void verifyOptions() {
  953. StringBuffer sb = new StringBuffer();
  954. if (fork && isInIncrementalMode() && !isInIncrementalFileMode()) {
  955. sb.append("can fork incremental only using tag file.\n");
  956. }
  957. if ((null != sourceRootCopyFilter) && (null == outjar)
  958. && (DEFAULT_DESTDIR == destDir)) {
  959. final String REQ = " requires dest dir or output jar.\n"; sb.append("sourceRootCopyFilter");
  960. sb.append(REQ);
  961. }
  962. if (0 < sb.length()) {
  963. throw new BuildException(sb.toString());
  964. }
  965. }
  966. /**
  967. * Run the compile in the same VM by
  968. * loading the compiler (Main),
  969. * setting up any message holders,
  970. * doing the compile,
  971. * and converting abort/failure and error messages
  972. * to BuildException, as appropriate.
  973. * @throws BuildException if abort or failure messages
  974. * or if errors and failonerror.
  975. *
  976. */
  977. protected void executeInSameVM(String[] args) {
  978. if (null != maxMem) {
  979. log("maxMem ignored unless forked: " + maxMem, Project.MSG_WARN);
  980. }
  981. IMessageHolder holder = messageHolder;
  982. int numPreviousErrors;
  983. if (null == holder) {
  984. MessageHandler mhandler = new MessageHandler(true);
  985. final IMessageHandler delegate
  986. = verbose ? MessagePrinter.VERBOSE: MessagePrinter.TERSE;
  987. mhandler.setInterceptor(delegate);
  988. if (!verbose) {
  989. mhandler.ignore(IMessage.INFO);
  990. }
  991. holder = mhandler;
  992. numPreviousErrors = 0;
  993. } else {
  994. numPreviousErrors = holder.numMessages(IMessage.ERROR, true);
  995. }
  996. {
  997. Main newmain = new Main();
  998. newmain.setHolder(holder);
  999. newmain.setCompletionRunner(new Runnable() {
  1000. public void run() {
  1001. doCompletionTasks();
  1002. }
  1003. });
  1004. if (null != main) {
  1005. MessageUtil.fail(holder, "still running prior main");
  1006. return;
  1007. }
  1008. main = newmain;
  1009. }
  1010. try {
  1011. main.runMain(args, false);
  1012. } finally {
  1013. main = null;
  1014. }
  1015. if (failonerror) {
  1016. int errs = holder.numMessages(IMessage.ERROR, false);
  1017. errs -= numPreviousErrors;
  1018. if (0 < errs) {
  1019. String m = errs + " errors";
  1020. MessageUtil.print(System.err, holder, "", MessageUtil.MESSAGE_ALL, MessageUtil.PICK_ERROR, true);
  1021. throw new BuildException(m);
  1022. }
  1023. }
  1024. // Throw BuildException if there are any fail or abort
  1025. // messages.
  1026. // The BuildException message text has a list of class names
  1027. // for the exceptions found in the messages, or the
  1028. // number of fail/abort messages found if there were
  1029. // no exceptions for any of the fail/abort messages.
  1030. // The interceptor message handler should have already
  1031. // printed the messages, including any stack traces.
  1032. // HACK: this ignores the Usage message
  1033. {
  1034. IMessage[] fails = holder.getMessages(IMessage.FAIL, true);
  1035. if (!LangUtil.isEmpty(fails)) {
  1036. StringBuffer sb = new StringBuffer();
  1037. String prefix = "fail due to ";
  1038. int numThrown = 0;
  1039. for (int i = 0; i < fails.length; i++) {
  1040. String message = fails[i].getMessage();
  1041. if (LangUtil.isEmpty(message)) {
  1042. message = "<no message>";
  1043. } else if (-1 != message.indexOf(USAGE_SUBSTRING)) {
  1044. continue;
  1045. }
  1046. Throwable t = fails[i].getThrown();
  1047. if (null != t) {
  1048. numThrown++;
  1049. sb.append(prefix);
  1050. sb.append(LangUtil.unqualifiedClassName(t.getClass()));
  1051. String thrownMessage = t.getMessage();
  1052. if (!LangUtil.isEmpty(thrownMessage)) {
  1053. sb.append(" \"" + thrownMessage + "\"");
  1054. }
  1055. }
  1056. sb.append("\"" + message + "\"");
  1057. prefix = ", ";
  1058. }
  1059. if (0 < sb.length()) {
  1060. sb.append(" (" + numThrown + " exceptions)");
  1061. throw new BuildException(sb.toString());
  1062. }
  1063. }
  1064. }
  1065. }
  1066. /**
  1067. * Execute in a separate VM.
  1068. * Differences from normal same-VM execution:
  1069. * <ul>
  1070. * <li>ignores any message holder {class} set</li>
  1071. * <li>No resource-copying between interative runs</li>
  1072. * <li>failonerror fails when process interface fails
  1073. * to return negative values</li>
  1074. * </ul>
  1075. * @param args String[] of the complete compiler command to execute
  1076. *
  1077. * @see DefaultCompilerAdapter#executeExternalCompile(String[], int)
  1078. * @throws BuildException if ajc aborts (negative value)
  1079. * or if failonerror and there were compile errors.
  1080. */
  1081. protected void executeInOtherVM(String[] args) {
  1082. if (null != messageHolder) {
  1083. log("message holder ignored when forking: "
  1084. + messageHolder.getClass().getName(), Project.MSG_WARN);
  1085. }
  1086. CommandlineJava javaCmd = new CommandlineJava();
  1087. javaCmd.setClassname(org.aspectj.tools.ajc.Main.class.getName());
  1088. final Path vmClasspath = javaCmd.createClasspath(getProject());
  1089. {
  1090. File aspectjtools = null;
  1091. int vmClasspathSize = vmClasspath.size();
  1092. if ((null != forkclasspath)
  1093. && (0 != forkclasspath.size())) {
  1094. vmClasspath.addExisting(forkclasspath);
  1095. } else {
  1096. aspectjtools = findAspectjtoolsJar();
  1097. if (null != aspectjtools) {
  1098. vmClasspath.createPathElement().setLocation(aspectjtools);
  1099. }
  1100. }
  1101. int newVmClasspathSize = vmClasspath.size();
  1102. if (vmClasspathSize == newVmClasspathSize) {
  1103. String m = "unable to find aspectjtools to fork - ";
  1104. if (null != aspectjtools) {
  1105. m += "tried " + aspectjtools.toString();
  1106. } else if (null != forkclasspath) {
  1107. m += "tried " + forkclasspath.toString();
  1108. } else {
  1109. m += "define forkclasspath or put aspectjtools on classpath";
  1110. }
  1111. throw new BuildException(m);
  1112. }
  1113. }
  1114. if (null != maxMem) {
  1115. javaCmd.setMaxmemory(maxMem);
  1116. }
  1117. File tempFile = null;
  1118. int numArgs = args.length;
  1119. args = GuardedCommand.limitTo(args, MAX_COMMANDLINE, getLocation());
  1120. if (args.length != numArgs) {
  1121. tempFile = new File(args[1]);
  1122. }
  1123. try {
  1124. String[] javaArgs = javaCmd.getCommandline();
  1125. String[] both = new String[javaArgs.length + args.length];
  1126. System.arraycopy(javaArgs,0,both,0,javaArgs.length);
  1127. System.arraycopy(args,0,both,javaArgs.length,args.length);
  1128. // try to use javaw instead on windows
  1129. if (both[0].endsWith("java.exe")) {
  1130. String path = both[0];
  1131. path = path.substring(0, path.length()-4);
  1132. path = path + "w.exe";
  1133. File javaw = new File(path);
  1134. if (javaw.canRead() && javaw.isFile()) {
  1135. both[0] = path;
  1136. }
  1137. }
  1138. if (verbose) { // XXX also when ant is verbose...
  1139. log("forking " + Arrays.asList(both));
  1140. }
  1141. int result = execInOtherVM(both);
  1142. if (0 > result) {
  1143. throw new BuildException("failure[" + result + "] running ajc");
  1144. } else if (failonerror && (0 < result)) {
  1145. throw new BuildException("compile errors: " + result);
  1146. }
  1147. // when forking, do completion only at end and when successful
  1148. doCompletionTasks();
  1149. } finally {
  1150. if (null != tempFile) {
  1151. tempFile.delete();
  1152. }
  1153. }
  1154. }
  1155. /**
  1156. * Execute in another process using the same JDK
  1157. * and the base directory of the project. XXX correct?
  1158. * @param args
  1159. * @return
  1160. */
  1161. protected int execInOtherVM(String[] args) {
  1162. try {
  1163. Project project = getProject();
  1164. LogStreamHandler handler = new LogStreamHandler(this,
  1165. Project.MSG_INFO, Project.MSG_WARN);
  1166. Execute exe = new Execute(handler);
  1167. exe.setAntRun(project);
  1168. exe.setWorkingDirectory(project.getBaseDir());
  1169. exe.setCommandline(args);
  1170. try {
  1171. if (executingInOtherVM) {
  1172. String s = "already running in other vm?";
  1173. throw new BuildException(s, location);
  1174. }
  1175. executingInOtherVM = true;
  1176. exe.execute();
  1177. } finally {
  1178. executingInOtherVM = false;
  1179. }
  1180. return exe.getExitValue();
  1181. } catch (IOException e) {
  1182. String m = "Error executing command " + Arrays.asList(args);
  1183. throw new BuildException(m, e, location);
  1184. }
  1185. }
  1186. // ------------------------------ setup and reporting
  1187. /** @return null if path null or empty, String rendition otherwise */
  1188. protected static void addFlaggedPath(String flag, Path path, List list) {
  1189. if (!LangUtil.isEmpty(flag)
  1190. && ((null != path) && (0 < path.size()))) {
  1191. list.add(flag);
  1192. list.add(path.toString());
  1193. }
  1194. }
  1195. /**
  1196. * Add to list any path or plural arguments.
  1197. */
  1198. protected void addListArgs(List list) throws BuildException {
  1199. addFlaggedPath("-classpath", classpath, list);
  1200. addFlaggedPath("-bootclasspath", bootclasspath, list);
  1201. addFlaggedPath("-extdirs", extdirs, list);
  1202. addFlaggedPath("-aspectpath", aspectpath, list);
  1203. addFlaggedPath("-injars", injars, list);
  1204. addFlaggedPath("-inpath", inpath, list);
  1205. addFlaggedPath("-sourceroots", sourceRoots, list);
  1206. if (argfiles != null) {
  1207. String[] files = argfiles.list();
  1208. for (int i = 0; i < files.length; i++) {
  1209. File argfile = project.resolveFile(files[i]);
  1210. if (check(argfile, files[i], false, location)) {
  1211. list.add("-argfile");
  1212. list.add(argfile.getAbsolutePath());
  1213. }
  1214. }
  1215. }
  1216. if (srcdir != null) {
  1217. // todo: ignore any srcdir if any argfiles and no explicit includes
  1218. String[] dirs = srcdir.list();
  1219. for (int i = 0; i < dirs.length; i++) {
  1220. File dir = project.resolveFile(dirs[i]);
  1221. check(dir, dirs[i], true, location);
  1222. // relies on compiler to prune non-source files
  1223. String[] files = getDirectoryScanner(dir).getIncludedFiles();
  1224. for (int j = 0; j < files.length; j++) {
  1225. File file = new File(dir, files[j]);
  1226. if (FileUtil.hasSourceSuffix(file)) {
  1227. list.add(file.getAbsolutePath());
  1228. }
  1229. }
  1230. }
  1231. }
  1232. if (0 < adapterFiles.size()) {
  1233. for (Iterator iter = adapterFiles.iterator(); iter.hasNext();) {
  1234. File file = (File) iter.next();
  1235. if (file.canRead() && FileUtil.hasSourceSuffix(file)) {
  1236. list.add(file.getAbsolutePath());
  1237. } else {
  1238. log("skipping file: " + file, Project.MSG_WARN);
  1239. }
  1240. }
  1241. }
  1242. }
  1243. /**
  1244. * Throw BuildException unless file is valid.
  1245. * @param file the File to check
  1246. * @param name the symbolic name to print on error
  1247. * @param isDir if true, verify file is a directory
  1248. * @param loc the Location used to create sensible BuildException
  1249. * @return
  1250. * @throws BuildException unless file valid
  1251. */
  1252. protected final boolean check(File file, String name,
  1253. boolean isDir, Location loc) {
  1254. loc = loc != null ? loc : location;
  1255. if (file == null) {
  1256. throw new BuildException(name + " is null!", loc);
  1257. }
  1258. if (!file.exists()) {
  1259. throw new BuildException(file + " doesn't exist!", loc);
  1260. }
  1261. if (isDir ^ file.isDirectory()) {
  1262. String e = file + " should" + (isDir ? "" : "n't") +
  1263. " be a directory!";
  1264. throw new BuildException(e, loc);
  1265. }
  1266. return true;
  1267. }
  1268. /**
  1269. * Called when compile or incremental compile is completing,
  1270. * this completes the output jar or directory
  1271. * by copying resources if requested.
  1272. * Note: this is a callback run synchronously by the compiler.
  1273. * That means exceptions thrown here are caught by Main.run(..)
  1274. * and passed to the message handler.
  1275. */
  1276. protected void doCompletionTasks() {
  1277. if (!executing) {
  1278. throw new IllegalStateException("should be executing");
  1279. }
  1280. if (null != outjar) {
  1281. completeOutjar();
  1282. } else {
  1283. completeDestdir();
  1284. }
  1285. }
  1286. /**
  1287. * Complete the destination directory
  1288. * by copying resources from the source root directories
  1289. * (if the filter is specified)
  1290. * and non-.class files from the input jars
  1291. * (if XCopyInjars is enabled).
  1292. */
  1293. private void completeDestdir() {
  1294. if (!copyInjars && (null == sourceRootCopyFilter)) {
  1295. return;
  1296. } else if ((destDir == DEFAULT_DESTDIR)
  1297. || !destDir.canWrite()) {
  1298. String s = "unable to copy resources to destDir: " + destDir;
  1299. throw new BuildException(s);
  1300. }
  1301. final Project project = getProject();
  1302. if (copyInjars) { // XXXX remove as unused since 1.1.1
  1303. if (null != inpath) {
  1304. log("copyInjars does not support inpath.\n", Project.MSG_WARN);
  1305. }
  1306. String taskName = getTaskName() + " - unzip";
  1307. String[] paths = injars.list();
  1308. if (!LangUtil.isEmpty(paths)) {
  1309. PatternSet patternSet = new PatternSet();
  1310. patternSet.setProject(project);
  1311. patternSet.setIncludes("**/*");
  1312. patternSet.setExcludes("**/*.class");
  1313. for (int i = 0; i < paths.length; i++) {
  1314. Expand unzip = new Expand();
  1315. unzip.setProject(project);
  1316. unzip.setTaskName(taskName);
  1317. unzip.setDest(destDir);
  1318. unzip.setSrc(new File(paths[i]));
  1319. unzip.addPatternset(patternSet);
  1320. unzip.execute();
  1321. }
  1322. }
  1323. }
  1324. if ((null != sourceRootCopyFilter) && (null != sourceRoots)) {
  1325. String[] paths = sourceRoots.list();
  1326. if (!LangUtil.isEmpty(paths)) {
  1327. Copy copy = new Copy();
  1328. copy.setProject(project);
  1329. copy.setTodir(destDir);
  1330. for (int i = 0; i < paths.length; i++) {
  1331. FileSet fileSet = new FileSet();
  1332. fileSet.setDir(new File(paths[i]));
  1333. fileSet.setIncludes("**/*");
  1334. fileSet.setExcludes(sourceRootCopyFilter);
  1335. copy.addFileset(fileSet);
  1336. }
  1337. copy.execute();
  1338. }
  1339. }
  1340. }
  1341. /**
  1342. * Complete the output jar
  1343. * by copying resources from the source root directories
  1344. * if the filter is specified.
  1345. * and non-.class files from the input jars if enabled.
  1346. */
  1347. private void completeOutjar() {
  1348. if (((null == tmpOutjar) || !tmpOutjar.canRead())
  1349. || (!copyInjars && (null == sourceRootCopyFilter))) {
  1350. return;
  1351. }
  1352. Zip zip = new Zip();
  1353. Project project = getProject();
  1354. zip.setProject(project);
  1355. zip.setTaskName(getTaskName() + " - zip");
  1356. zip.setDestFile(outjar);
  1357. ZipFileSet zipfileset = new ZipFileSet();
  1358. zipfileset.setProject(project);
  1359. zipfileset.setSrc(tmpOutjar);
  1360. zipfileset.setIncludes("**/*.class");
  1361. zip.addZipfileset(zipfileset);
  1362. if (copyInjars) {
  1363. String[] paths = injars.list();
  1364. if (!LangUtil.isEmpty(paths)) {
  1365. for (int i = 0; i < paths.length; i++) {
  1366. File jarFile = new File(paths[i]);
  1367. zipfileset = new ZipFileSet();
  1368. zipfileset.setProject(project);
  1369. zipfileset.setSrc(jarFile);
  1370. zipfileset.setIncludes("**/*");
  1371. zipfileset.setExcludes("**/*.class");
  1372. zip.addZipfileset(zipfileset);
  1373. }
  1374. }
  1375. }
  1376. if ((null != sourceRootCopyFilter) && (null != sourceRoots)) {
  1377. String[] paths = sourceRoots.list();
  1378. if (!LangUtil.isEmpty(paths)) {
  1379. for (int i = 0; i < paths.length; i++) {
  1380. File srcRoot = new File(paths[i]);
  1381. FileSet fileset = new FileSet();
  1382. fileset.setProject(project);
  1383. fileset.setDir(srcRoot);
  1384. fileset.setIncludes("**/*");
  1385. fileset.setExcludes(sourceRootCopyFilter);
  1386. zip.addFileset(fileset);
  1387. }
  1388. }
  1389. }
  1390. zip.execute();
  1391. }
  1392. // -------------------------- compiler adapter interface extras
  1393. /**
  1394. * Add specified source files.
  1395. */
  1396. void addFiles(File[] paths) {
  1397. for (int i = 0; i < paths.length; i++) {
  1398. addFile(paths[i]);
  1399. }
  1400. }
  1401. /**
  1402. * Add specified source file.
  1403. */
  1404. void addFile(File path) {
  1405. if (null != path) {
  1406. adapterFiles.add(path);
  1407. }
  1408. }
  1409. /**
  1410. * Read arguments in as if from a command line,
  1411. * mainly to support compiler adapter compilerarg subelement.
  1412. *
  1413. * @param args the String[] of arguments to read
  1414. */
  1415. public void readArguments(String[] args) { // XXX slow, stupid, unmaintainable
  1416. if ((null == args) || (0 == args.length)) {
  1417. return;
  1418. }
  1419. /** String[] wrapper with increment, error reporting */
  1420. class Args {
  1421. final String[] args;
  1422. int index = 0;
  1423. Args(String[] args) {
  1424. this.args = args; // not null or empty
  1425. }
  1426. boolean hasNext() {
  1427. return index < args.length;
  1428. }
  1429. String next() {
  1430. String err = null;
  1431. if (!hasNext()) {
  1432. err = "need arg for flag " + args[args.length-1];
  1433. } else {
  1434. String s = args[index++];
  1435. if (null == s) {
  1436. err = "null value";
  1437. } else {
  1438. s = s.trim();
  1439. if (0 == s.trim().length()) {
  1440. err = "no value";
  1441. } else {
  1442. return s;
  1443. }
  1444. }
  1445. }
  1446. err += " at [" + index + "] of " + Arrays.asList(args);
  1447. throw new BuildException(err);
  1448. }
  1449. } // class Args
  1450. Args in = new Args(args);
  1451. String flag;
  1452. while (in.hasNext()) {
  1453. flag = in.next();
  1454. if ("-1.3".equals(flag)) {
  1455. setCompliance("1.3");
  1456. } else if ("-1.4".equals(flag)) {
  1457. setCompliance("1.4");
  1458. // } else if ("-1.5".equals(flag)) {
  1459. // setCompliance("1.5");
  1460. } else if ("-argfile".equals(flag)) {
  1461. setArgfiles(new Path(project, in.next()));
  1462. } else if ("-aspectpath".equals(flag)) {
  1463. setAspectpath(new Path(project, in.next()));
  1464. } else if ("-classpath".equals(flag)) {
  1465. setClasspath(new Path(project, in.next()));
  1466. } else if ("-Xcopyinjars".equals(flag)) {
  1467. setCopyInjars(true); // ignored - will be flagged by setter
  1468. } else if ("-g".equals(flag)) {
  1469. setDebug(true);
  1470. } else if (flag.startsWith("-g:")) {
  1471. setDebugLevel(flag.substring(2));
  1472. } else if ("-deprecation".equals(flag)) {
  1473. setDeprecation(true);
  1474. } else if ("-d".equals(flag)) {
  1475. setDestdir(new File(in.next()));
  1476. } else if ("-emacssym".equals(flag)) {
  1477. setEmacssym(true);
  1478. } else if ("-encoding".equals(flag)) {
  1479. setEncoding(in.next());
  1480. } else if ("-Xfailonerror".equals(flag)) {
  1481. setFailonerror(true);
  1482. } else if ("-fork".equals(flag)) {
  1483. setFork(true);
  1484. } else if ("-forkclasspath".equals(flag)) {
  1485. setForkclasspath(new Path(project, in.next()));
  1486. } else if ("-help".equals(flag)) {
  1487. setHelp(true);
  1488. } else if ("-incremental".equals(flag)) {
  1489. setIncremental(true);
  1490. } else if ("-injars".equals(flag)) {
  1491. setInjars(new Path(project, in.next()));
  1492. } else if ("-inpath".equals(flag)) {
  1493. setInpath(new Path(project,in.next()));
  1494. } else if ("-Xlistfileargs".equals(flag)) {
  1495. setListFileArgs(true);
  1496. } else if ("-Xmaxmem".equals(flag)) {
  1497. setMaxmem(in.next());
  1498. } else if ("-Xmessageholderclass".equals(flag)) {
  1499. setMessageHolderClass(in.next());
  1500. } else if ("-noexit".equals(flag)) {
  1501. setNoExit(true);
  1502. } else if ("-noimport".equals(flag)) {
  1503. setNoExit(true);
  1504. } else if ("-noExit".equals(flag)) {
  1505. setNoExit(true);
  1506. } else if ("-noImportError".equals(flag)) {
  1507. setNoImportError(true);
  1508. } else if ("-noWarn".equals(flag)) {
  1509. setNowarn(true);
  1510. } else if ("-noexit".equals(flag)) {
  1511. setNoExit(true);
  1512. } else if ("-outjar".equals(flag)) {
  1513. setOutjar(new File(in.next()));
  1514. } else if ("-preserveAllLocals".equals(flag)) {
  1515. setPreserveAllLocals(true);
  1516. } else if ("-proceedOnError".equals(flag)) {
  1517. setProceedOnError(true);
  1518. } else if ("-progress".equals(flag)) {
  1519. setProgress(true);
  1520. } else if ("-referenceInfo".equals(flag)) {
  1521. setReferenceInfo(true);
  1522. } else if ("-source".equals(flag)) {
  1523. setSource(in.next());
  1524. } else if ("-Xsourcerootcopyfilter".equals(flag)) {
  1525. setSourceRootCopyFilter(in.next());
  1526. } else if ("-sourceroots".equals(flag)) {
  1527. setSourceRoots(new Path(project, in.next()));
  1528. } else if ("-Xsrcdir".equals(flag)) {
  1529. setSrcDir(new Path(project, in.next()));
  1530. } else if ("-Xtagfile".equals(flag)) {
  1531. setTagFile(new File(in.next()));
  1532. } else if ("-target".equals(flag)) {
  1533. setTarget(in.next());
  1534. } else if ("-time".equals(flag)) {
  1535. setTime(true);
  1536. } else if ("-time".equals(flag)) {
  1537. setTime(true);
  1538. } else if ("-verbose".equals(flag)) {
  1539. setVerbose(true);
  1540. } else if ("-version".equals(flag)) {
  1541. setVersion(true);
  1542. } else if ("-warn".equals(flag)) {
  1543. setWarn(in.next());
  1544. } else if (flag.startsWith("-warn:")) {
  1545. setWarn(flag.substring(6));
  1546. } else if ("-Xlint".equals(flag)) {
  1547. setXlintwarnings(true);
  1548. } else if (flag.startsWith("-Xlint:")) {
  1549. setXlint(flag.substring(7));
  1550. } else if ("-Xlintfile".equals(flag)) {
  1551. setXlintfile(new File(in.next()));
  1552. } else if ("-Xnoweave".equals(flag)) {
  1553. setXNoweave(true);
  1554. } else if (flag.startsWith("@")) {
  1555. File file = new File(flag.substring(1));
  1556. if (file.canRead()) {
  1557. setArgfiles(new Path(project, file.getPath()));
  1558. } else {
  1559. ignore(flag);
  1560. }
  1561. } else {
  1562. File file = new File(flag);
  1563. if (file.isFile()
  1564. && file.canRead()
  1565. && FileUtil.hasSourceSuffix(file)) {
  1566. addFile(file);
  1567. } else {
  1568. ignore(flag);
  1569. }
  1570. }
  1571. }
  1572. }
  1573. /**
  1574. * Commandline wrapper that
  1575. * only permits addition of non-empty values
  1576. * and converts to argfile form if necessary.
  1577. */
  1578. public static class GuardedCommand {
  1579. Commandline command;
  1580. //int size;
  1581. static boolean isEmpty(String s) {
  1582. return ((null == s) || (0 == s.trim().length()));
  1583. }
  1584. GuardedCommand() {
  1585. command = new Commandline();
  1586. }
  1587. void addFlag(String flag, boolean doAdd) {
  1588. if (doAdd && !isEmpty(flag)) {
  1589. command.createArgument().setValue(flag);
  1590. //size += 1 + flag.length();
  1591. }
  1592. }
  1593. void addFlagged(String flag, String argument) {
  1594. if (!isEmpty(flag) && !isEmpty(argument)) {
  1595. command.addArguments(new String[] {flag, argument});
  1596. //size += 1 + flag.length() + argument.length();
  1597. }
  1598. }
  1599. private void addFile(File file) {
  1600. if (null != file) {
  1601. String path = file.getAbsolutePath();
  1602. addFlag(path, true);
  1603. }
  1604. }
  1605. List extractArguments() {
  1606. ArrayList result = new ArrayList();
  1607. String[] cmds = command.getArguments();
  1608. if (!LangUtil.isEmpty(cmds)) {
  1609. result.addAll(Arrays.asList(cmds));
  1610. }
  1611. return result;
  1612. }
  1613. /**
  1614. * Adjust args for size if necessary by creating
  1615. * an argument file, which should be deleted by the client
  1616. * after the compiler run has completed.
  1617. * @param max the int maximum length of the command line (in char)
  1618. * @return the temp File for the arguments (if generated),
  1619. * for deletion when done.
  1620. * @throws IllegalArgumentException if max is negative
  1621. */
  1622. static String[] limitTo(String[] args, int max,
  1623. Location location) {
  1624. if (max < 0) {
  1625. throw new IllegalArgumentException("negative max: " + max);
  1626. }
  1627. // sigh - have to count anyway for now
  1628. int size = 0;
  1629. for (int i = 0; (i < args.length) && (size < max); i++) {
  1630. size += 1 + (null == args[i] ? 0 : args[i].length());
  1631. }
  1632. if (size <= max) {
  1633. return args;
  1634. }
  1635. File tmpFile = null;
  1636. PrintWriter out = null;
  1637. // adapted from DefaultCompilerAdapter.executeExternalCompile
  1638. try {
  1639. String userDirName = System.getProperty("user.dir");
  1640. File userDir = new File(userDirName);
  1641. tmpFile = File.createTempFile("argfile", "", userDir);
  1642. out = new PrintWriter(new FileWriter(tmpFile));
  1643. for (int i = 0; i < args.length; i++) {
  1644. out.println(args[i]);
  1645. }
  1646. out.flush();
  1647. return new String[] {"-argfile", tmpFile.getAbsolutePath()};
  1648. } catch (IOException e) {
  1649. throw new BuildException("Error creating temporary file",
  1650. e, location);
  1651. } finally {
  1652. if (out != null) {
  1653. try {out.close();} catch (Throwable t) {}
  1654. }
  1655. }
  1656. }
  1657. }
  1658. }