[공통] util → framework 유틸 (ACM-CM-002)

This commit is contained in:
forge-bot 2026-07-18 11:03:13 +00:00
parent 45406e9974
commit 92c06b9c9b

View file

@ -0,0 +1,507 @@
package com.klaro.acquirecore.framework.util;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;
import java.util.regex.Pattern;
/**
* Static utility class for message encoding/decoding migrated from legacy/util_msg.c
* Uses java.util.Base64 and java.nio.charset for codec operations.
*/
public final class MessageUtil {
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
public static final Charset EUC_KR_CHARSET = Charset.forName("EUC-KR");
public static final Charset ISO_8859_1_CHARSET = StandardCharsets.ISO_8859_1;
private static final Pattern EMAIL_PATTERN = Pattern.compile(
"^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"
);
private static final Pattern PHONE_PATTERN = Pattern.compile(
"^\\d{2,4}-\\d{3,4}-\\d{4}$|^\\d{10,11}$"
);
private static final Pattern KOREAN_PHONE_PATTERN = Pattern.compile(
"^01[016789]-\\d{3,4}-\\d{4}$"
);
private MessageUtil() {
throw new UnsupportedOperationException("Utility class cannot be instantiated");
}
// ==================== Base64 Encoding/Decoding ====================
/**
* Encodes a string to Base64.
*
* @param input the string to encode
* @return the Base64 encoded string
*/
public static String encodeBase64(String input) {
Objects.requireNonNull(input, "input must not be null");
return Base64.getEncoder().encodeToString(input.getBytes(DEFAULT_CHARSET));
}
/**
* Encodes a string to Base64 with specified charset.
*
* @param input the string to encode
* @param charset the charset to use
* @return the Base64 encoded string
*/
public static String encodeBase64(String input, Charset charset) {
Objects.requireNonNull(input, "input must not be null");
Objects.requireNonNull(charset, "charset must not be null");
return Base64.getEncoder().encodeToString(input.getBytes(charset));
}
/**
* Encodes bytes to Base64.
*
* @param bytes the bytes to encode
* @return the Base64 encoded string
*/
public static String encodeBase64(byte[] bytes) {
Objects.requireNonNull(bytes, "bytes must not be null");
return Base64.getEncoder().encodeToString(bytes);
}
/**
* Decodes a Base64 string to plain string.
*
* @param encoded the Base64 encoded string
* @return the decoded string
*/
public static String decodeBase64(String encoded) {
Objects.requireNonNull(encoded, "encoded must not be null");
byte[] decoded = Base64.getDecoder().decode(encoded);
return new String(decoded, DEFAULT_CHARSET);
}
/**
* Decodes a Base64 string to plain string with specified charset.
*
* @param encoded the Base64 encoded string
* @param charset the charset to use for decoding
* @return the decoded string
*/
public static String decodeBase64(String encoded, Charset charset) {
Objects.requireNonNull(encoded, "encoded must not be null");
Objects.requireNonNull(charset, "charset must not be null");
byte[] decoded = Base64.getDecoder().decode(encoded);
return new String(decoded, charset);
}
/**
* Decodes a Base64 string to bytes.
*
* @param encoded the Base64 encoded string
* @return the decoded bytes
*/
public static byte[] decodeBase64ToBytes(String encoded) {
Objects.requireNonNull(encoded, "encoded must not be null");
return Base64.getDecoder().decode(encoded);
}
/**
* Encodes a URL-safe Base64 string.
*
* @param input the string to encode
* @return the URL-safe Base64 encoded string
*/
public static String encodeBase64Url(String input) {
Objects.requireNonNull(input, "input must not be null");
return Base64.getUrlEncoder().encodeToString(input.getBytes(DEFAULT_CHARSET));
}
/**
* Decodes a URL-safe Base64 string.
*
* @param encoded the URL-safe Base64 encoded string
* @return the decoded string
*/
public static String decodeBase64Url(String encoded) {
Objects.requireNonNull(encoded, "encoded must not be null");
byte[] decoded = Base64.getUrlDecoder().decode(encoded);
return new String(decoded, DEFAULT_CHARSET);
}
// ==================== Hex Encoding/Decoding ====================
/**
* Encodes bytes to hexadecimal string.
*
* @param bytes the bytes to encode
* @return the hexadecimal string
*/
public static String encodeHex(byte[] bytes) {
Objects.requireNonNull(bytes, "bytes must not be null");
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
/**
* Decodes a hexadecimal string to bytes.
*
* @param hex the hexadecimal string
* @return the decoded bytes
*/
public static byte[] decodeHex(String hex) {
Objects.requireNonNull(hex, "hex must not be null");
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("Hex string must have even length");
}
int len = hex.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}
return data;
}
// ==================== URL Encoding/Decoding ====================
/**
* URL encodes a string using UTF-8.
*
* @param input the string to encode
* @return the URL encoded string
*/
public static String urlEncode(String input) {
Objects.requireNonNull(input, "input must not be null");
try {
return java.net.URLEncoder.encode(input, DEFAULT_CHARSET.name());
} catch (java.io.UnsupportedEncodingException e) {
throw new RuntimeException("Unsupported encoding", e);
}
}
/**
* URL decodes a string using UTF-8.
*
* @param encoded the URL encoded string
* @return the decoded string
*/
public static String urlDecode(String encoded) {
Objects.requireNonNull(encoded, "encoded must not be null");
try {
return java.net.URLDecoder.decode(encoded, DEFAULT_CHARSET.name());
} catch (java.io.UnsupportedEncodingException e) {
throw new RuntimeException("Unsupported encoding", e);
}
}
// ==================== String Manipulation ====================
/**
* Masks a string with asterisks, showing only the first and last characters.
*
* @param input the string to mask
* @return the masked string
*/
public static String mask(String input) {
return mask(input, 1, 1);
}
/**
* Masks a string with asterisks, showing only specified first and last characters.
*
* @param input the string to mask
* @param showFirst number of characters to show at the start
* @param showLast number of characters to show at the end
* @return the masked string
*/
public static String mask(String input, int showFirst, int showLast) {
if (input == null || input.isEmpty()) {
return input;
}
int length = input.length();
if (length <= showFirst + showLast) {
return input;
}
StringBuilder sb = new StringBuilder();
sb.append(input, 0, showFirst);
for (int i = showFirst; i < length - showLast; i++) {
sb.append('*');
}
sb.append(input.substring(length - showLast));
return sb.toString();
}
/**
* Masks an email address.
*
* @param email the email to mask
* @return the masked email
*/
public static String maskEmail(String email) {
if (email == null || !email.contains("@")) {
return email;
}
String[] parts = email.split("@");
String localPart = parts[0];
String domain = parts[1];
if (localPart.length() <= 2) {
return mask(localPart, 1, 0) + "@" + domain;
}
return mask(localPart, 1, 1) + "@" + domain;
}
/**
* Masks a phone number.
*
* @param phone the phone number to mask
* @return the masked phone number
*/
public static String maskPhone(String phone) {
if (phone == null || phone.isEmpty()) {
return phone;
}
String digitsOnly = phone.replaceAll("[^0-9]", "");
if (digitsOnly.length() < 7) {
return phone;
}
int length = digitsOnly.length();
String masked = digitsOnly.substring(0, 3) + "****" + digitsOnly.substring(length - 4);
if (phone.contains("-")) {
return masked.substring(0, 3) + "-" + "****" + "-" + masked.substring(7);
}
return masked;
}
// ==================== Validation ====================
/**
* Validates if a string is a valid email address.
*
* @param email the email to validate
* @return true if valid, false otherwise
*/
public static boolean isValidEmail(String email) {
if (email == null || email.isEmpty()) {
return false;
}
return EMAIL_PATTERN.matcher(email).matches();
}
/**
* Validates if a string is a valid phone number.
*
* @param phone the phone number to validate
* @return true if valid, false otherwise
*/
public static boolean isValidPhone(String phone) {
if (phone == null || phone.isEmpty()) {
return false;
}
return PHONE_PATTERN.matcher(phone).matches();
}
/**
* Validates if a string is a valid Korean phone number.
*
* @param phone the phone number to validate
* @return true if valid, false otherwise
*/
public static boolean isValidKoreanPhone(String phone) {
if (phone == null || phone.isEmpty()) {
return false;
}
return KOREAN_PHONE_PATTERN.matcher(phone).matches();
}
/**
* Checks if a string is null or empty.
*
* @param input the string to check
* @return true if null or empty
*/
public static boolean isEmpty(String input) {
return input == null || input.isEmpty();
}
/**
* Checks if a string is null, empty, or whitespace only.
*
* @param input the string to check
* @return true if null, empty, or whitespace only
*/
public static boolean isBlank(String input) {
return input == null || input.trim().isEmpty();
}
// ==================== Charset Conversion ====================
/**
* Converts a string from one charset to another.
*
* @param input the input string
* @param fromCharset the source charset
* @param toCharset the target charset
* @return the converted string
*/
public static String convertCharset(String input, Charset fromCharset, Charset toCharset) {
Objects.requireNonNull(input, "input must not be null");
Objects.requireNonNull(fromCharset, "fromCharset must not be null");
Objects.requireNonNull(toCharset, "toCharset must not be null");
byte[] bytes = input.getBytes(fromCharset);
return new String(bytes, toCharset);
}
/**
* Converts EUC-KR encoded bytes to UTF-8 string.
*
* @param eucKrBytes the EUC-KR encoded bytes
* @return the UTF-8 string
*/
public static String eucKrToUtf8(byte[] eucKrBytes) {
Objects.requireNonNull(eucKrBytes, "eucKrBytes must not be null");
return new String(eucKrBytes, EUC_KR_CHARSET);
}
/**
* Converts UTF-8 string to EUC-KR encoded bytes.
*
* @param input the UTF-8 string
* @return the EUC-KR encoded bytes
*/
public static byte[] utf8ToEucKr(String input) {
Objects.requireNonNull(input, "input must not be null");
return input.getBytes(EUC_KR_CHARSET);
}
// ==================== Truncation and Padding ====================
/**
* Truncates a string to the specified length.
*
* @param input the string to truncate
* @param maxLength the maximum length
* @return the truncated string
*/
public static String truncate(String input, int maxLength) {
if (input == null) {
return null;
}
if (input.length() <= maxLength) {
return input;
}
return input.substring(0, maxLength);
}
/**
* Pads a string on the left with spaces to reach the specified length.
*
* @param input the string to pad
* @param length the target length
* @return the padded string
*/
public static String padLeft(String input, int length) {
if (input == null) {
input = "";
}
return String.format("%" + length + "s", input);
}
/**
* Pads a string on the right with spaces to reach the specified length.
*
* @param input the string to pad
* @param length the target length
* @return the padded string
*/
public static String padRight(String input, int length) {
if (input == null) {
input = "";
}
return String.format("%- " + length + "s", input);
}
/**
* Pads a string on the left with zeros to reach the specified length.
*
* @param input the string to pad
* @param length the target length
* @return the zero-padded string
*/
public static String padLeftWithZeros(String input, int length) {
if (input == null) {
input = "";
}
return String.format("%0" + length + "d", Long.parseLong(input));
}
/**
* Left pads a numeric string with zeros.
*
* @param value the numeric value
* @param length the target length
* @return the zero-padded string
*/
public static String zeroPad(long value, int length) {
return String.format("%0" + length + "d", value);
}
// ==================== Byte Array Utilities ====================
/**
* Converts a string to bytes using the default charset.
*
* @param input the string to convert
* @return the bytes
*/
public static byte[] toBytes(String input) {
if (input == null) {
return null;
}
return input.getBytes(DEFAULT_CHARSET);
}
/**
* Converts a string to bytes using the specified charset.
*
* @param input the string to convert
* @param charset the charset to use
* @return the bytes
*/
public static byte[] toBytes(String input, Charset charset) {
if (input == null) {
return null;
}
Objects.requireNonNull(charset, "charset must not be null");
return input.getBytes(charset);
}
/**
* Converts bytes to string using the default charset.
*
* @param bytes the bytes to convert
* @return the string
*/
public static String toString(byte[] bytes) {
if (bytes == null) {
return null;
}
return new String(bytes, DEFAULT_CHARSET);
}
/**
* Converts bytes to string using the specified charset.
*
* @param bytes the bytes to convert
* @param charset the charset to use
* @return the string
*/
public static String toString(byte[] bytes, Charset charset) {
if (bytes == null) {
return null;
}
Objects.requireNonNull(charset, "charset must not be null");
return new String(bytes, charset);
}
}