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

box / box-java-sdk / #6626

08 Apr 2026 09:45AM UTC coverage: 12.681% (-0.001%) from 12.682%
#6626

Pull #1777

github

web-flow
Merge c5ca91809 into 9eb675591
Pull Request #1777: fix(boxsdkgen): Fix serialization of OffsetDateTime in Java (box/box-codegen#935)

0 of 1 new or added line in 1 file covered. (0.0%)

15 existing lines in 8 files now uncovered.

8372 of 66022 relevant lines covered (12.68%)

0.13 hits per line

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

0.0
/src/main/java/com/box/sdkgen/internal/utils/UtilsManager.java
1
package com.box.sdkgen.internal.utils;
2

3
import com.box.sdkgen.box.errors.BoxSDKError;
4
import com.box.sdkgen.internal.SerializableObject;
5
import com.box.sdkgen.serialization.json.EnumWrapper;
6
import com.box.sdkgen.serialization.json.JsonManager;
7
import com.box.sdkgen.serialization.json.Valuable;
8
import com.fasterxml.jackson.databind.JsonNode;
9
import com.fasterxml.jackson.databind.ObjectMapper;
10
import com.fasterxml.jackson.databind.node.ArrayNode;
11
import java.io.ByteArrayInputStream;
12
import java.io.ByteArrayOutputStream;
13
import java.io.FileNotFoundException;
14
import java.io.FileOutputStream;
15
import java.io.IOException;
16
import java.io.InputStream;
17
import java.io.OutputStream;
18
import java.math.BigInteger;
19
import java.nio.charset.StandardCharsets;
20
import java.nio.file.Files;
21
import java.nio.file.Paths;
22
import java.security.MessageDigest;
23
import java.time.OffsetDateTime;
24
import java.time.ZoneOffset;
25
import java.time.format.DateTimeFormatter;
26
import java.time.format.DateTimeFormatterBuilder;
27
import java.time.format.DateTimeParseException;
28
import java.time.temporal.ChronoField;
29
import java.time.temporal.ChronoUnit;
30
import java.util.Arrays;
31
import java.util.Base64;
32
import java.util.HashMap;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Locale;
36
import java.util.Map;
37
import java.util.Objects;
38
import java.util.Set;
39
import java.util.UUID;
40
import java.util.function.BiFunction;
41
import java.util.stream.Collectors;
42
import javax.crypto.Mac;
43
import javax.crypto.spec.SecretKeySpec;
44
import org.jose4j.jws.JsonWebSignature;
45
import org.jose4j.jwt.JwtClaims;
46
import org.jose4j.jwt.NumericDate;
47
import org.jose4j.lang.JoseException;
48

