1 package org.robolectric.internal.dependency; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.RandomAccessFile; 6 import java.net.MalformedURLException; 7 import java.net.URL; 8 import java.nio.channels.FileChannel; 9 import java.nio.channels.FileLock; 10 import java.util.Hashtable; 11 import org.apache.maven.artifact.ant.Authentication; 12 import org.apache.maven.artifact.ant.DependenciesTask; 13 import org.apache.maven.artifact.ant.RemoteRepository; 14 import org.apache.maven.model.Dependency; 15 import org.apache.tools.ant.Project; 16 import org.robolectric.RoboSettings; 17 import org.robolectric.util.Util; 18 19 public class MavenDependencyResolver implements DependencyResolver { 20 private final Project project = new Project(); 21 private final String repositoryUrl; 22 private final String repositoryId; 23 private final String repositoryUserName; 24 private final String repositoryPassword; 25 MavenDependencyResolver()26 public MavenDependencyResolver() { 27 this(RoboSettings.getMavenRepositoryUrl(), RoboSettings.getMavenRepositoryId(), RoboSettings.getMavenRepositoryUserName(), RoboSettings.getMavenRepositoryPassword()); 28 } 29 MavenDependencyResolver(String repositoryUrl, String repositoryId, String repositoryUserName, String repositoryPassword)30 public MavenDependencyResolver(String repositoryUrl, String repositoryId, String repositoryUserName, String repositoryPassword) { 31 this.repositoryUrl = repositoryUrl; 32 this.repositoryId = repositoryId; 33 this.repositoryUserName = repositoryUserName; 34 this.repositoryPassword = repositoryPassword; 35 } 36 37 @Override getLocalArtifactUrls(DependencyJar dependency)38 public URL[] getLocalArtifactUrls(DependencyJar dependency) { 39 return getLocalArtifactUrls(new DependencyJar[] {dependency}); 40 } 41 42 /** 43 * Get an array of local artifact URLs for the given dependencies. The order of the URLs is guaranteed to be the 44 * same as the input order of dependencies, i.e., urls[i] is the local artifact URL for dependencies[i]. 45 */ getLocalArtifactUrls(DependencyJar... dependencies)46 public URL[] getLocalArtifactUrls(DependencyJar... dependencies) { 47 DependenciesTask dependenciesTask = createDependenciesTask(); 48 configureMaven(dependenciesTask); 49 RemoteRepository remoteRepository = new RemoteRepository(); 50 remoteRepository.setUrl(repositoryUrl); 51 remoteRepository.setId(repositoryId); 52 if (repositoryUserName != null || repositoryPassword != null) { 53 Authentication authentication = new Authentication(); 54 authentication.setUserName(repositoryUserName); 55 authentication.setPassword(repositoryPassword); 56 remoteRepository.addAuthentication(authentication); 57 } 58 dependenciesTask.addConfiguredRemoteRepository(remoteRepository); 59 dependenciesTask.setProject(project); 60 for (DependencyJar dependencyJar : dependencies) { 61 Dependency dependency = new Dependency(); 62 dependency.setArtifactId(dependencyJar.getArtifactId()); 63 dependency.setGroupId(dependencyJar.getGroupId()); 64 dependency.setType(dependencyJar.getType()); 65 dependency.setVersion(dependencyJar.getVersion()); 66 if (dependencyJar.getClassifier() != null) { 67 dependency.setClassifier(dependencyJar.getClassifier()); 68 } 69 dependenciesTask.addDependency(dependency); 70 } 71 72 whileLocked(dependenciesTask::execute); 73 74 @SuppressWarnings("unchecked") 75 Hashtable<String, String> artifacts = project.getProperties(); 76 URL[] urls = new URL[dependencies.length]; 77 for (int i = 0; i < urls.length; i++) { 78 try { 79 urls[i] = Util.url(artifacts.get(key(dependencies[i]))); 80 } catch (MalformedURLException e) { 81 throw new RuntimeException(e); 82 } 83 } 84 return urls; 85 } 86 whileLocked(Runnable runnable)87 private void whileLocked(Runnable runnable) { 88 File lockFile = new File(System.getProperty("user.home"), ".robolectric-download-lock"); 89 try (RandomAccessFile raf = new RandomAccessFile(lockFile, "rw")) { 90 try (FileChannel channel = raf.getChannel()) { 91 try (FileLock ignored = channel.lock()) { 92 runnable.run(); 93 } 94 } 95 } catch (IOException e) { 96 throw new IllegalStateException("Couldn't create lock file " + lockFile, e); 97 } finally { 98 lockFile.delete(); 99 } 100 } 101 102 @Override getLocalArtifactUrl(DependencyJar dependency)103 public URL getLocalArtifactUrl(DependencyJar dependency) { 104 URL[] urls = getLocalArtifactUrls(dependency); 105 if (urls.length > 0) { 106 return urls[0]; 107 } 108 return null; 109 } 110 key(DependencyJar dependency)111 private String key(DependencyJar dependency) { 112 String key = dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getType(); 113 if(dependency.getClassifier() != null) { 114 key += ":" + dependency.getClassifier(); 115 } 116 return key; 117 } 118 createDependenciesTask()119 protected DependenciesTask createDependenciesTask() { 120 return new DependenciesTask(); 121 } 122 configureMaven(DependenciesTask dependenciesTask)123 protected void configureMaven(DependenciesTask dependenciesTask) { 124 // maybe you want to override this method and some settings? 125 } 126 } 127