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

smartsheet / smartsheet-java-sdk / #53

08 Dec 2023 05:30PM UTC coverage: 57.712% (-0.3%) from 58.04%
#53

push

github

web-flow
Fix deploy Command (#77)

3940 of 6827 relevant lines covered (57.71%)

0.58 hits per line

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

82.04
/src/main/java/com/smartsheet/api/internal/http/RequestAndResponseData.java
1
/*
2
 * Copyright (C) 2023 Smartsheet
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.smartsheet.api.internal.http;
18

19
import com.smartsheet.api.Trace;
20
import org.apache.http.Header;
21
import org.apache.http.client.methods.HttpRequestBase;
22

23
import java.nio.charset.StandardCharsets;
24
import java.util.Map;
25
import java.util.Set;
26
import java.util.TreeMap;
27

28
/**
29
 * a POJO from which is generated JSON from HTTP request/response pairs
30
 */
31
public class RequestAndResponseData {
32
    public abstract static class HttpPayloadData {
1✔
33
        Map<String, String> headers;
34
        String body;
35

36
        public String getBody() {
37
            return body;
×
38
        }
39

40
        public boolean hasBody() {
41
            return body != null;
1✔
42
        }
43

44
        public boolean hasHeaders() {
45
            return headers != null;
1✔
46
        }
47

48
        public Map<String, String> getHeaders() {
49
            return headers;
1✔
50
        }
51

52
        abstract static class Builder<T extends HttpPayloadData> {
1✔
53
            public void withHeaders() {
54
                // this is seaprate from addHeader in case headers were requested but none found
55
                if (getDataObject().headers == null) {
1✔
56
                    getDataObject().headers = new TreeMap<>();
1✔
57
                }
58
            }
1✔
59

60
            public Builder addHeader(String key, String val) {
61
                withHeaders();
1✔
62
                getDataObject().headers.put(key, val);
1✔
63
                return this;
1✔
64
            }
65

66
            public Builder setBody(String body) {
67
                getDataObject().body = body;
1✔
68
                return this;
1✔
69
            }
70

71
            public abstract T build();
72

73
            public abstract void reset();
74

75
            protected abstract T getDataObject();
76
        }
77
    }
78

79
    public static class RequestData extends HttpPayloadData {
1✔
80
        private String command;
81

82
        public String getCommand() {
83
            return command;
1✔
84
        }
85

86
        public static class Builder extends HttpPayloadData.Builder<RequestData> {
1✔
87
            private RequestData dataObject;
88

89
            @Override
90
            public void reset() {
91
                dataObject = null;
1✔
92
            }
1✔
93

94
            @Override
95
            protected RequestData getDataObject() {
96
                if (dataObject == null) {
1✔
97
                    dataObject = new RequestData();
1✔
98
                }
99
                return dataObject;
1✔
100
            }
101

102
            /**
103
             * Add a command
104
             */
105
            public HttpPayloadData.Builder withCommand(String command) {
106
                getDataObject().command = command;
1✔
107
                return this;
1✔
108
            }
109

110
            /**
111
             * Build the RequestData
112
             */
113
            public RequestData build() {
114
                try {
115
                    // if nothing was added then nothing was built (i.e., this can be null)
116
                    return dataObject;
1✔
117
                } finally {
118
                    reset();
1✔
119
                }
120
            }
121
        }
122
    }
123

124
    public static class ResponseData extends HttpPayloadData {
1✔
125
        private String status;
126

127
        public String getStatus() {
128
            return status;
1✔
129
        }
130

131
        public static class Builder extends HttpPayloadData.Builder<ResponseData> {
1✔
132
            private ResponseData dataObject;
133

134
            @Override
135
            public void reset() {
136
                dataObject = null;
1✔
137
            }
1✔
138

139
            @Override
140
            protected ResponseData getDataObject() {
141
                if (dataObject == null) {
1✔
142
                    dataObject = new ResponseData();
1✔
143
                }
144
                return dataObject;
1✔
145
            }
146

147
            /**
148
             * Add a status
149
             */
150
            public HttpPayloadData.Builder withStatus(String status) {
151
                getDataObject().status = status;
1✔
152
                return this;
1✔
153
            }
154

155
            /**
156
             * Build the ResponseData
157
             */
158
            public ResponseData build() {
159
                try {
160
                    // if nothing was added then nothing was built (i.e., this can be null)
161
                    return dataObject;
1✔
162
                } finally {
163
                    reset();
1✔
164
                }
165
            }
166
        }
167
    }
168

169
    private static int TRUNCATE_LENGTH = Integer.getInteger("Smartsheet.trace.truncateLen", 1024);
1✔
170
    private static final String NULL_STRING = "null";
171

172
    public final RequestData request;
173
    public final ResponseData response;
174

175
    private RequestAndResponseData(RequestData requestData, ResponseData responseData) {
1✔
176
        request = requestData;
1✔
177
        response = responseData;
1✔
178
    }
1✔
179

180
    @Override
181
    public String toString() {
182
        return toString(false);
1✔
183
    }
184

185
    /**
186
     * Convert to a String
187
     */
188
    public String toString(boolean pretty) {
189
        final String eol = pretty ? "\n" : "";
1✔
190
        final String indent = pretty ? "  " : "";
1✔
191
        final String doubleIndent = indent + indent;
1✔
192
        final String tripleIndent = doubleIndent + indent;
1✔
193

194
        StringBuilder buf = new StringBuilder();
1✔
195
        buf.append("{").append(eol);
1✔
196
        buf.append(indent).append("request:");
1✔
197
        if (request == null) {
1✔
198
            buf.append("null,").append(eol);
×
199
        } else {
200
            buf.append("{").append(eol);
1✔
201
            buf
1✔
202
                    .append(doubleIndent)
1✔
203
                    .append("command:'")
1✔
204
                    .append(request.getCommand())
1✔
205
                    .append("'")
1✔
206
                    .append(",")
1✔
207
                    .append(eol);
1✔
208
            if (request.hasHeaders()) {
1✔
209
                buf.append(doubleIndent).append("headers:");
1✔
210
                if (request.getHeaders() == null) {
1✔
211
                    buf.append(NULL_STRING);
×
212
                } else {
213
                    buf.append("{").append(eol);
1✔
214
                    for (Map.Entry<String, String> header : request.headers.entrySet()) {
1✔
215
                        buf
1✔
216
                                .append(tripleIndent)
1✔
217
                                .append("'")
1✔
218
                                .append(header.getKey())
1✔
219
                                .append("':'")
1✔
220
                                .append(header.getValue())
1✔
221
                                .append("'")
1✔
222
                                .append(",")
1✔
223
                                .append(eol);
1✔
224
                    }
1✔
225
                    buf.append(doubleIndent).append("}").append(",").append(eol);
1✔
226
                }
227
            }
228
            if (request.hasBody()) {
1✔
229
                buf.append(doubleIndent).append("body:");
1✔
230
                if (request.body == null) {
1✔
231
                    buf.append(NULL_STRING);
×
232
                } else {
233
                    buf.append("'").append(request.body).append("'");
1✔
234
                }
235
                buf.append(eol);
1✔
236
            }
237
            buf.append(indent).append("},").append(eol);
1✔
238
        }
239
        buf.append(indent).append("response:");
1✔
240
        if (response == null) {
1✔
241
            buf.append(NULL_STRING).append(eol);
×
242
        } else {
243
            buf.append("{").append(eol);
1✔
244
            buf.append(doubleIndent).append("status:'").append(response.getStatus()).append("',").append(eol);
1✔
245
            if (response.hasHeaders()) {
1✔
246
                buf.append(doubleIndent).append("headers:");
×
247
                if (response.getHeaders() == null) {
×
248
                    buf.append(NULL_STRING);
×
249
                } else {
250
                    buf.append("{").append(eol);
×
251
                    for (Map.Entry<String, String> header : response.headers.entrySet()) {
×
252
                        buf
×
253
                                .append(tripleIndent)
×
254
                                .append("'")
×
255
                                .append(header.getKey())
×
256
                                .append("':'")
×
257
                                .append(header.getValue())
×
258
                                .append("',").append(eol);
×
259
                    }
×
260
                    buf.append(doubleIndent).append("},").append(eol);
×
261
                }
262
            }
263
            if (response.hasBody()) {
1✔
264
                buf.append(doubleIndent).append("body:");
×
265
                if (response.body == null) {
×
266
                    buf.append(NULL_STRING);
×
267
                } else {
268
                    buf.append("'").append(response.body).append("'");
×
269
                }
270
                buf.append(eol);
×
271
            }
272
            buf.append(indent).append("}").append(eol);
1✔
273
        }
274
        buf.append("}");
1✔
275
        return buf.toString();
1✔
276
    }
277

278
    /**
279
     * factory method for creating a RequestAndResponseData object from request and response data with the specifid trace fields
280
     */
281
    public static RequestAndResponseData of(HttpRequestBase request, HttpEntitySnapshot requestEntity,
282
                                            HttpResponse response, HttpEntitySnapshot responseEntity,
283
                                            Set<Trace> traces) {
284
        RequestData.Builder requestBuilder = new RequestData.Builder();
1✔
285
        ResponseData.Builder responseBuilder = new ResponseData.Builder();
1✔
286

287
        if (request != null) {
1✔
288
            requestBuilder.withCommand(request.getMethod() + " " + request.getURI());
1✔
289
            boolean binaryBody = false;
1✔
290
            if (traces.contains(Trace.RequestHeaders) && request.getAllHeaders() != null) {
1✔
291
                requestBuilder.withHeaders();
1✔
292
                for (Header header : request.getAllHeaders()) {
1✔
293
                    String headerName = header.getName();
1✔
294
                    String headerValue = header.getValue();
1✔
295
                    if ("Authorization".equals(headerName) && headerValue.length() > 0) {
1✔
296
                        headerValue = "Bearer ****" + headerValue.substring(Math.max(0, headerValue.length() - 4));
1✔
297
                    } else if ("Content-Disposition".equals(headerName)) {
1✔
298
                        binaryBody = true;
1✔
299
                    }
300
                    requestBuilder.addHeader(headerName, headerValue);
1✔
301
                }
302
            }
303
            if (requestEntity != null) {
1✔
304
                if (traces.contains(Trace.RequestBody)) {
1✔
305
                    requestBuilder.setBody(binaryBody ? binaryBody(requestEntity) : getContentAsText(requestEntity));
×
306
                } else if (traces.contains(Trace.RequestBodySummary)) {
1✔
307
                    requestBuilder.setBody(binaryBody
1✔
308
                            ? binaryBody(requestEntity)
1✔
309
                            : truncateAsNeeded(getContentAsText(requestEntity), TRUNCATE_LENGTH));
1✔
310
                }
311
            }
312
        }
313
        if (response != null) {
1✔
314
            boolean binaryBody = false;
1✔
315
            responseBuilder.withStatus(response.getStatusText());
1✔
316
            if (traces.contains(Trace.ResponseHeaders) && response.getHeaders() != null) {
1✔
317
                responseBuilder.withHeaders();
1✔
318
                for (Map.Entry<String, String> header : response.getHeaders().entrySet()) {
1✔
319
                    String headerName = header.getKey();
1✔
320
                    String headerValue = header.getValue();
1✔
321
                    if ("Content-Disposition".equals(headerName)) {
1✔
322
                        binaryBody = true;
×
323
                    }
324
                    responseBuilder.addHeader(headerName, headerValue);
1✔
325
                }
1✔
326
            }
327
            if (responseEntity != null) {
1✔
328
                if (traces.contains(Trace.ResponseBody)) {
1✔
329
                    responseBuilder.setBody(binaryBody ? binaryBody(responseEntity) : getContentAsText(responseEntity));
×
330
                } else if (traces.contains(Trace.ResponseBodySummary)) {
1✔
331
                    responseBuilder.setBody(binaryBody
1✔
332
                            ? binaryBody(responseEntity)
×
333
                            : truncateAsNeeded(getContentAsText(responseEntity), TRUNCATE_LENGTH));
1✔
334
                }
335
            }
336
        }
337
        return new RequestAndResponseData(requestBuilder.build(), responseBuilder.build());
1✔
338
    }
339

340
    static String binaryBody(HttpEntitySnapshot entity) {
341
        return "**possibly-binary(type:" + entity.getContentType() + ", len:" + entity.getContentLength() + ")**";
1✔
342
    }
343

344
    /**
345
     * Get the Content as a String
346
     */
347
    public static String getContentAsText(HttpEntitySnapshot entity) {
348
        if (entity == null) {
1✔
349
            return "";
×
350
        }
351
        byte[] contentBytes = entity.getContentArray();
1✔
352
        String contentAsText;
353
        contentAsText = new String(contentBytes, StandardCharsets.UTF_8);
1✔
354
        return contentAsText;
1✔
355
    }
356

357
    /**
358
     * Truncate the string to the desired length if needed
359
     */
360
    public static String truncateAsNeeded(String string, int truncateLen) {
361
        if (truncateLen == -1) {
1✔
362
            return string;
×
363
        }
364
        truncateLen = Math.min(string.length(), truncateLen);
1✔
365
        String suffix = truncateLen < string.length() ? "..." : "";
1✔
366
        return string.substring(0, truncateLen) + suffix;
1✔
367
    }
368
}
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