diff --git a/src/main/java/com/eactive/eai/adapter/service/DJErpApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/DJErpApiAdapterService.java index af470e9..4e1353d 100644 --- a/src/main/java/com/eactive/eai/adapter/service/DJErpApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/DJErpApiAdapterService.java @@ -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 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 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 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 e = request.getHeaderNames(); e.hasMoreElements(); ) { + String key = e.nextElement(); + String value = request.getHeader(key); + /* + * IBK 표준안에 따라 <{key}>{value} 형태로 저장, KEY 는 소문자로 변경한다 + * 대상 사이트의 표준안에 따라 작성 할 것 + * + * HTTP 헤더 변환 예시 + * + * 일반적인 HTTP 헤더 변환 예시: + * Content-Type: application/json + * X-Forwarded-For: 10.0.0.1 + * + * + * original content + * + * application/json + * 10.0.0.1 + * + * + */ + 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> fieldEntrySet = JSONUtils.getField(headerGroup); + + for (Map.Entry 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 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