diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/transform/FilteringJarTransform.java b/build-tools/src/main/java/org/elasticsearch/gradle/transform/FilteringJarTransform.java new file mode 100644 index 0000000000000..1675dc3935f36 --- /dev/null +++ b/build-tools/src/main/java/org/elasticsearch/gradle/transform/FilteringJarTransform.java @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.gradle.transform; + +import org.gradle.api.Action; +import org.gradle.api.artifacts.dsl.DependencyHandler; +import org.gradle.api.artifacts.transform.InputArtifact; +import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformOutputs; +import org.gradle.api.artifacts.transform.TransformParameters; +import org.gradle.api.artifacts.type.ArtifactTypeDefinition; +import org.gradle.api.file.FileSystemLocation; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.Input; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.io.UncheckedIOException; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +public abstract class FilteringJarTransform implements TransformAction { + public static final String FILTERED_JAR_TYPE = "filtered-jar"; + + @InputArtifact + public abstract Provider getInputArtifact(); + + @Override + public void transform(TransformOutputs outputs) { + File original = getInputArtifact().get().getAsFile(); + File transformed = outputs.file(original.getName()); + List excludes = createMatchers(getParameters().getExcludes()); + + try ( + ZipFile input = new ZipFile(original); + ZipOutputStream output = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(transformed))) + ) { + Enumeration entries = input.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (excludes.stream().noneMatch(e -> e.matches(Path.of(entry.getName())))) { + output.putNextEntry(entry); + input.getInputStream(entry).transferTo(output); + output.closeEntry(); + } + } + + output.flush(); + output.finish(); + } catch (IOException e) { + throw new UncheckedIOException("Failed to patch archive", e); + } + } + + private List createMatchers(List patterns) { + return patterns.stream().map(p -> FileSystems.getDefault().getPathMatcher("glob:" + p)).toList(); + } + + public static void registerTransform(DependencyHandler dependencyHandler, Action config) { + dependencyHandler.registerTransform(FilteringJarTransform.class, spec -> { + spec.getFrom().attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE); + spec.getTo().attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, FILTERED_JAR_TYPE); + config.execute(spec.getParameters()); + }); + } + + public abstract static class Parameters implements TransformParameters, Serializable { + private List excludes = new ArrayList<>(); + + @Input + public List getExcludes() { + return excludes; + } + + public void exclude(String exclude) { + excludes.add(exclude); + } + } +} diff --git a/distribution/build.gradle b/distribution/build.gradle index a952d5d3f4674..1cdc1acf54f79 100644 --- a/distribution/build.gradle +++ b/distribution/build.gradle @@ -15,6 +15,7 @@ import org.elasticsearch.gradle.internal.ConcatFilesTask import org.elasticsearch.gradle.internal.DependenciesInfoPlugin import org.elasticsearch.gradle.internal.NoticeTask import org.elasticsearch.gradle.internal.test.ClusterFeaturesMetadataPlugin +import org.elasticsearch.gradle.transform.FilteringJarTransform import java.nio.file.Files import java.nio.file.Path @@ -261,7 +262,7 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) { * Properties to expand when copying packaging files * *****************************************************************************/ configurations { - ['libs', 'libsVersionChecker', 'libsCliLauncher', 'libsServerCli', 'libsWindowsServiceCli', 'libsPluginCli', 'libsKeystoreCli', 'libsSecurityCli', 'libsGeoIpCli', 'libsAnsiConsole', 'libsNative', 'libsEntitlementAgent', 'libsEntitlementBridge'].each { + ['libs', 'libsVersionChecker', 'libsCliLauncher', 'libsServerCli', 'libsWindowsServiceCli', 'libsPluginCli', 'libsKeystoreCli', 'libsSecurityCli', 'libsGeoIpCli', 'libsAnsiConsole', 'libsNative', 'libsEntitlementAgent'].each { create(it) { canBeConsumed = false canBeResolved = true @@ -272,12 +273,28 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) { } } } + libsEntitlementBridge { + canBeConsumed = false + canBeResolved = true + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.LIBRARY)) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME)) + attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL)) + attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, FilteringJarTransform.FILTERED_JAR_TYPE) + } + } all { resolutionStrategy.dependencySubstitution { substitute module("org.apache.logging.log4j:log4j-core") using project(":libs:log4j") because "patched to remove JndiLookup class"} } } + // Register artifact transform for filtering entitlements-bridge jar + FilteringJarTransform.registerTransform(dependencies) { spec -> + spec.exclude('module-info.class') + spec.exclude('META-INF/versions/**') + } + dependencies { libs project(':server')