|
38 | 38 | import org.aspectj.util.LangUtil;
|
39 | 39 | import org.aspectj.weaver.Dump;
|
40 | 40 |
|
| 41 | +import javax.lang.model.SourceVersion; |
| 42 | + |
41 | 43 | /**
|
42 | 44 | * Programmatic and command-line interface to AspectJ compiler. The compiler is an ICommand obtained by reflection. Not thread-safe.
|
43 | 45 | * By default, messages are printed as they are emitted; info messages go to the output stream, and warnings and errors go to the
|
@@ -79,6 +81,12 @@ public class Main {
|
79 | 81 |
|
80 | 82 | private static final String MESSAGE_HOLDER_OPTION = "-messageHolder";
|
81 | 83 |
|
| 84 | + // Minimal Java runtime version necessary to run AJC |
| 85 | + // TODO: Update value, if Eclipse JDT Core raises compilation target level. |
| 86 | + private static final int MINIMAL_JRE_VERSION = 17; |
| 87 | + private static final String MINIMAL_JRE_VERSION_ERROR = |
| 88 | + "The AspectJ compiler needs at least Java runtime " + MINIMAL_JRE_VERSION; |
| 89 | + |
82 | 90 | /** @param args the String[] of command-line arguments */
|
83 | 91 | public static void main(String[] args) throws IOException {
|
84 | 92 | new Main().runMain(args, true);
|
@@ -218,14 +226,31 @@ public void setCommand(ICommand command) {
|
218 | 226 | }
|
219 | 227 |
|
220 | 228 | /**
|
221 |
| - * Run without throwing exceptions but optionally using System.exit(..). This sets up a message handler which emits messages |
222 |
| - * immediately, so report(boolean, IMessageHandler) only reports total number of errors or warnings. |
| 229 | + * Run without throwing exceptions, but optionally using {@link System#exit(int)}. This sets up a message handler |
| 230 | + * which emits messages immediately, so {@link #report(boolean, IMessageHolder)} only reports the total number of |
| 231 | + * errors or warnings. |
223 | 232 | *
|
224 |
| - * @param args the String[] command line for the compiler |
225 |
| - * @param useSystemExit if true, use System.exit(int) to complete unless one of the args is -noExit. and signal result (0 no |
226 |
| - * exceptions/error, <0 exceptions, >0 compiler errors). |
| 233 | + * @param args the compiler command line |
| 234 | + * @param useSystemExit if true, use {@link System#exit(int)} to complete unless one of the args is {@code -noExit}, |
| 235 | + * and signal result (0 = no exceptions/error, <0 = exceptions, >0 = compiler errors). |
| 236 | + * Note: While some shells like Windows <i>cmd.exe</i> can correctly print negative exit codes |
| 237 | + * via {@code echo %errorlevel%"}, UNIX shells like Bash interpret them as positive byte values |
| 238 | + * modulo 256. E.g., exit code -1 will be printed as 127 using {@code echo $?}. |
227 | 239 | */
|
228 | 240 | public void runMain(String[] args, boolean useSystemExit) {
|
| 241 | + final boolean doExit = useSystemExit && !flagInArgs("-noExit", args); |
| 242 | + |
| 243 | + // This needs to be checked, before any classes using JDT Core classes are used for the first time. Otherwise, users |
| 244 | + // will see ugly UnsupportedClassVersionError stack traces, which they might or might not interpret correctly. |
| 245 | + // Therefore, interrupt AJC usage right here, even if it means that not even a usage page can be printed. It is |
| 246 | + // better to save users from subsequent problems later. |
| 247 | + if (SourceVersion.latest().ordinal() < MINIMAL_JRE_VERSION) { |
| 248 | + System.err.println(MINIMAL_JRE_VERSION_ERROR); |
| 249 | + if (doExit) |
| 250 | + System.exit(-1); |
| 251 | + return; |
| 252 | + } |
| 253 | + |
229 | 254 | // Urk - default no check for AJDT, enabled here for Ant, command-line
|
230 | 255 | AjBuildManager.enableRuntimeVersionCheck(this);
|
231 | 256 | final boolean verbose = flagInArgs("-verbose", args);
|
@@ -267,18 +292,8 @@ public void runMain(String[] args, boolean useSystemExit) {
|
267 | 292 | Dump.reset();
|
268 | 293 | }
|
269 | 294 |
|
270 |
| - boolean skipExit = false; |
271 |
| - if (useSystemExit && !LangUtil.isEmpty(args)) { // sigh - pluck -noExit |
272 |
| - for (String arg : args) { |
273 |
| - if ("-noExit".equals(arg)) { |
274 |
| - skipExit = true; |
275 |
| - break; |
276 |
| - } |
277 |
| - } |
278 |
| - } |
279 |
| - if (useSystemExit && !skipExit) { |
280 |
| - systemExit(holder); |
281 |
| - } |
| 295 | + if (doExit) |
| 296 | + systemExit(); |
282 | 297 | }
|
283 | 298 |
|
284 | 299 | // put calls around run() call above to allowing connecting jconsole
|
@@ -453,14 +468,13 @@ public void setCompletionRunner(Runnable runner) {
|
453 | 468 | /**
|
454 | 469 | * Call System.exit(int) with values derived from the number of failures/aborts or errors in messages.
|
455 | 470 | *
|
456 |
| - * @param messages the IMessageHolder to interrogate. |
457 | 471 | */
|
458 |
| - protected void systemExit(IMessageHolder messages) { |
459 |
| - int num = lastFails; // messages.numMessages(IMessage.FAIL, true); |
| 472 | + protected void systemExit() { |
| 473 | + int num = lastFails; |
460 | 474 | if (0 < num) {
|
461 | 475 | System.exit(-num);
|
462 | 476 | }
|
463 |
| - num = lastErrors; // messages.numMessages(IMessage.ERROR, false); |
| 477 | + num = lastErrors; |
464 | 478 | if (0 < num) {
|
465 | 479 | System.exit(num);
|
466 | 480 | }
|
|
0 commit comments