From 60fe468af9db487c2a915fc421a05d3b9d4551bc Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Mar 2014 11:36:24 +0000 Subject: [PATCH] Make JAR files on classpath a special case for archive If the user adds a JAR file to the classpath in "spring jar -cp ..." he expected it to end up in the classpath of the executable jar (i.e. in the nested lib/ directory). Before this change it would have gone in the root of the executable JAR, causing errors at runtime. The fix is slightly awkward, since it assumes that any JAR in the "roots" of the ResourceMatcher come from the classpath (which *is* the case currently, but might not always be at least in principle). Seems like a reasonable compromise given it's a quick change and some tests have been included. Fixes gh-565 --- .../boot/cli/command/jar/JarCommand.java | 6 ++- .../boot/cli/command/jar/ResourceMatcher.java | 2 +- .../cli/command/jar/ResourceMatcherTests.java | 54 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java index 51f3be65f8..e6748ac4cb 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java @@ -155,9 +155,11 @@ public class JarCommand extends OptionParsingCommand { options.valuesOf(this.excludeOption)); List roots = new ArrayList(); for (URL classpathEntry : classpath) { - roots.add(new File(URI.create(classpathEntry.toString()))); + File file = new File(URI.create(classpathEntry.toString())); + roots.add(file); } - return matcher.find(roots); + List found = matcher.find(roots); + return found; } private void writeJar(File file, Class[] compiledClasses, diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/ResourceMatcher.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/ResourceMatcher.java index 7523b11b40..403cf2ebd8 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/ResourceMatcher.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/ResourceMatcher.java @@ -147,7 +147,7 @@ class ResourceMatcher { private MatchedResource(File file) { this.name = file.getName(); this.file = file; - this.root = false; + this.root = this.name.endsWith(".jar"); } private MatchedResource(File rootFolder, File file) { diff --git a/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/jar/ResourceMatcherTests.java b/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/jar/ResourceMatcherTests.java index 288e48a594..8a242addf5 100644 --- a/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/jar/ResourceMatcherTests.java +++ b/spring-boot-cli/src/test/java/org/springframework/boot/cli/command/jar/ResourceMatcherTests.java @@ -22,10 +22,15 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.hamcrest.Description; +import org.hamcrest.TypeSafeMatcher; import org.junit.Test; import org.springframework.boot.cli.command.jar.ResourceMatcher.MatchedResource; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** @@ -45,6 +50,27 @@ public class ResourceMatcherTests { assertEquals(0, matchedResources.size()); } + @Test + public void excludedWins() throws Exception { + ResourceMatcher resourceMatcher = new ResourceMatcher(Arrays.asList("*"), + Arrays.asList("**/*.jar")); + List found = resourceMatcher.find(Arrays.asList(new File( + "src/test/resources"))); + assertThat(found, not(hasItem(new FooJarMatcher(MatchedResource.class)))); + } + + @Test + public void jarFileAlwaysMatches() throws Exception { + ResourceMatcher resourceMatcher = new ResourceMatcher(Arrays.asList("*"), + Arrays.asList("**/*.jar")); + List found = resourceMatcher.find(Arrays.asList(new File( + "src/test/resources/templates"), new File("src/test/resources/foo.jar"))); + FooJarMatcher matcher = new FooJarMatcher(MatchedResource.class); + assertThat(found, hasItem(matcher)); + // A jar file is always treated as a dependency (stick it in /lib) + assertTrue(matcher.getMatched().isRoot()); + } + @Test public void resourceMatching() throws IOException { List matchedResources = this.resourceMatcher.find(Arrays.asList( @@ -61,4 +87,32 @@ public class ResourceMatcherTests { assertTrue(paths.containsAll(Arrays.asList("alpha/nested/fileA", "bravo/fileC", "fileD", "bravo/fileE", "fileF", "three"))); } + + private final class FooJarMatcher extends TypeSafeMatcher { + + private MatchedResource matched; + + public MatchedResource getMatched() { + return this.matched; + } + + private FooJarMatcher(Class expectedType) { + super(expectedType); + } + + @Override + public void describeTo(Description description) { + description.appendText("foo.jar"); + } + + @Override + protected boolean matchesSafely(MatchedResource item) { + boolean matches = item.getFile().getName().equals("foo.jar"); + if (matches) { + this.matched = item; + } + return matches; + } + } + }