use std::error::Error;
use std::fmt;
use std::fs;
use std::path::{Path,PathBuf};
use log::{info,error};
use reqwest;
use reqwest::Url;
#[derive(Clone,Debug,PartialEq)]
pub struct MavenArtifact<'a> {
group_id : &'a str,
artifact_id : &'a str,
version: &'a str
}
impl<'a> MavenArtifact<'a> {
pub fn new(desc : &str) -> Result<MavenArtifact,()> {
let parts = desc.split(":").collect::<Vec<&str>>();
if parts.len() != 3 {
Err(())
} else {
Ok(MavenArtifact{group_id:parts[0],artifact_id:parts[1],version:parts[2]})
}
}
pub fn to_jarname(&self) -> String {
let mut n = String::new();
n.push_str(self.artifact_id);
n.push_str("-");
n.push_str(self.version);
n.push_str(".jar");
n
}
pub fn to_url(&self, base: &Url) -> Url {
let mut s = String::new();
s.push_str(self.group_id.replace(".","/").as_str());
s.push_str("/");
s.push_str(self.artifact_id);
s.push_str("/");
s.push_str(self.version);
s.push_str("/");
s.push_str(self.to_jarname().as_str());
base.join(&s).unwrap()
}
}
impl<'a> fmt::Display for MavenArtifact<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,"{}:{}:{}",self.group_id,self.artifact_id,self.version)
}
}
#[derive(Clone,Debug,PartialEq)]
pub struct MavenResolver<T: AsRef<Path>> {
dir: T,
url: Url
}
impl<T: AsRef<Path>> MavenResolver<T> {
pub fn new(dir: T, url: Url) -> MavenResolver<T> {
fs::create_dir_all(dir.as_ref()).unwrap();
MavenResolver{dir,url}
}
pub fn get<'b>(&self, artifact: MavenArtifact<'b>) -> Result<PathBuf,Box<dyn Error>> {
let mut jar = PathBuf::new();
jar.push(self.dir.as_ref());
jar.push(artifact.to_jarname());
if !jar.as_path().exists() {
let url = artifact.to_url(&self.url);
let response = reqwest::blocking::get(url.clone())?;
if response.status().is_success() {
info!("Downloaded {}",url.as_str());
fs::write(jar.as_path(),response.bytes()?)?;
} else {
error!("Downloading {} ({:?})",url.as_str(),response.status());
return Err(Box::new(ResolutionError{name:artifact.to_jarname()}));
}
}
Ok(jar)
}
}
#[derive(Clone)]
struct ResolutionError {
name: String
}
impl fmt::Display for ResolutionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "failed resolving maven package {}",self.name)
}
}
impl fmt::Debug for ResolutionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "failed resolving maven package {}",self.name)
}
}
impl Error for ResolutionError {}