Skip to main content

provenant/parsers/maven/
mod.rs

1// SPDX-FileCopyrightText: nexB Inc. and others
2// ScanCode is a trademark of nexB Inc.
3// SPDX-FileCopyrightText: Provenant contributors
4// SPDX-License-Identifier: Apache-2.0
5// Derived from ScanCode Toolkit (Apache-2.0); modified. See NOTICE.
6
7//! Parser for Apache Maven pom.xml files.
8//!
9//! Extracts package metadata, dependencies, and license information from
10//! Maven Project Object Model (POM) files.
11//!
12//! # Supported Formats
13//! - pom.xml (Project Object Model)
14//! - pom.properties
15//! - MANIFEST.MF (JAR manifest)
16//!
17//! # Key Features
18//! - Property value substitution (`${project.version}`)
19//! - `is_pinned` analysis (exact version vs ranges like `[1.0,2.0)`)
20//! - Dependency scope handling (compile, test, provided, runtime, system)
21//! - Package URL (purl) generation
22//! - Multiple license support (combined with " OR ")
23
24mod coordinates;
25mod jar;
26mod manifest;
27mod pom;
28mod properties;
29
30pub use self::jar::{JvmArchiveKind, extract_jvm_archive};
31
32#[cfg(test)]
33mod jar_scan_test;
34#[cfg(test)]
35mod jar_test;
36#[cfg(test)]
37mod manifest_test;
38#[cfg(test)]
39mod pom_test;
40#[cfg(test)]
41mod properties_test;
42#[cfg(test)]
43mod scan_test;
44
45use self::{manifest::parse_manifest_mf, pom::parse_pom_xml, properties::parse_pom_properties};
46use super::PackageParser;
47use super::metadata::ParserMetadata;
48use crate::models::{DatasourceId, PackageData, PackageType};
49use std::path::Path;
50
51/// Maven package parser supporting pom.xml, pom.properties, and MANIFEST.MF files.
52pub struct MavenParser;
53
54impl PackageParser for MavenParser {
55    const PACKAGE_TYPE: PackageType = PackageType::Maven;
56
57    fn metadata() -> Vec<ParserMetadata> {
58        vec![ParserMetadata {
59            description: "Apache Maven POM",
60            file_patterns: &[
61                "**/*.pom",
62                "**/pom.xml",
63                "**/pom.properties",
64                "**/META-INF/MANIFEST.MF",
65            ],
66            package_type: "maven",
67            primary_language: "Java",
68            documentation_url: Some("https://maven.apache.org/pom.html"),
69        }]
70    }
71
72    fn extract_packages(path: &Path) -> Vec<PackageData> {
73        if let Some(filename) = path.file_name().and_then(|name| name.to_str()) {
74            if filename == "pom.properties" {
75                return vec![parse_pom_properties(path)];
76            }
77            if filename == "MANIFEST.MF" {
78                return vec![parse_manifest_mf(path)];
79            }
80        }
81
82        parse_pom_xml(path)
83    }
84
85    fn is_match(path: &Path) -> bool {
86        if let Some(filename) = path.file_name().and_then(|name| name.to_str()) {
87            filename == "pom.xml"
88                || filename.ends_with(".pom.xml")
89                || filename.ends_with("-pom.xml")
90                || filename.ends_with("_pom.xml")
91                || filename == "pom.properties"
92                || filename == "MANIFEST.MF"
93                || filename.ends_with(".pom")
94        } else {
95            false
96        }
97    }
98}
99
100fn default_package_data(datasource_id: DatasourceId) -> PackageData {
101    PackageData {
102        package_type: Some(PackageType::Maven),
103        datasource_id: Some(datasource_id),
104        ..Default::default()
105    }
106}