Skip to content

Commit

Permalink
JBEHAVE-712: Spaces in path breaks StoryFinder().findPaths()
Browse files Browse the repository at this point in the history
added method getPathFromURL to replace the URL.getFile() calls which do not decode encoded chars.
The same problem appears with other chars that have to be encoded e.g. [], accented chars.
One function in LoadFromRelativeFile used URLDecoder before, which is incorrect for + chars in path
(the class doesn't have a unit test, so I couldn't actually check for that problem, but its fixed
with the new call)
  • Loading branch information
alexlehm committed Mar 11, 2012
1 parent 15989e2 commit a45988c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import static org.apache.commons.lang.StringUtils.removeStart;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

/**
Expand All @@ -21,7 +23,7 @@ public class CodeLocations {
public static URL codeLocationFromClass(Class<?> codeLocationClass) {
String pathOfClass = codeLocationClass.getName().replace(".", "/") + ".class";
URL classResource = codeLocationClass.getClassLoader().getResource(pathOfClass);
String codeLocationPath = removeStart(removeEnd(classResource.getFile(), pathOfClass),"file:");
String codeLocationPath = removeEnd(getPathFromURL(classResource), pathOfClass);
return codeLocationFromPath(codeLocationPath);
}

Expand Down Expand Up @@ -64,4 +66,34 @@ public InvalidCodeLocation(String path) {

}

/**
* Get absolute path from URL objects starting with file:
* This method takes care of decoding %-encoded chars, e.g. %20 -> space etc
* Since we do not use a File object, the system specific path encoding
* is not used (e.g. C:\ on Windows). This is necessary to facilitate
* the removal of a class file with path in codeLocationFromClass
*
* @param url the file-URL
* @return String absolute decoded path
* @throws InvalidCodeLocation if URL contains format errors
*/
public static String getPathFromURL(URL url) {
URI uri;
try {
uri = url.toURI();
} catch (URISyntaxException e) {
// this will probably not happen since the url was created
// from a filename beforehand
throw new InvalidCodeLocation(e.toString());
}

if(uri.toString().startsWith("file:") || uri.toString().startsWith("jar:")) {
return removeStart(uri.getSchemeSpecificPart(),"file:");
} else {
// this is wrong, but should at least give a
// helpful error when trying to open the file later
return uri.toString();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -51,7 +49,7 @@ public LoadFromRelativeFile(URL location, StoryFilePath... traversals) {

public String loadResourceAsText(String resourcePath) {
List<String> traversalPaths = new ArrayList<String>();
String locationPath = new File(location.getFile()).getAbsolutePath();
String locationPath = new File(CodeLocations.getPathFromURL(location)).getAbsolutePath();
for (StoryFilePath traversal : traversals) {
String filePath = locationPath.replace(traversal.toRemove, traversal.relativePath) + "/" + resourcePath;
File file = new File(filePath);
Expand All @@ -66,12 +64,7 @@ public String loadResourceAsText(String resourcePath) {

public String loadStoryAsText(String storyPath) {
List<String> traversalPaths = new ArrayList<String>();
String locationPath;
try {
locationPath = new File(URLDecoder.decode(location.getFile(), "UTF-8")).getAbsolutePath();
} catch (UnsupportedEncodingException e) {
throw new InvalidStoryResource(storyPath, e);
}
String locationPath = new File(CodeLocations.getPathFromURL(location)).getAbsolutePath();
for (StoryFilePath traversal : traversals) {
String filePath = locationPath.replace(traversal.toRemove, traversal.relativePath) + "/" + storyPath;
File file = new File(filePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public List<String> findClassNames(String searchInDirectory, List<String> includ
* @return A List of paths found
*/
public List<String> findPaths(URL searchInURL, String include, String exclude) {
return findPaths(searchInURL.getFile(), asList(include), asList(exclude));
return findPaths(CodeLocations.getPathFromURL(searchInURL), asList(include), asList(exclude));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.StoryLocation;

/**
Expand Down Expand Up @@ -92,7 +93,7 @@ public static interface FilePathResolver {
public static abstract class AbstractPathResolver implements FilePathResolver {

public String resolveDirectory(StoryLocation storyLocation, String relativeDirectory) {
File parent = new File(storyLocation.getCodeLocation().getFile()).getParentFile();
File parent = new File(CodeLocations.getPathFromURL(storyLocation.getCodeLocation())).getParentFile();
return parent.getPath().replace('\\', '/') + "/" + relativeDirectory;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;

import org.jbehave.core.io.CodeLocations.InvalidCodeLocation;
Expand All @@ -33,10 +36,12 @@ public void shouldCreateCodeLocationFromURL() {

@Test
public void shouldCreateCodeLocationFromJarClass() {
// wrong output looks like this:
// "C:/Projects/jbehave/file:/C:/Users/Name/.m2/repository/junit/junit-dep/4.8.2/junit-dep-4.8.2.jar!"
// wrong output looks like this:
// "C:/Projects/jbehave/file:/C:/Users/Name/.m2/repository/junit/junit-dep/4.8.2/junit-dep-4.8.2.jar!"
assertThat(CodeLocations.codeLocationFromClass(this.getClass()).getFile(), not(containsString("/file:")));
assertThat(CodeLocations.codeLocationFromClass(JUnitCore.class).getFile(), not(containsString("/file:")));
final String filename = CodeLocations.codeLocationFromClass(JUnitCore.class).getFile();
assertThat(filename, not(containsString("/file:")));
assertThat(filename, not(containsString("/jar:")));
}

@Test(expected = InvalidCodeLocation.class)
Expand All @@ -54,4 +59,17 @@ public void shouldAllowInstantiation() {
assertThat(new CodeLocations(), is(notNullValue()));
}

}
@Test
public void shouldHandleSpacesAndSpecialChars() throws MalformedURLException, URISyntaxException {
assertThat(CodeLocations.getPathFromURL(CodeLocations.codeLocationFromPath("some Path")), not(containsString("%20")));
assertThat(CodeLocations.getPathFromURL(pathToURL("c:/a b c+++/")), equalTo("/c:/a b c+++"));
assertThat(CodeLocations.getPathFromURL(pathToURL("/home/user/foo bar/+++/")), endsWith("/home/user/foo bar/+++"));
assertThat(CodeLocations.getPathFromURL(CodeLocations.codeLocationFromURL("http://www.example.com/stories/")), equalTo("http://www.example.com/stories/"));
assertThat(CodeLocations.getPathFromURL(CodeLocations.codeLocationFromPath("äöü")), endsWith("/äöü"));
}

private URL pathToURL(final String path) throws MalformedURLException {
return new File(path).toURI().toURL();
}

}

0 comments on commit a45988c

Please sign in to comment.