Skip to content

Commit 7a79a18

Browse files
committed
Add functional interfaces
1 parent 472034c commit 7a79a18

8 files changed

Lines changed: 86 additions & 23 deletions

File tree

src/main/java/org/kohsuke/github/GHRepository.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,7 +1783,7 @@ public InputStream readBlob(String blobSha) throws IOException {
17831783
return root.createRequest()
17841784
.withHeader("Accept", "application/vnd.github.v3.raw")
17851785
.withUrlPath(target)
1786-
.fetchStream();
1786+
.fetchStream(Requester::copyInputStream);
17871787
}
17881788

17891789
/**
@@ -2810,7 +2810,7 @@ public Reader renderMarkdown(String text, MarkdownMode mode) throws IOException
28102810
.with("mode", mode == null ? null : mode.toString())
28112811
.with("context", getFullName())
28122812
.withUrlPath("/markdown")
2813-
.fetchStream(),
2813+
.fetchStream(Requester::copyInputStream),
28142814
"UTF-8");
28152815
}
28162816

src/main/java/org/kohsuke/github/GitHub.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1203,7 +1203,7 @@ public Reader renderMarkdown(String text) throws IOException {
12031203
.with(new ByteArrayInputStream(text.getBytes("UTF-8")))
12041204
.contentType("text/plain;charset=UTF-8")
12051205
.withUrlPath("/markdown/raw")
1206-
.fetchStream(),
1206+
.fetchStream(Requester::copyInputStream),
12071207
"UTF-8");
12081208
}
12091209

src/main/java/org/kohsuke/github/GitHubResponse.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.fasterxml.jackson.databind.InjectableValues;
55
import com.fasterxml.jackson.databind.JsonMappingException;
66
import org.apache.commons.io.IOUtils;
7+
import org.kohsuke.github.function.FunctionThrows;
78

89
import java.io.Closeable;
910
import java.io.IOException;
@@ -194,24 +195,11 @@ public T body() {
194195
/**
195196
* Represents a supplier of results that can throw.
196197
*
197-
* <p>
198-
* This is a <a href="package-summary.html">functional interface</a> whose functional method is
199-
* {@link #apply(ResponseInfo)}.
200-
*
201198
* @param <T>
202199
* the type of results supplied by this supplier
203200
*/
204201
@FunctionalInterface
205-
interface BodyHandler<T> {
206-
207-
/**
208-
* Gets a result.
209-
*
210-
* @return a result
211-
* @throws IOException
212-
* if an I/O Exception occurs.
213-
*/
214-
T apply(ResponseInfo input) throws IOException;
202+
interface BodyHandler<T> extends FunctionThrows<ResponseInfo, T, IOException> {
215203
}
216204

217205
/**

src/main/java/org/kohsuke/github/Requester.java

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
*/
2424
package org.kohsuke.github;
2525

26+
import edu.umd.cs.findbugs.annotations.NonNull;
2627
import org.apache.commons.io.IOUtils;
28+
import org.kohsuke.github.function.InputStreamConsumer;
29+
import org.kohsuke.github.function.InputStreamFunction;
2730

2831
import java.io.ByteArrayInputStream;
2932
import java.io.IOException;
@@ -106,15 +109,45 @@ public int fetchHttpStatusCode() throws IOException {
106109
* Response input stream. There are scenarios where direct stream reading is needed, however it is better to use
107110
* {@link #fetch(Class)} where possible.
108111
*
109-
* @return the input stream
110112
* @throws IOException
111113
* the io exception
112114
*/
113-
public InputStream fetchStream() throws IOException {
114-
return client
115-
.sendRequest(this,
116-
(responseInfo) -> new ByteArrayInputStream(IOUtils.toByteArray(responseInfo.bodyStream())))
117-
.body();
115+
public void fetchStream(@Nonnull InputStreamConsumer consumer) throws IOException {
116+
fetchStream((inputStream) -> {
117+
consumer.accept(inputStream);
118+
return null;
119+
});
120+
}
121+
122+
/**
123+
* Response input stream. There are scenarios where direct stream reading is needed, however it is better to use
124+
* {@link #fetch(Class)} where possible.
125+
*
126+
* @throws IOException
127+
* the io exception
128+
*/
129+
public <T> T fetchStream(@Nonnull InputStreamFunction<T> handler) throws IOException {
130+
return client.sendRequest(this, (responseInfo) -> handler.apply(responseInfo.bodyStream())).body();
131+
}
132+
133+
/**
134+
* Helper function to make it easy to pull streams.
135+
*
136+
* Copies an input stream to an in-memory input stream. The performance on this is not great but
137+
* {@link GitHubResponse.ResponseInfo#bodyStream()} is closed at the end of every call to
138+
* {@link GitHubClient#sendRequest(GitHubRequest, GitHubResponse.BodyHandler)}, so any reads to the original input
139+
* stream must be completed before then. There are a number of deprecated methods that return {@link InputStream}.
140+
* This method keeps all of them using the same code path.
141+
*
142+
* @param inputStream
143+
* the input stream to be copied
144+
* @return an in-memory copy of the passed input stream
145+
* @throws IOException
146+
* if an error occurs while copying the stream
147+
*/
148+
@NonNull
149+
public static InputStream copyInputStream(InputStream inputStream) throws IOException {
150+
return new ByteArrayInputStream(IOUtils.toByteArray(inputStream));
118151
}
119152

120153
/**
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.kohsuke.github.function;
2+
3+
/**
4+
* A functional interface, equivalent to {@link java.util.function.Consumer} but that allows throwing {@link Throwable}
5+
*/
6+
@FunctionalInterface
7+
public interface ConsumerThrows<T, E extends Throwable> {
8+
void accept(T input) throws E;
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.kohsuke.github.function;
2+
3+
/**
4+
* A functional interface, equivalent to {@link java.util.function.Function} but that allows throwing {@link Throwable}
5+
*/
6+
@FunctionalInterface
7+
public interface FunctionThrows<T, R, E extends Throwable> {
8+
R apply(T input) throws E;
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.kohsuke.github.function;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
6+
/**
7+
* A functional interface, equivalent to {@link java.util.function.Consumer} but that takes an {@link InputStream} and
8+
* can throw an {@link IOException}
9+
*/
10+
@FunctionalInterface
11+
public interface InputStreamConsumer extends ConsumerThrows<InputStream, IOException> {
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.kohsuke.github.function;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
6+
/**
7+
* A functional interface, equivalent to {@link java.util.function.Function} but that allows throwing {@link Throwable}
8+
*
9+
*/
10+
@FunctionalInterface
11+
public interface InputStreamFunction<R> extends FunctionThrows<InputStream, R, IOException> {
12+
}

0 commit comments

Comments
 (0)