Browse Source

Polishing external contribution

This commit makes several changes to PR #24651.

- Add byte[] getContentAsByteArray() on Resource.
- Remove getContentAsString() from Resource, as it relied on the default
charset which is not reliable.
- Add getContentAsString() to EncodedResource, as a charset is provided
through the constructor.

See gh-24651
pull/29975/head
Arjen Poutsma 3 years ago
parent
commit
12d4dc1bae
  1. 36
      spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java
  2. 16
      spring-core/src/main/java/org/springframework/core/io/ByteArrayResource.java
  3. 23
      spring-core/src/main/java/org/springframework/core/io/FileSystemResource.java
  4. 23
      spring-core/src/main/java/org/springframework/core/io/PathResource.java
  5. 52
      spring-core/src/main/java/org/springframework/core/io/Resource.java
  6. 23
      spring-core/src/main/java/org/springframework/core/io/support/EncodedResource.java
  7. 88
      spring-core/src/test/java/org/springframework/core/io/ResourceTests.java
  8. 3
      spring-core/src/test/resources/org/springframework/core/io/example.xml
  9. 13
      spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java
  10. 13
      spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionResourceResolver.java
  11. 13
      spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java
  12. 13
      spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java

36
spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java

@ -26,10 +26,7 @@ import java.net.URL; @@ -26,10 +26,7 @@ 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;
@ -323,39 +320,6 @@ public abstract class AbstractFileResolvingResource extends AbstractResource { @@ -323,39 +320,6 @@ 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.

16
spring-core/src/main/java/org/springframework/core/io/ByteArrayResource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package org.springframework.core.io; @@ -19,6 +19,7 @@ package org.springframework.core.io;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import org.springframework.lang.Nullable;
@ -100,6 +101,19 @@ public class ByteArrayResource extends AbstractResource { @@ -100,6 +101,19 @@ public class ByteArrayResource extends AbstractResource {
return new ByteArrayInputStream(this.byteArray);
}
@Override
public byte[] getContentAsByteArray() throws IOException {
int length = this.byteArray.length;
byte[] result = new byte[length];
System.arraycopy(this.byteArray, 0, result, 0, length);
return result;
}
@Override
public String getContentAsString(Charset charset) throws IOException {
return new String(this.byteArray, charset);
}
/**
* This implementation returns a description that includes the passed-in
* {@code description}, if any.

23
spring-core/src/main/java/org/springframework/core/io/FileSystemResource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,6 +27,7 @@ import java.net.URL; @@ -27,6 +27,7 @@ import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
@ -196,6 +197,26 @@ public class FileSystemResource extends AbstractResource implements WritableReso @@ -196,6 +197,26 @@ public class FileSystemResource extends AbstractResource implements WritableReso
}
}
@Override
public byte[] getContentAsByteArray() throws IOException {
try {
return Files.readAllBytes(this.filePath);
}
catch (NoSuchFileException ex) {
throw new FileNotFoundException(ex.getMessage());
}
}
@Override
public String getContentAsString(Charset charset) throws IOException {
try {
return Files.readString(this.filePath, charset);
}
catch (NoSuchFileException ex) {
throw new FileNotFoundException(ex.getMessage());
}
}
/**
* This implementation checks whether the underlying file is marked as writable
* (and corresponds to an actual file with content, not to a directory).

23
spring-core/src/main/java/org/springframework/core/io/PathResource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,6 +25,7 @@ import java.net.URI; @@ -25,6 +25,7 @@ import java.net.URI;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
@ -141,6 +142,26 @@ public class PathResource extends AbstractResource implements WritableResource { @@ -141,6 +142,26 @@ public class PathResource extends AbstractResource implements WritableResource {
return Files.newInputStream(this.path);
}
@Override
public byte[] getContentAsByteArray() throws IOException {
try {
return Files.readAllBytes(this.path);
}
catch (NoSuchFileException ex) {
throw new FileNotFoundException(ex.getMessage());
}
}
@Override
public String getContentAsString(Charset charset) throws IOException {
try {
return Files.readString(this.path, charset);
}
catch (NoSuchFileException ex) {
throw new FileNotFoundException(ex.getMessage());
}
}
/**
* This implementation checks whether the underlying file is marked as writable
* (and corresponds to an actual file with content, not to a directory).

52
spring-core/src/main/java/org/springframework/core/io/Resource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,9 +17,9 @@ @@ -17,9 +17,9 @@
package org.springframework.core.io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
@ -27,6 +27,7 @@ import java.nio.channels.ReadableByteChannel; @@ -27,6 +27,7 @@ import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;
/**
* Interface for a resource descriptor that abstracts from the actual
@ -179,40 +180,29 @@ public interface Resource extends InputStreamSource { @@ -179,40 +180,29 @@ public interface Resource extends InputStreamSource {
String getDescription();
/**
* Return a {@link ReadableByteChannel}.
* <p>It is expected that each call creates a <i>fresh</i> channel.
* <p>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.
* <p>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
* Return the contents of this resource as a byte array.
* @return the contents of this resource as byte array
* @throws java.io.FileNotFoundException if the resource cannot be resolved as
* absolute file path, i.e. if the resource is not available in a file system
* @throws IOException in case of general resolution/reading failures
* @since 6.0.5
*/
default String getContentAsString() throws IOException{
return toString();
default byte[] getContentAsByteArray() throws IOException {
return FileCopyUtils.copyToByteArray(getInputStream());
}
/**
* Returns the contents of a file as a string using the specified Charset.
* <p>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
* Returns the contents of this resource as a string, using the specified
* charset.
* @param charset the charset to use for decoding
* @return the contents of this resource as a {@code String}
* @throws java.io.FileNotFoundException if the resource cannot be resolved as
* absolute file path, i.e. if the resource is not available in a file system
* @throws IOException in case of general resolution/reading failures
* @since 6.0.5
*/
default String getContentAsString(Charset charset) throws IOException{
return toString();
default String getContentAsString(Charset charset) throws IOException {
return FileCopyUtils.copyToString(new InputStreamReader(getInputStream(), charset));
}
}

23
spring-core/src/main/java/org/springframework/core/io/support/EncodedResource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -159,6 +159,27 @@ public class EncodedResource implements InputStreamSource { @@ -159,6 +159,27 @@ public class EncodedResource implements InputStreamSource {
return this.resource.getInputStream();
}
/**
* Returns the contents of the specified resource as a string, using the specified
* {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}
* (if any).
* @throws IOException if opening the resource failed
* @since 6.0.5
*/
public String getContentAsString() throws IOException {
Charset charset;
if (this.charset != null) {
charset = this.charset;
}
else if (this.encoding != null) {
charset = Charset.forName(this.encoding);
}
else {
charset = Charset.defaultCharset();
}
return this.resource.getContentAsString(charset);
}
@Override
public boolean equals(@Nullable Object other) {

88
spring-core/src/test/java/org/springframework/core/io/ResourceTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,6 +29,8 @@ import java.net.URISyntaxException; @@ -29,6 +29,8 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
@ -49,6 +51,7 @@ import org.springframework.util.FileCopyUtils; @@ -49,6 +51,7 @@ import org.springframework.util.FileCopyUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* Unit tests for various {@link Resource} implementations.
@ -69,6 +72,7 @@ class ResourceTests { @@ -69,6 +72,7 @@ class ResourceTests {
assertThat(resource.isReadable()).isTrue();
assertThat(resource.contentLength() > 0).isTrue();
assertThat(resource.lastModified() > 0).isTrue();
assertThat(resource.getContentAsByteArray()).containsExactly(Files.readAllBytes(Path.of(resource.getURI())));
}
@ParameterizedTest(name = "{index}: {0}")
@ -113,24 +117,13 @@ class ResourceTests { @@ -113,24 +117,13 @@ class ResourceTests {
Resource relative4 = resource.createRelative("X.class");
assertThat(relative4.exists()).isFalse();
assertThat(relative4.isReadable()).isFalse();
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(relative4::contentLength);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(relative4::lastModified);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(relative4::getInputStream);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(relative4::readableChannel);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(relative4::getContentAsByteArray);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(
relative4::contentLength);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(
relative4::lastModified);
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void loadingMissingResourceFails(Resource resource) {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
resource.createRelative("X").getInputStream());
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("resource")
void readingMissingResourceFails(Resource resource) {
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
resource.createRelative("X").readableChannel());
() -> relative4.getContentAsString(StandardCharsets.UTF_8));
}
private static Stream<Arguments> resource() throws URISyntaxException {
@ -153,12 +146,18 @@ class ResourceTests { @@ -153,12 +146,18 @@ class ResourceTests {
@Test
void hasContent() throws Exception {
Resource resource = new ByteArrayResource("testString".getBytes());
String testString = "testString";
byte[] testBytes = testString.getBytes();
Resource resource = new ByteArrayResource(testBytes);
assertThat(resource.exists()).isTrue();
assertThat(resource.isOpen()).isFalse();
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(new ByteArrayResource("testString".getBytes())).isEqualTo(resource);
byte[] contentBytes = resource.getContentAsByteArray();
assertThat(contentBytes).containsExactly(testBytes);
String contentString = resource.getContentAsString(StandardCharsets.US_ASCII);
assertThat(contentString).isEqualTo(testString);
contentString = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(contentString).isEqualTo(testString);
assertThat(new ByteArrayResource(testBytes)).isEqualTo(resource);
}
@Test
@ -181,11 +180,22 @@ class ResourceTests { @@ -181,11 +180,22 @@ class ResourceTests {
@Test
void hasContent() throws Exception {
InputStream is = new ByteArrayInputStream("testString".getBytes());
Resource resource = new InputStreamResource(is);
String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
assertThat(content).isEqualTo("testString");
assertThat(new InputStreamResource(is)).isEqualTo(resource);
String testString = "testString";
byte[] testBytes = testString.getBytes();
InputStream is = new ByteArrayInputStream(testBytes);
Resource resource1 = new InputStreamResource(is);
String content = FileCopyUtils.copyToString(new InputStreamReader(resource1.getInputStream()));
assertThat(content).isEqualTo(testString);
assertThat(new InputStreamResource(is)).isEqualTo(resource1);
assertThatIllegalStateException().isThrownBy(resource1::getInputStream);
Resource resource2 = new InputStreamResource(new ByteArrayInputStream(testBytes));
assertThat(resource2.getContentAsByteArray()).containsExactly(testBytes);
assertThatIllegalStateException().isThrownBy(resource2::getContentAsByteArray);
Resource resource3 = new InputStreamResource(new ByteArrayInputStream(testBytes));
assertThat(resource3.getContentAsString(StandardCharsets.US_ASCII)).isEqualTo(testString);
assertThatIllegalStateException().isThrownBy(() -> resource3.getContentAsString(StandardCharsets.US_ASCII));
}
@Test
@ -435,6 +445,9 @@ class ResourceTests { @@ -435,6 +445,9 @@ class ResourceTests {
.withMessageContaining(name);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() ->
resource.createRelative("/testing")).withMessageContaining(name);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(resource::getContentAsByteArray);
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(
() -> resource.getContentAsString(StandardCharsets.US_ASCII));
assertThat(resource.getFilename()).isNull();
}
@ -456,25 +469,4 @@ class ResourceTests { @@ -456,25 +469,4 @@ class ResourceTests {
}
@Test
void getContentAsString_givenValidFile_ShouldReturnFileContent() throws IOException {
String expectedString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">\n"
+ "<properties version=\"1.0\">\n"
+ "\t<entry key=\"foo\">bar</entry>\n"
+ "</properties>";
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);
}
}

3
spring-core/src/test/resources/org/springframework/core/io/example.xml

@ -2,4 +2,5 @@ @@ -2,4 +2,5 @@
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties version="1.0">
<entry key="foo">bar</entry>
</properties>
</properties>

13
spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ import java.io.IOException; @@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -269,6 +270,16 @@ public class EncodedResourceResolver extends AbstractResourceResolver { @@ -269,6 +270,16 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
return this.encoded.getDescription();
}
@Override
public byte[] getContentAsByteArray() throws IOException {
return this.encoded.getContentAsByteArray();
}
@Override
public String getContentAsString(Charset charset) throws IOException {
return this.encoded.getContentAsString(charset);
}
@Override
public HttpHeaders getResponseHeaders() {
HttpHeaders headers;

13
spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionResourceResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ import java.io.IOException; @@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@ -308,6 +309,16 @@ public class VersionResourceResolver extends AbstractResourceResolver { @@ -308,6 +309,16 @@ public class VersionResourceResolver extends AbstractResourceResolver {
return this.original.getDescription();
}
@Override
public byte[] getContentAsByteArray() throws IOException {
return this.original.getContentAsByteArray();
}
@Override
public String getContentAsString(Charset charset) throws IOException {
return this.original.getContentAsString(charset);
}
@Override
public InputStream getInputStream() throws IOException {
return this.original.getInputStream();

13
spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ import java.io.IOException; @@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -266,6 +267,16 @@ public class EncodedResourceResolver extends AbstractResourceResolver { @@ -266,6 +267,16 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
return this.encoded.getDescription();
}
@Override
public byte[] getContentAsByteArray() throws IOException {
return this.encoded.getContentAsByteArray();
}
@Override
public String getContentAsString(Charset charset) throws IOException {
return this.encoded.getContentAsString(charset);
}
@Override
public HttpHeaders getResponseHeaders() {
HttpHeaders headers;

13
spring-webmvc/src/main/java/org/springframework/web/servlet/resource/VersionResourceResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ import java.io.IOException; @@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@ -304,6 +305,16 @@ public class VersionResourceResolver extends AbstractResourceResolver { @@ -304,6 +305,16 @@ public class VersionResourceResolver extends AbstractResourceResolver {
return this.original.getDescription();
}
@Override
public byte[] getContentAsByteArray() throws IOException {
return this.original.getContentAsByteArray();
}
@Override
public String getContentAsString(Charset charset) throws IOException {
return this.original.getContentAsString(charset);
}
@Override
public InputStream getInputStream() throws IOException {
return this.original.getInputStream();

Loading…
Cancel
Save