diff --git a/pom.xml b/pom.xml index fcd70f51c..8ce474b68 100644 --- a/pom.xml +++ b/pom.xml @@ -81,6 +81,10 @@ SOFTWARE. https://github.com/yegor256/cactoos + + src/test/test-lib + ${project.build.directory}/${project.artifactId}-test-lib-${project.version}.jar + org.takes @@ -144,6 +148,10 @@ SOFTWARE. 8 75 500 + + ${testLibJarPath} + + true @@ -172,6 +180,59 @@ SOFTWARE. + + org.apache.maven.plugins + maven-surefire-plugin + + + + org.cactoos + ${project.artifactId}-test-lib + ${project.version} + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + make-test-lib + initialize + + single + + + ${project.artifactId}-test-lib-${project.version} + + ${testLibPath}/assembly.xml + + false + + + + + + org.apache.maven.plugins + maven-install-plugin + + + make-test-lib + initialize + + install-file + + + ${testLibJarPath} + org.cactoos + ${project.artifactId}-test-lib + ${project.version} + jar + + + + org.jacoco jacoco-maven-plugin diff --git a/src/main/java/org/cactoos/io/ResourceOf.java b/src/main/java/org/cactoos/io/ResourceOf.java index e5af53e72..8a2c0c908 100644 --- a/src/main/java/org/cactoos/io/ResourceOf.java +++ b/src/main/java/org/cactoos/io/ResourceOf.java @@ -25,6 +25,12 @@ import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; import org.cactoos.Func; import org.cactoos.Input; import org.cactoos.Text; @@ -225,10 +231,18 @@ public InputStream stream() throws Exception { "The \"classloader\" is NULL, which is not allowed" ); } - InputStream input = this.loader.getResourceAsStream( - this.path.asString() - ); - if (input == null) { + final InputStream input; + final String pth = this.path.asString(); + final URL resource = this.loader.getResource(pth); + if (pth.endsWith("/") + && resource != null + && "jar".equals(resource.getProtocol()) + ) { + input = new JarDirectoryFileNameStream(resource, pth) + .files(); + } else if (resource != null) { + input = resource.openStream(); + } else { if (this.fallback == null) { throw new IllegalArgumentException( "The \"fallback\" is NULL, which is not allowed" @@ -240,4 +254,68 @@ public InputStream stream() throws Exception { } return input; } + + /** + * Class for creating a stream of file names from a directory to a jar. + * + * @since 0.56.2 + */ + private static final class JarDirectoryFileNameStream { + + /** + * URL of the jar file. + */ + private final URL url; + + /** + * Path to the directory in the jar file. + */ + private final String path; + + /** + * Ctor. + * + * @param jarurl URL of the jar file. + * @param pth The directory for which we want to get a list of files. + */ + JarDirectoryFileNameStream(final URL jarurl, final String pth) { + this.url = jarurl; + this.path = pth; + } + + /** + * Create InputStream of file names from directory to jar. + * + * @return Stream with file names. + * @throws Exception If something goes wrong + */ + public InputStream files() throws Exception { + try (JarFile jar = new JarFile(this.extract())) { + return new InputStreamOf( + jar + .stream() + .map(JarEntry::getName) + .filter( + name -> !this.path.equals(name) + && name.lastIndexOf(this.path) >= 0 + ) + .map(name -> name.substring(this.path.length())) + .collect(Collectors.joining("\n")) + .getBytes(StandardCharsets.UTF_8) + ); + } + } + + /** + * Extracts the path to a jar file from a URL. + * + * @return Path to jar file. + * @throws URISyntaxException If this URL cannot be converted to a URI. + */ + private String extract() throws URISyntaxException { + final String fullpath = this.url.toURI().getSchemeSpecificPart(); + final int idx = fullpath.indexOf("!/"); + return fullpath.substring("file:".length(), idx); + } + } } diff --git a/src/test/java/org/cactoos/io/ResourceOfTest.java b/src/test/java/org/cactoos/io/ResourceOfTest.java index 9bd2d29f4..33092f81c 100644 --- a/src/test/java/org/cactoos/io/ResourceOfTest.java +++ b/src/test/java/org/cactoos/io/ResourceOfTest.java @@ -28,11 +28,13 @@ import org.cactoos.Text; import org.cactoos.bytes.BytesOf; import org.cactoos.text.FormattedText; +import org.cactoos.text.Split; import org.cactoos.text.TextOf; import org.hamcrest.core.IsEqual; import org.junit.jupiter.api.Test; import org.llorllale.cactoos.matchers.Assertion; import org.llorllale.cactoos.matchers.EndsWith; +import org.llorllale.cactoos.matchers.HasValues; import org.llorllale.cactoos.matchers.StartsWith; import org.llorllale.cactoos.matchers.Throws; @@ -42,7 +44,7 @@ * @since 0.1 * @checkstyle JavadocMethodCheck (500 lines) */ -@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") +@SuppressWarnings({"PMD.JUnitTestsShouldIncludeAssert", "PMD.TooManyMethods"}) final class ResourceOfTest { @Test @@ -113,6 +115,66 @@ void throwsWhenResourceIsAbsent() { ).affirm(); } + @Test + void readTextFromJar() { + new Assertion<>( + "Can't to read file from jar", + new TextOf( + new BytesOf( + new ResourceOf( + "org/cactoos/io/small-text-file.txt", + "the replacement" + ) + ) + ), + new EndsWith("parent directory.") + ).affirm(); + } + + @Test + void readDirectoryFromJar() { + new Assertion<>( + "Unable to read file names from jar directory", + new Split( + new TextOf( + new BytesOf( + new ResourceOf( + "org/cactoos/io/dir/", + "the replacement" + ) + ) + ), + new TextOf("\\n") + ), + new HasValues<>( + new TextOf("second-text-file.txt"), + new TextOf("small-file-in-dir.txt") + ) + ).affirm(); + } + + @Test + void readDirectory() { + new Assertion<>( + "Unable to read file names from directory", + new Split( + new TextOf( + new BytesOf( + new ResourceOf( + "org/cactoos/", + "the replacement" + ) + ) + ), + new TextOf("\\n") + ), + new HasValues<>( + new TextOf("digest-calculation.txt"), + new TextOf("small-text.txt") + ) + ).affirm(); + } + @Test void acceptsTextAsResourceName() { new Assertion<>( diff --git a/src/test/test-lib/assembly.xml b/src/test/test-lib/assembly.xml new file mode 100644 index 000000000..5aab736e0 --- /dev/null +++ b/src/test/test-lib/assembly.xml @@ -0,0 +1,42 @@ + + + + test-lib + + jar + + false + + + ${project.basedir}/${testLibPath} + / + + org/cactoos/io/small-text-file.txt + org/cactoos/io/dir/second-text-file.txt + org/cactoos/io/dir/small-file-in-dir.txt + + + + diff --git a/src/test/test-lib/org/cactoos/io/dir/second-text-file.txt b/src/test/test-lib/org/cactoos/io/dir/second-text-file.txt new file mode 100644 index 000000000..e77d8b257 --- /dev/null +++ b/src/test/test-lib/org/cactoos/io/dir/second-text-file.txt @@ -0,0 +1 @@ +Second text file. \ No newline at end of file diff --git a/src/test/test-lib/org/cactoos/io/dir/small-file-in-dir.txt b/src/test/test-lib/org/cactoos/io/dir/small-file-in-dir.txt new file mode 100644 index 000000000..d63be22f2 --- /dev/null +++ b/src/test/test-lib/org/cactoos/io/dir/small-file-in-dir.txt @@ -0,0 +1 @@ +Small file in the directory. \ No newline at end of file diff --git a/src/test/test-lib/org/cactoos/io/small-text-file.txt b/src/test/test-lib/org/cactoos/io/small-text-file.txt new file mode 100644 index 000000000..61ef2bac6 --- /dev/null +++ b/src/test/test-lib/org/cactoos/io/small-text-file.txt @@ -0,0 +1 @@ +Small file in the parent directory. \ No newline at end of file