Skip to content

Commit e9abaa7

Browse files
committed
Finish implementation and test of HttpURLConnectionAdapter
1 parent 65363d3 commit e9abaa7

File tree

4 files changed

+160
-46
lines changed

4 files changed

+160
-46
lines changed

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

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ public String getHeaderFieldKey(int n) {
3232

3333
@Override
3434
public void setFixedLengthStreamingMode(int contentLength) {
35-
throw new UnsupportedOperationException("Setting streaming mode is not supported by " + this.getClass());
35+
throw new UnsupportedOperationException();
3636
}
3737

3838
@Override
3939
public void setFixedLengthStreamingMode(long contentLength) {
40-
throw new UnsupportedOperationException("Setting streaming mode is not supported by " + this.getClass());
40+
throw new UnsupportedOperationException();
4141
}
4242

4343
@Override
4444
public void setChunkedStreamingMode(int chunklen) {
45-
throw new UnsupportedOperationException("Setting streaming mode is not supported by " + this.getClass());
45+
throw new UnsupportedOperationException();
4646
}
4747

4848
@Override
@@ -52,17 +52,17 @@ public String getHeaderField(int n) {
5252

5353
@Override
5454
public void setInstanceFollowRedirects(boolean followRedirects) {
55-
super.setInstanceFollowRedirects(followRedirects);
55+
throw new UnsupportedOperationException();
5656
}
5757

5858
@Override
5959
public boolean getInstanceFollowRedirects() {
60-
return super.getInstanceFollowRedirects();
60+
throw new UnsupportedOperationException();
6161
}
6262

6363
@Override
6464
public void setRequestMethod(String method) throws ProtocolException {
65-
super.setRequestMethod(method);
65+
throw new UnsupportedOperationException();
6666
}
6767

6868
@Override
@@ -84,7 +84,7 @@ public String getResponseMessage() throws IOException {
8484
public long getHeaderFieldDate(String name, long defaultValue) {
8585
String dateString = getHeaderField(name);
8686
try {
87-
return GitHubClient.parseDate(dateString).getTime();
87+
return Date.parse(dateString);
8888
} catch (Exception e) {
8989
}
9090
return defaultValue;
@@ -107,7 +107,7 @@ public void setConnectTimeout(int timeout) {
107107

108108
@Override
109109
public int getConnectTimeout() {
110-
return super.getConnectTimeout();
110+
throw new UnsupportedOperationException();
111111
}
112112

113113
@Override
@@ -117,7 +117,7 @@ public void setReadTimeout(int timeout) {
117117

118118
@Override
119119
public int getReadTimeout() {
120-
return super.getReadTimeout();
120+
throw new UnsupportedOperationException();
121121
}
122122

123123
@Override
@@ -190,18 +190,18 @@ public long getHeaderFieldLong(String name, long defaultValue) {
190190

191191
@Override
192192
public Object getContent() throws IOException {
193-
return super.getContent();
193+
throw new UnsupportedOperationException();
194194
}
195195

196-
// @Override
197-
// public Object getContent(Class<?>[] classes) throws IOException {
198-
// return super.getContent(classes);
199-
// }
200-
//
201-
// @Override
202-
// public InputStream getInputStream() throws IOException {
203-
// return connectorResponse.bodyStream();
204-
// }
196+
@Override
197+
public Object getContent(Class[] classes) throws IOException {
198+
throw new UnsupportedOperationException();
199+
}
200+
201+
@Override
202+
public InputStream getInputStream() throws IOException {
203+
return connectorResponse.bodyStream();
204+
}
205205

206206
@Override
207207
public OutputStream getOutputStream() throws IOException {
@@ -215,67 +215,62 @@ public String toString() {
215215

216216
@Override
217217
public void setDoInput(boolean doinput) {
218-
throw new IllegalStateException();
218+
throw new UnsupportedOperationException();
219219
}
220220

221221
@Override
222222
public boolean getDoInput() {
223-
return super.getDoInput();
223+
throw new UnsupportedOperationException();
224224
}
225225

226226
@Override
227227
public void setDoOutput(boolean dooutput) {
228-
throw new IllegalStateException();
228+
throw new UnsupportedOperationException();
229229
}
230230

231231
@Override
232232
public boolean getDoOutput() {
233-
return super.getDoOutput();
233+
throw new UnsupportedOperationException();
234234
}
235235

236236
@Override
237237
public void setAllowUserInteraction(boolean allowuserinteraction) {
238-
super.setAllowUserInteraction(allowuserinteraction);
238+
throw new UnsupportedOperationException();
239239
}
240240

241241
@Override
242242
public void setUseCaches(boolean usecaches) {
243-
throw new IllegalStateException();
243+
throw new UnsupportedOperationException();
244244
}
245245

246246
@Override
247247
public boolean getUseCaches() {
248-
return super.getUseCaches();
248+
throw new UnsupportedOperationException();
249249
}
250250

251251
@Override
252252
public void setIfModifiedSince(long ifmodifiedsince) {
253-
throw new IllegalStateException();
253+
throw new UnsupportedOperationException();
254254
}
255255

256256
@Override
257257
public long getIfModifiedSince() {
258-
String modifiedSince = connectorResponse.request().header("If-Modified-Since");
259-
if (modifiedSince != null) {
260-
return GitHubClient.parseDate(modifiedSince).getTime();
261-
} else {
262-
return 0;
263-
}
258+
return getHeaderFieldDate("If-Modified-Since", 0);
264259
}
265260

266261
@Override
267262
public void setDefaultUseCaches(boolean defaultusecaches) {
268-
throw new IllegalStateException();
263+
throw new UnsupportedOperationException();
269264
}
270265

271266
@Override
272267
public void setRequestProperty(String key, String value) {
273-
throw new IllegalStateException();
268+
throw new UnsupportedOperationException();
274269
}
275270

276271
@Override
277272
public void addRequestProperty(String key, String value) {
278-
throw new IllegalStateException();
273+
throw new UnsupportedOperationException();
279274
}
280275

281276
@Override
@@ -305,7 +300,7 @@ public void disconnect() {
305300

306301
@Override
307302
public boolean usingProxy() {
308-
return false;
303+
throw new UnsupportedOperationException();
309304
}
310305

311306
@Override

src/main/java/org/kohsuke/github/internal/GitHubConnectorHttpConnectorAdapter.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.kohsuke.github.connector.GitHubConnectorRequest;
88
import org.kohsuke.github.connector.GitHubConnectorResponse;
99

10+
import java.io.ByteArrayInputStream;
1011
import java.io.IOException;
1112
import java.io.InputStream;
1213
import java.lang.reflect.Field;
@@ -152,6 +153,11 @@ private static void setRequestMethod(String method, HttpURLConnection connection
152153
*/
153154
static class HttpURLConnectionGitHubConnectorResponse extends GitHubConnectorResponse {
154155

156+
private boolean inputStreamRead = false;
157+
private byte[] inputBytes = null;
158+
private boolean errorStreamRead = false;
159+
private String errorString = null;
160+
155161
@Nonnull
156162
private final HttpURLConnection connection;
157163

@@ -167,24 +173,41 @@ static class HttpURLConnectionGitHubConnectorResponse extends GitHubConnectorRes
167173
* {@inheritDoc}
168174
*/
169175
public InputStream bodyStream() throws IOException {
170-
return wrapStream(connection.getInputStream());
176+
synchronized (this) {
177+
if (!inputStreamRead) {
178+
try (InputStream stream = wrapStream(connection.getInputStream())) {
179+
if (stream != null) {
180+
inputBytes = IOUtils.toByteArray(stream);
181+
inputStreamRead = true;
182+
}
183+
}
184+
}
185+
}
186+
187+
return inputBytes == null ? null : new ByteArrayInputStream(inputBytes);
171188
}
172189

173190
/**
174191
* {@inheritDoc}
175192
*/
176193
public String errorMessage() {
177194
String result = null;
178-
InputStream stream = null;
179195
try {
180-
stream = connection.getErrorStream();
181-
if (stream != null) {
182-
result = IOUtils.toString(wrapStream(stream), StandardCharsets.UTF_8);
196+
synchronized (this) {
197+
if (!errorStreamRead) {
198+
try (InputStream stream = wrapStream(connection.getErrorStream())) {
199+
if (stream != null) {
200+
errorString = new String(IOUtils.toByteArray(stream), StandardCharsets.UTF_8);
201+
errorStreamRead = true;
202+
}
203+
}
204+
}
205+
}
206+
if (errorString != null) {
207+
result = errorString;
183208
}
184209
} catch (Exception e) {
185210
LOGGER.log(FINER, "Ignored exception get error message", e);
186-
} finally {
187-
IOUtils.closeQuietly(stream);
188211
}
189212
return result;
190213
}

src/test/java/org/kohsuke/github/AbuseLimitHandlerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public void testHandler_WaitStuck() throws Exception {
113113
snapshotNotAllowed();
114114

115115
gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl())
116-
.withRateLimitHandler(new RateLimitHandler() {
116+
.withAbuseLimitHandler(new AbuseLimitHandler() {
117117
@Override
118118
public void onError(IOException e, HttpURLConnection uc) throws IOException {
119119
}

src/test/java/org/kohsuke/github/RateLimitHandlerTest.java

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package org.kohsuke.github;
22

33
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
4+
import org.apache.commons.io.IOUtils;
5+
import org.hamcrest.Matchers;
6+
import org.junit.Assert;
47
import org.junit.Test;
58

69
import java.io.IOException;
10+
import java.io.InputStream;
711
import java.net.HttpURLConnection;
12+
import java.nio.charset.StandardCharsets;
13+
import java.util.Date;
14+
import java.util.Map;
815

916
import static org.hamcrest.CoreMatchers.*;
1017
import static org.hamcrest.core.IsInstanceOf.instanceOf;
@@ -46,7 +53,96 @@ public void testHandler_Fail() throws Exception {
4653
snapshotNotAllowed();
4754

4855
gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl())
49-
.withRateLimitHandler(RateLimitHandler.FAIL)
56+
.withRateLimitHandler(new RateLimitHandler() {
57+
@Override
58+
public void onError(IOException e, HttpURLConnection uc) throws IOException {
59+
// Verify
60+
assertThat(uc.getDate(), Matchers.greaterThanOrEqualTo(new Date().getTime() - 10000));
61+
assertThat(uc.getExpiration(), equalTo(0L));
62+
assertThat(uc.getIfModifiedSince(), equalTo(0L));
63+
assertThat(uc.getLastModified(), equalTo(1581014017000L));
64+
assertThat(uc.getRequestMethod(), equalTo("GET"));
65+
assertThat(uc.getResponseCode(), equalTo(403));
66+
assertThat(uc.getResponseMessage(), equalTo("403 Forbidden"));
67+
assertThat(uc.getURL().toString(), endsWith("/repos/hub4j-test-org/temp-testHandler_Fail"));
68+
assertThat(uc.getHeaderFieldInt("X-RateLimit-Limit", 10), equalTo(5000));
69+
assertThat(uc.getHeaderFieldInt("X-RateLimit-Remaining", 10), equalTo(0));
70+
assertThat(uc.getHeaderFieldInt("X-Foo", 20), equalTo(20));
71+
assertThat(uc.getHeaderFieldLong("X-RateLimit-Limit", 15L), equalTo(5000L));
72+
assertThat(uc.getHeaderFieldLong("X-RateLimit-Remaining", 15L), equalTo(0L));
73+
assertThat(uc.getHeaderFieldLong("X-Foo", 20L), equalTo(20L));
74+
75+
assertThat(uc.getContentEncoding(), nullValue());
76+
assertThat(uc.getContentType(), equalTo("application/json; charset=utf-8"));
77+
assertThat(uc.getContentLength(), equalTo(-1));
78+
79+
// getting an input stream in an error case should throw
80+
IOException ioEx = Assert.assertThrows(IOException.class, () -> uc.getInputStream());
81+
82+
InputStream errorStream = uc.getErrorStream();
83+
assertThat(errorStream, notNullValue());
84+
String error = IOUtils.toString(errorStream, StandardCharsets.UTF_8);
85+
assertThat(error, containsString("Must have push access to repository"));
86+
87+
// calling again should still error
88+
ioEx = Assert.assertThrows(IOException.class, () -> uc.getInputStream());
89+
90+
assertThat(uc.getHeaderFields(), instanceOf(Map.class));
91+
assertThat(uc.getHeaderFields().size(), equalTo(27));
92+
assertThat(uc.getHeaderField("Status"), equalTo("403 Forbidden"));
93+
assertThat(uc.getHeaderField(0), equalTo("HTTP/1.1 403 Forbidden"));
94+
assertThat(uc.getHeaderFieldKey(0), nullValue());
95+
assertThat(uc.getHeaderFieldKey(1), equalTo("Access-Control-Allow-Origin"));
96+
97+
assertThat(uc.getRequestProperties(), instanceOf(Map.class));
98+
assertThat(uc.getRequestProperties().size(), equalTo(3));
99+
assertThat(uc.getRequestProperty("Accept"), equalTo("application/vnd.github.v3+json"));
100+
101+
// disconnect does nothing, never throws
102+
uc.disconnect();
103+
uc.disconnect();
104+
105+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.connect());
106+
107+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getAllowUserInteraction());
108+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getConnectTimeout());
109+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getContent());
110+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getContent(null));
111+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getDefaultUseCaches());
112+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getDoInput());
113+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getDoOutput());
114+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getInstanceFollowRedirects());
115+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getOutputStream());
116+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getPermission());
117+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getReadTimeout());
118+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.getUseCaches());
119+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.usingProxy());
120+
121+
Assert.assertThrows(UnsupportedOperationException.class,
122+
() -> uc.addRequestProperty("bogus", "item"));
123+
Assert.assertThrows(UnsupportedOperationException.class,
124+
() -> uc.setAllowUserInteraction(true));
125+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setChunkedStreamingMode(1));
126+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setConnectTimeout(10));
127+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setDefaultUseCaches(true));
128+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setDoInput(true));
129+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setDoOutput(true));
130+
Assert.assertThrows(UnsupportedOperationException.class,
131+
() -> uc.setFixedLengthStreamingMode(1));
132+
Assert.assertThrows(UnsupportedOperationException.class,
133+
() -> uc.setFixedLengthStreamingMode(1L));
134+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setIfModifiedSince(1L));
135+
Assert.assertThrows(UnsupportedOperationException.class,
136+
() -> uc.setInstanceFollowRedirects(true));
137+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setReadTimeout(10));
138+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setRequestMethod("GET"));
139+
Assert.assertThrows(UnsupportedOperationException.class,
140+
() -> uc.setRequestProperty("bogus", "thing"));
141+
Assert.assertThrows(UnsupportedOperationException.class, () -> uc.setUseCaches(true));
142+
143+
RateLimitHandler.FAIL.onError(e, uc);
144+
}
145+
})
50146
.build();
51147

52148
gitHub.getMyself();

0 commit comments

Comments
 (0)