You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Javac.java 56 kB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
8 years ago
11 years ago
11 years ago
11 years ago
8 years ago
11 years ago
8 years ago
11 years ago
11 years ago
8 years ago
11 years ago
8 years ago
11 years ago
11 years ago
8 years ago
8 years ago
8 years ago
11 years ago
8 years ago
11 years ago
11 years ago
8 years ago
11 years ago
11 years ago
8 years ago
11 years ago
11 years ago
11 years ago
8 years ago
11 years ago
8 years ago
11 years ago
11 years ago
11 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.taskdefs;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.io.OutputStream;
  22. import java.nio.file.Files;
  23. import java.util.ArrayList;
  24. import java.util.Collection;
  25. import java.util.HashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.TreeMap;
  29. import org.apache.tools.ant.BuildException;
  30. import org.apache.tools.ant.DirectoryScanner;
  31. import org.apache.tools.ant.MagicNames;
  32. import org.apache.tools.ant.Project;
  33. import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
  34. import org.apache.tools.ant.taskdefs.compilers.CompilerAdapterExtension;
  35. import org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory;
  36. import org.apache.tools.ant.types.Path;
  37. import org.apache.tools.ant.types.Reference;
  38. import org.apache.tools.ant.util.FileUtils;
  39. import org.apache.tools.ant.util.GlobPatternMapper;
  40. import org.apache.tools.ant.util.JavaEnvUtils;
  41. import org.apache.tools.ant.util.SourceFileScanner;
  42. import org.apache.tools.ant.util.facade.FacadeTaskHelper;
  43. /**
  44. * Compiles Java source files. This task can take the following
  45. * arguments:
  46. * <ul>
  47. * <li>sourcedir
  48. * <li>destdir
  49. * <li>deprecation
  50. * <li>classpath
  51. * <li>bootclasspath
  52. * <li>extdirs
  53. * <li>optimize
  54. * <li>debug
  55. * <li>encoding
  56. * <li>target
  57. * <li>depend
  58. * <li>verbose
  59. * <li>failonerror
  60. * <li>includeantruntime
  61. * <li>includejavaruntime
  62. * <li>source
  63. * <li>compiler
  64. * <li>release
  65. * </ul>
  66. * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
  67. * <p>
  68. * When this task executes, it will recursively scan the sourcedir and
  69. * destdir looking for Java source files to compile. This task makes its
  70. * compile decision based on timestamp.
  71. *
  72. *
  73. * @since Ant 1.1
  74. *
  75. * @ant.task category="java"
  76. */
  77. public class Javac extends MatchingTask {
  78. private static final String FAIL_MSG
  79. = "Compile failed; see the compiler error output for details.";
  80. private static final String JAVAC9 = "javac9";
  81. private static final String JAVAC19 = "javac1.9";
  82. private static final String JAVAC18 = "javac1.8";
  83. private static final String JAVAC17 = "javac1.7";
  84. private static final String JAVAC16 = "javac1.6";
  85. private static final String JAVAC15 = "javac1.5";
  86. private static final String JAVAC14 = "javac1.4";
  87. private static final String JAVAC13 = "javac1.3";
  88. private static final String JAVAC12 = "javac1.2";
  89. private static final String JAVAC11 = "javac1.1";
  90. private static final String MODERN = "modern";
  91. private static final String CLASSIC = "classic";
  92. private static final String EXTJAVAC = "extJavac";
  93. private static final char GROUP_START_MARK = '{'; //modulesourcepath group start character
  94. private static final char GROUP_END_MARK = '}'; //modulesourcepath group end character
  95. private static final char GROUP_SEP_MARK = ','; //modulesourcepath group element separator character
  96. private static final String MODULE_MARKER = "*"; //modulesourcepath module name marker
  97. private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  98. private Path src;
  99. private File destDir;
  100. private File nativeHeaderDir;
  101. private Path compileClasspath;
  102. private Path modulepath;
  103. private Path upgrademodulepath;
  104. private Path compileSourcepath;
  105. private Path moduleSourcepath;
  106. private String encoding;
  107. private boolean debug = false;
  108. private boolean optimize = false;
  109. private boolean deprecation = false;
  110. private boolean depend = false;
  111. private boolean verbose = false;
  112. private String targetAttribute;
  113. private String release;
  114. private Path bootclasspath;
  115. private Path extdirs;
  116. private Boolean includeAntRuntime;
  117. private boolean includeJavaRuntime = false;
  118. private boolean fork = false;
  119. private String forkedExecutable = null;
  120. private boolean nowarn = false;
  121. private String memoryInitialSize;
  122. private String memoryMaximumSize;
  123. private FacadeTaskHelper facade = null;
  124. // CheckStyle:VisibilityModifier OFF - bc
  125. protected boolean failOnError = true;
  126. protected boolean listFiles = false;
  127. protected File[] compileList = new File[0];
  128. private Map<String, Long> packageInfos = new HashMap<>();
  129. // CheckStyle:VisibilityModifier ON
  130. private String source;
  131. private String debugLevel;
  132. private File tmpDir;
  133. private String updatedProperty;
  134. private String errorProperty;
  135. private boolean taskSuccess = true; // assume the best
  136. private boolean includeDestClasses = true;
  137. private CompilerAdapter nestedAdapter = null;
  138. private boolean createMissingPackageInfoClass = true;
  139. /**
  140. * Javac task for compilation of Java files.
  141. */
  142. public Javac() {
  143. facade = new FacadeTaskHelper(assumedJavaVersion());
  144. }
  145. private String assumedJavaVersion() {
  146. if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_4)) {
  147. return JAVAC14;
  148. }
  149. if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_5)) {
  150. return JAVAC15;
  151. }
  152. if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_6)) {
  153. return JAVAC16;
  154. }
  155. if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_7)) {
  156. return JAVAC17;
  157. }
  158. if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_8)) {
  159. return JAVAC18;
  160. }
  161. if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_9)) {
  162. return JAVAC9;
  163. }
  164. return CLASSIC;
  165. }
  166. /**
  167. * Get the value of debugLevel.
  168. * @return value of debugLevel.
  169. */
  170. public String getDebugLevel() {
  171. return debugLevel;
  172. }
  173. /**
  174. * Keyword list to be appended to the -g command-line switch.
  175. *
  176. * This will be ignored by all implementations except modern
  177. * and classic(ver &gt;= 1.2). Legal values are none or a
  178. * comma-separated list of the following keywords: lines, vars,
  179. * and source. If debuglevel is not specified, by default, :none
  180. * will be appended to -g. If debug is not turned on, this attribute
  181. * will be ignored.
  182. *
  183. * @param v Value to assign to debugLevel.
  184. */
  185. public void setDebugLevel(final String v) {
  186. this.debugLevel = v;
  187. }
  188. /**
  189. * Get the value of source.
  190. * @return value of source.
  191. */
  192. public String getSource() {
  193. return source != null
  194. ? source : getProject().getProperty(MagicNames.BUILD_JAVAC_SOURCE);
  195. }
  196. /**
  197. * Value of the -source command-line switch; will be ignored by
  198. * all implementations except modern, jikes and gcj (gcj uses
  199. * -fsource).
  200. *
  201. * <p>If you use this attribute together with jikes or gcj, you
  202. * must make sure that your version of jikes supports the -source
  203. * switch.</p>
  204. *
  205. * <p>Legal values are 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, and 5, 6, 7, 8 and 9
  206. * - by default, no -source argument will be used at all.</p>
  207. *
  208. * @param v Value to assign to source.
  209. */
  210. public void setSource(final String v) {
  211. this.source = v;
  212. }
  213. /**
  214. * Adds a path for source compilation.
  215. *
  216. * @return a nested src element.
  217. */
  218. public Path createSrc() {
  219. if (src == null) {
  220. src = new Path(getProject());
  221. }
  222. return src.createPath();
  223. }
  224. /**
  225. * Recreate src.
  226. *
  227. * @return a nested src element.
  228. */
  229. protected Path recreateSrc() {
  230. src = null;
  231. return createSrc();
  232. }
  233. /**
  234. * Set the source directories to find the source Java files.
  235. * @param srcDir the source directories as a path
  236. */
  237. public void setSrcdir(final Path srcDir) {
  238. if (src == null) {
  239. src = srcDir;
  240. } else {
  241. src.append(srcDir);
  242. }
  243. }
  244. /**
  245. * Gets the source dirs to find the source java files.
  246. * @return the source directories as a path
  247. */
  248. public Path getSrcdir() {
  249. return src;
  250. }
  251. /**
  252. * Set the destination directory into which the Java source
  253. * files should be compiled.
  254. * @param destDir the destination director
  255. */
  256. public void setDestdir(final File destDir) {
  257. this.destDir = destDir;
  258. }
  259. /**
  260. * Gets the destination directory into which the java source files
  261. * should be compiled.
  262. * @return the destination directory
  263. */
  264. public File getDestdir() {
  265. return destDir;
  266. }
  267. /**
  268. * Set the destination directory into which the generated native
  269. * header files should be placed.
  270. * @param nhDir where to place generated native header files
  271. * @since Ant 1.9.8
  272. */
  273. public void setNativeHeaderDir(final File nhDir) {
  274. this.nativeHeaderDir = nhDir;
  275. }
  276. /**
  277. * Gets the destination directory into which the generated native
  278. * header files should be placed.
  279. * @return where to place generated native header files
  280. * @since Ant 1.9.8
  281. */
  282. public File getNativeHeaderDir() {
  283. return nativeHeaderDir;
  284. }
  285. /**
  286. * Set the sourcepath to be used for this compilation.
  287. * @param sourcepath the source path
  288. */
  289. public void setSourcepath(final Path sourcepath) {
  290. if (compileSourcepath == null) {
  291. compileSourcepath = sourcepath;
  292. } else {
  293. compileSourcepath.append(sourcepath);
  294. }
  295. }
  296. /**
  297. * Gets the sourcepath to be used for this compilation.
  298. * @return the source path
  299. */
  300. public Path getSourcepath() {
  301. return compileSourcepath;
  302. }
  303. /**
  304. * Adds a path to sourcepath.
  305. * @return a sourcepath to be configured
  306. */
  307. public Path createSourcepath() {
  308. if (compileSourcepath == null) {
  309. compileSourcepath = new Path(getProject());
  310. }
  311. return compileSourcepath.createPath();
  312. }
  313. /**
  314. * Adds a reference to a source path defined elsewhere.
  315. * @param r a reference to a source path
  316. */
  317. public void setSourcepathRef(final Reference r) {
  318. createSourcepath().setRefid(r);
  319. }
  320. /**
  321. * Set the modulesourcepath to be used for this compilation.
  322. * @param msp the modulesourcepath
  323. * @since 1.9.7
  324. */
  325. public void setModulesourcepath(final Path msp) {
  326. if (moduleSourcepath == null) {
  327. moduleSourcepath = msp;
  328. } else {
  329. moduleSourcepath.append(msp);
  330. }
  331. }
  332. /**
  333. * Gets the modulesourcepath to be used for this compilation.
  334. * @return the modulesourcepath
  335. * @since 1.9.7
  336. */
  337. public Path getModulesourcepath() {
  338. return moduleSourcepath;
  339. }
  340. /**
  341. * Adds a path to modulesourcepath.
  342. * @return a modulesourcepath to be configured
  343. * @since 1.9.7
  344. */
  345. public Path createModulesourcepath() {
  346. if (moduleSourcepath == null) {
  347. moduleSourcepath = new Path(getProject());
  348. }
  349. return moduleSourcepath.createPath();
  350. }
  351. /**
  352. * Adds a reference to a modulesourcepath defined elsewhere.
  353. * @param r a reference to a modulesourcepath
  354. * @since 1.9.7
  355. */
  356. public void setModulesourcepathRef(final Reference r) {
  357. createModulesourcepath().setRefid(r);
  358. }
  359. /**
  360. * Set the classpath to be used for this compilation.
  361. *
  362. * @param classpath an Ant Path object containing the compilation classpath.
  363. */
  364. public void setClasspath(final Path classpath) {
  365. if (compileClasspath == null) {
  366. compileClasspath = classpath;
  367. } else {
  368. compileClasspath.append(classpath);
  369. }
  370. }
  371. /**
  372. * Gets the classpath to be used for this compilation.
  373. * @return the class path
  374. */
  375. public Path getClasspath() {
  376. return compileClasspath;
  377. }
  378. /**
  379. * Adds a path to the classpath.
  380. * @return a class path to be configured
  381. */
  382. public Path createClasspath() {
  383. if (compileClasspath == null) {
  384. compileClasspath = new Path(getProject());
  385. }
  386. return compileClasspath.createPath();
  387. }
  388. /**
  389. * Adds a reference to a classpath defined elsewhere.
  390. * @param r a reference to a classpath
  391. */
  392. public void setClasspathRef(final Reference r) {
  393. createClasspath().setRefid(r);
  394. }
  395. /**
  396. * Set the modulepath to be used for this compilation.
  397. * @param mp an Ant Path object containing the modulepath.
  398. * @since 1.9.7
  399. */
  400. public void setModulepath(final Path mp) {
  401. if (modulepath == null) {
  402. modulepath = mp;
  403. } else {
  404. modulepath.append(mp);
  405. }
  406. }
  407. /**
  408. * Gets the modulepath to be used for this compilation.
  409. * @return the modulepath
  410. * @since 1.9.7
  411. */
  412. public Path getModulepath() {
  413. return modulepath;
  414. }
  415. /**
  416. * Adds a path to the modulepath.
  417. * @return a modulepath to be configured
  418. * @since 1.9.7
  419. */
  420. public Path createModulepath() {
  421. if (modulepath == null) {
  422. modulepath = new Path(getProject());
  423. }
  424. return modulepath.createPath();
  425. }
  426. /**
  427. * Adds a reference to a modulepath defined elsewhere.
  428. * @param r a reference to a modulepath
  429. * @since 1.9.7
  430. */
  431. public void setModulepathRef(final Reference r) {
  432. createModulepath().setRefid(r);
  433. }
  434. /**
  435. * Set the upgrademodulepath to be used for this compilation.
  436. * @param ump an Ant Path object containing the upgrademodulepath.
  437. * @since 1.9.7
  438. */
  439. public void setUpgrademodulepath(final Path ump) {
  440. if (upgrademodulepath == null) {
  441. upgrademodulepath = ump;
  442. } else {
  443. upgrademodulepath.append(ump);
  444. }
  445. }
  446. /**
  447. * Gets the upgrademodulepath to be used for this compilation.
  448. * @return the upgrademodulepath
  449. * @since 1.9.7
  450. */
  451. public Path getUpgrademodulepath() {
  452. return upgrademodulepath;
  453. }
  454. /**
  455. * Adds a path to the upgrademodulepath.
  456. * @return an upgrademodulepath to be configured
  457. * @since 1.9.7
  458. */
  459. public Path createUpgrademodulepath() {
  460. if (upgrademodulepath == null) {
  461. upgrademodulepath = new Path(getProject());
  462. }
  463. return upgrademodulepath.createPath();
  464. }
  465. /**
  466. * Adds a reference to the upgrademodulepath defined elsewhere.
  467. * @param r a reference to an upgrademodulepath
  468. * @since 1.9.7
  469. */
  470. public void setUpgrademodulepathRef(final Reference r) {
  471. createUpgrademodulepath().setRefid(r);
  472. }
  473. /**
  474. * Sets the bootclasspath that will be used to compile the classes
  475. * against.
  476. * @param bootclasspath a path to use as a boot class path (may be more
  477. * than one)
  478. */
  479. public void setBootclasspath(final Path bootclasspath) {
  480. if (this.bootclasspath == null) {
  481. this.bootclasspath = bootclasspath;
  482. } else {
  483. this.bootclasspath.append(bootclasspath);
  484. }
  485. }
  486. /**
  487. * Gets the bootclasspath that will be used to compile the classes
  488. * against.
  489. * @return the boot path
  490. */
  491. public Path getBootclasspath() {
  492. return bootclasspath;
  493. }
  494. /**
  495. * Adds a path to the bootclasspath.
  496. * @return a path to be configured
  497. */
  498. public Path createBootclasspath() {
  499. if (bootclasspath == null) {
  500. bootclasspath = new Path(getProject());
  501. }
  502. return bootclasspath.createPath();
  503. }
  504. /**
  505. * Adds a reference to a classpath defined elsewhere.
  506. * @param r a reference to a classpath
  507. */
  508. public void setBootClasspathRef(final Reference r) {
  509. createBootclasspath().setRefid(r);
  510. }
  511. /**
  512. * Sets the extension directories that will be used during the
  513. * compilation.
  514. * @param extdirs a path
  515. */
  516. public void setExtdirs(final Path extdirs) {
  517. if (this.extdirs == null) {
  518. this.extdirs = extdirs;
  519. } else {
  520. this.extdirs.append(extdirs);
  521. }
  522. }
  523. /**
  524. * Gets the extension directories that will be used during the
  525. * compilation.
  526. * @return the extension directories as a path
  527. */
  528. public Path getExtdirs() {
  529. return extdirs;
  530. }
  531. /**
  532. * Adds a path to extdirs.
  533. * @return a path to be configured
  534. */
  535. public Path createExtdirs() {
  536. if (extdirs == null) {
  537. extdirs = new Path(getProject());
  538. }
  539. return extdirs.createPath();
  540. }
  541. /**
  542. * If true, list the source files being handed off to the compiler.
  543. * @param list if true list the source files
  544. */
  545. public void setListfiles(final boolean list) {
  546. listFiles = list;
  547. }
  548. /**
  549. * Get the listfiles flag.
  550. * @return the listfiles flag
  551. */
  552. public boolean getListfiles() {
  553. return listFiles;
  554. }
  555. /**
  556. * Indicates whether the build will continue
  557. * even if there are compilation errors; defaults to true.
  558. * @param fail if true halt the build on failure
  559. */
  560. public void setFailonerror(final boolean fail) {
  561. failOnError = fail;
  562. }
  563. /**
  564. * @ant.attribute ignore="true"
  565. * @param proceed inverse of failoferror
  566. */
  567. public void setProceed(final boolean proceed) {
  568. failOnError = !proceed;
  569. }
  570. /**
  571. * Gets the failonerror flag.
  572. * @return the failonerror flag
  573. */
  574. public boolean getFailonerror() {
  575. return failOnError;
  576. }
  577. /**
  578. * Indicates whether source should be
  579. * compiled with deprecation information; defaults to off.
  580. * @param deprecation if true turn on deprecation information
  581. */
  582. public void setDeprecation(final boolean deprecation) {
  583. this.deprecation = deprecation;
  584. }
  585. /**
  586. * Gets the deprecation flag.
  587. * @return the deprecation flag
  588. */
  589. public boolean getDeprecation() {
  590. return deprecation;
  591. }
  592. /**
  593. * The initial size of the memory for the underlying VM
  594. * if javac is run externally; ignored otherwise.
  595. * Defaults to the standard VM memory setting.
  596. * (Examples: 83886080, 81920k, or 80m)
  597. * @param memoryInitialSize string to pass to VM
  598. */
  599. public void setMemoryInitialSize(final String memoryInitialSize) {
  600. this.memoryInitialSize = memoryInitialSize;
  601. }
  602. /**
  603. * Gets the memoryInitialSize flag.
  604. * @return the memoryInitialSize flag
  605. */
  606. public String getMemoryInitialSize() {
  607. return memoryInitialSize;
  608. }
  609. /**
  610. * The maximum size of the memory for the underlying VM
  611. * if javac is run externally; ignored otherwise.
  612. * Defaults to the standard VM memory setting.
  613. * (Examples: 83886080, 81920k, or 80m)
  614. * @param memoryMaximumSize string to pass to VM
  615. */
  616. public void setMemoryMaximumSize(final String memoryMaximumSize) {
  617. this.memoryMaximumSize = memoryMaximumSize;
  618. }
  619. /**
  620. * Gets the memoryMaximumSize flag.
  621. * @return the memoryMaximumSize flag
  622. */
  623. public String getMemoryMaximumSize() {
  624. return memoryMaximumSize;
  625. }
  626. /**
  627. * Set the Java source file encoding name.
  628. * @param encoding the source file encoding
  629. */
  630. public void setEncoding(final String encoding) {
  631. this.encoding = encoding;
  632. }
  633. /**
  634. * Gets the java source file encoding name.
  635. * @return the source file encoding name
  636. */
  637. public String getEncoding() {
  638. return encoding;
  639. }
  640. /**
  641. * Indicates whether source should be compiled
  642. * with debug information; defaults to off.
  643. * @param debug if true compile with debug information
  644. */
  645. public void setDebug(final boolean debug) {
  646. this.debug = debug;
  647. }
  648. /**
  649. * Gets the debug flag.
  650. * @return the debug flag
  651. */
  652. public boolean getDebug() {
  653. return debug;
  654. }
  655. /**
  656. * If true, compiles with optimization enabled.
  657. * @param optimize if true compile with optimization enabled
  658. */
  659. public void setOptimize(final boolean optimize) {
  660. this.optimize = optimize;
  661. }
  662. /**
  663. * Gets the optimize flag.
  664. * @return the optimize flag
  665. */
  666. public boolean getOptimize() {
  667. return optimize;
  668. }
  669. /**
  670. * Enables dependency-tracking for compilers
  671. * that support this (jikes and classic).
  672. * @param depend if true enable dependency-tracking
  673. */
  674. public void setDepend(final boolean depend) {
  675. this.depend = depend;
  676. }
  677. /**
  678. * Gets the depend flag.
  679. * @return the depend flag
  680. */
  681. public boolean getDepend() {
  682. return depend;
  683. }
  684. /**
  685. * If true, asks the compiler for verbose output.
  686. * @param verbose if true, asks the compiler for verbose output
  687. */
  688. public void setVerbose(final boolean verbose) {
  689. this.verbose = verbose;
  690. }
  691. /**
  692. * Gets the verbose flag.
  693. * @return the verbose flag
  694. */
  695. public boolean getVerbose() {
  696. return verbose;
  697. }
  698. /**
  699. * Sets the target VM that the classes will be compiled for. Valid
  700. * values depend on the compiler, for jdk 1.4 the valid values are
  701. * "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "5", "6", "7", "8", "9".
  702. * @param target the target VM
  703. */
  704. public void setTarget(final String target) {
  705. this.targetAttribute = target;
  706. }
  707. /**
  708. * Gets the target VM that the classes will be compiled for.
  709. * @return the target VM
  710. */
  711. public String getTarget() {
  712. return targetAttribute != null
  713. ? targetAttribute
  714. : getProject().getProperty(MagicNames.BUILD_JAVAC_TARGET);
  715. }
  716. /**
  717. * Sets the version to use for the {@code --release} switch that
  718. * combines {@code source}, {@code target} and setting the
  719. * bootclasspath.
  720. *
  721. * Values depend on the compiler, for jdk 9 the valid values are
  722. * "6", "7", "8", "9".
  723. * @param release the value of the release attribute
  724. * @since Ant 1.9.8
  725. */
  726. public void setRelease(final String release) {
  727. this.release = release;
  728. }
  729. /**
  730. * Gets the version to use for the {@code --release} switch that
  731. * combines {@code source}, {@code target} and setting the
  732. * bootclasspath.
  733. *
  734. * @return the value of the release attribute
  735. * @since Ant 1.9.8
  736. */
  737. public String getRelease() {
  738. return release;
  739. }
  740. /**
  741. * If true, includes Ant's own classpath in the classpath.
  742. * @param include if true, includes Ant's own classpath in the classpath
  743. */
  744. public void setIncludeantruntime(final boolean include) {
  745. includeAntRuntime = Boolean.valueOf(include);
  746. }
  747. /**
  748. * Gets whether or not the ant classpath is to be included in the classpath.
  749. * @return whether or not the ant classpath is to be included in the classpath
  750. */
  751. public boolean getIncludeantruntime() {
  752. return includeAntRuntime != null ? includeAntRuntime.booleanValue() : true;
  753. }
  754. /**
  755. * If true, includes the Java runtime libraries in the classpath.
  756. * @param include if true, includes the Java runtime libraries in the classpath
  757. */
  758. public void setIncludejavaruntime(final boolean include) {
  759. includeJavaRuntime = include;
  760. }
  761. /**
  762. * Gets whether or not the java runtime should be included in this
  763. * task's classpath.
  764. * @return the includejavaruntime attribute
  765. */
  766. public boolean getIncludejavaruntime() {
  767. return includeJavaRuntime;
  768. }
  769. /**
  770. * If true, forks the javac compiler.
  771. *
  772. * @param f "true|false|on|off|yes|no"
  773. */
  774. public void setFork(final boolean f) {
  775. fork = f;
  776. }
  777. /**
  778. * Sets the name of the javac executable.
  779. *
  780. * <p>Ignored unless fork is true or extJavac has been specified
  781. * as the compiler.</p>
  782. * @param forkExec the name of the executable
  783. */
  784. public void setExecutable(final String forkExec) {
  785. forkedExecutable = forkExec;
  786. }
  787. /**
  788. * The value of the executable attribute, if any.
  789. *
  790. * @since Ant 1.6
  791. * @return the name of the java executable
  792. */
  793. public String getExecutable() {
  794. return forkedExecutable;
  795. }
  796. /**
  797. * Is this a forked invocation of JDK's javac?
  798. * @return true if this is a forked invocation
  799. */
  800. public boolean isForkedJavac() {
  801. return fork || EXTJAVAC.equalsIgnoreCase(getCompiler());
  802. }
  803. /**
  804. * The name of the javac executable to use in fork-mode.
  805. *
  806. * <p>This is either the name specified with the executable
  807. * attribute or the full path of the javac compiler of the VM Ant
  808. * is currently running in - guessed by Ant.</p>
  809. *
  810. * <p>You should <strong>not</strong> invoke this method if you
  811. * want to get the value of the executable command - use {@link
  812. * #getExecutable getExecutable} for this.</p>
  813. * @return the name of the javac executable
  814. */
  815. public String getJavacExecutable() {
  816. if (forkedExecutable == null && isForkedJavac()) {
  817. forkedExecutable = getSystemJavac();
  818. } else if (forkedExecutable != null && !isForkedJavac()) {
  819. forkedExecutable = null;
  820. }
  821. return forkedExecutable;
  822. }
  823. /**
  824. * If true, enables the -nowarn option.
  825. * @param flag if true, enable the -nowarn option
  826. */
  827. public void setNowarn(final boolean flag) {
  828. this.nowarn = flag;
  829. }
  830. /**
  831. * Should the -nowarn option be used.
  832. * @return true if the -nowarn option should be used
  833. */
  834. public boolean getNowarn() {
  835. return nowarn;
  836. }
  837. /**
  838. * Adds an implementation specific command-line argument.
  839. * @return a ImplementationSpecificArgument to be configured
  840. */
  841. public ImplementationSpecificArgument createCompilerArg() {
  842. final ImplementationSpecificArgument arg =
  843. new ImplementationSpecificArgument();
  844. facade.addImplementationArgument(arg);
  845. return arg;
  846. }
  847. /**
  848. * Get the additional implementation specific command line arguments.
  849. * @return array of command line arguments, guaranteed to be non-null.
  850. */
  851. public String[] getCurrentCompilerArgs() {
  852. final String chosen = facade.getExplicitChoice();
  853. try {
  854. // make sure facade knows about magic properties and fork setting
  855. final String appliedCompiler = getCompiler();
  856. facade.setImplementation(appliedCompiler);
  857. String[] result = facade.getArgs();
  858. final String altCompilerName = getAltCompilerName(facade.getImplementation());
  859. if (result.length == 0 && altCompilerName != null) {
  860. facade.setImplementation(altCompilerName);
  861. result = facade.getArgs();
  862. }
  863. return result;
  864. } finally {
  865. facade.setImplementation(chosen);
  866. }
  867. }
  868. private String getAltCompilerName(final String anImplementation) {
  869. if (JAVAC9.equalsIgnoreCase(anImplementation)
  870. || JAVAC19.equalsIgnoreCase(anImplementation)
  871. || JAVAC18.equalsIgnoreCase(anImplementation)
  872. || JAVAC17.equalsIgnoreCase(anImplementation)
  873. || JAVAC16.equalsIgnoreCase(anImplementation)
  874. || JAVAC15.equalsIgnoreCase(anImplementation)
  875. || JAVAC14.equalsIgnoreCase(anImplementation)
  876. || JAVAC13.equalsIgnoreCase(anImplementation)) {
  877. return MODERN;
  878. }
  879. if (JAVAC12.equalsIgnoreCase(anImplementation)
  880. || JAVAC11.equalsIgnoreCase(anImplementation)) {
  881. return CLASSIC;
  882. }
  883. if (MODERN.equalsIgnoreCase(anImplementation)) {
  884. final String nextSelected = assumedJavaVersion();
  885. if (JAVAC9.equalsIgnoreCase(nextSelected)
  886. || JAVAC18.equalsIgnoreCase(nextSelected)
  887. || JAVAC17.equalsIgnoreCase(nextSelected)
  888. || JAVAC16.equalsIgnoreCase(nextSelected)
  889. || JAVAC15.equalsIgnoreCase(nextSelected)
  890. || JAVAC14.equalsIgnoreCase(nextSelected)
  891. || JAVAC13.equalsIgnoreCase(nextSelected)) {
  892. return nextSelected;
  893. }
  894. }
  895. if (CLASSIC.equalsIgnoreCase(anImplementation)) {
  896. return assumedJavaVersion();
  897. }
  898. if (EXTJAVAC.equalsIgnoreCase(anImplementation)) {
  899. return assumedJavaVersion();
  900. }
  901. return null;
  902. }
  903. /**
  904. * Where Ant should place temporary files.
  905. *
  906. * @since Ant 1.6
  907. * @param tmpDir the temporary directory
  908. */
  909. public void setTempdir(final File tmpDir) {
  910. this.tmpDir = tmpDir;
  911. }
  912. /**
  913. * Where Ant should place temporary files.
  914. *
  915. * @since Ant 1.6
  916. * @return the temporary directory
  917. */
  918. public File getTempdir() {
  919. return tmpDir;
  920. }
  921. /**
  922. * The property to set on compilation success.
  923. * This property will not be set if the compilation
  924. * fails, or if there are no files to compile.
  925. * @param updatedProperty the property name to use.
  926. * @since Ant 1.7.1.
  927. */
  928. public void setUpdatedProperty(final String updatedProperty) {
  929. this.updatedProperty = updatedProperty;
  930. }
  931. /**
  932. * The property to set on compilation failure.
  933. * This property will be set if the compilation
  934. * fails.
  935. * @param errorProperty the property name to use.
  936. * @since Ant 1.7.1.
  937. */
  938. public void setErrorProperty(final String errorProperty) {
  939. this.errorProperty = errorProperty;
  940. }
  941. /**
  942. * This property controls whether to include the
  943. * destination classes directory in the classpath
  944. * given to the compiler.
  945. * The default value is "true".
  946. * @param includeDestClasses the value to use.
  947. */
  948. public void setIncludeDestClasses(final boolean includeDestClasses) {
  949. this.includeDestClasses = includeDestClasses;
  950. }
  951. /**
  952. * Get the value of the includeDestClasses property.
  953. * @return the value.
  954. */
  955. public boolean isIncludeDestClasses() {
  956. return includeDestClasses;
  957. }
  958. /**
  959. * Get the result of the javac task (success or failure).
  960. * @return true if compilation succeeded, or
  961. * was not necessary, false if the compilation failed.
  962. */
  963. public boolean getTaskSuccess() {
  964. return taskSuccess;
  965. }
  966. /**
  967. * The classpath to use when loading the compiler implementation
  968. * if it is not a built-in one.
  969. *
  970. * @since Ant 1.8.0
  971. */
  972. public Path createCompilerClasspath() {
  973. return facade.getImplementationClasspath(getProject());
  974. }
  975. /**
  976. * Set the compiler adapter explicitly.
  977. * @since Ant 1.8.0
  978. */
  979. public void add(final CompilerAdapter adapter) {
  980. if (nestedAdapter != null) {
  981. throw new BuildException(
  982. "Can't have more than one compiler adapter");
  983. }
  984. nestedAdapter = adapter;
  985. }
  986. /**
  987. * Whether package-info.class files will be created by Ant
  988. * matching package-info.java files that have been compiled but
  989. * didn't create class files themselves.
  990. *
  991. * @since Ant 1.8.3
  992. */
  993. public void setCreateMissingPackageInfoClass(final boolean b) {
  994. createMissingPackageInfoClass = b;
  995. }
  996. /**
  997. * Executes the task.
  998. * @exception BuildException if an error occurs
  999. */
  1000. @Override
  1001. public void execute() throws BuildException {
  1002. checkParameters();
  1003. resetFileLists();
  1004. // scan source directories and dest directory to build up
  1005. // compile list
  1006. if (hasPath(src)) {
  1007. collectFileListFromSourcePath();
  1008. } else {
  1009. assert hasPath(moduleSourcepath) : "Either srcDir or moduleSourcepath must be given";
  1010. collectFileListFromModulePath();
  1011. }
  1012. compile();
  1013. if (updatedProperty != null
  1014. && taskSuccess
  1015. && compileList.length != 0) {
  1016. getProject().setNewProperty(updatedProperty, "true");
  1017. }
  1018. }
  1019. /**
  1020. * Clear the list of files to be compiled and copied..
  1021. */
  1022. protected void resetFileLists() {
  1023. compileList = new File[0];
  1024. packageInfos = new HashMap<>();
  1025. }
  1026. /**
  1027. * Scans the directory looking for source files to be compiled.
  1028. * The results are returned in the class variable compileList
  1029. *
  1030. * @param srcDir The source directory
  1031. * @param destDir The destination directory
  1032. * @param files An array of filenames
  1033. */
  1034. protected void scanDir(final File srcDir, final File destDir, final String[] files) {
  1035. final GlobPatternMapper m = new GlobPatternMapper();
  1036. final String[] extensions = findSupportedFileExtensions();
  1037. for (String extension : extensions) {
  1038. m.setFrom(extension);
  1039. m.setTo("*.class");
  1040. final SourceFileScanner sfs = new SourceFileScanner(this);
  1041. final File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
  1042. if (newFiles.length > 0) {
  1043. lookForPackageInfos(srcDir, newFiles);
  1044. final File[] newCompileList
  1045. = new File[compileList.length + newFiles.length];
  1046. System.arraycopy(compileList, 0, newCompileList, 0,
  1047. compileList.length);
  1048. System.arraycopy(newFiles, 0, newCompileList,
  1049. compileList.length, newFiles.length);
  1050. compileList = newCompileList;
  1051. }
  1052. }
  1053. }
  1054. private void collectFileListFromSourcePath() {
  1055. final String[] list = src.list();
  1056. for (int i = 0; i < list.length; i++) {
  1057. final File srcDir = getProject().resolveFile(list[i]);
  1058. if (!srcDir.exists()) {
  1059. throw new BuildException("srcdir \""
  1060. + srcDir.getPath()
  1061. + "\" does not exist!", getLocation());
  1062. }
  1063. final DirectoryScanner ds = this.getDirectoryScanner(srcDir);
  1064. final String[] files = ds.getIncludedFiles();
  1065. scanDir(srcDir, destDir != null ? destDir : srcDir, files);
  1066. }
  1067. }
  1068. private void collectFileListFromModulePath() {
  1069. final FileUtils fu = FileUtils.getFileUtils();
  1070. for (String pathElement : moduleSourcepath.list()) {
  1071. boolean valid = false;
  1072. for (Map.Entry<String, Collection<File>> modules : resolveModuleSourcePathElement(
  1073. getProject().getBaseDir(), pathElement).entrySet()) {
  1074. final String moduleName = modules.getKey();
  1075. for (File srcDir : modules.getValue()) {
  1076. if (srcDir.exists()) {
  1077. valid = true;
  1078. final DirectoryScanner ds = getDirectoryScanner(srcDir);
  1079. final String[] files = ds.getIncludedFiles();
  1080. scanDir(srcDir, fu.resolveFile(destDir, moduleName), files);
  1081. }
  1082. }
  1083. }
  1084. if (!valid) {
  1085. throw new BuildException("modulesourcepath \""
  1086. + pathElement
  1087. + "\" does not exist!", getLocation());
  1088. }
  1089. }
  1090. }
  1091. private String[] findSupportedFileExtensions() {
  1092. final String compilerImpl = getCompiler();
  1093. final CompilerAdapter adapter =
  1094. nestedAdapter != null ? nestedAdapter :
  1095. CompilerAdapterFactory.getCompiler(compilerImpl, this,
  1096. createCompilerClasspath());
  1097. String[] extensions = null;
  1098. if (adapter instanceof CompilerAdapterExtension) {
  1099. extensions =
  1100. ((CompilerAdapterExtension) adapter).getSupportedFileExtensions();
  1101. }
  1102. if (extensions == null) {
  1103. extensions = new String[] { "java" };
  1104. }
  1105. // now process the extensions to ensure that they are the
  1106. // right format
  1107. for (int i = 0; i < extensions.length; i++) {
  1108. if (!extensions[i].startsWith("*.")) {
  1109. extensions[i] = "*." + extensions[i];
  1110. }
  1111. }
  1112. return extensions;
  1113. }
  1114. /**
  1115. * Gets the list of files to be compiled.
  1116. * @return the list of files as an array
  1117. */
  1118. public File[] getFileList() {
  1119. return compileList;
  1120. }
  1121. /**
  1122. * Is the compiler implementation a jdk compiler
  1123. *
  1124. * @param compilerImpl the name of the compiler implementation
  1125. * @return true if compilerImpl is "modern", "classic",
  1126. * "javac1.1", "javac1.2", "javac1.3", "javac1.4", "javac1.5",
  1127. * "javac1.6", "javac1.7", "javac1.8", "javac1.9" or "javac9".
  1128. */
  1129. protected boolean isJdkCompiler(final String compilerImpl) {
  1130. return MODERN.equals(compilerImpl)
  1131. || CLASSIC.equals(compilerImpl)
  1132. || JAVAC9.equals(compilerImpl)
  1133. || JAVAC18.equals(compilerImpl)
  1134. || JAVAC17.equals(compilerImpl)
  1135. || JAVAC16.equals(compilerImpl)
  1136. || JAVAC15.equals(compilerImpl)
  1137. || JAVAC14.equals(compilerImpl)
  1138. || JAVAC13.equals(compilerImpl)
  1139. || JAVAC12.equals(compilerImpl)
  1140. || JAVAC11.equals(compilerImpl);
  1141. }
  1142. /**
  1143. * @return the executable name of the java compiler
  1144. */
  1145. protected String getSystemJavac() {
  1146. return JavaEnvUtils.getJdkExecutable("javac");
  1147. }
  1148. /**
  1149. * Choose the implementation for this particular task.
  1150. * @param compiler the name of the compiler
  1151. * @since Ant 1.5
  1152. */
  1153. public void setCompiler(final String compiler) {
  1154. facade.setImplementation(compiler);
  1155. }
  1156. /**
  1157. * The implementation for this particular task.
  1158. *
  1159. * <p>Defaults to the build.compiler property but can be overridden
  1160. * via the compiler and fork attributes.</p>
  1161. *
  1162. * <p>If fork has been set to true, the result will be extJavac
  1163. * and not classic or java1.2 - no matter what the compiler
  1164. * attribute looks like.</p>
  1165. *
  1166. * @see #getCompilerVersion
  1167. * @return the compiler.
  1168. * @since Ant 1.5
  1169. */
  1170. public String getCompiler() {
  1171. String compilerImpl = getCompilerVersion();
  1172. if (fork) {
  1173. if (isJdkCompiler(compilerImpl)) {
  1174. compilerImpl = EXTJAVAC;
  1175. } else {
  1176. log("Since compiler setting isn't classic or modern, ignoring fork setting.",
  1177. Project.MSG_WARN);
  1178. }
  1179. }
  1180. return compilerImpl;
  1181. }
  1182. /**
  1183. * The implementation for this particular task.
  1184. *
  1185. * <p>Defaults to the build.compiler property but can be overridden
  1186. * via the compiler attribute.</p>
  1187. *
  1188. * <p>This method does not take the fork attribute into
  1189. * account.</p>
  1190. *
  1191. * @see #getCompiler
  1192. * @return the compiler.
  1193. *
  1194. * @since Ant 1.5
  1195. */
  1196. public String getCompilerVersion() {
  1197. facade.setMagicValue(getProject().getProperty("build.compiler"));
  1198. return facade.getImplementation();
  1199. }
  1200. /**
  1201. * Check that all required attributes have been set and nothing
  1202. * silly has been entered.
  1203. *
  1204. * @since Ant 1.5
  1205. * @exception BuildException if an error occurs
  1206. */
  1207. protected void checkParameters() throws BuildException {
  1208. if (hasPath(src)) {
  1209. if (hasPath(moduleSourcepath)) {
  1210. throw new BuildException("modulesourcepath cannot be combined with srcdir attribute!",
  1211. getLocation());
  1212. }
  1213. } else if (hasPath(moduleSourcepath)) {
  1214. if (hasPath(src) || hasPath(compileSourcepath)) {
  1215. throw new BuildException("modulesourcepath cannot be combined with srcdir or sourcepath !",
  1216. getLocation());
  1217. }
  1218. if (destDir == null) {
  1219. throw new BuildException("modulesourcepath requires destdir attribute to be set!",
  1220. getLocation());
  1221. }
  1222. } else {
  1223. throw new BuildException("either srcdir or modulesourcepath attribute must be set!",
  1224. getLocation());
  1225. }
  1226. if (destDir != null && !destDir.isDirectory()) {
  1227. throw new BuildException("destination directory \""
  1228. + destDir
  1229. + "\" does not exist or is not a directory", getLocation());
  1230. }
  1231. if (includeAntRuntime == null && getProject().getProperty("build.sysclasspath") == null) {
  1232. log(getLocation()
  1233. + "warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds",
  1234. Project.MSG_WARN);
  1235. }
  1236. }
  1237. /**
  1238. * Perform the compilation.
  1239. *
  1240. * @since Ant 1.5
  1241. */
  1242. protected void compile() {
  1243. final String compilerImpl = getCompiler();
  1244. if (compileList.length > 0) {
  1245. log("Compiling " + compileList.length + " source file"
  1246. + (compileList.length == 1 ? "" : "s")
  1247. + (destDir != null ? " to " + destDir : ""));
  1248. if (listFiles) {
  1249. for (File element : compileList) {
  1250. log(element.getAbsolutePath());
  1251. }
  1252. }
  1253. final CompilerAdapter adapter =
  1254. nestedAdapter != null ? nestedAdapter :
  1255. CompilerAdapterFactory.getCompiler(compilerImpl, this,
  1256. createCompilerClasspath());
  1257. // now we need to populate the compiler adapter
  1258. adapter.setJavac(this);
  1259. // finally, lets execute the compiler!!
  1260. if (adapter.execute()) {
  1261. // Success
  1262. if (createMissingPackageInfoClass) {
  1263. try {
  1264. generateMissingPackageInfoClasses(destDir != null
  1265. ? destDir
  1266. : getProject()
  1267. .resolveFile(src.list()[0]));
  1268. } catch (final IOException x) {
  1269. // Should this be made a nonfatal warning?
  1270. throw new BuildException(x, getLocation());
  1271. }
  1272. }
  1273. } else {
  1274. // Fail path
  1275. this.taskSuccess = false;
  1276. if (errorProperty != null) {
  1277. getProject().setNewProperty(
  1278. errorProperty, "true");
  1279. }
  1280. if (failOnError) {
  1281. throw new BuildException(FAIL_MSG, getLocation());
  1282. }
  1283. log(FAIL_MSG, Project.MSG_ERR);
  1284. }
  1285. }
  1286. }
  1287. /**
  1288. * Adds an "compiler" attribute to Commandline$Attribute used to
  1289. * filter command line attributes based on the current
  1290. * implementation.
  1291. */
  1292. public class ImplementationSpecificArgument extends
  1293. org.apache.tools.ant.util.facade.ImplementationSpecificArgument {
  1294. /**
  1295. * @param impl the name of the compiler
  1296. */
  1297. public void setCompiler(final String impl) {
  1298. super.setImplementation(impl);
  1299. }
  1300. }
  1301. private void lookForPackageInfos(final File srcDir, final File[] newFiles) {
  1302. for (File f : newFiles) {
  1303. if (!"package-info.java".equals(f.getName())) {
  1304. continue;
  1305. }
  1306. final String path = FILE_UTILS.removeLeadingPath(srcDir, f).
  1307. replace(File.separatorChar, '/');
  1308. final String suffix = "/package-info.java";
  1309. if (!path.endsWith(suffix)) {
  1310. log("anomalous package-info.java path: " + path, Project.MSG_WARN);
  1311. continue;
  1312. }
  1313. final String pkg = path.substring(0, path.length() - suffix.length());
  1314. packageInfos.put(pkg, Long.valueOf(f.lastModified()));
  1315. }
  1316. }
  1317. /**
  1318. * Ensure that every {@code package-info.java} produced a {@code package-info.class}.
  1319. * Otherwise this task's up-to-date tracking mechanisms do not work.
  1320. * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43114">Bug #43114</a>
  1321. */
  1322. private void generateMissingPackageInfoClasses(final File dest) throws IOException {
  1323. for (final Map.Entry<String, Long> entry : packageInfos.entrySet()) {
  1324. final String pkg = entry.getKey();
  1325. final Long sourceLastMod = entry.getValue();
  1326. final File pkgBinDir = new File(dest, pkg.replace('/', File.separatorChar));
  1327. pkgBinDir.mkdirs();
  1328. final File pkgInfoClass = new File(pkgBinDir, "package-info.class");
  1329. if (pkgInfoClass.isFile() && pkgInfoClass.lastModified() >= sourceLastMod.longValue()) {
  1330. continue;
  1331. }
  1332. log("Creating empty " + pkgInfoClass);
  1333. try (OutputStream os = Files.newOutputStream(pkgInfoClass.toPath())) {
  1334. os.write(PACKAGE_INFO_CLASS_HEADER);
  1335. final byte[] name = pkg.getBytes("UTF-8");
  1336. final int length = name.length + /* "/package-info" */ 13;
  1337. os.write((byte) length / 256);
  1338. os.write((byte) length % 256);
  1339. os.write(name);
  1340. os.write(PACKAGE_INFO_CLASS_FOOTER);
  1341. }
  1342. }
  1343. }
  1344. /**
  1345. * Checks if a path exists and is non empty.
  1346. * @param path to be checked
  1347. * @return true if the path is non <code>null</code> and non empty.
  1348. * @since 1.9.7
  1349. */
  1350. private static boolean hasPath(final Path path) {
  1351. return path != null && !path.isEmpty();
  1352. }
  1353. /**
  1354. * Resolves the modulesourcepath element possibly containing groups
  1355. * and module marks to module names and source roots.
  1356. * @param projectDir the project directory
  1357. * @param element the modulesourcepath elemement
  1358. * @return a mapping from module name to module source roots
  1359. * @since 1.9.7
  1360. */
  1361. private static Map<String,Collection<File>> resolveModuleSourcePathElement(
  1362. final File projectDir,
  1363. final String element) {
  1364. final Map<String,Collection<File>> result = new TreeMap<String, Collection<File>>();
  1365. for (CharSequence resolvedElement : expandGroups(element)) {
  1366. findModules(projectDir, resolvedElement.toString(), result);
  1367. }
  1368. return result;
  1369. }
  1370. /**
  1371. * Expands the groups in the modulesourcepath entry to alternatives.
  1372. * <p>
  1373. * The <code>'*'</code> is a token representing the name of any of the modules in the compilation module set.
  1374. * The <code>'{' ... ',' ... '}'</code> express alternates for expansion.
  1375. * An example of the modulesourcepath entry is <code>src/&#42;/{linux,share}/classes</code>
  1376. * </p>
  1377. * @param element the entry to expand groups in
  1378. * @return the possible alternatives
  1379. * @since 1.9.7
  1380. */
  1381. private static Collection<? extends CharSequence> expandGroups(
  1382. final CharSequence element) {
  1383. List<StringBuilder> result = new ArrayList<>();
  1384. result.add(new StringBuilder());
  1385. StringBuilder resolved = new StringBuilder();
  1386. for (int i = 0; i < element.length(); i++) {
  1387. final char c = element.charAt(i);
  1388. switch (c) {
  1389. case GROUP_START_MARK:
  1390. final int end = getGroupEndIndex(element, i);
  1391. if (end < 0) {
  1392. throw new BuildException(String.format(
  1393. "Unclosed group %s, starting at: %d",
  1394. element,
  1395. i));
  1396. }
  1397. final Collection<? extends CharSequence> parts = resolveGroup(element.subSequence(i+1, end));
  1398. switch (parts.size()) {
  1399. case 0:
  1400. break;
  1401. case 1:
  1402. resolved.append(parts.iterator().next());
  1403. break;
  1404. default:
  1405. final List<StringBuilder> oldRes = result;
  1406. result = new ArrayList<>(oldRes.size() * parts.size());
  1407. for (CharSequence part : parts) {
  1408. for (CharSequence prefix : oldRes) {
  1409. result.add(new StringBuilder(prefix).append(resolved).append(part));
  1410. }
  1411. }
  1412. resolved = new StringBuilder();
  1413. }
  1414. i = end;
  1415. break;
  1416. default:
  1417. resolved.append(c);
  1418. }
  1419. }
  1420. for (StringBuilder prefix : result) {
  1421. prefix.append(resolved);
  1422. }
  1423. return result;
  1424. }
  1425. /**
  1426. * Resolves the group to alternatives.
  1427. * @param group the group to resolve
  1428. * @return the possible alternatives
  1429. * @since 1.9.7
  1430. */
  1431. private static Collection<? extends CharSequence> resolveGroup(final CharSequence group) {
  1432. final Collection<CharSequence> result = new ArrayList<>();
  1433. int start = 0;
  1434. int depth = 0;
  1435. for (int i = 0; i < group.length(); i++) {
  1436. final char c = group.charAt(i);
  1437. switch (c) {
  1438. case GROUP_START_MARK:
  1439. depth++;
  1440. break;
  1441. case GROUP_END_MARK:
  1442. depth--;
  1443. break;
  1444. case GROUP_SEP_MARK:
  1445. if (depth == 0) {
  1446. result.addAll(expandGroups(group.subSequence(start, i)));
  1447. start = i + 1;
  1448. }
  1449. break;
  1450. }
  1451. }
  1452. result.addAll(expandGroups(group.subSequence(start, group.length())));
  1453. return result;
  1454. }
  1455. /**
  1456. * Finds the index of an enclosing brace of the group.
  1457. * @param element the element to find the enclosing brace in
  1458. * @param start the index of the opening brace.
  1459. * @return return the index of an enclosing brace of the group or -1 if not found
  1460. * @since 1.9.7
  1461. */
  1462. private static int getGroupEndIndex(
  1463. final CharSequence element,
  1464. final int start) {
  1465. int depth = 0;
  1466. for (int i = start; i < element.length(); i++) {
  1467. final char c = element.charAt(i);
  1468. switch (c) {
  1469. case GROUP_START_MARK:
  1470. depth++;
  1471. break;
  1472. case GROUP_END_MARK:
  1473. depth--;
  1474. if (depth == 0) {
  1475. return i;
  1476. }
  1477. break;
  1478. }
  1479. }
  1480. return -1;
  1481. }
  1482. /**
  1483. * Finds modules in the expanded modulesourcepath entry.
  1484. * @param root the project root
  1485. * @param pattern the expanded modulesourcepath entry
  1486. * @param collector the map to put modules into
  1487. * @since 1.9.7
  1488. */
  1489. private static void findModules(
  1490. final File root,
  1491. String pattern,
  1492. final Map<String,Collection<File>> collector) {
  1493. pattern = pattern
  1494. .replace('/', File.separatorChar)
  1495. .replace('\\', File.separatorChar);
  1496. final int startIndex = pattern.indexOf(MODULE_MARKER);
  1497. if (startIndex == -1) {
  1498. findModules(root, pattern, null, collector);
  1499. return;
  1500. }
  1501. if (startIndex == 0) {
  1502. throw new BuildException("The modulesourcepath entry must be a folder.");
  1503. }
  1504. final int endIndex = startIndex + MODULE_MARKER.length();
  1505. if (pattern.charAt(startIndex - 1) != File.separatorChar) {
  1506. throw new BuildException("The module mark must be preceded by separator");
  1507. }
  1508. if (endIndex < pattern.length() && pattern.charAt(endIndex) != File.separatorChar) {
  1509. throw new BuildException("The module mark must be followed by separator");
  1510. }
  1511. if (pattern.indexOf(MODULE_MARKER, endIndex) != -1) {
  1512. throw new BuildException("The modulesourcepath entry must contain at most one module mark");
  1513. }
  1514. final String pathToModule = pattern.substring(0, startIndex);
  1515. final String pathInModule = endIndex == pattern.length() ?
  1516. null :
  1517. pattern.substring(endIndex + 1); //+1 the separator
  1518. findModules(root, pathToModule, pathInModule, collector);
  1519. }
  1520. /**
  1521. * Finds modules in the expanded modulesourcepath entry.
  1522. * @param root the project root
  1523. * @param pathToModule the path to modules folder
  1524. * @param pathInModule the path in module to source folder
  1525. * @param collector the map to put modules into
  1526. * @since 1.9.7
  1527. */
  1528. private static void findModules(
  1529. final File root,
  1530. final String pathToModule,
  1531. final String pathInModule,
  1532. final Map<String,Collection<File>> collector) {
  1533. final FileUtils fu = FileUtils.getFileUtils();
  1534. final File f = fu.resolveFile(root, pathToModule);
  1535. if (!f.isDirectory()) {
  1536. return;
  1537. }
  1538. for (File module : f.listFiles(File::isDirectory)) {
  1539. final String moduleName = module.getName();
  1540. final File moduleSourceRoot = pathInModule == null ?
  1541. module :
  1542. new File(module, pathInModule);
  1543. Collection<File> moduleRoots = collector.get(moduleName);
  1544. if (moduleRoots == null) {
  1545. moduleRoots = new ArrayList<>();
  1546. collector.put(moduleName, moduleRoots);
  1547. }
  1548. moduleRoots.add(moduleSourceRoot);
  1549. }
  1550. }
  1551. private static final byte[] PACKAGE_INFO_CLASS_HEADER = {
  1552. (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe, 0x00, 0x00, 0x00,
  1553. 0x31, 0x00, 0x07, 0x07, 0x00, 0x05, 0x07, 0x00, 0x06, 0x01, 0x00, 0x0a,
  1554. 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x00,
  1555. 0x11, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2d, 0x69, 0x6e, 0x66,
  1556. 0x6f, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0x01
  1557. };
  1558. private static final byte[] PACKAGE_INFO_CLASS_FOOTER = {
  1559. 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2d, 0x69, 0x6e, 0x66,
  1560. 0x6f, 0x01, 0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e,
  1561. 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x02, 0x00, 0x00, 0x01,
  1562. 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,
  1563. 0x00, 0x00, 0x00, 0x02, 0x00, 0x04
  1564. };
  1565. }