Skip to content

Commit abb84a3

Browse files
committed
Move module version and services checks to per-subproject
fix test
1 parent 81854c5 commit abb84a3

File tree

4 files changed

+116
-70
lines changed

4 files changed

+116
-70
lines changed

build-tools-internal/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ gradlePlugin {
121121
}
122122
javaModulePath {
123123
id = 'elasticsearch.java-module'
124-
implementationClass = 'org.elasticsearch.gradle.internal.ElasticsearchJavaModulePathPlugin'
124+
implementationClass = 'org.elasticsearch.gradle.internal.ElasticsearchJavaModulePlugin'
125125
}
126126
releaseTools {
127127
id = 'elasticsearch.release-tools'
Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.elasticsearch.gradle.VersionProperties;
1212
import org.elasticsearch.gradle.util.GradleUtils;
1313
import org.gradle.api.Action;
14+
import org.gradle.api.GradleException;
1415
import org.gradle.api.Named;
1516
import org.gradle.api.Plugin;
1617
import org.gradle.api.Project;
@@ -23,30 +24,60 @@
2324
import org.gradle.api.file.FileCollection;
2425
import org.gradle.api.logging.Logger;
2526
import org.gradle.api.plugins.JavaPlugin;
27+
import org.gradle.api.tasks.InputDirectory;
2628
import org.gradle.api.tasks.Internal;
2729
import org.gradle.api.tasks.SourceSet;
30+
import org.gradle.api.tasks.TaskProvider;
2831
import org.gradle.api.tasks.compile.JavaCompile;
2932
import org.gradle.process.CommandLineArgumentProvider;
3033

3134
import java.io.File;
35+
import java.io.IOException;
36+
import java.io.UncheckedIOException;
37+
import java.lang.module.ModuleDescriptor.Provides;
38+
import java.lang.module.ModuleFinder;
39+
import java.lang.module.ModuleReference;
40+
import java.net.URI;
41+
import java.nio.file.FileSystems;
3242
import java.nio.file.Files;
43+
import java.nio.file.Path;
3344
import java.util.ArrayList;
3445
import java.util.Arrays;
46+
import java.util.Comparator;
3547
import java.util.HashSet;
3648
import java.util.List;
49+
import java.util.Map;
3750
import java.util.Set;
51+
import java.util.function.Predicate;
3852
import java.util.stream.Collectors;
3953
import java.util.stream.Stream;
4054
import java.util.stream.StreamSupport;
4155

56+
import static java.util.stream.Collectors.toSet;
57+
4258
/**
43-
* The Java Module Compile Path Plugin, i.e. --module-path, ---module-version
59+
* The Java Module Plugin.
60+
*
61+
* Supports the following:
62+
* 1) Module Compile Path and version, i.e. --module-path, ---module-version
63+
* 2) Additional module specific check tasks, e.g. module version, module services
4464
*/
45-
public class ElasticsearchJavaModulePathPlugin implements Plugin<Project> {
65+
public class ElasticsearchJavaModulePlugin implements Plugin<Project> {
66+
4667
@Override
4768
public void apply(Project project) {
4869
project.getPluginManager().apply(JavaPlugin.class);
4970
configureCompileModulePath(project);
71+
72+
if (hasModuleInfoDotJava(project)) {
73+
TaskProvider<Task> checkModuleVersionTask = registerCheckModuleVersionTask(project, VersionProperties.getElasticsearch());
74+
TaskProvider<Task> checkModuleServicesTask = registerCheckModuleServicesTask(project);
75+
TaskProvider<Task> checkTask = project.getTasks().named("check");
76+
checkTask.configure(task -> {
77+
task.dependsOn(checkModuleVersionTask);
78+
task.dependsOn(checkModuleServicesTask);
79+
});
80+
}
5081
}
5182

5283
// List of root tasks, by name, whose compileJava task should not use the module path. These are test related sources.
@@ -202,4 +233,83 @@ static String pathToString(String path) {
202233
static boolean isIdea() {
203234
return System.getProperty("idea.sync.active", "false").equals("true");
204235
}
236+
237+
// -- check tasks
238+
239+
private static final Predicate<ModuleReference> isESModule = mref -> mref.descriptor().name().startsWith("org.elasticsearch");
240+
241+
private static final Class<ElasticsearchJavaModulePlugin> THIS_CLASS = ElasticsearchJavaModulePlugin.class;
242+
243+
/** Checks that all expected Elasticsearch modules have the expected versions. */
244+
private static TaskProvider<Task> registerCheckModuleVersionTask(Project project, String expectedVersion) {
245+
return project.getTasks().register("checkModuleVersion", task -> {
246+
task.doLast(new Action<>() {
247+
@InputDirectory
248+
File distroRoot = project.file(new File(project.getBuildDir(), "distributions"));
249+
250+
@Override
251+
public void execute(Task task) {
252+
for (ModuleReference mref : esModulesFor(distroRoot)) {
253+
task.getLogger().info("%s checking module version for %s".formatted(task.toString(), mref.descriptor().name()));
254+
String mVersion = mref.descriptor()
255+
.rawVersion()
256+
.orElseThrow(() -> new GradleException("no version found in module " + mref.descriptor().name()));
257+
if (mVersion.equals(expectedVersion) == false) {
258+
throw new GradleException("Expected version [" + expectedVersion + "], in " + mref.descriptor());
259+
}
260+
}
261+
}
262+
});
263+
});
264+
}
265+
266+
/** Checks that ES modules have, at least, the META-INF services declared. */
267+
private static TaskProvider<Task> registerCheckModuleServicesTask(Project project) {
268+
return project.getTasks().register("checkModuleServices", task -> {
269+
task.doLast(new Action<>() {
270+
@InputDirectory
271+
File distroRoot = project.file(new File(project.getBuildDir(), "distributions"));
272+
273+
@Override
274+
public void execute(Task task) {
275+
for (ModuleReference mref : esModulesFor(distroRoot)) {
276+
URI uri = URI.create("jar:" + mref.location().get());
277+
Set<String> modServices = mref.descriptor().provides().stream().map(Provides::service).collect(toSet());
278+
try (var fileSystem = FileSystems.newFileSystem(uri, Map.of(), THIS_CLASS.getClassLoader())) {
279+
Path servicesRoot = fileSystem.getPath("/META-INF/services");
280+
if (Files.exists(servicesRoot)) {
281+
Files.walk(servicesRoot)
282+
.filter(Files::isRegularFile)
283+
.map(p -> servicesRoot.relativize(p))
284+
.map(Path::toString)
285+
.peek(s -> task.getLogger().info("%s checking service %s".formatted(task.toString(), s)))
286+
.forEach(service -> {
287+
if (modServices.contains(service) == false) {
288+
throw new GradleException(
289+
"Expected provides %s in module %s with provides %s.".formatted(
290+
service,
291+
mref.descriptor().name(),
292+
mref.descriptor().provides()
293+
)
294+
);
295+
}
296+
});
297+
}
298+
} catch (IOException e) {
299+
throw new UncheckedIOException(e);
300+
}
301+
}
302+
}
303+
});
304+
});
305+
}
306+
307+
private static List<ModuleReference> esModulesFor(File filePath) {
308+
return ModuleFinder.of(filePath.toPath())
309+
.findAll()
310+
.stream()
311+
.filter(isESModule)
312+
.sorted(Comparator.comparing(ModuleReference::descriptor))
313+
.toList();
314+
}
205315
}

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchJavaPlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class ElasticsearchJavaPlugin implements Plugin<Project> {
4343
public void apply(Project project) {
4444
project.getPluginManager().apply(ElasticsearchJavaBasePlugin.class);
4545
project.getPluginManager().apply(JavaLibraryPlugin.class);
46-
project.getPluginManager().apply(ElasticsearchJavaModulePathPlugin.class);
46+
project.getPluginManager().apply(ElasticsearchJavaModulePlugin.class);
4747

4848
// configureConfigurations(project);
4949
configureJars(project);

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionModuleCheckTaskProvider.java

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,17 @@
2020

2121
import java.io.IOException;
2222
import java.io.UncheckedIOException;
23-
import java.lang.module.ModuleDescriptor;
2423
import java.lang.module.ModuleFinder;
2524
import java.lang.module.ModuleReference;
26-
import java.net.URI;
27-
import java.nio.file.FileSystems;
2825
import java.nio.file.Files;
2926
import java.nio.file.Path;
30-
import java.util.Comparator;
3127
import java.util.List;
32-
import java.util.Map;
33-
import java.util.Set;
3428
import java.util.function.Function;
3529
import java.util.function.Predicate;
3630
import java.util.jar.JarEntry;
3731
import java.util.jar.JarFile;
3832

3933
import static java.util.stream.Collectors.joining;
40-
import static java.util.stream.Collectors.toSet;
4134

4235
/**
4336
* Distribution level checks for Elasticsearch Java modules, i.e. modular jar files.
@@ -60,14 +53,12 @@ public class InternalDistributionModuleCheckTaskProvider {
6053
"org.elasticsearch.cli",
6154
"org.elasticsearch.geo",
6255
"org.elasticsearch.lz4",
63-
"org.elasticsearch.plugin.classloader",
64-
"org.elasticsearch.secure_sm",
56+
"org.elasticsearch.pluginclassloader",
57+
"org.elasticsearch.securesm",
6558
"org.elasticsearch.server",
6659
"org.elasticsearch.xcontent"
6760
);
6861

69-
private static final Class<?> THIS_CLASS = InternalDistributionModuleCheckTaskProvider.class;
70-
7162
private static final Predicate<ModuleReference> isESModule = mref -> mref.descriptor().name().startsWith("org.elasticsearch");
7263

7364
private static Predicate<Path> isESJar = path -> path.getFileName().toString().startsWith(ES_JAR_PREFIX);
@@ -96,8 +87,6 @@ public void execute(Task task) {
9687
try {
9788
assertAllESJarsAreModular(libPath);
9889
assertAllModulesPresent(libPath);
99-
assertModuleVersions(libPath, VersionProperties.getElasticsearch());
100-
assertModuleServices(libPath);
10190
} catch (IOException e) {
10291
throw new UncheckedIOException(e);
10392
}
@@ -132,59 +121,6 @@ private static void assertAllModulesPresent(Path libPath) {
132121
}
133122
}
134123

135-
/** Checks that all expected Elasticsearch modules have the expected versions. */
136-
private static void assertModuleVersions(Path libPath, String expectedVersion) {
137-
List<ModuleReference> esModules = ModuleFinder.of(libPath)
138-
.findAll()
139-
.stream()
140-
.filter(isESModule)
141-
.sorted(Comparator.comparing(ModuleReference::descriptor))
142-
.toList();
143-
for (ModuleReference mref : esModules) {
144-
String mVersion = mref.descriptor()
145-
.rawVersion()
146-
.orElseThrow(() -> new GradleException("no version found in module " + mref.descriptor().name()));
147-
if (mVersion != expectedVersion) {
148-
new GradleException("Expected version [" + expectedVersion + "], in " + mref.descriptor());
149-
}
150-
}
151-
}
152-
153-
/** Checks that all modules have, at least, the META-INF services declared. */
154-
private static void assertModuleServices(Path libPath) throws IOException {
155-
List<ModuleReference> esModules = ModuleFinder.of(libPath)
156-
.findAll()
157-
.stream()
158-
.filter(isESModule) // TODO: how to open this to all, including plugins and modules
159-
.sorted(Comparator.comparing(ModuleReference::descriptor))
160-
.toList();
161-
162-
for (ModuleReference mref : esModules) {
163-
URI uri = URI.create("jar:" + mref.location().get());
164-
Set<String> modServices = mref.descriptor().provides().stream().map(ModuleDescriptor.Provides::service).collect(toSet());
165-
try (var fileSystem = FileSystems.newFileSystem(uri, Map.of(), THIS_CLASS.getClassLoader())) {
166-
Path servicesRoot = fileSystem.getPath("/META-INF/services");
167-
if (Files.exists(servicesRoot)) {
168-
Files.walk(servicesRoot)
169-
.filter(Files::isRegularFile)
170-
.map(p -> servicesRoot.relativize(p))
171-
.map(Path::toString)
172-
.forEach(service -> {
173-
if (modServices.contains(service) == false) {
174-
throw new GradleException(
175-
"Expected provides %s in module %s with provides %s.".formatted(
176-
service,
177-
mref.descriptor().name(),
178-
mref.descriptor().provides()
179-
)
180-
);
181-
}
182-
});
183-
}
184-
}
185-
}
186-
}
187-
188124
// ####: eventually assert hashes, etc
189125

190126
static String listToString(List<String> list) {

0 commit comments

Comments
 (0)