XML 메시지 지원

This commit is contained in:
curry772
2026-06-02 08:30:51 +09:00
parent 7109c56623
commit 7d89d6d43e
@@ -12,8 +12,10 @@ import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthFilter;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.message.MessageType;
import com.eactive.eai.common.util.CommonLib;
import com.eactive.eai.common.util.JSONUtils;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.TxFileLogger;
import com.eactive.eai.common.util.XMLUtils;
import com.eactive.eai.inbound.action.ActionFactory;
import com.eactive.eai.inbound.action.RequestAction;
import com.eactive.eai.inbound.processor.Processor;
@@ -25,6 +27,13 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.mina.common.ByteBuffer;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.JSONParser;
@@ -50,6 +59,7 @@ import java.nio.charset.StandardCharsets;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.StringWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import org.springframework.security.oauth2.provider.ClientDetails;
@@ -150,6 +160,9 @@ public class DJErpApiAdapterService extends HttpAdapterServiceSupport {
transactionProp.put(AbstractCryptoFilter.PROP_MODULE_NAME, httpProp.getProperty(AbstractCryptoFilter.PROP_MODULE_NAME, ""));
transactionProp.put(HEADER_GROUP, headerGroupName);
transactionProp.put(HEADER_KEYS, relayRequestHeaderKeys);
// SEED 컬럼암호하 시 Key로 사용함
String seedkey = getHeaders(request).getOrDefault("x-obp-partnercode", "").toString();
ElinkTransactionContext.setSeedKey(seedkey);
@@ -230,47 +243,47 @@ public class DJErpApiAdapterService extends HttpAdapterServiceSupport {
logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n"
+ CommonLib.getDumpMessage(paramValue.getBytes(encode)));
}
} else {
if (request.getContentLength() > 0) {
ServletInputStream sis = request.getInputStream();
ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true);
int i = 0;
byte[] cbuf = new byte[1024];
while ((i = sis.read(cbuf, 0, 1024)) != -1) {
if (i == 1024) {
bb.put(cbuf);
} else {
byte[] tail = new byte[i];
System.arraycopy(cbuf, 0, tail, 0, i);
bb.put(tail);
} else {
if (request.getContentLength() > 0) {
ServletInputStream sis = request.getInputStream();
ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true);
int i = 0;
byte[] cbuf = new byte[1024];
while ((i = sis.read(cbuf, 0, 1024)) != -1) {
if (i == 1024) {
bb.put(cbuf);
} else {
byte[] tail = new byte[i];
System.arraycopy(cbuf, 0, tail, 0, i);
bb.put(tail);
}
}
byte[] data = new byte[bb.position()];
bb.position(0);
bb.get(data);
String bodyEncode = encode;
String contentTypeHeader = request.getContentType();
if (StringUtils.isNotBlank(contentTypeHeader)) {
try {
MediaType mediaType = MediaType.parseMediaType(contentTypeHeader);
if (mediaType.getCharset() != null) {
bodyEncode = mediaType.getCharset().name();
}
} catch (Exception ignored) {}
}
paramValue = new String(data, bodyEncode);
if (traceLevel >= 3) {
HttpMemoryLogger.txlog(adptGrpName + adptName,
"RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(data));
}
if (logger.isDebug()) {
logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n"
+ CommonLib.getDumpMessage(data));
}
}
}
byte[] data = new byte[bb.position()];
bb.position(0);
bb.get(data);
String bodyEncode = encode;
String contentTypeHeader = request.getContentType();
if (StringUtils.isNotBlank(contentTypeHeader)) {
try {
MediaType mediaType = MediaType.parseMediaType(contentTypeHeader);
if (mediaType.getCharset() != null) {
bodyEncode = mediaType.getCharset().name();
}
} catch (Exception ignored) {}
}
paramValue = new String(data, bodyEncode);
if (traceLevel >= 3) {
HttpMemoryLogger.txlog(adptGrpName + adptName,
"RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(data));
}
if (logger.isDebug()) {
logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n"
+ CommonLib.getDumpMessage(data));
}
}
}
if (paramValue == null) { // parameter가 없는 경우때문에 처리
paramValue = "";
@@ -304,47 +317,48 @@ public class DJErpApiAdapterService extends HttpAdapterServiceSupport {
// HttpHeaders responseHeaders = new HttpHeaders();
// responseHeaders.setContentType(MediaType.valueOf("application/json;charset=" + encode));
// HEADER_GROUP 셋팅
if (MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName)
&& StringUtils.isNotBlank(relayRequestHeaderKeys)) {
JSONObject jsonMessage = (JSONObject) JSONValue.parse(message);
JSONObject headerJson = new JSONObject();
if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) {
for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements(); ) {
String key = e.nextElement();
headerJson.put(key, request.getHeader(key));
}
} else {
String[] relayKeyArr = org.springframework.util.StringUtils
.tokenizeToStringArray(relayRequestHeaderKeys, ",");
for (String key : relayKeyArr) {
String headerValue = request.getHeader(key);
if (StringUtils.isNotBlank(headerValue)) {
headerJson.put(key, headerValue);
}
}
}
if (headerJson.size() > 0) {
jsonMessage.put(headerGroupName, headerJson);
message = jsonMessage.toJSONString();
}
}
if (message == null) {
message = "";
}
// if (MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName)
// && StringUtils.isNotBlank(relayRequestHeaderKeys)) {
// JSONObject jsonMessage = (JSONObject) JSONValue.parse(message);
// JSONObject headerJson = new JSONObject();
// if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) {
// for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements(); ) {
// String key = e.nextElement();
// headerJson.put(key, request.getHeader(key));
// }
// } else {
// String[] relayKeyArr = org.springframework.util.StringUtils
// .tokenizeToStringArray(relayRequestHeaderKeys, ",");
//
// for (String key : relayKeyArr) {
// String headerValue = request.getHeader(key);
// if (StringUtils.isNotBlank(headerValue)) {
// headerJson.put(key, headerValue);
// }
// }
// }
//
// if (headerJson.size() > 0) {
// jsonMessage.put(headerGroupName, headerJson);
// message = jsonMessage.toJSONString();
// }
// }
Object reqObject = assignHeaderGroupRequestHeaders(adptGrpName, adptName, message,
transactionProp, request, response, adptMsgType);
// 위치변경 : 가공되지 않은 Body값을 저장하기 위하여 위쪽으로 이동.
// transactionProp.put(INBOUND_REQUEST_MESSAGE, message);
// 로컬 서비스 호출 ,encoding 처리 추가
String result = (String) service(adptGrpName, adptName, message, transactionProp, request, response);
String result = (String) service(adptGrpName, adptName, reqObject, transactionProp, request, response);
// bypass만 필요
applyOutboundResponseHeaders(transactionProp, response);
if (logger.isDebug()) {
result = applyHeaderGroupResponseHeaders(adptGrpName, adptName, result, transactionProp, request, response, adptMsgType);
if (logger.isDebug()) {
logger.debug("HttpAdapterServiceRest] result " + encode + " (" + adptGrpName + ") = [" + result + "]");
}
@@ -376,6 +390,113 @@ public class DJErpApiAdapterService extends HttpAdapterServiceSupport {
return result;
}
private Object assignHeaderGroupRequestHeaders(String adptGrpName, String adptName, Object message, Properties prop,
HttpServletRequest request, HttpServletResponse response, String adptMsgType) throws DocumentException, IOException {
// XML 지원 개발
String headerGroupName = prop.getProperty(HEADER_GROUP);
String relayRequestHeaderKeys = prop.getProperty(HEADER_KEYS);
if(StringUtils.isNotBlank(headerGroupName) && StringUtils.isNotBlank(relayRequestHeaderKeys)) {
if (MessageType.JSON.equals(adptMsgType)) {
if(message instanceof String && StringUtils.isEmpty((String)message))
message = "{}";
JSONObject jsonMessage = JSONUtils.parseJson(message);
JSONObject headerJson = JSONUtils.getChildJson(jsonMessage, headerGroupName);
if (headerJson == null)
headerJson = new JSONObject();
if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) {
for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements(); ) {
String key = e.nextElement();
headerJson.put(StringUtils.lowerCase(key), request.getHeader(key));
}
} else {
String[] relayKeyArr = org.springframework.util.StringUtils
.tokenizeToStringArray(relayRequestHeaderKeys, ",");
for (String key : relayKeyArr) {
String headerValue = request.getHeader(key);
if (StringUtils.isNotBlank(headerValue)) {
headerJson.put(StringUtils.lowerCase(key), headerValue);
}
}
}
if (headerJson.size() > 0) {
jsonMessage.put(headerGroupName, headerJson);
message = jsonMessage.toJSONString();
}
} else if(MessageType.XML.equals(adptMsgType)) {
Document document = XMLUtils.convertXmlDocument(message);
if(document != null) {
Element rootElement = document.getRootElement();
Element headerElement = rootElement.element(headerGroupName);
if(headerElement == null)
headerElement = DocumentHelper.createElement(headerGroupName);
boolean hasHeaderValues = false;
if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) {
for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements(); ) {
String key = e.nextElement();
String value = request.getHeader(key);
/*
* IBK 표준안에 따라 <{key}>{value}</{key}> 형태로 저장, KEY 는 소문자로 변경한다
* 대상 사이트의 표준안에 따라 작성 할 것
*
* HTTP 헤더 변환 예시
*
* 일반적인 HTTP 헤더 변환 예시:
* Content-Type: application/json
* X-Forwarded-For: 10.0.0.1
*
* <root>
* <data> original content </data>
* <httpHeaderGroup>
* <content-type>application/json</content-type>
* <x-forwarded-for>10.0.0.1</x-forwarded-for>
* </httpHeaderGroup>
* </root>
*/
if(StringUtils.isNotBlank(value)) {
Element headerItem = headerElement.addElement(key);
headerItem.setText(value);
hasHeaderValues = true;
}
}
} else {
String[] relayKeyArr = org.springframework.util.StringUtils
.tokenizeToStringArray(relayRequestHeaderKeys, ",");
for (String key : relayKeyArr) {
String headerValue = request.getHeader(key);
if (StringUtils.isNotBlank(headerValue)) {
String value = request.getHeader(key);
String keyName = StringUtils.lowerCase(key);
Element headerItem = headerElement.addElement(keyName);
headerItem.setText(value);
hasHeaderValues = true;
}
}
}
if (hasHeaderValues) {
rootElement.add(headerElement);
OutputFormat format = OutputFormat.createPrettyPrint();
StringWriter writer = new StringWriter();
XMLWriter xmlWriter = new XMLWriter(writer, format);
xmlWriter.write(document);
message = writer.toString();
}
}
}
}
if (message == null) {
message = "";
} // XML 지원 개발
return message;
}
/**
@@ -420,8 +541,95 @@ public class DJErpApiAdapterService extends HttpAdapterServiceSupport {
}
}
// jwhong decrypt
private String applyHeaderGroupResponseHeaders(String adptGrpName, String adptName, Object resultMessage, Properties prop,
HttpServletRequest request, HttpServletResponse response, String adptMsgType) throws Exception {
// body headergroup -> http header 세팅
String headerGroupName = prop.getProperty(ApiAdapterService.HEADER_GROUP);
if (StringUtils.isNotBlank(headerGroupName)) {
if (resultMessage instanceof Node) {
adptMsgType = MessageType.XML;
} else if (resultMessage instanceof String) {
String strMessage = (String) resultMessage;
if (StringUtils.startsWith(strMessage, "<")) {
adptMsgType = MessageType.XML;
}
} else if (resultMessage instanceof byte[]) {
String strMessage = new String((byte[]) resultMessage);
if (StringUtils.startsWith(strMessage, "<")) {
adptMsgType = MessageType.XML;
}
}
if (MessageType.JSON.equals(adptMsgType)) {
JSONObject jsonObject = JSONUtils.parseJson(resultMessage);
JSONObject headerGroup = (JSONObject)jsonObject.get(headerGroupName);
if (headerGroup != null) {
Set<Map.Entry<String, Object>> fieldEntrySet = JSONUtils.getField(headerGroup);
for (Map.Entry<String, Object> fieldEntry : fieldEntrySet) {
logger.info("header group entry : {} , {}", fieldEntry.getKey(), fieldEntry.getValue());
if (fieldEntry.getValue() instanceof String) {
if(fieldEntry.getKey().equalsIgnoreCase("content-type")) {
logger.debug("set content-type {}: {}", fieldEntry.getKey(), fieldEntry.getValue());
response.setContentType((String) fieldEntry.getValue());
} else {
logger.debug("add header {}: {}", fieldEntry.getKey(), fieldEntry.getValue());
response.addHeader(fieldEntry.getKey(), (String) fieldEntry.getValue());
}
} else {
logger.info("fieldEntry value is not String. {}", fieldEntry.getValue());
}
}
} else {
logger.info("headerGroup is null");
}
jsonObject.remove(headerGroupName);
return jsonObject.toJSONString();
} else if(MessageType.XML.equals(adptMsgType)) {
Document document = XMLUtils.convertXmlDocument(resultMessage);
if(document != null) {
Element rootElement = document.getRootElement();
Element headerGroupElement = rootElement.element(headerGroupName);
if(headerGroupElement != null) {
//헤더그룹의 모든 하위 엘리먼트를 HTTP 응답 헤더로 설정
for(Iterator<Element> it = headerGroupElement.elementIterator(); it.hasNext();) {
Element headerElement = it.next();
String name = headerElement.getName();
String value = headerElement.getTextTrim();
if(StringUtils.isNoneBlank(value)) {
if(value.equalsIgnoreCase("content-type")) {
response.setContentType(value);
} else {
logger.debug("add header {}: {}", name, value);
response.addHeader(name, value);
}
} else {
logger.info("value is not String. {}", value);
}
}
} else {
logger.info("headerGroup is null");
}
// 헤더그룹 삭제
rootElement.remove(headerGroupElement);
return document.asXML();
}
}
} else {
logger.info("headerGroupName is blank");
}
return (String)resultMessage;
}
// jwhong decrypt
private String doPreDecryption(String eaiBody, Properties transactionProp, HttpServletRequest request) throws Exception {
String decryptAlgorithm = transactionProp.getProperty(ENCRYPT_ALGORITHM, "");
String xElinkClientId = transactionProp.getProperty(HEADER_NAME_CLIENT_ID, ""); // 이 값이 OAuth의 client id 값이다 . http header 에 포함되어 온다. jwhong