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

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