Merge branch 'jenkins_with_weblogic' into master

This commit is contained in:
curry772
2026-03-11 10:34:28 +09:00
134 changed files with 4591 additions and 874 deletions
+2
View File
@@ -65,6 +65,8 @@ dependencies {
api 'io.github.resilience4j:resilience4j-micrometer:1.7.1'
api 'io.micrometer:micrometer-core:1.5.17'
api 'io.micrometer:micrometer-registry-prometheus:1.5.17'
implementation "com.google.code.gson:gson:2.3.1"
//api "com.eactive:mina-core-1.0.10-custom:1.0:custom@jar"
api ("org.apache.mina:mina-filter-ssl:1.0.10") {
+3 -1
View File
@@ -3,7 +3,9 @@ rootProject.name = 'elink-online-common'
include 'elink-online-core-jpa'
include 'elink-online-core'
include 'elink-online-transformer'
include 'elink-online-alarm'
project (':elink-online-core-jpa').projectDir = new File(settingsDir, "../elink-online-core-jpa")
project (':elink-online-core').projectDir = new File(settingsDir, "../elink-online-core")
project (':elink-online-transformer').projectDir = new File(settingsDir, "../elink-online-transformer")
project (':elink-online-transformer').projectDir = new File(settingsDir, "../elink-online-transformer")
project (':elink-online-alarm').projectDir = new File(settingsDir, "../elink-online-alarm")
@@ -14,8 +14,8 @@ public class AdapterUtils {
map.put("Unid", "ID00000001");
String prefix = "%", surfix = "%";
System.out.println(updateSql);
System.out.println(getUpdateQuery(updateSql, map, prefix, surfix));
// System.out.println(updateSql);
// System.out.println(getUpdateQuery(updateSql, map, prefix, surfix));
}
public static Properties getAdapterProerties(String propGroupName) {
@@ -56,7 +56,7 @@ public class DBInboudSqlAdapter {
if(isLocal != null && "true".equalsIgnoreCase(isLocal)) {
isLocalTest = true;
}
System.out.println("$$$ DBInboudSqlAdapter] isLocalTest = " + isLocalTest);
// System.out.println("$$$ DBInboudSqlAdapter] isLocalTest = " + isLocalTest);
}
public boolean execute() {
@@ -5,6 +5,7 @@ public enum HttpMethodType {
PUT,
DELETE,
GET,
PATCH,
UNKNOWN;
public static HttpMethodType getValue(String value) {
try {
@@ -40,6 +40,7 @@ import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.Keys;
import com.eactive.eai.adapter.http.secure.HttpClient5SSLContextFactory;
import com.eactive.eai.common.TransactionContextKeys;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.HttpAdapterExtraLogUtil;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
@@ -78,7 +79,7 @@ public abstract class HttpClient5AdapterServiceSupport implements HttpClientAdap
String trustStorePassword = null;
int connectionTimeout = 0;
int timeout = -1;
int timeout = 10000; // 기존값 -1 인데, 의미가 없음, -1로 설정될경우 client에서 에러남.
int traceLevel = 0;
long slowTranTime = 2000L;
@@ -88,6 +89,13 @@ public abstract class HttpClient5AdapterServiceSupport implements HttpClientAdap
if (!StringUtils.isEmpty(url2grp)) {
url = url2grp;
}
boolean isDrMode = Boolean.valueOf(PropManager.getInstance().getProperty(DR_PROP_GROUP, DR_PROP_KEY, "false"));
if (isDrMode) {
url = prop.getProperty(DR_URL);
}
method = prop.getProperty(METHOD);
parameterName = prop.getProperty(PARAMETER_NAME, PARAMETER_MESSAGE);
contentType = prop.getProperty(CONTENT_TYPE, "");
@@ -99,7 +107,7 @@ public abstract class HttpClient5AdapterServiceSupport implements HttpClientAdap
adapterHeader = prop.getProperty(ADAPTER_HEADER, "");
String traceLevelTemp = prop.getProperty(TRACE_LEVEL, "0");
String timeoutTemp = prop.getProperty(HTTP_TIME_OUT, "0");
String timeoutTemp = "10000"; // 타임아웃 기준이 불명확해 운영 혼란 발생 → 인터페이스 TIMEOUT으로 단일화
useMtls = StringUtils.equalsIgnoreCase(prop.getProperty(HttpClientAdapterServiceKey.USE_MTLS),"Y");
keyStorePath = prop.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PATH);
@@ -418,6 +426,8 @@ public abstract class HttpClient5AdapterServiceSupport implements HttpClientAdap
};
this.client = HttpClients.custom()
.disableDefaultUserAgent()
.disableContentCompression()
.addRequestInterceptorLast(requestLogInterceptor)
.addResponseInterceptorFirst(responseLogInterceptor)
.setConnectionManager(connectionManager)
@@ -507,12 +517,6 @@ public abstract class HttpClient5AdapterServiceSupport implements HttpClientAdap
requestConfigBuilder.setResponseTimeout(vo.getTimeout(), TimeUnit.MILLISECONDS);
}
/*
if (HTTP_VERSION_1_1.equals(vo.getHttpVersion())) {
method.addHeader("Connection", "close");
}
*/
org.apache.hc.core5.http.HttpVersion httpVersion ;
if (HTTP_VERSION_1_0.equals(vo.getHttpVersion())) {
httpVersion = org.apache.hc.core5.http.HttpVersion.HTTP_1_0;
@@ -8,6 +8,9 @@ public interface HttpClientAdapterServiceKey {
public static final String HTTP_TYPE = "HTTP_TYPE";
public static final String URL = "URL";
public static final String DR_PROP_GROUP = "DR";
public static final String DR_PROP_KEY = "dr.enable";
public static final String DR_URL = "URL_DR";
public static final String URL_2GRP = "URL_2GRP";
public static final String METHOD = "METHOD";
@@ -66,6 +69,7 @@ public interface HttpClientAdapterServiceKey {
public static final String INBOUND_METHOD = "INBOUND_METHOD";
public static final String INBOUND_URI = "INBOUND_URI";
public static final String INBOUND_EXTURI = "INBOUND_EXTURI";
public static final String INBOUND_EXTPARAMS = "INBOUND_EXTPARAMS";
public static final String INBOUND_HEADER = "INBOUND_HEADER";
public static final String HTTP_VERSION = "HTTP_VERSION";
@@ -27,6 +27,7 @@ import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
import com.eactive.eai.adapter.http.secure.CustomSSLProtocolSocketFactory;
import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
import com.eactive.eai.adapter.http.secure.SSLContextFactory;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoManager;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
@@ -83,7 +84,7 @@ public abstract class HttpClientAdapterServiceSupport implements HttpClientAdapt
adapterHeader = prop.getProperty(ADAPTER_HEADER, "");
String traceLevelTemp = prop.getProperty(TRACE_LEVEL, "0");
String timeoutTemp = prop.getProperty(HTTP_TIME_OUT);
String timeoutTemp = "10000";// 타임아웃 기준이 불명확해 운영 혼란 발생 → 인터페이스 TIMEOUT으로 단일화
useMtls = StringUtils.equalsIgnoreCase(prop.getProperty(HttpClientAdapterServiceKey.USE_MTLS), "Y");
keyStorePath = prop.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PATH);
@@ -100,6 +101,12 @@ public abstract class HttpClientAdapterServiceSupport implements HttpClientAdapt
if (StringUtils.isNotBlank(interfaceTimeout) && NumberUtils.toInt(interfaceTimeout) > 0) {
timeoutTemp = interfaceTimeout;
}
boolean isDrMode = Boolean.valueOf(PropManager.getInstance().getProperty(DR_PROP_GROUP, DR_PROP_KEY, "false"));
if (isDrMode) {
url = prop.getProperty(DR_URL);
}
url = StringUtils.trim(url);
parameterName = StringUtils.trim(parameterName);
@@ -116,6 +123,7 @@ public abstract class HttpClientAdapterServiceSupport implements HttpClientAdapt
try {
connectionTimeout = Integer.parseInt(connectionTimeoutTemp);
} catch (Exception e) {
connectionTimeout = 3000;
logger.debug("HttpClientAdapterSupport] connectionTimeoutTemp not int");
}
try {
@@ -5,6 +5,7 @@ import com.eactive.eai.adapter.http.client.HttpClient5AdapterServiceSupport;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
import com.eactive.eai.common.TransactionContextKeys;
import com.eactive.eai.common.message.MessageType;
import com.eactive.eai.common.util.CommonLib;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang3.StringUtils;
@@ -57,14 +58,16 @@ public class HttpClient5AdapterServiceBody extends HttpClient5AdapterServiceSupp
} else if (data instanceof byte[]) {
sendData = new String((byte[]) data, vo.getEncode());
}
ObjectMapper mapper = new ObjectMapper();
ObjectNode jsonNode = (ObjectNode) mapper.readTree(sendData);
ObjectNode headerPart = (ObjectNode) jsonNode.get("header_part");
if( headerPart.get("mciIntfId") != null && headerPart.get("mciIntfId").asText().trim().length() > 0 ) {
headerPart.put("eaiIntfId", "");
sendData = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
if(MessageType.JSON.equals(prop.getProperty("messageType"))) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode jsonNode = (ObjectNode) mapper.readTree(sendData);
ObjectNode headerPart = (ObjectNode) jsonNode.get("header_part");
if( headerPart.get("mciIntfId") != null && headerPart.get("mciIntfId").asText().trim().length() > 0 ) {
headerPart.put("eaiIntfId", "");
sendData = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
}
}
if ("Y".equals(vo.getUrlEncodeYn())) {
@@ -0,0 +1,21 @@
package com.eactive.eai.adapter.http.client.impl;
import com.eactive.eai.adapter.http.client.HttpClientAdapterService;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
import java.util.Properties;
public class HttpClientAdapterServiceNoop implements HttpClientAdapterService {
public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
return null;
}
@Override
public void close() {
}
@Override
public void init(String adapterName, boolean useMtls, HttpOutTlsInfoVO mtlsInfo, int maxTotalConnections, int maxHostConnections) {
}
}
@@ -1,7 +1,7 @@
package com.eactive.eai.adapter.http.dynamic;
public interface HttpAdapterServiceKey {
// URL 파리미터 DEFAULT 이름
// URL 파리미터 DEFAULT 이름
static final String PARAMETER_MESSAGE = "_message_";
// URL 파리미터 이름
@@ -43,6 +43,7 @@ public interface HttpAdapterServiceKey {
static final String INBOUND_METHOD = "INBOUND_METHOD";
static final String INBOUND_URI = "INBOUND_URI";
static final String INBOUND_EXTURI = "INBOUND_EXTURI";
static final String INBOUND_EXTPARAMS = "INBOUND_EXTPARAMS";
static final String INBOUND_HEADER = "INBOUND_HEADER";
static final String INBOUND_QUERY_STRING = "INBOUND_QUERY_STRING";
static final String INBOUND_REWRITE_PATH = "INBOUND_REWRITE_PATH";
@@ -73,10 +74,14 @@ public interface HttpAdapterServiceKey {
static final String ENC_PATHS = "ENC_PATHS";
static final String ENCRYPT_ALGORITHM = "ENCRYPT_ALGORITHM"; //jwhong
static final String INBOUND_TOKEN = "authorization"; // jwhong
static final String INBOUND_TOKEN = "AUTHORIZATION"; // jwhong
static final String ENCRYPT_BASE_TYPE = "ENCRYPT_BASE_TYPE"; // jwhong
static final String ENCRYPT_AES256_IV = "ENCRYPT_AES256_IV"; // jwhong
static final String ENCRYPT_AES256_KEY = "ENCRYPT_AES256_KEY"; // jwhong
static final String INBOUND_REQUESTED_TIME = "INBOUND_REQUESTED_TIME"; // jwhong
static final String GUID = "GUID"; // jwhong
static final String API_SERVICE_CODE = "API_SERVICE_CODE"; // jwhong
static final String OUT_ADAPTER_GROUP_NAME = "OUT_ADAPTER_GROUP_NAME"; // jwhong
//응답 처리 용 표준 전문 오브젝트
static final String STANDARD_MESSAGE_OBJECT = "STANDARD_MESSAGE_OBJECT";
@@ -9,14 +9,11 @@ import org.apache.commons.lang3.StringUtils;
import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterPropManager;
import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.adapter.RequestDispatcher;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilter;
import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilterFactory;
import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilterFactoryKjb;
import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilterType;
import com.eactive.eai.data.entity.onl.adapter.AdapterProp;
public abstract class HttpAdapterServiceSupport implements HttpAdapterService, HttpAdapterServiceKey {
protected long slowTranTime = 2000L;
@@ -65,7 +62,7 @@ public abstract class HttpAdapterServiceSupport implements HttpAdapterService, H
if (!"HTC".equals(group.getType())) {
String allowIp = prop.getProperty(ALLOW_IP,"");
if (StringUtils.isNotBlank(allowIp)) {
HttpAdapterFilter adapterFilter = HttpAdapterFilterFactory.createFilter(HttpAdapterFilterType.ADAPTERALLOWIPLISTFILTER.toString());
HttpAdapterFilter adapterFilter = HttpAdapterFilterFactoryKjb.createFilter(HttpAdapterFilterType.ADAPTERALLOWIPLISTFILTER.toString());
if (adapterFilter != null) {
message = adapterFilter.doPreFilter(adptGrpName, adptName, message, prop, request, response);
}
@@ -83,7 +80,7 @@ public abstract class HttpAdapterServiceSupport implements HttpAdapterService, H
continue;
}
HttpAdapterFilter adapterFilter = HttpAdapterFilterFactory.createFilter(filterName.trim());
HttpAdapterFilter adapterFilter = HttpAdapterFilterFactoryKjb.createFilter(filterName.trim());
if (adapterFilter != null) {
message = adapterFilter.doPreFilter(adptGrpName, adptName, message, prop, request, response);
} else {
@@ -106,7 +103,7 @@ public abstract class HttpAdapterServiceSupport implements HttpAdapterService, H
continue;
}
HttpAdapterFilter adapterFilter = HttpAdapterFilterFactory.createFilter(filterName.trim());
HttpAdapterFilter adapterFilter = HttpAdapterFilterFactoryKjb.createFilter(filterName.trim());
if (adapterFilter != null) {
resultMessage = adapterFilter.doPostFilter(adptGrpName, adptName, resultMessage, prop, request,
response);
@@ -24,8 +24,10 @@ public class HttpDynamicInAdapterManager implements Lifecycle {
private static HttpDynamicInAdapterManager instance = new HttpDynamicInAdapterManager();
private ConcurrentHashMap<String, HttpDynamicInAdapterUri> adptUriMap = new ConcurrentHashMap<String, HttpDynamicInAdapterUri>();
//private ConcurrentHashMap<String, HttpDynamicInAdapterUri> adptUriMap = new ConcurrentHashMap<String, HttpDynamicInAdapterUri>();
public ConcurrentHashMap<String, HttpDynamicInAdapterUri> adptUriMap = new ConcurrentHashMap<String, HttpDynamicInAdapterUri>();
public static HttpDynamicInAdapterManager getInstance() {
return instance;
}
@@ -28,7 +28,7 @@ public class HttpDynamicInAdapterUri {
return isEqualsAdpt(other.getAdptGrpName(), other.getAdptName());
}
public boolean isEqualsAdpt(String adptGrpName, String adptNamer) {
public boolean isEqualsAdpt(String adptGrpName, String adptName) {
if ( adptGrpName != null && adptGrpName.equals(this.adptGrpName)
&& adptName != null && adptName.equals(this.adptName) ) {
return true;
@@ -1,14 +1,19 @@
package com.eactive.eai.adapter.http.dynamic.filter;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
import com.eactive.eai.authserver.service.BearerTokenInfo;
//import com.eactive.eai.authserver.vo.BearerTokenInfo;
//import com.eactive.eai.authserver.custom.BearerTokenService;
import com.eactive.eai.authserver.service.OAuth2Manager;
import com.eactive.eai.authserver.vo.ClientVO;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageManager;
import com.eactive.eai.common.property.PropGroupVO;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.session.SessionManager;
import com.eactive.eai.common.stdmessage.STDMessageManager;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.StringUtil;
import com.eactive.eai.inbound.action.ActionFactory;
import com.eactive.eai.inbound.action.RequestAction;
import com.eactive.eai.inbound.processor.Processor;
@@ -35,7 +40,9 @@ import java.text.ParseException;
import java.util.Base64;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
public class ApiAuthFilter implements HttpAdapterFilter {
static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
@@ -52,7 +59,10 @@ public class ApiAuthFilter implements HttpAdapterFilter {
private JWSVerifier jwsVerifier;
public ApiAuthFilter() {
// // CA 토큰 저장소
// private final Map<String, BearerTokenInfo> CATokenStore = new ConcurrentHashMap<>();
public ApiAuthFilter() {
super();
PropGroupVO vo = PropManager.getInstance().getPropGroupVO(PROP_GROUP_AUTH_SERVER);
@@ -94,32 +104,55 @@ public class ApiAuthFilter implements HttpAdapterFilter {
*/
StandardMessage standardMessage = STDMessageManager.getInstance().getSTDMessage(apiId);
String eaiSvcCd = StandardMessageManager.getInstance().getMapper().getEaiSvcCode(standardMessage);
if(!StringUtils.equals(eaiSvcCd, prop.getProperty("API_SERVICE_CODE"))) eaiSvcCd = prop.getProperty("API_SERVICE_CODE");
EAIMessage eaiMessage = EAIMessageManager.getInstance().getEAIMessage(eaiSvcCd);
if(StringUtils.isBlank(eaiMessage.getAuthType())){
return message;
}
boolean isPassScope = false;
switch (eaiMessage.getAuthType()){
case "oauth":
try {
String token = ApiAuthFilter.extractJWTToken(request);
String token = extractBearerToken(request);
SignedJWT signedJWT = SignedJWT.parse(token);
if (new Date().after(signedJWT.getJWTClaimsSet().getExpirationTime())) {
if (signedJWT.getJWTClaimsSet().getExpirationTime() == null) {
logger.debug("Static Token");
} else if (new Date().after(signedJWT.getJWTClaimsSet().getExpirationTime())) {
throw new JwtAuthException(ERROR_TOKEN_EXPIRED, "Access token expired");
}
if (!signedJWT.verify(jwsVerifier)) {
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
try {
if (!signedJWT.verify(jwsVerifier)) {
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
}
}catch (Exception e) {
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid", e);
}
OAuth2Manager manager = OAuth2Manager.getInstance();
HashSet<String> scopeSet = manager.getApiScopeMap().get(apiId);
if (!verifyScope(scopeSet, signedJWT)) {
String[] scopeArr = signedJWT.getJWTClaimsSet().getStringArrayClaim(PAYLOAD_PARAM_NAME_SCOPE);
if (scopeArr == null || scopeArr.length == 0) {
throw new JwtAuthException(ERROR_AUTHORIZATION_FAIL,
String.format("Insufficient [Scope](Allowed Scope=%s)", scopeSet.toString()));
}
for (String scope : scopeArr) {
if (StringUtils.equals(scope, "oob") || StringUtils.equals(scope, "public")) {
isPassScope = true;
}
}
if (!isPassScope) {
if (!verifyScope(scopeSet, signedJWT)) {
throw new JwtAuthException(ERROR_AUTHORIZATION_FAIL,
String.format("Insufficient [Scope](Allowed Scope=%s)", scopeSet.toString()));
}
}
// header 값으로 전송된 clientId와 토큰 소유 clientId check
if (!verifyClientId(prop, signedJWT)) {
@@ -130,7 +163,7 @@ public class ApiAuthFilter implements HttpAdapterFilter {
throw e;
} catch (Exception e) {
logger.error(e.getMessage());
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token unknown Error", e);
}
break;
case "api_key":
@@ -140,25 +173,43 @@ public class ApiAuthFilter implements HttpAdapterFilter {
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Invalid or missing API key \""+apiKeyName+"\" in Http Header");
}
prop.setProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID, apiKey);
isPassScope = true;
break;
case "ca":
String token = extractBearerToken(request);
BearerTokenInfo bearerTokenInfo = SessionManager.getInstance().getCAToken(token);
if ( bearerTokenInfo != null ) {
if( bearerTokenInfo.isExpired() ) {
SessionManager.getInstance().removeCAToken(token);
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "expried API key \""+token+"\" in Http Authrozation Header");
}
prop.setProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID, bearerTokenInfo.getClientId());
isPassScope = true;
}
else {
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Invalid or missing API key \""+token+"\" in Http Authrozation Header");
}
break;
case "none":
return message;
}
String clientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
ClientVO clientVO = OAuth2Manager.getInstance().getClientVO(clientId);
if(clientVO == null){
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Unregistered APP");
}
if (isPassScope) {
String clientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
ClientVO clientVO = OAuth2Manager.getInstance().getClientVO(clientId);
if(clientVO == null){
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Unregistered APP");
}
if(clientVO.getApiMap().containsKey(eaiSvcCd) == false){
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Unregistered API ["+eaiSvcCd+"] in ["+clientVO.getClientName()+"] APP");
if(clientVO.getApiMap().containsKey(eaiSvcCd) == false){
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Unregistered API ["+eaiSvcCd+"] in ["+clientVO.getClientName()+"] APP");
}
}
return message;
}
private boolean verifyClientId(Properties prop, SignedJWT signedJWT) {
private boolean verifyClientId(Properties prop, SignedJWT signedJWT) throws JwtAuthException {
try {
// 이전 filter에서 셋팅한 clientId 확보
String headerClientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
@@ -176,6 +227,7 @@ public class ApiAuthFilter implements HttpAdapterFilter {
}
} catch (Exception e) {
logger.error(e.getMessage());
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
}
return true;
@@ -227,8 +279,16 @@ public class ApiAuthFilter implements HttpAdapterFilter {
if (scopeArr == null || scopeArr.length == 0) {
return false;
}
String passScope = "oob,public";
String[] passScopeArr = org.springframework.util.StringUtils.tokenizeToStringArray(passScope, ",");
for (String scope : scopeArr) {
for (String pScope : passScopeArr) {
if ( StringUtils.equalsAny(scope, pScope)) {
return true;
}
}
if (scopeSet.contains(scope)) {
return true;
}
@@ -237,7 +297,7 @@ public class ApiAuthFilter implements HttpAdapterFilter {
return false;
}
public static String extractJWTToken(HttpServletRequest request) throws JwtAuthException {
public static String extractBearerToken(HttpServletRequest request) throws JwtAuthException {
String authorization = request.getHeader("Authorization");
if (StringUtils.isBlank(authorization)) {
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "No have header info: Authorization");
@@ -0,0 +1,183 @@
package com.eactive.eai.adapter.http.dynamic.filter;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Properties;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//import org.apache.commons.net.util.Base64;
import org.springframework.http.HttpStatus;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import com.eactive.eai.adapter.http.HttpMethodType;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
import com.eactive.eai.authserver.service.OAuth2Manager;
import com.eactive.eai.authserver.vo.ClientVO;
import com.eactive.eai.common.TransactionContextKeys;
import com.eactive.eai.common.util.Logger;
public class HmacSha256VerifyFilterKjb implements HttpAdapterFilter {
static final String KJB_ROOTLESS_ARRAY = "{ \"KJB_ROOTLESS_ARRAY\" : ";
static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
public HmacSha256VerifyFilterKjb() {
super();
}
@Override
public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
HttpServletRequest request, HttpServletResponse response) throws Exception {
String inboundMethod = prop.getProperty(HttpAdapterServiceKey.INBOUND_METHOD);
String inboundUri = prop.getProperty(HttpAdapterServiceKey.INBOUND_URI);
String inboundBody = prop.getProperty(HttpAdapterServiceKey.INBOUND_REQUEST_MESSAGE);
try {
String xObpPartnercode = request.getHeader("x-obp-partnercode");
String xObpSignatureUrl = request.getHeader("x-obp-signature-url");
String xObpSignatureBody = request.getHeader("x-obp-signature-body");
if (StringUtils.isBlank(xObpPartnercode)
|| StringUtils.isBlank(xObpSignatureUrl)) {
throw new JwtAuthException(
String.valueOf(HttpStatus.UNAUTHORIZED.value()),
"Can not find mandatory Http Header");
}
if (StringUtils.isNotBlank(prop.getProperty(HttpAdapterServiceKey.INBOUND_QUERY_STRING))) {
inboundUri = inboundUri + "?" + prop.getProperty(HttpAdapterServiceKey.INBOUND_QUERY_STRING);
inboundBody = "";
}
String chkUrl = inboundMethod + "&" + inboundUri;
String chkBody = inboundBody;
String clientSecret = assignClientSecret(prop, request);
if (chkBody.startsWith(KJB_ROOTLESS_ARRAY)) {
chkBody = chkBody.substring(KJB_ROOTLESS_ARRAY.length());
if (chkBody.endsWith("}")) {
chkBody = chkBody.substring(0, chkBody.length() - 1);
}
}
String macUrl = calculateHMAC(chkUrl, clientSecret);
String macBody = calculateHMAC(chkBody, clientSecret);
if (!StringUtils.equals(xObpSignatureUrl, macUrl)) {
throw new JwtAuthException(
String.valueOf(HttpStatus.UNAUTHORIZED.value()),
"Signature verifying failed : x-obp-signature-url");
}
switch (HttpMethodType.getValue(request.getMethod())) {
case GET:
case DELETE:
break;
default:
if (StringUtils.isNotBlank(inboundBody) && !StringUtils.equals("{}", inboundBody)) {
if (!StringUtils.equals(xObpSignatureBody, macBody)) {
throw new JwtAuthException(
String.valueOf(HttpStatus.UNAUTHORIZED.value()),
"Signature verifying failed : x-obp-signature-body");
}
break;
}
}
} catch (JwtAuthException e) {
logger.debug(e.getMessage());
throw e;
} catch (Exception e) {
logger.error(e.getMessage());
throw new JwtAuthException(
String.valueOf(HttpStatus.UNAUTHORIZED.value()),
"Signature verifying failed(unkown)");
}
return message;
}
public static String calculateHMAC(String data, String key)
throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key.getBytes(), "HmacSHA256"));
return Base64.getEncoder().encodeToString(mac.doFinal(data.getBytes("UTF-8")));
}
private String assignClientSecret(Properties prop, HttpServletRequest request) throws Exception {
String clientId = assignClientId(prop, request);
if (StringUtils.isBlank(clientId)) {
throw new JwtAuthException(
String.valueOf(HttpStatus.UNAUTHORIZED.value()),
"Can not find clientId info");
}
ClientVO client = (ClientVO) OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId);
if (client == null) {
throw new JwtAuthException(
String.valueOf(HttpStatus.UNAUTHORIZED.value()),
"Can not find client info");
}
return client.getClientSecret();
}
private String assignClientId(Properties prop, HttpServletRequest request) {
String clientId = null;
try {
// 이전 filter에서 셋팅한 clientId 확보
clientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
// 이전 filter에서 셋팅한 값이 없다면 header 정보에서 확보
if (StringUtils.isBlank(clientId)) {
clientId = request.getHeader(HttpAdapterServiceSupport.HEADER_NAME_CLIENT_ID);
}
} catch (Exception e) {
logger.error(e.getMessage());
}
return clientId;
}
@Override
public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
HttpServletRequest request, HttpServletResponse response) throws Exception {
String outboundBody = (String) resultMessage;
try {
Object root = JSONValue.parse(outboundBody);
if (root instanceof JSONObject && ((JSONObject) root).containsKey("KJB_ROOTLESS_ARRAY")) {
JSONArray jsonArray = (JSONArray) ((JSONObject) root).get("KJB_ROOTLESS_ARRAY");
outboundBody = jsonArray.toJSONString();
}
String clientSecret = assignClientSecret(prop, request);
String macBody = calculateHMAC(outboundBody, clientSecret);
response.addHeader("x-obp-signature-body", macBody);
response.addHeader("x-obp-partnercode", request.getHeader("x-obp-partnercode"));
response.addHeader("x-obp-txid", prop.getProperty(TransactionContextKeys.TRANSACTION_UUID,""));
} catch (Exception e) {
logger.error(e.getMessage());
}
return resultMessage;
}
}
@@ -0,0 +1,67 @@
package com.eactive.eai.adapter.http.dynamic.filter;
import java.util.concurrent.ConcurrentHashMap;
import com.eactive.eai.common.util.Logger;
public class HttpAdapterFilterFactoryKjb extends HttpAdapterFilterFactory {
static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
static String basePackage = "com.eactive.eai.custom.adapter.http.dynamic.filter";
static private ConcurrentHashMap<String, HttpAdapterFilter> h = new ConcurrentHashMap<String, HttpAdapterFilter>();
public HttpAdapterFilterFactoryKjb() {
super();
}
@SuppressWarnings("rawtypes")
public static HttpAdapterFilter createFilter(String type) {
if (h.containsKey(type)) {
return (HttpAdapterFilter) h.get(type);
}
HttpAdapterFilter filter = null;
switch (HttpAdapterFilterType.getValue(type)) {
case APIAUTHFILTER:
filter = new ApiAuthFilter();
break;
case JWTAUTHFILTER:
filter = new JwtAuthFilter();
break;
case IPWHITELISTFILTER:
filter = new IpWhiteListFilter();
break;
case ADAPTERALLOWIPLISTFILTER:
filter = new AdapterAllowIPListFilter();
break;
case HMAC_SHA256:
filter = new HmacSha256VerifyFilterKjb();
break;
case REFLECTALLHEADER:
filter = new ReflectAllHeaderFilter();
break;
default:
filter = classForName(type);
if (filter == null) {
filter = classForName(basePackage + "." + type);
}
break;
}
if (filter != null) {
h.put(type, filter);
return filter;
} else {
return null;
}
}
private static HttpAdapterFilter classForName(String type) {
try {
Class<?> cl = Class.forName(type);
return (HttpAdapterFilter) cl.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
logger.error("Cannot create a HttpAdapterFilter. - {}", type);
return null;
}
}
}
@@ -5,6 +5,8 @@ public enum HttpAdapterFilterType {
JWTAUTHFILTER,
IPWHITELISTFILTER,
ADAPTERALLOWIPLISTFILTER,
HMAC_SHA256,
REFLECTALLHEADER,
UNKNOWN;
public static HttpAdapterFilterType getValue(String type) {
@@ -88,7 +88,9 @@ public class JwtAuthFilter implements HttpAdapterFilter {
String token = JwtAuthFilter.extractJWTToken(request);
SignedJWT signedJWT = SignedJWT.parse(token);
if (new Date().after(signedJWT.getJWTClaimsSet().getExpirationTime())) {
if (signedJWT.getJWTClaimsSet().getExpirationTime() == null) {
logger.debug("Static Token");
} else if (new Date().after(signedJWT.getJWTClaimsSet().getExpirationTime())) {
throw new JwtAuthException(ERROR_TOKEN_EXPIRED, "Access token expired");
}
@@ -118,7 +120,7 @@ public class JwtAuthFilter implements HttpAdapterFilter {
return message;
}
private boolean verifyClientId(Properties prop, SignedJWT signedJWT) {
private boolean verifyClientId(Properties prop, SignedJWT signedJWT) throws JwtAuthException {
try {
// 이전 filter에서 셋팅한 clientId 확보
String headerClientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
@@ -136,6 +138,7 @@ public class JwtAuthFilter implements HttpAdapterFilter {
}
} catch (Exception e) {
logger.error(e.getMessage());
throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
}
return true;
@@ -0,0 +1,96 @@
package com.eactive.eai.adapter.http.dynamic.filter;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.property.PropManager;
import java.util.Arrays;
import java.util.stream.Stream;
public class ReflectAllHeaderFilter implements HttpAdapterFilter {
public ReflectAllHeaderFilter() {
super();
}
protected static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
public static final String PROPERTIES_GROUP_NAME = "HttpHeaderFilter";
public static final String HEADER_KEY_NAMES = "AllHeaderFilter.blackList";
String[] HttpHeaderRelayBlackList = {
"Content-Length",
"Transfer-Encoding",
"Host",
"Authorization",
"Accept",
"Host",
"Cookie",
"Connection",
"Keep-Alive",
"Proxy-Authenticate",
"Proxy-Authorization",
"TE",
"Trailer",
"Transfer-Encoding",
"Upgrade",
"Content-Type",
"Content-Encoding",
"Content-Language",
"Content-Location",
"Content-MD5",
"Expect",
};
@Override
public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
HttpServletRequest request, HttpServletResponse response) throws Exception {
return message;
}
@Override
public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
HttpServletRequest request, HttpServletResponse response) throws Exception {
logger.debug("doPreFilter ReflectAllHeaderFilter Start.");
String propValue = PropManager.getInstance().getProperty(PROPERTIES_GROUP_NAME, HEADER_KEY_NAMES, "").trim();
String[] userSettingBlackList = propValue.split(",");
if( userSettingBlackList.length > 0 ) {
HttpHeaderRelayBlackList = Stream
.concat(Arrays.stream(HttpHeaderRelayBlackList), Arrays.stream(userSettingBlackList))
.toArray(String[]::new);
}
try {
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
if( StringUtils.equalsAnyIgnoreCase( headerName, HttpHeaderRelayBlackList ) ) {
logger.debug("Skip Processing Key ["+headerName+"], value ["+headerValue+"] in HttpHeaderRelayBlackList");
continue;
}
response.setHeader(headerName, headerValue);
}
} catch (Exception e) {
logger.error(e.getMessage());
}
logger.debug("doPreFilter ReflectAllHeaderFilter End.");
return resultMessage;
}
}
@@ -131,6 +131,7 @@ public class HttpAdapterServiceBypass extends HttpAdapterServiceSupport {
prop.put(INBOUND_URI, request.getRequestURI());
prop.put(INBOUND_QUERY_STRING, StringUtils.defaultString(request.getQueryString()));
prop.put(INBOUND_HEADER, getHeaders(request));
prop.put(INBOUND_EXTPARAMS, StringUtils.defaultString(request.getQueryString()));
if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)
|| StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) {
// /api/v1/public/getUserInfo.svc
@@ -503,6 +504,6 @@ public class HttpAdapterServiceBypass extends HttpAdapterServiceSupport {
String orgUri = "/HTT/CbsInNetSys/abcd/123456";
String result = "";
result = getExtUri(orgUri, 3);
System.out.println(result);
// System.out.println(result);
}
}
@@ -275,6 +275,7 @@ public class HttpAdapterServiceRest extends HttpAdapterServiceSupport {
prop = new Properties();
prop.put(INBOUND_METHOD, request.getMethod());
prop.put(INBOUND_URI, request.getRequestURI());
prop.put(INBOUND_EXTPARAMS, StringUtils.defaultString(request.getQueryString()));
prop.put(INBOUND_HEADER, getHeaders(request));
if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)
|| StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) {
@@ -588,7 +589,13 @@ public class HttpAdapterServiceRest extends HttpAdapterServiceSupport {
String adapterGroupName = prop.getProperty(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME);
String adapterName = prop.getProperty(HttpClientAdapterServiceKey.ADAPTER_NAME);
int httpStatusCode = response.getStatus();
HttpAdapterExtraLogUtil.insertHttpAdapterExtraLog(uuid, 400, adapterGroupName, adapterName, new HashMap<>(), url, method, httpStatusCode);
Map<Object, Object> headerMap = new HashMap<>();
// 응답 헤더 로깅
for (String headerName : response.getHeaderNames()) {
String headerValue = response.getHeader(headerName);
headerMap.put(headerName, headerValue);
}
HttpAdapterExtraLogUtil.insertHttpAdapterExtraLog(uuid, 400, adapterGroupName, adapterName, headerMap, url, method, httpStatusCode);
}
}
@@ -1,14 +1,19 @@
package com.eactive.eai.adapter.http.dynamic.impl;
import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterPropManager;
import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.adapter.Keys;
import com.eactive.eai.adapter.http.HttpMemoryLogger;
import com.eactive.eai.adapter.http.HttpStatusException;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
import com.eactive.eai.common.TransactionContextKeys;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.util.CommonLib;
import com.eactive.eai.common.util.HttpAdapterExtraLogUtil;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.MessageUtil;
import com.eactive.eai.env.ElinkConfig;
@@ -17,6 +22,9 @@ import com.eactive.eai.inbound.processor.Processor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.mina.common.ByteBuffer;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
@@ -26,8 +34,11 @@ import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
{
@@ -49,10 +60,14 @@ public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
**/
public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) {
int traceLevel = 0;
AdapterGroupVO adapterGroupVo = null;
Properties prop = null;
try {
AdapterManager adapterManager = AdapterManager.getInstance();
AdapterVO adptVO = adapterManager.getAdapterVO(adptGrpName,adptName);
adapterGroupVo = adptVO.getAdapterGroupVO();
AdapterPropManager manager = AdapterPropManager.getInstance();
if(adptVO == null) {
@@ -153,10 +168,11 @@ public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
logger.debug("HttpAdapter] " + resMsg);
}
Properties prop = new Properties();
prop = new Properties();
prop.put(INBOUND_METHOD, request.getMethod());
prop.put(INBOUND_URI, request.getRequestURI());
prop.put(INBOUND_HEADER, getHeaders(request));
prop.put(INBOUND_EXTPARAMS, StringUtils.defaultString(request.getQueryString()));
if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)
|| StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) {
// /api/v1/public/getUserInfo.svc
@@ -172,6 +188,20 @@ public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
prop.put(PROPERTIES_NAME_HTTP_REQUEST_METHOD, request.getMethod());
prop.put(ALLOW_IP, httpProp.getProperty(ALLOW_IP, ""));
String body = new String ( requestBytes,encode);
try {
Object root = JSONValue.parse(body);
if( root instanceof JSONArray ) {
JSONObject wrappedObject = new JSONObject();
wrappedObject.put("KJB_ROOTLESS_ARRAY", root);
requestBytes = wrappedObject.toJSONString().getBytes(encode);
}
}catch (Exception e) {
// ignore json이 아니기에 해줄것이 없음.
}
// 로컬 서비스 호출
Object result = null;
if (MessageUtil.isBytesMessage(messageType)) {
@@ -190,14 +220,17 @@ public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
}
}
if (result == null) {
if ( result == null) {
responseData = ElinkConfig.getAsyncDummyDataForAdapterGroup(adptGrpName);
} else if (result instanceof byte[]) {
responseData = new String((byte[]) result, encode);
} else if (result instanceof String) {
responseData = (String) result;
if ( StringUtils.isBlank( responseData ) ) {
responseData = ElinkConfig.getAsyncDummyDataForAdapterGroup(adptGrpName, adptName);
}
}
response.setCharacterEncoding(encode);
response.getWriter().print(responseData);
if (traceLevel >= 3){
@@ -218,8 +251,32 @@ public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
if (addData.length() > 0){
responseData = addData + responseData;
}
// UI와 통신시(UTF-8) 변환오류로 ENCODE 제거
response.setContentType("text/plain");
try {
Object root = JSONValue.parse(responseData);
if( root instanceof JSONObject ) {
JSONObject wrappedObject = (JSONObject) root;
responseData = wrappedObject.get("KJB_ROOTLESS_ARRAY").toString();
}
}catch (Exception e) {
// ignore json이 아니기에 해줄것이 없음.
}
// 300응답에서 받은 Header정보 사용하기 위해 읽어옴.
Map<String, Object> responsePropertyMap = (Map<String, Object>) prop.get(OUTBOUND_PROPERTY_MAP);
if(responsePropertyMap != null){
Properties responseHeaders = (Properties)responsePropertyMap.get(OUTBOUND_RESPONSE_HEADERS);
Map<String, String> responseHeaderMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
// Properties 내용을 모두 복사
for (String name : responseHeaders.stringPropertyNames()) {
responseHeaderMap.put(name, responseHeaders.getProperty(name));
}
String contentTytpe = responseHeaderMap.get("Content-Type");
response.setContentType(contentTytpe); // 300응답에서 받은 Content-Type을 그대로 적용.
}
// UI와 통신시(UTF-8) 변환오류로 ENCODE 제거
response.setCharacterEncoding(encode);
response.getWriter().print(responseData);
if (logger.isDebug()){
@@ -241,26 +298,64 @@ public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
}
logger.warn("HttpAdapter] " + adptGrpName + "-" + adptName + ">>" + e.getMessage());
response.setStatus(e.getStatus());
try {
String errorMsg = String.format("(%d) %s", e.getStatus(), e.getMessage());
response.getWriter().println(errorMsg);
} catch (Exception ex) {
// IGNORE
if( "JSN".equals( adapterGroupVo.getMessageType() ) ) {
try {
String errorMsg = MessageUtil.makeJsonErrorMessage( MessageUtil.ERROR_CODE_AP_ERROR, e.getMessage());
response.getWriter().println(errorMsg);
} catch (Exception ex) {
// IGNORE
}
}else {
try {
String errorMsg = String.format("(%d) %s", e.getStatus(), e.getMessage());
response.getWriter().println(errorMsg);
} catch (Exception ex) {
// IGNORE
}
}
} catch (Exception e) {
if (traceLevel >= 3){
HttpMemoryLogger.error(adptGrpName+adptName, e.toString(),e);
}
logger.error("HttpAdapter] "+adptGrpName+"-"+adptName, e);
response.setStatus(500);
try {
response.getWriter().println(e.getMessage());
String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
throw new Exception(errCode);
} catch (Exception ex) {
logger.warn("error", ex);
if( "JSN".equals( adapterGroupVo.getMessageType() ) ) {
try {
String errorMsg = MessageUtil.makeJsonErrorMessage( MessageUtil.ERROR_CODE_AP_ERROR, e.getMessage());
response.getWriter().println(errorMsg);
throw new Exception(MessageUtil.ERROR_CODE_AP_ERROR);
} catch (Exception ex) {
logger.warn("error", ex);
}
}else {
try {
response.getWriter().println(e.getMessage());
String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
throw new Exception(errCode);
} catch (Exception ex) {
logger.warn("error", ex);
}
}
}
}finally {
String uuid = prop.getProperty(TransactionContextKeys.TRANSACTION_UUID);
String url = prop.getProperty(HttpClientAdapterServiceKey.INBOUND_EXTURI);
String method = prop.getProperty(HttpClientAdapterServiceKey.INBOUND_METHOD);
String adapterGroupName = prop.getProperty(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME);
String adapterName = prop.getProperty(HttpClientAdapterServiceKey.ADAPTER_NAME);
int httpStatusCode = response.getStatus();
Map<Object, Object> headerMap = new HashMap<>();
// 응답 헤더 로깅
for (String headerName : response.getHeaderNames()) {
String headerValue = response.getHeader(headerName);
headerMap.put(headerName, headerValue);
}
HttpAdapterExtraLogUtil.insertHttpAdapterExtraLog(uuid, 400, adapterGroupName, adapterName, headerMap, url, method, httpStatusCode);
}
}
/**
@@ -54,7 +54,7 @@ public class KeepAliveTrueWrapper implements HandlerWrapper {
// 최대 요청 횟수를 초과한 경우 연결을 종료하고 로그를 출력
if (count > maxRequestCount) {
exchange.getConnection().close();
System.out.println("Connection closed due to exceeding max requests limit.");
// System.out.println("Connection closed due to exceeding max requests limit.");
return;
}
handler.handleRequest(exchange);
@@ -45,7 +45,7 @@ public class JtcBeanSample implements JtmaxService {
String bufferType = tux.getBufferTypeString();
if ("STRING".equals(bufferType)) {
TuxStringBuffer tuxbuf = (TuxStringBuffer) tux;
System.out.println("received string value : " + tuxbuf.getString());
// System.out.println("received string value : " + tuxbuf.getString());
TuxStringBuffer ret = new TuxStringBuffer(WebtSystem.getDefaultCharset());
ret.setString(tuxbuf.getString().toUpperCase());
return ret;
@@ -60,8 +60,8 @@ public class JtcBeanSample implements JtmaxService {
}
String rtnstr = rcvstr.toUpperCase();
System.out.println("received string value : " + rcvstr);
System.out.println("return string value : " + rtnstr);
// System.out.println("received string value : " + rcvstr);
// System.out.println("return string value : " + rtnstr);
TuxCarrayBuffer ret = new TuxCarrayBuffer(WebtSystem.getDefaultCharset());
ret.setBytes(rtnstr.getBytes());;
return ret;
@@ -73,8 +73,8 @@ public class JtcBeanSample implements JtmaxService {
String rcvstr = tuxbuf.getField("SEC100").get().stringValue();
String rtnstr = rcvstr.toUpperCase();
System.out.println("received string value : " + rcvstr);
System.out.println("return string value : " + rtnstr);
// System.out.println("received string value : " + rcvstr);
// System.out.println("return string value : " + rtnstr);
TuxFieldBuffer ret = new TuxFieldBuffer(false); // FML 16임으로 false로
// ret.createField(sample.fml_sec2).add(rtnstr);
ret.createField("SEC2").add(rtnstr);
@@ -73,7 +73,7 @@ public class JtcClientSample {
try {
// if(cd == null) {
System.out.println("tpconnect failed!");
// System.out.println("tpconnect failed!");
// }
// else {
@@ -84,12 +84,12 @@ public class JtcClientSample {
sndbuf.setString("conversation service");
TuxBuffer rcvbuf = service.tpcall(sndbuf);
System.out.println(rcvbuf.getString());
// System.out.println(rcvbuf.getString());
// }
}
catch (WebtException e) {
e.printStackTrace();
System.out.println("error Occurred");
// System.out.println("error Occurred");
}
finally {
@@ -58,7 +58,7 @@ public class JtcServerAdapterBean implements JtmaxService {
try {
if ("STRING".equals(bufferType)) {
TuxStringBuffer tuxbuf = (TuxStringBuffer) tux;
System.out.println("received string value : " + tuxbuf.getString());
// System.out.println("received string value : " + tuxbuf.getString());
byte[] request = tuxbuf.getString().getBytes();
RequestDispatcher dispatcher = RequestDispatcher.getRequestDispatcher(adapterGroupName);
byte[] response = (byte[]) dispatcher.handle(adapterName, request, prop);
@@ -31,12 +31,11 @@ public class TestMsgListener implements TuxAsyncMsgListener {
}
public void handleError(Exception e) {
System.out.println(e);
// System.out.println(e);
}
public void handleEvent(TuxBuffer rcvBuffer) {
System.out.println(Thread.currentThread().getName()
+" ] rcv " + rcvBuffer);
// System.out.println(Thread.currentThread().getName()+" ] rcv " + rcvBuffer);
try {
// TODO : Call Internal service
}
@@ -9,7 +9,7 @@ import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
public class DumpServer {
static public void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Usage : dump <port>");
// System.out.println("Usage : dump <port>");
return;
}
int port = Integer.parseInt(args[0]);
@@ -53,12 +53,12 @@ public class DumpServer {
System.out.print("> ");
String cmd = (new java.io.BufferedReader(new java.io.InputStreamReader(System.in))).readLine();
if ("".equals(cmd)) {
System.out.println(SocketAdapterManager.getInstance());
// System.out.println(SocketAdapterManager.getInstance());
} else if ("exit".equals(cmd)) {
System.exit(1);
}
} catch(Exception e) {
System.out.println(e.toString());
// System.out.println(e.toString());
}
}
}
@@ -46,12 +46,12 @@ public class EchoServer {
System.out.print("> ");
String cmd = (new java.io.BufferedReader(new java.io.InputStreamReader(System.in))).readLine();
if ("".equals(cmd)) {
System.out.println(SocketAdapterManager.getInstance());
// System.out.println(SocketAdapterManager.getInstance());
} else if ("exit".equals(cmd)) {
System.exit(1);
}
} catch(Exception e) {
System.out.println("processCommand errpr "+ e.toString());
// System.out.println("processCommand errpr "+ e.toString());
}
}
}
@@ -49,15 +49,15 @@ public class Muxer {
}
public synchronized byte[] handle(byte[] message) {
System.out.println("##############################################################");
System.out.println("CiscoListener | message received : " + new String(message));
System.out.println("##############################################################");
// System.out.println("##############################################################");
// System.out.println("CiscoListener | message received : " + new String(message));
// System.out.println("##############################################################");
return message;
}
static public void main(String[] args) throws Exception {
if (args.length != 3) {
System.out.println("java " + Muxer.class.getName() + " <inbound-port> <outbound-hostname> <outbound-port>");
// System.out.println("java " + Muxer.class.getName() + " <inbound-port> <outbound-hostname> <outbound-port>");
return;
}
@@ -77,9 +77,9 @@ class MuxerRequestProcessor implements IRequestProcessor {
}
public synchronized byte[] handle(byte[] message) throws EAIException {
System.out.println("##############################################################");
System.out.println("MuxerRequestProcessor | message received : " + new String(message));
System.out.println("##############################################################");
// System.out.println("##############################################################");
// System.out.println("MuxerRequestProcessor | message received : " + new String(message));
// System.out.println("##############################################################");
return (byte[]) outboundAdapter.sendMessage(message);
}
@@ -34,7 +34,7 @@ public class ProxyServer {
static public void main(String[] args) throws Exception {
if (args.length != 3) {
System.out.println("java " + ProxyServer.class.getName() + " <proxy-port> <remote-hostname> <remote-port>");
// System.out.println("java " + ProxyServer.class.getName() + " <proxy-port> <remote-hostname> <remote-port>");
return;
}
@@ -188,9 +188,9 @@ public class LoadRunner {
}
stopLatch.countDown();
} catch (Exception e) {
System.out.println(e.toString());
// System.out.println(e.toString());
} catch (Error e) {
System.out.println(e.toString());
// System.out.println(e.toString());
}
}
});
@@ -202,7 +202,7 @@ public class LoadRunner {
stopLatch.await();
} catch (InterruptedException ex) {
//ex.printStackTrace();
System.out.println("wait error");
// System.out.println("wait error");
}
executor.shutdown();
@@ -211,27 +211,27 @@ public class LoadRunner {
boolean result = executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
if (result)
break;
System.out.println("[LoadRunner] shutdown() progressing ... await 1 seconds more");
// System.out.println("[LoadRunner] shutdown() progressing ... await 1 seconds more");
} catch (InterruptedException e) {
//e.printStackTrace();
System.out.println("awaitTermination error");
// System.out.println("awaitTermination error");
}
}
latch.await();
stopWatch.stop();
System.out.println();
System.out.println();
System.out.println("===============================================================");
System.out.println(" think time : " + thinkTime + " ms");
System.out.println(" thread count : " + threadCount);
System.out.println(" loop count : " + loopCount);
System.out.println(" total request : " + (threadCount * loopCount));
System.out.println(" elapsed : " + stopWatch.toString());
System.out.println(" tps : " + new Integer(threadCount * loopCount * 1000).longValue() / stopWatch.getTime());
System.out.println("===============================================================");
System.out.println();
// System.out.println();
// System.out.println();
// System.out.println("===============================================================");
// System.out.println(" think time : " + thinkTime + " ms");
// System.out.println(" thread count : " + threadCount);
// System.out.println(" loop count : " + loopCount);
// System.out.println(" total request : " + (threadCount * loopCount));
// System.out.println(" elapsed : " + stopWatch.toString());
// System.out.println(" tps : " + new Integer(threadCount * loopCount * 1000).longValue() / stopWatch.getTime());
// System.out.println("===============================================================");
// System.out.println();
}
@@ -245,13 +245,13 @@ public class LoadRunner {
break;
} else if ("".equals(line.trim())) {
} else if ("help".equals(line.trim())) {
System.out.println("===============================================================");
System.out.println("LoadRunner v1.0 (http port = 8282)");
System.out.println("===============================================================");
System.out.println(" help : help");
System.out.println(" start : start [thread count] [loop count] [think time]");
System.out.println(" exit : exit");
System.out.println("");
// System.out.println("===============================================================");
// System.out.println("LoadRunner v1.0 (http port = 8282)");
// System.out.println("===============================================================");
// System.out.println(" help : help");
// System.out.println(" start : start [thread count] [loop count] [think time]");
// System.out.println(" exit : exit");
// System.out.println("");
} else if (line.trim().startsWith("start")) {
String[] tokens = line.trim().split("[ ]+");
if (tokens.length > 1)
@@ -264,10 +264,10 @@ public class LoadRunner {
} else if ("exit".equals(line.trim())) {
System.exit(1);
} else {
System.out.println("Unknow command. type help.");
// System.out.println("Unknow command. type help.");
}
} catch(Exception e) {
System.out.println("Error " + e.toString());
// System.out.println("Error " + e.toString());
}
}
}
@@ -298,7 +298,7 @@ public class LoadRunner {
if(br != null) br.close();
}
catch(Exception ee) {
System.out.println("close error");
// System.out.println("close error");
}
}
@@ -369,10 +369,10 @@ public class LoadRunner {
if (args.length == 2) {
hostname = args[0];
System.out.println("remote host : " + hostname);
// System.out.println("remote host : " + hostname);
filename = args[1];
} else {
System.out.println("Usage : loadrunner [ip] [file]");
// System.out.println("Usage : loadrunner [ip] [file]");
return;
}
@@ -189,10 +189,10 @@ public class LoadRunner2 {
stopLatch.countDown();
} catch (Exception e) {
// e.printStackTrace();
System.out.println("executor.execute Exception");
// System.out.println("executor.execute Exception");
} catch (Error e) {
// e.printStackTrace();
System.out.println("executor.execute error");
// System.out.println("executor.execute error");
}
}
});
@@ -204,7 +204,7 @@ public class LoadRunner2 {
stopLatch.await();
} catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println("InterruptedException");
// System.out.println("InterruptedException");
}
executor.shutdown();
@@ -213,27 +213,27 @@ public class LoadRunner2 {
boolean result = executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
if (result)
break;
System.out.println("[LoadRunner] shutdown() progressing ... await 1 seconds more");
// System.out.println("[LoadRunner] shutdown() progressing ... await 1 seconds more");
} catch (InterruptedException e) {
// e.printStackTrace();
System.out.println("[LoadRunner] shutdown() progressing ...InterruptedException");
// System.out.println("[LoadRunner] shutdown() progressing ...InterruptedException");
}
}
latch.await();
stopWatch.stop();
System.out.println();
System.out.println();
System.out.println("===============================================================");
System.out.println(" think time : " + thinkTime + " ms");
System.out.println(" thread count : " + threadCount);
System.out.println(" loop count : " + loopCount);
System.out.println(" total request : " + (threadCount * loopCount));
System.out.println(" elapsed : " + stopWatch.toString());
System.out.println(" tps : " + new Integer(threadCount * loopCount * 1000).longValue() / stopWatch.getTime());
System.out.println("===============================================================");
System.out.println();
// System.out.println();
// System.out.println();
// System.out.println("===============================================================");
// System.out.println(" think time : " + thinkTime + " ms");
// System.out.println(" thread count : " + threadCount);
// System.out.println(" loop count : " + loopCount);
// System.out.println(" total request : " + (threadCount * loopCount));
// System.out.println(" elapsed : " + stopWatch.toString());
// System.out.println(" tps : " + new Integer(threadCount * loopCount * 1000).longValue() / stopWatch.getTime());
// System.out.println("===============================================================");
// System.out.println();
}
@@ -247,13 +247,13 @@ public class LoadRunner2 {
break;
} else if ("".equals(line.trim())) {
} else if ("help".equals(line.trim())) {
System.out.println("===============================================================");
System.out.println("LoadRunner v1.0 (http port = 8282)");
System.out.println("===============================================================");
System.out.println(" help : help");
System.out.println(" start : start [thread count] [loop count] [think time]");
System.out.println(" exit : exit");
System.out.println("");
// System.out.println("===============================================================");
// System.out.println("LoadRunner v1.0 (http port = 8282)");
// System.out.println("===============================================================");
// System.out.println(" help : help");
// System.out.println(" start : start [thread count] [loop count] [think time]");
// System.out.println(" exit : exit");
// System.out.println("");
} else if (line.trim().startsWith("start")) {
String[] tokens = line.trim().split("[ ]+");
if (tokens.length > 1)
@@ -266,11 +266,11 @@ public class LoadRunner2 {
} else if ("exit".equals(line.trim())) {
System.exit(1);
} else {
System.out.println("Unknow command. type help.");
// System.out.println("Unknow command. type help.");
}
} catch(Exception e) {
// e.printStackTrace();
System.out.println("Exception");
// System.out.println("Exception");
}
}
}
@@ -293,14 +293,14 @@ public class LoadRunner2 {
}
}
catch(Exception e) {
System.out.println(e.toString());
// System.out.println(e.toString());
}
finally {
try {
br.close();
}
catch(Exception e) {
System.out.println(e.toString());
// System.out.println(e.toString());
}
}
@@ -371,10 +371,10 @@ public class LoadRunner2 {
if (args.length == 2) {
hostname = args[0];
System.out.println("remote host : " + hostname);
// System.out.println("remote host : " + hostname);
filename = args[1];
} else {
System.out.println("Usage : loadrunner [ip] [file]");
// System.out.println("Usage : loadrunner [ip] [file]");
return;
}
@@ -623,14 +623,14 @@ public class ExpiringMap<K, V> implements Map<K, V> {
ExpiringMap m = new ExpiringMap(1);
String key ="aaaaaaa";
m.put(key,key);
System.out.println(m.get(key));
// System.out.println(m.get(key));
Thread.sleep(1 * 1000L);
System.out.println(m.get(key));
// System.out.println(m.get(key));
Thread.sleep(1 * 1000L);
System.out.println(m.get(key));
// System.out.println(m.get(key));
Thread.sleep(1 * 1000L);
System.out.println(m.get(key));
// System.out.println(m.get(key));
Thread.sleep(1 * 1000L);
System.out.println(m.get(key));
// System.out.println(m.get(key));
}
}
@@ -18,7 +18,7 @@ public class TelnetAdminHandler extends ProtocolHandler {
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
String msg = message.toString().trim();
System.out.println("<RECV> " + msg);
// System.out.println("<RECV> " + msg);
if ("quit".equals(msg) || "exit".equals(msg)) {
session.write("bye......");
@@ -42,10 +42,10 @@ public class Server {
acceptor
.bind(new InetSocketAddress(port), new ServerHandler(), cfg);
System.out.println("Server now listening on port " + port);
// System.out.println("Server now listening on port " + port);
} catch (Exception ex) {
// ex.printStackTrace();
System.out.println("Error" + ex.toString());
// System.out.println("Error" + ex.toString());
}
}
}
@@ -61,7 +61,7 @@ public class HttpResponse {
try {
body.write(b);
} catch (IOException ex) {
System.out.println("appendBody error");
// System.out.println("appendBody error");
}
}
@@ -69,7 +69,7 @@ public class HttpResponse {
try {
body.write(s.getBytes());
} catch (IOException ex) {
System.out.println("appendBody string error");
// System.out.println("appendBody string error");
}
}
@@ -10,8 +10,8 @@ public class NetAdmin {
if (args.length == 1) {
hostname = args[0];
} else if (args.length == 2) {
System.out.println("args[0] " + args[0]);
System.out.println("args[1] " + args[1]);
// System.out.println("args[0] " + args[0]);
// System.out.println("args[1] " + args[1]);
hostname = args[0];
port = Integer.parseInt(args[1]);
}
@@ -32,6 +32,6 @@ public class NetAdmin {
sb.append("set connection - Max Connection 수 조정 ( netadmin set connection adapterName #OfConnection )");
sb.append("set thread - Max Thread 수 조정 ( netadmin set thread adapterName #OfSession )");
sb.append("set trace - 소켓어뎁터 추적관리 레벨 조정 ( netadmin set trace adapterName [ 0 | 1 | 2] )\n");
System.out.println(sb.toString());
// System.out.println(sb.toString());
}
}
@@ -64,7 +64,7 @@ public class Shell {
public void loop() throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println(welcomeMsg);
// System.out.println(welcomeMsg);
do {
// set prompt
prompt = "\nnetadmin-" + hostname + ":" + port + "| " + context + "> ";
@@ -74,7 +74,7 @@ public class Shell {
try {
if(line != null) process(line);
} catch(Exception e) {
System.out.println("loop error "+ e.toString());
// System.out.println("loop error "+ e.toString());
}
} while(true);
}
@@ -87,9 +87,9 @@ public class Shell {
SimpleFuture future = admin.stop();
future.join();
} catch(Exception e) {
System.out.println("stop error");
// System.out.println("stop error");
}
System.out.println(byeMsg);
// System.out.println(byeMsg);
System.exit(1);
}
@@ -103,6 +103,6 @@ public class Shell {
context = res;
}
}
System.out.println(new String(response));
// System.out.println(new String(response));
}
}
@@ -393,7 +393,7 @@ public class WCASessionThread implements Runnable {
myLog.logMsg(MyLog.WARN, "myLog Path : " + sMyLogPath);
}
catch(Exception ignore) {
System.out.println("WCASessionThread> Exception Msg = " + ignore.toString());
// System.out.println("WCASessionThread> Exception Msg = " + ignore.toString());
}
/* 20080523 End */
}
@@ -739,7 +739,7 @@ public class WCASessionThread implements Runnable {
}
}
catch (Exception ignore) {
System.out.println("WCASessionThread:run> Exception Msg = " + ignore.toString());
// System.out.println("WCASessionThread:run> Exception Msg = " + ignore.toString());
}
/* 20080523 SMS 로그 추가 끝 */
}
@@ -382,7 +382,7 @@ public class WCAQueue {
if (pBuff.length >= WCAHeader.WCA_HEADER_LEN + 3)
System.arraycopy(pBuff, WCAHeader.WCA_HEADER_LEN, pDFSBuff, 0, pDFSBuff.length);
System.out.println("------> DFS : " + new String(pDFSBuff));
// System.out.println("------> DFS : " + new String(pDFSBuff));
if((new String(pDFSBuff)).equals(new String(WCADefine.DFS_MSG)))
bDFSFlag = true;
else bDFSFlag = false;
@@ -544,7 +544,7 @@ public class MyLog {
logMsg("LOG LEVLE = " + nLogLevel + ", LOG SIZE = " + MAX_LOG_FILE_SIZE + "M");
}
catch (Exception e) {
System.out.println("openLogStream error -"+e.toString());
// System.out.println("openLogStream error -"+e.toString());
}
}
@@ -559,7 +559,7 @@ public class MyLog {
}
}
catch (Exception e) {
System.out.println("closeLogStream error -"+e.toString());
// System.out.println("closeLogStream error -"+e.toString());
}
}
@@ -0,0 +1,56 @@
package com.eactive.eai.agent.inflow;
import com.eactive.eai.agent.command.Command;
import com.eactive.eai.agent.command.CommandException;
import com.eactive.eai.common.inflow.InflowControlManager;
import com.eactive.eai.common.util.Logger;
public class ReloadInflowGroupControlCommand extends Command {
private static final long serialVersionUID = 1L;
public ReloadInflowGroupControlCommand() {
super("ReloadInflowGroupControlCommand");
}
public Object execute() throws CommandException {
Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
if (logger.isInfo())
logger.info(this.name + " is executed");
if (!(args instanceof String)) {
String rspErrorCode = "RECEAIMCM001";
String msg = makeException(rspErrorCode, null);
if (logger.isError())
logger.error(msg);
throw new CommandException(msg);
}
String keyName = (String) args;
try {
InflowControlManager manager = InflowControlManager.getInstance();
if (keyName != null) {
if ("ALL".equals(keyName)) {
manager.reloadGroup();
if (logger.isWarn())
logger.warn(this.name + "] all group rule Reload.");
} else {
manager.reloadGroup(keyName);
if (logger.isWarn())
logger.warn(this.name + "] group " + keyName + " Reload.");
}
}
} catch (Exception e) {
String rspErrorCode = "RECEAIMCM002";
String msg = makeException(rspErrorCode, e);
if (logger.isError())
logger.error(msg, e);
throw new CommandException(msg);
}
return "success";
}
}
@@ -0,0 +1,45 @@
package com.eactive.eai.agent.inflow;
import com.eactive.eai.agent.command.Command;
import com.eactive.eai.agent.command.CommandException;
import com.eactive.eai.common.inflow.InflowControlManager;
import com.eactive.eai.common.util.Logger;
public class RemoveInflowGroupControlCommand extends Command {
private static final long serialVersionUID = 1L;
public RemoveInflowGroupControlCommand() {
super("RemoveInflowGroupControlCommand");
}
public Object execute() throws CommandException {
Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
if (logger.isInfo())
logger.info(this.name + " is executed");
if (!(args instanceof String)) {
String rspErrorCode = "RECEAIMCM001";
String msg = makeException(rspErrorCode, null);
if (logger.isError())
logger.error(msg);
throw new CommandException(msg);
}
String key = (String) args;
try {
InflowControlManager manager = InflowControlManager.getInstance();
manager.removeGroup(key);
if (logger.isWarn())
logger.warn(this.name + "] group " + key + " removed.");
} catch (Exception e) {
String rspErrorCode = "RECEAIMCM002";
String msg = makeException(rspErrorCode, e);
if (logger.isError())
logger.error(msg, e);
throw new CommandException(msg);
}
return "success";
}
}
@@ -41,6 +41,10 @@ public class ReloadPropertyCommand extends Command {
if (logger.isWarn())
logger.warn(this.name + "] " + keyName + " Reload.");
}
if (keyName.startsWith("FileLogger{")) {
com.eactive.eai.common.util.Logger.setLoggerLevel(keyName);
}
}
} catch (Exception e) {
String rspErrorCode = "RECEAIMCM002";
@@ -31,6 +31,6 @@ public interface HttpClientAccessTokenServiceByDB {
* @return 반환 AccessTokenVO
* @exception Exception 수동 시스템 통신 발생
**/
public Object execute(String name, Properties adapterProp, OutboundOAuthCredentialVo oAuthCredentialVo) throws Exception ;
public Object execute(String adapterGroupName, Properties adapterProp, OutboundOAuthCredentialVo oAuthCredentialVo) throws Exception ;
}
@@ -1,6 +1,6 @@
package com.eactive.eai.authoutbound.client.impl;
import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
@@ -96,8 +96,7 @@ public class HttpClientAccessTokenServiceWithBase64Header implements HttpClientA
if (!UrlUtils.isAbsoluteUrl(uri)) {
uri = appendPath(adapterUrl, uri);
}
//String contentType = "application/json;"; // comment by jwhong
String contentType = "application/x-www-form-urlencoded"; // 광주은행 나이스지키미
String contentType = "application/json;";
Charset charset;
if (StringUtils.isNotBlank(encode)) {
@@ -114,9 +113,7 @@ public class HttpClientAccessTokenServiceWithBase64Header implements HttpClientA
"uri:{}, charset:{}, transactionTimeout:{}, connectionTimeout:{}, useForwardProxy:{}, forwardProxyUrl:{}",
uri, encode, timeout, connectionTimeout, useForwardProxy, forwardProxyUrl);
// mTLS config with default connection parameters
boolean useMtls = StringUtils.equalsIgnoreCase(adapterProp.getProperty(HttpClientAdapterServiceKey.USE_MTLS),
"Y");
@@ -237,17 +234,19 @@ public class HttpClientAccessTokenServiceWithBase64Header implements HttpClientA
logger.debug("contentType = [" + contentType + "]");
logger.debug("encode = [" + encode + "]");
OAuth2AccessTokenVO accessToken = new OAuth2AccessTokenVO();
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
if (response.getCode() != 200) {
throw new Exception("OAuth token receive status fail value= " + response.getCode());
}
logger.info("HttpClientAccessTokenServiceWithBase64Header==>" + response.getCode());
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, encode);
logger.debug("oauthToken RECV = [" + responseString + "]");
logger.debug("Base64Header oauthToken RECV = [" + responseString + "]");
if (StringUtils.isNotBlank(responseString)) {
OAuth2AccessTokenVO accessToken = new OAuth2AccessTokenVO();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode responseJSON = objectMapper.readTree(responseString);
@@ -272,6 +271,10 @@ public class HttpClientAccessTokenServiceWithBase64Header implements HttpClientA
} else {
throw new Exception("oauth token return null");
}
} catch (Exception e) {
e.printStackTrace();
logger.error("[HttpClientAccessTokenServiceWithBase64Header] retrieve accessToken exception :" + e.getMessage());
return accessToken;
}
}
}
@@ -0,0 +1,308 @@
package com.eactive.eai.authoutbound.client.impl;
import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.adapter.http.secure.HttpClient5SSLContextFactory;
import com.eactive.eai.authoutbound.OutboundOAuthCredentialVo;
import com.eactive.eai.authoutbound.client.HttpClientAccessTokenServiceByDB;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoManager;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
import com.eactive.eai.util.TestModeChecker;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.openbanking.eai.common.token.AccessTokenVO;
import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.TrustAllStrategy;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.util.Timeout;
import org.springframework.security.web.util.UrlUtils;
import tcseed.base64;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.*;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
/**
* 1. 기능 : HTTP 컴포넌트를 POST 방식으로 호출할 있는 기능을 제공한다. 2. 처리 개요 : * - 2009.11.24
* retry 로직 제거 : 요청 3. 주의사항
*
* @author :
* @version : v 1.0.0
* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
* @since :
*
*/
public class HttpClientAccessTokenServiceWithBase64NiceOn implements HttpClientAccessTokenServiceByDB {
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
private static boolean testMode = TestModeChecker.isTestMode();
/**
* 1. 기능 : 법인검증 토큰 발급에 사용 2. 처리 개요 : - 속성 정보를 설정 하고 토큰 발급 URL 호출 한다. 3. 주의사항
* - JSON 방식
* - ( Header Authorization Basic <base64_Encode(client_id:client_secret)> ) 으로 구성
* @param adapterProp Http Adapter 속성 정보
* @return 반환 AccessTokenVO
* @exception Exception 수동 시스템 통신 발생
**/
public AccessTokenVO execute(String name, Properties adapterProp, OutboundOAuthCredentialVo oAuthCredentialVo)
throws Exception {
AdapterGroupVO gvo = AdapterManager.getInstance().getAdapterGroupVO(name);
String adapterUrl = adapterProp.getProperty("URL");
String encode = gvo.getMessageEncode();
String timeoutTemp = adapterProp.getProperty("HTTP_TIME_OUT");
if (StringUtils.isBlank(timeoutTemp)) {
timeoutTemp = "30000";
}
String connectionTimeoutTemp = adapterProp.getProperty("CONNECTION_TIMEOUT");
if (StringUtils.isBlank(connectionTimeoutTemp)) {
connectionTimeoutTemp = "30000";
}
int timeout = Integer.parseInt(timeoutTemp);
int connectionTimeout = Integer.parseInt(connectionTimeoutTemp);
long currentTime = System.currentTimeMillis();
String uri = oAuthCredentialVo.getUrl();
if (!UrlUtils.isAbsoluteUrl(uri)) {
uri = appendPath(adapterUrl, uri);
}
String contentType = "application/x-www-form-urlencoded"; // 광주은행 나이스지키미
Charset charset;
if (StringUtils.isNotBlank(encode)) {
charset = Charset.forName(encode);
} else {
charset = Charset.defaultCharset();
encode = charset.toString();
}
boolean useForwardProxy = StringUtils.equalsIgnoreCase(adapterProp.getProperty("FORWARD_PROXY_USE_YN"), "Y");
String forwardProxyUrl = adapterProp.getProperty("FORWARD_PROXY_URL");
logger.debug(
"uri:{}, charset:{}, transactionTimeout:{}, connectionTimeout:{}, useForwardProxy:{}, forwardProxyUrl:{}",
uri, encode, timeout, connectionTimeout, useForwardProxy, forwardProxyUrl);
List<NameValuePair> formParams = new ArrayList<>();
//formParams.add(new BasicNameValuePair("client_id", oAuthCredentialVo.getClientId()));
//formParams.add(new BasicNameValuePair("client_secret", oAuthCredentialVo.getClientSecret()));
formParams.add(new BasicNameValuePair("grant_type", oAuthCredentialVo.getGrantType()));
formParams.add(new BasicNameValuePair("scope", oAuthCredentialVo.getScope()));
//String postParameters = "grant_type=" + oAuthCredentialVo.getGrantType() + "&scope=" + oAuthCredentialVo.getScope();
// mTLS config with default connection parameters
boolean useMtls = StringUtils.equalsIgnoreCase(adapterProp.getProperty(HttpClientAdapterServiceKey.USE_MTLS),
"Y");
AdapterGroupVO adapterGroup = AdapterManager.getInstance().getAdapterGroup(name);
String clientId = adapterGroup.getClientId();
if (logger.isInfo()) {
logger.info("MTLS adapterGroupName. : {}, useMtls. : {}, clientId : {}", name, useMtls, clientId);
}
int maxTotalConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_TOTAL_CONNECTIONS;
int maxHostConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_CONNECTION_PER_HOST;
HttpOutTlsInfoVO mtlsInfo = null;
SSLContext sslContext = null;
PoolingHttpClientConnectionManagerBuilder cmBuilder = PoolingHttpClientConnectionManagerBuilder.create();
PoolingHttpClientConnectionManager connectionManager = null;
try {
if (useMtls) {
HttpOutTlsInfoManager tlsManager = HttpOutTlsInfoManager.getInstance();
if (StringUtils.isNotEmpty(clientId)) {
mtlsInfo = tlsManager.getHttpOutTlsInfo(clientId);
}
}
if (useMtls && mtlsInfo != null) {
String storeType = mtlsInfo.getStoreType();
String keyStoreInfo = mtlsInfo.getKeystoreInfo();
String keyStorePassword = mtlsInfo.getKeystorePassword();
String trustStoreInfo = mtlsInfo.getTruststoreInfo();
String trustStorePassword = mtlsInfo.getTruststorePassword();
String[] tlsVersions = null;
String[] cipherSuites = null;
if (StringUtils.isAnyEmpty(keyStoreInfo, keyStorePassword)) {
throw new Exception("mTLS keyStore config error");
}
boolean skipTrust = false;
if (StringUtils.isAnyEmpty(trustStoreInfo, trustStorePassword)) {
if (logger.isWarn())
logger.warn("Skip trustStore validation adapterGroupName : " + name);
skipTrust = true;
}
sslContext = HttpClient5SSLContextFactory.createMTLSContextFromContent(storeType, keyStoreInfo,
keyStorePassword, trustStoreInfo, trustStorePassword, skipTrust, tlsVersions, cipherSuites);
SSLConnectionSocketFactory sslSocketFactory = null;
if (testMode) {
sslSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
} else {
sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
}
cmBuilder.setSSLSocketFactory(sslSocketFactory);
} else {
sslContext = SSLContextBuilder.create().loadTrustMaterial(new TrustAllStrategy()).build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
cmBuilder.setSSLSocketFactory(csf);
}
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException
| IOException | UnrecoverableKeyException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
connectionManager = cmBuilder.build();
connectionManager.setMaxTotal(maxTotalConnections);
connectionManager.setDefaultMaxPerRoute(maxHostConnections);
try (CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();) {
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(new UrlEncodedFormEntity(formParams, charset));
//httpPost.setEntity(new StringEntity(postParameters, StandardCharsets.UTF_8));
httpPost.setHeader("Content-Type", contentType+";charset=" + encode); // 중간에 ; 주어야
//HTTP HEADER에 client id, client secret를 base64Encode 추가
String cId = oAuthCredentialVo.getClientId();
String cSecret = oAuthCredentialVo.getClientSecret();
String authValue = cId + ":" + cSecret;
String encodedAuth = Base64.getEncoder().encodeToString(authValue.getBytes(StandardCharsets.UTF_8));
httpPost.setHeader("Authorization","Basic "+ encodedAuth);
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
if (useForwardProxy) {
java.net.URL url = new java.net.URL(forwardProxyUrl);
// 프로토콜, 호스트, 포트 추출
String protocol = url.getProtocol();
String host = url.getHost();
int port = url.getPort();
HttpHost proxy = new HttpHost(protocol, host, port);
requestConfigBuilder.setProxy(proxy);
}
RequestConfig requestConfig = requestConfigBuilder
.setConnectTimeout(Timeout.ofMilliseconds(connectionTimeout))
.setResponseTimeout(Timeout.ofMilliseconds(timeout)).build();
httpPost.setConfig(requestConfig);
logger.debug("uri = [" + uri + "]");
logger.debug("oauthClientId = [" + oAuthCredentialVo.getClientId() + "]");
logger.debug("oauthClientSecret = [" + oAuthCredentialVo.getClientSecret() + "]");
logger.debug("oauthScope = [" + oAuthCredentialVo.getScope() + "]");
logger.debug("oauthGrantType = [" + oAuthCredentialVo.getGrantType() + "]");
logger.debug("oauthauthValue = [" + authValue + "]");
logger.debug("oauthauthEncodedAuth = [" + encodedAuth + "]");
logger.debug("contentType = [" + contentType + "]");
logger.debug("encode = [" + encode + "]");
OAuth2AccessTokenVO accessToken = new OAuth2AccessTokenVO();
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
if (response.getCode() != 200) {
throw new Exception("NiceOn token receive status fail value== " + response.getCode());
}
logger.info("HttpClientAccessTokenServiceWithBase64NiceOn==>" + response.getCode());
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, encode);
logger.debug("Base64NiceOn oauthToken RECV == [" + responseString + "]");
if (StringUtils.isNotBlank(responseString)) {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode responseJSONRtn = objectMapper.readTree(responseString);
JsonNode responseJSON = null;
String gwRsltCd = responseJSONRtn.get("dataHeader").get("GW_RSLT_CD").asText();
if ("1200".equals(gwRsltCd)) {
responseJSON = responseJSONRtn.get("dataBody");
}
if (responseJSON.has("access_token") && responseJSON.has("token_type")
&& responseJSON.has("expires_in") && responseJSON.has("scope")) {
accessToken.setAccessToken(responseJSON.get("access_token").asText());
accessToken.setTokenType(responseJSON.get("token_type").asText());
long expiresIn = responseJSON.get("expires_in").asLong();
accessToken.setExpiration(new Date(currentTime + expiresIn * 1000L));
accessToken.setScope(responseJSON.get("scope").asText());
accessToken.setClientId(cId);
}
if (responseJSON.has("client_use_code")) {
accessToken.setClientUseCode(responseJSON.get("client_use_code").asText());
}
logger.debug("NiceOn oauthToken =" + accessToken.toString());
return accessToken;
} else {
throw new Exception("oauth token return null");
}
} catch (Exception e) {
e.printStackTrace();
logger.error("[HttpClientAccessTokenServiceWithBase64NiceOn] retrieve accessToken exception :" + e.getMessage());
return accessToken;
}
}
}
/**
* URL에 경로를 추가합니다. 중복되는 슬래시를 방지합니다.
*
* @param baseUrl 기본 URL
* @param pathToAdd 추가할 경로
* @return 완성된 URL 문자열
*/
public static String appendPath(String baseUrl, String pathToAdd) {
if (!baseUrl.endsWith("/") && !pathToAdd.startsWith("/")) {
return baseUrl + "/" + pathToAdd;
} else if (baseUrl.endsWith("/") && pathToAdd.startsWith("/")) {
return baseUrl + pathToAdd.substring(1);
} else {
return baseUrl + pathToAdd;
}
}
}
@@ -0,0 +1,27 @@
package com.eactive.eai.authoutbound.client.impl;
import java.util.Properties;
import com.eactive.eai.authoutbound.OutboundOAuthCredentialVo;
import com.eactive.eai.authoutbound.client.HttpClientAccessTokenServiceByDB;
import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
public class HttpClientAccessTokenServiceWithFixedToken implements HttpClientAccessTokenServiceByDB {
@Override
public Object execute(String adapterGroupName, Properties adapterProp, OutboundOAuthCredentialVo oAuthCredentialVo)
throws Exception {
OAuth2AccessTokenVO fixedAccessToken = new OAuth2AccessTokenVO();
fixedAccessToken.setAccessToken(oAuthCredentialVo.getClientSecret());
fixedAccessToken.setClientId("none");
fixedAccessToken.setClientUseCode("anyone");
fixedAccessToken.setExpiresIn(60 * 60 * 24 * 365); //1년
fixedAccessToken.setScope("none");
fixedAccessToken.setTokenType("fixed");
return fixedAccessToken;
}
}
@@ -193,7 +193,8 @@ public class HttpClientAccessTokenServiceWithParam implements HttpClientAccessTo
connectionManager.setMaxTotal(maxTotalConnections);
connectionManager.setDefaultMaxPerRoute(maxHostConnections);
try (CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();) {
// http header에 zip 제외하려면 disableContentCompression() 추가해서 제외할것
try (CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).disableContentCompression().disableDefaultUserAgent().build();) {
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(new UrlEncodedFormEntity(formParams, charset));
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=" + encode);
@@ -227,10 +228,10 @@ public class HttpClientAccessTokenServiceWithParam implements HttpClientAccessTo
OAuth2AccessTokenVO accessToken = new OAuth2AccessTokenVO();
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
if (response.getCode() != 200) {
System.out.println("OAuth token receive status fail value= "+ response.getCode());
logger.info("OAuth token receive status fail value= " + response.getCode());
throw new Exception("OAuth token receive status fail value= " + response.getCode());
}
System.out.println("OAuth token receive status SUCCESS value= "+ response.getCode());
logger.info("OAuth token receive status SUCCESS value= "+ response.getCode());
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, encode);
@@ -31,9 +31,15 @@ public class ScopeDAO extends BaseDAO {
Map<String, HashSet<String>> clientEntitymap = new HashMap<>();
scopeEntities.forEach(scopeEntity -> {
HashSet<String> set = new HashSet<>();
String scopeId = scopeEntity.getId().getBzwksvckeyname() + scopeEntity.getId().getScopeid();
clientEntitymap.put(scopeId, set);
String apiId = scopeEntity.getId().getBzwksvckeyname();
HashSet<String> scopeSet = clientEntitymap.get(apiId);
if (scopeSet == null) {
scopeSet = new HashSet<String>();
clientEntitymap.put(apiId, scopeSet);
}
String scopeId = scopeEntity.getId().getScopeid();
clientEntitymap.get(apiId).add(scopeId);
// clientEntitymap.put(scopeId, set);
});
return clientEntitymap;
@@ -48,7 +54,7 @@ public class ScopeDAO extends BaseDAO {
ScopeEntity scopeEntity = scopeLoader.findByIdBzwksvckeyname(apiId);
scopeSet.add(scopeEntity.getId().getBzwksvckeyname());
scopeSet.add(scopeEntity.getId().getScopeid());
return scopeSet;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAIAUC001"));
@@ -0,0 +1,49 @@
package com.eactive.eai.authserver.service;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonProperty;
public class BearerTokenInfo {
@JsonProperty("client_id")
private String clientId;
private Long expiresIn;
private Long expiresAt;
private Set<String> scopeSet;
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public Long getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Long expiresIn) {
this.expiresIn = expiresIn;
}
public Long getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(Long expiresIn) {
this.expiresAt = System.currentTimeMillis() + (expiresIn * 1000);
}
public Set<String> getScopeSet() {
return scopeSet;
}
public void setScopeSet(Set<String> scopeSet) {
this.scopeSet = scopeSet;
}
public boolean isExpired() {
return System.currentTimeMillis() > expiresAt;
}
}
@@ -0,0 +1,73 @@
package com.eactive.eai.authserver.service;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.eactive.eai.common.session.SessionManager;
import com.eactive.eai.common.session.SessionManagerForIgnite;
@Service
public class BearerTokenService {
public String generateCAToken(String clientId, Long expiresIn, Set<String> scopeSet) {
String token = UUID.randomUUID().toString();
BearerTokenInfo CATokenInfo = new BearerTokenInfo();
CATokenInfo.setClientId(clientId);
CATokenInfo.setExpiresIn(expiresIn);
CATokenInfo.setExpiresAt(expiresIn);
CATokenInfo.setScopeSet(scopeSet);
//CATokenStore.put(token, CATokenInfo);
SessionManager.getInstance().putCAToken(token, CATokenInfo);
return token;
}
public boolean validateCA(String token) {
BearerTokenInfo CATokenInfo = SessionManager.getInstance().getCAToken(token);
if (CATokenInfo == null) return false;
if (CATokenInfo.isExpired()) {
SessionManager.getInstance().removeCAToken(token);
return false;
}else {
return true;
}
}
public String getClientIdFromCA(String token) {
BearerTokenInfo CATokenInfo = SessionManager.getInstance().getCAToken(token);
return CATokenInfo.getClientId();
}
// private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// private static final SecureRandom secureRandom = new SecureRandom();
//
// public static String generateTokenString(int length) {
// // Java 8의 IntStream과 Collectors.joining을 사용한 효율적인 방법
// return IntStream.range(0, length)
// .map(i -> secureRandom.nextInt(CHARACTERS.length()))
// .mapToObj(CHARACTERS::charAt)
// .map(String::valueOf)
// .collect(Collectors.joining());
// }
}
@@ -8,4 +8,5 @@ public interface TransactionContextKeys {
public static final String GUID = "GUID";
public static final String INTERFACE_ID = "INTERFACE_ID";
public static final String TRANSACTION_UUID = "TRANSACTION_UUID";
public static final String X_LOAN_TOKEN = "X-LOAN-TOKEN";
}
@@ -6,6 +6,11 @@ import com.eactive.eai.common.lifecycle.LifecycleListener;
import com.eactive.eai.common.lifecycle.LifecycleSupport;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.custom.alarm.AlarmStateManager;
import com.eactive.eai.custom.alarm.condition.AlarmCondition;
import com.eactive.eai.custom.alarm.event.AlarmEvent;
import com.eactive.eai.custom.alarm.key.CoreAlarmKey;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
@@ -71,6 +76,28 @@ public class CircuitBreakerManager implements Lifecycle {
circuitBreakerRegistry = CircuitBreakerRegistry.of(config);
TaggedCircuitBreakerMetrics.ofCircuitBreakerRegistry(circuitBreakerRegistry).bindTo(meterRegistry);
circuitBreakerRegistry.getEventPublisher().onEntryAdded(event -> {
CircuitBreaker cb = event.getAddedEntry();
String apiId = cb.getName();
// 여기서 상태 변경 리스너를 번만 등록
cb.getEventPublisher().onStateTransition(stateEvent -> {
CircuitBreaker.State from = stateEvent.getStateTransition().getFromState();
CircuitBreaker.State to = stateEvent.getStateTransition().getToState();
AlarmEvent alarmEvent = AlarmEvent.builder().key(CoreAlarmKey.CircuitBreaker)
.condition(AlarmCondition.builder().build())
.message(String.format("CircuitBreaker state changed. apiId=%s, %s -> %s", apiId, from, to))
.build();
AlarmStateManager.getAlarmStateManager().onEvnet(alarmEvent);
logger.warn("CircuitBreaker state changed. apiId={}, {} -> {}", apiId, from, to);
});
logger.info("Registered StateTransition listener for: {}", apiId);
});
logger.info("init CircuitBreaker - "+config);
}
@@ -7,7 +7,7 @@ public class PrometheusController {
public PrometheusController() {
System.out.println("init");
// System.out.println("init");
}
// @GetMapping("/prometheus")
@@ -6,4 +6,10 @@ public interface Bucket {
public InflowTargetVO getAdapterInflowThreashold(String adapter);
public InflowTargetVO getInterfaceInflowThreashold(String inter);
public InflowTargetVO getInflowThreashold(String inter);
// 그룹 관련 메서드
/** @return null이면 통과, "PER_SECOND" 또는 "THRESHOLD"면 해당 버킷에서 차단 */
public String isGroupPass(String groupId);
public InflowGroupVO getGroupInflowThreshold(String groupId);
public String getGroupIdByInterface(String interfaceId);
}
@@ -0,0 +1,84 @@
package com.eactive.eai.common.inflow;
import io.github.bucket4j.local.LocalBucket;
/**
* 그룹 유량제어 전용 버킷
* 초당 임계치와 추가 임계치를 별도 버킷으로 관리하여 개별 토큰 조회 가능
*/
public class CustomGroupBucket {
private LocalBucket perSecondBucket; // 초당 임계치 버킷 (null 가능)
private LocalBucket thresholdBucket; // 추가 임계치 버킷 (null 가능)
private InflowGroupVO groupVo;
public CustomGroupBucket(LocalBucket perSecondBucket, LocalBucket thresholdBucket, InflowGroupVO groupVo) {
this.perSecondBucket = perSecondBucket;
this.thresholdBucket = thresholdBucket;
this.groupVo = groupVo;
}
/** 소비 결과: 성공 */
public static final String RESULT_PASS = null;
/** 소비 결과: 초당 임계치 초과 */
public static final String RESULT_BLOCKED_PER_SECOND = "PER_SECOND";
/** 소비 결과: 추가 임계치 초과 */
public static final String RESULT_BLOCKED_THRESHOLD = "THRESHOLD";
/**
* 버킷 모두에서 토큰 소비 시도
* @return null이면 성공, "PER_SECOND" 또는 "THRESHOLD" 해당 버킷에서 차단
*/
public String tryConsume() {
boolean perSecondPass = (perSecondBucket == null) || perSecondBucket.tryConsume(1);
if (!perSecondPass) {
return RESULT_BLOCKED_PER_SECOND;
}
boolean thresholdPass = (thresholdBucket == null) || thresholdBucket.tryConsume(1);
if (!thresholdPass) {
// 초당 버킷에서 이미 소비했으므로 롤백은 불가 (Token Bucket 특성상)
// 하지만 초당 버킷은 빠르게 리필되므로 실질적 영향 미미
return RESULT_BLOCKED_THRESHOLD;
}
return RESULT_PASS;
}
/**
* 초당 임계치 버킷의 사용 가능한 토큰
*/
public long getPerSecondAvailableTokens() {
return (perSecondBucket != null) ? perSecondBucket.getAvailableTokens() : -1;
}
/**
* 추가 임계치 버킷의 사용 가능한 토큰
*/
public long getThresholdAvailableTokens() {
return (thresholdBucket != null) ? thresholdBucket.getAvailableTokens() : -1;
}
public LocalBucket getPerSecondBucket() {
return perSecondBucket;
}
public void setPerSecondBucket(LocalBucket perSecondBucket) {
this.perSecondBucket = perSecondBucket;
}
public LocalBucket getThresholdBucket() {
return thresholdBucket;
}
public void setThresholdBucket(LocalBucket thresholdBucket) {
this.thresholdBucket = thresholdBucket;
}
public InflowGroupVO getGroupVo() {
return groupVo;
}
public void setGroupVo(InflowGroupVO groupVo) {
this.groupVo = groupVo;
}
}
@@ -12,16 +12,21 @@ import org.springframework.transaction.annotation.Transactional;
import com.eactive.eai.common.dao.BaseDAO;
import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.inflow.loader.InflowControlGroupLoader;
import com.eactive.eai.common.inflow.loader.InflowControlGroupMappingLoader;
import com.eactive.eai.common.inflow.loader.InflowControlLoader;
import com.eactive.eai.common.inflow.loader.InflowControlLogLogger;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.data.entity.onl.inflow.InflowControl;
import com.eactive.eai.data.entity.onl.inflow.InflowControlGroup;
import com.eactive.eai.data.entity.onl.inflow.InflowControlGroupMapping;
import com.eactive.eai.data.entity.onl.inflow.InflowControlLog;
import com.eactive.eai.data.entity.onl.inflow.InflowControlLogId;
@Service
@Transactional
public class InflowControlDAO extends BaseDAO {
private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
@Autowired
@@ -30,6 +35,12 @@ public class InflowControlDAO extends BaseDAO {
@Autowired
private InflowControlLogLogger inflowControlLogLogger;
@Autowired
private InflowControlGroupLoader inflowControlGroupLoader;
@Autowired
private InflowControlGroupMappingLoader inflowControlGroupMappingLoader;
public List<InflowTargetVO> getInflowAdapterList() throws DAOException {
return getInflowList("01");
}
@@ -132,4 +143,90 @@ public class InflowControlDAO extends BaseDAO {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
// ==================== 그룹 관련 메서드 ====================
/**
* 활성화된 유량제어 그룹 목록 조회
*/
public List<InflowGroupVO> getInflowGroupList() throws DAOException {
try {
Iterable<InflowControlGroup> groups = inflowControlGroupLoader.findActiveGroups();
List<InflowGroupVO> groupList = new ArrayList<>();
logger.info("[ @@ Load InflowControlGroup Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControlGroup group : groups) {
InflowGroupVO vo = convertToGroupVO(group);
// 그룹에 속한 인터페이스 목록 조회
Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveByGroupId(group.getGroupId());
for (InflowControlGroupMapping mapping : mappings) {
vo.addInterface(mapping.getInterfaceId());
}
groupList.add(vo);
}
logger.info("[>>Load InflowControlGroup Configuration - ended. count=" + groupList.size() + " ]");
return groupList;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
/**
* 인터페이스ID 그룹ID 매핑 조회
*/
public Map<String, String> getInterfaceToGroupMap() throws DAOException {
try {
Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveMappings();
Map<String, String> interfaceToGroupMap = new HashMap<>();
logger.info("[ @@ Load InterfaceToGroupMap Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControlGroupMapping mapping : mappings) {
interfaceToGroupMap.put(mapping.getInterfaceId(), mapping.getGroupId());
}
logger.info("[>>Load InterfaceToGroupMap Configuration - ended. count=" + interfaceToGroupMap.size() + " ]");
return interfaceToGroupMap;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
/**
* 특정 그룹 조회
*/
public Map<String, InflowGroupVO> getInflowTargetByGroup(String groupId) throws DAOException {
try {
Iterable<InflowControlGroup> groups = inflowControlGroupLoader.findByConditions(groupId);
Map<String, InflowGroupVO> groupMap = new HashMap<>();
logger.info("[ @@ Load InflowControlGroup getInflowTargetByGroup Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControlGroup group : groups) {
InflowGroupVO vo = convertToGroupVO(group);
// 그룹에 속한 인터페이스 목록 조회
Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveByGroupId(group.getGroupId());
for (InflowControlGroupMapping mapping : mappings) {
vo.addInterface(mapping.getInterfaceId());
}
groupMap.put(vo.getGroupId(), vo);
}
logger.info("[>>Load InflowControlGroup getInflowTargetByGroup Configuration - ended ]");
return groupMap;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
/**
* Entity VO 변환
*/
private InflowGroupVO convertToGroupVO(InflowControlGroup group) {
InflowGroupVO vo = new InflowGroupVO();
vo.setGroupId(group.getGroupId());
vo.setGroupName(group.getGroupName());
vo.setThreshold(group.getThreshold() != null ? group.getThreshold() : 0);
vo.setThresholdPerSecond(group.getThresholdPerSecond() != null ? group.getThresholdPerSecond() : 0);
vo.setThresholdTimeUnit(group.getThresholdTimeUnit());
vo.setActivate(!"0".equals(group.getUseYn()));
return vo;
}
}
@@ -27,6 +27,7 @@ import com.ext.eai.common.stdmessage.STDMessageKeys;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.local.LocalBucket;
import io.github.bucket4j.local.LocalBucketBuilder;
@Component
@@ -40,6 +41,9 @@ public class InflowControlManager implements Lifecycle, Bucket {
private Map<String, CustomBucket> adapterBucketList = new HashMap<>();
private Map<String, CustomBucket> interfaceBucketList = new HashMap<>();
private Map<String, CustomGroupBucket> groupBucketList = new HashMap<>();
private Map<String, String> interfaceToGroupMap = new HashMap<>();
private Map<String, InflowGroupVO> groupVoMap = new HashMap<>();
private boolean started;
private LifecycleSupport lifecycle = new LifecycleSupport(this);
@@ -63,11 +67,9 @@ public class InflowControlManager implements Lifecycle, Bucket {
*/
public static Boolean isTargetOfInflowControl(EAIServerManager eaiServerManager, EAIMessage eaiMessage) {
InterfaceMapper mapper = eaiMessage.getMapper();
String inExDiv = MessageUtil.getInExDivision(mapper.getInExDivision(eaiMessage.getStandardMessage()),
eaiMessage.getInternalExternalDvcd()); // 1|2
String returnType = mapper.getSendRecvDivision(eaiMessage.getStandardMessage()); // S|R
if (STDMessageKeys.DIRECTION_IN.equals(inExDiv) && STDMessageKeys.SEND_RECV_CD_SEND.equals(returnType)) {
if (STDMessageKeys.SEND_RECV_CD_SEND.equals(returnType)) {
return Boolean.valueOf(true);
}
@@ -91,6 +93,7 @@ public class InflowControlManager implements Lifecycle, Bucket {
private void init() throws Exception {
initAdapter();
initInterface();
initGroup();
}
private void initAdapter() throws Exception {
@@ -121,6 +124,33 @@ public class InflowControlManager implements Lifecycle, Bucket {
}
}
private void initGroup() throws Exception {
groupBucketList = new HashMap<>();
interfaceToGroupMap = new HashMap<>();
groupVoMap = new HashMap<>();
List<InflowGroupVO> inflowGroupVoList = inflowControlDAO.getInflowGroupList();
for (InflowGroupVO groupVo : inflowGroupVoList) {
if (isInflowGroupTarget(groupVo)) {
CustomGroupBucket bucket = makeGroupBucket(groupVo);
if (bucket != null) {
groupBucketList.put(groupVo.getGroupId(), bucket);
groupVoMap.put(groupVo.getGroupId(), groupVo);
// 인터페이스 그룹 매핑 등록
for (String interfaceId : groupVo.getInterfaceList()) {
interfaceToGroupMap.put(interfaceId, groupVo.getGroupId());
}
}
}
}
if (logger.isInfo()) {
logger.info("InflowControlManager] initGroup completed. groups=" + groupBucketList.size()
+ ", mappings=" + interfaceToGroupMap.size());
}
}
public synchronized void reloadAdapter() throws Exception {
if (logger.isWarn()) {
logger.warn("InflowControlManager] reload all Started ...");
@@ -200,6 +230,61 @@ public class InflowControlManager implements Lifecycle, Bucket {
}
}
public synchronized void reloadGroup() throws Exception {
if (logger.isWarn()) {
logger.warn("InflowControlManager] reloadGroup all Started ...");
}
initGroup();
if (logger.isWarn()) {
logger.warn("InflowControlManager] reloadGroup all finished ...");
}
}
public synchronized void reloadGroup(String groupId) throws Exception {
if (logger.isWarn()) {
logger.warn("InflowControlManager] reloadGroup Started ... groupId=" + groupId);
}
Map<String, InflowGroupVO> map = inflowControlDAO.getInflowTargetByGroup(groupId);
if (map != null) {
// 기존 그룹에 속한 인터페이스 매핑 제거
Iterator<Map.Entry<String, String>> mappingIt = interfaceToGroupMap.entrySet().iterator();
while (mappingIt.hasNext()) {
Map.Entry<String, String> entry = mappingIt.next();
if (groupId.equals(entry.getValue())) {
mappingIt.remove();
}
}
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
InflowGroupVO groupVo = map.get(key);
if (isInflowGroupTarget(groupVo)) {
CustomGroupBucket bucket = makeGroupBucket(groupVo);
if (bucket != null) {
groupBucketList.put(groupVo.getGroupId(), bucket);
groupVoMap.put(groupVo.getGroupId(), groupVo);
// 인터페이스 그룹 매핑 재등록
for (String interfaceId : groupVo.getInterfaceList()) {
interfaceToGroupMap.put(interfaceId, groupVo.getGroupId());
}
} else {
groupBucketList.remove(groupVo.getGroupId());
groupVoMap.remove(groupVo.getGroupId());
}
} else {
groupBucketList.remove(groupVo.getGroupId());
groupVoMap.remove(groupVo.getGroupId());
}
}
}
if (logger.isWarn()) {
logger.warn("InflowControlManager] reloadGroup finished ...");
}
}
public void stop() throws LifecycleException {
// Validate and update our current component state
if (!started)
@@ -210,6 +295,9 @@ public class InflowControlManager implements Lifecycle, Bucket {
adapterBucketList.clear();
interfaceBucketList.clear();
groupBucketList.clear();
interfaceToGroupMap.clear();
groupVoMap.clear();
started = false;
// Notify our interested LifecycleListeners
@@ -260,6 +348,29 @@ public class InflowControlManager implements Lifecycle, Bucket {
interfaceBucketList.remove(inter);
}
public void removeGroup(String groupId) {
groupBucketList.remove(groupId);
groupVoMap.remove(groupId);
// 해당 그룹에 속한 인터페이스 매핑도 제거
Iterator<Map.Entry<String, String>> it = interfaceToGroupMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
if (groupId.equals(entry.getValue())) {
it.remove();
}
}
}
public String[] getGroupAllKeys() {
Iterator<String> it = this.groupBucketList.keySet().iterator();
String[] groupIds = new String[this.groupBucketList.size()];
for (int i = 0; it.hasNext(); i++) {
groupIds[i] = it.next();
}
Arrays.sort(groupIds);
return groupIds;
}
private CustomBucket makeBucketUsingInflowVO(InflowTargetVO inflowTarget) {
if (InflowControlManager.isInflowTarget(inflowTarget)) {
LocalBucketBuilder builder = Bucket4j.builder();
@@ -278,6 +389,35 @@ public class InflowControlManager implements Lifecycle, Bucket {
return null;
}
/**
* 그룹용 버킷 생성 - 초당/추가 임계치를 별도 버킷으로 분리
*/
private CustomGroupBucket makeGroupBucket(InflowGroupVO groupVo) {
if (!isInflowGroupTarget(groupVo)) {
return null;
}
LocalBucket perSecondBucket = null;
LocalBucket thresholdBucket = null;
// 초당 임계치 버킷 (별도)
if (groupVo.getThresholdPerSecond() > 0) {
perSecondBucket = Bucket4j.builder()
.addLimit(Bandwidth.simple(groupVo.getThresholdPerSecond(), Duration.ofSeconds(1)))
.build();
}
// 추가 임계치 버킷 (별도)
if (groupVo.getThreshold() > 0 && StringUtils.isNotBlank(groupVo.getThresholdTimeUnit())) {
thresholdBucket = Bucket4j.builder()
.addLimit(Bandwidth.simple(groupVo.getThreshold(),
InflowControlManager.getPeriod(groupVo.getThresholdTimeUnit())))
.build();
}
return new CustomGroupBucket(perSecondBucket, thresholdBucket, groupVo);
}
@Override
public boolean isAdapterPass(String adapter) {
CustomBucket b = adapterBucketList.get(adapter);
@@ -327,6 +467,30 @@ public class InflowControlManager implements Lifecycle, Bucket {
return getInterfaceInflowThreashold(inter);
}
@Override
public String isGroupPass(String groupId) {
CustomGroupBucket b = groupBucketList.get(groupId);
if (b == null)
return null;
return b.tryConsume();
}
@Override
public InflowGroupVO getGroupInflowThreshold(String groupId) {
return groupVoMap.get(groupId);
}
@Override
public String getGroupIdByInterface(String interfaceId) {
return interfaceToGroupMap.get(interfaceId);
}
public InflowGroupVO getGroupInflow(String groupId) {
return getGroupInflowThreshold(groupId);
}
public static boolean isInflowTarget(InflowTargetVO inflowTarget) {
if (inflowTarget == null || !inflowTarget.isActivate()) {
return false;
@@ -338,6 +502,16 @@ public class InflowControlManager implements Lifecycle, Bucket {
}
public static boolean isInflowGroupTarget(InflowGroupVO groupVo) {
if (groupVo == null || !groupVo.isActivate()) {
return false;
}
return groupVo.getThresholdPerSecond() > 0 || (groupVo.getThreshold() > 0 && StringUtils
.equalsAnyIgnoreCase(groupVo.getThresholdTimeUnit(), QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_SECOND,
QUOTA_TIMEUNIT_MINUTE, QUOTA_TIMEUNIT_HOUR, QUOTA_TIMEUNIT_DAY, QUOTA_TIMEUNIT_MONTH));
}
public static Duration getPeriod(String timeUnit) {
if (StringUtils.equalsIgnoreCase(timeUnit, QUOTA_TIMEUNIT_SECOND)) {
return Duration.ofSeconds(1);
@@ -0,0 +1,102 @@
package com.eactive.eai.common.inflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("serial")
public class InflowGroupVO implements Serializable {
private String groupId;
private String groupName;
private long thresholdPerSecond;
private long threshold;
private String thresholdTimeUnit;
private boolean activate;
private List<String> interfaceList = new ArrayList<>();
@Override
public boolean equals(Object obj) {
if (obj instanceof InflowGroupVO) {
return groupId.equals(((InflowGroupVO) obj).getGroupId());
}
return false;
}
@Override
public int hashCode() {
return groupId != null ? groupId.hashCode() : 0;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public long getThresholdPerSecond() {
return thresholdPerSecond;
}
public void setThresholdPerSecond(long thresholdPerSecond) {
this.thresholdPerSecond = thresholdPerSecond;
}
public long getThreshold() {
return threshold;
}
public void setThreshold(long threshold) {
this.threshold = threshold;
}
public String getThresholdTimeUnit() {
return thresholdTimeUnit;
}
public void setThresholdTimeUnit(String thresholdTimeUnit) {
this.thresholdTimeUnit = thresholdTimeUnit;
}
public boolean isActivate() {
return activate;
}
public void setActivate(boolean activate) {
this.activate = activate;
}
public List<String> getInterfaceList() {
return interfaceList;
}
public void setInterfaceList(List<String> interfaceList) {
this.interfaceList = interfaceList;
}
public void addInterface(String interfaceId) {
if (this.interfaceList == null) {
this.interfaceList = new ArrayList<>();
}
this.interfaceList.add(interfaceId);
}
@Override
public String toString() {
return "InflowGroupVO [groupId=" + groupId + ", groupName=" + groupName
+ ", thresholdPerSecond=" + thresholdPerSecond
+ ", threshold=" + threshold
+ ", thresholdTimeUnit=" + thresholdTimeUnit
+ ", activate=" + activate
+ ", interfaceCount=" + (interfaceList != null ? interfaceList.size() : 0) + "]";
}
}
@@ -60,7 +60,6 @@ import com.ext.eai.common.stdmessage.STDMessageKeys;
// safeDB
import com.eactive.ext.kjb.safedb.KjbSafedbWrapper;
import com.eactive.ext.kjb.safedb.Utils;
// until here
@Service
@@ -240,8 +239,8 @@ public class EAILogDAO {
if (svcLogLvl > 3) {
loggingBizData = false;
}
if (logger.isWarn())
logger.warn("EAILogDAO] loggingBizData - " + loggingBizData);
if (logger.isInfo())
logger.info("EAILogDAO] loggingBizData - " + loggingBizData);
// 복합거래인 경우 2X1,3X1 -> 200, 2X2,3X2 -> 300 처럼 처리한다.
if ((logPssSno > 200 && logPssSno < 300) || (logPssSno > 300 && logPssSno < 400)) {
@@ -814,7 +813,7 @@ public class EAILogDAO {
StatLog statLog = statLogMapper.toEntity(vo);
statLogLogger.save(statLog);
} catch (Exception e) {
logger.error("DB Logging[STATIC_LOG] Failed - " + vo.toString(), e);
//logger.error("DB Logging[STATIC_LOG] Failed - " + vo.toString(), e);
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003"));
}
}
@@ -824,7 +823,7 @@ public class EAILogDAO {
StatTranLog statTranLog = statTranLogMapper.toEntity(vo);
statTranLogLogger.save(statTranLog);
} catch (Exception e) {
logger.error("DB Logging[STATIC_TRANCD_LOG] Failed - " + vo.toString(), e);
//logger.error("DB Logging[STATIC_TRANCD_LOG] Failed - " + vo.toString(), e);
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003"));
}
}
@@ -834,7 +833,7 @@ public class EAILogDAO {
StatAdapterLog statAdapterLog = statAdapterLogMapper.toEntity(vo);
statAdapterLogLogger.save(statAdapterLog);
} catch (Exception e) {
logger.error("DB Logging[STATIC_ADAPTER_LOG] Failed - " + vo.toString(), e);
//logger.error("DB Logging[STATIC_ADAPTER_LOG] Failed - " + vo.toString(), e);
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICLG003"));
}
}
@@ -881,7 +880,7 @@ public class EAILogDAO {
}
originalAttribute = sb.toString();
System.out.println("DB 암호화 #2 : {"+ originalAttribute +"} -> {"+attribute+"}");
// System.out.println("DB 암호화 #2 : {"+ originalAttribute +"} -> {"+attribute+"}");
//logger.debug("DB 암호화 #2 : {} -> {}", originalAttribute, attribute);
}
}
@@ -965,7 +964,7 @@ public class EAILogDAO {
try {
encryptedBytes1 = safedb.encrypt(userName, tableName, columnName1, byteMsg);
System.out.println("Encrypted Data : [" + new String(encryptedBytes1) + "]");
// System.out.println("Encrypted Data : [" + new String(encryptedBytes1) + "]");
byte[] decryptedBytes1 = safedb.decrypt(userName, tableName, columnName1, encryptedBytes1);
@@ -2,11 +2,15 @@ package com.eactive.eai.common.logger;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
public class HttpAdapterExtraHeaderVo {
private String name;
private String value;
public HttpAdapterExtraHeaderVo() {
}
}
@@ -8,6 +8,7 @@ import java.util.List;
public class HttpAdapterExtraLogVo {
private String guid;
private int serviceProcessNumber;
private String prcsDate;
private String adapterGroupName;
private String adapterName;
private String url;
@@ -3,7 +3,7 @@ package com.eactive.eai.common.logger.async;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.util.LogKeys;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraHeader;
//import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraHeader;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraLog;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@@ -66,7 +66,7 @@ public class HttpAdapterExtraLogH2Factory {
// 엔티티 클래스 추가
configuration.addAnnotatedClass(HttpAdapterExtraLog.class);
configuration.addAnnotatedClass(HttpAdapterExtraHeader.class);
// configuration.addAnnotatedClass(HttpAdapterExtraHeader.class);
return configuration.buildSessionFactory();
} catch (Throwable ex) {
@@ -1,22 +0,0 @@
package com.eactive.eai.common.logger.mapper;
import com.eactive.eai.common.logger.HttpAdapterExtraHeaderVo;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraHeader;
import com.eactive.eai.data.mapper.BaseMapperConfig;
import com.eactive.eai.data.mapper.GenericMapper;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(config = BaseMapperConfig.class)
public interface HttpAdapterExtraHeaderMapper extends GenericMapper<HttpAdapterExtraHeaderVo, HttpAdapterExtraHeader> {
@Override
@Mapping(source = "id.name", target = "name")
HttpAdapterExtraHeaderVo toVo(HttpAdapterExtraHeader entity);
@Override
@InheritInverseConfiguration
HttpAdapterExtraHeader toEntity(HttpAdapterExtraHeaderVo vo);
}
@@ -1,42 +1,80 @@
package com.eactive.eai.common.logger.mapper;
import com.eactive.eai.common.logger.HttpAdapterExtraHeaderVo;
import com.eactive.eai.common.logger.HttpAdapterExtraLogVo;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraHeaderId;
import com.eactive.eai.data.entity.onl.logger.HttpAdapterExtraLog;
import com.eactive.eai.data.mapper.BaseMapperConfig;
import com.eactive.eai.data.mapper.GenericMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.*;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Optional;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
@Mapper(config = BaseMapperConfig.class, uses = HttpAdapterExtraHeaderMapper.class)
public interface HttpAdapterExtraLogMapper extends GenericMapper<HttpAdapterExtraLogVo, HttpAdapterExtraLog> {
@Slf4j
@Mapper(config = BaseMapperConfig.class)
public abstract class HttpAdapterExtraLogMapper implements GenericMapper<HttpAdapterExtraLogVo, HttpAdapterExtraLog> {
private final static ObjectMapper objectMapper = new ObjectMapper();
private static final DateTimeFormatter SDF_YYYYMMDD = DateTimeFormatter.ofPattern( "yyyyMMdd");
@Override
@Mapping(source = "id.guid", target = "guid")
@Mapping(source = "id.serviceProcessNumber", target = "serviceProcessNumber")
HttpAdapterExtraLogVo toVo(HttpAdapterExtraLog entity);
abstract public HttpAdapterExtraLogVo toVo(HttpAdapterExtraLog entity);
@Override
@InheritInverseConfiguration
HttpAdapterExtraLog toEntity(HttpAdapterExtraLogVo vo);
abstract public HttpAdapterExtraLog toEntity(HttpAdapterExtraLogVo vo);
@AfterMapping
default void setHeaderIdAndWeekday(@MappingTarget HttpAdapterExtraLog entity, HttpAdapterExtraLogVo vo) {
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek(); // 현재 요일
int dayOfWeekNumber = dayOfWeek.getValue() % 7 + 1; // 1 (일요일)부터 7 (토요일)까지
entity.getId().setWeekday(dayOfWeekNumber);
Optional.ofNullable(entity.getHeaderList())
.ifPresent(headers -> headers.forEach(header -> {
if (header.getId() == null) {
header.setId(new HttpAdapterExtraHeaderId());
}
header.getId().setWeekday(dayOfWeekNumber);
header.getId().setGuid(vo.getGuid());
header.getId().setServiceProcessNumber(vo.getServiceProcessNumber());
}));
public void voToEntity(@MappingTarget HttpAdapterExtraLog entity, HttpAdapterExtraLogVo vo) {
// 1. Set weekday for partition table
// DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek(); // 현재 요일
// int dayOfWeekNumber = dayOfWeek.getValue() % 7 + 1; // 1 (일요일)부터 7 (토요일)까지
// entity.getId().setWeekday(dayOfWeekNumber);
// String prcs_date = SDF_YYYYMMDD.format(ZonedDateTime.now());
String prcs_date = LocalDate.now().format(SDF_YYYYMMDD);
entity.getId().setPrcsDate(prcs_date);
// 2. Set Content
try {
String headerContent = objectMapper.writeValueAsString(vo.getHeaderList());
entity.setHeaderContent(headerContent);
} catch (JsonProcessingException e) {
log.warn("Http Header Json Parse 실패", e);
entity.setHeaderContent("[{ \"error\": \"parse error\"}]");
}
}
/**
* Entity VO 변환 추가 처리
*/
@AfterMapping
protected void entityToVo(@MappingTarget HttpAdapterExtraLogVo vo, HttpAdapterExtraLog entity) {
String headerContent = entity.getHeaderContent();
if (headerContent == null || headerContent.isEmpty()) {
vo.setHeaderList(Collections.emptyList());
return;
}
try {
List<HttpAdapterExtraHeaderVo> headerList = objectMapper.readValue(
headerContent,
new TypeReference<List<HttpAdapterExtraHeaderVo>>() {}
);
vo.setHeaderList(headerList);
} catch (JsonProcessingException e) {
log.warn("Http Header 역직렬화 실패", e);
vo.setHeaderList(Collections.emptyList());
}
}
}
@@ -3,7 +3,9 @@ package com.eactive.eai.common.message;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.manager.StandardMessageManager;
@@ -32,6 +34,7 @@ public class EAIMessage implements EAIMessageKeys, Serializable, Comparable<EAIM
private String sngSysItfTp; // 기동시스템어댑터업무그룹명[TSEAIHE01.GstatSysAdptrBzwkGroupName] - StartingSystemInterfaceType - [Adapter_업무명_IN]
private String lydMsgID; // 레이어메시지ID - vlf
private String rspErrCd; // 응답에러코드 - ResponseErrorCode - [12 BYTE EAI에러코드]
private int statErrorCode = 0; // 통계용 에러코드 (0:정상, 1:업무에러, 2:타임아웃, 3:시스템에러)
private String rspErrMsg; // 응답에러메시지 - ResponseErrorMessage - [ 200 BYTE ]
private long msgRcvTm; // 메시지수신시각 - MessageReceiveTime - RequestProcessor에서 설정한다.
private long msgPssTm; // 메시지처리시각 - MessageProcessTime - LOGGER에서 로깅전 설정한다. Queue로 Push하기전에...
@@ -107,6 +110,7 @@ public class EAIMessage implements EAIMessageKeys, Serializable, Comparable<EAIM
private String authCheckdYn;
public EAIMessage() {
this.svcMsgs = new ArrayList<>();
this.svcPssSeq = 1;
@@ -181,6 +185,10 @@ public class EAIMessage implements EAIMessageKeys, Serializable, Comparable<EAIM
}
public void setRspErrCd(String rspErrCd) {
setRspErrCd(rspErrCd, true);
}
public void setRspErrCd(String rspErrCd, boolean isSetStandardMessageError) {
this.rspErrCd = rspErrCd;
// --------------------------------------------
// 에러메시지는 뒤의 9자리를 짤라서 설정한다.
@@ -191,18 +199,15 @@ public class EAIMessage implements EAIMessageKeys, Serializable, Comparable<EAIM
// 20080919 - 업무에러일 경우에도 메시지에 설정하도록 수정
// --------------------------------------------
if (this.mapper != null && this.standardMessage != null && rspErrCd != null && rspErrCd.length() == 12) {
if (isSetStandardMessageError && this.mapper != null && this.standardMessage != null && rspErrCd != null && rspErrCd.length() == 12) {
if (rspErrCd.startsWith("RE") || rspErrCd.startsWith("RF") || rspErrCd.equals(BWK_FAILMSG_CODE)) {
// migration ExtMessage to StandardMessage
//getMapper().setErrorCode(standardMessage, rspErrCd);
StandardMessageManager standardManager = StandardMessageManager.getInstance();
standardManager.getMessageCoordinator().coordinateSetStandardMessageError(standardMessage, getMapper(), rspErrCd, null);
getMapper().setResponseType(standardMessage, STDMessageKeys.RESPONSE_TYPE_CODE_E);
}
}
}
public String getRspErrMsg() {
@@ -219,6 +224,14 @@ public class EAIMessage implements EAIMessageKeys, Serializable, Comparable<EAIM
}
}
public int getStatErrorCode() {
return statErrorCode;
}
public void setStatErrorCode(int statErrorCode) {
this.statErrorCode = statErrorCode;
}
public void setRspErr(String rspErrCd, String rspErrMsg) {
this.rspErrCd = rspErrCd;
this.rspErrMsg = rspErrMsg;
@@ -624,6 +637,42 @@ public class EAIMessage implements EAIMessageKeys, Serializable, Comparable<EAIM
this.authCheckdYn = authCheckdYn;
}
/**
* [주의] 비동기 JMS 전달 전용 - 직접 사용 금지!
*
* 필드는 비동기 거래 JMS ObjectMessage 직렬화를 통해
* Consumer 스레드로 컨텍스트를 전달하기 위한 용도로만 사용됩니다.
*
* 컨텍스트 읽기/쓰기는 반드시 ElinkTransactionContext를 사용하세요:
* - ElinkTransactionContext.setSeedSalt() / getSeedSalt()
* - ElinkTransactionContext.setEncryptionKey() / getEncryptionKey()
*
* 설정 위치:
* - FlowRouter: getAll() 복사하여 필드에 설정
* - ElinkESBProcessProxy: 필드에서 restore() 복원
*
* @see com.eactive.eai.common.context.ElinkTransactionContext
*/
private Map<String, Object> transactionContextTransfer;
/**
* [비동기 전달 전용] 컨텍스트 전달용 Map 반환
* @see #transactionContextTransfer
*/
public Map<String, Object> getTransactionContextTransfer() {
return transactionContextTransfer;
}
/**
* [비동기 전달 전용] 컨텍스트 전달용 Map 설정
* @see #transactionContextTransfer
*/
public void setTransactionContextTransfer(Map<String, Object> transactionContextTransfer) {
this.transactionContextTransfer = transactionContextTransfer;
}
@Override
public Object clone() throws CloneNotSupportedException {
EAIMessage cloned = (EAIMessage) super.clone();
@@ -636,6 +685,8 @@ public class EAIMessage implements EAIMessageKeys, Serializable, Comparable<EAIM
cloned.setStandardMessage((StandardMessage) standardMessage.clone());
if (subMessage != null)
cloned.setSubMessage((StandardMessage) subMessage.clone());
if (transactionContextTransfer != null)
cloned.setTransactionContextTransfer(new HashMap<>(transactionContextTransfer));
return cloned;
}
@@ -110,6 +110,9 @@ public class EAIServiceMonitor implements Lifecycle {
private MonitorCleaner cleaner;
private Timer cleanerTimer;
@Autowired
private StatisticsMonitor statisticsMonitor;
public static synchronized EAIServiceMonitor getInstance() {
return ApplicationContextProvider.getContext().getBean(EAIServiceMonitor.class);
@@ -328,6 +331,9 @@ public class EAIServiceMonitor implements Lifecycle {
}
}
// 통계용 에러코드 설정
msg.setStatErrorCode(iErrorCode);
if (monitors == null)
monitors = createMonitorVO();
@@ -374,6 +380,12 @@ public class EAIServiceMonitor implements Lifecycle {
intfacSendTranCd, adapterGroupName);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 실시간 통계 로직 추가
statisticsMonitor.recordStatistics(msg);
////////////////////////////////////////////////////////////////////////////////////////////////////////////
HashMap<String, MonitorVO> bwkVO = bwkClss.get(bwkCls);
@@ -391,7 +403,7 @@ public class EAIServiceMonitor implements Lifecycle {
logger.error(ExceptionUtil.make("RECEAICMT204", errorText));
}
}
public void resetAll() {
String[] keys = getAllMonitorVOKey();
MonitorVO vo = null;
@@ -246,7 +246,7 @@ public class MonitorChecker extends TimerTask
try {
dao.addStaticLog(logVo);
} catch(Exception e) {
if (logger.isError()) logger.error("MonitorVO.insertStaticCount ERROR. - " + e.getMessage(),e);
//if (logger.isError()) logger.error("MonitorVO.insertStaticCount ERROR. - " + e.getMessage(),e);
}
}
@@ -280,8 +280,7 @@ public class MonitorChecker extends TimerTask
try {
dao.addStaticTranCdLog(tmpLogVo);
} catch(Exception e) {
if (logger.isError()) logger.error("MonitorVO.insertStaticCount TRANCODE ERROR. - "
+ tmpLogVo.toString() + "\n" + e.getMessage(),e);
}
}
@@ -294,8 +293,7 @@ public class MonitorChecker extends TimerTask
try {
dao.addStaticAdapterLog(tmpLogVo);
} catch(Exception e) {
if (logger.isError()) logger.error("MonitorVO.insertStaticCount ADAPTER ERROR. - "
+ tmpLogVo.toString() + "\n" + e.getMessage(),e);
}
}
}
@@ -310,7 +308,7 @@ public class MonitorChecker extends TimerTask
logVo.setPrcssTtmVal((statVo.getSumOfprocessTime() - statVo.getPsvSumOfPssTime()));
logVo.setPsvPrcssTtmVal(statVo.getPsvSumOfPssTime());
logVo.setTotalPrcssTtmVal(statVo.getSumOfprocessTime());
logVo.setKey(" ");
if(IFType.AA.equals(ifType)) {
if( rType == 'S') {
totCnt = statVo.getCnt100() + statVo.getErr100();
@@ -0,0 +1,9 @@
package com.eactive.eai.common.monitor;
import com.eactive.eai.common.message.EAIMessage;
public interface StatisticsMonitor {
public void recordStatistics(EAIMessage requestEaiMessage);
}
@@ -1,11 +1,13 @@
package com.eactive.eai.common.routing;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.util.Logger;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import com.eactive.eai.common.context.ElinkTransactionContext;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageKeys;
import com.eactive.eai.common.util.Logger;
/**
* 1. 기능 : ElinkESBProcess를 호출하는 공통 Class
@@ -42,17 +44,30 @@ public class ElinkESBProcessProxy
public static EAIMessage callElinkESBProcess(String serviceURI, EAIMessage eaiMessage, boolean isLocal, Properties prop) throws Exception
{
EAIMessage retMsg = null;
// [ElinkTransactionContext] 비동기 거래 컨텍스트 초기화 여부 판단
// - ASYNC 거래이고, outbound Process 호출이 아닌 경우에만 초기화
boolean shouldManageContext = eaiMessage != null
&& EAIMessageKeys.ASYNC_SVC.equals(eaiMessage.getSvcTsmtUsgTp())
&& (serviceURI == null || !serviceURI.startsWith("com.eactive.eai.outbound"));
try {
if (isLocal){
// [ElinkTransactionContext] 비동기 거래 진입점 - 컨텍스트 복원
if (shouldManageContext) {
ElinkTransactionContext.restore(eaiMessage.getTransactionContextTransfer());
eaiMessage.setTransactionContextTransfer(null); // 복원 전달용 필드 초기화
}
if (isLocal){
Class cl = classLocalCache.get(serviceURI);
if(cl == null) {
cl = Class.forName(serviceURI);
classLocalCache.put(serviceURI, cl);
}
Process proc = (Process)cl.newInstance();
proc.callService(eaiMessage, prop);
retMsg = proc.clientReturn();
}else{
if(eaiMessage == null) {
@@ -62,12 +77,17 @@ public class ElinkESBProcessProxy
retMsg = RemoteProxyClient.callProxyBean(eaiMessage, prop);
}
}
} catch( ClassNotFoundException e) {
} catch( ClassNotFoundException e) {
if (logger.isError()) logger.error("ElinkProcessProxy] callElinkESBProcess["+serviceURI+"] Class Not Found Exception : ");
throw new Exception(PROXY_ERROR_CODE);
} catch( Exception e) {
throw new Exception(PROXY_ERROR_CODE);
} catch( Exception e) {
if (logger.isError()) logger.error("ElinkProcessProxy] callElinkESBProcess["+serviceURI+"] Exception : "+e.getMessage(),e);
throw new Exception(PROXY_ERROR_CODE);
throw new Exception(PROXY_ERROR_CODE);
} finally {
// [ElinkTransactionContext] 비동기 거래 - 해제
if (shouldManageContext) {
ElinkTransactionContext.clear();
}
}
return retMsg;
}
@@ -2,6 +2,7 @@ package com.eactive.eai.common.routing;
import java.util.Properties;
import com.eactive.eai.common.context.ElinkTransactionContext;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.property.PropManager;
@@ -136,6 +137,8 @@ public class FlowRouter
}
try {
// [ElinkTransactionContext] 비동기 송신 컨텍스트 복사
eaiMessage.setTransactionContextTransfer(ElinkTransactionContext.getAll());
JMSSender.sendToQueue(eaiMessage, queueConFactory, routeQueueName, prop);
} catch(Exception e) {
if (logger.isError()) logger.error(guidLogPrefix +" process.Queue Error. Queue Name[" + routeQueueName + "]- " + e.getMessage(), e);
@@ -164,6 +167,8 @@ public class FlowRouter
}
try {
// [ElinkTransactionContext] 비동기 송신 컨텍스트 복사
eaiMessage.setTransactionContextTransfer(ElinkTransactionContext.getAll());
if (ElinkConfig.isUseCacheTopic()) {
SessionManager.getInstance().putTopic(traceKey, eaiMessage);
}
@@ -33,7 +33,9 @@ public abstract class Process {
String outboundAdapterGroupName = eaiMessage.getCurrentSvcMsg().getPsvSysItfTp();
AdapterGroupVO outboundAdapterGvo = AdapterManager.getInstance().getAdapterGroupVO(outboundAdapterGroupName);
standardMessage.setBizData(bizObject, outboundAdapterGvo.getMessageEncode());
StandardMessageManager.getInstance().getMessageCoordinator().coordinateBeforeStandardMessageSend(standardMessage, msgType, charset);
if(MessageType.JSON.equals(msgType)) {
return standardMessage.toJson();
}
@@ -1,5 +1,6 @@
package com.eactive.eai.common.session;
import com.eactive.eai.authserver.service.BearerTokenInfo;
import com.eactive.eai.common.lifecycle.Lifecycle;
import com.eactive.eai.common.lifecycle.LifecycleException;
import com.eactive.eai.common.lifecycle.LifecycleListener;
@@ -58,6 +59,7 @@ public abstract class SessionManager implements Lifecycle {
public static final String USERID_CAHCE_NAME = "convertUserIdSession";
public static final String WEBSOCKER_CAHCE_NAME = "webSocketTimeout";
public static final String TERMINAL_CAHCE_NAME = "terminalSession";
public static final String CAGATEWAY_TOKEN_CACHE_NAME = "CAGatewayToken";
public static final String SESSION_MANAGER_GROUPNAME = "RMIInfo";
public static final String SESSION_MANAGER_CACHETYPE = "cacheType";
@@ -66,6 +68,7 @@ public abstract class SessionManager implements Lifecycle {
public static final String SESSION_MANAGER_EXPIRE_INTERVAL = "expireInterval";
public static final String SESSION_MANAGER_MULTI_GROUP_IP = "multi_group_ip";
public static final String LOGGER_LEVEL = "loggerLevel";
public static final String SESSION_MANAGER_MULTI_GROUP_PORT = "multi_group_port";
public static final String SESSION_MANAGER_SESSION_TIMEOUT = "sessionTimeout";
public static final String SESSION_MANAGER_WEBSOCKET_TIMEOUT = "webSocketTimeout";
@@ -193,6 +196,14 @@ public abstract class SessionManager implements Lifecycle {
public abstract void putLogin(String key, SessionVO value);
public abstract void removeLogin(String key);
//CA Token Cache
public abstract BearerTokenInfo getCAToken(String key);
public abstract void putCAToken(String key, BearerTokenInfo value);
public abstract void removeCAToken(String key);
// HTTP Cache
public abstract SessionVO getHttpLogin(String key);
@@ -3,6 +3,7 @@ package com.eactive.eai.common.session;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import com.eactive.eai.authserver.service.BearerTokenInfo;
import com.eactive.eai.common.ehcache.CustomRMICacheReplicatorFactory;
import com.eactive.eai.common.logger.EAIDBLogControl;
import com.eactive.eai.common.message.EAIMessage;
@@ -155,7 +156,7 @@ public class SessionManagerForEhcache extends SessionManager {
}
System.setProperty("net.sf.ehcache.skipUpdateCheck", "true");
String bootstrapAsynchronously = "false";
String bootstrapAsynchronously = "true";
Configuration cf = new Configuration();
FactoryConfiguration ppFactory = new FactoryConfiguration();
@@ -921,4 +922,19 @@ public class SessionManagerForEhcache extends SessionManager {
sb.append("</Caches>");
return sb.toString();
}
@Override
public BearerTokenInfo getCAToken(String key) {
throw new UnsupportedOperationException();
}
@Override
public void putCAToken(String key, BearerTokenInfo value) {
throw new UnsupportedOperationException();
}
@Override
public void removeCAToken(String key) {
throw new UnsupportedOperationException();
}
}
@@ -42,6 +42,7 @@ import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMultic
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import com.eactive.eai.adapter.socket2.common.Env;
import com.eactive.eai.authserver.service.BearerTokenInfo;
import com.eactive.eai.common.logger.EAIDBLogControl;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.property.PropManager;
@@ -63,6 +64,7 @@ import ch.qos.logback.classic.Level;
// 에러내용 : Failed to execute the cache operation
// (all partition owners have left the grid, partition data has been lost)
//------------------------------------------------------------------------------------
public class SessionManagerForIgnite extends SessionManager {
// evictMaster Instance - single socket 관련
private static IgniteCache<String, String> evictMasterCache = null;
@@ -72,7 +74,8 @@ public class SessionManagerForIgnite extends SessionManager {
private static IgniteCache<String, EAIMessage> cacheTopic = null;
// 비동기 거래 복원용
private static IgniteCache<String, CacheStoreObject> cacheStore = null;
// CA Gateway Token 관리용
private static IgniteCache<String, BearerTokenInfo> cacheCAToken = null;
// webSocket Login cache 정보
private static IgniteCache<String, SessionVO> cacheLogin = null; // key = loginId
private static IgniteCache<String, String> cacheConvertUserId = null; // 단말ID userID로 변경
@@ -273,7 +276,7 @@ public class SessionManagerForIgnite extends SessionManager {
String server = null;
// 서버정보의 IP가 시스템과 다른 ip로 설정되면 기동이 안되는 문제
if (localServerName.equals(key) && !"GW".equals(System.getProperty("spring.profiles.active", ""))) {
server = "127.0.0.1:" + discoverPort;
server = vo.getAddress() + ":" + discoverPort;
} else {
server = vo.getAddress() + ":" + discoverPort;
}
@@ -330,7 +333,32 @@ public class SessionManagerForIgnite extends SessionManager {
ch.qos.logback.classic.Logger blogger = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory
.getLogger("org.apache.ignite");
blogger.setLevel(Level.INFO);
String loggerLevel = prpty.getProperty(SessionManager.LOGGER_LEVEL, "ERROR");
switch(loggerLevel) {
case "ERROR":
blogger.setLevel(Level.ERROR);
break;
case "INFO":
blogger.setLevel(Level.INFO);
break;
case "WARN":
blogger.setLevel(Level.WARN);
break;
case "DEBUG":
blogger.setLevel(Level.DEBUG);
break;
case "TRACE":
blogger.setLevel(Level.TRACE);
break;
}
if( logger.isDebug() ) {
logger.debug("Ignite loggerLevel = "+loggerLevel);
}
IgniteLogger log = new Slf4jLogger((org.slf4j.Logger) blogger);
config.setGridLogger(log);
@@ -364,6 +392,7 @@ public class SessionManagerForIgnite extends SessionManager {
caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, USERID_CAHCE_NAME, 20000, false));
caches.add(initCache(config, webSocketTimeout, bootstrapAsynchronously, WEBSOCKER_CAHCE_NAME, 20000, false));
caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, TERMINAL_CAHCE_NAME, 20000, false));
caches.add(initCache(config, 0, bootstrapAsynchronously, CAGATEWAY_TOKEN_CACHE_NAME, 1000, false));
config.setCacheConfiguration(caches.stream().toArray(CacheConfiguration[]::new));
@@ -391,6 +420,7 @@ public class SessionManagerForIgnite extends SessionManager {
cacheSocket = manager.cache(ADAPTER_CAHCE_NAME);
cacheTopic = manager.cache(TOPIC_CAHCE_NAME);
cacheStore = manager.cache(STORE_CAHCE_NAME);
cacheCAToken = manager.cache(CAGATEWAY_TOKEN_CACHE_NAME);
cacheLogin = manager.cache(LOGIN_CAHCE_NAME);
httpLogin = manager.cache(HTTP_CAHCE_NAME);
@@ -810,4 +840,33 @@ public class SessionManagerForIgnite extends SessionManager {
sb.append("</Caches>");
return sb.toString();
}
@Override
public BearerTokenInfo getCAToken(String key) {
try {
return cacheCAToken.get(key);
} catch (Exception e) {
logger.error("getCAToken null key=" + key, e);
return null;
}
}
@Override
public void putCAToken(String key, BearerTokenInfo value) {
if (logger.isWarn()) {
logger.warn("Put CAToken key - " + key + ", CAToken - " + value.toString());
}
cacheCAToken.put(key, value);
}
@Override
public void removeCAToken(String key) {
if (logger.isWarn()) {
logger.warn("Remove CAToken key - " + key);
}
cacheCAToken.remove(key);
}
}
@@ -19,7 +19,7 @@ public class ElinkStateManager {
if (logger != null) {
logger.warn(message);
}
System.out.println(DatetimeUtil.getCurrentTime() + " " + LOG_PREFIX + message);
// System.out.println(DatetimeUtil.getCurrentTime() + " " + LOG_PREFIX + message);
}
public static synchronized ElinkStateManager getInstance() {
@@ -12,9 +12,13 @@ import org.springframework.transaction.annotation.Transactional;
import com.eactive.eai.common.dao.BaseDAO;
import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageDAO;
import com.eactive.eai.common.message.EAIMessageManager;
import com.eactive.eai.common.stdmessage.loader.StandardMessageInfoLoader;
import com.eactive.eai.common.stdmessage.loader.StandardMessageRestoreService;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.data.entity.onl.message.EAIMessageEntity;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageInfo;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageItem;
import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageRestore;
@@ -224,4 +228,71 @@ public class STDMessageDAO extends BaseDAO {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE111"));
}
}
// jwhong 추가
public StandardMessageInfo getSTDMsgByPath(String apiFullPath) throws DAOException {
Optional<StandardMessageInfo> optional = standardMessageInfoLoader.findByApiFullPath(apiFullPath);
return optional.orElseThrow(() -> new DAOException("해당 full path의 TSEAIHS04 에 데이터가 없습니다."));
}
// Path Variable 처리를 위한 Method/FullURL 베이스 처리.
public HashMap<String, STDMsgInfoAddOnVO> getAllStdMsgInfos() throws DAOException {
HashMap<String, STDMsgInfoAddOnVO> apiInfo = new HashMap<>();
EAIMessageManager eaiManager = EAIMessageManager.getInstance();
EAIMessage eaiMsg = null;
STDMsgInfoAddOnVO vo = null;
try {
List<StandardMessageInfo> list = standardMessageInfoLoader.findAll();
for (StandardMessageInfo info : list) {
eaiMsg = eaiManager.getEAIMessage(info.getEaisvcname());
vo = new STDMsgInfoAddOnVO();
vo.setBzwksvckeyname(info.getBzwksvckeyname());
vo.setEaiSvcCd(info.getEaisvcname());
vo.setApiFullPath(info.getApifullpath());
vo.setAdapterGroupName(eaiMsg.getSngSysItfTp());
apiInfo.put(vo.getApiFullPath(), vo);
}
return apiInfo;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE102"), e);
}
}
public STDMsgInfoAddOnVO getUrlStdMsgInfo(String apiFullPath) throws DAOException {
EAIMessageManager eaiManager = EAIMessageManager.getInstance();
EAIMessage eaiMsg = null;
STDMsgInfoAddOnVO vo = null;
try {
Optional<StandardMessageInfo> optional = standardMessageInfoLoader.findByApiFullPath(apiFullPath);
if (optional.isPresent()) {
StandardMessageInfo info = optional.get();
eaiMsg = eaiManager.getEAIMessage(info.getEaisvcname());
vo.setBzwksvckeyname(info.getBzwksvckeyname());
vo.setEaiSvcCd(info.getEaisvcname());
vo.setApiFullPath(info.getApifullpath());
vo.setAdapterGroupName(eaiMsg.getSngSysItfTp());
}
return vo;
} catch (Exception e) {
throw new DAOException("RECEAICKE110");
}
}
public String getApiFullPath(String serviceKey) throws DAOException {
try {
Optional<StandardMessageInfo> optional = standardMessageInfoLoader.findById(serviceKey);
if (optional.isPresent()) {
StandardMessageInfo info = optional.get();
return info.getApifullpath();
} else {
throw new DAOException("RECEAICKE110");
}
} catch (DAOException e) {
throw e;
} catch(Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICKE111"));
}
}
}
@@ -30,6 +30,8 @@ public class STDMessageManager implements Lifecycle {
private HashMap<String, StandardMessage> headers = new HashMap<>();
private HashMap<String, StandardMessage> headersForPathVariables = new HashMap<>();
private HashMap<String, STDMsgInfoAddOnVO> headerUrls = new HashMap<>();
private HashMap<String, STDMsgInfoAddOnVO> headerUrlsForPathVariables = new HashMap<>();
private boolean started;
private LifecycleSupport lifecycle = new LifecycleSupport(this);
@@ -60,6 +62,14 @@ public class STDMessageManager implements Lifecycle {
headersForPathVariables.put(entry.getKey(), entry.getValue());
}
}
// url base로 처리 추가.
headerUrls = sTDMessageDAO.getAllStdMsgInfos();
headerUrlsForPathVariables.clear();
for (Map.Entry<String, STDMsgInfoAddOnVO> entry : headerUrls.entrySet()) {
if (isPathVariable(entry.getKey())) {
headerUrlsForPathVariables.put(entry.getKey(), entry.getValue());
}
}
}
public static boolean isPathVariable(String key) {
@@ -86,6 +96,17 @@ public class STDMessageManager implements Lifecycle {
} else {
throw new Exception("STDMessage not found in Database : key[" + keyName + "]");
}
// url base로 처리 추가.
String apiFullPath = sTDMessageDAO.getApiFullPath(keyName);
STDMsgInfoAddOnVO msgUrl = sTDMessageDAO.getUrlStdMsgInfo(apiFullPath);
if (msgUrl != null) {
headerUrls.put(apiFullPath, msgUrl);
if (isPathVariable(apiFullPath)) {
headerUrlsForPathVariables.put(apiFullPath, msgUrl);
}
} else {
throw new Exception("STDMessage not found in Database : key[" + apiFullPath + "]");
}
}
public void stop() throws LifecycleException {
@@ -145,6 +166,41 @@ public class STDMessageManager implements Lifecycle {
return null;
}
// apiFullPath 기준 Path Variable 조회
public StandardMessage getSTDMessageForUrlPathVariable(String apiFullPath) {
String matchedKey = getMatchedUrlPathVariable(apiFullPath);
if (matchedKey != null) {
return getSTDMessage(matchedKey);
} else {
return null;
}
}
public String getMatchedUrlPathVariable(String apiFullPath) {
AntPathMatcher matcher = new AntPathMatcher();
for (String key : headerUrlsForPathVariables.keySet()) {
if (matcher.match(key, apiFullPath)) {
return key;
}
}
return null;
}
public STDMsgInfoAddOnVO getStdMsgInfoAddOn(String apiFullPath) {
for (Map.Entry<String, STDMsgInfoAddOnVO> entry : headerUrls.entrySet()) {
if (StringUtils.equals(entry.getKey(), apiFullPath) ) {
return entry.getValue();
}
}
String apiPathVariable = getMatchedUrlPathVariable(apiFullPath);
for (Map.Entry<String, STDMsgInfoAddOnVO> entry : headerUrlsForPathVariables.entrySet()) {
if (StringUtils.equals(entry.getKey(), apiPathVariable) ) {
return entry.getValue();
}
}
return null;
}
public String[] getAllSTDMessageKeys() {
String[] ks = new String[this.headers.size()];
Iterator<String> it = this.headers.keySet().iterator();
@@ -163,6 +219,19 @@ public class STDMessageManager implements Lifecycle {
}
return al;
}
// 업무서비스키로 동록된 apiFullPath 가져오기.
public String getApiFullPath(String serviceKey) {
String apiFullPath = "";
for (Map.Entry<String, STDMsgInfoAddOnVO> entry : headerUrls.entrySet()) {
STDMsgInfoAddOnVO msgVO = entry.getValue();
if (StringUtils.equals(serviceKey, msgVO.getBzwksvckeyname())) {
apiFullPath = msgVO.getApiFullPath();
return apiFullPath;
}
}
return null;
}
public void addSTDMessage(StandardMessage msg) {
this.headers.put(msg.getServiceKey(), msg);
@@ -175,5 +244,9 @@ public class STDMessageManager implements Lifecycle {
public synchronized void removeSTDMessage(String bwkSvcKey) {
this.headers.remove(bwkSvcKey);
this.headersForPathVariables.remove(bwkSvcKey);
// apiFullPath 기준 등록정보 삭제.
String apiFullPath = getApiFullPath(bwkSvcKey);
this.headerUrls.remove(apiFullPath);
this.headerUrlsForPathVariables.remove(apiFullPath);
}
}
@@ -0,0 +1,40 @@
package com.eactive.eai.common.stdmessage;
import org.json.simple.JSONObject;
public class STDMsgInfoAddOnVO {
private String bzwksvckeyname = null;// 업무서비스키
private String eaiSvcCd = null;// EAI서비스코드
private String apiFullPath = null;// Method/Url
private String adapterGroupName = null;// 인바운드 어댑터그룹
public String getBzwksvckeyname() {
return bzwksvckeyname;
}
public void setBzwksvckeyname(String bzwksvckeyname) {
this.bzwksvckeyname = bzwksvckeyname;
}
public String getEaiSvcCd() {
return eaiSvcCd;
}
public void setEaiSvcCd(String eaiSvcCd) {
this.eaiSvcCd = eaiSvcCd;
}
public String getApiFullPath() {
return apiFullPath;
}
public void setApiFullPath(String apiFullPath) {
this.apiFullPath = apiFullPath;
}
public String gAdapterGroupName() {
return adapterGroupName;
}
public void setAdapterGroupName(String adapterGroupName) {
this.adapterGroupName = adapterGroupName;
}
}
@@ -1,6 +1,8 @@
package com.eactive.eai.common.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -34,7 +36,13 @@ public class HttpAdapterExtraLogUtil {
}
public static void insertHttpAdapterExtraLog(String guid, int serviceProcessNumber, String adapterGroupName, String adapterName, Header[] headers, String url, String httpMethod, int httpStatus){
List<HttpAdapterExtraHeaderVo> headerVoList = convertHeaderToListOfHttpAdapterExtraHeaderVo(headers);
List<HttpAdapterExtraHeaderVo> headerVoList = new ArrayList<HttpAdapterExtraHeaderVo>();
if ( headers != null && headers.length != 0 ) {
headerVoList = convertHeaderToListOfHttpAdapterExtraHeaderVo(headers);
}
insertHttpAdapterExtraLog(guid, serviceProcessNumber, adapterGroupName, adapterName, headerVoList, url, httpMethod, httpStatus);
}
@@ -50,17 +58,13 @@ public class HttpAdapterExtraLogUtil {
httpAdapterExtraLogVo.setHttpMethod(httpMethod);
for (HttpAdapterExtraHeaderVo httpAdapterExtraHeaderVo : headerVoList) {
String name = httpAdapterExtraHeaderVo.getName();
if(StringUtils.isNotBlank(name) && "authorization".equals(name.toLowerCase())) {
httpAdapterExtraHeaderVo.setValue("{hidden}");
}
String value = httpAdapterExtraHeaderVo.getValue();
if(StringUtils.isNotBlank(value) && value.length() > 400) {
value = value.substring(0, 400) + "...";
httpAdapterExtraHeaderVo.setValue(value);
}else if(value == null){
httpAdapterExtraHeaderVo.setValue(" ");
}
if (value == null) {
httpAdapterExtraHeaderVo.setValue(" ");
}
}
httpAdapterExtraLogVo.setHeaderList(headerVoList);
httpAdapterExtraLogVo.setHttpStatus(httpStatus);
@@ -101,14 +105,15 @@ public class HttpAdapterExtraLogUtil {
public static List<HttpAdapterExtraHeaderVo> convertHeaderToListOfHttpAdapterExtraHeaderVo(Header[] headers) {
Set<String> seenNames = new HashSet<>();
return Arrays.stream(headers)
.filter(header -> seenNames.add(header.getName())) // 중복된 이름을 스킵
// .filter(header -> seenNames.add(header.getName())) // 중복된 이름을 스킵
.map(header -> new HttpAdapterExtraHeaderVo(header.getName(), header.getValue()))
.collect(Collectors.toList());
}
public static List<HttpAdapterExtraHeaderVo> convertMapToListOfHttpAdapterExtraHeaderVo(Map<Object, Object> map) {
return map.entrySet().stream()
.map(entry -> new HttpAdapterExtraHeaderVo(entry.getKey().toString(), entry.getValue().toString()))
.map(entry -> new HttpAdapterExtraHeaderVo(entry.getKey().toString(), entry.getValue() == null ? "" : entry.getValue().toString()))
.collect(Collectors.toList());
}
}
@@ -1,5 +1,5 @@
package com.eactive.eai.common.util;
import java.util.Iterator;
import java.util.Properties;
@@ -69,6 +69,7 @@ public class JMSSender {
throw new Exception("qconFactory not found -" + connectionFactory);
queue = locator.getQueue(destination);
logger.info("resolved quene name is:" + "["+ queue + "]");
qsender = qsession.createSender(queue);
ObjectMessage msg = qsession.createObjectMessage();
@@ -0,0 +1,10 @@
package com.eactive.eai.common.util;
import com.google.gson.Gson;
public final class Jsons {
private Jsons() {}
public static final Gson GSON = new Gson();
}
@@ -1,5 +1,25 @@
package com.eactive.eai.common.util;
import java.io.BufferedInputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.filters.StringInputStream;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import com.eactive.eai.common.EAIKeys;
import com.eactive.eai.common.message.MessageType;
import com.eactive.eai.common.monitor.EAIServiceMonitor;
@@ -10,30 +30,17 @@ import com.eactive.eai.transformer.util.ISO8583DumpUtil;
import com.ext.eai.common.stdmessage.STDMessageErrorKeys;
import com.jayway.jsonpath.JsonPath;
import com.solab.iso8583.IsoMessage;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.filters.StringInputStream;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import java.io.BufferedInputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public final class MessageUtil {
static Logger logger = LoggerFactory.getLogger(MessageUtil.class);
//public static final String ERROR_MESSAGE_DEFAULT_FORMAT = "{\"error\":{\"code\":\"%s\",\"message\":\"%s\"}}";
public static final String ERROR_MESSAGE_DEFAULT_FORMAT = "{\"code\":\"%s\",\"message\":\"%s\"}";
public static final String ERROR_CODE_AP_ERROR = "E.GW.AP_ERROR";
public static final String ERROR_CODE_AUTH_FAIL = "E.GW.AUTH_FAIL";
public static final String ERROR_CODE_SERVICE_NOT_FOUND = "E.GW.SERVICE_NOT_FOUND";
private MessageUtil() {
}
@@ -492,12 +499,10 @@ public final class MessageUtil {
public static String makeErrorMessageByMessageType(String msgType, String msgCharset, String code, String msg,
String errorFormat) {
if (StringUtils.equals(msgType, MessageType.JSON)) {
return makeJsonErrorMessage(code, msg, errorFormat);
} else if (StringUtils.equals(msgType, MessageType.XML)) {
if (StringUtils.equals(msgType, MessageType.XML)) {
return makeXmlErrorMessage(code, msg, msgCharset, errorFormat);
} else {
return "[errCd]" + code + "[/errCd]" + "[errMsg]" + msg + "[/errMsg]";
return makeJsonErrorMessage(code, msg, errorFormat);
}
}
@@ -510,14 +515,17 @@ public final class MessageUtil {
}
public static String makeJsonErrorMessage(String code, String msg, String errorFormat) {
if (StringUtils.isNotBlank(errorFormat)) {
try {
return String.format(errorFormat, code, JSONValue.escape(msg));
} catch (Exception e) {
logger.error(e.getMessage());
}
if (StringUtils.isBlank(errorFormat)) {
errorFormat = ERROR_MESSAGE_DEFAULT_FORMAT;
}
// errorFormat에 %s가 1개만 있으면 msg만, 2개 이상이면 code, msg 전달
int paramCount = StringUtils.countMatches(errorFormat, "%s");
if (paramCount == 1) {
return String.format(errorFormat, JSONValue.escape(msg));
} else {
return String.format(errorFormat, code, JSONValue.escape(msg));
}
return String.format("{\"error\":\"%s\",\"error_description\":\"%s\"}", code, JSONValue.escape(msg));
}
public static String makeXmlErrorMessage(String code, String msg, String charset, String errorFormat) {
@@ -6,6 +6,8 @@ import java.lang.reflect.Method;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.rmi.RemoteException;
import java.security.Security;
import java.util.Arrays;
import javax.sql.DataSource;
@@ -203,6 +205,8 @@ public class AppInitializer implements InitializingBean, DisposableBean {
* eLink FrameWork의 웹어플리케이션이 초기화 작업을 수행
**/
private void init() {
ElinkStateManager.getInstance().setWaitMaxMs(shutdownWaitSecs * 1000);
ElinkStateManager.getInstance().setSleepIntervalMs(shutdownWaitIntervalMs);
ElinkStateManager.getInstance().starting();
@@ -399,6 +403,11 @@ public class AppInitializer implements InitializingBean, DisposableBean {
if (pRmiServicePort != null) {
this.rmiServicePort = pRmiServicePort;
}
Arrays.stream(Security.getProviders())
.forEach(p -> System.out.println("JavaSecurityProviders name=" + p.getName() +" / info="+ p.getInfo() +" / version="+ p.getVersion()));
Security.removeProvider("BC");
try {
logger.warn("\n@@ eLink RMI Register Port : " + rmiPort + ", Service Port : " + rmiServicePort);
@@ -0,0 +1,132 @@
package com.eactive.eai.custom.alarm;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import org.springframework.stereotype.Service;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.Jsons;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.custom.alarm.key.AlarmKey;
import com.eactive.eai.custom.alarm.key.DynamicAlarmKey;
import com.eactive.eai.custom.alarm.policy.AlarmPolicy;
import com.eactive.eai.custom.alarm.policy.CounterPolicy;
import com.eactive.eai.custom.alarm.policy.SendPolicy;
import com.eactive.eai.custom.alarm.policy.TimerPolicy;
import com.google.gson.JsonObject;
@Service
public class AlarmService {
protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
final static String ALARM_GROUP = "Alarm";
final static String ALARM_KEY = "{ALARM}";
final static String ALARM_RECIVER = "{RECIVER}";
final static String ALARM_EABLE = "enable.alarm";
public Map<AlarmKey, AlarmPolicy> getAlarmPolicy() {
Map<AlarmKey, AlarmPolicy> policyMap = new HashMap<AlarmKey, AlarmPolicy>();
try {
Properties props = PropManager.getInstance().getProperties(ALARM_GROUP);
props.forEach((key, value) -> {
String keyName = (String) key;
String configStr = (String) value;
if (keyName.contains(ALARM_KEY)) {
AlarmPolicy newPolicy = buildAlarmPolicy(keyName, configStr);
policyMap.put(newPolicy.getAlarmKey(), newPolicy);
}
});
} catch (Exception e) {
logger.warn("getAlarmPolicy fail.", e);
return Collections.EMPTY_MAP;
}
return policyMap;
}
public boolean isAlarmEnabled() {
return Optional.ofNullable(PropManager.getInstance().getProperty(ALARM_GROUP, ALARM_EABLE))
.map(Boolean::valueOf).orElse(false);
}
private AlarmPolicy buildAlarmPolicy(String key, String configJsonStr) {
JsonObject alarmConfig = Jsons.GSON.fromJson(configJsonStr, JsonObject.class);
String policyType = alarmConfig.get("type").getAsString();
int thresholdCount = Optional.ofNullable(alarmConfig.get("thresholdCount")).map(i -> i.getAsInt()).orElse(5);
int timeWindowSec = Optional.ofNullable(alarmConfig.get("timeWindowSec")).map(i -> i.getAsInt()).orElse(60);
AlarmPolicy alarmPolicy;
if ("count".equals(policyType)) {
alarmPolicy = CounterPolicy.builder().alarmKey(new DynamicAlarmKey(key)).thresholdCount(thresholdCount)
.build();
} else {
alarmPolicy = TimerPolicy.builder().alarmKey(new DynamicAlarmKey(key)).timeWindowMs(timeWindowSec * 1000)
.build();
}
return alarmPolicy;
}
public Map<AlarmKey, SendPolicy> getSendPolicy() {
Map<AlarmKey, SendPolicy> policyMap = new HashMap<AlarmKey, SendPolicy>();
try {
Properties props = PropManager.getInstance().getProperties(ALARM_GROUP);
props.forEach((key, value) -> {
String keyName = (String) key;
String configStr = (String) value;
if (!keyName.contains(ALARM_RECIVER))
return;
SendPolicy newPolicy = buildSendPolicy(keyName, configStr);
policyMap.put(newPolicy.getAlarmKey(), newPolicy);
});
} catch (Exception e) {
logger.warn("getSendPolicy fail.", e);
return Collections.EMPTY_MAP;
}
return policyMap;
}
private SendPolicy buildSendPolicy(String key, String configStr) {
List<String> reciverList = Optional.ofNullable(configStr).map(t -> Arrays.asList(t.split(",")))
.orElse(Collections.EMPTY_LIST);
key = key.replace(ALARM_RECIVER, "").trim() + "{ALARM}";
SendPolicy sendPolicy = new SendPolicy(key, reciverList);
return sendPolicy;
}
}
@@ -0,0 +1,146 @@
package com.eactive.eai.custom.alarm;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.eactive.eai.common.util.ApplicationContextProvider;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.custom.alarm.event.AlarmEvent;
import com.eactive.eai.custom.alarm.key.AlarmKey;
import com.eactive.eai.custom.alarm.policy.AlarmPolicy;
import com.eactive.eai.custom.alarm.policy.SendPolicy;
import com.eactive.eai.custom.alarm.ums.UmsSendManager;
import com.eactive.eai.custom.alarm.ums.UmsService;
import com.eactive.eai.custom.alarm.ums.payload.ObpMonitoringUmsTemplate;
import com.eactive.eai.custom.alarm.ums.payload.UmsRequestPayload;
@Component
public class AlarmStateManager {
List<AlarmEvent> registerAlarmList = new ArrayList<AlarmEvent>();
private final ScheduledExecutorService scheduler;
protected static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
private static AlarmStateManager alarmStateManager;
@Autowired
AlarmService alarmService;
@Autowired
UmsSendManager umsSendManager;
public static AlarmStateManager getAlarmStateManager() {
if (alarmStateManager == null) {
alarmStateManager = ApplicationContextProvider.getContext().getBean(AlarmStateManager.class);
}
return alarmStateManager;
}
public AlarmStateManager() {
this.scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r);
t.setName("AlarmStateManager-worker");
t.setDaemon(false);
return t;
});
scheduler.scheduleWithFixedDelay(() -> {
try {
// === 여기에 지속 실행할 로직 ===
fireAlarm();
} catch (Throwable e) {
// 반드시 예외 잡기 ( 잡으면 스케줄 자체가 죽음)
logger.error("fireAlarm fail", e);
}
}, 0, 5, TimeUnit.SECONDS); // 최초 0초, 이후 5초 간격
}
public void onEvnet(AlarmEvent alaramEvent) {
Optional<AlarmEvent> existEvent = registerAlarmList.stream().filter(e -> e.equals(alaramEvent)).findFirst();
if (existEvent.isPresent()) {
AlarmEvent event = existEvent.get();
event.onOcurr();
} else {
registerAlarmList.add(alaramEvent);
}
}
private void fireAlarm() {
Map<AlarmKey, AlarmPolicy> alarmPolicyMap = alarmService.getAlarmPolicy();
Map<AlarmKey, SendPolicy> sendPolicyMap = alarmService.getSendPolicy();
Iterator<AlarmEvent> iterator = registerAlarmList.iterator();
while (iterator.hasNext()) {
AlarmEvent event = iterator.next();
AlarmPolicy alarmPolicy = alarmPolicyMap.get(event.getKey());
if (alarmPolicy != null && alarmPolicy.isAlarmTriggered(event)) {
// 알람 발송 로직
SendPolicy sendPolicy = sendPolicyMap.get(event.getKey());
if (alarmService.isAlarmEnabled()) {
send(sendPolicy, event);
} else {
logger.info("Alarm is disabled, event = {}, policy = {}", event, sendPolicy);
}
// 리스트에서 안전하게 제거
iterator.remove();
} else { // 트리거 조건이 안되더라도, 이벤트발생한지 오래 되었으면 제거하여 OOM 예방.
long firstOcurredAt = event.getCondition().getOcurredAt();
long diffInMs = System.currentTimeMillis() - firstOcurredAt;
if (diffInMs >= TimeUnit.MINUTES.toMillis(60)) { // 1시간 지난거면 삭제
iterator.remove();
}
}
}
}
private void send(SendPolicy sendPolicy, AlarmEvent event) {
UmsRequestPayload payload = null;
try {
List<String> cellPhoneList = sendPolicy.getCellPhoneList();
for (String cellPhone : cellPhoneList) {
payload = UmsRequestPayload.builder()
.content(ObpMonitoringUmsTemplate.builder().message(event.getMessage()).build())
.cellphone(cellPhone).build();
logger.info("Alarm is disabled, UmsRequestPayload = {}", payload);
umsSendManager.enqueue(payload);
}
} catch (Exception e) {
logger.error(String.format("Alarm message delivery failed (UMS), payload=%s", payload), e);
}
}
}
@@ -0,0 +1,21 @@
package com.eactive.eai.custom.alarm.condition;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
@Builder
@Getter
@ToString
public class AlarmCondition {
final long ocurredAt = System.currentTimeMillis();
long lastOcurredAt; // 일단, 미사용
@Builder.Default
long count = 1;
public void onOcurr() {
this.lastOcurredAt = System.currentTimeMillis();
this.count++;
}
}
@@ -0,0 +1,5 @@
package com.eactive.eai.custom.alarm.condition;
public enum AlarmLevel {
ERROR, WARN, FATAL
}
@@ -0,0 +1,44 @@
package com.eactive.eai.custom.alarm.event;
import java.util.Objects;
import com.eactive.eai.custom.alarm.condition.AlarmCondition;
import com.eactive.eai.custom.alarm.key.AlarmKey;
import com.eactive.eai.custom.alarm.policy.AlarmPolicy;
import com.eactive.eai.custom.alarm.policy.CounterPolicy;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@Builder
@ToString
public class AlarmEvent {
AlarmKey key;
AlarmCondition condition;
String message;
public void onOcurr() {
condition.onOcurr();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AlarmEvent)) return false;
AlarmEvent that = (AlarmEvent) o;
return Objects.equals(this.key, that.key)
&& Objects.equals(this.message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(key, message);
}
}
@@ -0,0 +1,6 @@
package com.eactive.eai.custom.alarm.key;
public interface AlarmKey {
String code();
}
@@ -0,0 +1,12 @@
package com.eactive.eai.custom.alarm.key;
public final class CoreAlarmKey {
private CoreAlarmKey() { }
public static final AlarmKey CircuitBreaker = new DynamicAlarmKey("CircuitBreaker{ALARM}");
public static final AlarmKey Timeout = new DynamicAlarmKey("Timeout{ALARM}");
}
@@ -0,0 +1,33 @@
package com.eactive.eai.custom.alarm.key;
import lombok.ToString;
@ToString
public final class DynamicAlarmKey implements AlarmKey {
private final String code;
public DynamicAlarmKey(String code) {
if (code == null || code.isEmpty()) {
throw new IllegalArgumentException("AlarmKey code must not be empty");
}
this.code = code;
}
@Override
public String code() {
return code;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AlarmKey)) return false;
return code.equals(((AlarmKey) o).code());
}
@Override
public int hashCode() {
return code.hashCode();
}
}
@@ -0,0 +1,71 @@
package com.eactive.eai.custom.alarm.policy;
import com.eactive.eai.custom.alarm.event.AlarmEvent;
import com.eactive.eai.custom.alarm.key.AlarmKey;
public abstract class AlarmPolicy {
private AlarmKey alarmKey;
private int thresholdCount;
private long timeWindowMs;
protected AlarmPolicy(Builder<?> builder) {
this.alarmKey = builder.alarmKey;
this.thresholdCount = builder.thresholdCount;
this.timeWindowMs = builder.timeWindowMs;
}
public AlarmKey getAlarmKey() {
return alarmKey;
}
public int getThresholdCount() {
return thresholdCount;
}
public long getTimeWindowMs() {
return timeWindowMs;
}
public abstract boolean isAlarmTriggered(AlarmEvent event);
public boolean hasElapsed(long baseTimeMs) {
return System.currentTimeMillis() - baseTimeMs >= timeWindowMs;
}
public boolean hasExceededLimit(long count) {
return count >= thresholdCount;
}
public abstract static class Builder<T extends Builder<T>> {
private AlarmKey alarmKey;
private int thresholdCount;
private long timeWindowMs;
public T alarmKey(AlarmKey alarmKey) {
this.alarmKey = alarmKey;
return self();
}
public T thresholdCount(int thresholdCount) {
this.thresholdCount = thresholdCount;
return self();
}
public T timeWindowMs(long timeWindowMs) {
this.timeWindowMs = timeWindowMs;
return self();
}
protected abstract T self();
abstract AlarmPolicy build();
}
}
@@ -0,0 +1,5 @@
package com.eactive.eai.custom.alarm.policy;
public enum AlarmType {
COUNT, TIMER
}
@@ -0,0 +1,39 @@
package com.eactive.eai.custom.alarm.policy;
import com.eactive.eai.custom.alarm.event.AlarmEvent;
public class CounterPolicy extends AlarmPolicy {
private CounterPolicy(Builder builder) {
super(builder);
}
@Override
public boolean isAlarmTriggered(AlarmEvent event) {
if (!event.getKey().equals(getAlarmKey())) {
return false;
}
long count = event.getCondition().getCount();
return hasExceededLimit(count);
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends AlarmPolicy.Builder<Builder> {
@Override
protected Builder self() {
return this;
}
@Override
public CounterPolicy build() {
return new CounterPolicy(this);
}
}
}
@@ -0,0 +1,23 @@
package com.eactive.eai.custom.alarm.policy;
import java.util.List;
import com.eactive.eai.custom.alarm.key.AlarmKey;
import com.eactive.eai.custom.alarm.key.DynamicAlarmKey;
import lombok.Getter;
import lombok.ToString;
@ToString
@Getter
public class SendPolicy {
final AlarmKey alarmKey;
final List<String> cellPhoneList;
public SendPolicy(String alarmKey, List<String> cellPhoneList) {
this.alarmKey = new DynamicAlarmKey(alarmKey);
this.cellPhoneList = cellPhoneList;
}
}

Some files were not shown because too many files have changed in this diff Show More