Skip to content

Commit 783d464

Browse files
committed
Merge pull request cucumber#34 from UrsKR/issue17
Fix for issue cucumber#17: Cucumber replaces %20 when resolving jar paths on Windows
2 parents a84c753 + 875d60c commit 783d464

File tree

4 files changed

+86
-10
lines changed

4 files changed

+86
-10
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package cucumber.resources;
2+
3+
import java.io.UnsupportedEncodingException;
4+
import java.net.URLDecoder;
5+
6+
public class Decoder {
7+
public String decode(String string) throws UnsupportedEncodingException {
8+
return URLDecoder.decode(string, "UTF-8");
9+
}
10+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package cucumber.resources;
2+
3+
import cucumber.runtime.CucumberException;
4+
5+
import java.io.UnsupportedEncodingException;
6+
import java.net.URLDecoder;
7+
8+
public class FilePathExtractor {
9+
10+
private Decoder decoder;
11+
12+
public FilePathExtractor() {
13+
this(new Decoder());
14+
}
15+
16+
public FilePathExtractor(Decoder decoder) {
17+
this.decoder = decoder;
18+
}
19+
20+
public String filePath(String jarUrl) {
21+
String pathWithProtocol = jarUrl.substring(0, jarUrl.indexOf("!/"));
22+
String[] segments = pathWithProtocol.split(":");
23+
// WINDOWS: jar:file:/C:/Users/ahellesoy/scm/cucumber-jvm/java/target/java-1.0.0-SNAPSHOT.jar
24+
// POSIX: jar:file:/Users/ahellesoy/scm/cucumber-jvm/java/target/java-1.0.0-SNAPSHOT.jar
25+
String pathToJar = segments.length == 4 ? segments[2].substring(1) + ":" + segments[3] : segments[2];
26+
return resolveEncodedBlanksInPath(pathToJar);
27+
}
28+
29+
public String resolveEncodedBlanksInPath(String path) {
30+
try {
31+
return decoder.decode(path);
32+
} catch (UnsupportedEncodingException e) {
33+
throw new CucumberException("UTF-8 is not supported on your system. This should not be happening.", e);
34+
}
35+
}
36+
}

core/src/main/java/cucumber/resources/Resources.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import java.util.zip.ZipEntry;
1313
import java.util.zip.ZipFile;
1414

15+
import static cucumber.resources.FilePathExtractor.*;
16+
1517
/**
1618
* Static utility methods for looking up classes and resources on the classpath.
1719
* TODO: Look them op on the file system as well. The CLI needs to offer resources like that. DUH!
@@ -127,7 +129,7 @@ public static <T> List<T> instantiateSubclasses(Class<T> type, String packagePre
127129

128130
private static void scanJar(URL jarDir, PathWithLines pwl, String suffix, Consumer consumer) {
129131
String jarUrl = jarDir.toExternalForm();
130-
String path = filePath(jarUrl);
132+
String path = new FilePathExtractor().filePath(jarUrl);
131133
try {
132134
ZipFile jarFile = new ZipFile(path);
133135
Enumeration<? extends ZipEntry> entries = jarFile.entries();
@@ -143,14 +145,6 @@ private static void scanJar(URL jarDir, PathWithLines pwl, String suffix, Consum
143145
}
144146
}
145147

146-
private static String filePath(String jarUrl) {
147-
String pathWithProtocol = jarUrl.substring(0, jarUrl.indexOf("!/"));
148-
String[] segments = pathWithProtocol.split(":");
149-
// WINDOWS: jar:file:/C:/Users/ahellesoy/scm/cucumber-jvm/java/target/java-1.0.0-SNAPSHOT.jar
150-
// POSIX: jar:file:/Users/ahellesoy/scm/cucumber-jvm/java/target/java-1.0.0-SNAPSHOT.jar
151-
return segments.length == 4 ? segments[2].substring(1) + ":" + segments[3] : segments[2];
152-
}
153-
154148
private static void scanFilesystem(URL startDir, PathWithLines pathPrefix, String suffix, Consumer consumer) {
155149
PathWithLines dir = new PathWithLines(getPath(startDir));
156150
String rootPath = getPath(startDir).substring(0, getPath(startDir).length() - pathPrefix.path.length() - 1);
@@ -159,7 +153,8 @@ private static void scanFilesystem(URL startDir, PathWithLines pathPrefix, Strin
159153
}
160154

161155
private static String getPath(URL url) {
162-
return url.getPath().replaceAll("%20", " ");
156+
String path = url.getPath();
157+
return new FilePathExtractor().resolveEncodedBlanksInPath(path);
163158
}
164159

165160
private static void scanFilesystem(File rootDir, PathWithLines pathWithLines, String suffix, Consumer consumer) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cucumber.runtime;
2+
3+
import cucumber.resources.Decoder;
4+
import cucumber.resources.FilePathExtractor;
5+
import org.junit.Test;
6+
import org.mockito.Mockito;
7+
8+
import java.io.UnsupportedEncodingException;
9+
10+
import static org.hamcrest.CoreMatchers.*;
11+
import static org.junit.Assert.*;
12+
import static org.junit.matchers.JUnitMatchers.*;
13+
import static org.mockito.Matchers.anyString;
14+
import static org.mockito.Mockito.mock;
15+
import static org.mockito.Mockito.when;
16+
17+
/**
18+
* Tests for Issue #17
19+
*/
20+
public class FilePathExtractorTest {
21+
public static final String anyString = "";
22+
23+
@Test
24+
public void replacesUrlEncodedBlanksWithActualBlanks() {
25+
String pathToJar = new FilePathExtractor().filePath("jar:file:/C:/path%20with%20blanks/actual.jar!/content.file");
26+
assertThat(pathToJar, not(containsString("%20")));
27+
}
28+
29+
@Test(expected = CucumberException.class)
30+
public void forwardsExceptionsAsCucumberExceptions() throws Exception {
31+
Decoder decoder = mock(Decoder.class);
32+
when(decoder.decode(anyString())).thenThrow(new UnsupportedEncodingException());
33+
new FilePathExtractor(decoder).resolveEncodedBlanksInPath(anyString);
34+
}
35+
}

0 commit comments

Comments
 (0)