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

CompilerRun.java 70KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC),
  3. * 2003 Contributors.
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Common Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/cpl-v10.html
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * Wes Isberg 2003 updates
  13. * ******************************************************************/
  14. package org.aspectj.testing.harness.bridge;
  15. import java.io.*;
  16. import java.util.*;
  17. import org.aspectj.bridge.*;
  18. import org.aspectj.testing.ajde.CompileCommand;
  19. import org.aspectj.testing.run.*;
  20. import org.aspectj.testing.taskdefs.AjcTaskCompileCommand;
  21. import org.aspectj.testing.util.options.*;
  22. import org.aspectj.testing.util.options.Option.*;
  23. import org.aspectj.testing.xml.*;
  24. import org.aspectj.util.*;
  25. /**
  26. * Run the compiler once.
  27. * The lifecycle is as follows:
  28. * <ul>
  29. * <li>Spec (specification) is created.</li>
  30. * <li>This is created using the Spec.</li>
  31. * <li>setupAjcRun(Sandbox, Validator) is invoked,
  32. * at which point this populates the shared sandbox
  33. * with values derived from the spec and also
  34. * sets up internal state based on both the sandbox
  35. * and the spec.</li>
  36. * <li>run(IRunStatus) is invoked, and this runs the compiler
  37. * based on internal state, the spec, and the sandbox.</li>
  38. * </ul>
  39. * Programmer notes:
  40. * <ul>
  41. * <li>Paths are resolved absolutely, which fails to test the
  42. * compiler's ability to find files relative to a source base</li>
  43. * <li>This does not enforce the lifecycle.</li>
  44. * <li>This must be used as the initial compile
  45. * before doing an incremental compile.
  46. * In that case, staging must be enabled.</li>
  47. * </ul>
  48. */
  49. public class CompilerRun implements IAjcRun {
  50. // static final String JAVAC_COMPILER
  51. // = JavacCompileCommand.class.getName();
  52. static final String[] RA_String = new String[0];
  53. static final String[] JAR_SUFFIXES = new String[] { ".jar", ".zip" };
  54. static final String[] SOURCE_SUFFIXES =
  55. (String[]) FileUtil.SOURCE_SUFFIXES.toArray(new String[0]);
  56. /** specifications, set on construction */
  57. Spec spec;
  58. //------------ calculated during setup
  59. /** get shared stuff during setup */
  60. Sandbox sandbox;
  61. /**
  62. * During run, these String are passed as the source and arg files to compile.
  63. * The list is set up in setupAjcRun(..), when arg files are prefixed with "@".
  64. */
  65. final List /*String*/
  66. arguments;
  67. /**
  68. * During run, these String are collapsed and passed as the injar option.
  69. * The list is set up in setupAjcRun(..).
  70. */
  71. final List /*String*/
  72. injars;
  73. /**
  74. * During run, these String are collapsed and passed as the inpath option.
  75. * The list is set up in setupAjcRun(..),
  76. * which extracts only directories from the files attribute.
  77. */
  78. final List inpaths;
  79. private CompilerRun(Spec spec) {
  80. if (null == spec) {
  81. throw new IllegalArgumentException("null spec");
  82. }
  83. this.spec = spec;
  84. arguments = new ArrayList();
  85. injars = new ArrayList();
  86. inpaths = new ArrayList();
  87. }
  88. /**
  89. * This checks that the spec is reasonable and does setup:
  90. * <ul>
  91. * <li>calculate and set sandbox testBaseSrcDir as {Sandbox.testBaseDir}/
  92. * {Spec.testSrcDirOffset}/<li>
  93. * <li>get the list of source File to compile as {Sandbox.testBaseSrcDir} /
  94. * {Spec.getPaths..}</li>
  95. * <li>get the list of extraClasspath entries to add to default classpath as
  96. * {Sandbox.testBaseSrcDir} / {Spec.classpath..}</li>
  97. * <li>get the list of aspectpath entries to use as the aspectpath as
  98. * {Sandbox. testBaseSrcDir} / {Spec.aspectpath..}</li>
  99. * </ul>
  100. * All sources must be readable at this time,
  101. * unless spec.badInput is true (for invalid-input tests).
  102. * If staging, the source files and source roots are copied
  103. * to a separate staging directory so they can be modified
  104. * for incremental tests. Note that (as of this writing) the
  105. * compiler only handles source roots for incremental tests.
  106. * @param classesDir the File
  107. * @see org.aspectj.testing.harness.bridge.AjcTest.IAjcRun#setup(File, File)
  108. * @throws AbortException containing IOException or IllegalArgumentException
  109. * if the staging operations fail
  110. */
  111. public boolean setupAjcRun(Sandbox sandbox, Validator validator) {
  112. if (!validator.nullcheck(spec.getOptionsArray(), "localOptions")
  113. || !validator.nullcheck(sandbox, "sandbox")
  114. || !validator.nullcheck(spec.compiler, "compilerName")
  115. || !validator.canRead(Globals.F_aspectjrt_jar, "aspectjrt.jar")
  116. || !validator.canRead(
  117. Globals.F_testingclient_jar,
  118. "testing-client.jar")) {
  119. return false;
  120. }
  121. this.sandbox = sandbox;
  122. String rdir = spec.testSrcDirOffset;
  123. File testBaseSrcDir;
  124. if ((null == rdir) || (0 == rdir.length())) {
  125. testBaseSrcDir = sandbox.testBaseDir;
  126. } else {
  127. testBaseSrcDir = new File(sandbox.testBaseDir, rdir);
  128. // XXX what if rdir is two levels deep?
  129. if (!validator
  130. .canReadDir(testBaseSrcDir, "sandbox.testBaseSrcDir")) {
  131. return false;
  132. }
  133. }
  134. // Sources come as relative paths - check read, copy if staging.
  135. // This renders paths absolute before run(RunStatusI) is called.
  136. // For a compile run to support relative paths + source base,
  137. // change so the run calculates the paths (differently when staging)
  138. final String[] inpathPaths;
  139. final String[] injarPaths;
  140. final String[] srcPaths;
  141. {
  142. final String[] paths = spec.getPathsArray();
  143. srcPaths =
  144. LangUtil.endsWith(
  145. paths,
  146. CompilerRun.SOURCE_SUFFIXES,
  147. true);
  148. injarPaths =
  149. LangUtil.endsWith(paths, CompilerRun.JAR_SUFFIXES, true);
  150. inpathPaths =
  151. LangUtil.selectDirectories(paths, testBaseSrcDir);
  152. if (!spec.badInput) {
  153. int found = inpathPaths.length + injarPaths.length + srcPaths.length;
  154. if (paths.length != found) {
  155. validator.fail("found " + found + " of " + paths.length + " sources");
  156. }
  157. }
  158. }
  159. // validate readable for sources
  160. if (!spec.badInput) {
  161. if (!validator.canRead(testBaseSrcDir, srcPaths, "sources")
  162. // see validation of inpathPaths below due to ambiguous base dir
  163. || !validator.canRead(
  164. testBaseSrcDir,
  165. spec.argfiles,
  166. "argfiles")
  167. || !validator.canRead(
  168. testBaseSrcDir,
  169. spec.classpath,
  170. "classpath")
  171. || !validator.canRead(
  172. testBaseSrcDir,
  173. spec.aspectpath,
  174. "aspectpath")
  175. || !validator.canRead(
  176. testBaseSrcDir,
  177. spec.sourceroots,
  178. "sourceroots")
  179. || !validator.canRead(
  180. testBaseSrcDir,
  181. spec.extdirs,
  182. "extdirs")) {
  183. return false;
  184. }
  185. }
  186. int numSources =
  187. srcPaths.length
  188. + injarPaths.length
  189. + inpathPaths.length
  190. + spec.argfiles.length
  191. + spec.sourceroots.length;
  192. if (!spec.badInput && (numSources < 1)) {
  193. validator.fail(
  194. "no input jars, arg files, or source files or roots");
  195. return false;
  196. }
  197. final File[] argFiles =
  198. FileUtil.getBaseDirFiles(testBaseSrcDir, spec.argfiles);
  199. final File[] injarFiles =
  200. FileUtil.getBaseDirFiles(testBaseSrcDir, injarPaths);
  201. final File[] inpathFiles =
  202. FileUtil.getBaseDirFiles(testBaseSrcDir, inpathPaths);
  203. final File[] aspectFiles =
  204. FileUtil.getBaseDirFiles(testBaseSrcDir, spec.aspectpath);
  205. final File[] extdirFiles =
  206. FileUtil.getBaseDirFiles(testBaseSrcDir, spec.extdirs);
  207. final File[] classFiles =
  208. FileUtil.getBaseDirFiles(testBaseSrcDir, spec.classpath);
  209. final File[] xlintFiles = (null == spec.xlintfile ? new File[0]
  210. : FileUtil.getBaseDirFiles(testBaseSrcDir, new String[] {spec.xlintfile}));
  211. // injars might be outjars in the classes dir...
  212. for (int i = 0; i < injarFiles.length; i++) {
  213. if (!injarFiles[i].exists()) {
  214. injarFiles[i] = new File(sandbox.classesDir, injarPaths[i]);
  215. }
  216. }
  217. for (int i = 0; i < inpathFiles.length; i++) {
  218. if (!inpathFiles[i].exists()) {
  219. inpathFiles[i] = new File(sandbox.classesDir, inpathPaths[i]);
  220. }
  221. }
  222. // moved after solving any injars that were outjars
  223. if (!validator.canRead(injarFiles, "injars")
  224. || !validator.canRead(injarFiles, "injars")) {
  225. return false;
  226. }
  227. // hmm - duplicates validation above, verifying getBaseDirFiles?
  228. if (!spec.badInput) {
  229. if (!validator.canRead(argFiles, "argFiles")
  230. || !validator.canRead(injarFiles, "injarFiles")
  231. || !validator.canRead(inpathFiles, "inpathFiles")
  232. || !validator.canRead(aspectFiles, "aspectFiles")
  233. || !validator.canRead(classFiles, "classFiles")
  234. || !validator.canRead(xlintFiles, "xlintFiles")) {
  235. return false;
  236. }
  237. }
  238. final File[] srcFiles;
  239. File[] sourcerootFiles = new File[0];
  240. // source text files are copied when staging incremental tests
  241. if (!spec.isStaging()) {
  242. // XXX why this? was always? || (testBaseSrcDir != sandbox.stagingDir))) {
  243. srcFiles =
  244. FileUtil.getBaseDirFiles(
  245. testBaseSrcDir,
  246. srcPaths,
  247. CompilerRun.SOURCE_SUFFIXES);
  248. if (!LangUtil.isEmpty(spec.sourceroots)) {
  249. sourcerootFiles =
  250. FileUtil.getBaseDirFiles(
  251. testBaseSrcDir,
  252. spec.sourceroots,
  253. null);
  254. }
  255. } else { // staging - copy files
  256. if (spec.badInput) {
  257. validator.info(
  258. "badInput ignored - files checked when staging");
  259. }
  260. try {
  261. // copy all files, then remove tagged ones
  262. // XXX make copyFiles support a filter?
  263. srcFiles =
  264. FileUtil.copyFiles(
  265. testBaseSrcDir,
  266. srcPaths,
  267. sandbox.stagingDir);
  268. if (!LangUtil.isEmpty(spec.sourceroots)) {
  269. sourcerootFiles =
  270. FileUtil.copyFiles(
  271. testBaseSrcDir,
  272. spec.sourceroots,
  273. sandbox.stagingDir);
  274. // delete incremental files in sourceroot after copying // XXX inefficient
  275. // an incremental file has an extra "." in name
  276. // most .java files don't, because they are named after
  277. // the principle type they contain, and simple type names
  278. // have no dots.
  279. FileFilter pickIncFiles = new FileFilter() {
  280. public boolean accept(File file) {
  281. if (file.isDirectory()) {
  282. // continue recursion
  283. return true;
  284. }
  285. String path = file.getPath();
  286. // only source files are relevant to staging
  287. if (!FileUtil.hasSourceSuffix(path)) {
  288. return false;
  289. }
  290. int first = path.indexOf(".");
  291. int last = path.lastIndexOf(".");
  292. return (first != last);
  293. }
  294. };
  295. for (int i = 0; i < sourcerootFiles.length; i++) {
  296. FileUtil.deleteContents(
  297. sourcerootFiles[i],
  298. pickIncFiles,
  299. false);
  300. }
  301. if (0 < sourcerootFiles.length) {
  302. FileUtil.sleepPastFinalModifiedTime(
  303. sourcerootFiles);
  304. }
  305. }
  306. File[] files =
  307. FileUtil.getBaseDirFiles(sandbox.stagingDir, srcPaths);
  308. if (0 < files.length) {
  309. FileUtil.sleepPastFinalModifiedTime(files);
  310. }
  311. } catch (IllegalArgumentException e) {
  312. validator.fail("staging - bad input", e);
  313. return false;
  314. } catch (IOException e) {
  315. validator.fail("staging - operations", e);
  316. return false;
  317. }
  318. }
  319. if (!spec.badInput
  320. && !validator.canRead(srcFiles, "copied paths")) {
  321. return false;
  322. }
  323. arguments.clear();
  324. if (!LangUtil.isEmpty(xlintFiles)) {
  325. arguments.add("-Xlintfile");
  326. String sr = FileUtil.flatten(xlintFiles, null);
  327. arguments.add(sr);
  328. }
  329. if (spec.outjar != null) {
  330. arguments.add("-outjar");
  331. arguments.add(new File(sandbox.classesDir,spec.outjar).getPath());
  332. }
  333. if (!LangUtil.isEmpty(extdirFiles)) {
  334. arguments.add("-extdirs");
  335. String sr = FileUtil.flatten(extdirFiles, null);
  336. arguments.add(sr);
  337. }
  338. if (!LangUtil.isEmpty(sourcerootFiles)) {
  339. arguments.add("-sourceroots");
  340. String sr = FileUtil.flatten(sourcerootFiles, null);
  341. arguments.add(sr);
  342. }
  343. if (!LangUtil.isEmpty(srcFiles)) {
  344. arguments.addAll(Arrays.asList(FileUtil.getPaths(srcFiles)));
  345. }
  346. injars.clear();
  347. if (!LangUtil.isEmpty(injarFiles)) {
  348. injars.addAll(Arrays.asList(FileUtil.getPaths(injarFiles)));
  349. }
  350. inpaths.clear();
  351. if (!LangUtil.isEmpty(inpathFiles)) {
  352. inpaths.addAll(Arrays.asList(FileUtil.getPaths(inpathFiles)));
  353. }
  354. if (!LangUtil.isEmpty(argFiles)) {
  355. String[] ra = FileUtil.getPaths(argFiles);
  356. for (int j = 0; j < ra.length; j++) {
  357. arguments.add("@" + ra[j]);
  358. }
  359. if (!spec.badInput && spec.isStaging) {
  360. validator.fail(
  361. "warning: files listed in argfiles not staged");
  362. }
  363. }
  364. // save classpath and aspectpath in sandbox for this and other clients
  365. final boolean checkReadable = !spec.badInput;
  366. int size = spec.includeClassesDir ? 3 : 2;
  367. File[] cp = new File[size + classFiles.length];
  368. System.arraycopy(classFiles, 0, cp, 0, classFiles.length);
  369. int index = classFiles.length;
  370. if (spec.includeClassesDir) {
  371. cp[index++] = sandbox.classesDir;
  372. }
  373. cp[index++] = Globals.F_aspectjrt_jar;
  374. cp[index++] = Globals.F_testingclient_jar;
  375. sandbox.compilerRunInit(this, testBaseSrcDir, aspectFiles,
  376. checkReadable, cp, checkReadable, null);
  377. // XXX todo set bootclasspath if set for forking?
  378. return true;
  379. }
  380. /**
  381. * Setup result evaluation and command line, run, and evaluate result.
  382. * <li>setup an AjcMessageHandler using the expected messages from
  383. * {@link Spec#getMessages()}.<li>
  384. * <li>heed any globals interpreted into a TestSetup by reading
  385. * {@link Spec@getOptions()}. For a list of supported globals, see
  386. * {@link setupArgs(ArrayList, IMessageHandler}.</li>
  387. * <li>construct a command line, using as classpath
  388. * {@link Sandbox.classpathToString()}<li>
  389. * <li>construct a compiler using {@link Spec#compiler}
  390. * or any overriding value set in TestSetup.<li>
  391. * <li>Just before running, set the compiler in the sandbox using
  392. * {@link Sandbox.setCompiler(ICommand)}.<li>
  393. * <li>After running, report AjcMessageHandler results to the status parameter.
  394. * If the AjcMessageHandler reports a failure, then send info messages
  395. * for the Spec, TestSetup, and command line.<li>
  396. * @see org.aspectj.testing.run.IRun#run(IRunStatus)
  397. */
  398. public boolean run(IRunStatus status) {
  399. if (null == spec.testSetup) {
  400. MessageUtil.abort(
  401. status,
  402. "no test setup - adoptParentValues not called");
  403. return false;
  404. } else if (!spec.testSetup.result) {
  405. MessageUtil.abort(status, spec.testSetup.failureReason);
  406. return false;
  407. }
  408. AjcMessageHandler handler =
  409. new AjcMessageHandler(spec.getMessages());
  410. handler.init();
  411. boolean handlerResult = false;
  412. boolean result = false;
  413. boolean commandResult = false;
  414. ArrayList argList = new ArrayList();
  415. final Spec.TestSetup setupResult = spec.testSetup;
  416. try {
  417. if (spec.outjar == null) {
  418. argList.add("-d");
  419. String outputDirPath = sandbox.classesDir.getAbsolutePath();
  420. try { // worth it to try for canonical?
  421. outputDirPath = sandbox.classesDir.getCanonicalPath();
  422. } catch (IOException e) {
  423. MessageUtil.abort(
  424. status,
  425. "canonical " + sandbox.classesDir,
  426. e);
  427. }
  428. argList.add(outputDirPath);
  429. }
  430. String path = sandbox.classpathToString(this);
  431. if (!LangUtil.isEmpty(path)) {
  432. argList.add("-classpath");
  433. argList.add(path);
  434. }
  435. path = sandbox.getBootclasspath(this);
  436. if (!LangUtil.isEmpty(path)) {
  437. argList.add("-bootclasspath");
  438. argList.add(path);
  439. }
  440. path = sandbox.aspectpathToString(this);
  441. if (!LangUtil.isEmpty(path)) {
  442. argList.add("-aspectpath");
  443. argList.add(path);
  444. }
  445. if (0 < injars.size()) {
  446. argList.add("-injars");
  447. argList.add(
  448. FileUtil.flatten(
  449. (String[]) injars.toArray(new String[0]),
  450. null));
  451. }
  452. if (0 < inpaths.size()) {
  453. argList.add("-inpath");
  454. argList.add(
  455. FileUtil.flatten(
  456. (String[]) inpaths.toArray(new String[0]),
  457. null));
  458. }
  459. // put specified arguments last, for better badInput tests
  460. argList.addAll(setupResult.commandOptions);
  461. // add both java/aspectj and argfiles
  462. argList.addAll(arguments);
  463. // XXX hack - seek on request as a side effect. reimplement as listener
  464. if (null != setupResult.seek) {
  465. String slopPrefix = Spec.SEEK_MESSAGE_PREFIX + " slop - ";
  466. PrintStream slop =
  467. MessageUtil.handlerPrintStream(
  468. status,
  469. IMessage.INFO,
  470. System.err,
  471. slopPrefix);
  472. List found =
  473. FileUtil.lineSeek(
  474. setupResult.seek,
  475. arguments,
  476. false,
  477. slop);
  478. if (!LangUtil.isEmpty(found)) {
  479. for (Iterator iter = found.iterator();
  480. iter.hasNext();
  481. ) {
  482. MessageUtil.info(
  483. status,
  484. Spec.SEEK_MESSAGE_PREFIX + iter.next());
  485. }
  486. }
  487. }
  488. ICommand compiler = spec.reuseCompiler
  489. // throws IllegalStateException if null
  490. ? sandbox.getCommand(this)
  491. : ReflectionFactory.makeCommand(setupResult.compilerName, status);
  492. DirChanges dirChanges = null;
  493. if (null == compiler) {
  494. MessageUtil.fail(
  495. status,
  496. "unable to make compiler " + setupResult.compilerName);
  497. return false;
  498. } else {
  499. if (setupResult.compilerName != Spec.DEFAULT_COMPILER) {
  500. MessageUtil.info(
  501. status,
  502. "compiler: " + setupResult.compilerName);
  503. }
  504. if (status.aborted()) {
  505. MessageUtil.debug(
  506. status,
  507. "aborted, but compiler valid?: " + compiler);
  508. } else {
  509. // same DirChanges handling for JavaRun, CompilerRun, IncCompilerRun
  510. // XXX around advice or template method/class
  511. if (!LangUtil.isEmpty(spec.dirChanges)) {
  512. LangUtil.throwIaxIfFalse(
  513. 1 == spec.dirChanges.size(),
  514. "expecting 0..1 dirChanges");
  515. dirChanges =
  516. new DirChanges(
  517. (DirChanges.Spec) spec.dirChanges.get(0));
  518. if (!dirChanges
  519. .start(status, sandbox.classesDir)) {
  520. return false; // setup failed
  521. }
  522. }
  523. MessageUtil.info(
  524. status,
  525. compiler + "(" + argList + ")");
  526. sandbox.setCommand(compiler, this);
  527. String[] args = (String[]) argList.toArray(RA_String);
  528. commandResult = compiler.runCommand(args, handler);
  529. }
  530. }
  531. handlerResult = handler.passed();
  532. if (!handlerResult) {
  533. return false;
  534. } else {
  535. result = (commandResult == handler.expectingCommandTrue());
  536. if (!result) {
  537. String m =
  538. commandResult
  539. ? "compile did not fail as expected"
  540. : "compile failed unexpectedly";
  541. MessageUtil.fail(status, m);
  542. } else if (null != dirChanges) {
  543. result = dirChanges.end(status, sandbox.testBaseDir);
  544. }
  545. }
  546. return result;
  547. } finally {
  548. if (!handlerResult) { // more debugging context in case of failure
  549. MessageUtil.info(handler, spec.toLongString());
  550. MessageUtil.info(handler, "" + argList);
  551. if (null != setupResult) {
  552. MessageUtil.info(handler, "" + setupResult);
  553. }
  554. }
  555. handler.report(status);
  556. // XXX weak - actual messages not reported in real-time, no fast-fail
  557. }
  558. }
  559. public String toString() {
  560. return "CompilerRun(" + spec + ")";
  561. }
  562. /**
  563. * Initializer/factory for CompilerRun
  564. * any path or file is relative to this test base dir
  565. */
  566. public static class Spec extends AbstractRunSpec {
  567. public static final String XMLNAME = "compile";
  568. public static final String DEFAULT_COMPILER =
  569. ReflectionFactory.ECLIPSE;
  570. static final String SEEK_PREFIX = "-seek:";
  571. static final String SEEK_MESSAGE_PREFIX = "found: ";
  572. private static final CRSOptions CRSOPTIONS = new CRSOptions();
  573. /**
  574. * Retitle description to title, paths to files, do comment,
  575. * staging, badInput,
  576. * do dirChanges, and print no chidren.
  577. */
  578. private static final AbstractRunSpec.XMLNames NAMES =
  579. new AbstractRunSpec.XMLNames(
  580. AbstractRunSpec.XMLNames.DEFAULT,
  581. "title",
  582. null,
  583. null,
  584. null,
  585. "files",
  586. null,
  587. null,
  588. null,
  589. false,
  590. false,
  591. true);
  592. /**
  593. * If the source version warrants, add a -bootclasspath
  594. * entry to the list of arguments to add.
  595. * This will fail and return an error String if the
  596. * required library is not found.
  597. * @param sourceVersion the String (if any) describing the -source option
  598. * (expecting one of [null, "1.3", "1.4", "1.5"].
  599. * @param compilerName the String name of the target compiler
  600. * @param toAdd the ArrayList to add -bootclasspath to
  601. * @return the String describing any errors, or null if no errors
  602. */
  603. private static String updateBootclasspathForSourceVersion(
  604. String sourceVersion,
  605. String compilerName,
  606. ArrayList toAdd) {
  607. if (null == sourceVersion) {
  608. return null;
  609. }
  610. if (3 != sourceVersion.length()) {
  611. throw new IllegalArgumentException(
  612. "bad version: " + sourceVersion);
  613. }
  614. if (null == toAdd) {
  615. throw new IllegalArgumentException("null toAdd");
  616. }
  617. int version = sourceVersion.charAt(2) - '0';
  618. switch (version) {
  619. case (3) :
  620. if (LangUtil.supportsJava("1.4")) {
  621. if (!FileUtil.canReadFile(Globals.J2SE13_RTJAR)) {
  622. return "no 1.3 libraries to handle -source 1.3";
  623. }
  624. toAdd.add("-bootclasspath");
  625. toAdd.add(Globals.J2SE13_RTJAR.getAbsolutePath());
  626. }
  627. break;
  628. case (4) :
  629. if (!LangUtil.supportsJava("1.4")) {
  630. if (ReflectionFactory
  631. .ECLIPSE
  632. .equals(compilerName)) {
  633. return "run eclipse under 1.4 to handle -source 1.4";
  634. }
  635. if (!FileUtil.canReadFile(Globals.J2SE14_RTJAR)) {
  636. return "no 1.4 libraries to handle -source 1.4";
  637. }
  638. toAdd.add("-bootclasspath");
  639. toAdd.add(Globals.J2SE14_RTJAR.getAbsolutePath());
  640. }
  641. break;
  642. case (5) :
  643. return "1.5 not supported in CompilerRun";
  644. case (0) :
  645. // ignore - no version specified
  646. break;
  647. default :
  648. throw new Error("unexpected version: " + version);
  649. }
  650. return null;
  651. }
  652. static CRSOptions testAccessToCRSOptions() {
  653. return CRSOPTIONS;
  654. }
  655. static Options testAccessToOptions() {
  656. return CRSOPTIONS.getOptions();
  657. }
  658. private static String[] copy(String[] input) {
  659. if (null == input) {
  660. return null;
  661. }
  662. String[] result = new String[input.length];
  663. System.arraycopy(input, 0, result, 0, input.length);
  664. return result;
  665. }
  666. protected String compiler;
  667. // use same command - see also IncCompiler.Spec.fresh
  668. protected boolean reuseCompiler;
  669. protected boolean permitAnyCompiler;
  670. protected boolean includeClassesDir;
  671. protected TestSetup testSetup;
  672. protected String[] argfiles = new String[0];
  673. protected String[] aspectpath = new String[0];
  674. protected String[] classpath = new String[0];
  675. protected String[] sourceroots = new String[0];
  676. protected String[] extdirs = new String[0];
  677. /** src path = {suiteParentDir}/{testBaseDirOffset}/{testSrcDirOffset}/{path} */
  678. protected String testSrcDirOffset;
  679. protected String xlintfile;
  680. protected String outjar;
  681. public Spec() {
  682. super(XMLNAME);
  683. setXMLNames(NAMES);
  684. compiler = DEFAULT_COMPILER;
  685. }
  686. protected void initClone(Spec spec)
  687. throws CloneNotSupportedException {
  688. super.initClone(spec);
  689. spec.argfiles = copy(argfiles);
  690. spec.aspectpath = copy(aspectpath);
  691. spec.classpath = copy(classpath);
  692. spec.compiler = compiler;
  693. spec.includeClassesDir = includeClassesDir;
  694. spec.reuseCompiler = reuseCompiler;
  695. spec.permitAnyCompiler = permitAnyCompiler;
  696. spec.sourceroots = copy(sourceroots);
  697. spec.extdirs = copy(extdirs);
  698. spec.outjar = outjar;
  699. spec.testSetup = null;
  700. if (null != testSetup) {
  701. spec.testSetup = (TestSetup) testSetup.clone();
  702. }
  703. spec.testSrcDirOffset = testSrcDirOffset;
  704. }
  705. public Object clone() throws CloneNotSupportedException {
  706. Spec result = new Spec();
  707. initClone(result);
  708. return result;
  709. }
  710. public void setIncludeClassesDir(boolean include) {
  711. this.includeClassesDir = include;
  712. }
  713. public void setReuseCompiler(boolean reuse) {
  714. this.reuseCompiler = reuse;
  715. }
  716. public void setPermitAnyCompiler(boolean permitAny) {
  717. this.permitAnyCompiler = permitAny;
  718. }
  719. public void setCompiler(String compilerName) {
  720. this.compiler = compilerName;
  721. }
  722. public void setTestSrcDirOffset(String s) {
  723. if (null != s) {
  724. testSrcDirOffset = s;
  725. }
  726. }
  727. /** override to set dirToken to Sandbox.CLASSES and default suffix to ".class" */
  728. public void addDirChanges(DirChanges.Spec spec) {
  729. if (null == spec) {
  730. return;
  731. }
  732. spec.setDirToken(Sandbox.CLASSES_DIR);
  733. spec.setDefaultSuffix(".class");
  734. super.addDirChanges(spec);
  735. }
  736. public String toLongString() {
  737. return getPrintName() + "(" + super.containedSummary() + ")";
  738. }
  739. public String toString() {
  740. return getPrintName() + "(" + super.containedSummary() + ")";
  741. }
  742. /** bean mapping for writers */
  743. public void setFiles(String paths) {
  744. addPaths(paths);
  745. }
  746. /**
  747. * Add to default classpath
  748. * (which includes aspectjrt.jar and testing-client.jar).
  749. * @param files comma-delimited list of classpath entries - ignored if
  750. * null or empty
  751. */
  752. public void setClasspath(String files) {
  753. if (!LangUtil.isEmpty(files)) {
  754. classpath = XMLWriter.unflattenList(files);
  755. }
  756. }
  757. /**
  758. * Set source roots, deleting any old ones
  759. * @param files comma-delimited list of directories
  760. * - ignored if null or empty
  761. */
  762. public void setSourceroots(String dirs) {
  763. if (!LangUtil.isEmpty(dirs)) {
  764. sourceroots = XMLWriter.unflattenList(dirs);
  765. }
  766. }
  767. public void setXlintfile(String path) {
  768. xlintfile = path;
  769. }
  770. public void setOutjar(String path) {
  771. outjar = path;
  772. }
  773. /**
  774. * Set extension dirs, deleting any old ones
  775. * @param files comma-delimited list of directories
  776. * - ignored if null or empty
  777. */
  778. public void setExtdirs(String dirs) {
  779. if (!LangUtil.isEmpty(dirs)) {
  780. extdirs = XMLWriter.unflattenList(dirs);
  781. }
  782. }
  783. /**
  784. * Set aspectpath, deleting any old ones
  785. * @param files comma-delimited list of aspect jars - ignored if null or
  786. * empty
  787. */
  788. public void setAspectpath(String files) {
  789. if (!LangUtil.isEmpty(files)) {
  790. aspectpath = XMLWriter.unflattenList(files);
  791. }
  792. }
  793. /**
  794. * Set argfiles, deleting any old ones
  795. * @param files comma-delimited list of argfiles - ignored if null or empty
  796. */
  797. public void setArgfiles(String files) {
  798. if (!LangUtil.isEmpty(files)) {
  799. argfiles = XMLWriter.unflattenList(files);
  800. }
  801. }
  802. /** @return String[] copy of argfiles array */
  803. public String[] getArgfilesArray() {
  804. String[] argfiles = this.argfiles;
  805. if (LangUtil.isEmpty(argfiles)) {
  806. return new String[0];
  807. }
  808. return (String[]) LangUtil.copy(argfiles);
  809. }
  810. /**
  811. * This implementation skips if:
  812. * <ul>
  813. * <li>incremental test, but using ajc (not eclipse)</li>
  814. * <li>usejavac, but javac is not available on the classpath</li>
  815. * <li>eclipse, but -usejavac or -preprocess test</li>
  816. * <li>-source 1.4, but running under 1.2 (XXX design)</li>
  817. * <li>local/global option conflicts (-lenient/-strict)</li>
  818. * <li>semantic conflicts (e.g., -lenient/-strict)</li>
  819. * </ul>
  820. * @return false if this wants to be skipped, true otherwise
  821. */
  822. protected boolean doAdoptParentValues(
  823. RT parentRuntime,
  824. IMessageHandler handler) {
  825. if (!super.doAdoptParentValues(parentRuntime, handler)) {
  826. return false;
  827. }
  828. testSetup = setupArgs(handler);
  829. if (!testSetup.result) {
  830. skipMessage(handler, testSetup.failureReason);
  831. }
  832. return testSetup.result;
  833. }
  834. private String getShortCompilerName() {
  835. String compilerClassName = compiler;
  836. if (null != testSetup) {
  837. compilerClassName = testSetup.compilerName;
  838. }
  839. if (null != compilerClassName) {
  840. int loc = compilerClassName.lastIndexOf(".");
  841. if (-1 != loc) {
  842. compilerClassName =
  843. compilerClassName.substring(loc + 1);
  844. }
  845. }
  846. return compilerClassName;
  847. }
  848. /** @return a CompilerRun with this as spec if setup completes successfully. */
  849. public IRunIterator makeRunIterator(
  850. Sandbox sandbox,
  851. Validator validator) {
  852. CompilerRun run = new CompilerRun(this);
  853. if (run.setupAjcRun(sandbox, validator)) {
  854. // XXX need name for compilerRun
  855. return new WrappedRunIterator(this, run);
  856. }
  857. return null;
  858. }
  859. protected String getPrintName() {
  860. return "CompilerRun.Spec " + getShortCompilerName();
  861. }
  862. /**
  863. * Each non-incremental run, fold the global flags in with
  864. * the run flags, which may involve adding or removing from
  865. * either list, depending on the flag prefix:
  866. * <ul>
  867. * <li>-foo: use -foo unless forced off.<li>
  868. * <li>^foo: (force off) remove any -foo option from the run flags</li>
  869. * <li>!foo: (force on) require the -foo flag </li>
  870. * </ul>
  871. * If there is a force conflict, then the test is skipped
  872. * ("skipping" info message, TestSetup.result is false).
  873. * This means an option local to the test which was specified
  874. * without forcing may be overridden by a globally-forced option.
  875. * <p>
  876. * There are some flags which are interpreted by the test
  877. * and removed from the list of flags passed to the command
  878. * (see testFlag()):
  879. * <ul>
  880. * <li>eclipse: use the new eclipse compiler (can force)</li>
  881. * <li>ajc: use the old ajc compiler (can force)</li>
  882. * <li>ignoreWarnings: ignore warnings in result evaluations (no force)</li>
  883. * </ul>
  884. * <p>
  885. * There are some flags which are inconsistent with each other.
  886. * These are treated as conflicts and the test is skipped:
  887. * <ul>
  888. * <li>lenient, strict</li>
  889. * </ul>
  890. * <p>
  891. * <p>
  892. * This also interprets any relevant System properties,
  893. * e.g., from <code>JavaRun.BOOTCLASSPATH_KEY</code>.
  894. * <p>
  895. * Finally, compiler limitations are enforced here by skipping
  896. * tests which the compiler cannot do:
  897. * <ul>
  898. * <li>eclipse does not do -lenient, -strict, -usejavac, -preprocess,
  899. * -XOcodeSize, -XSerializable, XaddSafePrefix,
  900. * -XserializableAspects,-XtargetNearSource</li>
  901. * <li>ajc does not run in incremental (staging) mode,
  902. * nor with -usejavac if javac is not on the classpath</li>
  903. * </ul>
  904. * <u>Errors</u>:This will remove an arg not prefixed by [-|!|^] after
  905. * providing an info message.
  906. * <u>TestSetup Result</u>:
  907. * If this completes successfully, then TestSetup.result is true,
  908. * and commandOptions is not null, and any test flags (ignore warning,
  909. * compiler) are reflected in the TestSetup.
  910. * If this fails, then TestSetup.result is false,
  911. * and a TestSetup.failreason is set.
  912. * This means the test is skipped.
  913. * @return TestSetup with results
  914. * (TestSetup result=false if the run should not continue)
  915. */
  916. protected TestSetup setupArgs(IMessageHandler handler) {
  917. // warning: HarnessSelectionTest checks for specific error wording
  918. final Spec spec = this;
  919. final TestSetup result = new TestSetup();
  920. result.compilerName = spec.compiler;
  921. // urk - s.b. null, but expected
  922. Values values = gatherValues(result);
  923. if ((null == values) || (null != result.failureReason)) {
  924. return checkResult(result);
  925. }
  926. // send info messages about
  927. // forced staging when -incremental
  928. // or staging but no -incremental flag
  929. Option.Family getFamily =
  930. CRSOPTIONS.crsIncrementalOption.getFamily();
  931. final boolean haveIncrementalFlag =
  932. (null != values.firstInFamily(getFamily));
  933. if (spec.isStaging()) {
  934. if (!haveIncrementalFlag) {
  935. MessageUtil.info(
  936. handler,
  937. "staging but no -incremental flag");
  938. }
  939. } else if (haveIncrementalFlag) {
  940. spec.setStaging(true);
  941. MessageUtil.info(handler, "-incremental forcing staging");
  942. }
  943. if (hasInvalidOptions(values, result)) {
  944. return checkResult(result);
  945. }
  946. // set compiler in result
  947. getFamily = CRSOPTIONS.ajccompilerOption.getFamily();
  948. Option.Value compiler = values.firstInFamily(getFamily);
  949. if (null != compiler) {
  950. result.compilerName
  951. = CRSOPTIONS.compilerClassName(compiler.option);
  952. if (null == result.compilerName) {
  953. result.failureReason =
  954. "unable to get class name for " + compiler;
  955. return checkResult(result);
  956. }
  957. }
  958. String compilerName =
  959. (null == result.compilerName
  960. ? spec.compiler
  961. : result.compilerName);
  962. // check compiler semantics
  963. if (hasCompilerSpecErrors(compilerName, values, result)) {
  964. return checkResult(result);
  965. }
  966. // add toadd and finish result
  967. ArrayList args = new ArrayList();
  968. String[] rendered = values.render();
  969. if (!LangUtil.isEmpty(rendered)) {
  970. args.addAll(Arrays.asList(rendered));
  971. }
  972. // update bootclasspath
  973. getFamily = CRSOPTIONS.crsSourceOption.getFamily();
  974. Option.Value source = values.firstInFamily(getFamily);
  975. if (null != source) {
  976. String sourceVersion = source.unflatten()[1];
  977. ArrayList toAdd = new ArrayList();
  978. /*String err =*/
  979. updateBootclasspathForSourceVersion(
  980. sourceVersion,
  981. spec.compiler,
  982. toAdd);
  983. args.addAll(toAdd);
  984. }
  985. result.commandOptions = args;
  986. result.result = true;
  987. return checkResult(result);
  988. }
  989. /**
  990. * Ensure exit invariant:
  991. * <code>result.result == (null == result.failureReason)
  992. * == (null != result.commandOptions)</code>
  993. * @param result the TestSetup to verify
  994. * @return result
  995. * @throws Error if invariant is not true
  996. */
  997. TestSetup checkResult(TestSetup result) {
  998. String err = null;
  999. if (null == result) {
  1000. err = "null result";
  1001. } else if (result.result != (null == result.failureReason)) {
  1002. err =
  1003. result.result
  1004. ? "expected no failure: " + result.failureReason
  1005. : "fail for no reason";
  1006. } else if (result.result != (null != result.commandOptions)) {
  1007. err =
  1008. result.result
  1009. ? "expected command options"
  1010. : "unexpected command options";
  1011. }
  1012. if (null != err) {
  1013. throw new Error(err);
  1014. }
  1015. return result;
  1016. }
  1017. boolean hasInvalidOptions(Values values, TestSetup result) {
  1018. // not supporting 1.0 options any more
  1019. for (Iterator iter = CRSOPTIONS.invalidOptions.iterator();
  1020. iter.hasNext();
  1021. ) {
  1022. Option option = (Option) iter.next();
  1023. if (null != values.firstOption(option)) {
  1024. result.failureReason =
  1025. "invalid option in harness: " + option;
  1026. return true;
  1027. }
  1028. }
  1029. return false;
  1030. }
  1031. boolean hasCompilerSpecErrors(
  1032. String compilerName,
  1033. Values values,
  1034. TestSetup result) {
  1035. /*
  1036. * Describe any semantic conflicts between options.
  1037. * This skips:
  1038. * - old 1.0 options, including lenient v. strict
  1039. * - old ajc options, include !incremental and usejavac w/o javac
  1040. * - invalid eclipse options (mostly ajc)
  1041. * @param compilerName the String name of the target compiler
  1042. * @return a String describing any conflicts, or null if none
  1043. */
  1044. if (!permitAnyCompiler
  1045. && (!(ReflectionFactory.ECLIPSE.equals(compilerName)
  1046. || ReflectionFactory.OLD_AJC.equals(compilerName)
  1047. || CRSOptions.AJDE_COMPILER.equals(compilerName)
  1048. || CRSOptions.AJCTASK_COMPILER.equals(compilerName)
  1049. || permitAnyCompiler
  1050. ))) {
  1051. //|| BUILDER_COMPILER.equals(compilerName))
  1052. result.failureReason =
  1053. "unrecognized compiler: " + compilerName;
  1054. return true;
  1055. }
  1056. // not supporting ajc right now
  1057. if (null
  1058. != values.firstOption(CRSOPTIONS.ajccompilerOption)) {
  1059. result.failureReason = "ajc not supported";
  1060. return true;
  1061. }
  1062. // not supporting 1.0 options any more
  1063. for (Iterator iter = CRSOPTIONS.ajc10Options.iterator();
  1064. iter.hasNext();
  1065. ) {
  1066. Option option = (Option) iter.next();
  1067. if (null != values.firstOption(option)) {
  1068. result.failureReason = "old ajc 1.0 option: " + option;
  1069. return true;
  1070. }
  1071. }
  1072. return false;
  1073. }
  1074. protected Values gatherValues(TestSetup result) {
  1075. final Spec spec = this;
  1076. // ---- local option values
  1077. final Values localValues;
  1078. final Options options = CRSOPTIONS.getOptions();
  1079. try {
  1080. String[] input = getOptionsArray();
  1081. // this handles reading options,
  1082. // flattening two-String options, etc.
  1083. localValues = options.acceptInput(input);
  1084. // all local values should be picked up
  1085. String err = Options.missedMatchError(input, localValues);
  1086. if (!LangUtil.isEmpty(err)) {
  1087. result.failureReason = err;
  1088. return null;
  1089. }
  1090. } catch (InvalidInputException e) {
  1091. result.failureReason = e.getFullMessage();
  1092. return null;
  1093. }
  1094. // ---- global option values
  1095. StringBuffer errs = new StringBuffer();
  1096. final Values globalValues =
  1097. spec.runtime.extractOptions(options, true, errs);
  1098. if (errs.length() > 0) {
  1099. result.failureReason = errs.toString();
  1100. return null;
  1101. }
  1102. final Values combined =
  1103. Values.wrapValues(
  1104. new Values[] { localValues, globalValues });
  1105. String err = combined.resolve();
  1106. if (null != err) {
  1107. result.failureReason = err;
  1108. return null;
  1109. }
  1110. return handleTestArgs(combined, result);
  1111. }
  1112. // final int len = globalValues.length() + localValues.length();
  1113. // final Option.Value[] combinedValues = new Option.Value[len];
  1114. // System.arraycopy(
  1115. // globalValues,
  1116. // 0,
  1117. // combinedValues,
  1118. // 0,
  1119. // globalValues.length());
  1120. // System.arraycopy(
  1121. // localValues,
  1122. // 0,
  1123. // combinedValues,
  1124. // globalValues.length(),
  1125. // localValues.length());
  1126. //
  1127. // result.compilerName = spec.compiler;
  1128. // if (0 < combinedValues.length) {
  1129. // // this handles option forcing, etc.
  1130. // String err = Options.resolve(combinedValues);
  1131. // if (null != err) {
  1132. // result.failureReason = err;
  1133. // return null;
  1134. // }
  1135. // if (!handleTestArgs(combinedValues, result)) {
  1136. // return null;
  1137. // }
  1138. // }
  1139. // return Values.wrapValues(combinedValues);
  1140. // }
  1141. /**
  1142. * This interprets and nullifies values for the test.
  1143. * @param values the Option.Value[] being processed
  1144. * @param result the TestSetup to modify
  1145. * @return false if error (caller should return), true otherwise
  1146. */
  1147. Values handleTestArgs(Values values, final TestSetup result) {
  1148. final Option.Family compilerFamily =
  1149. CRSOPTIONS.ajccompilerOption.getFamily();
  1150. Values.Selector selector = new Values.Selector() {
  1151. protected boolean accept(Option.Value value) {
  1152. if (null == value) {
  1153. return false;
  1154. }
  1155. Option option = value.option;
  1156. if (compilerFamily.sameFamily(option.getFamily())) {
  1157. if (value.prefix.isSet()) {
  1158. String compilerClass
  1159. = CRSOPTIONS.compilerClassName(option);
  1160. if (null == compilerClass) {
  1161. result.failureReason =
  1162. "unrecognized compiler: " + value;
  1163. throw Values.Selector.STOP;
  1164. }
  1165. if (!CRSOPTIONS.compilerIsLoadable(option)) {
  1166. result.failureReason =
  1167. "unable to load compiler: " + option;
  1168. throw Values.Selector.STOP;
  1169. }
  1170. result.compilerName = compilerClass;
  1171. }
  1172. return true;
  1173. } else if (
  1174. CRSOPTIONS.crsIgnoreWarnings.sameOptionIdentifier(
  1175. option)) {
  1176. result.ignoreWarnings = value.prefix.isSet();
  1177. result.ignoreWarningsSet = true;
  1178. return true;
  1179. }
  1180. return false;
  1181. }
  1182. };
  1183. return values.nullify(selector);
  1184. }
  1185. // /**
  1186. // * This interprets and nullifies values for the test.
  1187. // * @param values the Option.Value[] being processed
  1188. // * @param result the TestSetup to modify
  1189. // * @return false if error (caller should return), true otherwise
  1190. // */
  1191. // boolean handleTestArgs(Option.Value[] values, TestSetup result) {
  1192. // if (!LangUtil.isEmpty(values)) {
  1193. // for (int i = 0; i < values.length; i++) {
  1194. // Option.Value value = values[i];
  1195. // if (null == value) {
  1196. // continue;
  1197. // }
  1198. // Option option = value.option;
  1199. // if (option.sameOptionFamily(ECLIPSE_OPTION)) {
  1200. // if (!value.prefix.isSet()) {
  1201. // values[i] = null;
  1202. // continue;
  1203. // }
  1204. // String compilerClass =
  1205. // (String) COMPILER_OPTION_TO_CLASSNAME.get(
  1206. // option);
  1207. // if (null == compilerClass) {
  1208. // result.failureReason =
  1209. // "unrecognized compiler: " + value;
  1210. // return false;
  1211. // }
  1212. // result.compilerName = compilerClass;
  1213. // values[i] = null;
  1214. // } else if (
  1215. // option.sameOptionFamily(crsIgnoreWarnings)) {
  1216. // result.ignoreWarnings = value.prefix.isSet();
  1217. // result.ignoreWarningsSet = true;
  1218. // values[i] = null;
  1219. // }
  1220. // }
  1221. // }
  1222. // return true;
  1223. // }
  1224. // XXX need keys, cache...
  1225. /** @return index of global in argList, ignoring first char */
  1226. protected int indexOf(String global, ArrayList argList) {
  1227. int max = argList.size();
  1228. for (int i = 0; i < max; i++) {
  1229. if (global
  1230. .equals(((String) argList.get(i)).substring(1))) {
  1231. return i;
  1232. }
  1233. }
  1234. return -1;
  1235. }
  1236. /**
  1237. * Write this out as a compile element as defined in
  1238. * AjcSpecXmlReader.DOCTYPE.
  1239. * @see AjcSpecXmlReader#DOCTYPE
  1240. * @see IXmlWritable#writeXml(XMLWriter)
  1241. */
  1242. public void writeXml(XMLWriter out) {
  1243. out.startElement(xmlElementName, false);
  1244. if (!LangUtil.isEmpty(testSrcDirOffset)) {
  1245. out.printAttribute("dir", testSrcDirOffset);
  1246. }
  1247. super.writeAttributes(out);
  1248. if (!DEFAULT_COMPILER.equals(compiler)) {
  1249. out.printAttribute("compiler", compiler);
  1250. }
  1251. if (reuseCompiler) {
  1252. out.printAttribute("reuseCompiler", "true");
  1253. }
  1254. // test-only feature
  1255. // if (permitAnyCompiler) {
  1256. // out.printAttribute("permitAnyCompiler", "true");
  1257. // }
  1258. if (includeClassesDir) {
  1259. out.printAttribute("includeClassesDir", "true");
  1260. }
  1261. if (!LangUtil.isEmpty(argfiles)) {
  1262. out.printAttribute(
  1263. "argfiles",
  1264. XMLWriter.flattenFiles(argfiles));
  1265. }
  1266. if (!LangUtil.isEmpty(aspectpath)) {
  1267. out.printAttribute(
  1268. "aspectpath",
  1269. XMLWriter.flattenFiles(aspectpath));
  1270. }
  1271. if (!LangUtil.isEmpty(sourceroots)) {
  1272. out.printAttribute(
  1273. "sourceroots",
  1274. XMLWriter.flattenFiles(sourceroots));
  1275. }
  1276. if (!LangUtil.isEmpty(extdirs)) {
  1277. out.printAttribute(
  1278. "extdirs",
  1279. XMLWriter.flattenFiles(extdirs));
  1280. }
  1281. out.endAttributes();
  1282. if (!LangUtil.isEmpty(dirChanges)) {
  1283. DirChanges.Spec.writeXml(out, dirChanges);
  1284. }
  1285. SoftMessage.writeXml(out, getMessages());
  1286. out.endElement(xmlElementName);
  1287. }
  1288. /**
  1289. * Encapsulate the directives that can be set using
  1290. * global arguments supplied in {@link Spec.getOptions()}.
  1291. * This supports changing the compiler and ignoring warnings.
  1292. */
  1293. class TestSetup {
  1294. /** null unless overriding the compiler to be used */
  1295. String compilerName;
  1296. /**
  1297. * true if we should tell AjcMessageHandler whether
  1298. * to ignore warnings in its result evaluation
  1299. */
  1300. boolean ignoreWarningsSet;
  1301. /** if telling AjcMessageHandler, what we tell it */
  1302. boolean ignoreWarnings;
  1303. /** false if setup failed */
  1304. boolean result;
  1305. /** if setup failed, this has the reason why */
  1306. String failureReason;
  1307. /** beyond running test, also seek text in sources */
  1308. String seek;
  1309. /** if setup completed, this has the combined global/local options */
  1310. ArrayList commandOptions;
  1311. public Object clone() {
  1312. TestSetup testSetup = new TestSetup();
  1313. testSetup.compilerName = compilerName;
  1314. testSetup.ignoreWarnings = ignoreWarnings;
  1315. testSetup.ignoreWarningsSet = ignoreWarningsSet;
  1316. testSetup.result = result;
  1317. testSetup.failureReason = failureReason;
  1318. testSetup.seek = seek;
  1319. if (null != commandOptions) {
  1320. testSetup.commandOptions = new ArrayList();
  1321. testSetup.commandOptions.addAll(commandOptions);
  1322. }
  1323. return testSetup;
  1324. }
  1325. public String toString() {
  1326. return "TestSetup("
  1327. + (null == compilerName ? "" : compilerName + " ")
  1328. + (!ignoreWarningsSet
  1329. ? ""
  1330. : (ignoreWarnings ? "" : "do not ")
  1331. + "ignore warnings ")
  1332. + (result ? "" : "setup failed")
  1333. + ")";
  1334. }
  1335. }
  1336. /**
  1337. * Options-related stuff in the spec.
  1338. */
  1339. static class CRSOptions {
  1340. // static final String BUILDER_COMPILER =
  1341. // "org.aspectj.ajdt.internal.core.builder.Builder.Command";
  1342. static final String AJDE_COMPILER =
  1343. CompileCommand.class.getName();
  1344. static final String AJCTASK_COMPILER =
  1345. AjcTaskCompileCommand.class.getName();
  1346. private final Map compilerOptionToLoadable = new TreeMap();
  1347. /*
  1348. * The options field in a compiler test permits some arbitrary
  1349. * command-line options to be set. It does not permit things
  1350. * like classpath, aspectpath, files, etc. which are set
  1351. * using other fields in the test specification, so the options
  1352. * permitted are a subset of those permitted on the command-line.
  1353. *
  1354. * Global options specified on the harness command-line are
  1355. * adopted for the compiler command-line if they are permitted
  1356. * in the options field. That means we have to detect each
  1357. * permitted option, rather than just letting all through
  1358. * for the compiler.
  1359. *
  1360. * Conversely, some options are targeted not at the compiler,
  1361. * but at the test itself (e.g., to ignore warnings, or to
  1362. * select a compiler.
  1363. *
  1364. * The harness can run many compilers, and they differ in
  1365. * which options are permitted. You can specify a compiler
  1366. * as an option (e.g., -eclipse). So the set of constraints
  1367. * on the list of permitted options can differ from test to test.
  1368. *
  1369. * The following code sets up the lists of permitted options
  1370. * and breaks out subsets for different compiler-variant checks.
  1371. * Most options are created but not named, but some options
  1372. * are named to detect corresponding values for further
  1373. * processing. e.g., the compiler options are saved so
  1374. * we can do per-compiler option verification.
  1375. *
  1376. */
  1377. private final Options crsOptions;
  1378. private final Family compilerFamily;
  1379. private final Option crsIncrementalOption;
  1380. private final Option crsSourceOption;
  1381. // these are options handled/absorbed by CompilerRun
  1382. private final Option crsIgnoreWarnings;
  1383. private final Option eclipseOption;
  1384. private final Option buildercompilerOption;
  1385. private final Option ajdecompilerOption;
  1386. private final Option javacOption;
  1387. private final Option ajctaskcompilerOption;
  1388. private final Option ajccompilerOption;
  1389. private final Map compilerOptionToClassname;
  1390. private final Set compilerOptions;
  1391. // compiler verification - permit but flag ajc 1.0 options
  1392. private final List ajc10Options;
  1393. private final List invalidOptions;
  1394. private CRSOptions() {
  1395. crsOptions = new Options(true);
  1396. Option.Factory factory = new Option.Factory("CompilerRun");
  1397. // compiler options go in map
  1398. eclipseOption =
  1399. factory.create(
  1400. "eclipse",
  1401. "compiler",
  1402. Option.FORCE_PREFIXES,
  1403. false);
  1404. compilerFamily = eclipseOption.getFamily();
  1405. buildercompilerOption =
  1406. factory.create(
  1407. "builderCompiler",
  1408. "compiler",
  1409. Option.FORCE_PREFIXES,
  1410. false);
  1411. ajctaskcompilerOption =
  1412. factory.create(
  1413. "ajctaskCompiler",
  1414. "compiler",
  1415. Option.FORCE_PREFIXES,
  1416. false);
  1417. ajdecompilerOption =
  1418. factory.create(
  1419. "ajdeCompiler",
  1420. "compiler",
  1421. Option.FORCE_PREFIXES,
  1422. false);
  1423. ajccompilerOption =
  1424. factory.create(
  1425. "ajc",
  1426. "compiler",
  1427. Option.FORCE_PREFIXES,
  1428. false);
  1429. javacOption =
  1430. factory.create(
  1431. "javac",
  1432. "compiler",
  1433. Option.FORCE_PREFIXES,
  1434. false);
  1435. Map map = new TreeMap();
  1436. map.put(eclipseOption, ReflectionFactory.ECLIPSE);
  1437. //map.put(BUILDERCOMPILER_OPTION, BUILDER_COMPILER);
  1438. map.put(
  1439. ajctaskcompilerOption,
  1440. AJCTASK_COMPILER);
  1441. map.put(ajdecompilerOption, AJDE_COMPILER);
  1442. map.put(ajccompilerOption, ReflectionFactory.OLD_AJC);
  1443. //map.put(JAVAC_OPTION, "XXX javac option not supported");
  1444. compilerOptionToClassname =
  1445. Collections.unmodifiableMap(map);
  1446. compilerOptions =
  1447. Collections.unmodifiableSet(
  1448. compilerOptionToClassname.keySet());
  1449. // options not permitted in the harness
  1450. List list = new ArrayList();
  1451. list.add(factory.create("workingdir"));
  1452. list.add(factory.create("argfile"));
  1453. list.add(factory.create("sourceroots"));
  1454. list.add(factory.create("outjar"));
  1455. invalidOptions = Collections.unmodifiableList(list);
  1456. // other options added directly
  1457. crsIncrementalOption = factory.create("incremental");
  1458. crsIgnoreWarnings = factory.create("ignoreWarnings");
  1459. crsSourceOption =
  1460. factory
  1461. .create(
  1462. "source",
  1463. "source",
  1464. Option.FORCE_PREFIXES,
  1465. false,
  1466. new String[][] { new String[] { "1.3", "1.4", "1.5" }
  1467. });
  1468. // ajc 1.0 options
  1469. // workingdir above in invalid options
  1470. list = new ArrayList();
  1471. list.add(factory.create("usejavac"));
  1472. list.add(factory.create("preprocess"));
  1473. list.add(factory.create("nocomment"));
  1474. list.add(factory.create("porting"));
  1475. list.add(factory.create("XOcodeSize"));
  1476. list.add(factory.create("XTargetNearSource"));
  1477. list.add(factory.create("XaddSafePrefix"));
  1478. list.add(
  1479. factory.create(
  1480. "lenient",
  1481. "lenient",
  1482. Option.FORCE_PREFIXES,
  1483. false));
  1484. list.add(
  1485. factory.create(
  1486. "strict",
  1487. "lenient",
  1488. Option.FORCE_PREFIXES,
  1489. false));
  1490. ajc10Options = Collections.unmodifiableList(list);
  1491. // -warn:.. and -g/-g:.. are not exclusive
  1492. if (!(factory.setupFamily("debug", true)
  1493. && factory.setupFamily("warning", true))) {
  1494. System.err.println("CompilerRun debug/warning fail!");
  1495. }
  1496. Option[] options =
  1497. new Option[] {
  1498. crsIncrementalOption,
  1499. crsIgnoreWarnings,
  1500. crsSourceOption,
  1501. factory.create(
  1502. "Xlint",
  1503. "XLint",
  1504. Option.FORCE_PREFIXES,
  1505. true),
  1506. factory.create("verbose"),
  1507. factory.create("emacssym"),
  1508. factory.create("referenceInfo"),
  1509. factory.create("nowarn"),
  1510. factory.create("deprecation"),
  1511. factory.create("noImportError"),
  1512. factory.create("proceedOnError"),
  1513. factory.create("preserveAllLocals"),
  1514. factory.create(
  1515. "warn",
  1516. "warning",
  1517. Option.STANDARD_PREFIXES,
  1518. true),
  1519. factory.create(
  1520. "g",
  1521. "debug",
  1522. Option.STANDARD_PREFIXES,
  1523. false),
  1524. factory.create(
  1525. "g:",
  1526. "debug",
  1527. Option.STANDARD_PREFIXES,
  1528. true),
  1529. factory.create(
  1530. "1.3",
  1531. "compliance",
  1532. Option.FORCE_PREFIXES,
  1533. false),
  1534. factory.create(
  1535. "1.4",
  1536. "compliance",
  1537. Option.FORCE_PREFIXES,
  1538. false),
  1539. factory.create(
  1540. "1.5",
  1541. "compliance",
  1542. Option.FORCE_PREFIXES,
  1543. false),
  1544. factory
  1545. .create(
  1546. "target",
  1547. "target",
  1548. Option.FORCE_PREFIXES,
  1549. false,
  1550. new String[][] { new String[] {
  1551. "1.1",
  1552. "1.2",
  1553. "1.3",
  1554. "1.4",
  1555. "1.5" }}),
  1556. factory.create("XnoInline"),
  1557. factory.create("XnoWeave"),
  1558. factory.create("Xreweavable"),
  1559. factory.create("XnotReweavable"),
  1560. factory.create("XserializableAspects")
  1561. };
  1562. // among options not permitted: extdirs...
  1563. for (int i = 0; i < options.length; i++) {
  1564. crsOptions.addOption(options[i]);
  1565. }
  1566. for (Iterator iter = compilerOptions.iterator();
  1567. iter.hasNext();
  1568. ) {
  1569. crsOptions.addOption((Option) iter.next());
  1570. }
  1571. // these are recognized but records with them are skipped
  1572. for (Iterator iter = ajc10Options.iterator();
  1573. iter.hasNext();
  1574. ) {
  1575. crsOptions.addOption((Option) iter.next());
  1576. }
  1577. crsOptions.freeze();
  1578. }
  1579. Options getOptions() {
  1580. return crsOptions;
  1581. }
  1582. /**
  1583. * @return unmodifiable Set of options sharing the
  1584. * family "compiler".
  1585. */
  1586. Set compilerOptions() {
  1587. return compilerOptions;
  1588. }
  1589. /**
  1590. * @param option the compiler Option to get name for
  1591. * @return null if option is null or not a compiler option,
  1592. * or the fully-qualified classname of the ICommand
  1593. * implementing the compiler.
  1594. */
  1595. String compilerClassName(Option option) {
  1596. if ((null == option)
  1597. || (!compilerFamily.sameFamily(option.getFamily()))) {
  1598. return null;
  1599. }
  1600. return (String) compilerOptionToClassname.get(option);
  1601. }
  1602. /**
  1603. * Check that the compiler class associated with a compiler
  1604. * option can be loaded. This check only happens once;
  1605. * the result is cached (by compilerOption key) for later calls.
  1606. * @param compilerOption the Option (family compiler) to check
  1607. * @return true if compiler class for this option can be loaded
  1608. */
  1609. boolean compilerIsLoadable(Option compilerOption) {
  1610. LangUtil.throwIaxIfNull(compilerOption, "compilerName");
  1611. synchronized (compilerOptionToLoadable) {
  1612. Boolean result =
  1613. (Boolean) compilerOptionToLoadable.get(
  1614. compilerOption);
  1615. if (null == result) {
  1616. MessageHandler sink = new MessageHandler();
  1617. String compilerClassname =
  1618. (String) compilerOptionToClassname.get(
  1619. compilerOption);
  1620. if (null == compilerClassname) {
  1621. result = Boolean.FALSE;
  1622. } else {
  1623. ICommand c =
  1624. ReflectionFactory.makeCommand(
  1625. compilerClassname,
  1626. sink);
  1627. if ((null == c)
  1628. || sink.hasAnyMessage(
  1629. IMessage.ERROR,
  1630. true)) {
  1631. result = Boolean.FALSE;
  1632. } else {
  1633. result = Boolean.TRUE;
  1634. }
  1635. }
  1636. compilerOptionToLoadable.put(
  1637. compilerOption,
  1638. result);
  1639. }
  1640. return result.booleanValue();
  1641. }
  1642. }
  1643. } // CompilerRun.Spec.CRSOptions
  1644. } // CompilerRun.Spec
  1645. } // CompilerRun