1 package com.guinetik.rr.util;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.Scanner;
6
7 /**
8 * Utility class for safe input stream operations with proper resource management.
9 *
10 * <p>This class provides static methods for reading input streams into strings,
11 * ensuring proper cleanup of resources even when exceptions occur.
12 *
13 * <h2>Reading Input Streams</h2>
14 * <pre class="language-java"><code>
15 * // Read an input stream to string
16 * InputStream is = connection.getInputStream();
17 * String content = StreamUtils.readInputStreamAsString(is);
18 *
19 * // Read error stream (returns null if unavailable)
20 * InputStream errorStream = connection.getErrorStream();
21 * String error = StreamUtils.readErrorStream(errorStream);
22 * if (error != null) {
23 * System.err.println("Error response: " + error);
24 * }
25 * </code></pre>
26 *
27 * <h2>Usage in HTTP Response Handling</h2>
28 * <pre class="language-java"><code>
29 * HttpURLConnection conn = (HttpURLConnection) url.openConnection();
30 * int status = conn.getResponseCode();
31 *
32 * if (status >= 200 && status < 300) {
33 * String body = StreamUtils.readInputStreamAsString(conn.getInputStream());
34 * // Process successful response
35 * } else {
36 * String error = StreamUtils.readErrorStream(conn.getErrorStream());
37 * // Handle error response
38 * }
39 * </code></pre>
40 *
41 * @author guinetik <guinetik@gmail.com>
42 * @since 1.0.0
43 */
44 public final class StreamUtils {
45
46 private StreamUtils() {
47 // Utility class, no instantiation
48 }
49
50 /**
51 * Reads an input stream into a string, handling resource cleanup properly.
52 * This method ensures the Scanner is properly closed after reading.
53 *
54 * @param is The input stream to read
55 * @return The string contents of the stream
56 * @throws IOException If an I/O error occurs
57 */
58 public static String readInputStreamAsString(InputStream is) throws IOException {
59 if (is == null) {
60 return "";
61 }
62
63 try (Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A")) {
64 return scanner.hasNext() ? scanner.next() : "";
65 }
66 }
67
68 /**
69 * Attempts to read from an error stream, handling possible exceptions gracefully.
70 * This method ensures the Scanner is properly closed after reading.
71 *
72 * @param errorStream The error stream to read
73 * @return The string contents of the stream, or null if not available
74 */
75 public static String readErrorStream(InputStream errorStream) {
76 if (errorStream == null) {
77 return null;
78 }
79
80 try (Scanner scanner = new Scanner(errorStream, "UTF-8").useDelimiter("\\A")) {
81 return scanner.hasNext() ? scanner.next() : "";
82 } catch (Exception e) {
83 // Silently handle errors reading the error stream
84 return null;
85 }
86 }
87 }