* General-purpose static utilities: hashing, dates/times, collections, I/O helpers,
* simple email validation, reflection helpers, file tailing, etc.
*
* Author: JRA
* Last reviewed by JRA on Oct 6, 2025.
*/
public class Utils {
private static final Logger LOG = LogManager.getLogger(Utils.class);
/* --------------------- Hash functions --------------------- */
/**
* md5
* Returns MD5 digest (hex, 32 chars) for the input text.
*
* @param str source text
* @return lowercase hex MD5 or null on error
*/
public static String md5(String str) {
try {
MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(str.getBytes(), 0, str.length());
BigInteger i = new BigInteger(1, mDigest.digest());
return String.format("%1$032x", i);
} catch (NoSuchAlgorithmException e) {
LOG.error("Error generating MD5 for string: " + str, e);
}
return null;
}
/**
* sha1
* Returns SHA-1 digest (hex, 40 chars) for the input text.
*
* @param str source text
* @return lowercase hex SHA-1 or null on error
*/
public static String sha1(String str) {
try {
MessageDigest mDigest = MessageDigest.getInstance("SHA1");
mDigest.update(str.getBytes(), 0, str.length());
BigInteger i = new BigInteger(1, mDigest.digest());
return String.format("%1$040x", i);
} catch (NoSuchAlgorithmException e) {
LOG.error("Error generating SHA1 for string: " + str, e);
}
return null;
}
/**
* sha256
* Returns SHA-256 digest (hex, 64 chars) for the input text.
*
* @param str source text
* @return lowercase hex SHA-256 or null on error
*/
public static String sha256(String str) {
return sha256(str.getBytes());
}
/**
* sha256
* Returns SHA-256 digest (hex) for a byte array.
*
* @param bytes data
* @return hex SHA-256 or null on error
*/
public static String sha256(byte[] bytes) {
try {
MessageDigest mDigest = MessageDigest.getInstance("SHA-256");
mDigest.update(bytes, 0, bytes.length);
BigInteger i = new BigInteger(1, mDigest.digest());
return String.format("%1$064x", i);
} catch (NoSuchAlgorithmException e) {
LOG.error("Error generating SHA-256 for bytes: " + bytes, e);
}
return null;
}
/**
* sha256
* Incrementally updates SHA-256 with multiple byte arrays and returns hex digest.
*
* @param bytes multiple byte chunks
* @return hex SHA-256 or null on error
*/
public static String sha256(byte[]... bytes) {
try {
MessageDigest mDigest = MessageDigest.getInstance("SHA-256");
for (byte[] bs : bytes) {
mDigest.update(bs, 0, bs.length);
}
BigInteger i = new BigInteger(1, mDigest.digest());
return String.format("%1$064x", i);
} catch (NoSuchAlgorithmException e) {
LOG.error("Error generating SHA-256 for bytes: " + bytes, e);
}
return null;
}
/* --------------------- ISO date helpers --------------------- */
private static final String ISO_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
private static final SimpleDateFormat sdf = new SimpleDateFormat(ISO_PATTERN);
static {
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
}
/**
* toIsoFormat
* Formats a Date to ISO-8601-like string with milliseconds in GMT.
*
* @param date input date
* @return formatted string
*/
public static synchronized String toIsoFormat(Date date) {
return sdf.format(date);
}
private static final String ISO_PATTERN_REDUCED_PRECISION = "yyyy-MM-dd'T'HH:mm:ssZ";
private static final SimpleDateFormat sdfReduced = new SimpleDateFormat(ISO_PATTERN_REDUCED_PRECISION);
static {
sdfReduced.setTimeZone(TimeZone.getTimeZone("GMT"));
}
/**
* toIsoFormatReduced
* Formats a Date to ISO string without milliseconds in GMT.
*
* @param date input date
* @return formatted string
*/
public static synchronized String toIsoFormatReduced(Date date) {
return sdfReduced.format(date);
}
/**
* toDateFromIso
* Parses a string in {@link #ISO_PATTERN} into a Date (GMT).
*
* @param dateStr string to parse
* @return Date or null if parsing fails
*/
public static synchronized Date toDateFromIso(String dateStr) {
try {
return sdf.parse(dateStr);
} catch (ParseException e) {
LOG.error("Error parsing string '{}' to Date object with pattern: {}", dateStr, ISO_PATTERN);
return null;
}
}
/* --------------------- Null-safe helpers --------------------- */
/**
* nonull
* Returns {@code value} cast to T, or {@code defaultValue} if null.
*
* @param value input
* @param defaultValue fallback
* @return value or default
*/
@SuppressWarnings("unchecked")
public static T nonull(Object value, T defaultValue) {
return value == null ? defaultValue : (T) value;
}
/**
* nonull
* Returns String value or empty string if null.
*
* @param value input
* @return non-null string
*/
public static String nonull(Object value) {
return nonull(value, "");
}
/**
* value
* Unchecked cast helper (avoid using unless necessary).
*
* @param value object
* @param type target type
* @return casted value
*/
@SuppressWarnings("unchecked")
public static T value(Object value, Class type) {
return (T) value;
}
/**
* createMap
* Convenience to create a Map from varargs key/value pairs.
*
* @param keyValue alternating key, value
* @return map with pairs
*/
@SuppressWarnings("unchecked")
public static Map createMap(Object... keyValue) {
Map map = (Map) new HashMap