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

box / box-java-sdk / #4766

04 Sep 2025 02:54PM UTC coverage: 37.239% (-1.6%) from 38.858%
#4766

push

github

web-flow
feat: Support event with long polling (box/box-codegen#807) (#1409)

32 of 420 new or added lines in 7 files covered. (7.62%)

800 existing lines in 66 files now uncovered.

18480 of 49626 relevant lines covered (37.24%)

0.37 hits per line

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

76.85
/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.text.SimpleDateFormat;
24
import java.util.Arrays;
25
import java.util.Base64;
26
import java.util.Date;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.Locale;
31
import java.util.Map;
32
import java.util.Objects;
33
import java.util.Set;
34
import java.util.TimeZone;
35
import java.util.UUID;
36
import java.util.function.BiFunction;
37
import java.util.stream.Collectors;
38
import javax.crypto.Mac;
39
import javax.crypto.spec.SecretKeySpec;
40
import org.jose4j.jws.JsonWebSignature;
41
import org.jose4j.jwt.JwtClaims;
42
import org.jose4j.jwt.NumericDate;
43
import org.jose4j.lang.JoseException;
44

45
public class UtilsManager {
×
46
  private static final int BUFFER_SIZE = 8192;
47
  private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
1✔
48
  private static final SimpleDateFormat DATE_TIME_FORMAT =
1✔
49
      new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
50
  private static final SimpleDateFormat DATE_TIME_FORMAT_WITH_MILLIS =
1✔
51
      new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
52
  private static final SimpleDateFormat DATE_TIME_FORMAT_WITH_MICROS =
1✔
53
      new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSX");
54

55
  public static <K, V> Map<K, V> mapOf(Entry<K, V>... entries) {
56
    return Arrays.stream(entries)
1✔
57
        .collect(
1✔
58
            HashMap::new,
59
            (map, entry) -> map.put(entry.getKey(), entry.getValue()),
1✔
60
            HashMap::putAll);
61
  }
62

63
  public static <V> Set<V> setOf(V... values) {
64
    return Arrays.stream(values).collect(Collectors.toSet());
×
65
  }
66

67
  public static <K, V> Entry<K, V> entryOf(K key, V value) {
68
    return Entry.of(key, value);
1✔
69
  }
70

71
  public static <K, V> Map<K, V> mergeMaps(Map<K, V> map1, Map<K, V> map2) {
72
    Map<K, V> mergedMap = new HashMap<>();
1✔
73
    if (map1 != null) {
1✔
74
      mergedMap.putAll(map1);
1✔
75
    }
76
    if (map2 != null) {
1✔
77
      mergedMap.putAll(map2);
1✔
78
    }
79
    return mergedMap;
1✔
80
  }
81

82
  public static Map<String, String> prepareParams(Map<String, String> map) {
83
    map.values().removeIf(Objects::isNull);
1✔
84
    return map;
1✔
85
  }
86

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

118
  public static void writeInputStreamToOutputStream(InputStream input, OutputStream output) {
119
    try {
120
      byte[] buffer = new byte[BUFFER_SIZE];
1✔
121
      int n = input.read(buffer);
1✔
122
      while (n != -1) {
1✔
123
        output.write(buffer, 0, n);
1✔
124
        n = input.read(buffer);
1✔
125
      }
126
    } catch (IOException e) {
×
127
      throw new RuntimeException(e);
×
128
    } finally {
129
      try {
130
        input.close();
1✔
131
        output.close();
1✔
132
      } catch (IOException e) {
×
133
        throw new RuntimeException(e);
×
134
      }
1✔
135
    }
136
  }
1✔
137

138
  public static String getUuid() {
139
    return UUID.randomUUID().toString();
1✔
140
  }
141

142
  public static byte[] generateByteBuffer(int size) {
143
    byte[] bytes = new byte[size];
1✔
144
    Arrays.fill(bytes, (byte) 0);
1✔
145
    return bytes;
1✔
146
  }
147

148
  public static InputStream generateByteStream(int size) {
149
    byte[] bytes = generateByteBuffer(size);
1✔
150
    return new ByteArrayInputStream(bytes);
1✔
151
  }
152

153
  public static InputStream generateByteStreamFromBuffer(byte[] buffer) {
154
    return new ByteArrayInputStream(buffer);
1✔
155
  }
156

157
  public static byte[] readByteStream(InputStream inputStream) {
158
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1✔
159
    byte[] data = new byte[BUFFER_SIZE];
1✔
160
    int bytesRead;
161
    try {
162
      while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
1✔
163
        buffer.write(data, 0, bytesRead);
1✔
164
      }
165
    } catch (IOException e) {
×
166
      throw new RuntimeException(e);
×
167
    } finally {
168
      try {
169
        inputStream.close();
1✔
170
      } catch (IOException e) {
×
171
        throw new RuntimeException(e);
×
172
      }
1✔
173
    }
174

175
    return buffer.toByteArray();
1✔
176
  }
177

178
  public static boolean bufferEquals(byte[] buffer1, byte[] buffer2) {
179
    return Arrays.equals(buffer1, buffer2);
1✔
180
  }
181

182
  public static int bufferLength(byte[] buffer) {
183
    return buffer.length;
1✔
184
  }
185

186
  public static InputStream decodeBase64ByteStream(String value) {
187
    return new ByteArrayInputStream(Base64.getDecoder().decode(value));
1✔
188
  }
189

190
  public static String decodeBase64(String value) {
191
    return new String(Base64.getDecoder().decode(value));
1✔
192
  }
193

194
  public static InputStream stringToByteStream(String value) {
195
    return new ByteArrayInputStream(value.getBytes());
1✔
196
  }
197

198
  public static OutputStream getFileOutputStream(String filePath) {
199
    try {
200
      return new FileOutputStream(filePath);
1✔
201
    } catch (FileNotFoundException e) {
×
202
      throw new RuntimeException(e);
×
203
    }
204
  }
205

206
  public static void closeFileOutputStream(OutputStream outputStream) {
207
    try {
208
      outputStream.close();
1✔
209
    } catch (IOException e) {
×
210
      throw new RuntimeException(e);
×
211
    }
1✔
212
  }
1✔
213

214
  public static byte[] readBufferFromFile(String filePath) {
215
    try {
216
      InputStream inputStream = Files.newInputStream(Paths.get(filePath));
1✔
217
      return readByteStream(inputStream);
1✔
218
    } catch (IOException e) {
×
219
      throw new RuntimeException(e);
×
220
    }
221
  }
222

223
  public static String getEnvVar(String envVar) {
224
    return System.getenv(envVar);
1✔
225
  }
226

227
  public static void delayInSeconds(int seconds) {
228
    try {
229
      Thread.sleep(seconds * 1000L);
1✔
230
    } catch (InterruptedException e) {
×
231
      throw new RuntimeException(e);
×
232
    }
1✔
233
  }
1✔
234

235
  public static String readTextFromFile(String filePath) {
236
    try {
237
      return new String(Files.readAllBytes(Paths.get(filePath)));
×
238
    } catch (IOException e) {
×
239
      throw new RuntimeException(e);
×
240
    }
241
  }
242

243
  public static boolean isBrowser() {
244
    return false;
1✔
245
  }
246

247
  public static long getEpochTimeInSeconds() {
248
    return System.currentTimeMillis() / 1000;
1✔
249
  }
250

251
  public static String createJwtAssertion(
252
      Map<String, Object> claims, JwtKey jwtKey, JwtSignOptions jwtOptions) {
253
    JwtClaims jwtClaims = new JwtClaims();
1✔
254
    jwtClaims.setIssuer(jwtOptions.getIssuer());
1✔
255
    jwtClaims.setAudience(jwtOptions.getAudience());
1✔
256
    jwtClaims.setExpirationTime(NumericDate.fromSeconds((Long) claims.get("exp")));
1✔
257

258
    jwtClaims.setSubject(jwtOptions.getSubject());
1✔
259
    jwtClaims.setClaim("box_sub_type", claims.get("box_sub_type"));
1✔
260
    jwtClaims.setGeneratedJwtId(64);
1✔
261

262
    JsonWebSignature jws = new JsonWebSignature();
1✔
263
    jws.setPayload(jwtClaims.toJson());
1✔
264
    jws.setKey(
1✔
265
        jwtOptions.privateKeyDecryptor.decryptPrivateKey(jwtKey.getKey(), jwtKey.getPassphrase()));
1✔
266
    jws.setAlgorithmHeaderValue(jwtOptions.getAlgorithm().getValue());
1✔
267
    jws.setHeader("typ", "JWT");
1✔
268
    if ((jwtOptions.getKeyid() != null) && !jwtOptions.getKeyid().isEmpty()) {
1✔
269
      jws.setHeader("kid", jwtOptions.getKeyid());
1✔
270
    }
271

272
    String assertion;
273

274
    try {
275
      assertion = jws.getCompactSerialization();
1✔
276
    } catch (JoseException e) {
×
277
      throw new BoxSDKError("Error serializing JSON Web Token assertion.", e);
×
278
    }
1✔
279

280
    return assertion;
1✔
281
  }
282

283
  public static JsonNode getValueFromObjectRawData(SerializableObject obj, String key) {
284
    JsonNode value = obj.getRawData();
1✔
285
    for (String k : key.split("\\.")) {
1✔
286
      if (value == null || !value.has(k)) {
1✔
287
        return null;
×
288
      }
289
      value = value.get(k);
1✔
290
    }
291

292
    return value;
1✔
293
  }
294

295
  public static double random(double min, double max) {
296
    return Math.random() * (max - min) + min;
1✔
297
  }
298

299
  public static String hexToBase64(String hex) {
300
    return Base64.getEncoder().encodeToString(new BigInteger(hex, 16).toByteArray());
1✔
301
  }
302

303
  public static Iterator<InputStream> iterateChunks(
304
      InputStream stream, long chunkSize, long fileSize) {
305
    return new Iterator<InputStream>() {
1✔
306
      private boolean streamIsFinished = false;
1✔
307

308
      @Override
309
      public boolean hasNext() {
310
        return !streamIsFinished;
1✔
311
      }
312

313
      @Override
314
      public InputStream next() {
315
        try {
316
          byte[] buffer = new byte[(int) chunkSize];
1✔
317
          int bytesRead = 0;
1✔
318

319
          while (bytesRead < chunkSize) {
1✔
320
            int read = stream.read(buffer, bytesRead, (int) (chunkSize - bytesRead));
1✔
321
            if (read == -1) {
1✔
322
              // End of stream
323
              streamIsFinished = true;
1✔
324
              break;
1✔
325
            }
326
            bytesRead += read;
1✔
327
          }
1✔
328

329
          if (bytesRead == 0) {
1✔
330
            // No more data to yield
331
            streamIsFinished = true;
×
332
            return null;
×
333
          }
334

335
          // Return the chunk as a ByteArrayInputStream
336
          return new ByteArrayInputStream(buffer, 0, bytesRead);
1✔
337
        } catch (Exception e) {
×
338
          throw new RuntimeException("Error reading from stream", e);
×
339
        }
340
      }
341
    };
342
  }
343

344
  /**
345
   * Reduces an iterator using a reducer function and an initial value.
346
   *
347
   * @param <Accumulator> The type of the accumulator (result)
348
   * @param <T> The type of the items in the iterator
349
   * @param iterator The iterator to process
350
   * @param reducer The reducer function
351
   * @param initialValue The initial value for the accumulator
352
   * @return The accumulated result
353
   */
354
  public static <Accumulator, T> Accumulator reduceIterator(
355
      Iterator<T> iterator,
356
      BiFunction<Accumulator, T, Accumulator> reducer,
357
      Accumulator initialValue) {
358
    Accumulator result = initialValue;
1✔
359

360
    while (iterator.hasNext()) {
1✔
361
      T item = iterator.next();
1✔
362
      result = reducer.apply(result, item);
1✔
363
    }
1✔
364

365
    return result;
1✔
366
  }
367

368
  public static Map<String, String> sanitizeMap(
369
      Map<String, String> dictionary, Map<String, String> keysToSanitize) {
UNCOV
370
    return dictionary.entrySet().stream()
×
UNCOV
371
        .collect(
×
UNCOV
372
            Collectors.toMap(
×
373
                Map.Entry::getKey,
374
                entry ->
UNCOV
375
                    keysToSanitize.containsKey(entry.getKey().toLowerCase(Locale.ROOT))
×
UNCOV
376
                        ? JsonManager.sanitizedValue()
×
UNCOV
377
                        : entry.getValue()));
×
378
  }
379

380
  public static Date dateTimeFromString(String dateString) {
381
    SimpleDateFormat[] formats = {
1✔
382
      DATE_TIME_FORMAT, DATE_TIME_FORMAT_WITH_MILLIS, DATE_TIME_FORMAT_WITH_MICROS
383
    };
384

385
    for (SimpleDateFormat format : formats) {
1✔
386
      try {
387
        return format.parse(dateString);
1✔
388
      } catch (java.text.ParseException e) {
1✔
389
        // Ignore and try the next format
390
      }
391
    }
392
    return null;
×
393
  }
394

395
  public static String dateTimeToString(Date dateTime) {
396
    DATE_TIME_FORMAT_WITH_MILLIS.setTimeZone(TimeZone.getTimeZone("UTC"));
1✔
397
    return DATE_TIME_FORMAT_WITH_MILLIS.format(dateTime);
1✔
398
  }
399

400
  public static Date dateFromString(String dateString) {
401
    try {
402
      return DATE_FORMAT.parse(dateString);
1✔
403
    } catch (java.text.ParseException e) {
×
404
      return null;
×
405
    }
406
  }
407

408
  public static String dateToString(Date date) {
409
    DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
1✔
410
    return DATE_FORMAT.format(date);
1✔
411
  }
412

413
  public static String escapeUnicode(String value) {
414
    if (value == null) {
1✔
415
      return null;
×
416
    }
417

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

444
  public static Date epochSecondsToDateTime(long seconds) {
445
    return new Date(seconds * 1000);
1✔
446
  }
447

448
  public static long dateTimeToEpochSeconds(Date dateTime) {
449
    return dateTime.getTime() / 1000;
1✔
450
  }
451

452
  public static boolean compareSignatures(String expectedSignature, String receivedSignature) {
453
    if (expectedSignature == null || receivedSignature == null) {
1✔
454
      return false;
×
455
    }
456
    byte[] expectedBytes = expectedSignature.getBytes(StandardCharsets.UTF_8);
1✔
457
    byte[] receivedBytes = receivedSignature.getBytes(StandardCharsets.UTF_8);
1✔
458
    return MessageDigest.isEqual(expectedBytes, receivedBytes);
1✔
459
  }
460

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

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