| 1 | package com.reallifedeveloper.tools; | |
| 2 | ||
| 3 | import java.io.IOException; | |
| 4 | import java.io.InputStream; | |
| 5 | import java.net.URI; | |
| 6 | import java.net.URISyntaxException; | |
| 7 | import java.net.URL; | |
| 8 | import java.nio.charset.StandardCharsets; | |
| 9 | ||
| 10 | import org.slf4j.Logger; | |
| 11 | import org.slf4j.LoggerFactory; | |
| 12 | ||
| 13 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; | |
| 14 | ||
| 15 | /** | |
| 16 | * Utility class to read a file and display the content as bytes. | |
| 17 | * | |
| 18 | * @author RealLifeDeveloper | |
| 19 | */ | |
| 20 | @SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD", justification = "Use at your own risk") | |
| 21 | public final class ReadBytes { | |
| 22 | ||
| 23 | private static final int BLOCK_SIZE = 16; | |
| 24 | ||
| 25 | private static final String NEWLINE = "\\R"; | |
| 26 | ||
| 27 | private static final Logger LOG = LoggerFactory.getLogger(ReadBytes.class); | |
| 28 | ||
| 29 | /** | |
| 30 | * This is a utility class with only static methods, so we hide the only constructor. | |
| 31 | */ | |
| 32 | private ReadBytes() { | |
| 33 | } | |
| 34 | ||
| 35 | /** | |
| 36 | * Main method to read bytes from a URL and log the result. | |
| 37 | * | |
| 38 | * @param args a string array that should contain one element, the URL to read from | |
| 39 | * | |
| 40 | * @throws IOException if reading from the URL failed | |
| 41 | * @throws URISyntaxException if the provided URL is malformed | |
| 42 | */ | |
| 43 | public static void main(String... args) throws IOException, URISyntaxException { | |
| 44 |
1
1. main : negated conditional → KILLED |
if (args.length != 1) { |
| 45 | throw new IllegalArgumentException("Usage: java " + ReadBytes.class.getName() + " <url>"); | |
| 46 | } | |
| 47 | URL url = new URI(args[0]).toURL(); | |
| 48 |
1
1. main : removed call to com/reallifedeveloper/tools/ReadBytes::logBytesFromUrl → KILLED |
logBytesFromUrl(url); |
| 49 | } | |
| 50 | ||
| 51 | /** | |
| 52 | * Reads bytes from the given URL and logs them at info level, both as hexadecimal byte values and as an ASCII string. | |
| 53 | * | |
| 54 | * @param url the URL to read from | |
| 55 | * | |
| 56 | * @throws IOException if reading from {@code url} failed | |
| 57 | */ | |
| 58 | public static void logBytesFromUrl(URL url) throws IOException { | |
| 59 |
1
1. logBytesFromUrl : negated conditional → KILLED |
if (url == null) { |
| 60 | throw new IllegalArgumentException("url must not be null"); | |
| 61 | } | |
| 62 | byte[] data = new byte[BLOCK_SIZE]; | |
| 63 | try (InputStream in = url.openConnection().getInputStream()) { | |
| 64 | int bytesRead; | |
| 65 |
1
1. logBytesFromUrl : negated conditional → KILLED |
while ((bytesRead = in.read(data)) != -1) { |
| 66 |
1
1. logBytesFromUrl : removed call to com/reallifedeveloper/tools/ReadBytes::logBytes → KILLED |
logBytes(data, bytesRead); |
| 67 | } | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | @SuppressFBWarnings(value = "CRLF_INJECTION_LOGS", justification = "The string is being sanitized replacing line break with space") | |
| 72 | private static void logBytes(byte[] data, int n) { | |
| 73 | StringBuilder sb = new StringBuilder(); | |
| 74 |
2
1. logBytes : changed conditional boundary → KILLED 2. logBytes : negated conditional → KILLED |
for (int i = 0; i < n; i++) { |
| 75 | byte b = data[i]; | |
| 76 | sb.append(String.format("%02X ", b)); | |
| 77 | } | |
| 78 |
2
1. logBytes : negated conditional → SURVIVED 2. logBytes : changed conditional boundary → SURVIVED |
if (n < BLOCK_SIZE) { |
| 79 |
2
1. logBytes : negated conditional → RUN_ERROR 2. logBytes : changed conditional boundary → SURVIVED |
for (int i = n; i < BLOCK_SIZE; i++) { |
| 80 | sb.append(" "); | |
| 81 | } | |
| 82 | } | |
| 83 | sb.append(": ").append(new String(data, StandardCharsets.US_ASCII).replaceAll(NEWLINE, " ")); | |
| 84 | LOG.info(sb.toString()); | |
| 85 | } | |
| 86 | } | |
Mutations | ||
| 44 |
1.1 |
|
| 48 |
1.1 |
|
| 59 |
1.1 |
|
| 65 |
1.1 |
|
| 66 |
1.1 |
|
| 74 |
1.1 2.2 |
|
| 78 |
1.1 2.2 |
|
| 79 |
1.1 2.2 |