Handle short reads in BasePayloadSlicer

InputStream.read(byte[]) can return fewer bytes than requested.
Specifically ByteSource.concat(ByteSource...).openStream() will only
return as many bytes as the current ByteSource contains.  Thus
ByteSources.repeatingArrayByteSource(byte[]).openStream() will return
short reads despite the byte[] input from its single logical
InputStream.
This commit is contained in:
Andrew Gaul 2014-07-02 15:02:26 -07:00
parent b259af48c0
commit d43c3ea3e0
2 changed files with 27 additions and 4 deletions

View File

@ -96,17 +96,25 @@ public class BasePayloadSlicer implements PayloadSlicer {
private Payload getNextPayload() {
byte[] content = new byte[readLen];
int read = 0;
int offset = 0;
try {
if ((read = input.read(content)) == -1) {
return null;
while (true) {
int read = input.read(content, offset, readLen - offset);
if (read <= 0) {
if (offset == 0) {
return null;
} else {
break;
}
}
offset += read;
}
} catch (IOException e) {
throw Throwables.propagate(e);
}
return createPayload((content.length == read) ? content : Arrays.copyOf(content, read));
return createPayload((content.length == offset) ? content : Arrays.copyOf(content, offset));
}
private Payload createPayload(byte[] content) {

View File

@ -24,13 +24,17 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Iterator;
import org.jclouds.io.ByteSources;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadSlicer;
import org.jclouds.io.payloads.ByteSourcePayload;
import org.jclouds.io.payloads.InputStreamPayload;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.collect.Iterables;
import com.google.common.io.ByteSource;
import com.google.common.io.ByteStreams;
@Test
@ -67,4 +71,15 @@ public class BasePayloadSlicerTest {
}
@Test
public void testIterableSliceWithRepeatingByteSource() throws IOException {
String content = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n"; /* 53 chars */
byte[] contentBytes = content.getBytes(Charsets.UTF_8);
ByteSource byteSource = ByteSources.repeatingArrayByteSource(contentBytes).slice(0, 1024);
PayloadSlicer slicer = new BasePayloadSlicer();
Payload payload = new ByteSourcePayload(byteSource);
assertEquals(Iterables.size(slicer.slice(payload, 100)), 11);
assertEquals(Iterables.size(slicer.slice(payload, 53)), 20);
}
}