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 |