Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 49 additions & 10 deletions core/src/main/java/org/kohsuke/stapler/framework/io/LargeText.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,24 @@ public class LargeText {
/**
* Represents the data source of this text.
*/
private interface Source {
public interface Source {
/**
* Open a Source for reading.
* @return Opened Session for reading.
* @throws IOException if an error occurs.
*/
Session open() throws IOException;

/**
* Size of the Source.
* @return Number of bytes in the Source.
*/
long length();

/**
* Check existence of the Source.
* @return true if it exists, otherwise false.
*/
boolean exists();
}

Expand Down Expand Up @@ -170,6 +183,12 @@ public boolean exists() {
this.completed = completed;
}

public LargeText(Source source, Charset charset, boolean completed) {
this.charset = charset;
this.source = source;
this.completed = completed;
}

public void markAsComplete() {
completed = true;
}
Expand Down Expand Up @@ -509,11 +528,31 @@ public boolean isFull() {
* Represents the read session of the {@link Source}.
* Methods follow the contracts of {@link InputStream}.
*/
private interface Session extends Closeable {
long skip(long start) throws IOException;
public interface Session extends Closeable {
/**
* See also {@link InputStream#skip(long)}.
* @param n Number of bytes to skip ahead.
* @return Number of bytes that were skipped.
* @throws IOException if an error occurs. Skipping less than n bytes does not need to throw.
*/
long skip(long n) throws IOException;

/**
* See also {@link InputStream#read(byte[])}.
* @param buf Buffer to fill.
* @return Number of bytes that were filled.
* @throws IOException if an error occurs.
*/
int read(byte[] buf) throws IOException;

/**
* See also {@link InputStream#read(byte[], int, int)}.
* @param buf Buffer to fill.
* @param offset Number of bytes to skip in buf.
* @param length Number of bytes to read at most.
* @return Number of bytes that were read.
* @throws IOException if an error occurs.
*/
int read(byte[] buf, int offset, int length) throws IOException;
}

Expand All @@ -536,10 +575,10 @@ public void close() throws IOException {
* Like {@link RandomAccessFile#skipBytes} but with long instead of int.
*/
@Override
public long skip(long start) throws IOException {
if (start <= 0) return 0;
public long skip(long n) throws IOException {
if (n <= 0) return 0;
long pos = file.getFilePointer();
long newPos = Math.min(file.length(), pos + start);
long newPos = Math.min(file.length(), pos + n);
file.seek(newPos);
return newPos - pos;
}
Expand Down Expand Up @@ -575,8 +614,8 @@ public void close() throws IOException {
}

@Override
public long skip(long start) throws IOException {
return gz.skip(start);
public long skip(long n) throws IOException {
return gz.skip(n);
}

@Override
Expand Down Expand Up @@ -657,8 +696,8 @@ public void close() throws IOException {
}

@Override
public long skip(long start) throws IOException {
return in.skip(start);
public long skip(long n) throws IOException {
return in.skip(n);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.FileOutputStream;
Expand Down Expand Up @@ -62,6 +63,11 @@ public void writeLogToFromByteBuffer() throws Exception {
writeLogToWith(byteBuffer());
}

@Test
public void writeLogToFromInterface() throws Exception {
writeLogToWith(interfaceBased());
}

@Test
public void writeLogToFromFile() throws Exception {
writeLogToWith(file());
Expand Down Expand Up @@ -115,6 +121,10 @@ BuildLargeText gzFile() {
return new FromGzFile();
}

BuildLargeText interfaceBased() {
return new FromInterface();
}

static class FromByteBuffer implements BuildLargeText {
public LargeText build(String text) throws IOException {
ByteBuffer bb = new ByteBuffer();
Expand All @@ -125,6 +135,35 @@ public LargeText build(String text) throws IOException {
public void close() {}
}

static class FromInterface implements BuildLargeText {
public LargeText build(String text) throws IOException {
LargeText.Source src = new LargeText.Source() {
private final byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);

class BytesSession extends ByteArrayInputStream implements LargeText.Session {
BytesSession() {
super(textBytes);
}
}

public LargeText.Session open() {
return new BytesSession();
}

public long length() {
return textBytes.length;
}

public boolean exists() {
return true;
}
};
return new LargeText(src, StandardCharsets.UTF_8, true);
}

public void close() {}
}

static class FromFile implements BuildLargeText {
private Path path;
final boolean detectGzip;
Expand Down