Skip to content

Commit

Permalink
Add error handling and useful prints for SBOM feature
Browse files Browse the repository at this point in the history
  • Loading branch information
rudsberg committed Sep 26, 2024
1 parent 322dfd6 commit 6c5fdf3
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import static org.graalvm.buildtools.utils.SharedConstants.GRAALVM_EXE_EXTENSION;

public class NativeImageUtils {
public static final String ORACLE_GRAALVM_IDENTIFIER = "Oracle GraalVM";

private static final Pattern requiredVersionPattern = Pattern.compile("^([0-9]+)(?:\\.([0-9]+)?)?(?:\\.([0-9]+)?)?$");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.graalvm.buildtools.utils.NativeImageUtils.ORACLE_GRAALVM_IDENTIFIER;

/**
* @author Sebastien Deleuze
*/
Expand Down Expand Up @@ -442,7 +444,7 @@ protected void checkRequiredVersionIfNeeded() throws MojoExecutionException {
}

protected boolean isOracleGraalVM() throws MojoExecutionException {
return getVersionInformation().contains("Oracle GraalVM");
return getVersionInformation().contains(ORACLE_GRAALVM_IDENTIFIER);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,14 @@
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.graalvm.buildtools.maven.sbom.SBOMGenerator;
import org.graalvm.buildtools.utils.NativeImageUtils;

import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;

import static org.graalvm.buildtools.utils.NativeImageUtils.ORACLE_GRAALVM_IDENTIFIER;

/**
* This goal runs native builds. It functions the same as the native:compile goal, but it
* does not fork the build, so it is suitable for attaching to the build lifecycle.
Expand All @@ -74,9 +77,9 @@ public class NativeCompileNoForkMojo extends AbstractNativeImageMojo {
@Parameter(property = "skipNativeBuildForPom", defaultValue = "false")
private boolean skipNativeBuildForPom;

public static final String enableSBOMParamName = "enableSBOM";
@Parameter(property = enableSBOMParamName, defaultValue = "true")
private boolean enableSBOM;
public static final String enableAugmentedSBOMParamName = "enableAugmentedSBOM";
@Parameter(property = enableAugmentedSBOMParamName, defaultValue = "false")
private boolean enableAugmentedSBOM;

private PluginParameterExpressionEvaluator evaluator;

Expand Down Expand Up @@ -106,14 +109,73 @@ public void execute() throws MojoExecutionException {
maybeSetMainClassFromPlugin(this::consumeConfigurationNodeValue, "org.apache.maven.plugins:maven-jar-plugin", "archive", "manifest", "mainClass");
maybeAddGeneratedResourcesConfig(buildArgs);

if (isOracleGraalVM() && enableSBOM) {
var generator = new SBOMGenerator(mavenProject, mavenSession, pluginManager, repositorySystem, mainClass, logger);
generator.generate();
}
generateSBOMIfPossible();

buildImage();
}

/**
* Generates an SBOM using the {@link SBOMGenerator} if {@link NativeCompileNoForkMojo#enableAugmentedSBOM} is true
* and the required pre-conditions are met.
*
* @throws IllegalArgumentException when some pre-conditions are not met.
* @throws MojoExecutionException when SBOM generation failed.
*/
private void generateSBOMIfPossible() throws IllegalArgumentException, MojoExecutionException {
String sbomNativeImageFlag = "--enable-sbom";
boolean sbomEnabledForNativeImage = getBuildArgs().stream().anyMatch(v -> v.contains(sbomNativeImageFlag));
if (!sbomEnabledForNativeImage && !enableAugmentedSBOM) {
/* Omit showing a hint to use SBOM since the Native Image build output will include such a hint. */
return;
}

if (!isOracleGraalVM()) {
if (enableAugmentedSBOM) {
throw new IllegalArgumentException(
String.format("Configuration option %s is only supported in %s.", enableAugmentedSBOMParamName, ORACLE_GRAALVM_IDENTIFIER));
}
return;
}

if (!enableAugmentedSBOM) {
if (checkAugmentedSBOMSupportedByVersion(false)) {
logger.info(String.format("Set configuration option %s to true to create an enhanced and more accurate SBOM.", enableAugmentedSBOMParamName));
}
return;
}

checkAugmentedSBOMSupportedByVersion(true);
if (!sbomEnabledForNativeImage) {
logger.info(String.format("Automatically added build argument %s with default options to Native Image because configuration option %s was set to true. " +
"An SBOM will be embedded in the image.", sbomNativeImageFlag, enableAugmentedSBOMParamName));
buildArgs.add(sbomNativeImageFlag);
}

var sbomGenerator = new SBOMGenerator(mavenProject, mavenSession, pluginManager, repositorySystem, mainClass, logger);
sbomGenerator.generate();
}

/**
* Checks if the JDK version supports the {@link NativeCompileNoForkMojo#enableAugmentedSBOM} flag.
*
* @param throwErrorIfNotSupported if true, then an error is thrown if the check failed.
* @return true if the JDK version supports the flag, otherwise false (if {@param throwErrorIfNotSupported} is false).
* @throws MojoExecutionException when {@param throwErrorIfNotSupported} is true and the version information could not be derived.
* @throws IllegalArgumentException when {@param throwErrorIfNotSupported} is true and the version check failed.
*/
private boolean checkAugmentedSBOMSupportedByVersion(boolean throwErrorIfNotSupported) throws IllegalArgumentException, MojoExecutionException {
int detectedJdkVersion = NativeImageUtils.getMajorJDKVersion(getVersionInformation());
if (detectedJdkVersion < SBOMGenerator.requiredNativeImageVersion) {
if (throwErrorIfNotSupported) {
throw new IllegalArgumentException(
String.format("%s version %s is required to use configuration option %s but major JDK version %s has been detected.",
ORACLE_GRAALVM_IDENTIFIER, SBOMGenerator.requiredNativeImageVersion, enableAugmentedSBOMParamName, detectedJdkVersion));
}
return false;
}
return true;
}

private String consumeConfigurationNodeValue(String pluginKey, String... nodeNames) {
Plugin selectedPlugin = project.getPlugin(pluginKey);
if (selectedPlugin == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.aether.RepositorySystem;
import org.graalvm.buildtools.maven.NativeCompileNoForkMojo;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -61,6 +59,7 @@
import java.util.Set;
import java.util.stream.Collectors;

import static org.graalvm.buildtools.maven.NativeCompileNoForkMojo.enableAugmentedSBOMParamName;
import static org.twdata.maven.mojoexecutor.MojoExecutor.*;

/**
Expand All @@ -82,6 +81,8 @@
* * Enhanced Accuracy: Native Image augments and refines the SBOM, potentially significantly improving its accuracy.
*/
final public class SBOMGenerator {
public static final int requiredNativeImageVersion = 24;

private final MavenProject mavenProject;
private final MavenSession mavenSession;
private final BuildPluginManager pluginManager;
Expand Down Expand Up @@ -176,7 +177,7 @@ public void generate() throws MojoExecutionException {
} catch (Exception exception) {
deleteFileIfExists(sbomPath);
String errorMsg = String.format("Failed to create SBOM. Please try again and report this issue if it persists. " +
"To bypass this failure, disable SBOM generation by setting %s to false.", NativeCompileNoForkMojo.enableSBOMParamName);
"To bypass this failure, disable SBOM generation by setting configuration option %s to false.", enableAugmentedSBOMParamName);
throw new MojoExecutionException(errorMsg, exception);
}
}
Expand Down

0 comments on commit 6c5fdf3

Please sign in to comment.