1414import org .gradle .api .logging .LogLevel ;
1515import org .gradle .api .logging .LoggingManager ;
1616import org .gradle .api .model .ObjectFactory ;
17+ import org .gradle .api .plugins .JavaPluginExtension ;
1718import org .gradle .api .provider .ListProperty ;
18- import org .gradle .api .provider .MapProperty ;
1919import org .gradle .api .provider .Property ;
2020import org .gradle .api .provider .Provider ;
2121import org .gradle .api .provider .ProviderFactory ;
2828import org .gradle .api .tasks .Nested ;
2929import org .gradle .api .tasks .Optional ;
3030import org .gradle .api .tasks .TaskAction ;
31+ import org .gradle .jvm .toolchain .JavaLanguageVersion ;
3132import org .gradle .jvm .toolchain .JavaLauncher ;
33+ import org .gradle .jvm .toolchain .JavaToolchainService ;
34+ import org .gradle .jvm .toolchain .JavaToolchainSpec ;
3235import org .gradle .process .ExecOperations ;
3336import org .gradle .process .ExecResult ;
3437import org .jetbrains .annotations .MustBeInvokedByOverriders ;
4245import java .util .List ;
4346import java .util .Locale ;
4447import java .util .Map ;
45- import java .util .Objects ;
4648import java .util .concurrent .Callable ;
4749
4850/// This tool execution task is a template on top of [JavaExec] to make executing [tools][Tool] much easier and more
@@ -73,6 +75,10 @@ public abstract class ToolExecBase<P extends EnhancedProblems> extends DefaultTa
7375 protected abstract @ Input @ Optional Property <String > getMainClass ();
7476
7577 protected abstract @ Nested Property <JavaLauncher > getJavaLauncher ();
78+
79+ protected abstract @ Nested Property <JavaLauncher > getToolchainLauncher ();
80+
81+ public abstract @ Input @ Optional Property <Boolean > getPreferToolchainJvm ();
7682 //endregion
7783
7884 //region Logging
@@ -92,6 +98,8 @@ public abstract class ToolExecBase<P extends EnhancedProblems> extends DefaultTa
9298
9399 protected abstract @ Inject ExecOperations getExecOperations ();
94100
101+ protected abstract @ Inject JavaToolchainService getJavaToolchains ();
102+
95103 /// Creates a new task instance using the given types and tool information.
96104 ///
97105 /// @param tool The tool to use for this task
@@ -112,6 +120,11 @@ protected ToolExecBase(Tool tool) {
112120 this .getMainClass ().set (resolved .getMainClass ());
113121 this .getJavaLauncher ().set (resolved .getJavaLauncher ());
114122
123+ this .getToolchainLauncher ().convention (getJavaToolchains ().launcherFor (spec -> spec .getLanguageVersion ().set (JavaLanguageVersion .current ())));
124+ getProject ().getPluginManager ().withPlugin ("java" , javaAppliedPlugin ->
125+ this .getToolchainLauncher ().set (getJavaToolchains ().launcherFor (getProject ().getExtensions ().getByType (JavaPluginExtension .class ).getToolchain ()))
126+ );
127+
115128 this .getStandardOutputLogLevel ().convention (LogLevel .LIFECYCLE );
116129 this .getStandardErrorLogLevel ().convention (LogLevel .ERROR );
117130 }
@@ -132,7 +145,6 @@ private <T extends FileSystemLocation> Transformer<T, T> ensureFileLocationInter
132145 @ MustBeInvokedByOverriders
133146 protected void addArguments () { }
134147
135- private transient boolean executing = false ;
136148 private transient @ Nullable List <Provider <String >> args ;
137149 private transient @ Nullable List <Provider <String >> jvmArgs ;
138150 private transient @ Nullable Map <String , String > environment ;
@@ -142,7 +154,6 @@ protected void addArguments() { }
142154 /// [#addArguments()] never being run.
143155 @ TaskAction
144156 protected ExecResult exec () {
145- this .executing = true ;
146157 this .args = new ArrayList <>();
147158 this .jvmArgs = new ArrayList <>();
148159 this .environment = new HashMap <>();
@@ -157,12 +168,24 @@ protected ExecResult exec() {
157168
158169 var stdOutLevel = this .getStandardOutputLogLevel ().get ();
159170 var stdErrLevel = this .getStandardErrorLogLevel ().get ();
171+
172+ JavaLauncher javaLauncher ;
173+ if (getPreferToolchainJvm ().getOrElse (false )) {
174+ var candidateLauncher = getJavaLauncher ().get ();
175+ var toolchainLauncher = getToolchainLauncher ().get ();
176+ javaLauncher = toolchainLauncher .getMetadata ().getLanguageVersion ().canCompileOrRun (candidateLauncher .getMetadata ().getLanguageVersion ())
177+ ? toolchainLauncher
178+ : candidateLauncher ;
179+ } else {
180+ javaLauncher = getJavaLauncher ().get ();
181+ }
182+
160183 return this .getExecOperations ().javaexec (spec -> {
161184 spec .setIgnoreExitValue (true );
162185
163186 spec .setClasspath (this .getClasspath ());
164187 spec .getMainClass ().set (this .getMainClass ());
165- spec .setExecutable (this . getJavaLauncher (). get () .getExecutablePath ().getAsFile ().getAbsolutePath ());
188+ spec .setExecutable (javaLauncher .getExecutablePath ().getAsFile ().getAbsolutePath ());
166189 spec .setArgs (args );
167190 spec .setJvmArgs (jvmArgs );
168191 spec .setEnvironment (this .environment );
@@ -173,20 +196,22 @@ protected ExecResult exec() {
173196 });
174197 }
175198
199+ @ SuppressWarnings ("DataFlowIssue" )
176200 protected final void args (Object ... args ) {
177201 try {
178202 for (var arg : args ) {
179- Objects . requireNonNull ( this .args ) .add (this .getProviders ().provider (arg ::toString ));
203+ this .args .add (this .getProviders ().provider (arg ::toString ));
180204 }
181205 } catch (NullPointerException e ) {
182206 throw new IllegalStateException ("ToolExecBase#jvmArgs can only be called inside of #addArguments()" , e );
183207 }
184208 }
185209
210+ @ SuppressWarnings ("DataFlowIssue" )
186211 protected final void args (Iterable <?> args ) {
187212 try {
188213 for (var arg : args ) {
189- Objects . requireNonNull ( this .args ) .add (this .getProviders ().provider (arg ::toString ));
214+ this .args .add (this .getProviders ().provider (arg ::toString ));
190215 }
191216 } catch (NullPointerException e ) {
192217 throw new IllegalStateException ("ToolExecBase#jvmArgs can only be called inside of #addArguments()" , e );
@@ -246,37 +271,41 @@ protected final void args(Map<?, ?> args) {
246271 }
247272 }
248273
274+ @ SuppressWarnings ("DataFlowIssue" )
249275 protected final void jvmArgs (Object ... args ) {
250276 try {
251277 for (var arg : args ) {
252- Objects . requireNonNull ( this .jvmArgs ) .add (this .getProviders ().provider (arg ::toString ));
278+ this .jvmArgs .add (this .getProviders ().provider (arg ::toString ));
253279 }
254280 } catch (NullPointerException e ) {
255281 throw new IllegalStateException ("ToolExecBase#jvmArgs can only be called inside of #addArguments()" , e );
256282 }
257283 }
258284
285+ @ SuppressWarnings ("DataFlowIssue" )
259286 protected final void jvmArgs (Iterable <?> args ) {
260287 try {
261288 for (var arg : args ) {
262- Objects . requireNonNull ( this .jvmArgs ) .add (this .getProviders ().provider (arg ::toString ));
289+ this .jvmArgs .add (this .getProviders ().provider (arg ::toString ));
263290 }
264291 } catch (NullPointerException e ) {
265292 throw new IllegalStateException ("ToolExecBase#jvmArgs can only be called inside of #addArguments()" , e );
266293 }
267294 }
268295
296+ @ SuppressWarnings ("DataFlowIssue" )
269297 protected final void environment (String key , String value ) {
270298 try {
271- Objects . requireNonNull ( this .environment ) .put (key , value );
299+ this .environment .put (key , value );
272300 } catch (NullPointerException e ) {
273301 throw new IllegalStateException ("ToolExecBase#environment can only be called inside of #addArguments()" , e );
274302 }
275303 }
276304
305+ @ SuppressWarnings ("DataFlowIssue" )
277306 protected final void systemProperty (String key , String value ) {
278307 try {
279- Objects . requireNonNull ( this .systemProperties ) .put (key , value );
308+ this .systemProperties .put (key , value );
280309 } catch (NullPointerException e ) {
281310 throw new IllegalStateException ("ToolExecBase#systemProperty can only be called inside of #addArguments()" , e );
282311 }
0 commit comments