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 manifest;
25mod pom;
26mod properties;
27
28#[cfg(test)]
29mod manifest_test;
30#[cfg(test)]
31mod pom_test;
32#[cfg(test)]
33mod properties_test;
34#[cfg(test)]
35mod scan_test;
36
37use self::{manifest::parse_manifest_mf, pom::parse_pom_xml, properties::parse_pom_properties};
38use super::PackageParser;
39use super::metadata::ParserMetadata;
40use crate::models::{DatasourceId, PackageData, PackageType};
41use std::path::Path;
42
43/// Maven package parser supporting pom.xml, pom.properties, and MANIFEST.MF files.
44pub struct MavenParser;
45
46impl PackageParser for MavenParser {
47    const PACKAGE_TYPE: PackageType = PackageType::Maven;
48
49    fn metadata() -> Vec<ParserMetadata> {
50        vec![ParserMetadata {
51            description: "Apache Maven POM",
52            file_patterns: &[
53                "**/*.pom",
54                "**/pom.xml",
55                "**/pom.properties",
56                "**/META-INF/MANIFEST.MF",
57            ],
58            package_type: "maven",
59            primary_language: "Java",
60            documentation_url: Some("https://maven.apache.org/pom.html"),
61        }]
62    }
63
64    fn extract_packages(path: &Path) -> Vec<PackageData> {
65        if let Some(filename) = path.file_name().and_then(|name| name.to_str()) {
66            if filename == "pom.properties" {
67                return vec![parse_pom_properties(path)];
68            }
69            if filename == "MANIFEST.MF" {
70                return vec![parse_manifest_mf(path)];
71            }
72        }
73
74        parse_pom_xml(path)
75    }
76
77    fn is_match(path: &Path) -> bool {
78        if let Some(filename) = path.file_name().and_then(|name| name.to_str()) {
79            filename == "pom.xml"
80                || filename.ends_with(".pom.xml")
81                || filename.ends_with("-pom.xml")
82                || filename.ends_with("_pom.xml")
83                || filename == "pom.properties"
84                || filename == "MANIFEST.MF"
85                || filename.ends_with(".pom")
86        } else {
87            false
88        }
89    }
90}
91
92fn default_package_data(datasource_id: DatasourceId) -> PackageData {
93    PackageData {
94        package_type: Some(PackageType::Maven),
95        datasource_id: Some(datasource_id),
96        ..Default::default()
97    }
98}