diff --git a/History.md b/History.md index ce9f560d62..c43aead706 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,6 @@ ## [1.2.3-SNAPSHOT](https://github.com/cucumber/cucumber-jvm/compare/v1.2.2...master) (In Git) +* [Core] Properly decode jar URLs with spaces (%20) - ([#866](https://github.com/cucumber/cucumber-jvm/issues/866) Aslak Hellesøy) * [Java] Arity mismatch Java8 Step Definition error ([#852](https://github.com/cucumber/cucumber-jvm/issues/852), [#847](https://github.com/cucumber/cucumber-jvm/pull/847) David Coelho) * [Java] Print Java 8 lambda snippets when `cucumber-java8` is active (Aslak Hellesøy) * [Core] Make the Summary Printer into a plugin ([#828](https://github.com/cucumber/cucumber-jvm/pull/828) Björn Rasmusson) diff --git a/core/src/main/java/cucumber/runtime/io/ClasspathResourceIterable.java b/core/src/main/java/cucumber/runtime/io/ClasspathResourceIterable.java index d1b4c36140..77c6133f1f 100644 --- a/core/src/main/java/cucumber/runtime/io/ClasspathResourceIterable.java +++ b/core/src/main/java/cucumber/runtime/io/ClasspathResourceIterable.java @@ -39,15 +39,4 @@ public Iterator iterator() { } } - static boolean hasSuffix(String suffix, String name) { - return suffix == null || name.endsWith(suffix); - } - - static String getPath(URL url) { - try { - return URLDecoder.decode(url.getPath(), "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new CucumberException("Encoding problem", e); - } - } } diff --git a/core/src/main/java/cucumber/runtime/io/FileResourceIterator.java b/core/src/main/java/cucumber/runtime/io/FileResourceIterator.java index f09be7f4f1..7a66c98025 100644 --- a/core/src/main/java/cucumber/runtime/io/FileResourceIterator.java +++ b/core/src/main/java/cucumber/runtime/io/FileResourceIterator.java @@ -4,7 +4,7 @@ import java.io.FileFilter; import java.util.Iterator; -import static cucumber.runtime.io.ClasspathResourceIterable.hasSuffix; +import static cucumber.runtime.io.Helpers.hasSuffix; import static java.util.Arrays.asList; public class FileResourceIterator implements Iterator { diff --git a/core/src/main/java/cucumber/runtime/io/FileResourceIteratorFactory.java b/core/src/main/java/cucumber/runtime/io/FileResourceIteratorFactory.java index d3d08c1004..d4de92548b 100644 --- a/core/src/main/java/cucumber/runtime/io/FileResourceIteratorFactory.java +++ b/core/src/main/java/cucumber/runtime/io/FileResourceIteratorFactory.java @@ -4,7 +4,7 @@ import java.net.URL; import java.util.Iterator; -import static cucumber.runtime.io.ClasspathResourceIterable.getPath; +import static cucumber.runtime.io.Helpers.filePath; /** * Factory which creates {@link FileResourceIterator}s. @@ -25,7 +25,7 @@ public boolean isFactoryFor(URL url) { @Override public Iterator createIterator(URL url, String path, String suffix) { - File file = new File(getPath(url)); + File file = new File(filePath(url)); File rootDir = new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - path.length())); return new FileResourceIterator(rootDir, file, suffix); } diff --git a/core/src/main/java/cucumber/runtime/io/Helpers.java b/core/src/main/java/cucumber/runtime/io/Helpers.java new file mode 100644 index 0000000000..c6ee649c3e --- /dev/null +++ b/core/src/main/java/cucumber/runtime/io/Helpers.java @@ -0,0 +1,32 @@ +package cucumber.runtime.io; + +import cucumber.runtime.CucumberException; + +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; + +public class Helpers { + static boolean hasSuffix(String suffix, String name) { + return suffix == null || name.endsWith(suffix); + } + + static String filePath(URL url) { + try { + return url.toURI().getSchemeSpecificPart(); + } catch (URISyntaxException e) { + throw new CucumberException(e); + } + } + + static String jarFilePath(URL jarUrl) throws UnsupportedEncodingException, MalformedURLException { + String urlFile = jarUrl.getFile(); + + int separatorIndex = urlFile.indexOf("!/"); + if (separatorIndex == -1) { + throw new CucumberException("Not a jar URL: " + jarUrl.toExternalForm()); + } + return filePath(new URL(urlFile.substring(0, separatorIndex))); + } +} diff --git a/core/src/main/java/cucumber/runtime/io/ZipResourceIterator.java b/core/src/main/java/cucumber/runtime/io/ZipResourceIterator.java index 9ed538f384..fe0f8abdbf 100644 --- a/core/src/main/java/cucumber/runtime/io/ZipResourceIterator.java +++ b/core/src/main/java/cucumber/runtime/io/ZipResourceIterator.java @@ -50,7 +50,7 @@ private void moveToNext() { while (entries.hasMoreElements()) { ZipEntry jarEntry = entries.nextElement(); String entryName = jarEntry.getName(); - if (entryName.startsWith(path) && ClasspathResourceIterable.hasSuffix(suffix, entryName)) { + if (entryName.startsWith(path) && Helpers.hasSuffix(suffix, entryName)) { next = new ZipResource(jarFile, jarEntry); break; } diff --git a/core/src/main/java/cucumber/runtime/io/ZipResourceIteratorFactory.java b/core/src/main/java/cucumber/runtime/io/ZipResourceIteratorFactory.java index eb77d50945..2b2e41dba8 100644 --- a/core/src/main/java/cucumber/runtime/io/ZipResourceIteratorFactory.java +++ b/core/src/main/java/cucumber/runtime/io/ZipResourceIteratorFactory.java @@ -1,9 +1,6 @@ package cucumber.runtime.io; -import java.io.File; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; @@ -15,27 +12,15 @@ */ public class ZipResourceIteratorFactory implements ResourceIteratorFactory { - static String filePath(URL jarUrl) throws UnsupportedEncodingException, MalformedURLException { - String urlFile = jarUrl.getFile(); - - int separatorIndex = urlFile.indexOf("!/"); - if (separatorIndex != -1) { - urlFile = urlFile.substring(0, separatorIndex); - } - - URL url = new URL(urlFile); - return new File(url.getFile()).getPath(); - } - @Override public boolean isFactoryFor(URL url) { - return url.getFile().indexOf("!/") != -1; + return url.getFile().contains("!/"); } @Override public Iterator createIterator(URL url, String path, String suffix) { try { - String jarPath = filePath(url); + String jarPath = Helpers.jarFilePath(url); return new ZipResourceIterator(jarPath, path, suffix); } catch (IOException e) { throw new CucumberException(e); diff --git a/core/src/test/java/cucumber/runtime/io/ClasspathResourceIterableTest.java b/core/src/test/java/cucumber/runtime/io/ClasspathResourceIterableTest.java deleted file mode 100644 index 3cd39484a2..0000000000 --- a/core/src/test/java/cucumber/runtime/io/ClasspathResourceIterableTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package cucumber.runtime.io; - -import org.junit.Test; - -import java.io.File; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; - -import static cucumber.runtime.io.ZipResourceIteratorFactory.filePath; -import static org.junit.Assert.assertEquals; - -public class ClasspathResourceIterableTest { - @Test - public void computes_file_path_for_windows_path() throws UnsupportedEncodingException, MalformedURLException { - if (File.separatorChar == '\\') { - // Windows - URL url = new URL("jar:file:/C:/src/cucumber-jvm/core/target/cucumber-core-1.0.0.RC12-SNAPSHOT.jar!/cucumber/runtime"); - assertEquals(new File("C:/src/cucumber-jvm/core/target/cucumber-core-1.0.0.RC12-SNAPSHOT.jar").getAbsolutePath(), filePath(url)); - } else { - // POSIX - URL url = new URL("jar:file:/src/cucumber-jvm/core/target/cucumber-core-1.0.0.RC12-SNAPSHOT.jar!/cucumber/runtime"); - assertEquals(new File("/src/cucumber-jvm/core/target/cucumber-core-1.0.0.RC12-SNAPSHOT.jar").getAbsolutePath(), filePath(url)); - } - } - - @Test - public void computes_file_path_for_windows_path_with_dots() throws UnsupportedEncodingException, MalformedURLException { - if (File.separatorChar == '\\') { - // Windows - URL url = new URL("jar:file:C:/src/cucumber-jvm/jruby/bin/../lib/cucumber-jruby-full.jar!/cucumber/runtime"); - assertEquals(new File("C:/src/cucumber-jvm/jruby/bin/../lib/cucumber-jruby-full.jar").getAbsolutePath(), filePath(url)); - } else { - // POSIX - URL url = new URL("jar:file:/src/cucumber-jvm/jruby/bin/../lib/cucumber-jruby-full.jar!/cucumber/runtime"); - assertEquals(new File("/src/cucumber-jvm/jruby/bin/../lib/cucumber-jruby-full.jar").getAbsolutePath(), filePath(url)); - } - } -} diff --git a/core/src/test/java/cucumber/runtime/io/HelpersTest.java b/core/src/test/java/cucumber/runtime/io/HelpersTest.java new file mode 100644 index 0000000000..4e0443b0ae --- /dev/null +++ b/core/src/test/java/cucumber/runtime/io/HelpersTest.java @@ -0,0 +1,40 @@ +package cucumber.runtime.io; + +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +import static cucumber.runtime.io.Helpers.filePath; +import static cucumber.runtime.io.Helpers.jarFilePath; +import static org.junit.Assert.assertEquals; + +public class HelpersTest { + private static final URLStreamHandler NULL_URL_STREAM_HANDLER = new URLStreamHandler() { + @Override + protected URLConnection openConnection(URL u) throws IOException { + throw new UnsupportedOperationException(); + } + }; + + @Test + public void computes_file_path_for_file_url() throws UnsupportedEncodingException, MalformedURLException { + URL url = new URL("file:/Users/First%20Last/.m2/repository/info/cukes/cucumber-java/1.2.2/cucumber-java-1.2.2.jar"); + assertEquals(new File("/Users/First Last/.m2/repository/info/cukes/cucumber-java/1.2.2/cucumber-java-1.2.2.jar").getAbsolutePath(), filePath(url)); + } + + @Test + public void computes_file_path_for_jar_protocols() throws Exception { + assertEquals("foo bar+zap/cucumber-core.jar", jarFilePath(new URL("jar:file:foo%20bar+zap/cucumber-core.jar!/cucumber/runtime/io"))); + assertEquals("foo bar+zap/cucumber-core.jar", jarFilePath(new URL(null, "zip:file:foo%20bar+zap/cucumber-core.jar!/cucumber/runtime/io", NULL_URL_STREAM_HANDLER))); + assertEquals("foo bar+zap/cucumber-core.jar", jarFilePath(new URL(null, "wsjar:file:foo%20bar+zap/cucumber-core.jar!/cucumber/runtime/io", NULL_URL_STREAM_HANDLER))); + assertEquals("foo bar+zap/cucumber-core.jar", jarFilePath(new URL("jar:file:foo%20bar+zap/cucumber-core.jar!/"))); + assertEquals("foo bar+zap/cucumber-core.jar", jarFilePath(new URL(null, "zip:file:foo%20bar+zap/cucumber-core.jar!/", NULL_URL_STREAM_HANDLER))); + assertEquals("foo bar+zap/cucumber-core.jar", jarFilePath(new URL(null, "wsjar:file:foo%20bar+zap/cucumber-core.jar!/", NULL_URL_STREAM_HANDLER))); + } +} diff --git a/core/src/test/java/cucumber/runtime/io/ZipResourceIteratorFactoryTest.java b/core/src/test/java/cucumber/runtime/io/ZipResourceIteratorFactoryTest.java index 28e258883d..34649647d8 100644 --- a/core/src/test/java/cucumber/runtime/io/ZipResourceIteratorFactoryTest.java +++ b/core/src/test/java/cucumber/runtime/io/ZipResourceIteratorFactoryTest.java @@ -1,16 +1,14 @@ package cucumber.runtime.io; -import static cucumber.runtime.io.ZipResourceIteratorFactory.filePath; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Test; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; -import org.junit.Test; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; // https://github.com/cucumber/cucumber-jvm/issues/808 public class ZipResourceIteratorFactoryTest { @@ -18,7 +16,7 @@ public class ZipResourceIteratorFactoryTest { private static final URLStreamHandler NULL_URL_STREAM_HANDLER = new URLStreamHandler() { @Override protected URLConnection openConnection(URL u) throws IOException { - return null; + throw new UnsupportedOperationException(); } }; @@ -32,14 +30,4 @@ public void is_factory_for_jar_protocols() throws IOException { assertFalse(factory.isFactoryFor(new URL("file:cucumber-core"))); assertFalse(factory.isFactoryFor(new URL("http://http://cukes.info/cucumber-core.jar"))); } - - @Test - public void computes_file_path_for_jar_protocols() throws Exception { - assertEquals("cucumber-core.jar", filePath(new URL("jar:file:cucumber-core.jar!/cucumber/runtime/io"))); - assertEquals("cucumber-core.jar", filePath(new URL(null, "zip:file:cucumber-core.jar!/cucumber/runtime/io", NULL_URL_STREAM_HANDLER))); - assertEquals("cucumber-core.jar", filePath(new URL(null, "wsjar:file:cucumber-core.jar!/cucumber/runtime/io", NULL_URL_STREAM_HANDLER))); - assertEquals("cucumber-core.jar", filePath(new URL("jar:file:cucumber-core.jar!/"))); - assertEquals("cucumber-core.jar", filePath(new URL(null, "zip:file:cucumber-core.jar!/", NULL_URL_STREAM_HANDLER))); - assertEquals("cucumber-core.jar", filePath(new URL(null, "wsjar:file:cucumber-core.jar!/", NULL_URL_STREAM_HANDLER))); - } }