Skip to content

Commit 0ba9f25

Browse files
committed
Add minimal JRE version check to Main.runMain
Use new constant Main.MINIMAL_JRE_VERSION (currently = 17) and SourceVersion.latest().ordinal() to check, if the minimal JRE version requirement for AJC is met. If not, then exit with code -1 and error message "The AspectJ compiler needs at least Java runtime 17". Relates to #269. Signed-off-by: Alexander Kriegisch <[email protected]>
1 parent 9b77839 commit 0ba9f25

File tree

1 file changed

+35
-21
lines changed
  • org.aspectj.ajdt.core/src/main/java/org/aspectj/tools/ajc

1 file changed

+35
-21
lines changed

org.aspectj.ajdt.core/src/main/java/org/aspectj/tools/ajc/Main.java

+35-21
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import org.aspectj.util.LangUtil;
3939
import org.aspectj.weaver.Dump;
4040

41+
import javax.lang.model.SourceVersion;
42+
4143
/**
4244
* Programmatic and command-line interface to AspectJ compiler. The compiler is an ICommand obtained by reflection. Not thread-safe.
4345
* 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 {
7981

8082
private static final String MESSAGE_HOLDER_OPTION = "-messageHolder";
8183

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+
8290
/** @param args the String[] of command-line arguments */
8391
public static void main(String[] args) throws IOException {
8492
new Main().runMain(args, true);
@@ -218,14 +226,31 @@ public void setCommand(ICommand command) {
218226
}
219227

220228
/**
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.
223232
*
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, &lt;0 exceptions, &gt;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, &lt;0 = exceptions, &gt;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 $?}.
227239
*/
228240
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+
229254
// Urk - default no check for AJDT, enabled here for Ant, command-line
230255
AjBuildManager.enableRuntimeVersionCheck(this);
231256
final boolean verbose = flagInArgs("-verbose", args);
@@ -267,18 +292,8 @@ public void runMain(String[] args, boolean useSystemExit) {
267292
Dump.reset();
268293
}
269294

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();
282297
}
283298

284299
// put calls around run() call above to allowing connecting jconsole
@@ -453,14 +468,13 @@ public void setCompletionRunner(Runnable runner) {
453468
/**
454469
* Call System.exit(int) with values derived from the number of failures/aborts or errors in messages.
455470
*
456-
* @param messages the IMessageHolder to interrogate.
457471
*/
458-
protected void systemExit(IMessageHolder messages) {
459-
int num = lastFails; // messages.numMessages(IMessage.FAIL, true);
472+
protected void systemExit() {
473+
int num = lastFails;
460474
if (0 < num) {
461475
System.exit(-num);
462476
}
463-
num = lastErrors; // messages.numMessages(IMessage.ERROR, false);
477+
num = lastErrors;
464478
if (0 < num) {
465479
System.exit(num);
466480
}

0 commit comments

Comments
 (0)