commit 5b94f23274117a57a6b5d6c5a0f380da617aa184 Author: kdg@gmtc.kr Date: Fri Sep 15 17:58:39 2023 +0900 dddfdfd diff --git a/applicaion.pid b/applicaion.pid new file mode 100644 index 0000000..1334b68 --- /dev/null +++ b/applicaion.pid @@ -0,0 +1 @@ +10064 \ No newline at end of file diff --git a/cfg/allowClient.xml b/cfg/allowClient.xml new file mode 100644 index 0000000..9bc5841 --- /dev/null +++ b/cfg/allowClient.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/cfg/client.xml b/cfg/client.xml new file mode 100644 index 0000000..5f6eac4 --- /dev/null +++ b/cfg/client.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + diff --git a/cfg/log4j2.xml b/cfg/log4j2.xml new file mode 100644 index 0000000..75346b0 --- /dev/null +++ b/cfg/log4j2.xml @@ -0,0 +1,40 @@ + + + + logs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cfg/server.xml b/cfg/server.xml new file mode 100644 index 0000000..10c8f93 --- /dev/null +++ b/cfg/server.xml @@ -0,0 +1,62 @@ + + + + + + + + diff --git a/cfg/udpsocket.xml b/cfg/udpsocket.xml new file mode 100644 index 0000000..71cff81 --- /dev/null +++ b/cfg/udpsocket.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d946be1 --- /dev/null +++ b/pom.xml @@ -0,0 +1,157 @@ + + 4.0.0 + + kr.gmtc + EyeGW-ASDE-Send + 0.0.0.1 + jar + + EyeGW-ASDE-Send + SACP ASDE 수신 S/W + + + + + + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + + + + + + xwiki + XWiki Externals Repository + https://maven.xwiki.org/externals + + + local-repository + local jars + file://${project.basedir}/lib + + + + + + + + UTF-8 + UTF-8 + 1.8 + true + + + 2.17.2 + + + + + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.apache.logging.log4j + log4j-api + ${log4j2.version} + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + + com.oracle.jdbc + ojdbc8 + 12.2.0.1 + + + + mysql + mysql-connector-java + + + + org.mariadb.jdbc + mariadb-java-client + + + + org.postgresql + postgresql + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + ipworks + ipworks-local + 1.0.0 + + + + + + + + + + + + org.yaml + snakeyaml + 1.33 + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/src/main/java/kr/gmtc/eyegw/GmtApplication.java b/src/main/java/kr/gmtc/eyegw/GmtApplication.java new file mode 100644 index 0000000..8989b73 --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/GmtApplication.java @@ -0,0 +1,54 @@ +package kr.gmtc.eyegw; + +import java.time.ZoneId; +import java.util.TimeZone; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.context.ApplicationPidFileWriter; +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.boot.system.ApplicationHome; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.EnableScheduling; + +import gmt.logger.GmtLogManager; + +@SpringBootApplication +@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) +@EnableScheduling +public class GmtApplication { + + @Value("${root}") + String path; + + public static void main(String[] args) { + + ApplicationHome home = new ApplicationHome(GmtApplication.class); + String root = home.getDir().getPath(); + + System.setProperty("user.dir", root); + + Thread.currentThread().setName("JVM - Main"); + + TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("UTC"))); + + SpringApplication springApplication = new SpringApplication(GmtApplication.class); + springApplication.addListeners(new LogPathSetter()); + springApplication.addListeners(new ApplicationPidFileWriter("./applicaion.pid")); + springApplication.run(args); + + } + +} + +class LogPathSetter implements ApplicationListener { + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) { + GmtLogManager.setpath(applicationEvent.getEnvironment().getProperty("root")); + } + } \ No newline at end of file diff --git a/src/main/java/kr/gmtc/eyegw/config/ServiceConfig.java b/src/main/java/kr/gmtc/eyegw/config/ServiceConfig.java new file mode 100644 index 0000000..9d02a8b --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/config/ServiceConfig.java @@ -0,0 +1,80 @@ +package kr.gmtc.eyegw.config; + +import java.nio.charset.Charset; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration("ServiceConfig") +public class ServiceConfig { + + @Value("${root}") + private String root; + + @Value("${tcpip.client.send}") + private String clientSendCharsetStr; + @Value("${tcpip.client.receive}") + private String clientReceiveCharsetStr; + @Value("${tcpip.client.checksum}") + private boolean clientReceiveChecksum; + + @Value("${tcpip.server.send}") + private String serverSendCharsetStr; + @Value("${tcpip.server.receive}") + private String serverReceiveCharsetStr; + @Value("${tcpip.server.checksum}") + private boolean serverReceiveChecksum; + + private Charset clientReceiveCharset; + private Charset serverReceiveCharset; + private Charset clientSendCharset; + private Charset serverSendCharset; + + @PostConstruct + private void initialize() { + clientSendCharset = Charset.forName(clientReceiveCharsetStr); + serverSendCharset = Charset.forName(serverReceiveCharsetStr); + clientReceiveCharset = Charset.forName(clientReceiveCharsetStr); + serverReceiveCharset = Charset.forName(serverReceiveCharsetStr); + } + + /** @return 프로그램 설치 경로 */ + public String getRoot() { + return root; + } + /** @return 클라이언트 포트 송신 인코드 캐릭터셋 */ + public Charset getClientSendCharset() { + return clientSendCharset; + } + /** @return 클라이언트 포트 수신 디코드 캐릭터셋 */ + public Charset getClientReceiveCharset() { + return clientReceiveCharset; + } + /** @return 클라이언트 포트 수신 체크섬 검증 여부 */ + public boolean isClientReceiveChecksum() { + return clientReceiveChecksum; + } + /** @return 서버 포트 송신 인코드 캐릭터셋 */ + public Charset getServerSendCharset() { + return serverSendCharset; + } + /** @return 서버 포트 수신 디코드 캐릭터셋 */ + public Charset getServerReceiveCharset() { + return serverReceiveCharset; + } + /** @return 서버 포트 수신 체크섬 검증 여부 */ + public boolean isServerReceiveChecksum() { + return serverReceiveChecksum; + } + + @Bean(name = "packetQ") + public Queue packetQ(){ + return new LinkedBlockingQueue(); + } + +} diff --git a/src/main/java/kr/gmtc/eyegw/controller/MainController.java b/src/main/java/kr/gmtc/eyegw/controller/MainController.java new file mode 100644 index 0000000..d7f4a76 --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/controller/MainController.java @@ -0,0 +1,512 @@ +package kr.gmtc.eyegw.controller; + +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.annotation.Resource; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import gmt.common.type.LogLevelType; +import gmt.common.util.GmtUtils; +import gmt.common.vo.MsgObjVO; +import gmt.controller.GmtController; +import gmt.io.client.event.GmtClientEventListener; +import gmt.io.server.event.GmtServerEventListener; +import gmt.io.udp.event.GmtUDPEventListener; +import gmt.logger.GmtLogManager; +import kr.gmtc.eyegw.config.ServiceConfig; +import kr.gmtc.eyegw.db.DB1Connection; +import kr.gmtc.eyegw.file.TextReader; +import kr.gmtc.eyegw.file.TextReaderMergeAndSort; +import kr.gmtc.eyegw.frame.CustomThread; +import kr.gmtc.eyegw.frame.StatusReporter; + +@Component("controller") +public class MainController extends GmtController implements ApplicationListener { + + // 프레임 워크 구성요소 // + /** 서비스 설정, {@code application.yml} */ + @Resource(name = "ServiceConfig") + private ServiceConfig serviceConfig; + + /* 상태 확인 스테드 */ + private StatusReporter stateReporter; + + /* 실생상태 확인 */ + private boolean running = false; + + /* UDP test 소켓 */ + //UDPEchoClient UDPSocket ; + + private long lSendCnt = 0; + + @Resource(name = "packetQ") + Queue packetQ; + + @Value("${asde.filepath1}") + private String sfilepath1; + + @Value("${asde.filepath2}") + private String sfilepath2; + + public Queue> fileQ; + + // DB // + /** + * DB1 Connection
+ * application.yml에 db.db1.use가 true로 설정되어야 사용가능
+ * db.db1.use가 false일 경우 주석처리 (Bean 런타임 에러 발생) + * @see DB1Connection + */ + @Resource(name = "DB1Connection") + private DB1Connection db1Connection; + + + // 업무처리 // + /** 업무 처리 스레드 */ + private CustomThread bizThread; + + + /** + * 수정 금지
+ * Spring Bean 객체 생성, logger 초기화 + */ + public MainController(@Value("${root}") String path) { + super(path); + + GmtLogManager.setpath(path); + } + + /** + * 체크섬 검증
+ * 끝에서 3자리 가져와서 검증
+ * 체크섬 검증 옵션이 false이면 무조건 true 반환 + * @param msg 메시지 + * @param spliter 체크섬 구분자 + * @return 체크섬 검증 결과, 체크섬 확인옵션이 false면 무조건 true 리턴 + */ + private boolean verifyChecksum(final String msg, final String originalMsg) { + // 메시지 길이 체크 + if (msg == null || msg.trim().isEmpty()) { + return false; + } + // 체크섬 검증 + try { + char splitChar = msg.charAt(msg.length() - 4); + if (splitChar == '*') { + String inputChecksum = msg.substring(msg.length() - 2, msg.length()); + //String realChecksum = GmtUtils.makeCRC(originalMsg.getBytes()); + String realChecksum = GmtUtils.makeCRC(originalMsg); + return inputChecksum.equals(realChecksum); + } + } catch (@SuppressWarnings("unused") Exception e) { + // Nothing to do + } + return false; + } + + /** + * 디코드
+ * null safe + * @param rawMsg 수신 한 메시지 + * @return 디코드 된 메시지, 비어있는 메지시는 빈 String 반환 + */ + private String decodeString(final byte[] rawMsg, Charset charset) { + // 메시지 길이 체크 + if (rawMsg == null || rawMsg.length < 1) { + return ""; + } + // 캐릭터 셋에 맞게 디코드 + return new String(rawMsg, charset).trim(); + } + + /** + * 실행 (1순위)
+ * 프로그램 초기화 + */ + @Order(0) + @EventListener(ApplicationReadyEvent.class) + public void initialize() { + try { + // 상태보고 스레드 생성, 1분간격으로 보고 + stateReporter = new StatusReporter(this, CustomThread.SLEEP_MINIUTE); + + // 업무 스레드 생성, 대기 없이 무한반복 + bizThread = new CustomThread("bizThread", this, CustomThread.NO_SLEEP, this::bizWork, null, false); + + // UDP소켓 객체 생성 + //UDPSocket = new UDPEchoClient(); + + fileQ = new LinkedBlockingQueue>(); + + } catch(Exception e){ + logger.writeLevelLog("[MainController] Prepare Fail " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + System.exit(1); + } + } + + + /** + * 실행 (2순위)
+ * 프로그램 실행 + */ + @Override + @Order(1) + @EventListener(ApplicationReadyEvent.class) + public void start() { + try { + running = true; + super.start(); + + // 상태보고 스레드 시작 + //stateReporter.start(); + + // 업무로직 시작 + bizThread.start(); + + // UDP수신 시작 + //UDPSocket.start(); + + getFileBufer(fileQ, sfilepath1, sfilepath2); + + } catch (Exception e) { + logger.writeLevelLog("[MainController] Start Fail " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + System.exit(1); + } + } + + /** + * 업무 로직
+ * 자동으로 무한반복 하므로 내부에 while문 필요 없음.
+ * 예외처리를 하지 않을 경우 {@link CustomThread} 내부에서 로그 처리 + */ + private void bizWork() throws InterruptedException { + + String msg = ""; + + // 읽어드린 데이터를 모두 전송한경우 초기화 + if(fileQ.peek() == null) { + getFileBufer(fileQ, sfilepath1, sfilepath2); + lSendCnt = 0; + } + + try { + + int iSleep = 0; + + // 클라이언트 포트 브로드캐스트 + MsgObjVO msgVO = new MsgObjVO(); + if(fileQ.peek() != null) { + + Map qMap = new HashMap(); + Map qMap_after = new HashMap(); + + qMap = fileQ.poll(); + + //msgVO.setMsg(qMap.get("data").getBytes(serviceConfig.getClientSendCharset())); + + String sHexData = qMap.get("data").replaceAll("\\p{Z}", ""); + + msgVO.setMsg(new java.math.BigInteger(sHexData, 16).toByteArray()); + broadcastUDP(msgVO); + + // 다음 전송까지 대기 시간 계산 + qMap_after = fileQ.peek(); + + String sTime_befre = qMap.get("time"); + String sTime_after = qMap_after.get("time"); + + Date tb = new SimpleDateFormat("yyyyMMddHHmmss").parse(sTime_befre); + Date ta = new SimpleDateFormat("yyyyMMddHHmmss").parse(sTime_after); + + long diffSec = (ta.getTime() - tb.getTime()); + + logger.writeLevelLog("[MainController-bizWork] send log : " + "***전송:" + sTime_befre + "***다음:" + sTime_after + "***차이:" + diffSec, LogLevelType.LOG_INFO, "AllLog"); + +// if(diffSec <0 ) { +// String sTim = "" ; +// } + lSendCnt ++; + +// System.out.print("\n***" + lSendCnt + "건 전송*** " + qMap.get("data")); + + Thread.sleep(diffSec); + } + + } catch (InterruptedException e) { + if (running) { + logger.writeLevelLog("[MainController-bizWork] InterruptedException : " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + } else { // 종료 중 인터럽트 발생 시 throw + System.out.println(e); + } + } catch (Exception e) { + if (running) { + logger.writeLevelLog("[MainController-bizWork] running process Exception : " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + } else { // 종료 중 인터럽트 발생 시 throw + System.out.println(e); + } + } + + + } + + + public void getFileBufer(Queue> fileQ, String sFilePath1, String sFilePath2) { + + //TextReader rf = new TextReader(file1, file2, sFilePath1, sFilePath2); + TextReaderMergeAndSort rf = new TextReaderMergeAndSort(fileQ, sFilePath1, sFilePath2); + rf.readFile(); + // System.out.println(result); + + } + + public static byte[] binaryStringToByteArray(String s) { + int count = s.length() / 8; + byte[] b = new byte[count]; + for (int i = 1; i < count; ++i) { + String t = s.substring((i - 1) * 8, i * 8); + b[i - 1] = binaryStringToByte(t); + } + return b; + } + + + public static byte binaryStringToByte(String s) { + byte ret = 0, total = 0; + for (int i = 0; i < 8; ++i) { + ret = (s.charAt(7 - i) == '1') ? (byte) (1 << i) : 0; + total = (byte) (ret | total); + } + return total; + } + + + + /** 종료 처리 */ + @Override + public void stop() { + super.stop(); + + // UDP소켓 종료 +// try { +// UDPSocket.start(); +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + + } + + /** 종료 이벤트 (강제종료시 수행 안됨) */ + @Override + public void onApplicationEvent(@SuppressWarnings("unused") ContextClosedEvent event) { + this.stop(); + logger.writeLevelLog("====================== SYSTEM STOPED ======================", LogLevelType.LOG_INFO, "AllLog"); + } + + /** 클라이언트 포트 데이터 수신 */ + @Override + protected void clientDataIn(MsgObjVO vo) { + if (vo.getMsg().length < 1) { + return; + } + + try { + // 메시지 디코드 + final String msg = decodeString(vo.getMsg(), serviceConfig.getClientReceiveCharset()); + // 체크섬 제거한 데이터 추출 + String originalMsg = msg.substring(0, msg.length() - 3); + // 체크섬 검증 + if (serviceConfig.isClientReceiveChecksum() && !verifyChecksum(msg, originalMsg)) { + return; // 체크섬 에러 발생 시 무시 + } + + // TODO: 메시지 처리 + + } catch (Exception e) { + logger.writeLevelLog("[clientDataIn] Unknown Exception Occur2. " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + } + + } + + /** 서버 포트 데이터 수신 */ + @Override + protected void serverDataIn(MsgObjVO vo) { + if (vo.getMsg().length < 1) { + return; + } + + try { + // 메시지 디코드 + final String msg = decodeString(vo.getMsg(), serviceConfig.getClientReceiveCharset()); + // 체크섬 제거한 데이터 추출 + String originalMsg = msg.substring(0, msg.length() - 3); + // 체크섬 검증 + if (serviceConfig.isServerReceiveChecksum() && !verifyChecksum(msg, originalMsg)) { + return; // 체크섬 에러 발생 시 무시 + } + + // TODO: 메시지 처리 + + } catch (Exception e) { + logger.writeLevelLog("[serverDataIn] Unknown Exception Occur. " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + } + } + + /** 시리얼 포트 데이터 수신 */ + @Override + protected void serialDataIn(MsgObjVO vo) { + if (vo.getMsg().length < 1) { + return ; + } + + try { + // TODO: 메시지 처리 + }catch (Exception e) { + logger.writeLevelLog("[serialDataIn] Unknown Exception Occur. " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + } + } + + + /** Client 이벤트 */ + @SuppressWarnings({ "unused", "synthetic-access"}) + @Override + protected GmtClientEventListener createClientEventListener() { + return new GmtClientEventListener() { + @Override + public void disconnected(String ip, int port, int statusCode, String description) { + String msg = String.format("[Client Disconnect : IP[%s] / PORT [%d]", ip, port); + logger.writeLevelLog(msg, LogLevelType.LOG_INFO, "AllLog"); + } + @Override + public void connected(String ip, int port, int statusCode, String description) { + String msg = String.format("[Client Connect : IP[%s] / PORT [%d]", ip, port); + logger.writeLevelLog(msg, LogLevelType.LOG_INFO, "AllLog"); + } + @Override + public void readyToSend() {} + @Override + public void error(String ip, int port, int errorCode, String description) {} + @Override + public void dataIn() {} + @Override + public void connectionStatus(String ip, int port, String connEvent, int statusCode, String description) {} + @Override + public void SSLStatus() {} + @Override + public void SSLServerAuthentication() {} + }; + } + + /** Server 이벤트 */ + @SuppressWarnings({ "unused", "synthetic-access"}) + @Override + protected GmtServerEventListener createServerEventListener() { + return new GmtServerEventListener() { + @Override + public void disconnected(int serverPort, String remoteHost, int remotePort) { + String msg = String.format("[SERVER %d ] SC Disconnected.. IP : %s PORT : %d", serverPort, remoteHost, remotePort); + logger.writeLevelLog(msg, LogLevelType.LOG_INFO, "AllLog"); + } + @Override + public void connected(int serverPort, String remoteHost, int remotePort) { + String msg = String.format("[SERVER %d ] SC Connected.. IP : %s PORT : %d", serverPort, remoteHost, remotePort); + logger.writeLevelLog(msg, LogLevelType.LOG_INFO, "AllLog"); + } + @Override + public void readyToSend(int port) {} + @Override + public void error(int serverPort, String remoteHost, int remotePort, int errorCode, String description) {} + @Override + public void dataIn(int serverPort, String remoteHost, int remotePort, String msg) {} + @Override + public void SSLClientAuthentication(int serverPort) {} + }; + + } + + @Override + protected void udpDataIn(MsgObjVO vo) { + if (vo.getMsg().length < 1) { + return; + } + + try { + // 메시지 디코드 + final String msg = decodeString(vo.getMsg(), serviceConfig.getClientReceiveCharset()); +// // 체크섬 제거한 데이터 추출 +// String originalMsg = msg.substring(0, msg.length() - 3); +// // 체크섬 검증 +// if (serviceConfig.isClientReceiveChecksum() && !verifyChecksum(msg, originalMsg)) { +// return; // 체크섬 에러 발생 시 무시 +// } + + // TODO: 메시지 처리 + packetQ.add(msg); + + } catch (Exception e) { + logger.writeLevelLog("[clientDataIn] Unknown Exception Occur1. " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + } + } + + @Override + protected GmtUDPEventListener createUDPEventListener() { + GmtUDPEventListener listener = new GmtUDPEventListener() { + + @Override + public void readyToSend() { + // TODO Auto-generated method stub + + } + + @Override + public void error(String ip, int port, int errorCode, String description) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnected(String ip, int port, int statusCode, String description) { + String msg = "[UDP Socket Disconnect : IP[" + ip + "] / PORT [" + String.valueOf(port) + "] "; + logger.writeLevelLog(msg, LogLevelType.LOG_INFO, "AllLog"); + } + + @Override + public void dataIn(int serverPort, String remoteHost, int remotePort, String msg) { + String msgd = "[UDP Socket d : IP[" + remoteHost + "] / PORT [" + String.valueOf(remotePort) + "] |msg:"+ msg; + logger.writeLevelLog(msgd, LogLevelType.LOG_INFO, "AllLog"); + + } + + @Override + public void connectionStatus(String ip, int port, String connEvent, int statusCode, String description) { + // TODO Auto-generated method stub + + } + + @Override + public void connected(String ip, int port, int statusCode, String description) { + String msg = "[UDP Socket Connect : IP[" + ip + "] / PORT [" + String.valueOf(port) + "] "; + logger.writeLevelLog(msg, LogLevelType.LOG_INFO, "AllLog"); + + } + + }; + + return listener; + } +} + + diff --git a/src/main/java/kr/gmtc/eyegw/db/DB1Connection.java b/src/main/java/kr/gmtc/eyegw/db/DB1Connection.java new file mode 100644 index 0000000..498f4fe --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/db/DB1Connection.java @@ -0,0 +1,83 @@ +package kr.gmtc.eyegw.db; + +import javax.annotation.Resource; +import javax.sql.DataSource; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.type.JdbcType; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Mapper +@Configuration +@EnableTransactionManagement +@ConditionalOnProperty("db.db1.use") +@Component("DB1Connection") +public class DB1Connection { + + @Bean(name="DB1DataSource") + @ConfigurationProperties(prefix = "db.db1.datasource") + public DataSource db1DataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name="DB1SqlSessionFactory") + public SqlSessionFactory db1SqlSessionFactory( + @Qualifier("DB1DataSource") DataSource dataSource, + ApplicationContext applicationContext) throws Exception { + + SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); + + // DataSource 지정 + sqlSessionFactoryBean.setDataSource(dataSource); + + // sqlmap 경로 지정 + sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:/kr/gmtc/eyegw/mapper/dao1/DB1.xml")); + + // 캐시 사용 여부 + sqlSessionFactoryBean.getObject().getConfiguration().setCacheEnabled(false); + + // JDBC null 데이터 타입 지정 + sqlSessionFactoryBean.getObject().getConfiguration().setJdbcTypeForNull(JdbcType.NULL); + + + + return sqlSessionFactoryBean.getObject(); + } + + @Bean(name = "DB1Session") + public SqlSessionTemplate session( + @Qualifier("DB1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { + return new SqlSessionTemplate(sqlSessionFactory); + } + + @Bean(name = "DB1BatchSession") + public SqlSessionTemplate batchSession( + @Qualifier("DB1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { + return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH); + } + + @Resource(name = "DB1Session") + public SqlSessionTemplate session; + + @Resource(name = "DB1BatchSession") + public SqlSessionTemplate batchSession; + + public boolean isAlive() { + session.selectOne("kr.gmtc.eyegw.mapper.dbo1.DB1.ping"); + return true; + } + + +} diff --git a/src/main/java/kr/gmtc/eyegw/file/TextReader.java b/src/main/java/kr/gmtc/eyegw/file/TextReader.java new file mode 100644 index 0000000..fa7f08b --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/file/TextReader.java @@ -0,0 +1,67 @@ +package kr.gmtc.eyegw.file; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Queue; + +import org.springframework.beans.factory.annotation.Value; + +public class TextReader { + + Queue fileQ1; + Queue fileQ2; + + private String sfilepath1; + private String sfilepath2; + + public TextReader(Queue fileQ1, Queue fileQ2, String sFilePath1, String sFilePath2) { + super(); + + this.fileQ1 = fileQ1; + this.fileQ2 = fileQ2; + this.sfilepath1 = sFilePath1; + this.sfilepath2 = sFilePath2; + } + + public void readFile() { + try{ + //파일 객체 생성 + File file1 = new File(sfilepath1); + File file2 = new File(sfilepath2); + + BufferedReader inFiles = new BufferedReader(new InputStreamReader(new FileInputStream(file1), StandardCharsets.UTF_8)); + + String line = ""; + while((line = inFiles.readLine()) != null){ + //if((char)singleCh == '\r') + + fileQ1.offer(line); + //System.out.print("n\r" + line); + + } + inFiles.close(); + + inFiles = new BufferedReader(new InputStreamReader(new FileInputStream(file2), StandardCharsets.UTF_8)); + line = ""; + while((line = inFiles.readLine()) != null){ + //if((char)singleCh == '\r') + + fileQ2.offer(line); + //System.out.print("n\r" + line); + + } + inFiles.close(); + + }catch (FileNotFoundException e) { + // TODO: handle exception + }catch(IOException e){ + System.out.println(e); + } + } +} diff --git a/src/main/java/kr/gmtc/eyegw/file/TextReaderMergeAndSort.java b/src/main/java/kr/gmtc/eyegw/file/TextReaderMergeAndSort.java new file mode 100644 index 0000000..d7e6562 --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/file/TextReaderMergeAndSort.java @@ -0,0 +1,156 @@ +package kr.gmtc.eyegw.file; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Queue; + +import XcoreXipworksX160X6588.is; + +public class TextReaderMergeAndSort { + + HashMap splitMap; + + ArrayList> splitMaps1 = new ArrayList>(); + ArrayList> splitMaps2 = new ArrayList>(); + ArrayList> mergeList = new ArrayList>(); + + Queue> fileQ; + + private String sfilepath1; + private String sfilepath2; + + public TextReaderMergeAndSort(Queue> fileQ, String sFilePath1, String sFilePath2) { + super(); + + this.fileQ = fileQ; + this.sfilepath1 = sFilePath1; + this.sfilepath2 = sFilePath2; + } + + public void readFile() { + try{ + //파일 객체 생성 + File file1 = new File(sfilepath1); + File file2 = new File(sfilepath2); + + BufferedReader inFiles = new BufferedReader(new InputStreamReader(new FileInputStream(file1), StandardCharsets.UTF_8)); + + String line = ""; + String lineSplit[] = null; + while((line = inFiles.readLine()) != null){ + + splitMap = new HashMap(); + + lineSplit = line.split("[|]"); + + splitMap.put("time", lineSplit[0]); + splitMap.put("data", lineSplit[1]); + + splitMaps1.add(splitMap); + + } + inFiles.close(); + + inFiles = new BufferedReader(new InputStreamReader(new FileInputStream(file2), StandardCharsets.UTF_8)); + line = ""; + while((line = inFiles.readLine()) != null){ + splitMap = new HashMap(); + + lineSplit = line.split("[|]"); + + splitMap.put("time", lineSplit[0]); + splitMap.put("data", lineSplit[1]); + + splitMaps2.add(splitMap); + + } + inFiles.close(); + + mergeList.addAll(splitMaps1); + mergeList.addAll(splitMaps2); + + + + // queue에 순서대로 담기 + int iSize = mergeList.size(); + if(iSize > 0) { + for(int idx=0; idx < iSize; idx++) { + + // Unix Time -> KST Time으로 변환 + try { + String sUnixTime = mergeList.get(idx).get("time"); + + sUnixTime = sUnixTime.substring(0, sUnixTime.indexOf(".") ); + + long ltimestamp = Long.parseLong(sUnixTime); + + Date localdate = new Date(ltimestamp * 1000L); + + SimpleDateFormat sformat = new SimpleDateFormat("yyyyMMddHHmmss"); + + sformat.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9")); + + String sCnvDate = sformat.format(localdate); + + mergeList.get(idx).put("time", sCnvDate); + + } catch (Exception e) { + System.out.println(e); + } + } + } + + // Unix Time 기준으로 오름차순 정렬 + + int iTmp = 0; + + try { + + while(iTmp <= mergeList.size()) { + + iTmp++; + + Collections.sort(mergeList, new Comparator>() { + @Override + public int compare(HashMap first, HashMap second) { + + String sfirst = first.get("time"); + + String ssecond = second.get("time"); + + return sfirst.compareTo(ssecond); + } + }); + } + + } catch (Exception e) { + System.out.println(e); + } + + // 큐에 담기 + // queue에 순서대로 담기 + for(int idx=0; idx < iSize; idx++) { + fileQ.offer(mergeList.get(idx)); + } + + + }catch (FileNotFoundException e) { + // TODO: handle exception + }catch(IOException e){ + System.out.println(e); + } + } + +} diff --git a/src/main/java/kr/gmtc/eyegw/frame/CustomThread.java b/src/main/java/kr/gmtc/eyegw/frame/CustomThread.java new file mode 100644 index 0000000..f65345a --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/frame/CustomThread.java @@ -0,0 +1,118 @@ +package kr.gmtc.eyegw.frame; + +import gmt.common.type.LogLevelType; +import gmt.logger.GmtLogManager; +import kr.gmtc.eyegw.frame.handler.CustomThreadOnTerminate; +import kr.gmtc.eyegw.frame.handler.CustomThreadWork; + +public class CustomThread extends Thread{ + + /* 대기시간 없음 */ + public static final long NO_SLEEP = 0; + /* 1밀리 초 */ + public static final long SLEEP_MILLI_SEC = 1; + /* 1초 */ + public static final long SLEEP_SECOND = 1000; + /* 30초 */ + public static final long SLEEP_HALF_MINIUTE = 30000; + /* 1분 */ + public static final long SLEEP_MINIUTE = 60000; + + public final String controllClassName; + public final long repeatMiliSec; + public final CustomThreadWork definedWork; + public final CustomThreadOnTerminate definedTerminate; + public final GmtLogManager logger; + private boolean running; + + /** + * 인터럽트를 받을 시 스레드가 종료됨.
+ * {@link Thread#sleep(long)} 기반으로 재실행 간격을 설정하므로 정확한 실행시간을 보장하지 않음.
+ * 정확한 실행시간 보장이 필요 할 경우 sleep 간격을 짧게 설정하고 호출위치에서 시간확인
+ * 정상적인 종료는 {@link #gracefulStop()}으로 종료함 + * @param threadName 스레드 이름 + * @param controllClass 스레드 관리 클래스, 일반적으로 this 사용 + * @param repeatMiliSec Sleep 시간(밀리 초), 0이하의 경우 대기시간 없음 + * @param definedWork 반복할 작업 + * @param definedTerminate 스레드가 인터럽트에 의해 종료될 경우 할 작업 + * @param autoStart 생성즉시 실행 + */ + + public CustomThread(String threadName, Object controllClass, long repeatMiliSec, + CustomThreadWork definedWork, CustomThreadOnTerminate definedTerminate, boolean autoStart) { + + if (definedWork == null) { + throw new IllegalArgumentException("[CustomThread] - definedWork is null."); + } + + this.definedWork = definedWork; + this.definedTerminate = definedTerminate; + this.controllClassName = controllClass == null ? "" : controllClass.getClass().getSimpleName(); + this.repeatMiliSec = repeatMiliSec > 0 ? repeatMiliSec : 0; + this.logger = GmtLogManager.getInstance(); + this.running = false; + + setName(threadName); + setDaemon(true); + if (autoStart) { + this.start(); + } + } + + + private void log(LogLevelType level, String message) { + String str = String.format("[%s] - %s: %s", controllClassName, getName(), message); + logger.writeLevelLog(str, level, "AllLog"); + } + + + @Override + public void run() { + log(LogLevelType.LOG_INFO, "Started."); + while ( this.running && !this.isInterrupted()) { + try { + try { + this.definedWork.work(); + } finally { + if (this.repeatMiliSec > 0) { + Thread.sleep(this.repeatMiliSec); + } + } + } catch(InterruptedException e) { // 인터럽트 수신시 종료 + log(LogLevelType.LOG_ERROR, "Interrupted. " + e.toString()); + Thread.currentThread().interrupt(); + break; + } catch(Exception e) { // 처리되지 않은 예외 로깅, 예외에 의한 무한루프에 주의 + log(LogLevelType.LOG_ERROR, "Unknown Exception Occur. " + e.toString()); + } + } + + if(this.definedTerminate != null) { + this.definedTerminate.onTerminate(); + } + + log(LogLevelType.LOG_ERROR, "Stoped."); + + } + + @Override + public String toString() { + + return "CustomThread [controllClass=" + this.controllClassName + ", threadName=" + getName() + + ", runnig=" + this.running + ", alive=" + isAlive()+ ", repeatMiliSec=" + this.repeatMiliSec + + ", definedTerminate=" + (this.definedTerminate == null ? "no" : "yes") + "]"; + } + + @Override + public synchronized void start() { + this.running = true; + super.start(); + } + + /** + * 스레드 정상종료, 진행중인 작업 완료 후 종료됨. + */ + public void gracefulStop() { + this.running = false; + } +} diff --git a/src/main/java/kr/gmtc/eyegw/frame/StatusReporter.java b/src/main/java/kr/gmtc/eyegw/frame/StatusReporter.java new file mode 100644 index 0000000..95056fb --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/frame/StatusReporter.java @@ -0,0 +1,104 @@ +package kr.gmtc.eyegw.frame; + +import gmt.common.type.LogLevelType; +import gmt.io.client.vo.ClientInfoVO; +import gmt.io.server.vo.ServerInfoVO; +import gmt.io.server.vo.ServiceClientVO; +import gmt.logger.GmtLogManager; +import kr.gmtc.eyegw.controller.MainController; + +public class StatusReporter { + private final CustomThread reporter; + private final MainController controller; + private final GmtLogManager logger; + + public StatusReporter(MainController controller, long reportInterval) { + reporter = new CustomThread("stateReporter", controller, reportInterval, this::reportState, null, false); + this.controller = controller; + this.logger = GmtLogManager.getInstance(); + } + + /** 상태 보고 스레드 */ + private void reportState() { + try { + StringBuilder logContent = new StringBuilder(); + logContent.append("\n=================== Monitoring info ==================="); + logContent.append("\n"); + logContent.append(String.format("1. Total RcvQ : %d/%d", controller.getCurrnetRecvQCount(), 100000)); + logContent.append("\n"); + logContent.append(String.format("2. Total SndQ : %d/%d", controller.getCurrnetSendQCount(), 100000)); + int cnt; + if (controller.clientAccess) { + logContent.append("\n3. Client Monitor Info(s)"); + cnt = 0; + for (ClientInfoVO clientInfo: controller.clientInfoList) { + String infoStr = String.format("%d. [%s:%d] %s: Rcv - %d, Snd - %d, QCnt - %d/%d", + cnt++, + clientInfo.getIp(), + clientInfo.getPort(), + clientInfo.getName(), + clientInfo.getMonitorInfo().getRecvMonitorCount(), + clientInfo.getMonitorInfo().getSendMonitorCount(), + clientInfo.getMonitorInfo().getSendQCount(), + clientInfo.getMonitorInfo().getSendQBufferCount()); + logContent.append("\n\t"); + logContent.append(infoStr); + } + } else { + logContent.append("\n3. Client Not Used."); + } + + if (controller.serverAccess) { + logContent.append("\n4. Server Monitor Info(s)"); + cnt = 0; + for (ServerInfoVO serverInfo: controller.serverInfoList) { + String infoStr = String.format("%d. [:%d] %s: SC cnt - %d, QCnt - %d/%d", + cnt++, + serverInfo.getPort(), + serverInfo.getName(), + serverInfo.getServiceClientCount(), + serverInfo.getSndQcount(), + serverInfo.getMaxSndQCount()); + logContent.append("\n\t"); + logContent.append(infoStr); + } + logContent.append("\n5. Service Client Monitor Info(s)"); + + cnt = 0; + for (ServiceClientVO serverClientVO: controller.serverScInfoList.values()) { + String infoStr = String.format("%d. [:%d <- %s:%d] %s: Rcv - %d, Snd - %d, RcvByte - %d, SndByte - %d, Qcnt - %d/%d", + cnt++, + serverClientVO.getServerPort(), + serverClientVO.getIp(), + serverClientVO.getServicePort(), + serverClientVO.getName(), + serverClientVO.getMonitorInfoVO().getRecvMonitorCount(), + serverClientVO.getMonitorInfoVO().getSendMonitorCount(), + serverClientVO.getMonitorInfoVO().getRecvMonitorByteSize(), + serverClientVO.getMonitorInfoVO().getSendMonitorByteSize(), + serverClientVO.getMonitorInfoVO().getSendQCount(), + serverClientVO.getMonitorInfoVO().getSendQBufferCount()); + logContent.append("\n\t"); + logContent.append(infoStr); + } + } else { + logContent.append("\n\t4. Server Not Used."); + logContent.append("\n\t5. Service Client Not Used."); + } + logContent.append("\n======================================================="); + + logger.writeLevelLog("[reportState] Report Status:" + logContent.toString(), LogLevelType.LOG_INFO, "AllLog"); + } catch (Exception e) { + logger.writeLevelLog("[reportState] Unknown Exception Occur. " + e.getMessage(), LogLevelType.LOG_ERROR, "AllLog"); + } + } + + public void start() { + reporter.start(); + } + + public void stop() { + reporter.gracefulStop(); + } + +} \ No newline at end of file diff --git a/src/main/java/kr/gmtc/eyegw/frame/handler/CustomThreadOnTerminate.java b/src/main/java/kr/gmtc/eyegw/frame/handler/CustomThreadOnTerminate.java new file mode 100644 index 0000000..c864801 --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/frame/handler/CustomThreadOnTerminate.java @@ -0,0 +1,6 @@ +package kr.gmtc.eyegw.frame.handler; + +@FunctionalInterface +public interface CustomThreadOnTerminate { + public void onTerminate(); +} diff --git a/src/main/java/kr/gmtc/eyegw/frame/handler/CustomThreadWork.java b/src/main/java/kr/gmtc/eyegw/frame/handler/CustomThreadWork.java new file mode 100644 index 0000000..28323b1 --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/frame/handler/CustomThreadWork.java @@ -0,0 +1,6 @@ +package kr.gmtc.eyegw.frame.handler; + +@FunctionalInterface +public interface CustomThreadWork { + public void work() throws Exception; +} diff --git a/src/main/java/kr/gmtc/eyegw/udpsocket/UDPEchoClient.java b/src/main/java/kr/gmtc/eyegw/udpsocket/UDPEchoClient.java new file mode 100644 index 0000000..34d62c5 --- /dev/null +++ b/src/main/java/kr/gmtc/eyegw/udpsocket/UDPEchoClient.java @@ -0,0 +1,47 @@ +package kr.gmtc.eyegw.udpsocket; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; + +public class UDPEchoClient { + + final static String SERVER_IP = "localhost"; + final static int SERVER_PORT = 3384; + + DatagramSocket ds; + + public void start() throws IOException { + + ds = new DatagramSocket(3384); // 패킷을 전송받을 포트를 열어둔다. + + //ds.connect(new InetSocketAddress(7000)); + System.out.println("isConnected : "+ ds.isConnected()); + System.out.println("port : "+ ds.getPort()); + System.out.println("localAddr : "+ ds.getLocalAddress()); + System.out.println("localPort : "+ ds.getLocalPort()); + + while(true) { // 무한루프 통해 메시지 계속 전송받는다 + byte[] data = new byte[65508]; // 한번에 받을 수 있는 최대 용량의 데이터 공간은 기본 정보 공간을 제외한 65,508 byte + + //데이터를 수신받을 객체 + DatagramPacket dp = new DatagramPacket(data, data.length); + + ds.receive(dp); + + //전송받은 패킷이 발송된 곳의 IP주소와 내용 출력 + System.out.println(dp.getAddress().getHostAddress() + " >> " + new String(dp.getData()).trim()); + } + + } + + + + public void stop() { + if(!ds.isClosed()) { + ds.close(); + } + + } + +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..e1d727d --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,82 @@ +## Client/Server Port Configuration +## Default ## +#tcpip: +# client: +# send: UTF-8 +# receive: UTF-8 +# checksum: true +# server: +# receive: UTF-8 +# send: UTF-8 +# checksum: true +tcpip: + client: + send: UTF-8 + receive: UTF-8 + checksum: true + server: + receive: UTF-8 + send: UTF-8 + checksum: true + +server: + port: 8081 + + +asde: + filepath1: D:\\작업임시\\Asterix_Parse\\java\\Asterix010.txt + filepath2: D:\\작업임시\\Asterix_Parse\\java\\Asterix011.txt + +## DB Configuration +db: + db1: + use: true + datasource: + poolName: IPT DB + jdbc-url: jdbc:oracle:thin:@118.220.143.155:1521:TEST155 + username: IPT + password: IPT + autoCommit: true + connectionTimeout: 3000 + idleTimeout: 600000 + keepaliveTime: 0 + maxLifetime: 1800000 + minimumIdle: 1 + maximumPoolSize: 5 +# db2: +# use: false +# datasource: +# poolName: secondary +# jdbc-url: jdbc:tibero:thin:@118.220.143.155:8629:secondary +# username: secondary +# password: secondary +# autoCommit: true +# connectionTimeout: 3000 +# idleTimeout: 600000 +# keepaliveTime: 0 +# maxLifetime: 1800000 +# minimumIdle: 1 +# maximumPoolSize: 5 + + +## Execution Profile +## spring.profiles - Execution Profile Name, Set as "-Dspring.profiles.active=${PROFILE}" +## root - Application installed location +--- +## "default" Execution Profile +spring: + profiles: default +# root: /home/manager/GMT/EyeGW_FlowController +root: D:\Workspace\Eclipse_UDP-Send\EyeGW-UDP-Send +--- +## "production" Execution Profile +spring: + profiles: production +# root: /home/manager/GMT/EyeGW_FlowController +root: D:\Workspace\Eclipse_UDP-Send\EyeGW-UDP-Send +--- +## "debug" Execution Profile +spring: + profiles: debug +# root: D:\[Project]\_E_Nav\UnSyncWorkSpace\EyeGW +root: D:\Workspace\Eclipse_UDP-Send\EyeGW-UDP-Send \ No newline at end of file diff --git a/src/main/resources/kr/gmtc/eyegw/mapper/dao1/DB1.xml b/src/main/resources/kr/gmtc/eyegw/mapper/dao1/DB1.xml new file mode 100644 index 0000000..317f2b4 --- /dev/null +++ b/src/main/resources/kr/gmtc/eyegw/mapper/dao1/DB1.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/main/resources/mybatis-config.xml b/src/main/resources/mybatis-config.xml new file mode 100644 index 0000000..bb904fd --- /dev/null +++ b/src/main/resources/mybatis-config.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/target/EyeGW-Core-1.0.0.jar b/target/EyeGW-Core-1.0.0.jar new file mode 100644 index 0000000..16e27a3 Binary files /dev/null and b/target/EyeGW-Core-1.0.0.jar differ