Add functional interfaces

This commit is contained in:
Liam Newman
2021-01-04 01:30:59 -08:00
parent 472034c950
commit 7a79a18d8f
8 changed files with 86 additions and 23 deletions

View File

@@ -1783,7 +1783,7 @@ public class GHRepository extends GHObject {
return root.createRequest()
.withHeader("Accept", "application/vnd.github.v3.raw")
.withUrlPath(target)
.fetchStream();
.fetchStream(Requester::copyInputStream);
}
/**
@@ -2810,7 +2810,7 @@ public class GHRepository extends GHObject {
.with("mode", mode == null ? null : mode.toString())
.with("context", getFullName())
.withUrlPath("/markdown")
.fetchStream(),
.fetchStream(Requester::copyInputStream),
"UTF-8");
}

View File

@@ -1203,7 +1203,7 @@ public class GitHub {
.with(new ByteArrayInputStream(text.getBytes("UTF-8")))
.contentType("text/plain;charset=UTF-8")
.withUrlPath("/markdown/raw")
.fetchStream(),
.fetchStream(Requester::copyInputStream),
"UTF-8");
}

View File

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonMappingException;
import org.apache.commons.io.IOUtils;
import org.kohsuke.github.function.FunctionThrows;
import java.io.Closeable;
import java.io.IOException;
@@ -194,24 +195,11 @@ class GitHubResponse<T> {
/**
* Represents a supplier of results that can throw.
*
* <p>
* This is a <a href="package-summary.html">functional interface</a> whose functional method is
* {@link #apply(ResponseInfo)}.
*
* @param <T>
* the type of results supplied by this supplier
*/
@FunctionalInterface
interface BodyHandler<T> {
/**
* Gets a result.
*
* @return a result
* @throws IOException
* if an I/O Exception occurs.
*/
T apply(ResponseInfo input) throws IOException;
interface BodyHandler<T> extends FunctionThrows<ResponseInfo, T, IOException> {
}
/**

View File

@@ -23,7 +23,10 @@
*/
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.NonNull;
import org.apache.commons.io.IOUtils;
import org.kohsuke.github.function.InputStreamConsumer;
import org.kohsuke.github.function.InputStreamFunction;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -106,15 +109,45 @@ class Requester extends GitHubRequest.Builder<Requester> {
* Response input stream. There are scenarios where direct stream reading is needed, however it is better to use
* {@link #fetch(Class)} where possible.
*
* @return the input stream
* @throws IOException
* the io exception
*/
public InputStream fetchStream() throws IOException {
return client
.sendRequest(this,
(responseInfo) -> new ByteArrayInputStream(IOUtils.toByteArray(responseInfo.bodyStream())))
.body();
public void fetchStream(@Nonnull InputStreamConsumer consumer) throws IOException {
fetchStream((inputStream) -> {
consumer.accept(inputStream);
return null;
});
}
/**
* Response input stream. There are scenarios where direct stream reading is needed, however it is better to use
* {@link #fetch(Class)} where possible.
*
* @throws IOException
* the io exception
*/
public <T> T fetchStream(@Nonnull InputStreamFunction<T> handler) throws IOException {
return client.sendRequest(this, (responseInfo) -> handler.apply(responseInfo.bodyStream())).body();
}
/**
* Helper function to make it easy to pull streams.
*
* Copies an input stream to an in-memory input stream. The performance on this is not great but
* {@link GitHubResponse.ResponseInfo#bodyStream()} is closed at the end of every call to
* {@link GitHubClient#sendRequest(GitHubRequest, GitHubResponse.BodyHandler)}, so any reads to the original input
* stream must be completed before then. There are a number of deprecated methods that return {@link InputStream}.
* This method keeps all of them using the same code path.
*
* @param inputStream
* the input stream to be copied
* @return an in-memory copy of the passed input stream
* @throws IOException
* if an error occurs while copying the stream
*/
@NonNull
public static InputStream copyInputStream(InputStream inputStream) throws IOException {
return new ByteArrayInputStream(IOUtils.toByteArray(inputStream));
}
/**

View File

@@ -0,0 +1,9 @@
package org.kohsuke.github.function;
/**
* A functional interface, equivalent to {@link java.util.function.Consumer} but that allows throwing {@link Throwable}
*/
@FunctionalInterface
public interface ConsumerThrows<T, E extends Throwable> {
void accept(T input) throws E;
}

View File

@@ -0,0 +1,9 @@
package org.kohsuke.github.function;
/**
* A functional interface, equivalent to {@link java.util.function.Function} but that allows throwing {@link Throwable}
*/
@FunctionalInterface
public interface FunctionThrows<T, R, E extends Throwable> {
R apply(T input) throws E;
}

View File

@@ -0,0 +1,12 @@
package org.kohsuke.github.function;
import java.io.IOException;
import java.io.InputStream;
/**
* A functional interface, equivalent to {@link java.util.function.Consumer} but that takes an {@link InputStream} and
* can throw an {@link IOException}
*/
@FunctionalInterface
public interface InputStreamConsumer extends ConsumerThrows<InputStream, IOException> {
}

View File

@@ -0,0 +1,12 @@
package org.kohsuke.github.function;
import java.io.IOException;
import java.io.InputStream;
/**
* A functional interface, equivalent to {@link java.util.function.Function} but that allows throwing {@link Throwable}
*
*/
@FunctionalInterface
public interface InputStreamFunction<R> extends FunctionThrows<InputStream, R, IOException> {
}