49
public class UtilsManager {
×
50
  private static final int BUFFER_SIZE = 8192;
51

52
  private static final DateTimeFormatter OFFSET_DATE_TIME_FORMAT =
×
53
      new DateTimeFormatterBuilder()
54
          .appendPattern("yyyy-MM-dd'T'HH:mm:ss")
×
55
          .optionalStart()
×
56
          .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
×
57
          .optionalEnd()
×
58
          .appendOffsetId()
×
59
          .toFormatter();
×
60
  private static final DateTimeFormatter OFFSET_DATE_FORMAT =
×
61
      DateTimeFormatter.ofPattern("yyyy-MM-dd");
×
62

63
  public static <K, V> Map<K, V> mapOf(Entry<K, V>... entries) {
64
    return Arrays.stream(entries)
×
65
        .collect(
×
66
            HashMap::new,
67
            (map, entry) -> map.put(entry.getKey(), entry.getValue()),
×
68
            HashMap::putAll);
69
  }
70

71
  public static <V> Set<V> setOf(V... values) {
72
    return Arrays.stream(values).collect(Collectors.toSet());
×
73
  }
74

75
  public static <K, V> Entry<K, V> entryOf(K key, V value) {
76
    return Entry.of(key, value);
×
77
  }
78

79
  public static <K, V> Map<K, V> mergeMaps(Map<K, V> map1, Map<K, V> map2) {
80
    Map<K, V> mergedMap = new HashMap<>();
×
81
    if (map1 != null) {
×
82
      mergedMap.putAll(map1);
×
83
    }
84
    if (map2 != null) {
×
85
      mergedMap.putAll(map2);
×
86
    }
87
    return mergedMap;
×
88
  }
89

90
  public static Map<String, String> prepareParams(Map<String, String> map) {
91
    map.values().removeIf(Objects::isNull);
×
92
    return map;
×
93
  }
94

95
  public static String convertToString(Object value) {
96
    if (value == null) {
×
97
      return null;
×
98
    }
99
    if (value instanceof EnumWrapper) {
×
100
      return ((EnumWrapper<?>) value).getStringValue();
×
101
    }
102
    if (value instanceof Valuable) {
×
103
      return ((Valuable) value).getValue();
×
104
    }
105
    if (value instanceof List) {
×
106
      List<?> list = (List<?>) value;
×
107
      if (!list.isEmpty() && list.get(0) instanceof SerializableObject) {
×
108
        return JsonManager.serialize(value).toString();
×
109
      } else {
110
        return ((List<?>) value)
×
111
            .stream().map(UtilsManager::convertToString).collect(Collectors.joining(","));
×
112
      }
113
    }
114
    if (value instanceof ArrayNode) {
×
115
      return convertToString(new ObjectMapper().convertValue(value, List.class));
×
116
    }
117
    if (value instanceof JsonNode) {
×
118
      return ((JsonNode) value).asText();
×
119
    }
120
    if (value instanceof SerializableObject) {
×
121
      return JsonManager.serialize(value).toString();
×
122
    }
123
    return value.toString();
×
124
  }
125

126
  public static void writeInputStreamToOutputStream(InputStream input, OutputStream output) {
127
    try {
128
      byte[] buffer = new byte[BUFFER_SIZE];
×
129
      int n = input.read(buffer);
×
130
      while (n != -1) {
×
131
        output.write(buffer, 0, n);
×
132
        n = input.read(buffer);
×
133
      }
134
    } catch (IOException e) {
×
135
      throw new RuntimeException(e);
×
136
    } finally {
137
      try {
138
        input.close();
×
139
        output.close();
×
140
      } catch (IOException e) {
×
141
        throw new RuntimeException(e);
×
142
      }
×
143
    }
144
  }
×
145

146
  public static String getUuid() {
147
    return UUID.randomUUID().toString();
×
148
  }
149

150
  public static byte[] generateByteBuffer(int size) {
151
    byte[] bytes = new byte[size];
×
152
    Arrays.fill(bytes, (byte) 0);
×
153
    return bytes;
×
154
  }
155

156
  public static InputStream generateByteStream(int size) {
157
    byte[] bytes = generateByteBuffer(size);
×
158
    return new ByteArrayInputStream(bytes);
×
159
  }
160

161
  public static InputStream generateByteStreamFromBuffer(byte[] buffer) {
162
    return new ByteArrayInputStream(buffer);
×
163
  }
164

165
  public static byte[] readByteStream(InputStream inputStream) {
166
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
×
167
    byte[] data = new byte[BUFFER_SIZE];
×
168
    int bytesRead;
169
    try {
170
      while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
×
171
        buffer.write(data, 0, bytesRead);
×
172
      }
173
    } catch (IOException e) {
×
174
      throw new RuntimeException(e);
×
175
    } finally {
176
      try {
177
        inputStream.close();
×
178
      } catch (IOException e) {
×
179
        throw new RuntimeException(e);
×
180
      }
×
181
    }
182

183
    return buffer.toByteArray();
×
184
  }
185

186
  public static boolean bufferEquals(byte[] buffer1, byte[] buffer2) {
187
    return Arrays.equals(buffer1, buffer2);
×
188
  }
189

190
  public static int bufferLength(byte[] buffer) {
191
    return buffer.length;
×
192
  }
193

