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

This commit is contained in:
forge-bot 2026-07-18 11:09:17 +00:00
parent 2757f6a51b
commit f2cc439327

View file

@ -0,0 +1,145 @@
package com.klaro.acquirecore.framework.util;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* Static utility class for message/frame processing migrated from legacy C code.
* Provides encoding, decoding, and checksum operations for message frames.
*/
public final class MessageUtil {
private static final int HEADER_SIZE = 4;
private static final int MAX_MESSAGE_SIZE = 4096;
private static final String DELIMITER = "|";
private MessageUtil() {
// Utility class - prevent instantiation
}
public static String encode(String type, byte[] payload) {
if (type == null || type.isBlank()) {
return null;
}
int length = (payload != null) ? payload.length : 0;
String header = String.format("%s%s%d%s", padRight(type, HEADER_SIZE), DELIMITER, length, DELIMITER);
if (payload == null || payload.length == 0) {
return header;
}
return header + new String(payload, StandardCharsets.UTF_8);
}
public static String encode(String type, String payload) {
if (payload == null) {
return encode(type, (byte[]) null);
}
return encode(type, payload.getBytes(StandardCharsets.UTF_8));
}
public static MessageFrame decode(String message) {
if (message == null || message.isBlank()) {
return null;
}
int firstDelim = message.indexOf(DELIMITER);
if (firstDelim < 0 || firstDelim > HEADER_SIZE) {
return null;
}
String type = message.substring(0, firstDelim).trim();
int secondDelim = message.indexOf(DELIMITER, firstDelim + 1);
if (secondDelim < 0) {
return null;
}
String lengthStr = message.substring(firstDelim + 1, secondDelim).trim();
int length;
try {
length = Integer.parseInt(lengthStr);
} catch (NumberFormatException e) {
return null;
}
String payloadStr = message.substring(secondDelim + 1);
byte[] payload = payloadStr.getBytes(StandardCharsets.UTF_8);
return new MessageFrame(type, length, payload);
}
public static int checksum(byte[] payload) {
if (payload == null || payload.length == 0) {
return 0;
}
int sum = 0;
for (byte b : payload) {
sum += (b & 0xFF);
}
return sum & 0xFFFF;
}
public static int checksum(String payload) {
if (payload == null || payload.isEmpty()) {
return 0;
}
return checksum(payload.getBytes(StandardCharsets.UTF_8));
}
public static String encodeBase64(byte[] data) {
if (data == null) {
return null;
}
return Base64.getEncoder().encodeToString(data);
}
public static byte[] decodeBase64(String encoded) {
if (encoded == null || encoded.isBlank()) {
return null;
}
try {
return Base64.getDecoder().decode(encoded);
} catch (IllegalArgumentException e) {
return null;
}
}
public static boolean isValidSize(String message) {
return message != null && message.length() <= MAX_MESSAGE_SIZE;
}
private static String padRight(String str, int length) {
if (str == null) {
str = "";
}
if (str.length() >= length) {
return str.substring(0, length);
}
StringBuilder sb = new StringBuilder(str);
while (sb.length() < length) {
sb.append(' ');
}
return sb.toString();
}
public static final class MessageFrame {
private final String type;
private final int length;
private final byte[] payload;
public MessageFrame(String type, int length, byte[] payload) {
this.type = type;
this.length = length;
this.payload = payload;
}
public String getType() { return type; }
public int getLength() { return length; }
public byte[] getPayload() { return payload; }
public String getPayloadAsString() {
if (payload == null) {
return "";
}
return new String(payload, StandardCharsets.UTF_8);
}
@Override
public String toString() {
return String.format("MessageFrame{type='%s', length=%d, payload=%s}", type, length, getPayloadAsString());
}
}
}