This commit is contained in:
Rinjae
2025-09-05 17:16:26 +09:00
commit c54ef1903f
4947 changed files with 817291 additions and 0 deletions
@@ -0,0 +1,15 @@
package com.eactive.eai.common;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* JsonView 에서 Null 값을 변경하는 모듈
*
*/
public class CustomObjectMapper extends ObjectMapper{
private static final long serialVersionUID = 1L;
public CustomObjectMapper() {
getSerializerProvider().setNullValueSerializer(new NullToEmptyStringSerializer());
}
}
@@ -0,0 +1,20 @@
package com.eactive.eai.common;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
/**
* jsonView시에 null 을 empty("")로 바꾸는 모듈
*
*/
public class NullToEmptyStringSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException, JsonProcessingException {
jsonGenerator.writeString("");
}
}
@@ -0,0 +1,326 @@
package com.eactive.eai.common.ibatis;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.io.Resource;
import org.springframework.orm.ibatis.SqlMapClientFactoryBean;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
/**
* iBATIS sqlmap 클라이언트의 sqlMap 및 sqlMapConfig 파일의 변경을 감지, 실시간 적용하는 팩토리 빈.
*
* <h2>개요</h2>
* iBATIS + Spring 개발시 쿼리 매핑 파일이 변경되면 웹애플리케이션 서버를 재기동해야 적용이 됐었다. 이러한 불편을 없애기
* 위해 매핑 파일 변경을 실시간으로 감시, 적용하는 모듈을 제공한다.<br />
*
* 감시 대상 이 모듈은 iBATIS sqlmap 클라이언트의 sqlMap 및 sqlMapConfig 파일의 변경을 감지, 실시간 적용해준다.<br />
*
* <h2>제약사항</h2>
* 감시 대상 파일들은 스타트업 당시에 결정된다. 그러므로 추가된 파일들에 대해서는 감지가 되지 않고, 삭제된 파일들에 대해서는 경고
* 메시지가 나온다. 예를 들어, sqlMapConfig에 sqlMap 파일이 추가되거나 하면 해당 맵이 적용되기는 하지만, 실시간 변경 감지
* 대상으로 추가되지는 않는다.<br />
*
* <h2>요구사항</h2>
* iBATIS sqlmap 2.3.0, Java 1.4, Spring 2.5 이상 또는 iBATIS sqlmap 2.3.2 이상,<br />
* Java 1.5 이상, Spring 2.5.5 이상<br />
*
* <h2>적용 순서</h2>
* 1. Spring의 applicationContext 설정 파일 중 sqlMapClient를 얻기 위한
* SqlMapClientFactory 빈을 신규 클래스로 교체한다. <br />
* 2. 변경 감지 시간 간격 (1000분의 1초 단위)를 지정한다.<br />
* <PRE>
* &lt;bean id="sqlMapClient" class="jcf.dao.ibatis.sqlmap.RefreshableSqlMapClientFactoryBean"&gt;
* &lt;!-- &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt;--&gt;
* &lt;property name="configLocation" value="classpath:jcf/inboundErrorInfoDao/ibatis/sqlmap/sqlmap-config.xml" /&gt;
* &lt;property name="dataSource" ref="dataSource" /&gt;
*
* &lt;!-- Java 1.5 or higher and iBATIS 2.3.2 or higher REQUIRED --&gt;
* &lt;property name="mappingLocations" value="jcf/inboundErrorInfoDao/\*\*\/T\*.xml" /&gt;
* &lt;!-- &lt;property name="mappingLocations" value="file:///D:/Type.xml" /&gt;--&gt;
*
* &lt;property name="checkInterval" value="1000" /&gt;
* &lt;/bean&gt;
* </PRE>
*
* 3. 라이브러리 추가 <br />
* backport-util-concurrent-3.1.jar<br />
*
* 테스트 기존의 applicationContext에 등록되어 있던 sqlMapClient에 해당하는 mappingFile들을 편집하거나,
* sqlMapConfig 파일 또는 그 파일에 등록된 mappingFile(sqlMap 파일)들을 편집하면 주어진 변경감지 시간 후 변경사항이 적용된다.<br />
* <br />
*
* @author setq
*/
public class RefreshableSqlMapClientFactoryBean extends SqlMapClientFactoryBean
implements SqlMapClientRefreshable, DisposableBean {
private static final Log logger = LogFactory
.getLog(RefreshableSqlMapClientFactoryBean.class);
private SqlMapClient proxy;
private int interval;
private Timer timer;
private TimerTask task;
private Resource[] configLocations;
private Resource[] mappingLocations;
/**
* 파일 감시 쓰레드가 실행중인지 여부.
*/
private boolean running = false;
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public void setConfigLocation(Resource configLocation) {
super.setConfigLocation(configLocation);
this.configLocations = (configLocation != null ? new Resource[] { configLocation }
: null);
}
public void setConfigLocations(Resource[] configLocations) {
super.setConfigLocations(configLocations);
this.configLocations = configLocations;
}
public void setMappingLocations(Resource[] mappingLocations) {
super.setMappingLocations(mappingLocations);
this.mappingLocations = mappingLocations;
}
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
public void doReload() throws Exception {
if(executor.getActiveCount() == executor.getMaximumPoolSize()){
return;
}
Runnable run = new Runnable() {
@Override
public void run() {
try {
refresh();
} catch (Exception e) {
logger.error("Error while reloading sqlMapClient", e);
}
}
};
executor.execute(run);
}
/**
* iBATIS 설정을 다시 읽어들인다.<br /> SqlMapClient 인스턴스 자체를 새로 생성하여 교체한다.
*
* @throws Exception
*/
public void refresh() throws Exception {
/*
* WRITE LOCK.
*/
w.lock();
try {
super.afterPropertiesSet();
logger.info("Refreshed SqlMapClient.");
} finally {
w.unlock();
}
}
/**
* 싱글톤 멤버로 SqlMapClient 원본 대신 프록시로 설정하도록 오버라이드.
*/
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
setRefreshable();
}
private void setRefreshable() {
proxy = (SqlMapClient) Proxy.newProxyInstance(SqlMapClient.class
.getClassLoader(), new Class[] { SqlMapClient.class,
ExtendedSqlMapClient.class }, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(getParentObject(), args);
}
});
task = new TimerTask() {
private Map map = new HashMap();
public void run() {
if (isModified()) {
try {
logger.info("Refreshing SqlMapClient...");
// refresh();
for (int i = 0; i < 3; i++) {
doReload();
Thread.sleep(2000);
}
}
catch (Exception e) {
logger.error("caught exception", e);
}
}
}
private boolean isModified() {
boolean retVal = false;
for (int i = 0; i < configLocations.length; i++) {
Resource configLocation = configLocations[i];
retVal |= findModifiedResource(configLocation);
}
if (mappingLocations != null) {
for (int i = 0; i < mappingLocations.length; i++) {
Resource mappingLocation = mappingLocations[i];
retVal |= findModifiedResource(mappingLocation);
}
}
return retVal;
}
private boolean findModifiedResource(Resource resource) {
boolean retVal = false;
List modifiedResources = new ArrayList();
try {
long modified = resource.lastModified();
if (map.containsKey(resource)) {
long lastModified = ((Long) map.get(resource)).longValue();
if (lastModified != modified) {
map.put(resource, new Long(modified));
modifiedResources.add(resource.getDescription());
retVal = true;
}
}
else {
map.put(resource, new Long(modified));
}
}
catch (Throwable e) {
logger.error("caught exception", e);
}
if (retVal) {
// if (logger.isInfoEnabled()) {
// logger.info("modified files : " + modifiedResources);
// }
logger.info("modified files : " + modifiedResources);
}
return retVal;
}
};
timer = new Timer(true);
resetInterval();
List mappingLocationList = extractMappingLocations(configLocations);
if (this.mappingLocations != null) {
mappingLocationList.addAll(Arrays.asList(this.mappingLocations));
}
this.mappingLocations = (Resource[]) mappingLocationList.toArray(new Resource[0]);
}
private List extractMappingLocations(Resource[] configLocations) {
List mappingLocationList = new ArrayList();
SqlMapExtractingSqlMapConfigParser configParser = new SqlMapExtractingSqlMapConfigParser();
for (int i = 0; i < configLocations.length; i++) {
try {
InputStream is = configLocations[i].getInputStream();
mappingLocationList.addAll(configParser.parse(is));
}
catch (IOException ex) {
logger.warn("Failed to parse config resource: "
+ configLocations[i], ex.getCause());
}
}
return mappingLocationList;
}
private Object getParentObject() {
/*
* READ LOCK.
*/
r.lock();
try {
return super.getObject();
} finally {
r.unlock();
}
}
@Override
public SqlMapClient getObject() {
return this.proxy;
}
public Class getObjectType() {
return (this.proxy != null ? this.proxy.getClass() : SqlMapClient.class);
}
public boolean isSingleton() {
return true;
}
public void setCheckInterval(int ms) {
interval = ms;
if (timer != null) {
resetInterval();
}
}
private void resetInterval() {
if (running) {
timer.cancel();
running = false;
}
if (interval > 0) {
timer.schedule(task, 0, interval);
running = true;
}
}
public void destroy() throws Exception {
timer.cancel();
}
}
@@ -0,0 +1,11 @@
package com.eactive.eai.common.ibatis;
public interface SqlMapClientRefreshable {
void refresh() throws Exception;
void setCheckInterval(int ms);
}
@@ -0,0 +1,85 @@
package com.eactive.eai.common.ibatis;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.w3c.dom.Node;
import com.ibatis.common.xml.Nodelet;
import com.ibatis.common.xml.NodeletParser;
import com.ibatis.common.xml.NodeletUtils;
import com.ibatis.sqlmap.client.SqlMapException;
import com.ibatis.sqlmap.engine.builder.xml.SqlMapClasspathEntityResolver;
//import com.ibatis.sqlmap.engine.builder.xml.XmlParserState;
@SuppressWarnings("unchecked")
public class SqlMapExtractingSqlMapConfigParser {
protected final NodeletParser parser = new NodeletParser();
// private XmlParserState state = new XmlParserState();
private List sqlMapList = new ArrayList();
private ResourceLoader resourceLoader = new DefaultResourceLoader();
public SqlMapExtractingSqlMapConfigParser() {
parser.setValidation(true);
parser.setEntityResolver(new SqlMapClasspathEntityResolver());
addSqlMapNodelets();
}
public List parse(Reader reader) {
try {
parser.parse(reader);
return sqlMapList;
}
catch (Exception e) {
throw new RuntimeException("Error occurred. Cause: " + e, e);
}
}
public List parse(InputStream inputStream) {
try {
parser.parse(inputStream);
return sqlMapList;
}
catch (Exception e) {
throw new RuntimeException("Error occurred. Cause: " + e, e);
}
}
protected void addSqlMapNodelets() {
parser.addNodelet("/sqlMapConfig/sqlMap", new Nodelet() {
public void process(Node node) throws Exception {
// state.getConfig().getErrorContext().setActivity(
// "loading the SQL Map resource");
Properties attributes = NodeletUtils.parseAttributes(node,
// state.getGlobalProps());
null);
String resource = attributes.getProperty("resource");
String url = attributes.getProperty("url");
if (resource != null) {
sqlMapList.add(resourceLoader.getResource(resource));
}
else if (url != null) {
sqlMapList.add(resourceLoader.getResource(url));
}
else {
throw new SqlMapException(
"The <sqlMap> element requires either a resource or a url attribute.");
}
}
});
}
}
@@ -0,0 +1,76 @@
package com.eactive.eai.common.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;
import org.apache.log4j.Logger;
public class HttpUtil {
protected static final Logger logger = Logger.getLogger(HttpUtil.class);
public static String httpCall(String urlStr, String httpMethod) throws Exception {
return httpCall(urlStr, httpMethod, Charset.defaultCharset().toString());
}
public static String httpCall(String urlStr, String httpMethod, String encoding) throws Exception {
logger.debug("httpCall (" +httpMethod+ ") : " + urlStr);
StringBuilder result = new StringBuilder();
try {
HttpURLConnection conn = (HttpURLConnection) new URL(urlStr).openConnection();
conn.setRequestMethod(httpMethod);
BufferedReader rd = null;
if (conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
InputStreamReader inputStreamReader = new InputStreamReader(conn.getInputStream(), encoding);
rd = new BufferedReader(inputStreamReader);
} else {
logger.error(urlStr + " / ResponseCode : " + conn.getResponseCode());
return null;
}
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
rd.close();
conn.disconnect();
} catch (ConnectException e) {
logger.error(urlStr + e.getMessage());
return null;
}
return result.toString();
}
public static String httpCall(String urlStr, String httpMethod, String encoding, Map<String, String> paramMap) throws Exception {
if(paramMap.size() < 0) {
return httpCall(urlStr, httpMethod, encoding);
}
StringBuilder sb = new StringBuilder();
sb.append(urlStr);
sb.append("?");
paramMap.forEach((k, v) -> {
sb.append(k);
sb.append("=");
sb.append(v);
sb.append("&");
});
return httpCall(sb.toString(), httpMethod, encoding);
}
}
@@ -0,0 +1,76 @@
package com.eactive.eai.common.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcTest {
// String driver = "org.mariadb.jdbc.Driver";
// String driver = "com.mysql.jdbc.Driver";
String driver = "com.ibm.db2.jcc.DB2Driver"; //db2
// String url = "jdbc:mariadb://localhost:4406/eai?useUnicode=true&characterEncoding=euckr";
String url = "jdbc:db2://localhost:50000/DSEADT";
String uId = "db2admin";
String uPwd = "e1001";
Connection con;
PreparedStatement pstmt;
ResultSet rs;
public JdbcTest() {
try {
Class.forName(driver);
con = DriverManager.getConnection(url, uId, uPwd);
System.out.println(con);
if( con != null ){ System.out.println("데이터 베이스 접속 성공"); }
} catch (ClassNotFoundException e) {
//e.printStackTrace();
System.out.println("드라이버 로드 실패");
}
catch (SQLException e) {
//e.printStackTrace();
System.out.println(e);
System.out.println("데이터 베이스 접속 실패");
}
}
public void insert(String id, String name){
String sql = "insert into test values(?, ?)";
try {
pstmt = con.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, name);
pstmt.executeQuery();
} catch (SQLException e) {
//e.printStackTrace();
System.out.println("쿼리 수행 실패");
}
}
public void select(){
String sql = "select * from test";
try {
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()){
System.out.println("id : " + rs.getString("id"));
System.out.println("name : " + rs.getString("name"));
}
} catch (SQLException e) { System.out.println("쿼리 수행 실패"); }
finally {
try { if(rs!=null) rs.close();} catch(Exception e) {}
try { if(con!=null) con.close();} catch(Exception e) {}
}
}
public static void main(String[] args){
JdbcTest dbm = new JdbcTest();
}
}
@@ -0,0 +1,81 @@
package com.eactive.eai.common.util;
/**
* 1. 기능 : Date, Time 관련 Utility Method 정의
* 2. 처리 개요 :
*
* 3. 주의사항
*
* @author :
* @version : v 1.0.0
* @see :
* @since :
*/
public final class NullControl {
/**
* Private 생성자
* Instance를 생성하지 못함
*/
private NullControl()
{
}
/**
* 1. 기능 : Null값을 공백으로 변경
* 2. 처리 개요 :
* - ""나 Null를 입력받아 SPACE로 변환한다.
* 3. 주의사항
*
* @param "", Null
* @return String
* @exception
**/
public static String addSpace(String val)
{
if(val == null || val.equals("")){
val = " ";
}
return val;
}
/**
* 1. 기능 : 입력값을 트림하여 화이트스페이스를 없앤다.
* 2. 처리 개요 :
* - 입력받은 값을 트림하여 리턴한다.
* 3. 주의사항
*
* @param "", Null
* @return String
* @exception
**/
public static String trimSpace(String val)
{
if(val == null || val.equals("")){
val = ""; // ""나 Null을 체크하여 트림하여 에러가 발생하지 않도록 한다..
}else{
val = val.trim();
}
return val;
}
public static String trimSpace2(String val)
{
if(val == null || val.equals("")){
return ""; // ""나 Null을 체크하여 트림하여 에러가 발생하지 않도록 한다..
}
if (val.trim().length() > 0){
return val;
}
else{
return val.trim();
}
}
}
@@ -0,0 +1,89 @@
package com.eactive.eai.common.util;
import org.apache.commons.lang3.StringUtils;
/**
* 1. 기능 : EAI서버 Rule 정보를 DB로 부터 로딩해 메모리에 관리하는 Manager 클래스
* 2. 처리 개요 : DB Rule 정보에 저장된 필드 추출 Rule 정보를 메모리에 로딩 관리한다.
* 3. 주의사항
*
* @author :
* @version : v 1.0.0
* @see : 관련 기능을 참조
* @since :
* :
*/
public class SystemUtil
{
public static final String EAI_SYSTEMMODE = "eai.systemmode";
private static final String EAI_PRODUCT = "P";
private static final String EAI_STAGING = "T";
private static final String EAI_DEVELOP = "D";
//시스템 운영환경 구분코드
private static final String SYSOPEREVIRNDSTCD_PRODUCT = "P";
private static final String SYSOPEREVIRNDSTCD_STAGING = "T";
private static final String SYSOPEREVIRNDSTCD_DEVELOP = "D";
public static boolean isProdServer() {
String systemMode = System.getProperty(EAI_SYSTEMMODE);
if (EAI_PRODUCT.equals(systemMode)){
return true;
}else{
return false;
}
}
public static boolean isDevServer() {
String systemMode = System.getProperty(EAI_SYSTEMMODE);
if (EAI_DEVELOP.equals(systemMode)|| "".equals(systemMode)){
return true;
}else{
return false;
}
}
public static boolean isStagingServer() {
String systemMode = System.getProperty(EAI_SYSTEMMODE);
if (EAI_STAGING.equals(systemMode)){
return true;
}else{
return false;
}
}
public static String getSysOperEvirnDstcd(){
if (isProdServer()){
return SYSOPEREVIRNDSTCD_PRODUCT;
} else if (isStagingServer()){
return SYSOPEREVIRNDSTCD_STAGING;
} else if (isDevServer()){
return SYSOPEREVIRNDSTCD_DEVELOP;
}
return "";
}
public static String getSystemModeTitle(){
String systemModeTitle = System.getProperty("systemModeTitle", "");
if(StringUtils.isBlank(systemModeTitle)){
if (SystemUtil.isDevServer()){
systemModeTitle = "개발";
}else if(SystemUtil.isStagingServer()){
systemModeTitle = "스테이징";
// systemModeTitle = "테스트";
}else if(SystemUtil.isProdServer()){
systemModeTitle = "운영";
}
}
if(StringUtils.isNotBlank(systemModeTitle)){
systemModeTitle = "["+systemModeTitle+"] ";
}
return systemModeTitle;
}
}
@@ -0,0 +1,89 @@
package com.eactive.eai.common.util;
/**
*/
public class XmlUtil {
private static final String CDATA_START = "<![CDATA[";
private static final String CDATA_END = "]]>";
private static final String CDATA_PSEUDO_END = "]]&gt;";
private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START;
private static final int CDATA_END_LEN = CDATA_END.length();
/**
* This method takes a string which may contain HTML tags (ie,
* &lt;b&gt;, &lt;table&gt;, etc) and replaces any
* '<', '>' , '&' or '"'
* characters with respective predefined entity references.
*
* @param input The text to be converted.
* @return The input string with the special characters replaced.
* */
static public String escapeTags(final String input) {
// Check if the string is null, zero length or devoid of special characters
// if so, return what was sent in.
if(input == null
|| input.length() == 0
|| (input.indexOf('"') == -1 &&
input.indexOf('&') == -1 &&
input.indexOf('<') == -1 &&
input.indexOf('>') == -1)) {
return input;
}
StringBuffer buf = new StringBuffer(input.length() + 6);
char ch;
int len = input.length();
for(int i=0; i < len; i++) {
ch = input.charAt(i);
if (ch > '>') {
buf.append(ch);
} else if(ch == '<') {
buf.append("&lt;");
} else if(ch == '>') {
buf.append("&gt;");
} else if(ch == '&') {
buf.append("&amp;");
} else if(ch == '"') {
buf.append("&quot;");
} else {
buf.append(ch);
}
}
return buf.toString();
}
/**
* Ensures that embeded CDEnd strings (]]>) are handled properly
* within message, NDC and throwable tag text.
*
* @param buf StringBuffer holding the XML data to this point. The
* initial CDStart (<![CDATA[) and final CDEnd (]]>) of the CDATA
* section are the responsibility of the calling method.
* @param str The String that is inserted into an existing CDATA Section within buf.
* */
static public void appendEscapingCDATA(final StringBuffer buf,
final String str) {
if (str != null) {
int end = str.indexOf(CDATA_END);
if (end < 0) {
buf.append(str);
} else {
int start = 0;
while (end > -1) {
buf.append(str.substring(start, end));
buf.append(CDATA_EMBEDED_END);
start = end + CDATA_END_LEN;
if (start < str.length()) {
end = str.indexOf(CDATA_END, start);
} else {
return;
}
}
buf.append(str.substring(start));
}
}
}
}