194
  public static InputStream decodeBase64ByteStream(String value) {
195
    return new ByteArrayInputStream(Base64.getDecoder().decode(value));
×
196
  }
197

198
  public static String decodeBase64(String value) {
199
    return new String(Base64.getDecoder().decode(value));
×
200
  }
201

202
  public static InputStream stringToByteStream(String value) {
203
    return new ByteArrayInputStream(value.getBytes());
×
204
  }
205

206
  public static OutputStream getFileOutputStream(String filePath) {
207
    try {
208
      return new FileOutputStream(filePath);
×
209
    } catch (FileNotFoundException e) {
×
210
      throw new RuntimeException(e);
×
211
    }
212
  }
213

214
  public static void closeFileOutputStream(OutputStream outputStream) {
215
    try {
216
      outputStream.close();
×
217
    } catch (IOException e) {
×
218
      throw new RuntimeException(e);
×
219
    }
×
220
  }
×
221

222
  public static byte[] readBufferFromFile(String filePath) {
223
    try {
224
      InputStream inputStream = Files.newInputStream(Paths.get(filePath));
×
225
      return readByteStream(inputStream);
×
226
    } catch (IOException e) {
×
227
      throw new RuntimeException(e);
×
228
    }
229
  }
230

231
  public static String getEnvVar(String envVar) {
232
    return System.getenv(envVar);
×
233
  }
234

235
  public static void delayInSeconds(int seconds) {
236
    try {
237
      Thread.sleep(seconds * 1000L);
×
238
    } catch (InterruptedException e) {
×
239
      throw new RuntimeException(e);
×
240
    }
×
241
  }
×
242

243
  public static String readTextFromFile(String filePath) {
244
    try {
245
      return new String(Files.readAllBytes(Paths.get(filePath)));
×
246
    } catch (IOException e) {
×
247
      throw new RuntimeException(e);
×
248
    }
249
  }
250

251
  public static boolean isBrowser() {
252
    return false;
×
253
  }
254

255
  public static long getEpochTimeInSeconds() {
256
    return System.currentTimeMillis() / 1000;
×
257
  }
258

259
  public static String createJwtAssertion(
260
      Map<String, Object> claims, JwtKey jwtKey, JwtSignOptions jwtOptions) {
261
    JwtClaims jwtClaims = new JwtClaims();
×
262
    jwtClaims.setIssuer(jwtOptions.getIssuer());
×
263
    jwtClaims.setAudience(jwtOptions.getAudience());
×
264
    jwtClaims.setExpirationTime(NumericDate.fromSeconds((Long) claims.get("exp")));
×
265

266
    jwtClaims.setSubject(jwtOptions.getSubject());
×
267
    jwtClaims.setClaim("box_sub_type", claims.get("box_sub_type"));
×
268
    jwtClaims.setGeneratedJwtId(64);
×
269

270
    JsonWebSignature jws = new JsonWebSignature();
×
271
    jws.setPayload(jwtClaims.toJson());
×
272
    jws.setKey(
×
273
        jwtOptions.privateKeyDecryptor.decryptPrivateKey(jwtKey.getKey(), jwtKey.getPassphrase()));
×
274
    jws.setAlgorithmHeaderValue(jwtOptions.getAlgorithm().getValue());
×
275
    jws.setHeader("typ", "JWT");
×
276
    if ((jwtOptions.getKeyid() != null) && !jwtOptions.getKeyid().isEmpty()) {
×
277
      jws.setHeader("kid", jwtOptions.getKeyid());
×
278
    }
279

280
    String assertion;
281

282
    try {
283
      assertion = jws.getCompactSerialization();
×
284
    } catch (JoseException e) {
×
285
      throw new BoxSDKError("Error serializing JSON Web Token assertion.", e);
×
286
    }
×
287

288
    return assertion;
×
289
  }
290

