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 57 kB

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