This is an automated email from the ASF dual-hosted git repository. tibordigana pushed a commit to branch SUREFIRE-1617 in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit 89d8f23be9a3669738536a4cbaf4368dafee92d1 Author: tibordigana <[email protected]> AuthorDate: Sun Apr 7 23:06:45 2019 +0200 [SUREFIRE-1617] Surefire fails with bad message when path contains whitespaces and colon --- .../booterclient/JarManifestForkConfiguration.java | 34 ++++++++++++++- .../JarManifestForkConfigurationTest.java | 48 +++++++++++++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java index 62fa4c1..285e747 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java @@ -31,8 +31,11 @@ import javax.annotation.Nullable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Iterator; @@ -215,8 +218,37 @@ public final class JarManifestForkConfiguration ClasspathElementUri( URI uri ) { - this.uri = uri.toASCIIString(); + this.uri = escapeUri( uri.toASCIIString(), Charset.defaultCharset() ); absolute = false; } } + + static String escapeUri( String input, Charset encoding ) + { + StringBuilder b = new StringBuilder( input.length() ); + for ( int i = 0; i < input.length(); i++ ) + { + char c = input.charAt( i ); + if ( c == ' ' ) + { + b.append( "%20" ); + } + else if ( c == '%' || c == '/' || c == '\\' ) + { + b.append( c ); + } + else + { + try + { + b.append( URLEncoder.encode( String.valueOf( c ), encoding.name() ) ); + } + catch ( UnsupportedEncodingException e ) + { + b.append( c ); + } + } + } + return b.toString(); + } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java index 5e71238..b42d4c4 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java @@ -22,14 +22,17 @@ package org.apache.maven.plugin.surefire.booterclient; import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.Charset; import java.nio.file.Path; import org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri; import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.relativize; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toAbsoluteUri; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toClasspathElementUri; +import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.escapeUri; import static org.fest.assertions.Assertions.assertThat; import org.junit.AfterClass; @@ -39,7 +42,9 @@ import org.junit.runner.RunWith; import static org.fest.util.Files.delete; import static org.fest.util.Files.newTemporaryFolder; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.same; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; @@ -88,6 +93,8 @@ public class JarManifestForkConfigurationTest .thenReturn( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" ); } @@ -105,6 +112,8 @@ public class JarManifestForkConfigurationTest .thenReturn( "../../../../../the Maven repo/grp/art/1.0/art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../../../the%20Maven%20repo/grp/art/1.0/art-1.0.jar" ); } @@ -122,6 +131,8 @@ public class JarManifestForkConfigurationTest .thenReturn( "..\\..\\..\\Users\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../Users/me/.m2/repository/grp/art/1.0/art-1.0.jar" ); } @@ -134,11 +145,14 @@ public class JarManifestForkConfigurationTest Path parent = mock( Path.class ); when( parent.toString() ).thenReturn( "C:\\Windows\\Temp\\surefire" ); Path classPathElement = mock( Path.class ); - when( classPathElement.toString() ).thenReturn( "C:\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); + when( classPathElement.toString() ) + .thenReturn("C:\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar"); when( relativize( parent, classPathElement ) ) .thenReturn( "..\\..\\..\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../Test%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" ); } @@ -168,6 +182,8 @@ public class JarManifestForkConfigurationTest .thenThrow( new IllegalArgumentException() ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); when( toAbsoluteUri( same( classPathElement ) ) ) .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) @@ -175,6 +191,34 @@ public class JarManifestForkConfigurationTest } @Test + public void shouldEscapeUri() + { + assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" ); + assertThat( escapeUri( " ", UTF_8 ) ).isEqualTo( "%20" ); + assertThat( escapeUri( "%", UTF_8 ) ).isEqualTo( "%" ); + assertThat( escapeUri( ",", UTF_8 ) ).isEqualTo( "%2C" ); + assertThat( escapeUri( "/", UTF_8 ) ).isEqualTo( "/" ); + assertThat( escapeUri( "7", UTF_8 ) ).isEqualTo( "7" ); + assertThat( escapeUri( ":", UTF_8 ) ).isEqualTo( "%3A" ); + assertThat( escapeUri( "@", UTF_8 ) ).isEqualTo( "%40" ); + assertThat( escapeUri( "A", UTF_8 ) ).isEqualTo( "A" ); + assertThat( escapeUri( "[", UTF_8 ) ).isEqualTo( "%5B" ); + assertThat( escapeUri( "\\", UTF_8 ) ).isEqualTo( "\\" ); + assertThat( escapeUri( "]", UTF_8 ) ).isEqualTo( "%5D" ); + assertThat( escapeUri( "`", UTF_8 ) ).isEqualTo( "%60" ); + assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" ); + assertThat( escapeUri( "{", UTF_8 ) ).isEqualTo( "%7B" ); + assertThat( escapeUri( "" + (char) 0xFF, UTF_8 ) ).isEqualTo( "%C3%BF" ); + + assertThat( escapeUri( "..\\..\\..\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar", UTF_8 ) ) + .isEqualTo( "..\\..\\..\\Test%20User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); + + assertThat( escapeUri( "..\\..\\..\\Test : User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar", + Charset.defaultCharset() ) ) + .isEqualTo( "..\\..\\..\\Test%20%3A%20User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); + } + + @Test public void shouldRelativizeOnRealPlatform() { Path parentDir = new File( TMP, "test-parent-1" ) @@ -218,6 +262,6 @@ public class JarManifestForkConfigurationTest ClasspathElementUri testDirUriPath = toClasspathElementUri( parentDir, testDir, dumpDirectory, true ); assertThat( testDirUriPath.uri ) - .isEqualTo( "../@3%20test%20with%20white%20spaces" ); + .isEqualTo( "../%403%20test%20with%20white%20spaces" ); } }
