mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
146 lines
4.0 KiB
Go
146 lines
4.0 KiB
Go
package java
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/anchore/packageurl-go"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe"
|
|
)
|
|
|
|
// PackageURL returns the PURL for the specific java package (see https://github.com/package-url/purl-spec)
|
|
func packageURL(name, version string, metadata pkg.JavaMetadata) 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()
|
|
}
|
|
|
|
// GroupIDFromJavaPackage 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.JavaMetadata) (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, pkgName); groupID != "" {
|
|
return groupID
|
|
}
|
|
|
|
return groupID
|
|
}
|
|
|
|
func groupIDFromKnownPackageList(pkgName string) (groupID string) {
|
|
if groupID, ok := cpe.DefaultArtifactIDToGroupID[pkgName]; ok {
|
|
return groupID
|
|
}
|
|
return groupID
|
|
}
|
|
|
|
func groupIDFromJavaManifest(manifest *pkg.JavaManifest, pkgName string) (groupID string) {
|
|
if manifest == nil {
|
|
return groupID
|
|
}
|
|
|
|
groupIDS := cpe.GetManifestFieldGroupIDs(manifest, cpe.PrimaryJavaManifestGroupIDFields, pkgName)
|
|
// assumes that primaryJavaManifestNameFields are ordered by priority
|
|
if len(groupIDS) != 0 {
|
|
return groupIDS[0]
|
|
}
|
|
|
|
groupIDS = cpe.GetManifestFieldGroupIDs(manifest, cpe.SecondaryJavaManifestGroupIDFields, pkgName)
|
|
|
|
if len(groupIDS) != 0 {
|
|
return groupIDS[0]
|
|
}
|
|
|
|
return groupID
|
|
}
|
|
|
|
func groupIDFromPomProperties(properties *pkg.PomProperties) (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.PomProject) (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]
|
|
}
|