Skip to main content

provenant/parsers/maven/
mod.rs

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