Skip to content

Commit

Permalink
Treat toolchain requirements as inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Muskalla committed Nov 18, 2020
1 parent 331c1ee commit f056aa3
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@
import org.gradle.api.file.Directory;
import org.gradle.api.file.RegularFile;
import org.gradle.api.internal.file.FileFactory;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
import org.gradle.internal.jvm.inspection.JvmInstallationMetadata;
import org.gradle.internal.os.OperatingSystem;
import org.gradle.jvm.toolchain.JavaCompiler;
import org.gradle.jvm.toolchain.JavaInstallationMetadata;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.gradle.jvm.toolchain.JavaLauncher;
import org.gradle.jvm.toolchain.JavaToolchainSpec;
import org.gradle.jvm.toolchain.JavadocTool;
import org.gradle.util.VersionNumber;

import javax.inject.Inject;
import java.nio.file.Path;

public class JavaToolchain implements Describable, JavaInstallationMetadata {
Expand All @@ -42,15 +42,21 @@ public class JavaToolchain implements Describable, JavaInstallationMetadata {
private final VersionNumber implementationVersion;
private final JavaLanguageVersion javaVersion;
private final JvmInstallationMetadata metadata;
private final JavaToolchainInput input;

@Inject
public JavaToolchain(JvmInstallationMetadata metadata, JavaCompilerFactory compilerFactory, ToolchainToolFactory toolFactory, FileFactory fileFactory) {
public JavaToolchain(JvmInstallationMetadata metadata, JavaCompilerFactory compilerFactory, ToolchainToolFactory toolFactory, FileFactory fileFactory, JavaToolchainSpec spec) {
this.javaHome = fileFactory.dir(computeEnclosingJavaHome(metadata.getJavaHome()).toFile());
this.javaVersion = JavaLanguageVersion.of(metadata.getLanguageVersion().getMajorVersion());
this.compilerFactory = compilerFactory;
this.toolFactory = toolFactory;
this.implementationVersion = VersionNumber.parse(metadata.getImplementationVersion());
this.metadata = metadata;
this.input = new JavaToolchainInput(spec);
}

@Nested
protected JavaToolchainInput getTaskInputs() {
return input;
}

@Internal
Expand All @@ -68,7 +74,7 @@ public JavadocTool getJavadocTool() {
return toolFactory.create(JavadocTool.class, this);
}

@Input
@Internal
public JavaLanguageVersion getLanguageVersion() {
return javaVersion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.gradle.api.internal.file.FileFactory;
import org.gradle.internal.jvm.inspection.JvmInstallationMetadata;
import org.gradle.internal.jvm.inspection.JvmMetadataDetector;
import org.gradle.jvm.toolchain.JavaToolchainSpec;

import javax.inject.Inject;
import java.io.File;
Expand All @@ -39,10 +40,10 @@ public JavaToolchainFactory(JvmMetadataDetector detector, JavaCompilerFactory co
this.fileFactory = fileFactory;
}

public Optional<JavaToolchain> newInstance(File javaHome) {
public Optional<JavaToolchain> newInstance(File javaHome, JavaToolchainSpec spec) {
final JvmInstallationMetadata metadata = detector.getMetadata(javaHome);
if(metadata.isValidInstallation()) {
final JavaToolchain toolchain = new JavaToolchain(metadata, compilerFactory, toolFactory, fileFactory);
final JavaToolchain toolchain = new JavaToolchain(metadata, compilerFactory, toolFactory, fileFactory, spec);
return Optional.of(toolchain);
}
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.gradle.jvm.toolchain.internal;

import org.gradle.api.tasks.Input;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.gradle.jvm.toolchain.JavaToolchainSpec;

public class JavaToolchainInput {

private final JavaToolchainSpec spec;

public JavaToolchainInput(JavaToolchainSpec spec) {
this.spec = spec;
}

@Input
JavaLanguageVersion getLanguageVersion() {
return spec.getLanguageVersion().get();
}

@Input
String getVendor() {
return spec.getVendor().get().toString();
}

@Input
String getImplementation() {
return spec.getImplementation().get().toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Provider<JavaToolchain> findMatchingToolchain(JavaToolchainSpec filter) {
private JavaToolchain query(JavaToolchainSpec filter) {
return registry.listInstallations().stream()
.map(InstallationLocation::getLocation)
.map(this::asToolchain)
.map(javaHome -> asToolchain(javaHome, filter))
.filter(Optional::isPresent)
.map(Optional::get)
.filter(new ToolchainMatcher(filter))
Expand All @@ -76,7 +76,7 @@ private JavaToolchain query(JavaToolchainSpec filter) {
private JavaToolchain downloadToolchain(JavaToolchainSpec spec) {
final Optional<File> installation = installService.tryInstall(spec);
final Optional<JavaToolchain> toolchain = installation
.map(this::asToolchain)
.map(home -> asToolchain(home, spec))
.orElseThrow(noToolchainAvailable(spec));
return toolchain.orElseThrow(provisionedToolchainIsInvalid(installation::get));
}
Expand All @@ -89,7 +89,7 @@ private Supplier<GradleException> provisionedToolchainIsInvalid(Supplier<File> j
return () -> new GradleException("Provisioned toolchain '" + javaHome.get() + "' could not be probed.");
}

private Optional<JavaToolchain> asToolchain(File javaHome) {
return toolchainFactory.newInstance(javaHome);
private Optional<JavaToolchain> asToolchain(File javaHome, JavaToolchainSpec spec) {
return toolchainFactory.newInstance(javaHome, spec);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.gradle.jvm.toolchain.internal


import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.jvm.toolchain.JvmImplementation
import org.gradle.jvm.toolchain.JvmVendorSpec
import org.gradle.util.TestUtil
import spock.lang.Specification

class JavaToolchainInputTest extends Specification {

def "optional properties are using defaults"() {
given:
def baseSpec = new DefaultToolchainSpec(TestUtil.objectFactory())
def diffSpec = new DefaultToolchainSpec(TestUtil.objectFactory())
baseSpec.languageVersion.set(JavaLanguageVersion.of(11))
diffSpec.languageVersion.set(JavaLanguageVersion.of(11))
def base = new JavaToolchainInput(baseSpec)
def diff = new JavaToolchainInput(diffSpec)

expect:
base.languageVersion == diff.languageVersion
base.vendor == diff.vendor
base.implementation == diff.implementation
}

def "language version is stable"() {
given:
def base = new JavaToolchainInput(newSpec(11))
def diff = new JavaToolchainInput(newSpec(11))

expect:
base.languageVersion == diff.languageVersion
base.vendor == diff.vendor
base.implementation == diff.implementation
}

def "change in language version is a different input"() {
given:
def base = new JavaToolchainInput(newSpec(11))
def diff = new JavaToolchainInput(newSpec(14))

expect:
base.languageVersion != diff.languageVersion
base.vendor == diff.vendor
base.implementation == diff.implementation
}

def "change in vendor is a different input"() {
given:
def base = new JavaToolchainInput(newSpec(11, "adoptopenjdk"))
def diff = new JavaToolchainInput(newSpec(11, "amazon"))

expect:
base.languageVersion == diff.languageVersion
base.vendor != diff.vendor
base.implementation == diff.implementation
}

def "change in implementation is a different input"() {
given:
def base = new JavaToolchainInput(newSpec(11, "adoptopenjdk", JvmImplementation.VENDOR_SPECIFIC))
def diff = new JavaToolchainInput(newSpec(11, "adoptopenjdk", JvmImplementation.J9))

expect:
base.languageVersion == diff.languageVersion
base.vendor == diff.vendor
base.implementation != diff.implementation
}

def newSpec(int languageVersion, String vendor = "ibm", JvmImplementation impl = JvmImplementation.VENDOR_SPECIFIC) {
def spec = new DefaultToolchainSpec(TestUtil.objectFactory())
spec.languageVersion.set(JavaLanguageVersion.of(languageVersion))
spec.vendor.set(JvmVendorSpec.matching(vendor))
spec.implementation.set(impl)
spec
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ class JavaToolchainQueryServiceTest extends Specification {
def compilerFactory = Mock(JavaCompilerFactory)
def toolFactory = Mock(ToolchainToolFactory)
def toolchainFactory = new JavaToolchainFactory(Mock(JvmMetadataDetector), compilerFactory, toolFactory, TestFiles.fileFactory()) {
Optional<JavaToolchain> newInstance(File javaHome) {
Optional<JavaToolchain> newInstance(File javaHome, JavaToolchainSpec spec) {
def vendor = vendors[Integer.valueOf(javaHome.name.substring(2))]
def metadata = newMetadata(new File("/path/8"), vendor)
return Optional.of(new JavaToolchain(metadata, compilerFactory, toolFactory, TestFiles.fileFactory()))
return Optional.of(new JavaToolchain(metadata, compilerFactory, toolFactory, TestFiles.fileFactory(), spec))
}
}
def queryService = new JavaToolchainQueryService(registry, toolchainFactory, Mock(JavaToolchainProvisioningService), createProviderFactory())
Expand Down Expand Up @@ -229,10 +229,10 @@ class JavaToolchainQueryServiceTest extends Specification {
def compilerFactory = Mock(JavaCompilerFactory)
def toolFactory = Mock(ToolchainToolFactory)
def toolchainFactory = new JavaToolchainFactory(Mock(JvmMetadataDetector), compilerFactory, toolFactory, TestFiles.fileFactory()) {
Optional<JavaToolchain> newInstance(File javaHome) {
Optional<JavaToolchain> newInstance(File javaHome, JavaToolchainSpec spec) {
def metadata = newMetadata(javaHome)
if(metadata.isValidInstallation()) {
def toolchain = new JavaToolchain(metadata, compilerFactory, toolFactory, TestFiles.fileFactory())
def toolchain = new JavaToolchain(metadata, compilerFactory, toolFactory, TestFiles.fileFactory(), spec)
return Optional.of(toolchain)
}
return Optional.empty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import org.gradle.internal.jvm.Jvm
import org.gradle.internal.jvm.inspection.JvmInstallationMetadata
import org.gradle.internal.work.WorkerLeaseRegistry
import org.gradle.jvm.toolchain.JavaLauncher
import org.gradle.jvm.toolchain.JavaToolchainSpec
import org.gradle.jvm.toolchain.internal.DefaultToolchainJavaLauncher
import org.gradle.jvm.toolchain.internal.JavaCompilerFactory
import org.gradle.jvm.toolchain.internal.JavaToolchain
Expand Down Expand Up @@ -288,7 +289,7 @@ class TestTest extends AbstractConventionTaskTest {
metadata.getLanguageVersion() >> Jvm.current().javaVersion
metadata.getCapabilities() >> Collections.emptySet()
metadata.getJavaHome() >> Jvm.current().javaHome.toPath()
def toolchain = new JavaToolchain(metadata, Mock(JavaCompilerFactory), Mock(ToolchainToolFactory), TestFiles.fileFactory())
def toolchain = new JavaToolchain(metadata, Mock(JavaCompilerFactory), Mock(ToolchainToolFactory), TestFiles.fileFactory(), Mock(JavaToolchainSpec))
def launcher = new DefaultToolchainJavaLauncher(toolchain)
when:
Expand Down

0 comments on commit f056aa3

Please sign in to comment.