1use crate::*;
2pub struct DefaultUrlFetcher {}
3
4impl UrlFetcher for DefaultUrlFetcher {
5 fn fetch(&self, url: &str) -> Result<String, ResolverError> {
6 let text = ureq::get(url.into())
7 .call()
8 .map_err(|_| ResolverError::file_not_found(url))?
9 .into_string();
10 Ok(text.unwrap())
11 }
12 fn fetch_bytes(&self, url: &str) -> Result<bytes::Bytes, ResolverError> {
13 let mut data = vec![];
14 ureq::get(url.into())
15 .call()
16 .map_err(|_| ResolverError::file_not_found(url))?
17 .into_reader()
18 .read_to_end(&mut data)
19 .unwrap();
20 Ok(data.into())
21 }
22}
23
24fn node<'a, 'input: 'a>(
25 parent: &'input roxmltree::Node,
26 tag_name: &'a str,
27) -> Option<roxmltree::Node<'a, 'input>> {
28 parent
29 .children()
30 .find(|child| child.is_element() && child.has_tag_name(tag_name))
31}
32
33fn node_text<'a, 'input: 'a>(parent: &'input roxmltree::Node, tag_name: &'a str) -> Option<String> {
34 let n = node(parent, tag_name)?;
35 n.text().map(|t| t.to_owned())
36}
37
38fn parse_gav(n: &roxmltree::Node) -> Artifact {
39 Artifact {
40 group_id: node_text(n, "groupId"),
41 artifact_id: node_text(n, "artifactId"),
42 version: node_text(n, "version"),
43 packaging: node_text(n, "type").or_else(|| node_text(n, "packaging")), classifier: node_text(n, "classifier"),
45 }
46}
47
48fn parse_parent(n: &roxmltree::Node) -> Option<Parent> {
49 let n = node(n, "parent")?;
50 Some(Parent {
51 artifact_fqn: parse_gav(&n),
52 })
53}
54
55fn parse_dependency(n: &roxmltree::Node) -> Dependency {
56 Dependency {
57 artifact_fqn: parse_gav(n),
58 scope: node_text(n, "scope"),
59 }
60}
61
62fn parse_dependencies(n: &roxmltree::Node) -> HashMap<DependencyKey, Dependency> {
63 match node(n, "dependencies") {
64 Some(n) => n
65 .children()
66 .filter(|child| child.is_element() && child.has_tag_name("dependency"))
67 .map(|child| {
68 let dep = parse_dependency(&child);
69 (dep.get_key(), dep)
70 })
71 .collect(),
72 _ => HashMap::new(),
73 }
74}
75
76fn parse_dependency_management(n: &roxmltree::Node) -> Option<DependencyManagement> {
77 node(n, "dependencyManagement").map(|n| DependencyManagement {
78 dependencies: parse_dependencies(&n),
79 })
80}
81
82pub struct DefaultPomParser {}
83
84impl PomParser for DefaultPomParser {
85 fn parse(&self, input: String) -> Result<Project, ResolverError> {
86 let doc = roxmltree::Document::parse(&input).unwrap();
87
88 let n = doc.root();
89 let project_node = node(&n, "project")
90 .ok_or_else(|| ResolverError::invalid_data("invalid XML content, no <project> tag"))?;
91
92 Ok(Project {
93 artifact_fqn: parse_gav(&project_node),
94 parent: parse_parent(&project_node),
95 dependency_management: parse_dependency_management(&project_node),
96 dependencies: parse_dependencies(&project_node),
97 properties: HashMap::new(),
98 })
99 }
100}