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

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