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

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