github.com/anchore/syft@v1.38.2/syft/pkg/java.go (about) 1 package pkg 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "sort" 7 "strings" 8 9 "github.com/anchore/syft/internal" 10 "github.com/anchore/syft/syft/file" 11 ) 12 13 var jenkinsPluginPomPropertiesGroupIDs = []string{ 14 "io.jenkins.plugins", 15 "org.jenkins.plugins", 16 "org.jenkins-ci.plugins", 17 "io.jenkins-ci.plugins", 18 "com.cloudbees.jenkins.plugins", 19 } 20 21 // JavaVMInstallation represents a Java Virtual Machine installation discovered on the system with its release information and file list. 22 type JavaVMInstallation struct { 23 // Release is JVM release information and version details 24 Release JavaVMRelease `json:"release"` 25 26 // Files are the list of files that are part of this JVM installation 27 Files []string `json:"files"` 28 } 29 30 func (m JavaVMInstallation) OwnedFiles() []string { 31 return m.Files 32 } 33 34 // JavaVMRelease represents JVM version and build information extracted from the release file in a Java installation. 35 type JavaVMRelease struct { 36 // Implementor is extracted with the `java.vendor` JVM property 37 Implementor string `mapstructure:"IMPLEMENTOR,omitempty" json:"implementor,omitempty"` 38 39 // ImplementorVersion is extracted with the `java.vendor.version` JVM property 40 ImplementorVersion string `mapstructure:"IMPLEMENTOR_VERSION,omitempty" json:"implementorVersion,omitempty"` 41 42 // JavaRuntimeVersion is extracted from the 'java.runtime.version' JVM property 43 JavaRuntimeVersion string `mapstructure:"JAVA_RUNTIME_VERSION,omitempty" json:"javaRuntimeVersion,omitempty"` 44 45 // JavaVersion matches that from `java -version` command output 46 JavaVersion string `mapstructure:"JAVA_VERSION,omitempty" json:"javaVersion,omitempty"` 47 48 // JavaVersionDate is extracted from the 'java.version.date' JVM property 49 JavaVersionDate string `mapstructure:"JAVA_VERSION_DATE,omitempty" json:"javaVersionDate,omitempty"` 50 51 // Libc can either be 'glibc' or 'musl' 52 Libc string `mapstructure:"LIBC,omitempty" json:"libc,omitempty"` 53 54 // Modules is a list of JVM modules that are packaged 55 Modules []string `mapstructure:"MODULES,omitempty" json:"modules,omitempty"` 56 57 // OsArch is the target CPU architecture 58 OsArch string `mapstructure:"OS_ARCH,omitempty" json:"osArch,omitempty"` 59 60 // OsName is the name of the target runtime operating system environment 61 OsName string `mapstructure:"OS_NAME,omitempty" json:"osName,omitempty"` 62 63 // OsVersion is the version of the target runtime operating system environment 64 OsVersion string `mapstructure:"OS_VERSION,omitempty" json:"osVersion,omitempty"` 65 66 // Source refers to the origin repository of OpenJDK source 67 Source string `mapstructure:"SOURCE,omitempty" json:"source,omitempty"` 68 69 // BuildSource Git SHA of the build repository 70 BuildSource string `mapstructure:"BUILD_SOURCE,omitempty" json:"buildSource,omitempty"` 71 72 // BuildSourceRepo refers to rhe repository URL for the build source 73 BuildSourceRepo string `mapstructure:"BUILD_SOURCE_REPO,omitempty" json:"buildSourceRepo,omitempty"` 74 75 // SourceRepo refers to the OpenJDK repository URL 76 SourceRepo string `mapstructure:"SOURCE_REPO,omitempty" json:"sourceRepo,omitempty"` 77 78 // FullVersion is extracted from the 'java.runtime.version' JVM property 79 FullVersion string `mapstructure:"FULL_VERSION,omitempty" json:"fullVersion,omitempty"` 80 81 // SemanticVersion is derived from the OpenJDK version 82 SemanticVersion string `mapstructure:"SEMANTIC_VERSION,omitempty" json:"semanticVersion,omitempty"` 83 84 // BuildInfo contains additional build information 85 BuildInfo string `mapstructure:"BUILD_INFO,omitempty" json:"buildInfo,omitempty"` 86 87 // JvmVariant specifies the JVM variant (e.g., Hotspot or OpenJ9) 88 JvmVariant string `mapstructure:"JVM_VARIANT,omitempty" json:"jvmVariant,omitempty"` 89 90 // JvmVersion is extracted from the 'java.vm.version' JVM property 91 JvmVersion string `mapstructure:"JVM_VERSION,omitempty" json:"jvmVersion,omitempty"` 92 93 // ImageType can be 'JDK' or 'JRE' 94 ImageType string `mapstructure:"IMAGE_TYPE,omitempty" json:"imageType,omitempty"` 95 96 // BuildType can be 'commercial' (used in some older oracle JDK distributions) 97 BuildType string `mapstructure:"BUILD_TYPE,omitempty" json:"buildType,omitempty"` 98 } 99 100 // JavaArchive encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship. 101 type JavaArchive struct { 102 // VirtualPath is path within the archive hierarchy, where nested entries are delimited with ':' (for nested JARs) 103 VirtualPath string `json:"virtualPath" cyclonedx:"virtualPath"` 104 105 // Manifest is parsed META-INF/MANIFEST.MF contents 106 Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"` 107 108 // PomProperties is parsed pom.properties file contents 109 PomProperties *JavaPomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty" cyclonedx:"-"` 110 111 // PomProject is parsed pom.xml file contents 112 PomProject *JavaPomProject `mapstructure:"PomProject" json:"pomProject,omitempty"` 113 114 // ArchiveDigests is cryptographic hashes of the archive file 115 ArchiveDigests []file.Digest `hash:"ignore" json:"digest,omitempty"` 116 117 // Parent is reference to parent package (for nested archives) 118 Parent *Package `hash:"ignore" json:"-"` 119 } 120 121 // JavaPomProperties represents the fields of interest extracted from a Java archive's pom.properties file. 122 type JavaPomProperties struct { 123 // Path is path to the pom.properties file within the archive 124 Path string `mapstructure:"path" json:"path"` 125 126 // Name is the project name 127 Name string `mapstructure:"name" json:"name"` 128 129 // GroupID is Maven group identifier uniquely identifying the project across all projects (follows reversed domain name convention like com.company.project) 130 GroupID string `mapstructure:"groupId" json:"groupId" cyclonedx:"groupID"` 131 132 // ArtifactID is Maven artifact identifier, the name of the jar/artifact (unique within the groupId scope) 133 ArtifactID string `mapstructure:"artifactId" json:"artifactId" cyclonedx:"artifactID"` 134 135 // Version is artifact version 136 Version string `mapstructure:"version" json:"version"` 137 138 // Scope is dependency scope determining when dependency is available (compile=default all phases, test=test compilation/execution only, runtime=runtime and test not compile, provided=expected from JDK or container) 139 Scope string `mapstructure:"scope" json:"scope,omitempty"` 140 141 // Extra is additional custom properties not in standard Maven coordinates 142 Extra map[string]string `mapstructure:",remain" json:"extraFields,omitempty"` 143 } 144 145 // JavaPomProject represents fields of interest extracted from a Java archive's pom.xml file. See https://maven.apache.org/ref/3.6.3/maven-model/maven.html for more details. 146 type JavaPomProject struct { 147 // Path is path to the pom.xml file within the archive 148 Path string `json:"path"` 149 150 // Parent is the parent POM reference for inheritance (child POMs inherit configuration from parent) 151 Parent *JavaPomParent `json:"parent,omitempty"` 152 153 // GroupID is Maven group identifier (reversed domain name like org.apache.maven) 154 GroupID string `json:"groupId"` 155 156 // ArtifactID is Maven artifact identifier (project name) 157 ArtifactID string `json:"artifactId"` 158 159 // Version is project version (together with groupId and artifactId forms Maven coordinates groupId:artifactId:version) 160 Version string `json:"version"` 161 162 // Name is a human-readable project name (displayed in Maven-generated documentation) 163 Name string `json:"name"` 164 165 // Description is detailed project description 166 Description string `json:"description,omitempty"` 167 168 // URL is the project URL (typically project website or repository) 169 URL string `json:"url,omitempty"` 170 } 171 172 // JavaPomParent contains the fields within the <parent> tag in a pom.xml file 173 type JavaPomParent struct { 174 // GroupID is the parent Maven group identifier 175 GroupID string `json:"groupId"` 176 177 // ArtifactID is the parent Maven artifact identifier 178 ArtifactID string `json:"artifactId"` 179 180 // Version is the parent version (child inherits configuration from this specific version of parent POM) 181 Version string `json:"version"` 182 } 183 184 // PkgTypeIndicated returns the package Type indicated by the data contained in the JavaPomProperties. 185 func (p JavaPomProperties) PkgTypeIndicated() Type { 186 if internal.HasAnyOfPrefixes(p.GroupID, jenkinsPluginPomPropertiesGroupIDs...) || strings.Contains(p.GroupID, ".jenkins.plugin") { 187 return JenkinsPluginPkg 188 } 189 190 return JavaPkg 191 } 192 193 // JavaManifest represents the fields of interest extracted from a Java archive's META-INF/MANIFEST.MF file. 194 type JavaManifest struct { 195 // Main is main manifest attributes as key-value pairs 196 Main KeyValues `json:"main,omitempty"` 197 198 // Sections are the named sections from the manifest (e.g. per-entry attributes) 199 Sections []KeyValues `json:"sections,omitempty"` 200 } 201 202 type unmarshalJavaManifest JavaManifest 203 204 type legacyJavaManifest struct { 205 Main map[string]string `json:"main"` 206 NamedSections map[string]map[string]string `json:"namedSections"` 207 } 208 209 func (m *JavaManifest) UnmarshalJSON(b []byte) error { 210 var either map[string]any 211 err := json.Unmarshal(b, &either) 212 if err != nil { 213 return fmt.Errorf("could not unmarshal java manifest: %w", err) 214 } 215 if _, ok := either["namedSections"]; ok { 216 var lm legacyJavaManifest 217 if err = json.Unmarshal(b, &lm); err != nil { 218 return fmt.Errorf("could not unmarshal java manifest: %w", err) 219 } 220 *m = lm.toNewManifest() 221 return nil 222 } 223 var jm unmarshalJavaManifest 224 err = json.Unmarshal(b, &jm) 225 if err != nil { 226 return fmt.Errorf("could not unmarshal java manifest: %w", err) 227 } 228 *m = JavaManifest(jm) 229 return nil 230 } 231 232 func (lm legacyJavaManifest) toNewManifest() JavaManifest { 233 var result JavaManifest 234 result.Main = keyValuesFromMap(lm.Main) 235 var sectionNames []string 236 for k := range lm.NamedSections { 237 sectionNames = append(sectionNames, k) 238 } 239 sort.Strings(sectionNames) 240 var sections []KeyValues 241 for _, name := range sectionNames { 242 section := KeyValues{ 243 KeyValue{ 244 Key: "Name", 245 Value: name, 246 }, 247 } 248 section = append(section, keyValuesFromMap(lm.NamedSections[name])...) 249 sections = append(sections, section) 250 } 251 result.Sections = sections 252 return result 253 } 254 255 func (m JavaManifest) Section(name string) KeyValues { 256 for _, section := range m.Sections { 257 if sectionName, ok := section.Get("Name"); ok && sectionName == name { 258 return section 259 } 260 } 261 return nil 262 }