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

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