Skip to content

Commit

Permalink
Add support for custom external references (#428)
Browse files Browse the repository at this point in the history
* Add support for custom external references (#421)

Signed-off-by: Volkan Yazıcı <volkan@yazi.ci>
  • Loading branch information
vy committed Jan 15, 2024
1 parent 86410aa commit 8836cbd
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 17 deletions.
11 changes: 10 additions & 1 deletion src/main/java/org/cyclonedx/maven/BaseCycloneDxMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.cyclonedx.model.Bom;
import org.cyclonedx.model.Component;
import org.cyclonedx.model.Dependency;
import org.cyclonedx.model.ExternalReference;
import org.cyclonedx.model.Metadata;
import org.cyclonedx.model.Property;
import org.cyclonedx.parsers.JsonParser;
Expand Down Expand Up @@ -217,6 +218,14 @@ public abstract class BaseCycloneDxMojo extends AbstractMojo {
@Parameter( defaultValue = "${project.build.outputTimestamp}" )
private String outputTimestamp;

/**
* External references to be added to <code>$.metadata.component.externalReferences[]</code>.
*
* @since 2.7.11
*/
@Parameter
private ExternalReference[] externalReferences;

@org.apache.maven.plugins.annotations.Component
private MavenProjectHelper mavenProjectHelper;

Expand Down Expand Up @@ -301,7 +310,7 @@ public void execute() throws MojoExecutionException {

String analysis = extractComponentsAndDependencies(topLevelComponents, componentMap, dependencyMap);
if (analysis != null) {
final Metadata metadata = modelConverter.convert(project, projectType, schemaVersion(), includeLicenseText);
final Metadata metadata = modelConverter.convert(project, projectType, schemaVersion(), includeLicenseText, externalReferences);

if (schemaVersion().getVersion() >= 1.3) {
metadata.addProperty(newProperty("maven.goal", analysis));
Expand Down
41 changes: 26 additions & 15 deletions src/main/java/org/cyclonedx/maven/DefaultModelConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,8 @@
*/
package org.cyclonedx.maven;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Properties;
import java.util.TreeMap;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
Expand All @@ -55,8 +45,18 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.TreeMap;
import java.util.stream.Collectors;

@Singleton
@Named
Expand Down Expand Up @@ -187,6 +187,16 @@ public Component convert(Artifact artifact, CycloneDxSchema.Version schemaVersio
}
}
return component;

}

private static void setExternalReferences(Component component, ExternalReference[] externalReferences) {
if (externalReferences == null || externalReferences.length == 0) {
return;
}
// We need a mutable `List`, hence `Arrays.asList()` won't work.
List<ExternalReference> externalReferences_ = Arrays.stream(externalReferences).collect(Collectors.toList());
component.setExternalReferences(externalReferences_);
}

private boolean isModified(Artifact artifact) {
Expand Down Expand Up @@ -341,7 +351,7 @@ else if (licenseChoiceToResolve.getExpression() != null && CycloneDxSchema.Versi
}

@Override
public Metadata convert(final MavenProject project, String projectType, CycloneDxSchema.Version schemaVersion, boolean includeLicenseText) {
public Metadata convert(final MavenProject project, String projectType, CycloneDxSchema.Version schemaVersion, boolean includeLicenseText, ExternalReference[] externalReferences) {
final Tool tool = new Tool();
final Properties properties = readPluginProperties();
tool.setVendor(properties.getProperty("vendor"));
Expand All @@ -367,6 +377,7 @@ public Metadata convert(final MavenProject project, String projectType, CycloneD
component.setType(resolveProjectType(projectType));
component.setPurl(generatePackageUrl(project.getArtifact()));
component.setBomRef(component.getPurl());
setExternalReferences(component, externalReferences);
extractComponentMetadata(project, component, schemaVersion, includeLicenseText);

final Metadata metadata = new Metadata();
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/cyclonedx/maven/ModelConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.maven.project.MavenProject;
import org.cyclonedx.CycloneDxSchema;
import org.cyclonedx.model.Component;
import org.cyclonedx.model.ExternalReference;
import org.cyclonedx.model.Metadata;

/**
Expand Down Expand Up @@ -57,7 +58,9 @@ public interface ModelConverter {
* @param projectType the target CycloneDX component type
* @param schemaVersion the target CycloneDX schema version
* @param includeLicenseText should license text be included in bom?
* @param externalReferences the external references
* @return a CycloneDX Metadata object
*/
Metadata convert(MavenProject project, String projectType, CycloneDxSchema.Version schemaVersion, boolean includeLicenseText);
Metadata convert(MavenProject project, String projectType, CycloneDxSchema.Version schemaVersion, boolean includeLicenseText, ExternalReference[] externalReferences);

}
65 changes: 65 additions & 0 deletions src/test/java/org/cyclonedx/maven/ExternalReferenceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package org.cyclonedx.maven;

import io.takari.maven.testing.executor.MavenRuntime.MavenRuntimeBuilder;
import io.takari.maven.testing.executor.MavenVersions;
import io.takari.maven.testing.executor.junit.MavenJUnitTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collections;

import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;

/**
* Verifies external references are populated as expected.
*/
@RunWith(MavenJUnitTestRunner.class)
@MavenVersions({"3.6.3"})
public class ExternalReferenceTest extends BaseMavenVerifier {

public ExternalReferenceTest(MavenRuntimeBuilder runtimeBuilder) throws Exception {
super(runtimeBuilder);
}

@Test
public void testAddedExternalReferences() throws Exception {

// Create the verifier
File projDir = resources.getBasedir("external-reference");
verifier
.forProject(projDir)
.withCliOption("-Dcyclonedx-maven-plugin.version=" + getCurrentVersion())
.withCliOption("-X")
.withCliOption("-B")
.execute("clean", "verify")
.assertErrorFreeLog();

// Verify parent metadata
assertExternalReferences(
new File(projDir, "target/bom.json"),
"$.metadata.component.externalReferences[?(@.type=='chat')].url",
Collections.singleton("https://acme.com/parent"));

// Verify child metadata
assertExternalReferences(
new File(projDir, "child/target/bom.json"),
"$.metadata.component.externalReferences[?(@.type=='chat')].url",
Arrays.asList("https://acme.com/parent", "https://acme.com/child"));

}

private static void assertExternalReferences(File bomFile, String jsonPath, Iterable<Object> expectedValues) throws IOException {
byte[] bomJsonBytes = Files.readAllBytes(bomFile.toPath());
String bomJson = new String(bomJsonBytes, StandardCharsets.UTF_8);
assertThatJson(bomJson)
.inPath(jsonPath)
.isArray()
.containsOnlyOnceElementsOf(expectedValues);
}

}
42 changes: 42 additions & 0 deletions src/test/resources/external-reference/child/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>${revision}</version>
</parent>

<artifactId>child</artifactId>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.1</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>${cyclonedx-maven-plugin.version}</version>
<configuration>
<externalReferences combine.children="append">
<externalReference>
<type>CHAT</type>
<url>https://acme.com/child</url>
</externalReference>
</externalReferences>
</configuration>
</plugin>
</plugins>
</build>

</project>
60 changes: 60 additions & 0 deletions src/test/resources/external-reference/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>${revision}</version>

<licenses>
<license>
<name>Apache-2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>

<properties>
<revision>1.0.0</revision>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<modules>
<module>child</module>
</modules>

<build>
<plugins>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>${cyclonedx-maven-plugin.version}</version>
<executions>
<execution>
<id>generate-sbom</id>
<goals>
<goal>makeAggregateBom</goal>
</goals>
<phase>verify</phase>
<configuration>
<outputFormat>json</outputFormat>
<externalReferences>
<externalReference>
<type>CHAT</type>
<url>https://acme.com/parent</url>
</externalReference>
</externalReferences>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>

0 comments on commit 8836cbd

Please sign in to comment.