Skip to content

Commit

Permalink
Merge pull request quarkusio#23332 from glefloch/fix/12889
Browse files Browse the repository at this point in the history
Add manifest configuration in build mojo/task
  • Loading branch information
gsmet authored Feb 1, 2022
2 parents 32450e6 + 0adc122 commit 8280c53
Show file tree
Hide file tree
Showing 13 changed files with 374 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.gradle.dsl;

import java.util.LinkedHashMap;
import java.util.Map;

import org.gradle.api.java.archives.Attributes;
import org.gradle.api.java.archives.internal.DefaultAttributes;

public class Manifest {

private Attributes attributes = new DefaultAttributes();
private Map<String, Attributes> sections = new LinkedHashMap<>();

public Attributes getAttributes() {
return attributes;
}

public Map<String, Attributes> getSections() {
return sections;
}

public Manifest attributes(Map<String, String> attributes) {
this.attributes.putAll(attributes);
return this;
}

public Manifest attributes(Map<String, String> attributes, String section) {
if (!this.sections.containsKey(section)) {
this.sections.put(section, new DefaultAttributes());
}
this.sections.get(section).putAll(attributes);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.file.FileCollection;
import org.gradle.api.java.archives.Attributes;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.OutputFile;
Expand All @@ -25,13 +27,17 @@
import io.quarkus.bootstrap.app.CuratedApplication;
import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.gradle.dsl.Manifest;
import io.quarkus.runtime.util.StringUtil;

public class QuarkusBuild extends QuarkusTask {

private static final String NATIVE_PROPERTY_NAMESPACE = "quarkus.native";
private static final String MANIFEST_SECTIONS_PROPERTY_PREFIX = "quarkus.package.manifest.manifest-sections";
private static final String MANIFEST_ATTRIBUTES_PROPERTY_PREFIX = "quarkus.package.manifest.attributes";

private List<String> ignoredEntries = new ArrayList<>();
private Manifest manifest = new Manifest();

public QuarkusBuild() {
super("Quarkus builds a runner jar based on the build jar");
Expand Down Expand Up @@ -89,6 +95,16 @@ public Map<String, String> getQuarkusBuildEnvProperties() {
return quarkusEnvProperties;
}

@Internal
public Manifest getManifest() {
return this.manifest;
}

public QuarkusBuild manifest(Action<Manifest> action) {
action.execute(this.getManifest());
return this;
}

@OutputFile
public File getRunnerJar() {
return new File(getProject().getBuildDir(), extension().finalName() + "-runner.jar");
Expand All @@ -115,6 +131,9 @@ public void buildQuarkus() {
String joinedEntries = String.join(",", ignoredEntries);
effectiveProperties.setProperty("quarkus.package.user-configured-ignored-entries", joinedEntries);
}

exportCustomManifestProperties(effectiveProperties);

try (CuratedApplication appCreationContext = QuarkusBootstrap.builder()
.setBaseClassLoader(getClass().getClassLoader())
.setExistingModel(appModel)
Expand All @@ -140,6 +159,42 @@ public void buildQuarkus() {
}
}

private void exportCustomManifestProperties(Properties buildSystemProperties) {
if (this.manifest == null) {
return;
}

for (Map.Entry<String, Object> attribute : manifest.getAttributes().entrySet()) {
buildSystemProperties.put(toManifestAttributeKey(attribute.getKey()),
attribute.getValue());
}

for (Map.Entry<String, Attributes> section : manifest.getSections().entrySet()) {
for (Map.Entry<String, Object> attribute : section.getValue().entrySet()) {
buildSystemProperties
.put(toManifestSectionAttributeKey(section.getKey(), attribute.getKey()), attribute.getValue());
}
}
}

private String toManifestAttributeKey(String key) {
if (key.contains("\"")) {
throw new GradleException("Manifest entry name " + key + " is invalid. \" characters are not allowed.");
}
return String.format("%s.\"%s\"", MANIFEST_ATTRIBUTES_PROPERTY_PREFIX, key);
}

private String toManifestSectionAttributeKey(String section, String key) {
if (section.contains("\"")) {
throw new GradleException("Manifest section name " + section + " is invalid. \" characters are not allowed.");
}
if (key.contains("\"")) {
throw new GradleException("Manifest entry name " + key + " is invalid. \" characters are not allowed.");
}
return String.format("%s.\"%s\".\"%s\"", MANIFEST_SECTIONS_PROPERTY_PREFIX, section,
key);
}

private String expandConfigurationKey(String shortKey) {
final String hyphenatedKey = StringUtil.hyphenate(shortKey);
if (hyphenatedKey.startsWith(NATIVE_PROPERTY_NAMESPACE)) {
Expand Down
3 changes: 1 addition & 2 deletions devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ && isNativeProfileEnabled(mavenProject())) {
System.setProperty(PACKAGE_TYPE_PROP, packageType);
propertiesToClear.add(PACKAGE_TYPE_PROP);
}

if (!propertiesToClear.isEmpty() && mavenSession().getRequest().getDegreeOfConcurrency() > 1) {
getLog().warn("*****************************************************************");
getLog().warn("* Your build is requesting parallel execution, but the project *");
Expand All @@ -127,7 +128,6 @@ && isNativeProfileEnabled(mavenProject())) {
getLog().warn("*****************************************************************");
}
try (CuratedApplication curatedApplication = bootstrapApplication()) {

AugmentAction action = curatedApplication.createAugmentor();
AugmentResult result = action.createProductionApplication();

Expand Down Expand Up @@ -179,5 +179,4 @@ public void setLog(Log log) {
super.setLog(log);
MojoLogger.delegate = log;
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.quarkus.maven;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

Expand All @@ -21,6 +23,7 @@
import org.eclipse.aether.repository.RemoteRepository;

import io.quarkus.bootstrap.app.CuratedApplication;
import io.quarkus.maven.components.ManifestSection;
import io.quarkus.maven.dependency.ArtifactKey;
import io.quarkus.maven.dependency.Dependency;
import io.quarkus.runtime.LaunchMode;
Expand Down Expand Up @@ -60,6 +63,18 @@ public abstract class QuarkusBootstrapMojo extends AbstractMojo {
@Parameter(defaultValue = "${project.build.finalName}")
private String finalName;

/**
* The list of main manifest attributes
*/
@Parameter
private Map<String, String> manifestEntries = new LinkedHashMap<>();

/**
* The list of manifest sections
*/
@Parameter
private List<ManifestSection> manifestSections = new ArrayList<>();

/**
* When building an uber-jar, this array specifies entries that should
* be excluded from the final jar. The entries are relative to the root of
Expand Down Expand Up @@ -199,6 +214,14 @@ protected String finalName() {
return finalName;
}

protected Map<String, String> manifestEntries() {
return manifestEntries;
}

protected List<ManifestSection> manifestSections() {
return manifestSections;
}

protected String[] ignoredEntries() {
return ignoredEntries;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutionException;
Expand All @@ -32,6 +33,7 @@
import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver;
import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import io.quarkus.maven.components.ManifestSection;
import io.quarkus.maven.dependency.ArtifactCoords;
import io.quarkus.maven.dependency.ArtifactKey;
import io.quarkus.maven.dependency.GACT;
Expand All @@ -43,6 +45,9 @@
@Component(role = QuarkusBootstrapProvider.class, instantiationStrategy = "singleton")
public class QuarkusBootstrapProvider implements Closeable {

private static final String MANIFEST_SECTIONS_PROPERTY_PREFIX = "quarkus.package.manifest.manifest-sections";
private static final String MANIFEST_ATTRIBUTES_PROPERTY_PREFIX = "quarkus.package.manifest.attributes";

@Requirement(role = RepositorySystem.class, optional = false)
protected RepositorySystem repoSystem;

Expand Down Expand Up @@ -153,6 +158,17 @@ protected CuratedApplication doBootstrap(QuarkusBootstrapMojo mojo, LaunchMode m
effectiveProperties.putIfAbsent("quarkus.application.name", mojo.mavenProject().getArtifactId());
effectiveProperties.putIfAbsent("quarkus.application.version", mojo.mavenProject().getVersion());

for (Map.Entry<String, String> attribute : mojo.manifestEntries().entrySet()) {
effectiveProperties.put(toManifestAttributeKey(attribute.getKey()),
attribute.getValue());
}
for (ManifestSection section : mojo.manifestSections()) {
for (Map.Entry<String, String> attribute : section.getManifestEntries().entrySet()) {
effectiveProperties
.put(toManifestSectionAttributeKey(section.getName(), attribute.getKey()), attribute.getValue());
}
}

// Add other properties that may be required for expansion
for (Object value : effectiveProperties.values()) {
for (String reference : Expression.compile((String) value, LENIENT_SYNTAX, NO_TRIM).getReferencedStrings()) {
Expand Down Expand Up @@ -213,6 +229,25 @@ protected CuratedApplication doBootstrap(QuarkusBootstrapMojo mojo, LaunchMode m
}
}

private String toManifestAttributeKey(String key) throws MojoExecutionException {
if (key.contains("\"")) {
throw new MojoExecutionException("Manifest entry name " + key + " is invalid. \" characters are not allowed.");
}
return String.format("%s.\"%s\"", MANIFEST_ATTRIBUTES_PROPERTY_PREFIX, key);
}

private String toManifestSectionAttributeKey(String section, String key) throws MojoExecutionException {
if (section.contains("\"")) {
throw new MojoExecutionException(
"Manifest section name " + section + " is invalid. \" characters are not allowed.");
}
if (key.contains("\"")) {
throw new MojoExecutionException("Manifest entry name " + key + " is invalid. \" characters are not allowed.");
}
return String.format("%s.\"%s\".\"%s\"", MANIFEST_SECTIONS_PROPERTY_PREFIX, section,
key);
}

protected CuratedApplication bootstrapApplication(QuarkusBootstrapMojo mojo, LaunchMode mode)
throws MojoExecutionException {
if (mode == LaunchMode.DEVELOPMENT) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.maven.components;

import java.util.LinkedHashMap;
import java.util.Map;

public class ManifestSection {

private String name = null;
private Map<String, String> manifestEntries = new LinkedHashMap<>();

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setManifestEntries(Map<String, String> manifestEntries) {
this.manifestEntries = manifestEntries;
}

public Map<String, String> getManifestEntries() {
return manifestEntries;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ compileTestJava {
quarkusDev {
workingDir = "./build"
}

quarkusBuild {
manifest {
attributes ([
'Built-By': 'quarkus-gradle-plugin'
])
attributes(['framework': 'quarkus'], 'org.acme')
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quarkus.package.type=uber-jar
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.quarkus.gradle;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.jar.Attributes;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

import org.junit.jupiter.api.Test;

public class CustomManifestArgumentsTest extends QuarkusGradleWrapperTestBase {

@Test
public void shouldContainsSpecificManifestProperty() throws Exception {
File projectDir = getProjectDir("custom-config-java-module");

runGradleWrapper(projectDir, "clean", "quarkusBuild");

Path buildDir = new File(projectDir, "build").toPath();
Path jar = buildDir.resolve("code-with-quarkus-1.0.0-SNAPSHOT-runner.jar");

assertThat(jar).exists();
try (InputStream fileInputStream = new FileInputStream(jar.toFile())) {
try (JarInputStream jarStream = new JarInputStream(fileInputStream)) {
Manifest manifest = jarStream.getManifest();
assertThat(manifest).isNotNull();

String customAttribute = manifest.getMainAttributes().getValue("Built-By");
assertThat(customAttribute).isNotNull();
assertThat(customAttribute).isEqualTo("quarkus-gradle-plugin");

Attributes customSection = manifest.getAttributes("org.acme");
assertThat(customSection).isNotNull();

String sectionAttribute = customSection.getValue("framework");
assertThat(sectionAttribute).isNotNull();
assertThat(sectionAttribute).isEqualTo("quarkus");
}
}
}

}
Loading

0 comments on commit 8280c53

Please sign in to comment.