Avoid infinite loop in AbstractResource#contentLength

Due to changes made in commit 2fa87a71 for SPR-9118,
AbstractResource#contentLength would fall into an infinite loop unless
the method were overridden by a subclass (which it is in the majority of
use cases).

This commit:

 - fixes the infinite recursion by refactoring to a while loop

 - asserts that the value returned from #getInputStream is not null in
   order to avoid NullPointerException

 - tests both of the above

 - adds Javadoc to the Resource interface to clearly document that the
   contract for any implementation is that #getInputStream must not
   return null

Issue: SPR-9161
This commit is contained in:
Chris Beams
2012-02-24 14:29:28 +01:00
parent f4010f14d1
commit 7ca5fba05f
3 changed files with 44 additions and 9 deletions

View File

@@ -25,6 +25,7 @@ import java.net.URISyntaxException;
import java.net.URL;
import org.springframework.core.NestedIOException;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
/**
@@ -112,13 +113,16 @@ public abstract class AbstractResource implements Resource {
* content length. Subclasses will almost always be able to provide
* a more optimal version of this, e.g. checking a File length.
* @see #getInputStream()
* @throws IllegalStateException if {@link #getInputStream()} returns null.
*/
public long contentLength() throws IOException {
InputStream is = getInputStream();
InputStream is = this.getInputStream();
Assert.state(is != null, "resource input stream must not be null");
try {
long size = 0;
byte[] buf = new byte[255];
for (int read = is.read(buf); read != -1;) {
int read;
while((read = is.read(buf)) != -1) {
size += read;
}
return size;

View File

@@ -18,6 +18,7 @@ package org.springframework.core.io;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
@@ -132,4 +133,9 @@ public interface Resource extends InputStreamSource {
*/
String getDescription();
/**
* {@inheritDoc}
* @return the input stream for the underlying resource (must not be {@code null}).
*/
public InputStream getInputStream() throws IOException;
}