From 4da249961355c1405077e62cb2d94f07f94e1952 Mon Sep 17 00:00:00 2001 From: Derrick Anderson Date: Fri, 6 Mar 2020 21:26:28 -0600 Subject: [PATCH] Introduce Resource::getContentAsString This commit introduces the getContentAsString method to Resource, returning the string contents of the resource. Closes gh-24651 --- .../io/AbstractFileResolvingResource.java | 36 +++++++++++++++++ .../org/springframework/core/io/Resource.java | 39 +++++++++++++++++++ .../core/io/ResourceTests.java | 21 ++++++++++ .../org/springframework/core/io/example.xml | 3 +- 4 files changed, 97 insertions(+), 2 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java b/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java index 89a97883c2..bfbe24aad5 100644 --- a/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java @@ -26,7 +26,10 @@ import java.net.URL; import java.net.URLConnection; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; +import java.nio.charset.Charset; +import java.nio.file.Files; import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.jar.JarEntry; @@ -320,6 +323,39 @@ public abstract class AbstractFileResolvingResource extends AbstractResource { protected void customizeConnection(HttpURLConnection con) throws IOException { } + /** + * This implementation returns the contents of a file as a string using the + * system default Charset. Provided the resource exists and the context has + * access to it, the contents will be returned as a single string with line + * feed characters retained. + * @return the contents of the requested file as a {@code String}. + * @throws FileNotFoundException in the event the file path is invalid. + * @throws IOException if the file can not be read or cannot be serialzied. + */ + @Override + public String getContentAsString() throws IOException { + + if( !exists() ) { + throw new FileNotFoundException(getDescription() + " cannot be found."); + } + if ( !isReadable() ) { + throw new IOException(getDescription() + " cannot be opened for reading."); + } + return new String(Files.readAllBytes(Paths.get(getFile().getAbsolutePath())), Charset.defaultCharset()); + } + + @Override + public String getContentAsString(Charset charset) throws IOException { + + if( !exists() ) { + throw new FileNotFoundException(getDescription() + " cannot be found."); + } + if ( !isReadable() ) { + throw new IOException(getDescription() + " cannot be opened for reading."); + } + return new String(Files.readAllBytes(Paths.get(getFile().getAbsolutePath())), charset); + + } /** * Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime. diff --git a/spring-core/src/main/java/org/springframework/core/io/Resource.java b/spring-core/src/main/java/org/springframework/core/io/Resource.java index 740d571931..0d665d98f0 100644 --- a/spring-core/src/main/java/org/springframework/core/io/Resource.java +++ b/spring-core/src/main/java/org/springframework/core/io/Resource.java @@ -17,12 +17,14 @@ package org.springframework.core.io; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; +import java.nio.charset.Charset; import org.springframework.lang.Nullable; @@ -176,4 +178,41 @@ public interface Resource extends InputStreamSource { */ String getDescription(); + /** + * Return a {@link ReadableByteChannel}. + *

It is expected that each call creates a fresh channel. + *

The default implementation returns {@link Channels#newChannel(InputStream)} + * with the result of {@link #getInputStream()}. + * @return the byte channel for the underlying resource (must not be {@code null}) + * @throws java.io.FileNotFoundException if the underlying resource doesn't exist + * @throws IOException if the content channel could not be opened + * @since 5.0 + * @see #getInputStream() + */ + + /** + * Returns the contents of a file as a string using the system default Charset. + *

The default implementation returns a {@link Object#toString()} representation of the resource. + * @return the contents of the requested file as a {@code String}. + * @throws FileNotFoundException in the event the file path is invalid. + * @throws IOException if the file can not be read or cannot be accessed. + * @since 5.2.5 + */ + default String getContentAsString() throws IOException{ + return toString(); + } + + /** + * Returns the contents of a file as a string using the specified Charset. + *

The default implementation returns a {@link Object#toString()} representation of the resource. + * @param charset the {@code Charset} to use to deserialize the content. Defaults to system default. + * @return the contents of the requested file as a {@code String}. + * @throws FileNotFoundException in the event the file path is invalid. + * @throws IOException if the file can not be read or cannot be accessed. + * @since 5.2.5 + */ + default String getContentAsString(Charset charset) throws IOException{ + return toString(); + } + } diff --git a/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java index 0744ece766..70d7dbd534 100644 --- a/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java +++ b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java @@ -456,4 +456,25 @@ class ResourceTests { } + @Test + void getContentAsString_givenValidFile_ShouldReturnFileContent() throws IOException { + String expectedString = "\n" + + "\n" + + "\n" + + "\tbar\n" + + ""; + + String fileDirString = + new ClassPathResource("org/springframework/core/io/example.xml").getContentAsString(); + assertThat(fileDirString).isNotBlank(); + assertThat(fileDirString).isEqualTo(expectedString); + } + + @Test + void getContentAsString_givenAnInvalidFile_ShouldThrowFileNotFoundException(){ + assertThatExceptionOfType(FileNotFoundException.class) + .isThrownBy(new ClassPathResource("nonExistantFile")::getContentAsString); + + } + } diff --git a/spring-core/src/test/resources/org/springframework/core/io/example.xml b/spring-core/src/test/resources/org/springframework/core/io/example.xml index 1d638537e1..b9d4450840 100644 --- a/spring-core/src/test/resources/org/springframework/core/io/example.xml +++ b/spring-core/src/test/resources/org/springframework/core/io/example.xml @@ -2,5 +2,4 @@ bar - - + \ No newline at end of file