JBehave
  1. JBehave
  2. JBEHAVE-389

Spaces in Path breaks LoadFromRelativeFile

    Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 3.0.3
    • Fix Version/s: 3.2
    • Component/s: Core
    • Labels:
      None
    • Environment:
      Redhat Linux 5.5
    • Testcase included:
      yes
    • Patch Submitted:
      Yes
    • Number of attachments :
      0

      Description

      LoadFromRelativeFile function loadStoryAsTextfails to unescape URLs passed into the constructor that have escaped characters like %20 for a space. As a result, the story files cannot be found.

      Test case snippet follows... add it to StoryLoaderBehaviour.java. Also need to add folder "foldername has spaces" to jbehave-core/src/test/java/org/jbehave/core/io/stories/ and copy MyPendingStory.txt into it. Also including revised code snippet for loadStoryAsText function. I didn't immediately see a way to do it without either checked exceptions or deprecated functions (ex UrlDecoder.decode(string)). Not sure if InvalidStoryResource was the right exception to convert to.

      StoryLoaderBehaviour.java
          @Test
          public void shouldLoadStoryFromRelativeFilePathsWithSpace() throws MalformedURLException, URISyntaxException {
              // Given
              String storyPath = "MyPendingStory.txt";
              String storyAsText = "Given my step";
              java.net.URL url = CodeLocations.codeLocationFromClass(MyPendingStory.class);
              java.io.File folderWithSpacesInName = new java.io.File(url.toURI().getPath() + "/org/jbehave/core/io/stories/foldername has spaces");
              java.net.URL urlThatHasEscapedSpaces = folderWithSpacesInName.toURI().toURL();
              assertThat(folderWithSpacesInName.exists(), is(true));
      
              // When
              StoryLoader loader = new LoadFromRelativeFile(urlThatHasEscapedSpaces);
      
              // Then
              assertThat(loader.loadStoryAsText(storyPath), equalTo(storyAsText));
          }
      
      LoadFromRelativeFile.java
          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);
      		}
              for (StoryFilePath traversal : traversals) {
                  String filePath = locationPath.replace(traversal.toRemove, traversal.relativePath) + "/" + storyPath;
                  File file = new File(filePath);
                  if (file.exists()) {
                      return loadContent(filePath);
                  } else {
                      traversalPaths.add(filePath);
                  }
              }
              throw new StoryResourceNotFound(storyPath, traversalPaths);
          }
      

        Activity

        Mauro Talevi made changes -
        Field Original Value New Value
        Fix Version/s 3.2 [ 16757 ]
        Hide
        Ayrat added a comment -

        I had a similar issue, my project was in [mage_hg] folder and I got "story not found" exception.
        Couldn't understand what was going wrong until downloaded sources and debugged where I found out that "[mage_hg]" is converted to "%5bmage%5d".

        If anyone don't want to fix sources, here is the workaround I came to: extend LoadFromRelativeFile and use it in configuration:

        MageEmbedder.java
           //
           private class MageStoryFilePath extends LoadFromRelativeFile {
        
                private final StoryFilePath[] traversals;
                private final URL location;
        
                public MageStoryFilePath(URL location, StoryFilePath... traversals) {
                    super(location, traversals);
                    this.location = location;
                    this.traversals = traversals;
                }
        
                @Override
                public String loadResourceAsText(String resourcePath) {
                    List<String> traversalPaths = new ArrayList<String>();
                    String locationPath = new File(location.getFile()).getAbsolutePath();
        
                    // Add here your code for conversion
        
                    File file = new File(filePath);
                    if (file.exists()) {
                            return loadContent(filePath);
                    }
        
                    throw new StoryResourceNotFound(resourcePath, traversalPaths);
                }
        
            }
        
            @Override
            public Configuration configuration() {
                Class<?> embedderClass = this.getClass();
                URL codeLocation = CodeLocations.codeLocationFromClass(embedderClass);
                Configuration configuration = new MostUsefulConfiguration()
                     .useStoryLoader(new MageStoryFilePath(codeLocation, LoadFromRelativeFile.mavenModuleTestStoryFilePath("src/test/java") ))
                     .useStoryReporterBuilder(new StoryReporterBuilder()
                             .withCodeLocation(codeLocation)
                             .withDefaultFormats());
                return configuration;
            }
        
        
        
        Show
        Ayrat added a comment - I had a similar issue, my project was in [mage_hg] folder and I got "story not found" exception. Couldn't understand what was going wrong until downloaded sources and debugged where I found out that " [mage_hg] " is converted to "%5bmage%5d". If anyone don't want to fix sources, here is the workaround I came to: extend LoadFromRelativeFile and use it in configuration: MageEmbedder.java // private class MageStoryFilePath extends LoadFromRelativeFile { private final StoryFilePath[] traversals; private final URL location; public MageStoryFilePath(URL location, StoryFilePath... traversals) { super (location, traversals); this .location = location; this .traversals = traversals; } @Override public String loadResourceAsText( String resourcePath) { List< String > traversalPaths = new ArrayList< String >(); String locationPath = new File(location.getFile()).getAbsolutePath(); // Add here your code for conversion File file = new File(filePath); if (file.exists()) { return loadContent(filePath); } throw new StoryResourceNotFound(resourcePath, traversalPaths); } } @Override public Configuration configuration() { Class <?> embedderClass = this .getClass(); URL codeLocation = CodeLocations.codeLocationFromClass(embedderClass); Configuration configuration = new MostUsefulConfiguration() .useStoryLoader( new MageStoryFilePath(codeLocation, LoadFromRelativeFile.mavenModuleTestStoryFilePath( "src/test/java" ) )) .useStoryReporterBuilder( new StoryReporterBuilder() .withCodeLocation(codeLocation) .withDefaultFormats()); return configuration; }
        Paul Hammant made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Assignee Paul Hammant [ paul ]
        Resolution Fixed [ 1 ]
        Paul Hammant made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Mauro Talevi made changes -
        Resolution Fixed [ 1 ]
        Status Closed [ 6 ] Reopened [ 4 ]
        Mauro Talevi made changes -
        Status Reopened [ 4 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]

          People

          • Assignee:
            Paul Hammant
            Reporter:
            Leif Carlsen
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: