Skip to content

Commit 82d10b4

Browse files
authored
Run forbidden api checks with runtimeJavaVersion (#32947)
Run forbidden APIs checks with runtime hava version
1 parent 0a4b55c commit 82d10b4

File tree

30 files changed

+241
-172
lines changed

30 files changed

+241
-172
lines changed

buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy

Lines changed: 41 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,12 @@
1818
*/
1919
package org.elasticsearch.gradle.precommit
2020

21-
import de.thetaphi.forbiddenapis.gradle.CheckForbiddenApis
22-
import de.thetaphi.forbiddenapis.gradle.ForbiddenApisPlugin
2321
import org.elasticsearch.gradle.ExportElasticsearchBuildResourcesTask
24-
import org.gradle.api.JavaVersion
2522
import org.gradle.api.Project
2623
import org.gradle.api.Task
27-
import org.gradle.api.file.FileCollection
24+
import org.gradle.api.artifacts.Configuration
2825
import org.gradle.api.plugins.JavaBasePlugin
2926
import org.gradle.api.plugins.quality.Checkstyle
30-
import org.gradle.api.tasks.JavaExec
31-
import org.gradle.api.tasks.StopExecutionException
32-
3327
/**
3428
* Validation tasks which should be run before committing. These run before tests.
3529
*/
@@ -38,8 +32,8 @@ class PrecommitTasks {
3832
/** Adds a precommit task, which depends on non-test verification tasks. */
3933
public static Task create(Project project, boolean includeDependencyLicenses) {
4034
List<Task> precommitTasks = [
41-
configureForbiddenApis(project),
4235
configureCheckstyle(project),
36+
configureForbiddenApisCli(project),
4337
configureNamingConventions(project),
4438
project.tasks.create('forbiddenPatterns', ForbiddenPatternsTask.class),
4539
project.tasks.create('licenseHeaders', LicenseHeadersTask.class),
@@ -48,9 +42,6 @@ class PrecommitTasks {
4842
project.tasks.create('thirdPartyAudit', ThirdPartyAuditTask.class)
4943
]
5044

51-
// Configure it but don't add it as a dependency yet
52-
configureForbiddenApisCli(project)
53-
5445
// tasks with just tests don't need dependency licenses, so this flag makes adding
5546
// the task optional
5647
if (includeDependencyLicenses) {
@@ -84,77 +75,60 @@ class PrecommitTasks {
8475
return project.tasks.create(precommitOptions)
8576
}
8677

87-
private static Task configureForbiddenApis(Project project) {
88-
project.pluginManager.apply(ForbiddenApisPlugin.class)
89-
project.forbiddenApis {
90-
failOnUnsupportedJava = false
91-
bundledSignatures = ['jdk-unsafe', 'jdk-deprecated', 'jdk-non-portable', 'jdk-system-out']
92-
signaturesURLs = [getClass().getResource('/forbidden/jdk-signatures.txt'),
93-
getClass().getResource('/forbidden/es-all-signatures.txt')]
94-
suppressAnnotations = ['**.SuppressForbidden']
95-
}
96-
project.tasks.withType(CheckForbiddenApis) {
97-
// we do not use the += operator to add signatures, as conventionMappings of Gradle do not work when it's configured using withType:
98-
if (name.endsWith('Test')) {
99-
signaturesURLs = project.forbiddenApis.signaturesURLs +
100-
[ getClass().getResource('/forbidden/es-test-signatures.txt'), getClass().getResource('/forbidden/http-signatures.txt') ]
101-
} else {
102-
signaturesURLs = project.forbiddenApis.signaturesURLs +
103-
[ getClass().getResource('/forbidden/es-server-signatures.txt') ]
104-
}
105-
// forbidden apis doesn't support Java 11, so stop at 10
106-
String targetMajorVersion = (project.compilerJavaVersion.compareTo(JavaVersion.VERSION_1_10) > 0 ?
107-
JavaVersion.VERSION_1_10 :
108-
project.compilerJavaVersion).getMajorVersion()
109-
targetCompatibility = Integer.parseInt(targetMajorVersion) >= 9 ?targetMajorVersion : "1.${targetMajorVersion}"
110-
}
111-
Task forbiddenApis = project.tasks.findByName('forbiddenApis')
112-
forbiddenApis.group = "" // clear group, so this does not show up under verification tasks
113-
114-
return forbiddenApis
115-
}
116-
11778
private static Task configureForbiddenApisCli(Project project) {
118-
project.configurations.create("forbiddenApisCliJar")
79+
Configuration forbiddenApisConfiguration = project.configurations.create("forbiddenApisCliJar")
11980
project.dependencies {
120-
forbiddenApisCliJar 'de.thetaphi:forbiddenapis:2.5'
81+
forbiddenApisCliJar ('de.thetaphi:forbiddenapis:2.5')
12182
}
122-
Task forbiddenApisCli = project.tasks.create('forbiddenApisCli')
83+
Task forbiddenApisCli = project.tasks.create('forbiddenApis')
12384

12485
project.sourceSets.forEach { sourceSet ->
12586
forbiddenApisCli.dependsOn(
126-
project.tasks.create(sourceSet.getTaskName('forbiddenApisCli', null), JavaExec) {
87+
project.tasks.create(sourceSet.getTaskName('forbiddenApis', null), ForbiddenApisCliTask) {
12788
ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources')
12889
dependsOn(buildResources)
129-
classpath = project.files(
130-
project.configurations.forbiddenApisCliJar,
90+
execAction = { spec ->
91+
spec.classpath = project.files(
92+
project.configurations.forbiddenApisCliJar,
93+
sourceSet.compileClasspath,
94+
sourceSet.runtimeClasspath
95+
)
96+
spec.executable = "${project.runtimeJavaHome}/bin/java"
97+
}
98+
inputs.files(
99+
forbiddenApisConfiguration,
131100
sourceSet.compileClasspath,
132101
sourceSet.runtimeClasspath
133102
)
134-
main = 'de.thetaphi.forbiddenapis.cli.CliMain'
135-
executable = "${project.runtimeJavaHome}/bin/java"
136-
args "-b", 'jdk-unsafe-1.8'
137-
args "-b", 'jdk-deprecated-1.8'
138-
args "-b", 'jdk-non-portable'
139-
args "-b", 'jdk-system-out'
140-
args "-f", buildResources.copy("forbidden/jdk-signatures.txt")
141-
args "-f", buildResources.copy("forbidden/es-all-signatures.txt")
142-
args "--suppressannotation", '**.SuppressForbidden'
103+
104+
targetCompatibility = project.compilerJavaVersion
105+
bundledSignatures = [
106+
"jdk-unsafe", "jdk-deprecated", "jdk-non-portable", "jdk-system-out"
107+
]
108+
signaturesFiles = project.files(
109+
buildResources.copy("forbidden/jdk-signatures.txt"),
110+
buildResources.copy("forbidden/es-all-signatures.txt")
111+
)
112+
suppressAnnotations = ['**.SuppressForbidden']
143113
if (sourceSet.name == 'test') {
144-
args "-f", buildResources.copy("forbidden/es-test-signatures.txt")
145-
args "-f", buildResources.copy("forbidden/http-signatures.txt")
114+
signaturesFiles += project.files(
115+
buildResources.copy("forbidden/es-test-signatures.txt"),
116+
buildResources.copy("forbidden/http-signatures.txt")
117+
)
146118
} else {
147-
args "-f", buildResources.copy("forbidden/es-server-signatures.txt")
119+
signaturesFiles += project.files(buildResources.copy("forbidden/es-server-signatures.txt"))
148120
}
149121
dependsOn sourceSet.classesTaskName
150-
doFirst {
151-
// Forbidden APIs expects only existing dirs, and requires at least one
152-
FileCollection existingOutputs = sourceSet.output.classesDirs
153-
.filter { it.exists() }
154-
if (existingOutputs.isEmpty()) {
155-
throw new StopExecutionException("${sourceSet.name} has no outputs")
156-
}
157-
existingOutputs.forEach { args "-d", it }
122+
classesDirs = sourceSet.output.classesDirs
123+
ext.replaceSignatureFiles = { String... names ->
124+
signaturesFiles = project.files(
125+
names.collect { buildResources.copy("forbidden/${it}.txt") }
126+
)
127+
}
128+
ext.addSignatureFiles = { String... names ->
129+
signaturesFiles += project.files(
130+
names.collect { buildResources.copy("forbidden/${it}.txt") }
131+
)
158132
}
159133
}
160134
)

buildSrc/src/main/java/org/elasticsearch/gradle/ExportElasticsearchBuildResourcesTask.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.io.InputStream;
3636
import java.nio.file.Files;
3737
import java.nio.file.Path;
38+
import java.nio.file.StandardCopyOption;
3839
import java.util.Collections;
3940
import java.util.HashSet;
4041
import java.util.Set;
@@ -105,7 +106,7 @@ public void doExport() {
105106
if (is == null) {
106107
throw new GradleException("Can't export `" + resourcePath + "` from build-tools: not found");
107108
}
108-
Files.copy(is, destination);
109+
Files.copy(is, destination, StandardCopyOption.REPLACE_EXISTING);
109110
} catch (IOException e) {
110111
throw new GradleException("Can't write resource `" + resourcePath + "` to " + destination, e);
111112
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.gradle.precommit;
20+
21+
import de.thetaphi.forbiddenapis.cli.CliMain;
22+
import org.gradle.api.Action;
23+
import org.gradle.api.DefaultTask;
24+
import org.gradle.api.JavaVersion;
25+
import org.gradle.api.file.FileCollection;
26+
import org.gradle.api.tasks.Input;
27+
import org.gradle.api.tasks.InputFiles;
28+
import org.gradle.api.tasks.OutputFile;
29+
import org.gradle.api.tasks.SkipWhenEmpty;
30+
import org.gradle.api.tasks.TaskAction;
31+
import org.gradle.process.JavaExecSpec;
32+
33+
import java.io.File;
34+
import java.io.IOException;
35+
import java.nio.file.Files;
36+
import java.util.ArrayList;
37+
import java.util.Collections;
38+
import java.util.LinkedHashSet;
39+
import java.util.List;
40+
import java.util.Set;
41+
42+
public class ForbiddenApisCliTask extends DefaultTask {
43+
44+
private FileCollection signaturesFiles;
45+
private List<String> signatures = new ArrayList<>();
46+
private Set<String> bundledSignatures = new LinkedHashSet<>();
47+
private Set<String> suppressAnnotations = new LinkedHashSet<>();
48+
private JavaVersion targetCompatibility;
49+
private FileCollection classesDirs;
50+
private Action<JavaExecSpec> execAction;
51+
52+
public JavaVersion getTargetCompatibility() {
53+
return targetCompatibility;
54+
}
55+
56+
public void setTargetCompatibility(JavaVersion targetCompatibility) {
57+
this.targetCompatibility = targetCompatibility;
58+
}
59+
60+
public Action<JavaExecSpec> getExecAction() {
61+
return execAction;
62+
}
63+
64+
public void setExecAction(Action<JavaExecSpec> execAction) {
65+
this.execAction = execAction;
66+
}
67+
68+
@OutputFile
69+
public File getMarkerFile() {
70+
return new File(
71+
new File(getProject().getBuildDir(), "precommit"),
72+
getName()
73+
);
74+
}
75+
76+
@InputFiles
77+
@SkipWhenEmpty
78+
public FileCollection getClassesDirs() {
79+
return classesDirs.filter(File::exists);
80+
}
81+
82+
public void setClassesDirs(FileCollection classesDirs) {
83+
this.classesDirs = classesDirs;
84+
}
85+
86+
@InputFiles
87+
public FileCollection getSignaturesFiles() {
88+
return signaturesFiles;
89+
}
90+
91+
public void setSignaturesFiles(FileCollection signaturesFiles) {
92+
this.signaturesFiles = signaturesFiles;
93+
}
94+
95+
@Input
96+
public List<String> getSignatures() {
97+
return signatures;
98+
}
99+
100+
public void setSignatures(List<String> signatures) {
101+
this.signatures = signatures;
102+
}
103+
104+
@Input
105+
public Set<String> getBundledSignatures() {
106+
return bundledSignatures;
107+
}
108+
109+
public void setBundledSignatures(Set<String> bundledSignatures) {
110+
this.bundledSignatures = bundledSignatures;
111+
}
112+
113+
@Input
114+
public Set<String> getSuppressAnnotations() {
115+
return suppressAnnotations;
116+
}
117+
118+
public void setSuppressAnnotations(Set<String> suppressAnnotations) {
119+
this.suppressAnnotations = suppressAnnotations;
120+
}
121+
122+
@TaskAction
123+
public void runForbiddenApisAndWriteMarker() throws IOException {
124+
getProject().javaexec((JavaExecSpec spec) -> {
125+
execAction.execute(spec);
126+
spec.setMain(CliMain.class.getName());
127+
// build the command line
128+
getSignaturesFiles().forEach(file -> spec.args("-f", file.getAbsolutePath()));
129+
getSuppressAnnotations().forEach(annotation -> spec.args("--suppressannotation", annotation));
130+
getBundledSignatures().forEach(bundled -> {
131+
// there's no option for target compatibility so we have to interpret it
132+
final String prefix;
133+
if (bundled.equals("jdk-system-out") ||
134+
bundled.equals("jdk-reflection") ||
135+
bundled.equals("jdk-non-portable")) {
136+
prefix = "";
137+
} else {
138+
prefix = "-" + (
139+
getTargetCompatibility().compareTo(JavaVersion.VERSION_1_9) >= 0 ?
140+
getTargetCompatibility().getMajorVersion() :
141+
"1." + getTargetCompatibility().getMajorVersion())
142+
;
143+
}
144+
spec.args("-b", bundled + prefix);
145+
}
146+
);
147+
getClassesDirs().forEach(dir ->
148+
spec.args("-d", dir)
149+
);
150+
});
151+
Files.write(getMarkerFile().toPath(), Collections.emptyList());
152+
}
153+
154+
}

client/rest-high-level/build.gradle

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19-
20-
import org.elasticsearch.gradle.precommit.PrecommitTasks
2119
import org.elasticsearch.gradle.test.RestIntegTestTask
2220
import org.gradle.api.internal.provider.Providers
2321

@@ -75,8 +73,8 @@ dependencyLicenses {
7573
forbiddenApisMain {
7674
// core does not depend on the httpclient for compile so we add the signatures here. We don't add them for test as they are already
7775
// specified
78-
signaturesURLs += [PrecommitTasks.getResource('/forbidden/http-signatures.txt')]
79-
signaturesURLs += [file('src/main/resources/forbidden/rest-high-level-signatures.txt').toURI().toURL()]
76+
addSignatureFiles 'http-signatures'
77+
signaturesFiles += files('src/main/resources/forbidden/rest-high-level-signatures.txt')
8078
}
8179

8280
integTestCluster {

client/rest/build.gradle

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import org.elasticsearch.gradle.precommit.ForbiddenApisCliTask
2+
13
/*
24
* Licensed to Elasticsearch under one or more contributor
35
* license agreements. See the NOTICE file distributed with
@@ -16,9 +18,6 @@
1618
* specific language governing permissions and limitations
1719
* under the License.
1820
*/
19-
20-
import org.elasticsearch.gradle.precommit.PrecommitTasks
21-
2221
apply plugin: 'elasticsearch.build'
2322
apply plugin: 'nebula.maven-base-publish'
2423
apply plugin: 'nebula.maven-scm'
@@ -53,10 +52,9 @@ dependencies {
5352
testCompile "org.elasticsearch:mocksocket:${versions.mocksocket}"
5453
}
5554

56-
forbiddenApisMain {
55+
tasks.withType(ForbiddenApisCliTask) {
5756
//client does not depend on server, so only jdk and http signatures should be checked
58-
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt'),
59-
PrecommitTasks.getResource('/forbidden/http-signatures.txt')]
57+
replaceSignatureFiles ('jdk-signatures', 'http-signatures')
6058
}
6159

6260
forbiddenPatterns {
@@ -67,9 +65,6 @@ forbiddenApisTest {
6765
//we are using jdk-internal instead of jdk-non-portable to allow for com.sun.net.httpserver.* usage
6866
bundledSignatures -= 'jdk-non-portable'
6967
bundledSignatures += 'jdk-internal'
70-
//client does not depend on server, so only jdk signatures should be checked
71-
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt'),
72-
PrecommitTasks.getResource('/forbidden/http-signatures.txt')]
7368
}
7469

7570
// JarHell is part of es server, which we don't want to pull in

0 commit comments

Comments
 (0)