package fr.inria.diversify.buildSystem.maven;
import fr.inria.diversify.buildSystem.android.AndroidSdk;
import fr.inria.diversify.buildSystem.android.InvalidSdkException;
import fr.inria.diversify.util.Log;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.Repository;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.kevoree.resolver.MavenResolver;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
/**
* User: Simon
* Date: 6/12/13
* Time: 3:47 PM
*/
public class MavenDependencyResolver {
Set<URL> jarURL = new HashSet<>();
Set<String> dependencyResolve = new HashSet<>();
Properties properties;
String baseDir;
MavenResolver resolver;
ArrayList<String> repositoriesUrls;
public void DependencyResolver(String pomFile) throws Exception {
Log.debug("Resolve dependency of {}", pomFile);
String[] split = pomFile.split("/");
baseDir = "";
for(int i = 0; i < split.length - 1; i++) {
baseDir += split[i] + "/";
}
MavenProject project = loadProject(new File(pomFile));
initMavenResolver();
resolveAllDependencies(project);
addApplicationClasses(new File(pomFile));
}
public MavenProject loadProject(File pomFile) throws IOException, XmlPullParserException {
MavenProject ret;
MavenXpp3Reader mavenReader = new MavenXpp3Reader();
//Removed null and file exists protections that mask errors
FileReader reader = null;
reader = new FileReader(pomFile);
Model model = mavenReader.read(reader);
model.setPomFile(pomFile);
ret = new MavenProject(model);
reader.close();
return ret;
}
protected void addApplicationClasses(File pomFile) throws MalformedURLException {
jarURL.add((new File( pomFile.getParent() + "/target/classes/").toURL()));
URLClassLoader child = new URLClassLoader(jarURL.toArray(new URL[jarURL.size()]), Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(child);
}
protected void initMavenResolver() {
resolver = new MavenResolver();
resolver.setBasePath(System.getProperty("user.home") + File.separator + ".m2/repository");
repositoriesUrls = new ArrayList<>();
repositoriesUrls.add("http://repo1.maven.org/maven2/");
}
protected void updateRepositoriesUrl(MavenProject project) {
for (Repository repo : project.getRepositories()) {
repositoriesUrls.add(repo.getUrl());
}
}
public void resolveAllDependencies(MavenProject project) throws MalformedURLException {
updateRepositoriesUrl(project);
updateProperties(project.getProperties());
for (Dependency dependency : project.getDependencies()) {
try {
String artifactId = "mvn:" + resolveName(dependency.getGroupId(), properties) +
":" + resolveName(dependency.getArtifactId(), properties) +
":" + resolveName(dependency.getVersion(), properties);
File cachedFile;
if(dependency.getScope() != null && dependency.getScope().equals("system")) {
cachedFile = new File(resolveName(dependency.getSystemPath(), properties));
} else {
cachedFile = resolver.resolve(artifactId + ":" + resolveName(dependency.getType(), properties), repositoriesUrls);
}
jarURL.add(cachedFile.toURI().toURL());
Log.debug("resolve artifact: {}", artifactId);
File pomD = resolver.resolve(artifactId + ":pom", repositoriesUrls);
if(!dependencyResolve.contains(pomD.getAbsolutePath())) {
dependencyResolve.add(pomD.getAbsolutePath());
resolveAllDependencies(loadProject(pomD));
}
} catch (Exception e) {}
}
for(String module: project.getModules()) {
try {
resolveModuleDependencies(module);
} catch (Exception e) {
e.printStackTrace();
}
}
URLClassLoader child = new URLClassLoader(jarURL.toArray(new URL[jarURL.size()]), Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(child);
}
protected void updateProperties(Properties properties) {
if(this.properties == null) {
this.properties = new Properties(properties);
properties.setProperty("basedir", baseDir);
} else {
for (Object key : properties.keySet()) {
this.properties.put(key, properties.get(key));
}
}
}
protected void resolveModuleDependencies(String moduleName) throws IOException, XmlPullParserException {
MavenProject project = loadProject(new File(baseDir + moduleName + "/pom.xml"));
resolveAllDependencies(project);
}
public void resolveAndroidDependencies(String chosenSdkPlatform) throws InvalidSdkException, MojoExecutionException, MalformedURLException {
File chosenSdkPath = new File( getAndroidHomeOrThrow() );
AndroidSdk androidSdk = new AndroidSdk( chosenSdkPath, chosenSdkPlatform );
jarURL.add(androidSdk.getAndroidJar().toURI().toURL());
jarURL.add(new File(androidSdk.getDxJarPath()).toURI().toURL());
URLClassLoader child = new URLClassLoader(jarURL.toArray(new URL[jarURL.size()]), Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(child);
}
protected String resolveName(String string, Properties properties) {
char[] chars = string.toCharArray();
int replaceBegin = -1;
String id = "";
for (int i = 0; i < chars.length; i++) {
if (replaceBegin != -1 && chars[i] != '{' && chars[i] != '}') {
id += chars[i];
}
if (replaceBegin != -1 && chars[i] == '}') {
string = string.substring(0, replaceBegin) + properties.getProperty(id) + string.substring(i + 1, string.length());
replaceBegin = -1;
id = "";
}
if (chars[i] == '$' && i + 1 < chars.length && chars[i + 1] == '{') {
replaceBegin = i;
}
}
return string;
}
protected String getAndroidHomeOrThrow()
{
final String androidHome = System.getenv( AndroidSdk.ENV_ANDROID_HOME );
return androidHome;
}
}