aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google
diff options
context:
space:
mode:
authorGravatar Kristina Chodorow <kchodorow@google.com>2015-08-06 15:14:19 +0000
committerGravatar David Chen <dzc@google.com>2015-08-06 22:18:18 +0000
commit87584a8cd7949cbdef695f2289fd7b83698a410c (patch)
tree3c49c6d31f213a32a69ad534b3446564cb77242d /src/main/java/com/google
parentd53d10bfc61096158f3b7ee7e8aab2f782398716 (diff)
Add output_dir option and improve repository handling
I finally worked out how to get a simple test maven repository working, so added back integration testing. This removes the dependency on Aether and just uses the maven model lib to resolve dependencies, which seems to work better in the face of custom repositories. -- MOS_MIGRATED_REVID=100031414
Diffstat (limited to 'src/main/java/com/google')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/repository/MavenConnector.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java2
-rw-r--r--src/main/java/com/google/devtools/build/workspace/BUILD1
-rw-r--r--src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java38
-rw-r--r--src/main/java/com/google/devtools/build/workspace/GenerateWorkspaceOptions.java10
-rw-r--r--src/main/java/com/google/devtools/build/workspace/Resolver.java27
-rw-r--r--src/main/java/com/google/devtools/build/workspace/maven/BUILD2
-rw-r--r--src/main/java/com/google/devtools/build/workspace/maven/DefaultModelResolver.java94
-rw-r--r--src/main/java/com/google/devtools/build/workspace/maven/Resolver.java165
-rw-r--r--src/main/java/com/google/devtools/build/workspace/maven/Rule.java23
10 files changed, 232 insertions, 142 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenConnector.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenConnector.java
index b405e7dccd..b3232efaa4 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenConnector.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenConnector.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.bazel.repository;
+import org.apache.maven.model.Repository;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.eclipse.aether.AbstractRepositoryListener;
import org.eclipse.aether.DefaultRepositorySystemSession;
@@ -61,8 +62,17 @@ public class MavenConnector {
/**
* How is this not a built-in for aether?
*/
- public static RemoteRepository getMavenCentral() {
+ public static RemoteRepository getMavenCentralRemote() {
return new RemoteRepository.Builder(
"central", "default", MAVEN_CENTRAL_URL).build();
}
+
+ public static Repository getMavenCentral() {
+ Repository repository = new Repository();
+ repository.setId("central");
+ repository.setName("default");
+ repository.setUrl(MAVEN_CENTRAL_URL);
+ return repository;
+ }
+
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java
index 1de2ea9569..9b525354cd 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenJarFunction.java
@@ -158,7 +158,7 @@ public class MavenJarFunction extends HttpArchiveFunction {
"user-defined repository " + repositories.size(), "default", repositoryUrl).build());
}
} else {
- this.repositories = ImmutableList.of(MavenConnector.getMavenCentral());
+ this.repositories = ImmutableList.of(MavenConnector.getMavenCentralRemote());
}
}
diff --git a/src/main/java/com/google/devtools/build/workspace/BUILD b/src/main/java/com/google/devtools/build/workspace/BUILD
index d1021b5aae..d503e3895c 100644
--- a/src/main/java/com/google/devtools/build/workspace/BUILD
+++ b/src/main/java/com/google/devtools/build/workspace/BUILD
@@ -21,5 +21,6 @@ java_library(
"//src/main/java/com/google/devtools/build/workspace/maven",
"//src/main/java/com/google/devtools/build/workspace/maven:rule",
"//third_party:guava",
+ "//third_party:maven_model",
],
)
diff --git a/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java b/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java
index 9e64efebc8..6473cc5550 100644
--- a/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java
+++ b/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java
@@ -42,6 +42,7 @@ public class GenerateWorkspace {
private final StoredEventHandler handler;
private final FileSystem fileSystem;
private final com.google.devtools.build.workspace.maven.Resolver resolver;
+ private final Path outputDir;
public static void main(String[] args) {
OptionsParser parser = OptionsParser.newOptionsParser(GenerateWorkspaceOptions.class);
@@ -52,7 +53,7 @@ public class GenerateWorkspace {
return;
}
- GenerateWorkspace workspaceFileGenerator = new GenerateWorkspace();
+ GenerateWorkspace workspaceFileGenerator = new GenerateWorkspace(options.outputDir);
workspaceFileGenerator.generateFromWorkspace(options.bazelProjects);
workspaceFileGenerator.generateFromPom(options.mavenProjects);
if (!workspaceFileGenerator.hasErrors()) {
@@ -65,17 +66,24 @@ public class GenerateWorkspace {
}
private static void printUsage(OptionsParser parser) {
- System.out.println("Usage: generate_workspace (-b PATH|-m PATH)+\n\n"
- + "Generates a workspace file from the given projects. At least one bazel_project or "
- + "maven_project must be specified.\n");
+ System.out.println("Usage: generate_workspace (-b PATH|-m PATH)+ [-o PATH]\n\n"
+ + "Generates a WORKSPACE file from the given projects and a BUILD file with a rule that "
+ + "contains all of the transitive dependencies. At least one bazel_project or "
+ + "maven_project must be specified. If output_dir is not specified, the generated files "
+ + "will be written to a temporary directory.\n");
System.out.println(parser.describeOptions(Collections.<String, String>emptyMap(),
OptionsParser.HelpVerbosity.LONG));
}
- private GenerateWorkspace() {
+ private GenerateWorkspace(String outputDir) {
this.handler = new StoredEventHandler();
this.fileSystem = getFileSystem();
- this.resolver = new com.google.devtools.build.workspace.maven.Resolver(handler, fileSystem);
+ this.resolver = new com.google.devtools.build.workspace.maven.Resolver(handler);
+ if (outputDir.isEmpty()) {
+ this.outputDir = fileSystem.getPath(Files.createTempDir().toString());
+ } else {
+ this.outputDir = fileSystem.getPath(outputDir);
+ }
}
static FileSystem getFileSystem() {
@@ -112,24 +120,30 @@ public class GenerateWorkspace {
private void writeResults() {
String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
- File tempDir = Files.createTempDir();
- File workspaceFile = new File(tempDir + "/" + date + ".WORKSPACE");
- File buildFile = new File(tempDir + "/" + date + ".BUILD");
+ File workspaceFile = outputDir.getRelative("WORKSPACE").getPathFile();
+ File buildFile = outputDir.getRelative("BUILD").getPathFile();
+
+ // Don't overwrite existing files with generated ones.
+ if (workspaceFile.exists()) {
+ workspaceFile = outputDir.getRelative(date + ".WORKSPACE").getPathFile();
+ }
+ if (buildFile.exists()) {
+ buildFile = outputDir.getRelative(date + ".BUILD").getPathFile();
+ }
+
try (PrintStream workspaceStream = new PrintStream(workspaceFile);
PrintStream buildStream = new PrintStream(buildFile)) {
resolver.writeWorkspace(workspaceStream);
resolver.writeBuild(buildStream);
} catch (IOException e) {
handler.handle(Event.error(
- "Could not write WORKSPACE and BUILD files to " + tempDir + ": " + e.getMessage()));
+ "Could not write WORKSPACE and BUILD files to " + outputDir + ": " + e.getMessage()));
return;
}
-
System.err.println("Wrote:\n" + workspaceFile + "\n" + buildFile);
}
private void cleanup() {
- resolver.cleanup();
for (Event event : handler.getEvents()) {
System.err.println(event);
}
diff --git a/src/main/java/com/google/devtools/build/workspace/GenerateWorkspaceOptions.java b/src/main/java/com/google/devtools/build/workspace/GenerateWorkspaceOptions.java
index 0db735f6ca..2a5a8cc3cd 100644
--- a/src/main/java/com/google/devtools/build/workspace/GenerateWorkspaceOptions.java
+++ b/src/main/java/com/google/devtools/build/workspace/GenerateWorkspaceOptions.java
@@ -48,4 +48,14 @@ public class GenerateWorkspaceOptions extends OptionsBase {
defaultValue = ""
)
public List<String> mavenProjects;
+
+ @Option(
+ name = "output_dir",
+ abbrev = 'o',
+ help = "Output directory to store the WORKSPACE and BUILD files. If unspecified, a temporary"
+ + " directory is used.",
+ defaultValue = ""
+ )
+ public String outputDir;
+
}
diff --git a/src/main/java/com/google/devtools/build/workspace/Resolver.java b/src/main/java/com/google/devtools/build/workspace/Resolver.java
index 4229fc40f7..c6de1b84aa 100644
--- a/src/main/java/com/google/devtools/build/workspace/Resolver.java
+++ b/src/main/java/com/google/devtools/build/workspace/Resolver.java
@@ -32,8 +32,13 @@ import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.workspace.maven.DefaultModelResolver;
import com.google.devtools.build.workspace.maven.Rule;
+import org.apache.maven.model.building.ModelSource;
+import org.apache.maven.model.resolution.InvalidRepositoryException;
+import org.apache.maven.model.resolution.UnresolvableModelException;
+
import java.io.IOException;
import java.util.List;
@@ -96,6 +101,7 @@ public class Resolver {
com.google.devtools.build.lib.packages.Rule workspaceRule =
externalPackage.getRepositoryInfo(repositoryName);
+ DefaultModelResolver modelResolver = resolver.getModelResolver();
AttributeMap attributeMap = AggregatingAttributeMapper.of(workspaceRule);
Rule rule;
try {
@@ -108,11 +114,26 @@ public class Resolver {
attributeMap.get("group_id", Type.STRING),
attributeMap.get("version", Type.STRING));
}
- } catch (Rule.InvalidRuleException e) {
- handler.handle(Event.error(location, e.getMessage()));
+ if (attributeMap.has("repository", Type.STRING)
+ && !attributeMap.get("repository", Type.STRING).isEmpty()) {
+ modelResolver.addUserRepository(attributeMap.get("repository", Type.STRING));
+ rule.setRepository(attributeMap.get("repository", Type.STRING));
+ }
+ } catch (Rule.InvalidRuleException | InvalidRepositoryException e) {
+ handler.handle(Event.error(location, "Couldn't get attribute: " + e.getMessage()));
return;
}
- resolver.getArtifactDependencies(rule, location);
+ ModelSource modelSource;
+
+ try {
+ modelSource = modelResolver.resolveModel(
+ rule.groupId(), rule.artifactId(), rule.version());
+ } catch (UnresolvableModelException e) {
+ handler.handle(Event.error(
+ "Could not resolve model for " + target + ": " + e.getMessage()));
+ continue;
+ }
+ resolver.resolveModelSource(modelSource);
} else {
handler.handle(Event.warn(location, "Cannot fetch transitive dependencies for " + target
+ " yet, skipping"));
diff --git a/src/main/java/com/google/devtools/build/workspace/maven/BUILD b/src/main/java/com/google/devtools/build/workspace/maven/BUILD
index b333690549..d5bc5123cb 100644
--- a/src/main/java/com/google/devtools/build/workspace/maven/BUILD
+++ b/src/main/java/com/google/devtools/build/workspace/maven/BUILD
@@ -17,8 +17,6 @@ java_library(
":rule",
"//src/main/java:events",
"//src/main/java:maven-connector",
- "//src/main/java:vfs",
- "//third_party:aether",
"//third_party:guava",
"//third_party:maven_model",
"//third_party:plexus_component_annotations",
diff --git a/src/main/java/com/google/devtools/build/workspace/maven/DefaultModelResolver.java b/src/main/java/com/google/devtools/build/workspace/maven/DefaultModelResolver.java
index eb0c430bd7..62c8058780 100644
--- a/src/main/java/com/google/devtools/build/workspace/maven/DefaultModelResolver.java
+++ b/src/main/java/com/google/devtools/build/workspace/maven/DefaultModelResolver.java
@@ -14,8 +14,10 @@
package com.google.devtools.build.workspace.maven;
-import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import com.google.devtools.build.lib.bazel.repository.MavenConnector;
+
import org.apache.maven.model.Parent;
import org.apache.maven.model.Repository;
import org.apache.maven.model.building.ModelSource;
@@ -25,21 +27,32 @@ import org.apache.maven.model.resolution.ModelResolver;
import org.apache.maven.model.resolution.UnresolvableModelException;
import java.io.IOException;
+import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
-import java.util.List;
+import java.util.Map;
+import java.util.Set;
-class DefaultModelResolver implements ModelResolver {
+/**
+ * Resolver to find the repository a given Maven artifact should be fetched
+ * from.
+ */
+public class DefaultModelResolver implements ModelResolver {
- private final List<Repository> repositories;
+ private final Set<Repository> repositories;
+ private final Map<String, ModelSource> artifactToRepository;
public DefaultModelResolver() {
- repositories = Lists.newArrayList();
+ repositories = Sets.newHashSet();
+ repositories.add(MavenConnector.getMavenCentral());
+ artifactToRepository = Maps.newHashMap();
}
- private DefaultModelResolver(List<Repository> repositories) {
+ private DefaultModelResolver(
+ Set<Repository> repositories, Map<String, ModelSource> artifactToRepository) {
this.repositories = repositories;
+ this.artifactToRepository = artifactToRepository;
}
@Override
@@ -52,35 +65,51 @@ class DefaultModelResolver implements ModelResolver {
return modelSource;
}
}
- UrlModelSource modelSource = getModelSource(
- MavenConnector.getMavenCentral().getUrl(), groupId, artifactId, version);
- if (modelSource == null) {
- throw new UnresolvableModelException("Could not find any repositories that knew how to "
- + "resolve the artifact (checked " + Arrays.toString(repositories.toArray()) + ")",
- groupId, artifactId, version);
- }
- return modelSource;
+ throw new UnresolvableModelException("Could not find any repositories that knew how to "
+ + "resolve " + groupId + ":" + artifactId + ":" + version + " (checked "
+ + Arrays.toString(repositories.toArray()) + ")", groupId, artifactId, version);
}
+ // TODO(kchodorow): make this work with local repositories.
private UrlModelSource getModelSource(
String url, String groupId, String artifactId, String version)
throws UnresolvableModelException {
try {
- UrlModelSource urlModelSource = new UrlModelSource(new URL(url
+ if (!url.endsWith("/")) {
+ url += "/";
+ }
+ URL urlUrl = new URL(url
+ groupId.replaceAll("\\.", "/") + "/" + artifactId + "/" + version + "/" + artifactId
- + "-" + version + ".pom"));
- if (urlModelSource.getInputStream().available() != 0) {
+ + "-" + version + ".pom");
+ if (pomFileExists(urlUrl)) {
+ UrlModelSource urlModelSource = new UrlModelSource(urlUrl);
+ artifactToRepository.put(Rule.name(groupId, artifactId), urlModelSource);
return urlModelSource;
}
} catch (MalformedURLException e) {
- throw new UnresolvableModelException(e.getMessage(), groupId, artifactId, version, e);
- } catch (IOException e) {
- // The artifact could not be fetched from the current repo, just move on and check the next
- // one.
+ throw new UnresolvableModelException("Bad URL " + url + ": " + e.getMessage(), groupId,
+ artifactId, version, e);
}
return null;
}
+ private boolean pomFileExists(URL url) {
+ try {
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("HEAD");
+ connection.setInstanceFollowRedirects(true);
+ connection.connect();
+
+ int code = connection.getResponseCode();
+ if (code == 200) {
+ return true;
+ }
+ } catch (IOException e) {
+ // Something went wrong, fall through.
+ }
+ return false;
+ }
+
@Override
public ModelSource resolveModel(Parent parent) throws UnresolvableModelException {
return resolveModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
@@ -99,6 +128,25 @@ class DefaultModelResolver implements ModelResolver {
@Override
public ModelResolver newCopy() {
- return new DefaultModelResolver(repositories);
+ return new DefaultModelResolver(repositories, artifactToRepository);
+ }
+
+ /**
+ * Returns the repository used to resolve the given artifact.
+ */
+ public ModelSource getPomUrl(String groupId, String artifactId) {
+ return artifactToRepository.get(Rule.name(groupId, artifactId));
}
-} \ No newline at end of file
+
+ /**
+ * Adds a user-specified repository to the list.
+ */
+ public void addUserRepository(String url) throws InvalidRepositoryException {
+ Repository repository = new Repository();
+ repository.setUrl(url);
+ repository.setId("user-defined repository");
+ repository.setName("default");
+ addRepository(repository);
+ }
+
+}
diff --git a/src/main/java/com/google/devtools/build/workspace/maven/Resolver.java b/src/main/java/com/google/devtools/build/workspace/maven/Resolver.java
index aa6b878d17..0eda313e18 100644
--- a/src/main/java/com/google/devtools/build/workspace/maven/Resolver.java
+++ b/src/main/java/com/google/devtools/build/workspace/maven/Resolver.java
@@ -16,58 +16,51 @@ package com.google.devtools.build.workspace.maven;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.io.Files;
-import com.google.devtools.build.lib.bazel.repository.MavenConnector;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.vfs.FileSystem;
import org.apache.maven.model.Model;
import org.apache.maven.model.Repository;
+import org.apache.maven.model.building.DefaultModelBuilder;
import org.apache.maven.model.building.DefaultModelBuilderFactory;
import org.apache.maven.model.building.DefaultModelBuildingRequest;
import org.apache.maven.model.building.DefaultModelProcessor;
+import org.apache.maven.model.building.FileModelSource;
import org.apache.maven.model.building.ModelBuildingException;
import org.apache.maven.model.building.ModelBuildingResult;
+import org.apache.maven.model.building.ModelSource;
import org.apache.maven.model.io.DefaultModelReader;
import org.apache.maven.model.locator.DefaultModelLocator;
import org.apache.maven.model.resolution.InvalidRepositoryException;
-import org.apache.maven.model.resolution.ModelResolver;
-import org.eclipse.aether.RepositorySystem;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.artifact.Artifact;
-import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.resolution.ArtifactDescriptorException;
-import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
-import org.eclipse.aether.resolution.ArtifactDescriptorResult;
+import org.apache.maven.model.resolution.UnresolvableModelException;
import java.io.File;
-import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
+import javax.annotation.Nullable;
+
/**
* Resolves Maven dependencies.
*/
public class Resolver {
- private final MavenConnector connector;
- private final File localRepository;
- private final FileSystem fileSystem;
+ private static final String COMPILE_SCOPE = "compile";
+
private final EventHandler handler;
+ private final DefaultModelBuilder modelBuilder;
+ private final DefaultModelResolver modelResolver;
private final List<String> headers;
// Mapping of maven_jar name to Rule.
private final Map<String, Rule> deps;
- public Resolver(EventHandler handler, FileSystem fileSystem) {
+ public Resolver(EventHandler handler) {
this.handler = handler;
- this.fileSystem = fileSystem;
- this.localRepository = Files.createTempDir();
- this.connector = new MavenConnector(localRepository.getPath());
- headers = Lists.newArrayList();
- deps = Maps.newHashMap();
+ this.headers = Lists.newArrayList();
+ this.deps = Maps.newHashMap();
+ this.modelBuilder = new DefaultModelBuilderFactory().newInstance();
+ this.modelResolver = new DefaultModelResolver();
}
/**
@@ -108,46 +101,56 @@ public class Resolver {
headers.add(header);
}
- /**
- * Remove the temporary directory storing pom files.
- */
- public void cleanup() {
- try {
- for (File file : Files.fileTreeTraverser().postOrderTraversal(localRepository)) {
- java.nio.file.Files.delete(file.toPath());
- }
- } catch (IOException e) {
- handler.handle(Event.error(Location.fromFile(fileSystem.getPath(localRepository.getPath())),
- "Could not create local repository directory " + localRepository + ": "
- + e.getMessage()));
- }
+ public DefaultModelResolver getModelResolver() {
+ return modelResolver;
}
/**
- * Resolves all dependencies from a pom.xml file in the given directory.
+ * Given a local path to a Maven project, this attempts to find the transitive dependencies of
+ * the project.
+ * @param projectPath The path to search for Maven projects.
*/
- public void resolvePomDependencies(String project) {
+ public void resolvePomDependencies(String projectPath) {
DefaultModelProcessor processor = new DefaultModelProcessor();
processor.setModelLocator(new DefaultModelLocator());
processor.setModelReader(new DefaultModelReader());
- File pom = processor.locatePom(new File(project));
- Location pomLocation = Location.fromFile(fileSystem.getPath(pom.getPath()));
+ File pom = processor.locatePom(new File(projectPath));
addHeader(pom.getAbsolutePath());
+ Model model = resolveModelSource(new FileModelSource(pom));
+
+ // For the top-level pom _only_, resolve all of its submodules.
+ resolveSubmodules(model, pom);
+ }
- DefaultModelBuilderFactory factory = new DefaultModelBuilderFactory();
+ /**
+ * This calls resolvePomDependencies on each submodule of the model, thus filling in the
+ * transitive submodules' dependencies as well as the main project's.
+ */
+ private void resolveSubmodules(Model model, File pom) {
+ for (String module : model.getModules()) {
+ resolvePomDependencies(pom.getParent() + "/" + module);
+ }
+ }
+
+ /**
+ * Resolves all dependencies from a given "model source," which could be either a URL or a local
+ * file.
+ * @return the model.
+ */
+ @Nullable
+ public Model resolveModelSource(ModelSource modelSource) {
DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
- ModelResolver modelResolver = new DefaultModelResolver();
request.setModelResolver(modelResolver);
- request.setPomFile(pom);
+ request.setModelSource(modelSource);
Model model;
try {
- ModelBuildingResult result = factory.newInstance().build(request);
+ ModelBuildingResult result = modelBuilder.build(request);
model = result.getEffectiveModel();
} catch (ModelBuildingException | IllegalArgumentException e) {
// IllegalArg can be thrown if the parent POM cannot be resolved.
- handler.handle(Event.error(pomLocation,
- "Unable to resolve Maven model from " + pom + ": " + e.getMessage()));
- return;
+ handler.handle(Event.error("Unable to resolve Maven model from " + modelSource.getLocation()
+ + ": " + e.getMessage()));
+ return null;
}
for (Repository repo : model.getRepositories()) {
@@ -156,68 +159,40 @@ public class Resolver {
} catch (InvalidRepositoryException e) {
handler.handle(Event.error("Unable to add repository " + repo.getName()
+ " (" + repo.getId() + "," + repo.getUrl() + ")"));
- return;
+ return model;
}
}
- for (String module : model.getModules()) {
- resolvePomDependencies(project + "/" + module);
- }
-
for (org.apache.maven.model.Dependency dependency : model.getDependencies()) {
+ if (!dependency.getScope().equals(COMPILE_SCOPE)) {
+ continue;
+ }
try {
Rule artifactRule = new Rule(
dependency.getArtifactId(), dependency.getGroupId(), dependency.getVersion());
- addArtifact(artifactRule, model.toString());
- getArtifactDependencies(artifactRule, pomLocation);
- } catch (Rule.InvalidRuleException e) {
- handler.handle(Event.error(pomLocation, e.getMessage()));
- }
- }
- }
-
- /**
- * Adds transitive dependencies of the given artifact.
- */
- public void getArtifactDependencies(Rule artifactRule, Location location) {
- Artifact artifact = artifactRule.getArtifact();
-
- RepositorySystem system = connector.newRepositorySystem();
- RepositorySystemSession session = connector.newRepositorySystemSession(system);
-
- ArtifactDescriptorRequest descriptorRequest = new ArtifactDescriptorRequest();
- descriptorRequest.setArtifact(artifact);
- descriptorRequest.addRepository(MavenConnector.getMavenCentral());
-
- ArtifactDescriptorResult descriptorResult;
- try {
- descriptorResult = system.readArtifactDescriptor(session, descriptorRequest);
- if (descriptorResult == null) {
- return;
- }
- } catch (ArtifactDescriptorException e) {
- handler.handle(Event.error(location, e.getMessage()));
- return;
- }
-
- for (Dependency dependency : descriptorResult.getDependencies()) {
- Artifact depArtifact = dependency.getArtifact();
- try {
- Rule rule = new Rule(
- depArtifact.getArtifactId(), depArtifact.getGroupId(), depArtifact.getVersion());
- if (addArtifact(rule, artifactRule.toMavenArtifactString())) {
- getArtifactDependencies(rule, location);
+ boolean isNewDependency = addArtifact(artifactRule, model.toString());
+ if (isNewDependency) {
+ ModelSource depModelSource = modelResolver.resolveModel(
+ dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion());
+ if (depModelSource != null) {
+ resolveModelSource(depModelSource);
+ } else {
+ handler.handle(Event.error("Could not get a model for " + dependency));
+ }
}
- } catch (Rule.InvalidRuleException e) {
- handler.handle(Event.error(location, e.getMessage()));
+ } catch (UnresolvableModelException | Rule.InvalidRuleException e) {
+ handler.handle(Event.error("Could not resolve dependency " + dependency.getGroupId()
+ + ":" + dependency.getArtifactId() + ":" + dependency.getVersion() + ": "
+ + e.getMessage()));
}
}
+ return model;
}
/**
- * Adds the artifact to the list of deps, if it is not already there. Returns if the artifact
- * was already in the list. If the artifact was in the list at a different version, adds an
- * error event to the event handler.
+ * Adds the artifact to the map of deps, if it is not already there. Returns if the artifact
+ * was newly added. If the artifact was in the list at a different version, adds an annotation
+ * about the desired version.
*/
private boolean addArtifact(Rule dependency, String parent) {
String artifactName = dependency.name();
diff --git a/src/main/java/com/google/devtools/build/workspace/maven/Rule.java b/src/main/java/com/google/devtools/build/workspace/maven/Rule.java
index 65fa88c437..648bcfa117 100644
--- a/src/main/java/com/google/devtools/build/workspace/maven/Rule.java
+++ b/src/main/java/com/google/devtools/build/workspace/maven/Rule.java
@@ -14,19 +14,20 @@
package com.google.devtools.build.workspace.maven;
-import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
-import java.util.List;
+import java.util.Set;
/**
* A struct representing the fields of maven_jar to be written to the WORKSPACE file.
*/
public final class Rule {
private final Artifact artifact;
- private final List<String> parents;
+ private final Set<String> parents;
+ private String repository;
public Rule(String artifactStr) throws InvalidRuleException {
try {
@@ -34,7 +35,7 @@ public final class Rule {
} catch (IllegalArgumentException e) {
throw new InvalidRuleException(e.getMessage());
}
- this.parents = Lists.newArrayList();
+ this.parents = Sets.newHashSet();
}
public Rule(String artifactId, String groupId, String version)
@@ -62,7 +63,14 @@ public final class Rule {
* A unique name for this artifact to use in maven_jar's name attribute.
*/
String name() {
- return (groupId() + "/" + artifactId()).replaceAll("\\.", "/");
+ return Rule.name(groupId(), artifactId());
+ }
+
+ /**
+ * A unique name for this artifact to use in maven_jar's name attribute.
+ */
+ public static String name(String groupId, String artifactId) {
+ return (groupId + "/" + artifactId).replaceAll("\\.", "/");
}
public Artifact getArtifact() {
@@ -73,6 +81,10 @@ public final class Rule {
return groupId() + ":" + artifactId() + ":" + version();
}
+ public void setRepository(String repository) {
+ this.repository = repository;
+ }
+
/**
* The way this jar should be stringified for the WORKSPACE file.
*/
@@ -85,6 +97,7 @@ public final class Rule {
builder.append("maven_jar(\n"
+ " name = \"" + name() + "\",\n"
+ " artifact = \"" + toMavenArtifactString() + "\",\n"
+ + (repository == null ? "" : " repository = \"" + repository + "\",\n")
+ ")");
return builder.toString();
}