291
  public static JsonNode getValueFromObjectRawData(SerializableObject obj, String key) {
292
    JsonNode value = obj.getRawData();
×
293
    for (String k : key.split("\\.")) {
×
294
      if (value == null || !value.has(k)) {
×
295
        return null;
×
296
      }
297
      value = value.get(k);
×
298
    }
299

300
    return value;
×
301
  }
302

303
  public static double random(double min, double max) {
304
    return Math.random() * (max - min) + min;
×
305
  }
306

307
  public static String hexToBase64(String hex) {
308
    return Base64.getEncoder().encodeToString(new BigInteger(hex, 16).toByteArray());
×
309
  }
310

311
  public static Iterator<InputStream> iterateChunks(
312
      InputStream stream, long chunkSize, long fileSize) {
313
    return new Iterator<InputStream>() {
×
314
      private boolean streamIsFinished = false;
×
315

316
      @Override
317
      public boolean hasNext() {
318
        return !streamIsFinished;
×
319
      }
320

321
      @Override
322
      public InputStream next() {
323
        try {
324
          byte[] buffer = new byte[(int) chunkSize];
×
325
          int bytesRead = 0;
×
326

327
          while (bytesRead < chunkSize) {
×
328
            int read = stream.read(buffer, bytesRead, (int) (chunkSize - bytesRead));
×
329
            if (read == -1) {
×
330
              // End of stream
331
              streamIsFinished = true;
×
332
              break;
×
333
            }
334
            bytesRead += read;
×
335
          }
×
336

337
          if (bytesRead == 0) {
×
338
            // No more data to yield
339
            streamIsFinished = true;
×
340
            return null;
×
341
          }
342

343
          // Return the chunk as a ByteArrayInputStream
344
          return new ByteArrayInputStream(buffer, 0, bytesRead);
×
345
        } catch (Exception e) {
×
346
          throw new RuntimeException("Error reading from stream", e);
×
347
        }
348
      }
349
    };
350
  }
351

352
  /**
353
   * Reduces an iterator using a reducer function and an initial value.
354
   *
355
   * @param <Accumulator> The type of the accumulator (result)
356
   * @param <T> The type of the items in the iterator
357
   * @param iterator The iterator to process
358
   * @param reducer The reducer function
359
   * @param initialValue The initial value for the accumulator
360
   * @return The accumulated result
361
   */
362
  public static <Accumulator, T> Accumulator reduceIterator(
363
      Iterator<T> iterator,
364
      BiFunction<Accumulator, T, Accumulator> reducer,
365
      Accumulator initialValue) {
366
    Accumulator result = initialValue;
×
367

368
    while (iterator.hasNext()) {
×
369
      T item = iterator.next();
×
370
      result = reducer.apply(result, item);
×
371
    }
×
372

373
    return result;
×
374
  }
375

376
  public static Map<String, String> sanitizeMap(
377
      Map<String, String> dictionary, Map<String, String> keysToSanitize) {
378
    return dictionary.entrySet().stream()
×
379
        .collect(
×
380
            Collectors.toMap(
×
381
                Map.Entry::getKey,
382
                entry ->
383
                    keysToSanitize.containsKey(entry.getKey().toLowerCase(Locale.ROOT))
×
384
                        ? JsonManager.sanitizedValue()
×
385
                        : entry.getValue()));
×
386
  }
387

388
  public static OffsetDateTime dateTimeFromString(String dateString) {
389
    try {
390
      return OffsetDateTime.parse(dateString, OFFSET_DATE_TIME_FORMAT);
×
391
    } catch (DateTimeParseException e) {
×
392
      return null;
×
393
    }
394
  }
395

396
  public static String dateTimeToString(OffsetDateTime dateTime) {
NEW
397
    return dateTime.truncatedTo(ChronoUnit.SECONDS).format(OFFSET_DATE_TIME_FORMAT);
×
398
  }
399

