translate maps to sequences in pkg metadata (#2553)

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman
2024-02-01 11:58:10 -05:00
committed by GitHub
parent fef0e54c0f
commit 6107e5e2ad
19 changed files with 3153 additions and 543 deletions
+152 -93
View File
@@ -14,6 +14,7 @@ import (
"syscall"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/gookit/color"
"github.com/scylladb/go-set/strset"
@@ -197,31 +198,31 @@ func TestParseJar(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/java-builds/packages/example-jenkins-plugin.hpi",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Specification-Title": "Example Jenkins Plugin",
"Specification-Version": "1.0",
"Implementation-Title": "Example Jenkins Plugin",
"Implementation-Version": "1.0-SNAPSHOT",
Main: pkg.KeyValues{
{Key: "Manifest-Version", Value: "1.0"},
{Key: "Created-By", Value: "Maven Archiver 3.6.0"},
{Key: "Build-Jdk-Spec", Value: "18"},
{Key: "Specification-Title", Value: "Example Jenkins Plugin"},
{Key: "Specification-Version", Value: "1.0"},
{Key: "Implementation-Title", Value: "Example Jenkins Plugin"},
{Key: "Implementation-Version", Value: "1.0-SNAPSHOT"},
{Key: "Group-Id", Value: "io.jenkins.plugins"},
{Key: "Short-Name", Value: "example-jenkins-plugin"},
{Key: "Long-Name", Value: "Example Jenkins Plugin"},
{Key: "Hudson-Version", Value: "2.204"},
{Key: "Jenkins-Version", Value: "2.204"},
{Key: "Plugin-Dependencies", Value: "structs:1.20"},
{Key: "Plugin-Developers", Value: ""},
{Key: "Plugin-License-Name", Value: "MIT License"},
{Key: "Plugin-License-Url", Value: "https://opensource.org/licenses/MIT"},
{Key: "Plugin-ScmUrl", Value: "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin"},
// extra fields...
//"Archiver-Version": "Plexus Archiver",
"Plugin-License-Url": "https://opensource.org/licenses/MIT",
"Plugin-License-Name": "MIT License",
"Created-By": "Maven Archiver 3.6.0",
//"Built-By": "?",
//"Build-Jdk": "14.0.1",
"Build-Jdk-Spec": "18",
"Jenkins-Version": "2.204",
//"Minimum-Java-Version": "1.8",
"Plugin-Developers": "",
"Plugin-ScmUrl": "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin",
//"Extension-Name": "example-jenkins-plugin",
"Short-Name": "example-jenkins-plugin",
"Group-Id": "io.jenkins.plugins",
"Plugin-Dependencies": "structs:1.20",
//"Plugin-Version": "1.0-SNAPSHOT (private-07/09/2020 13:30-?)",
"Hudson-Version": "2.204",
"Long-Name": "Example Jenkins Plugin",
//{Key: "Minimum-Java-Version", Value: "1.8"},
//{Key: "Archiver-Version", Value: "Plexus Archiver"},
//{Key: "Built-By", Value: "?"},
//{Key: "Build-Jdk", Value: "14.0.1"},
//{Key: "Extension-Name", Value: "example-jenkins-plugin"},
//{Key: "Plugin-Version", Value: "1.0-SNAPSHOT (private-07/09/2020 13:30-?)"},
},
},
PomProperties: &pkg.JavaPomProperties{
@@ -255,9 +256,15 @@ func TestParseJar(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-gradle-0.1.0.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Main-Class": "hello.HelloWorld",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
{
Key: "Main-Class",
Value: "hello.HelloWorld",
},
},
},
},
@@ -326,14 +333,32 @@ func TestParseJar(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
// extra fields...
"Archiver-Version": "Plexus Archiver",
"Created-By": "Apache Maven 3.8.6",
//"Built-By": "?",
//"Build-Jdk": "14.0.1",
"Main-Class": "hello.HelloWorld",
{
Key: "Archiver-Version",
Value: "Plexus Archiver",
},
{
Key: "Created-By",
Value: "Apache Maven 3.8.6",
},
//{
// Key: "Built-By",
// Value: "?",
//},
//{
// Key: "Build-Jdk",
// Value: "14.0.1",
//},
{
Key: "Main-Class",
Value: "hello.HelloWorld",
},
},
},
PomProperties: &pkg.JavaPomProperties{
@@ -455,7 +480,14 @@ func TestParseJar(t *testing.T) {
// ignore select fields (only works for the main section)
for _, field := range test.ignoreExtras {
if metadata.Manifest != nil && metadata.Manifest.Main != nil {
delete(metadata.Manifest.Main, field)
newMain := make(pkg.KeyValues, 0)
for i, kv := range metadata.Manifest.Main {
if kv.Key == field {
continue
}
newMain = append(newMain, metadata.Manifest.Main[i])
}
metadata.Manifest.Main = newMain
}
}
@@ -1158,32 +1190,32 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/jar-metadata/cache/jackson-core-2.15.2.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Build-Jdk-Spec": "1.8",
"Bundle-Description": "Core Jackson processing abstractions",
"Bundle-DocURL": "https://github.com/FasterXML/jackson-core",
"Bundle-License": "https://www.apache.org/licenses/LICENSE-2.0.txt",
"Bundle-ManifestVersion": "2",
"Bundle-Name": "Jackson-core",
"Bundle-SymbolicName": "com.fasterxml.jackson.core.jackson-core",
"Bundle-Vendor": "FasterXML",
"Bundle-Version": "2.15.2",
"Created-By": "Apache Maven Bundle Plugin 5.1.8",
"Export-Package": "com.fasterxml.jackson.core;version...snip",
"Implementation-Title": "Jackson-core",
"Implementation-Vendor": "FasterXML",
"Implementation-Vendor-Id": "com.fasterxml.jackson.core",
"Implementation-Version": "2.15.2",
"Import-Package": "com.fasterxml.jackson.core;version=...snip",
"Manifest-Version": "1.0",
"Multi-Release": "true",
"Require-Capability": `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`,
"Specification-Title": "Jackson-core",
"Specification-Vendor": "FasterXML",
"Specification-Version": "2.15.2",
"Tool": "Bnd-6.3.1.202206071316",
"X-Compile-Source-JDK": "1.8",
"X-Compile-Target-JDK": "1.8",
Main: pkg.KeyValues{
{Key: "Manifest-Version", Value: "1.0"},
{Key: "Bundle-License", Value: "https://www.apache.org/licenses/LICENSE-2.0.txt"},
{Key: "Bundle-SymbolicName", Value: "com.fasterxml.jackson.core.jackson-core"},
{Key: "Implementation-Vendor-Id", Value: "com.fasterxml.jackson.core"},
{Key: "Specification-Title", Value: "Jackson-core"},
{Key: "Bundle-DocURL", Value: "https://github.com/FasterXML/jackson-core"},
{Key: "Import-Package", Value: "com.fasterxml.jackson.core;version=...snip"},
{Key: "Require-Capability", Value: `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`},
{Key: "Export-Package", Value: "com.fasterxml.jackson.core;version...snip"},
{Key: "Bundle-Name", Value: "Jackson-core"},
{Key: "Multi-Release", Value: "true"},
{Key: "Build-Jdk-Spec", Value: "1.8"},
{Key: "Bundle-Description", Value: "Core Jackson processing abstractions"},
{Key: "Implementation-Title", Value: "Jackson-core"},
{Key: "Implementation-Version", Value: "2.15.2"},
{Key: "Bundle-ManifestVersion", Value: "2"},
{Key: "Specification-Vendor", Value: "FasterXML"},
{Key: "Bundle-Vendor", Value: "FasterXML"},
{Key: "Tool", Value: "Bnd-6.3.1.202206071316"},
{Key: "Implementation-Vendor", Value: "FasterXML"},
{Key: "Bundle-Version", Value: "2.15.2"},
{Key: "X-Compile-Target-JDK", Value: "1.8"},
{Key: "X-Compile-Source-JDK", Value: "1.8"},
{Key: "Created-By", Value: "Apache Maven Bundle Plugin 5.1.8"},
{Key: "Specification-Version", Value: "2.15.2"},
},
},
// not under test
@@ -1212,32 +1244,32 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/jar-metadata/cache/com.fasterxml.jackson.core.jackson-core-2.15.2.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Build-Jdk-Spec": "1.8",
"Bundle-Description": "Core Jackson processing abstractions",
"Bundle-DocURL": "https://github.com/FasterXML/jackson-core",
"Bundle-License": "https://www.apache.org/licenses/LICENSE-2.0.txt",
"Bundle-ManifestVersion": "2",
"Bundle-Name": "Jackson-core",
"Bundle-SymbolicName": "com.fasterxml.jackson.core.jackson-core",
"Bundle-Vendor": "FasterXML",
"Bundle-Version": "2.15.2",
"Created-By": "Apache Maven Bundle Plugin 5.1.8",
"Export-Package": "com.fasterxml.jackson.core;version...snip",
"Implementation-Title": "Jackson-core",
"Implementation-Vendor": "FasterXML",
"Implementation-Vendor-Id": "com.fasterxml.jackson.core",
"Implementation-Version": "2.15.2",
"Import-Package": "com.fasterxml.jackson.core;version=...snip",
"Manifest-Version": "1.0",
"Multi-Release": "true",
"Require-Capability": `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`,
"Specification-Title": "Jackson-core",
"Specification-Vendor": "FasterXML",
"Specification-Version": "2.15.2",
"Tool": "Bnd-6.3.1.202206071316",
"X-Compile-Source-JDK": "1.8",
"X-Compile-Target-JDK": "1.8",
Main: pkg.KeyValues{
{Key: "Manifest-Version", Value: "1.0"},
{Key: "Bundle-License", Value: "https://www.apache.org/licenses/LICENSE-2.0.txt"},
{Key: "Bundle-SymbolicName", Value: "com.fasterxml.jackson.core.jackson-core"},
{Key: "Implementation-Vendor-Id", Value: "com.fasterxml.jackson.core"},
{Key: "Specification-Title", Value: "Jackson-core"},
{Key: "Bundle-DocURL", Value: "https://github.com/FasterXML/jackson-core"},
{Key: "Import-Package", Value: "com.fasterxml.jackson.core;version=...snip"},
{Key: "Require-Capability", Value: `osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"`},
{Key: "Export-Package", Value: "com.fasterxml.jackson.core;version...snip"},
{Key: "Bundle-Name", Value: "Jackson-core"},
{Key: "Multi-Release", Value: "true"},
{Key: "Build-Jdk-Spec", Value: "1.8"},
{Key: "Bundle-Description", Value: "Core Jackson processing abstractions"},
{Key: "Implementation-Title", Value: "Jackson-core"},
{Key: "Implementation-Version", Value: "2.15.2"},
{Key: "Bundle-ManifestVersion", Value: "2"},
{Key: "Specification-Vendor", Value: "FasterXML"},
{Key: "Bundle-Vendor", Value: "FasterXML"},
{Key: "Tool", Value: "Bnd-6.3.1.202206071316"},
{Key: "Implementation-Vendor", Value: "FasterXML"},
{Key: "Bundle-Version", Value: "2.15.2"},
{Key: "X-Compile-Target-JDK", Value: "1.8"},
{Key: "X-Compile-Source-JDK", Value: "1.8"},
{Key: "Created-By", Value: "Apache Maven Bundle Plugin 5.1.8"},
{Key: "Specification-Version", Value: "2.15.2"},
},
},
// not under test
@@ -1261,11 +1293,23 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/jar-metadata/cache/api-all-2.0.0-sources.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Build-Jdk": "1.8.0_191",
"Built-By": "elecharny",
"Created-By": "Apache Maven 3.6.0",
"Manifest-Version": "1.0",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
{
Key: "Built-By",
Value: "elecharny",
},
{
Key: "Created-By",
Value: "Apache Maven 3.6.0",
},
{
Key: "Build-Jdk",
Value: "1.8.0_191",
},
},
},
PomProperties: &pkg.JavaPomProperties{
@@ -1314,10 +1358,25 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
if tt.assignParent {
assignParent(&tt.expectedPkgs[0], tt.expectedPkgs[1:]...)
}
for i := range tt.expectedPkgs {
tt.expectedPkgs[i].SetID()
}
pkgtest.NewCatalogTester().
FromFile(t, generateJavaMetadataJarFixture(t, tt.fixtureName)).
Expects(tt.expectedPkgs, tt.expectedRelationships).
WithCompareOptions(cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests")).
WithCompareOptions(
cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests"),
cmp.Comparer(func(x, y pkg.KeyValue) bool {
if x.Key != y.Key {
return false
}
if x.Value != y.Value {
return false
}
return true
}),
).
TestParser(t, gap.parseJavaArchive)
})
}
+25 -10
View File
@@ -24,8 +24,11 @@ func Test_packageURL(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
},
},
PomProperties: &pkg.JavaPomProperties{
@@ -49,8 +52,11 @@ func Test_packageURL(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
},
},
PomProperties: &pkg.JavaPomProperties{
@@ -74,8 +80,11 @@ func Test_packageURL(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
},
},
PomProperties: &pkg.JavaPomProperties{
@@ -101,8 +110,11 @@ func Test_packageURL(t *testing.T) {
Metadata: pkg.JavaArchive{
VirtualPath: "test-fixtures/java-builds/packages/example-java-app-maven-0.1.0.jar",
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
},
},
PomProperties: &pkg.JavaPomProperties{
@@ -163,8 +175,11 @@ func Test_groupIDFromJavaMetadata(t *testing.T) {
name: "java manifest",
metadata: pkg.JavaArchive{
Manifest: &pkg.JavaManifest{
Main: map[string]string{
"Implementation-Vendor": "org.anchore",
Main: []pkg.KeyValue{
{
Key: "Implementation-Vendor",
Value: "org.anchore",
},
},
},
},
+26 -35
View File
@@ -4,7 +4,6 @@ import (
"bufio"
"fmt"
"io"
"strconv"
"strings"
"unicode"
@@ -20,7 +19,7 @@ const manifestGlob = "/META-INF/MANIFEST.MF"
//nolint:funlen
func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error) {
var manifest pkg.JavaManifest
var sections []map[string]string
sections := make([]pkg.KeyValues, 0)
currentSection := func() int {
return len(sections) - 1
@@ -51,7 +50,9 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
continue
}
sections[currentSection()][lastKey] += strings.TrimSpace(line)
lastSection := sections[currentSection()]
sections[currentSection()][len(lastSection)-1].Value += strings.TrimSpace(line)
continue
}
@@ -73,10 +74,13 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
if lastKey == "" {
// we're entering a new section
sections = append(sections, make(map[string]string))
sections = append(sections, make(pkg.KeyValues, 0))
}
sections[currentSection()][key] = value
sections[currentSection()] = append(sections[currentSection()], pkg.KeyValue{
Key: key,
Value: value,
})
// keep track of key for potential future continuations
lastKey = key
@@ -89,20 +93,7 @@ func parseJavaManifest(path string, reader io.Reader) (*pkg.JavaManifest, error)
if len(sections) > 0 {
manifest.Main = sections[0]
if len(sections) > 1 {
manifest.NamedSections = make(map[string]map[string]string)
for i, s := range sections[1:] {
name, ok := s["Name"]
if !ok {
// per the manifest spec (https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#jar-manifest)
// this should never happen. If it does, we want to know about it, but not necessarily stop
// cataloging entirely... for this reason we only log.
log.Debugf("java manifest section found without a name: %s", path)
name = strconv.Itoa(i)
} else {
delete(s, "Name")
}
manifest.NamedSections[name] = s
}
manifest.Sections = sections[1:]
}
}
@@ -127,12 +118,12 @@ func extractNameFromApacheMavenBundlePlugin(manifest *pkg.JavaManifest) string {
// The computed symbolic name is also stored in the $(maven-symbolicname) property in case you want to add attributes or directives to it.
//
if manifest != nil {
if strings.Contains(manifest.Main["Created-By"], "Apache Maven Bundle Plugin") {
if symbolicName := manifest.Main["Bundle-SymbolicName"]; symbolicName != "" {
if strings.Contains(manifest.Main.MustGet("Created-By"), "Apache Maven Bundle Plugin") {
if symbolicName := manifest.Main.MustGet("Bundle-SymbolicName"); symbolicName != "" {
// It is possible that `Bundle-SymbolicName` is just the groupID (like in the case of
// https://repo1.maven.org/maven2/com/google/oauth-client/google-oauth-client/1.25.0/google-oauth-client-1.25.0.jar),
// so if `Implementation-Vendor-Id` is equal to `Bundle-SymbolicName`, bail on this logic
if vendorID := manifest.Main["Implementation-Vendor-Id"]; vendorID != "" && vendorID == symbolicName {
if vendorID := manifest.Main.MustGet("Implementation-Vendor-Id"); vendorID != "" && vendorID == symbolicName {
return ""
}
@@ -212,21 +203,21 @@ func selectName(manifest *pkg.JavaManifest, filenameObj archiveFilename) string
// remaining fields in the manifest is a bit of a free-for-all depending on the build tooling used and package maintainer preferences
if manifest != nil {
switch {
case manifest.Main["Name"] != "":
case manifest.Main.MustGet("Name") != "":
// Manifest original spec...
return manifest.Main["Name"]
case manifest.Main["Bundle-Name"] != "":
return manifest.Main.MustGet("Name")
case manifest.Main.MustGet("Bundle-Name") != "":
// BND tooling... TODO: this does not seem accurate (I don't see a reference in the BND tooling docs for this)
return manifest.Main["Bundle-Name"]
case manifest.Main["Short-Name"] != "":
return manifest.Main.MustGet("Bundle-Name")
case manifest.Main.MustGet("Short-Name") != "":
// Jenkins...
return manifest.Main["Short-Name"]
case manifest.Main["Extension-Name"] != "":
return manifest.Main.MustGet("Short-Name")
case manifest.Main.MustGet("Extension-Name") != "":
// Jenkins...
return manifest.Main["Extension-Name"]
case manifest.Main["Implementation-Title"] != "":
return manifest.Main.MustGet("Extension-Name")
case manifest.Main.MustGet("Implementation-Title") != "":
// last ditch effort...
return manifest.Main["Implementation-Title"]
return manifest.Main.MustGet("Implementation-Title")
}
}
return ""
@@ -278,12 +269,12 @@ func selectLicenses(manifest *pkg.JavaManifest) []string {
}
func fieldValueFromManifest(manifest pkg.JavaManifest, fieldName string) string {
if value := manifest.Main[fieldName]; value != "" {
if value := manifest.Main.MustGet(fieldName); value != "" {
return value
}
for _, section := range manifest.NamedSections {
if value := section[fieldName]; value != "" {
for _, section := range manifest.Sections {
if value := section.MustGet(fieldName); value != "" {
return value
}
}
@@ -19,41 +19,63 @@ func TestParseJavaManifest(t *testing.T) {
{
fixture: "test-fixtures/manifest/small",
expected: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
Main: pkg.KeyValues{
{Key: "Manifest-Version", Value: "1.0"},
},
},
},
{
fixture: "test-fixtures/manifest/standard-info",
expected: pkg.JavaManifest{
Main: map[string]string{
"Name": "the-best-name",
"Manifest-Version": "1.0",
"Specification-Title": "the-spec-title",
"Specification-Version": "the-spec-version",
"Specification-Vendor": "the-spec-vendor",
"Implementation-Title": "the-impl-title",
"Implementation-Version": "the-impl-version",
"Implementation-Vendor": "the-impl-vendor",
Main: pkg.KeyValues{
{Key: "Manifest-Version", Value: "1.0"},
{Key: "Name", Value: "the-best-name"},
{Key: "Specification-Title", Value: "the-spec-title"},
{Key: "Specification-Vendor", Value: "the-spec-vendor"},
{Key: "Specification-Version", Value: "the-spec-version"},
{Key: "Implementation-Title", Value: "the-impl-title"},
{Key: "Implementation-Vendor", Value: "the-impl-vendor"},
{Key: "Implementation-Version", Value: "the-impl-version"},
},
},
},
{
fixture: "test-fixtures/manifest/extra-info",
expected: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Archiver-Version": "Plexus Archiver",
"Created-By": "Apache Maven 3.6.3",
},
NamedSections: map[string]map[string]string{
"thing-1": {
"Built-By": "?",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
"1": {
"Build-Jdk": "14.0.1",
"Main-Class": "hello.HelloWorld",
{
Key: "Archiver-Version",
Value: "Plexus Archiver",
},
{
Key: "Created-By",
Value: "Apache Maven 3.6.3",
},
},
Sections: []pkg.KeyValues{
{
{
Key: "Name",
Value: "thing-1",
},
{
Key: "Built-By",
Value: "?",
},
},
{
{
Key: "Build-Jdk",
Value: "14.0.1",
},
{
Key: "Main-Class",
Value: "hello.HelloWorld",
},
},
},
},
@@ -61,23 +83,34 @@ func TestParseJavaManifest(t *testing.T) {
{
fixture: "test-fixtures/manifest/extra-empty-lines",
expected: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Archiver-Version": "Plexus Archiver",
"Created-By": "Apache Maven 3.6.3",
Main: pkg.KeyValues{
{
Key: "Manifest-Version",
Value: "1.0",
},
{
Key: "Archiver-Version",
Value: "Plexus Archiver",
},
{
Key: "Created-By",
Value: "Apache Maven 3.6.3",
},
},
NamedSections: map[string]map[string]string{
"thing-1": {
"Built-By": "?",
Sections: []pkg.KeyValues{
{
{Key: "Name", Value: "thing-1"},
{Key: "Built-By", Value: "?"},
},
"thing-2": {
"Built-By": "someone!",
{
{Key: "Name", Value: "thing-2"},
{Key: "Built-By", Value: "someone!"},
},
"2": {
"Other": "things",
{
{Key: "Other", Value: "things"},
},
"3": {
"Last": "item",
{
{Key: "Last", Value: "item"},
},
},
},
@@ -85,9 +118,15 @@ func TestParseJavaManifest(t *testing.T) {
{
fixture: "test-fixtures/manifest/continuation",
expected: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Plugin-ScmUrl": "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin",
Main: pkg.KeyValues{
{
Key: "Manifest-Version",
Value: "1.0",
},
{
Key: "Plugin-ScmUrl",
Value: "https://github.com/jenkinsci/plugin-pom/example-jenkins-plugin",
},
},
},
},
@@ -95,9 +134,15 @@ func TestParseJavaManifest(t *testing.T) {
// regression test, we should always keep the full version
fixture: "test-fixtures/manifest/version-with-date",
expected: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Implementation-Version": "1.3 2244 October 5 2005",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
{
Key: "Implementation-Version",
Value: "1.3 2244 October 5 2005",
},
},
},
},
@@ -106,9 +151,15 @@ func TestParseJavaManifest(t *testing.T) {
// https://github.com/anchore/syft/issues/2179
fixture: "test-fixtures/manifest/leading-space",
expected: pkg.JavaManifest{
Main: map[string]string{
"Key-keykeykey": "initialconfig:com$ # aka not empty line",
"should": "parse",
Main: []pkg.KeyValue{
{
Key: "Key-keykeykey",
Value: "initialconfig:com$ # aka not empty line",
},
{
Key: "should",
Value: "parse",
},
},
},
},
@@ -154,8 +205,11 @@ func TestSelectName(t *testing.T) {
desc: "Get name from Implementation-Title",
archive: archiveFilename{},
manifest: pkg.JavaManifest{
Main: map[string]string{
"Implementation-Title": "maven-wrapper",
Main: []pkg.KeyValue{
{
Key: "Implementation-Title",
Value: "maven-wrapper",
},
},
},
expected: "maven-wrapper",
@@ -163,9 +217,15 @@ func TestSelectName(t *testing.T) {
{
desc: "Implementation-Title does not override name from filename",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Name": "foo",
"Implementation-Title": "maven-wrapper",
Main: []pkg.KeyValue{
{
Key: "Name",
Value: "foo",
},
{
Key: "Implementation-Title",
Value: "maven-wrapper",
},
},
},
archive: newJavaArchiveFilename("/something/omg.jar"),
@@ -174,11 +234,11 @@ func TestSelectName(t *testing.T) {
{
desc: "Use the artifact ID baked by the Apache Maven Bundle Plugin",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Created-By": "Apache Maven Bundle Plugin",
"Bundle-SymbolicName": "com.atlassian.gadgets.atlassian-gadgets-api",
"Name": "foo",
"Implementation-Title": "maven-wrapper",
Main: pkg.KeyValues{
{Key: "Created-By", Value: "Apache Maven Bundle Plugin"},
{Key: "Bundle-SymbolicName", Value: "com.atlassian.gadgets.atlassian-gadgets-api"},
{Key: "Name", Value: "foo"},
{Key: "Implementation-Title", Value: "maven-wrapper"},
},
},
archive: newJavaArchiveFilename("/something/omg.jar"),
@@ -188,11 +248,11 @@ func TestSelectName(t *testing.T) {
// example: pkg:maven/org.apache.servicemix.bundles/org.apache.servicemix.bundles.spring-beans@5.3.26_1
desc: "Apache Maven Bundle Plugin might bake a version in the created-by field",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Created-By": "Apache Maven Bundle Plugin 5.1.6",
"Bundle-SymbolicName": "com.atlassian.gadgets.atlassian-gadgets-api",
"Name": "foo",
"Implementation-Title": "maven-wrapper",
Main: pkg.KeyValues{
{Key: "Created-By", Value: "Apache Maven Bundle Plugin 5.1.6"},
{Key: "Bundle-SymbolicName", Value: "com.atlassian.gadgets.atlassian-gadgets-api"},
{Key: "Name", Value: "foo"},
{Key: "Implementation-Title", Value: "maven-wrapper"},
},
},
archive: newJavaArchiveFilename("/something/omg.jar"),
@@ -201,9 +261,15 @@ func TestSelectName(t *testing.T) {
{
desc: "Filename looks like a groupid + artifact id",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Name": "foo",
"Implementation-Title": "maven-wrapper",
Main: []pkg.KeyValue{
{
Key: "Name",
Value: "foo",
},
{
Key: "Implementation-Title",
Value: "maven-wrapper",
},
},
},
archive: newJavaArchiveFilename("/something/com.atlassian.gadgets.atlassian-gadgets-api.jar"),
@@ -228,8 +294,11 @@ func TestSelectName(t *testing.T) {
{
desc: "Skip stripping groupId prefix from archive filename for org.eclipse",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Automatic-Module-Name": "org.eclipse.ant.core",
Main: []pkg.KeyValue{
{
Key: "Automatic-Module-Name",
Value: "org.eclipse.ant.core",
},
},
},
archive: newJavaArchiveFilename("/something/org.eclipse.ant.core-3.7.0.jar"),
@@ -239,21 +308,21 @@ func TestSelectName(t *testing.T) {
// example: pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0
desc: "skip Apache Maven Bundle Plugin logic if symbolic name is same as vendor id",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Bundle-DocURL": "http://www.google.com/",
"Bundle-License": "http://www.apache.org/licenses/LICENSE-2.0.txt",
"Bundle-ManifestVersion": "2",
"Bundle-Name": "Google OAuth Client Library for Java",
"Bundle-RequiredExecutionEnvironment": "JavaSE-1.6",
"Bundle-SymbolicName": "com.google.oauth-client",
"Bundle-Vendor": "Google",
"Bundle-Version": "1.25.0",
"Created-By": "Apache Maven Bundle Plugin",
"Export-Package": "com.google.api.client.auth.openidconnect;uses:=\"com.google.api.client.auth.oauth2,com.google.api.client.json,com.google.api.client.json.webtoken,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth;uses:=\"com.google.api.client.http,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth2;uses:=\"com.google.api.client.http,com.google.api.client.json,com.google.api.client.util,com.google.api.client.util.store\";version=\"1.25.0\"",
"Implementation-Title": "Google OAuth Client Library for Java",
"Implementation-Vendor": "Google",
"Implementation-Vendor-Id": "com.google.oauth-client",
"Implementation-Version": "1.25.0",
Main: pkg.KeyValues{
{Key: "Bundle-DocURL", Value: "http://www.google.com/"},
{Key: "Bundle-License", Value: "http://www.apache.org/licenses/LICENSE-2.0.txt"},
{Key: "Bundle-ManifestVersion", Value: "2"},
{Key: "Bundle-Name", Value: "Google OAuth Client Library for Java"},
{Key: "Bundle-RequiredExecutionEnvironment", Value: "JavaSE-1.6"},
{Key: "Bundle-SymbolicName", Value: "com.google.oauth-client"},
{Key: "Bundle-Vendor", Value: "Google"},
{Key: "Bundle-Version", Value: "1.25.0"},
{Key: "Created-By", Value: "Apache Maven Bundle Plugin"},
{Key: "Export-Package", Value: "com.google.api.client.auth.openidconnect;uses:=\"com.google.api.client.auth.oauth2,com.google.api.client.json,com.google.api.client.json.webtoken,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth;uses:=\"com.google.api.client.http,com.google.api.client.util\";version=\"1.25.0\",com.google.api.client.auth.oauth2;uses:=\"com.google.api.client.http,com.google.api.client.json,com.google.api.client.util,com.google.api.client.util.store\";version=\"1.25.0\""},
{Key: "Implementation-Title", Value: "Google OAuth Client Library for Java"},
{Key: "Implementation-Vendor", Value: "Google"},
{Key: "Implementation-Vendor-Id", Value: "com.google.oauth-client"},
{Key: "Implementation-Version", Value: "1.25.0"},
},
},
archive: newJavaArchiveFilename("/something/google-oauth-client-1.25.0.jar"),
@@ -283,8 +352,11 @@ func TestSelectVersion(t *testing.T) {
name: "Get name from Implementation-Version",
archive: archiveFilename{},
manifest: pkg.JavaManifest{
Main: map[string]string{
"Implementation-Version": "1.8.2",
Main: []pkg.KeyValue{
{
Key: "Implementation-Version",
Value: "1.8.2",
},
},
},
expected: "1.8.2",
@@ -292,9 +364,15 @@ func TestSelectVersion(t *testing.T) {
{
name: "Implementation-Version takes precedence over Specification-Version",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Implementation-Version": "1.8.2",
"Specification-Version": "1.0",
Main: []pkg.KeyValue{
{
Key: "Implementation-Version",
Value: "1.8.2",
},
{
Key: "Specification-Version",
Value: "1.0",
},
},
},
expected: "1.8.2",
@@ -302,14 +380,15 @@ func TestSelectVersion(t *testing.T) {
{
name: "Implementation-Version found outside the main section",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Ant-Version": "Apache Ant 1.8.2",
"Created-By": "1.5.0_22-b03 (Sun Microsystems Inc.)",
Main: pkg.KeyValues{
{Key: "Manifest-Version", Value: "1.0"},
{Key: "Ant-Version", Value: "Apache Ant 1.8.2"},
{Key: "Created-By", Value: "1.5.0_22-b03 (Sun Microsystems Inc.)"},
},
NamedSections: map[string]map[string]string{
"org/apache/tools/ant/taskdefs/optional/": {
"Implementation-Version": "1.8.2",
Sections: []pkg.KeyValues{
{
{Key: "Name", Value: "org/apache/tools/ant/taskdefs/optional/"},
{Key: "Implementation-Version", Value: "1.8.2"},
},
},
},
@@ -318,34 +397,53 @@ func TestSelectVersion(t *testing.T) {
{
name: "Implementation-Version takes precedence over Specification-Version in subsequent section",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Ant-Version": "Apache Ant 1.8.2",
"Created-By": "1.5.0_22-b03 (Sun Microsystems Inc.)",
"Specification-Version": "2.0",
Main: pkg.KeyValues{
{Key: "Manifest-Version", Value: "1.0"},
{Key: "Ant-Version", Value: "Apache Ant 1.8.2"},
{Key: "Created-By", Value: "1.5.0_22-b03 (Sun Microsystems Inc.)"},
{Key: "Specification-Version", Value: "2.0"},
},
NamedSections: map[string]map[string]string{
"org/apache/tools/ant/taskdefs/optional/": {
"Specification-Version": "1.8",
Sections: []pkg.KeyValues{
{
{Key: "Name", Value: "org/apache/tools/ant/taskdefs/optional/"},
{Key: "Specification-Version", Value: "1.8"},
},
"some-other-section": {
"Implementation-Version": "1.8.2",
{
{Key: "Name", Value: "some-other-section"},
{Key: "Implementation-Version", Value: "1.8.2"},
},
},
},
expected: "1.8.2",
},
{
name: "Implementation-Version takes precedence over Specification-Version in subsequent section",
manifest: pkg.JavaManifest{
Main: map[string]string{
"Manifest-Version": "1.0",
"Ant-Version": "Apache Ant 1.8.2",
"Created-By": "1.5.0_22-b03 (Sun Microsystems Inc.)",
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
{
Key: "Ant-Version",
Value: "Apache Ant 1.8.2",
},
{
Key: "Created-By",
Value: "1.5.0_22-b03 (Sun Microsystems Inc.)",
},
},
NamedSections: map[string]map[string]string{
"some-other-section": {
"Bundle-Version": "1.11.28",
Sections: []pkg.KeyValues{
{
{
Key: "Name",
Value: "some-other-section",
},
{
Key: "Bundle-Version",
Value: "1.11.28",
},
},
},
},