Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gradle: Avoid setting a manifest object #5276

Merged
merged 1 commit into from Jun 4, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -37,9 +37,6 @@
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.java.archives.Attributes;
import org.gradle.api.java.archives.ManifestException;
import org.gradle.api.java.archives.ManifestMergeSpec;
import org.gradle.api.java.archives.internal.DefaultManifest;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.ListProperty;
Expand All @@ -66,7 +63,6 @@
import aQute.lib.io.IO;
import aQute.lib.strings.Strings;
import aQute.lib.utf8properties.UTF8Properties;
import groovy.lang.Closure;

/**
* BundleTaskExtension for Gradle.
Expand Down Expand Up @@ -100,7 +96,6 @@ public class BundleTaskExtension {
private final ConfigurableFileCollection classpath;
private final Provider<String> bnd;
private final MapProperty<String, Object> properties;
private final EffectiveManifest effectiveManifest;

/**
* The bndfile property.
Expand Down Expand Up @@ -216,12 +211,6 @@ public BundleTaskExtension(org.gradle.api.tasks.bundling.Jar task) {
classpath(mainSourceSet.getCompileClasspath());
properties = objects.mapProperty(String.class, Object.class)
.convention(Maps.of("project", "__convention__"));
// Wrap manifest
org.gradle.api.java.archives.Manifest manifest = task.getManifest();
effectiveManifest = new EffectiveManifest(manifest);
if (manifest != null) {
task.setManifest(effectiveManifest);
}
// need to programmatically add to inputs since @InputFiles in a
// extension is not processed
task.getInputs()
Expand Down Expand Up @@ -367,6 +356,8 @@ public void execute(Task t) {
File buildDir = unwrapFile(getLayout().getBuildDirectory());
File buildFile = getBuildFile();
FileCollection sourcepath = getAllSource().filter(file -> file.exists());
Optional<org.gradle.api.java.archives.Manifest> taskManifest = Optional
.ofNullable(getTask().getManifest());
// create Builder
Properties gradleProperties = new BeanProperties();
gradleProperties.putAll(unwrap(getProperties()));
Expand All @@ -379,14 +370,14 @@ public void execute(Task t) {
try (Writer writer = IO.writer(temporaryBndFile)) {
// write any task manifest entries into the tmp bnd
// file
Optional<UTF8Properties> properties = Optional.ofNullable(getTask().getManifest())
.map(manifest -> MapStream.ofNullable(manifest.getEffectiveManifest()
Optional<UTF8Properties> properties = taskManifest.map(manifest -> MapStream
.ofNullable(manifest.getEffectiveManifest()
.getAttributes())
.filterKey(key -> !Objects.equals(key, "Manifest-Version"))
.mapValue(Object::toString)
.collect(MapStream.toMap((k1, k2) -> {
throw new IllegalStateException("Duplicate key " + k1);
}, UTF8Properties::new)));
.filterKey(key -> !Objects.equals(key, "Manifest-Version"))
.mapValue(Object::toString)
.collect(MapStream.toMap((k1, k2) -> {
throw new IllegalStateException("Duplicate key " + k1);
}, UTF8Properties::new)));
if (properties.isPresent()) {
properties.get()
.replaceHere(projectDir)
Expand Down Expand Up @@ -514,8 +505,15 @@ public void execute(Task t) {
builtJar.write(archiveFile);
long now = System.currentTimeMillis();
archiveFile.setLastModified(now);
// Set effective manifest to generated manifest
effectiveManifest.setEffectiveManifest(builtJar.getManifest());
// Set effective manifest from generated manifest
Manifest builtManifest = builtJar.getManifest();
taskManifest.ifPresent(
manifest -> manifest.from(mergeManifest(builtManifest), merge -> merge.eachEntry(details -> {
if (details.getMergeValue() == null) {
// exclude if entry not in merge manifest
details.exclude();
}
})));
logReport(builder, getTask().getLogger());
if (!builder.isOk()) {
failTask("Bundle " + archiveFileName + " has errors", archiveFile);
Expand All @@ -526,6 +524,14 @@ public void execute(Task t) {
}
}

private org.gradle.api.java.archives.Manifest mergeManifest(Manifest builtManifest) {
org.gradle.api.java.archives.Manifest mergeManifest = new DefaultManifest(null);
mergeManifest.attributes(new AttributesMap(builtManifest.getMainAttributes()));
builtManifest.getEntries()
.forEach((section, attrs) -> mergeManifest.attributes(new AttributesMap(attrs), section));
return mergeManifest;
}

private void failTask(String msg, File archiveFile) {
IO.delete(archiveFile);
throw new GradleException(msg);
Expand All @@ -537,80 +543,6 @@ private boolean isEmpty(String header) {
}
}

static final class EffectiveManifest implements org.gradle.api.java.archives.Manifest {
final org.gradle.api.java.archives.Manifest delegate;
Manifest effectiveManifest;

EffectiveManifest(org.gradle.api.java.archives.Manifest delegate) {
this.delegate = delegate;
this.effectiveManifest = null;
}

void setEffectiveManifest(Manifest effectiveManifest) {
this.effectiveManifest = effectiveManifest;
}

@Override
public org.gradle.api.java.archives.Manifest attributes(Map<String, ?> attributes) throws ManifestException {
delegate.attributes(attributes);
return this;
}

@Override
public org.gradle.api.java.archives.Manifest attributes(Map<String, ?> attributes, String sectionName)
throws ManifestException {
delegate.attributes(attributes, sectionName);
return this;
}

@Override
public org.gradle.api.java.archives.Manifest from(Object... mergePath) {
delegate.from(mergePath);
return this;
}

@Override
public org.gradle.api.java.archives.Manifest from(Object mergePath, Closure<?> closure) {
delegate.from(mergePath, closure);
return this;
}

@Override
public org.gradle.api.java.archives.Manifest from(Object mergePath, Action<ManifestMergeSpec> action) {
delegate.from(mergePath, action);
return this;
}

@Override
public Attributes getAttributes() {
return delegate.getAttributes();
}

@Override
public org.gradle.api.java.archives.Manifest getEffectiveManifest() {
Manifest effectiveManifest = this.effectiveManifest;
if (effectiveManifest == null) {
return delegate.getEffectiveManifest();
}
org.gradle.api.java.archives.Manifest result = new DefaultManifest(null);
result.attributes(new AttributesMap(effectiveManifest.getMainAttributes()));
effectiveManifest.getEntries()
.forEach((section, attrs) -> result.attributes(new AttributesMap(attrs), section));
return result;
}

@Override
public Map<String, Attributes> getSections() {
return delegate.getSections();
}

@Override
public org.gradle.api.java.archives.Manifest writeTo(Object path) {
getEffectiveManifest().writeTo(path);
return this;
}
}

static final class AttributesMap extends AbstractMap<String, Object> {
final java.util.jar.Attributes source;

Expand Down