400
  public static OffsetDateTime dateFromString(String dateString) {
401
    try {
402
      // For date-only strings, parse as date and convert to OffsetDateTime at start of day UTC
403
      if (dateString.matches("\\d{4}-\\d{2}-\\d{2}")) {
×
404
        return OffsetDateTime.parse(dateString + "T00:00:00Z");
×
405
      }
406
      // Otherwise try to parse as full OffsetDateTime
407
      return dateTimeFromString(dateString);
×
408
    } catch (DateTimeParseException e) {
×
409
      return null;
×
410
    }
411
  }
412

413
  public static String dateToString(OffsetDateTime date) {
414
    return date.format(OFFSET_DATE_FORMAT);
×
415
  }
416

417
  public static String escapeUnicode(String value) {
418
    if (value == null) {
×
419
      return null;
×
420
    }
421

422
    StringBuilder result = new StringBuilder();
×
423
    for (int i = 0; i < value.length(); i++) {
×
424
      char ch = value.charAt(i);
×
425
      if (ch >= 0x007F) {
×
426
        result.append(String.format("\\u%04x", (int) ch));
×
427
      } else if (ch == '\\') {
×
428
        result.append("\\\\");
×
429
      } else if (ch == '\n') {
×
430
        result.append("\\n");
×
431
      } else if (ch == '\r') {
×
432
        result.append("\\r");
×
433
      } else if (ch == '\t') {
×
434
        result.append("\\t");
×
435
      } else if (ch == '/') {
×
436
        if (i == 0 || value.charAt(i - 1) != '\\') {
×
437
          result.append("\\/");
×
438
        } else {
439
          result.append(ch);
×
440
        }
441
      } else {
442
        result.append(ch);
×
443
      }
444
    }
445
    return result.toString();
×
446
  }
447

448
  public static OffsetDateTime epochSecondsToDateTime(long seconds) {
449
    return OffsetDateTime.ofInstant(java.time.Instant.ofEpochSecond(seconds), ZoneOffset.UTC);
×
450
  }
451

452
  public static long dateTimeToEpochSeconds(OffsetDateTime dateTime) {
453
    return dateTime.toEpochSecond();
×
454
  }
455

456
  public static boolean compareSignatures(String expectedSignature, String receivedSignature) {
457
    if (expectedSignature == null || receivedSignature == null) {
×
458
      return false;
×
459
    }
460
    byte[] expectedBytes = expectedSignature.getBytes(StandardCharsets.UTF_8);
×
461
    byte[] receivedBytes = receivedSignature.getBytes(StandardCharsets.UTF_8);
×
462
    return MessageDigest.isEqual(expectedBytes, receivedBytes);
×
463
  }
464

465
  public static String computeWebhookSignature(
466
      String body, Map<String, String> headers, String signatureKey, boolean escapeBody) {
467
    if (signatureKey == null) {
×
468
      return null;
×
469
    }
470
    if (!"1".equals(headers.get("box-signature-version"))) {
×
471
      return null;
×
472
    }
473
    if (!"HmacSHA256".equals(headers.get("box-signature-algorithm"))) {
×
474
      return null;
×
475
    }
476
    if (!headers.containsKey("box-delivery-timestamp")) {
×
477
      return null;
×
478
    }
479

480
    try {
481
      String escapedBody = escapeBody ? escapeUnicode(body) : body;
×
482
      byte[] encodedSignatureKey = signatureKey.getBytes("UTF-8");
×
483
      byte[] encodedBody = escapedBody.getBytes("UTF-8");
×
484
      byte[] encodedTimestamp = headers.get("box-delivery-timestamp").getBytes("UTF-8");
×
485
      Mac mac = Mac.getInstance("HmacSHA256");
×
486
      SecretKeySpec secretKeySpec = new SecretKeySpec(encodedSignatureKey, "HmacSHA256");
×
487
      mac.init(secretKeySpec);
×
488
      mac.update(encodedBody);
×
489
      mac.update(encodedTimestamp);
×
490
      byte[] hmacDigest = mac.doFinal();
×
491
      return Base64.getEncoder().encodeToString(hmacDigest);
×
492
    } catch (Exception e) {
×
493
      return null;
×
494
    }
495
  }
496
}
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

© 2026 Coveralls, Inc