• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hyperwallet / java-sdk / #695

16 May 2025 12:19AM CUT coverage: 96.097%. Remained the same
#695

push

web-flow
Deprecate Double to String (#220)

* Deprecate Double to String

* Fix unit test

* Prepare to release 1.9.7

5048 of 5253 relevant lines covered (96.1%)

65.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.5
/src/main/java/com/hyperwallet/clientsdk/util/Request.java
1
package com.hyperwallet.clientsdk.util;
2

3
import cc.protea.util.http.BinaryResponse;
4
import cc.protea.util.http.Response;
5
import java.io.*;
6
import java.net.*;
7
import java.util.HashMap;
8
import java.util.List;
9
import java.util.Map;
10

11
/*
12

13
 Modified with modifications copyright Richard Stanford
14

15
 -- Original portions by Joe Ernst --
16

17
 * Copyright 2012 Joe J. Ernst
18
 * <p/>
19
 * Licensed under the Apache License, Version 2.0 (the "License");
20
 * you may not use this file except in compliance with the License.
21
 * You may obtain a copy of the License at
22
 * <p/>
23
 * http://www.apache.org/licenses/LICENSE-2.0
24
 * <p/>
25
 * Unless required by applicable law or agreed to in writing, software
26
 * distributed under the License is distributed on an "AS IS" BASIS,
27
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28
 * See the License for the specific language governing permissions and
29
 * limitations under the License.
30
 */
31

32
/**
33
 * This class represents an HTTP Request message.
34
 */
35
public class Request extends Message<Request> {
36

37
    protected final HttpURLConnection connection;
38
    private final Map<String, String> query = new HashMap<String, String>();
72✔
39
    private OutputStreamWriter writer;
40
    private URL url;
41

42
    /**
43
     * The Constructor takes the url as a String, a proxy as a Proxy, and proxy credentials as a String.
44
     *
45
     * @param url               The url parameter does not need the query string parameters if they are going to be supplied via calls to
46
     *                          {@link #addQueryParameter(String, String)}. You can, however, supply the query parameters in the URL if you wish.
47
     * @param connectionTimeout A specified timeout value, in milliseconds, to establish communications link to the resource by
48
     *                          {@link  URLConnection}.
49
     * @param readTimeout       A specified timeout, in milliseconds, for reading data from an established connection to the resource
50
     *                          by {@link  URLConnection}.
51
     * @param proxy             The Connection's Proxy value
52
     * @param proxyUsername     The Proxy username
53
     * @param proxyPassword     The Proxy password
54
     */
55
    public Request(final String url, int connectionTimeout, int readTimeout, final Proxy proxy, final String proxyUsername,
56
            final String proxyPassword) {
72✔
57
        try {
58
            this.url = new URL(url);
72✔
59
            if (proxyUsername != null && proxyPassword != null) {
72✔
60
                // NOTE: Removing Basic Auth from tunneling disabledSchemas is required in order
61
                // for Proxy Authorization to work. To prevent overriding client System Settings,
62
                // the client should set this System property themselves inside their JVM Options (1)
63
                // or their own code (2). Approaches listed below:
64
                // 1. jdk.http.auth.tunneling.disabledSchemes=
65
                // 2. System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "false");
66

67
                Authenticator authenticator = new DefaultPasswordAuthenticator(
×
68
                        proxyUsername, proxyPassword);
69
                Authenticator.setDefault(authenticator);
×
70
            }
71

72
            HttpURLConnection conn = null;
72✔
73
            if (proxy != null) {
72✔
74
                conn = (HttpURLConnection) this.url.openConnection(proxy);
12✔
75
            } else {
76
                conn = (HttpURLConnection) this.url.openConnection();
60✔
77
            }
78

79
            this.connection = conn;
72✔
80
            this.connection.setConnectTimeout(connectionTimeout);
72✔
81
            this.connection.setReadTimeout(readTimeout);
72✔
82
        } catch (IOException e) {
×
83
            throw new RuntimeException(e);
×
84
        }
72✔
85
    }
72✔
86

87
    /**
88
     * Adds a Query Parameter to a list. The list is converted to a String and appended to the URL when the Request is submitted.
89
     *
90
     * @param name  The Query Parameter's name
91
     * @param value The Query Parameter's value
92
     * @return this Request, to support chained method calls
93
     */
94
    public Request addQueryParameter(final String name, final String value) {
95
        this.query.put(name, value);
×
96
        return this;
×
97
    }
98

99
    /**
100
     * Removes the specified Query Parameter.
101
     *
102
     * @param name The name of the Query Parameter to remove
103
     * @return this Request, to support chained method calls
104
     */
105
    public Request removeQueryParameter(final String name) {
106
        this.query.remove(name);
×
107
        return this;
×
108
    }
109

110
    /**
111
     * Issues a GET to the server.
112
     *
113
     * @return The {@link Response} from the server
114
     * @throws IOException a {@link IOException}
115
     */
116
    public Response getResource() throws IOException {
117
        buildQueryString();
24✔
118
        buildHeaders();
24✔
119

120
        connection.setDoOutput(true);
24✔
121
        connection.setRequestMethod("GET");
24✔
122

123
        return readResponse();
24✔
124
    }
125

126
    /**
127
     * Issues a GET to the server.
128
     *
129
     * @return The {@link Response} from the server
130
     * @throws IOException a {@link IOException}
131
     */
132
    public BinaryResponse getBinaryResource() throws IOException {
133
        buildQueryString();
×
134
        buildHeaders();
×
135

136
        connection.setDoOutput(true);
×
137
        connection.setRequestMethod("GET");
×
138

139
        return readBinaryResponse();
×
140
    }
141

142
    /**
143
     * Issues a PUT to the server.
144
     *
145
     * @return The {@link Response} from the server
146
     * @throws IOException a {@link IOException}
147
     */
148
    public Response putResource() throws IOException {
149
        return writeResource("PUT", this.body);
14✔
150
    }
151

152
    public Response headResource() throws IOException {
153
        buildQueryString();
×
154
        buildHeaders();
×
155

156
        connection.setDoOutput(true);
×
157
        connection.setRequestMethod("HEAD");
×
158

159
        return readResponse();
×
160
    }
161

162
    public Response optionsResource() throws IOException {
163
        buildQueryString();
×
164
        buildHeaders();
×
165

166
        connection.setDoOutput(true);
×
167
        connection.setRequestMethod("OPTIONS");
×
168

169
        return readResponse();
×
170
    }
171

172
    public Response traceResource() throws IOException {
173
        buildQueryString();
×
174
        buildHeaders();
×
175

176
        connection.setDoOutput(true);
×
177
        connection.setRequestMethod("TRACE");
×
178

179
        return readResponse();
×
180
    }
181

182
    /**
183
     * Issues a POST to the server.
184
     *
185
     * @return The {@link Response} from the server
186
     * @throws IOException a {@link IOException}
187
     */
188
    public Response postResource() throws IOException {
189
        return writeResource("POST", this.body);
30✔
190
    }
191

192

193
    /**
194
     * Issues a DELETE to the server.
195
     *
196
     * @return The {@link Response} from the server
197
     * @throws IOException a {@link IOException}
198
     */
199
    public Response deleteResource() throws IOException {
200
        buildQueryString();
×
201
        buildHeaders();
×
202

203
        connection.setDoOutput(true);
×
204
        connection.setRequestMethod("DELETE");
×
205

206
        return readResponse();
×
207
    }
208

209
    /**
210
     * A private method that handles issuing POST and PUT requests
211
     *
212
     * @param method POST or PUT
213
     * @param body   The body of the Message
214
     * @return the {@link Response} from the server
215
     * @throws IOException a {@link IOException}
216
     */
217
    private Response writeResource(final String method, final String body) throws IOException {
218
        buildQueryString();
44✔
219
        buildHeaders();
44✔
220

221
        connection.setDoOutput(true);
44✔
222
        connection.setRequestMethod(method);
44✔
223

224
        writer = new OutputStreamWriter(connection.getOutputStream());
44✔
225
        writer.write(body);
37✔
226
        writer.close();
37✔
227

228
        return readResponse();
37✔
229
    }
230

231
    /**
232
     * A private method that handles reading the Responses from the server.
233
     *
234
     * @return a {@link Response} from the server.
235
     * @throws IOException a {@link IOException}
236
     */
237
    protected Response readResponse() throws IOException {
238
        Response response = new Response();
62✔
239
        response.setResponseCode(connection.getResponseCode());
62✔
240
        response.setResponseMessage(connection.getResponseMessage());
53✔
241
        response.setHeaders(connection.getHeaderFields());
53✔
242
        try {
243
            response.setBody(getStringFromStream(connection.getInputStream()));
53✔
244
        } catch (IOException e) {
25✔
245
            response.setBody(getStringFromStream(connection.getErrorStream()));
25✔
246
        }
28✔
247
        return response;
53✔
248
    }
249

250
    /**
251
     * A private method that handles reading the Responses from the server.
252
     *
253
     * @return a {@link Response} from the server.
254
     * @throws IOException a {@link IOException}
255
     */
256
    private BinaryResponse readBinaryResponse() throws IOException {
257
        BinaryResponse response = new BinaryResponse();
×
258
        response.setResponseCode(connection.getResponseCode());
×
259
        response.setResponseMessage(connection.getResponseMessage());
×
260
        response.setHeaders(connection.getHeaderFields());
×
261
        try {
262
            response.setBinaryBody(getBinaryFromStream(connection.getInputStream()));
×
263
        } catch (IOException e) {
×
264
            response.setBinaryBody(getBinaryFromStream(connection.getErrorStream()));
×
265
        }
×
266
        return response;
×
267
    }
268

269
    private byte[] getBinaryFromStream(final InputStream is) {
270
        if (is == null) {
×
271
            return null;
×
272
        }
273
        ByteArrayOutputStream os = new ByteArrayOutputStream();
×
274
        try {
275
            byte[] buffer = new byte[0xFFFF];
×
276
            for (int len = is.read(buffer); len != -1; len = is.read(buffer)) {
×
277
                os.write(buffer, 0, len);
×
278
            }
279
            return os.toByteArray();
×
280
        } catch (IOException e) {
×
281
            return null;
×
282
        } finally {
283
            if (os != null) {
×
284
                try {
285
                    os.close();
×
286
                } catch (IOException e) {
×
287
                    // no-op
288
                }
×
289
            }
290
        }
×
291
    }
292

293
    private String getStringFromStream(final InputStream is) {
294
        if (is == null) {
53✔
295
            return null;
5✔
296
        }
297
        BufferedReader reader = null;
48✔
298
        try {
299
            reader = new BufferedReader(new InputStreamReader(is));
48✔
300
            StringBuilder builder = new StringBuilder();
48✔
301
            String line;
302
            while ((line = reader.readLine()) != null) {
128✔
303
                builder.append(line).append("\n");
80✔
304
            }
305
            return builder.toString();
96✔
306
        } catch (IOException e) {
×
307
            return null;
×
308
        } finally {
309
            if (reader != null) {
48✔
310
                try {
311
                    reader.close();
48✔
312
                } catch (IOException e) {
×
313
                    // no-op
314
                }
48✔
315
            }
316
        }
×
317
    }
318

319
    /**
320
     * A private method that loops through the query parameter Map, building a String to be appended to the URL.
321
     *
322
     * @throws MalformedURLException a {@link MalformedURLException}
323
     */
324
    protected void buildQueryString() throws MalformedURLException {
325
        StringBuilder builder = new StringBuilder();
72✔
326

327
        // Put the query parameters on the URL before issuing the request
328
        if (!query.isEmpty()) {
72✔
329
            for (Map.Entry<String, String> param : query.entrySet()) {
×
330
                builder.append(param.getKey());
×
331
                builder.append("=");
×
332
                builder.append(param.getValue());
×
333
                builder.append("&");
×
334
            }
×
335
            builder.deleteCharAt(builder.lastIndexOf("&")); // Remove the trailing ampersand
×
336
        }
337

338
        if (builder.length() > 0) {
72✔
339
            // If there was any query string at all, begin it with the question mark
340
            builder.insert(0, "?");
×
341
        }
342

343
        url = new URL(url.toString() + builder.toString());
72✔
344
    }
72✔
345

346
    /**
347
     * A private method that loops through the headers Map, putting them on the Request or Response object.
348
     */
349
    protected void buildHeaders() {
350
        if (!headers.isEmpty()) {
72✔
351
            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
72✔
352
                List<String> values = entry.getValue();
481✔
353

354
                for (String value : values) {
481✔
355
                    connection.addRequestProperty(entry.getKey(), value);
481✔
356
                }
481✔
357
            }
481✔
358
        }
359
    }
72✔
360

361
    public Request setBodyUrlEncoded(final Map<String, String> map) {
362

363
        if (map == null) {
×
364
            this.body = null;
×
365
            return this;
×
366
        }
367

368
        StringBuilder sb = new StringBuilder();
×
369
        boolean first = true;
×
370

371
        for (Map.Entry<String, String> entry : map.entrySet()) {
×
372
            sb.append(first ? "" : "&").append(encode(entry.getKey())).append("=").append(encode(entry.getValue()));
×
373
            first = false;
×
374
        }
×
375

376
        setBody(sb.toString());
×
377
        addHeader("Content-type", "application/x-www-form-urlencoded");
×
378
        addHeader("Content-length", "" + (body.length()));
×
379

380
        return this;
×
381
    }
382

383
    public static class DefaultPasswordAuthenticator extends Authenticator {
384

385
        /**
386
         * Username
387
         */
388
        private String userName;
389

390
        /**
391
         * Password
392
         */
393
        private String password;
394

395
        public DefaultPasswordAuthenticator(String userName, String password) {
×
396
            this.userName = userName;
×
397
            this.password = password;
×
398
        }
×
399

400
        public PasswordAuthentication getPasswordAuthentication() {
401
            return (new PasswordAuthentication(userName, password.toCharArray()));
×
402
        }
403
    }
404

405
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc