From a97428a4864ddbc67c69487cbbd9b8d192a11f55 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 20 Aug 2013 22:52:32 -0700 Subject: [PATCH] Ensure localm2 ivy repo can resolve artifacts Fix the localm2 repository to only consider that a pom exists when its artifact is contained in the repository. This prevents a download error that can occur when the local m2 repository contains a POM file but not a JAR. Issue: #55532358 --- .../cli/compiler/GrapeEngineCustomizer.java | 95 ++++++++++++++++++- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GrapeEngineCustomizer.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GrapeEngineCustomizer.java index 4780cfd5dd9..824cdd6f2d6 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GrapeEngineCustomizer.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/GrapeEngineCustomizer.java @@ -19,10 +19,16 @@ package org.springframework.boot.cli.compiler; import groovy.grape.GrapeEngine; import groovy.grape.GrapeIvy; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.net.URL; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -34,6 +40,10 @@ import org.apache.ivy.core.event.resolve.EndResolveEvent; import org.apache.ivy.core.module.descriptor.Artifact; import org.apache.ivy.core.module.id.ModuleId; import org.apache.ivy.core.settings.IvySettings; +import org.apache.ivy.plugins.parser.m2.PomReader; +import org.apache.ivy.plugins.repository.Resource; +import org.apache.ivy.plugins.repository.url.URLRepository; +import org.apache.ivy.plugins.repository.url.URLResource; import org.apache.ivy.plugins.resolver.ChainResolver; import org.apache.ivy.plugins.resolver.DependencyResolver; import org.apache.ivy.plugins.resolver.IBiblioResolver; @@ -79,13 +89,23 @@ class GrapeEngineCustomizer { private void setupResolver(IvySettings settings) { ChainResolver grapesResolver = (ChainResolver) settings .getResolver("downloadGrapes"); + List grapesResolvers = grapesResolver.getResolvers(); - SpringBootResolver springBootResolver = new SpringBootResolver( - grapesResolver.getResolvers()); + // Replace localm2 resolver to fix missing artifact errors + for (int i = 0; i < grapesResolvers.size(); i++) { + DependencyResolver resolver = grapesResolvers.get(i); + if ("localm2".equals(resolver.getName())) { + ((IBiblioResolver) resolver).setRepository(new LocalM2Repository()); + } + } + + // Create a new top level resolver, encapsulating the default resolvers + SpringBootResolver springBootResolver = new SpringBootResolver(grapesResolvers); springBootResolver.setSettings(settings); springBootResolver.setReturnFirst(grapesResolver.isReturnFirst()); springBootResolver.setName("springBoot"); + // Add support for spring snapshots and milestones if required if (!Boolean.getBoolean("disableSpringSnapshotRepos")) { springBootResolver.addSpringSnapshotResolver(newResolver("spring-snapshot", "http://repo.springsource.org/snapshot")); @@ -93,11 +113,12 @@ class GrapeEngineCustomizer { "http://repo.springsource.org/milestone")); } - grapesResolver.getResolvers().clear(); - grapesResolver.getResolvers().add(springBootResolver); + // Replace the original resolvers + grapesResolvers.clear(); + grapesResolvers.add(springBootResolver); } - private DependencyResolver newResolver(String name, String root) { + private IBiblioResolver newResolver(String name, String root) { IBiblioResolver resolver = new IBiblioResolver(); resolver.setName(name); resolver.setRoot(root); @@ -195,6 +216,70 @@ class GrapeEngineCustomizer { } + /** + * Variant of {@link URLRepository} used to fix the 'localm2' so that when the local + * repo contains a POM but not an artifact we continue to maven central. + * @see "http://issues.gradle.org/browse/GRADLE-2034" + */ + private static class LocalM2Repository extends URLRepository { + + private Map resourcesCache = new HashMap(); + + @Override + public Resource getResource(String source) throws IOException { + Resource resource = this.resourcesCache.get(source); + if (resource == null) { + URL url = new URL(source); + resource = new LocalM2Resource(url); + this.resourcesCache.put(source, resource); + } + return resource; + } + + private static class LocalM2Resource extends URLResource { + + private Boolean artifactExists; + + public LocalM2Resource(URL url) { + super(url); + } + + @Override + public boolean exists() { + if (getURL().getPath().endsWith(".pom")) { + return super.exists() && artifactExists(); + } + return super.exists(); + } + + private boolean artifactExists() { + if (this.artifactExists == null) { + try { + PomReader reader = new PomReader(getURL(), this); + final String packaging = reader.getPackaging(); + if ("pom".equals(packaging)) { + this.artifactExists = true; + } + else { + File parent = new File(getURL().toURI()).getParentFile(); + File[] artifactFiles = parent.listFiles(new FileFilter() { + @Override + public boolean accept(File file) { + return file.getName().endsWith("." + packaging); + } + }); + this.artifactExists = artifactFiles.length > 0; + } + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + return this.artifactExists; + } + } + } + /** * {@link MessageLogger} to provide simple progress information. */