Files
syft/syft/pkg/cataloger/java/package_url.go
T
2024-05-01 18:04:02 +00:00

146 lines
4.1 KiB
Go

package java
import (
"strings"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/cpegenerate"
)
// PackageURL returns the PURL for the specific java package (see https://github.com/package-url/purl-spec)
func packageURL(name, version string, metadata pkg.JavaArchive) string {
var groupID = name
if gID := groupIDFromJavaMetadata(name, metadata); gID != "" {
groupID = gID
}
pURL := packageurl.NewPackageURL(
packageurl.TypeMaven, // TODO: should we filter down by package types here?
groupID,
name,
version,
nil, // TODO: there are probably several qualifiers that can be specified here
"")
return pURL.ToString()
}
// groupIDFromJavaMetadata returns the authoritative group ID for a Java package.
// The order of precedence is:
// 1. The group ID from the POM properties
// 2. The group ID from the POM project
// 3. The group ID from a select map of known group IDs
// 4. The group ID from the Java manifest
func groupIDFromJavaMetadata(pkgName string, metadata pkg.JavaArchive) (groupID string) {
if groupID = groupIDFromPomProperties(metadata.PomProperties); groupID != "" {
return groupID
}
if groupID = groupIDFromPomProject(metadata.PomProject); groupID != "" {
return groupID
}
if groupID = groupIDFromKnownPackageList(pkgName); groupID != "" {
return groupID
}
if groupID = groupIDFromJavaManifest(metadata.Manifest); groupID != "" {
return groupID
}
return groupID
}
func groupIDFromKnownPackageList(pkgName string) (groupID string) {
if groupID, ok := cpegenerate.DefaultArtifactIDToGroupID[pkgName]; ok {
return groupID
}
return groupID
}
func groupIDFromJavaManifest(manifest *pkg.JavaManifest) (groupID string) {
if manifest == nil {
return groupID
}
groupIDs := cpegenerate.GetManifestFieldGroupIDs(manifest, cpegenerate.PrimaryJavaManifestGroupIDFields)
// assumes that primaryJavaManifestNameFields are ordered by priority
if len(groupIDs) != 0 {
return groupIDs[0]
}
groupIDs = cpegenerate.GetManifestFieldGroupIDs(manifest, cpegenerate.SecondaryJavaManifestGroupIDFields)
if len(groupIDs) != 0 {
return groupIDs[0]
}
return groupID
}
func groupIDFromPomProperties(properties *pkg.JavaPomProperties) (groupID string) {
if properties == nil {
return groupID
}
if properties.GroupID != "" {
return cleanGroupID(properties.GroupID)
}
// sometimes the publisher puts the group ID in the artifact ID field unintentionally
if looksLikeGroupID(properties.ArtifactID) {
// there is a strong indication that the artifact ID is really a group ID
return cleanGroupID(properties.ArtifactID)
}
return groupID
}
func groupIDFromPomProject(project *pkg.JavaPomProject) (groupID string) {
if project == nil {
return groupID
}
// check the project details
if project.GroupID != "" {
return cleanGroupID(project.GroupID)
}
// sometimes the publisher puts the group ID in the artifact ID field unintentionally
if looksLikeGroupID(project.ArtifactID) {
// there is a strong indication that the artifact ID is really a group ID
return cleanGroupID(project.ArtifactID)
}
// let's check the parent details
// if the current project does not have a group ID, but the parent does, we'll use the parent's group ID
if project.Parent != nil {
if project.Parent.GroupID != "" {
return cleanGroupID(project.Parent.GroupID)
}
// sometimes the publisher puts the group ID in the artifact ID field unintentionally
if looksLikeGroupID(project.Parent.ArtifactID) {
// there is a strong indication that the artifact ID is really a group ID
return cleanGroupID(project.Parent.ArtifactID)
}
}
return groupID
}
func looksLikeGroupID(value string) bool {
return strings.Contains(value, ".")
}
func cleanGroupID(groupID string) string {
return strings.TrimSpace(removeOSCIDirectives(groupID))
}
func removeOSCIDirectives(groupID string) string {
// for example:
// org.bar;uses:=“org.foo” -> org.bar
// more about OSGI directives see https://spring.io/blog/2008/10/20/understanding-the-osgi-uses-directive/
return strings.Split(groupID, ";")[0]
}