쓰레드 기능 개선, 서비스타입별(SMS, LMS, MMS) 쓰기큐 교체, 서비스 구동 설정 추가, 큐풀 개선등

This commit is contained in:
dsjang 2024-05-26 23:50:55 +09:00
parent 1454c2658a
commit 47f9eab3d3
23 changed files with 1575 additions and 69 deletions

View File

@ -47,6 +47,8 @@ dependencies {
implementation 'commons-beanutils:commons-beanutils:1.9.4' implementation 'commons-beanutils:commons-beanutils:1.9.4'
// https://mvnrepository.com/artifact/io.netty/netty-all // https://mvnrepository.com/artifact/io.netty/netty-all
implementation 'io.netty:netty-all:4.1.42.Final' implementation 'io.netty:netty-all:4.1.42.Final'
// https://mvnrepository.com/artifact/org.jdom/jdom2
implementation 'org.jdom:jdom2:2.0.6.1'
testCompileOnly 'org.projectlombok:lombok' testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok'

View File

@ -0,0 +1,39 @@
package com.munjaon.server.config;
import com.munjaon.server.server.service.PropertyLoader;
import lombok.RequiredArgsConstructor;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
@Configuration
@RequiredArgsConstructor
public class RunnerConfiguration {
private final ServerConfig serverConfig;
@Bean
@Order(1)
public CommandLineRunner getRunnerBeanForProperty() {
System.setProperty("PROPS", serverConfig.getServerProperyFile());
PropertyLoader.load();
try {
String[] array = serverConfig.getStringArray("test.list");
if (array != null && array.length > 0) {
for (String s : array) {
System.out.println("List : " + s);
}
}
} catch (ConfigurationException e) {
throw new RuntimeException(e);
}
return args -> System.out.println("Runner Bean #1 : " + serverConfig.getServerProperyFile());
}
@Bean
@Order(2)
public CommandLineRunner getRunnerBeanForService() {
return args -> System.out.println("Runner Bean #2");
}
}

View File

@ -1,6 +1,7 @@
package com.munjaon.server.config; package com.munjaon.server.config;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.ConfigurationBuilderEvent; import org.apache.commons.configuration2.builder.ConfigurationBuilderEvent;
@ -19,6 +20,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@Component @Component
public class ServerConfig { public class ServerConfig {
@Getter
@Value("${agent.server-property-file}") @Value("${agent.server-property-file}")
private String serverProperyFile; private String serverProperyFile;
@ -47,4 +49,13 @@ public class ServerConfig {
public int getInt(String key) throws ConfigurationException { public int getInt(String key) throws ConfigurationException {
return builder.getConfiguration().getInt(key, 3); return builder.getConfiguration().getInt(key, 3);
} }
public String[] getStringArray(String key) throws ConfigurationException {
return getStringArray(key, ",");
}
public String[] getStringArray(String key, String regExp) throws ConfigurationException {
String value = getString(key);
return value == null ? null : value.split(regExp);
}
} }

View File

@ -0,0 +1,52 @@
package com.munjaon.server.config;
import lombok.Getter;
@Getter
public enum ServiceCode {
OK(200, "Success"),
MSG_ERROR_USERID(300, "userId is Null OR is Over Limit Byte"),
MSG_ERROR_FEETYPE(301, "feeType is Null OR is Over Limit Byte"),
MSG_ERROR_UNITCOST(302, "unitCost is Null OR is Over Limit Byte"),
MSG_ERROR_MSGGROUPID(303, "msgGroupID is Null OR is Over Limit Byte"),
MSG_ERROR_USERMSGID(304, "userMsgID is Null OR is Over Limit Byte"),
MSG_ERROR_SERVICETYPE(305, "serviceType is Null OR is Over Limit Byte"),
MSG_ERROR_SENDSTATUS(306, "sendStatus is Null OR is Over Limit Byte"),
MSG_ERROR_USERSENDER(307, "userSender is Null OR is Over Limit Byte"),
MSG_ERROR_USERRECEIVER(308, "userReceiver is Null OR is Over Limit Byte"),
MSG_ERROR_REQUESTDT(309, "requestDt is Null OR is Over Limit Byte"),
MSG_ERROR_REMOTEIP(310, "remoteIP is Null OR is Over Limit Byte"),
MSG_ERROR_ROUTERSEQ(311, "routerSeq is Null OR is Over Limit Byte"),
/* SMS 메시지 */
MSG_ERROR_SMS_MESSAGE(400, "SMS Message is Null OR is Over Limit Byte"),
/* LMS, MMS 제목, 메시지 */
MSG_ERROR_MEDIA_SUBJECT(500, "LMS, MMS Subject is Null OR is Over Limit Byte"),
MSG_ERROR_MEDIA_MESSAGE(501, "LMS, MMS Message is Null OR is Over Limit Byte"),
ETC_ERROR(999, "ETC ERROR");
private Integer code;
private String message;
ServiceCode(Integer code, String msg) {
this.code = code;
this.message = msg;
}
public static String getMessage(Integer code) {
if (code == null) {
return "etc";
}
for (ServiceCode resCode : values()) {
if (resCode.getCode().equals(code)) {
return resCode.getMessage();
}
}
return "etc";
}
}

View File

@ -20,6 +20,8 @@ public final class MediaBodyConfig {
public static final int FILENAME_THREE_BYTE_LENGTH = 128; public static final int FILENAME_THREE_BYTE_LENGTH = 128;
public static final int FILENAME_THREE_BYTE_POSITION = FILENAME_TWO_BYTE_POSITION + FILENAME_TWO_BYTE_LENGTH; public static final int FILENAME_THREE_BYTE_POSITION = FILENAME_TWO_BYTE_POSITION + FILENAME_TWO_BYTE_LENGTH;
/* Media Body 길이 */ /* LMS Body 길이 */
public static final int MEDIA_SUM_BYTE_LENGTH = BodyCommonConfig.COMMON_SUM_BYTE_LENGTH + SUBJECT_BYTE_LENGTH + MEDIA_MSG_BYTE_LENGTH + FILECNT_BYTE_LENGTH + FILENAME_ONE_BYTE_LENGTH + FILENAME_TWO_BYTE_LENGTH + FILENAME_THREE_BYTE_LENGTH; public static final int LMS_SUM_BYTE_LENGTH = BodyCommonConfig.COMMON_SUM_BYTE_LENGTH + SUBJECT_BYTE_LENGTH + MEDIA_MSG_BYTE_LENGTH;
/* MMS Body 길이 */
public static final int MMS_SUM_BYTE_LENGTH = BodyCommonConfig.COMMON_SUM_BYTE_LENGTH + SUBJECT_BYTE_LENGTH + MEDIA_MSG_BYTE_LENGTH + FILECNT_BYTE_LENGTH + FILENAME_ONE_BYTE_LENGTH + FILENAME_TWO_BYTE_LENGTH + FILENAME_THREE_BYTE_LENGTH;
} }

View File

@ -8,9 +8,9 @@ import lombok.ToString;
@Setter @Setter
@ToString @ToString
public class BasicMessageDto { public class BasicMessageDto {
protected String userId = ""; protected String userId = ""; // 사용자 아이디
protected String feeType = ""; protected final String feeType = "A"; // 요금제(선불 : P / 후불 : A)
protected String unitCost = ""; protected String unitCost = ""; // 단가
protected String msgGroupID = "0"; protected String msgGroupID = "0";
protected String userMsgID = ""; protected String userMsgID = "";
protected String serviceType = ""; protected String serviceType = "";
@ -23,5 +23,13 @@ public class BasicMessageDto {
protected String routerSeq = "0"; protected String routerSeq = "0";
protected String userMessage = ""; protected String userMessage = "";
protected String userMsgType = "";
protected String userSubject = "";
protected int userFileCnt = 0;
protected String userFileName01;
protected String userFileName02;
protected String userFileName03;
protected int userFileSize01 = 0;
protected int userFileSize02 = 0;
protected int userFileSize03 = 0;
} }

View File

@ -1,11 +1,13 @@
package com.munjaon.server.queue.dto; package com.munjaon.server.queue.dto;
import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Getter @Getter
@Setter @Setter
@Builder
@ToString @ToString
public class QueueInfo { public class QueueInfo {
private String queueName = ""; private String queueName = "";

View File

@ -0,0 +1,84 @@
package com.munjaon.server.queue.pool;
import com.munjaon.server.queue.dto.BasicMessageDto;
import com.munjaon.server.queue.service.LmsWriteQueue;
import java.util.LinkedList;
public class LmsQueuePool {
/** Lock Object */
private final Object lockMonitor = new Object();
/** File Queue Pool */
private final LinkedList<LmsWriteQueue> queuePool = new LinkedList<>();
/** File Queue */
private LmsWriteQueue queue = null;
/** File Queue 분배를 위한 인덱서 */
private int queueIndex = 0;
/** Singleton Instance */
private static SmsQueuePool fileQueue;
public synchronized static SmsQueuePool getInstance(){
if(fileQueue == null){
fileQueue = new SmsQueuePool();
}
return fileQueue;
}
/** Queue 존재하는지 조회 */
public boolean isExistQueue(String name){
synchronized(lockMonitor){
boolean isExist = false;
for (LmsWriteQueue writeQueue : queuePool) {
if (name.equals(writeQueue.getQueueName())) {
isExist = true;
break;
}
}
return isExist;
}
}
/** Queue 제거 */
public void removeQueue(String name){
synchronized(lockMonitor) {
for (int loopCnt = 0; loopCnt < queuePool.size(); loopCnt++) {
queue = queuePool.get(loopCnt);
if(name.equals(queue.getQueueName())){
queuePool.remove(loopCnt);
System.out.println("[LMS Queue] [" + queue.getQueueName() + " is Removed]");
break;
}
}
}
}
/** Queue 등록 */
public void addShortQueue(LmsWriteQueue queue){
synchronized(lockMonitor){
if (queue != null){
queuePool.addLast(queue);
lockMonitor.notifyAll();
}
}
}
/** Queue 데이터 저장 */
public void pushQueue(BasicMessageDto data) throws Exception{
synchronized(lockMonitor) {
if (queuePool.isEmpty()) {
try{
lockMonitor.wait();
}catch(InterruptedException e){
// 아무 처리도 하지 않는다.
}
}
//큐리스트의 끝까지 이동한 경우 처음으로 되돌린다.
if (queueIndex >= queuePool.size()) {
queueIndex = 0;
}
// 파일큐에 Push 한다.
queue = queuePool.get(queueIndex);
queue.pushMessageToBuffer(data);
// 큐인덱서를 증가시킨다.
queueIndex++;
}
}
}

View File

@ -0,0 +1,84 @@
package com.munjaon.server.queue.pool;
import com.munjaon.server.queue.dto.BasicMessageDto;
import com.munjaon.server.queue.service.MmsWriteQueue;
import java.util.LinkedList;
public class MmsQueuePool {
/** Lock Object */
private final Object lockMonitor = new Object();
/** File Queue Pool */
private final LinkedList<MmsWriteQueue> queuePool = new LinkedList<>();
/** File Queue */
private MmsWriteQueue queue = null;
/** File Queue 분배를 위한 인덱서 */
private int queueIndex = 0;
/** Singleton Instance */
private static SmsQueuePool fileQueue;
public synchronized static SmsQueuePool getInstance(){
if(fileQueue == null){
fileQueue = new SmsQueuePool();
}
return fileQueue;
}
/** Queue 존재하는지 조회 */
public boolean isExistQueue(String name){
synchronized(lockMonitor){
boolean isExist = false;
for (MmsWriteQueue writeQueue : queuePool) {
if (name.equals(writeQueue.getQueueName())) {
isExist = true;
break;
}
}
return isExist;
}
}
/** Queue 제거 */
public void removeQueue(String name){
synchronized(lockMonitor) {
for (int loopCnt = 0; loopCnt < queuePool.size(); loopCnt++) {
queue = queuePool.get(loopCnt);
if(name.equals(queue.getQueueName())){
queuePool.remove(loopCnt);
System.out.println("[MMS Queue] [" + queue.getQueueName() + " is Removed]");
break;
}
}
}
}
/** Queue 등록 */
public void addShortQueue(MmsWriteQueue queue){
synchronized(lockMonitor){
if (queue != null){
queuePool.addLast(queue);
lockMonitor.notifyAll();
}
}
}
/** Queue 데이터 저장 */
public void pushQueue(BasicMessageDto data) throws Exception{
synchronized(lockMonitor) {
if (queuePool.isEmpty()) {
try{
lockMonitor.wait();
} catch (InterruptedException e) {
// 아무 처리도 하지 않는다.
}
}
//큐리스트의 끝까지 이동한 경우 처음으로 되돌린다.
if (queueIndex >= queuePool.size()) {
queueIndex = 0;
}
// 파일큐에 Push 한다.
queue = queuePool.get(queueIndex);
queue.pushMessageToBuffer(data);
// 큐인덱서를 증가시킨다.
queueIndex++;
}
}
}

View File

@ -0,0 +1,84 @@
package com.munjaon.server.queue.pool;
import com.munjaon.server.queue.dto.BasicMessageDto;
import com.munjaon.server.queue.service.SmsWriteQueue;
import java.util.LinkedList;
public class SmsQueuePool {
/** Lock Object */
private final Object lockMonitor = new Object();
/** File Queue Pool */
private final LinkedList<SmsWriteQueue> queuePool = new LinkedList<>();
/** File Queue */
private SmsWriteQueue queue = null;
/** File Queue 분배를 위한 인덱서 */
private int queueIndex = 0;
/** Singleton Instance */
private static SmsQueuePool fileQueue;
public synchronized static SmsQueuePool getInstance(){
if(fileQueue == null){
fileQueue = new SmsQueuePool();
}
return fileQueue;
}
/** Queue 존재하는지 조회 */
public boolean isExistQueue(String name){
synchronized(lockMonitor){
boolean isExist = false;
for (SmsWriteQueue writeQueue : queuePool) {
if (name.equals(writeQueue.getQueueName())) {
isExist = true;
break;
}
}
return isExist;
}
}
/** Queue 제거 */
public void removeQueue(String name){
synchronized(lockMonitor) {
for (int loopCnt = 0; loopCnt < queuePool.size(); loopCnt++) {
queue = queuePool.get(loopCnt);
if(name.equals(queue.getQueueName())){
queuePool.remove(loopCnt);
System.out.println("[SMS Queue] [" + queue.getQueueName() + " is Removed]");
break;
}
}
}
}
/** Queue 등록 */
public void addShortQueue(SmsWriteQueue queue){
synchronized(lockMonitor){
if (queue != null){
queuePool.addLast(queue);
lockMonitor.notifyAll();
}
}
}
/** Queue 데이터 저장 */
public void pushQueue(BasicMessageDto data) throws Exception{
synchronized(lockMonitor) {
if (queuePool.isEmpty()) {
try{
lockMonitor.wait();
}catch(InterruptedException e){
// 아무 처리도 하지 않는다.
}
}
//큐리스트의 끝까지 이동한 경우 처음으로 되돌린다.
if (queueIndex >= queuePool.size()) {
queueIndex = 0;
}
// 파일큐에 Push 한다.
queue = queuePool.get(queueIndex);
queue.pushMessageToBuffer(data);
// 큐인덱서를 증가시킨다.
queueIndex++;
}
}
}

View File

@ -1,9 +1,21 @@
package com.munjaon.server.queue.service; package com.munjaon.server.queue.service;
import com.munjaon.server.queue.dto.KakaoMessageDto; import com.munjaon.server.queue.dto.BasicMessageDto;
public class KakaoWriteQueue extends WriteQueue { public class KakaoWriteQueue extends WriteQueue {
public void pushBuffer(KakaoMessageDto data) throws Exception {
@Override
int isisValidateMessageForExtend(BasicMessageDto messageDto) {
return 0;
}
@Override
void pushMessageToBuffer(BasicMessageDto messageDto) throws Exception {
}
@Override
void initDataBuffer() {
} }
} }

View File

@ -1,9 +1,61 @@
package com.munjaon.server.queue.service; package com.munjaon.server.queue.service;
import com.munjaon.server.queue.dto.LmsMessageDto; import com.munjaon.server.config.ServiceCode;
import com.munjaon.server.queue.config.MediaBodyConfig;
import com.munjaon.server.queue.config.QueueConstants;
import com.munjaon.server.queue.dto.BasicMessageDto;
import com.munjaon.server.util.MessageUtil;
import java.nio.ByteBuffer;
public class LmsWriteQueue extends WriteQueue { public class LmsWriteQueue extends WriteQueue {
public void pushBuffer(LmsMessageDto data) throws Exception {
@Override
public int isisValidateMessageForExtend(BasicMessageDto messageDto) {
/* 13. 제목 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserSubject(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserSubject(), MediaBodyConfig.SUBJECT_BYTE_LENGTH, false)) {
return ServiceCode.MSG_ERROR_MEDIA_SUBJECT.getCode();
}
/* 14. 메시지 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserMessage(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserMessage(), MediaBodyConfig.MEDIA_MSG_BYTE_LENGTH, false)) {
return ServiceCode.MSG_ERROR_MEDIA_MESSAGE.getCode();
}
return ServiceCode.OK.getCode();
}
@Override
public void pushMessageToBuffer(BasicMessageDto messageDto) throws Exception {
if (isValidateMessage(messageDto) == ServiceCode.OK.getCode()) {
/* 1. dataBuffer 초기화 */
initDataBuffer();
/* 2. messageDto >> dataBuffer */
MessageUtil.setBytesForCommonMessage(this.dataBuffer, messageDto);
MessageUtil.setBytesForMediaMessage(this.dataBuffer, messageDto);
/* 3. 파일큐에 적재 */
/* 3.1 Header 정보 다시 일기 */
readHeader();
if (this.dataBuffer != null){
this.channel.position(MessageUtil.calcWritePosition(this.pushCounter, MediaBodyConfig.LMS_SUM_BYTE_LENGTH));
this.dataBuffer.flip();
this.channel.write(this.dataBuffer);
/* 3.2 Push 카운터 증가 */
this.pushCounter = this.pushCounter + 1;
/* 3.3 Header 정보 변경 */
writeHeader();
}
}
}
@Override
public void initDataBuffer() {
if (this.dataBuffer == null) {
this.dataBuffer = ByteBuffer.allocateDirect(MediaBodyConfig.LMS_SUM_BYTE_LENGTH);
}
this.dataBuffer.clear();
for(int loopCnt = 0; loopCnt < MediaBodyConfig.LMS_SUM_BYTE_LENGTH; loopCnt++){
this.dataBuffer.put(QueueConstants.SET_DEFAULT_BYTE);
}
this.dataBuffer.position(0);
} }
} }

View File

@ -1,9 +1,62 @@
package com.munjaon.server.queue.service; package com.munjaon.server.queue.service;
import com.munjaon.server.queue.dto.MmsMessageDto; import com.munjaon.server.config.ServiceCode;
import com.munjaon.server.queue.config.MediaBodyConfig;
import com.munjaon.server.queue.config.QueueConstants;
import com.munjaon.server.queue.dto.BasicMessageDto;
import com.munjaon.server.util.MessageUtil;
import java.nio.ByteBuffer;
public class MmsWriteQueue extends WriteQueue { public class MmsWriteQueue extends WriteQueue {
public void pushBuffer(MmsMessageDto data) throws Exception {
@Override
public int isisValidateMessageForExtend(BasicMessageDto messageDto) {
/* 13. 제목 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserSubject(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserSubject(), MediaBodyConfig.SUBJECT_BYTE_LENGTH, false)) {
return ServiceCode.MSG_ERROR_MEDIA_SUBJECT.getCode();
}
/* 14. 메시지 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserMessage(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserMessage(), MediaBodyConfig.MEDIA_MSG_BYTE_LENGTH, false)) {
return ServiceCode.MSG_ERROR_MEDIA_MESSAGE.getCode();
}
return ServiceCode.OK.getCode();
}
@Override
public void pushMessageToBuffer(BasicMessageDto messageDto) throws Exception {
if (isValidateMessage(messageDto) == ServiceCode.OK.getCode()) {
/* 1. dataBuffer 초기화 */
initDataBuffer();
/* 2. messageDto >> dataBuffer */
MessageUtil.setBytesForCommonMessage(this.dataBuffer, messageDto);
MessageUtil.setBytesForMediaMessage(this.dataBuffer, messageDto);
MessageUtil.setBytesForMmsMessage(this.dataBuffer, messageDto);
/* 3. 파일큐에 적재 */
/* 3.1 Header 정보 다시 일기 */
readHeader();
if (this.dataBuffer != null){
this.channel.position(MessageUtil.calcWritePosition(this.pushCounter, MediaBodyConfig.MMS_SUM_BYTE_LENGTH));
this.dataBuffer.flip();
this.channel.write(this.dataBuffer);
/* 3.2 Push 카운터 증가 */
this.pushCounter = this.pushCounter + 1;
/* 3.3 Header 정보 변경 */
writeHeader();
}
}
}
@Override
public void initDataBuffer() {
if (this.dataBuffer == null) {
this.dataBuffer = ByteBuffer.allocateDirect(MediaBodyConfig.MMS_SUM_BYTE_LENGTH);
}
this.dataBuffer.clear();
for(int loopCnt = 0; loopCnt < MediaBodyConfig.MMS_SUM_BYTE_LENGTH; loopCnt++){
this.dataBuffer.put(QueueConstants.SET_DEFAULT_BYTE);
}
this.dataBuffer.position(0);
} }
} }

View File

@ -0,0 +1,197 @@
package com.munjaon.server.queue.service;
import com.munjaon.server.queue.dto.QueueInfo;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ReadQueue {
/** Queue Header Size - [Create Date:10 Byte, Push Count:10 Byte] */
private static final int QUEUE_HEADER_LENGTH = 20;
/** Queue Create Date - [Format:YYYYMMDD] */
private String createDate = "";
/** Queue Pop Counter */
private int popCounter = 0;
/** Queue Push Counter */
private int pushCounter = 0;
/** XML 읽은 날짜 */
private String readXMLDate = "";
/** Queue Header Buffer */
private ByteBuffer headerBuffer = null;
/** Queue Data Read Buffer */
private ByteBuffer readBuffer = null;
/** Queue Information */
private QueueInfo queueInfo = null;
/** Queue File Channel */
private FileChannel channel = null;
/** Header 에서 사용하는 변수 */
byte[] headerArray = null;
/** XML Control */
// private Document document = null; // XML Document
// private Element rootElement = null;
// private Element childElement = null;
// private final Format format = Format.getPrettyFormat();
// private XMLOutputter outputter = null;
// private FileWriter fileWriter = null;
//
// public ReadQueue(QueueInfo info) throws Exception{
// this.queueInfo = info;
// this.headerBuffer = ByteBuffer.allocateDirect(this.QUEUE_HEADER_LENGTH);
// this.readBuffer = ByteBuffer.allocateDirect(this.queueInfo.getQueueDataLength());
// try{
// File file = new File(this.queueInfo.getQueueFileName());
// if(file.exists()){
// this.channel = new RandomAccessFile(file, "r").getChannel();
// // 파일큐의 헤더 정보를 읽어온다.
// readHeader();
// // XML Write Formater
// this.format.setEncoding("EUC-KR");
// this.format.setIndent("\t");
//
// // 해당큐를 읽은 PopCounter 정보를 가져온다.
// file = new File(this.queueInfo.getReadXMLFileName());
// if(file.exists()){
// readPopCounter();
// }else{
// this.readXMLDate = MessageUtil.currentDay();
// this.popCounter = 0;
// writePopCounter();
// }
// }else{
// throw new Exception(this.queueInfo.getQueueName() + "'s Queue is Not Exists!!");
// }
//
// }catch(Exception e){
// throw e;
// }
// }
// public ByteBuffer popBuffer() throws Exception{
// try {
// readHeader();
// readPopCounter();
//
// if(this.popCounter == this.pushCounter){
// // 더이상 읽을 데이터가 없는 경우
// return null;
// }else{
// initReadBuffer();
// this.channel.position(QUEUE_HEADER_LENGTH + (this.queueInfo.getQueueDataLength() * this.popCounter));
// this.channel.read(this.readBuffer);
// this.popCounter = this.popCounter + 1;
// // Header 정보 변경
// writePopCounter();
//
// return this.readBuffer;
// }
// } catch(Exception e) {
// throw e;
// }
// }
// public void readPopCounter() throws Exception{
// try {
// this.document = new SAXBuilder().build(this.queueInfo.getReadXMLFileName());
// this.rootElement = this.document.getRootElement();
// this.readXMLDate = this.rootElement.getChild("createDate").getText().trim();
// this.popCounter = Integer.parseInt(this.rootElement.getChild("PopCounter").getText().trim());
// } catch(Exception e) {
// throw e;
// }
// }
// public void writePopCounter() throws Exception{
// try {
// // Root Element
// this.rootElement = new Element("ReadQueue");
// // 생성날짜
// this.childElement = new Element("createDate");
// this.childElement.setText(this.readXMLDate);
// this.rootElement.addContent(this.childElement);
// // 읽은 카운트
// this.childElement = new Element("PopCounter");
// this.childElement.setText(Integer.toString(this.popCounter));
// this.rootElement.addContent(this.childElement);
//
// this.document = new Document(this.rootElement);
// this.outputter = new XMLOutputter();
// this.outputter.setFormat(this.format);
// this.fileWriter = new FileWriter(this.queueInfo.getReadXMLFileName());
// this.outputter.output(this.document, this.fileWriter);
// } catch(Exception e) {
// throw e;
// }finally{
// if(this.fileWriter != null){this.fileWriter.close(); this.fileWriter = null; }
// }
// }
// public void initPopCounter() throws Exception{
// try {
// initHeaderBuffer();
// // 데이터 초기화
// this.readXMLDate = MessageUtil.currentDay();
// this.popCounter = 0;
//
// writePopCounter();
// } catch(Exception e) {
// throw e;
// }
// }
// public void readHeader() throws Exception {
// try {
// initHeaderBuffer();
// this.channel.position(0);
// this.channel.read(this.headerBuffer);
// this.headerArray = new byte[10];
// // 생성날짜 가져오기 - 생성날짜(10) / 쓴카운트(10)
// this.headerBuffer.position(0);
// this.headerBuffer.get(this.headerArray);
// this.createDate = (new String(this.headerArray)).trim();
// // 카운트 가져오기
// this.headerArray = new byte[10];
// this.headerBuffer.position(10);
// this.headerBuffer.get(this.headerArray);
// this.pushCounter = Integer.parseInt((new String(this.headerArray)).trim());
// } catch(Exception e) {
// throw e;
// }
// }
// public void close() throws IOException {
// try {
// if(channel != null && channel.isOpen()) {
// channel.close();
// }
// } catch(IOException e) {
// throw e;
// }
// }
// public void initHeaderBuffer(){
// this.headerBuffer.clear();
// for(int loopCnt=0;loopCnt<this.QUEUE_HEADER_LENGTH;loopCnt++){
// this.headerBuffer.put(QueueVariable.SET_DEFAULT_BYTE);
// }
// this.headerBuffer.position(0);
// }
// public void initReadBuffer(){
// this.readBuffer.clear();
// for(int loopCnt=0;loopCnt<this.queueInfo.getQueueDataLength();loopCnt++){
// this.readBuffer.put(QueueVariable.SET_DEFAULT_BYTE);
// }
// this.readBuffer.position(0);
// }
// public String getQueueName(){
// if(this.queueInfo == null)
// return null;
// else
// return this.queueInfo.getQueueName();
// }
// public String getCreateDate() {
// return createDate;
// }
// public String getReadXMLDate() {
// return readXMLDate;
// }
// public int getPushCounter() {
// return pushCounter;
// }
// public int getPopCounter() {
// return popCounter;
// }
}

View File

@ -1,9 +1,63 @@
package com.munjaon.server.queue.service; package com.munjaon.server.queue.service;
import com.munjaon.server.config.ServiceCode;
import com.munjaon.server.queue.config.QueueConstants;
import com.munjaon.server.queue.config.SmsBodyConfig;
import com.munjaon.server.queue.dto.BasicMessageDto; import com.munjaon.server.queue.dto.BasicMessageDto;
import com.munjaon.server.queue.dto.QueueInfo;
import com.munjaon.server.util.MessageUtil;
import java.nio.ByteBuffer;
public class SmsWriteQueue extends WriteQueue { public class SmsWriteQueue extends WriteQueue {
public void pushBuffer(BasicMessageDto data) throws Exception { public SmsWriteQueue(QueueInfo queueInfo) throws Exception {
this.queueInfo = queueInfo;
/* 큐초기화 */
initQueue();
}
@Override
public int isisValidateMessageForExtend(BasicMessageDto messageDto) {
/* 13. 메시지 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserMessage(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserMessage(), SmsBodyConfig.SMS_MSG_BYTE_LENGTH, false)) {
return ServiceCode.MSG_ERROR_SMS_MESSAGE.getCode();
}
return ServiceCode.OK.getCode();
}
@Override
public void pushMessageToBuffer(BasicMessageDto messageDto) throws Exception {
if (isValidateMessage(messageDto) == ServiceCode.OK.getCode()) {
/* 1. dataBuffer 초기화 */
initDataBuffer();
/* 2. messageDto >> dataBuffer */
MessageUtil.setBytesForCommonMessage(this.dataBuffer, messageDto);
MessageUtil.setBytesForSmsMessage(this.dataBuffer, messageDto);
/* 3. 파일큐에 적재 */
/* 3.1 Header 정보 다시 일기 */
readHeader();
if (this.dataBuffer != null){
this.channel.position(MessageUtil.calcWritePosition(this.pushCounter, SmsBodyConfig.SMS_SUM_BYTE_LENGTH));
this.dataBuffer.flip();
this.channel.write(this.dataBuffer);
/* 3.2 Push 카운터 증가 */
this.pushCounter = this.pushCounter + 1;
/* 3.3 Header 정보 변경 */
writeHeader();
}
}
}
@Override
public void initDataBuffer() {
if (this.dataBuffer == null) {
this.dataBuffer = ByteBuffer.allocateDirect(SmsBodyConfig.SMS_SUM_BYTE_LENGTH);
}
this.dataBuffer.clear();
for(int loopCnt = 0; loopCnt < SmsBodyConfig.SMS_SUM_BYTE_LENGTH; loopCnt++){
this.dataBuffer.put(QueueConstants.SET_DEFAULT_BYTE);
}
this.dataBuffer.position(0);
} }
} }

View File

@ -1,8 +1,13 @@
package com.munjaon.server.queue.service; package com.munjaon.server.queue.service;
import com.munjaon.server.config.ServiceCode;
import com.munjaon.server.queue.config.BodyCommonConfig;
import com.munjaon.server.queue.config.QueueConstants; import com.munjaon.server.queue.config.QueueConstants;
import com.munjaon.server.queue.config.QueueHeaderConfig; import com.munjaon.server.queue.config.QueueHeaderConfig;
import com.munjaon.server.queue.dto.BasicMessageDto;
import com.munjaon.server.queue.dto.QueueInfo; import com.munjaon.server.queue.dto.QueueInfo;
import com.munjaon.server.util.MessageUtil;
import lombok.Getter;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -13,20 +18,22 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
public abstract class WriteQueue { public abstract class WriteQueue {
/** Queue Header Size - [Create Date:10 Byte, Push Count:10 Byte] */
protected static final int QUEUE_HEADER_LENGTH = 20;
/** Queue Create Date - [Format:YYYYMMDD] */
protected String createDate = "";
/** Queue Push Counter */
protected int pushCounter = 0;
/** Queue Header Buffer */ /** Queue Header Buffer */
protected ByteBuffer headerBuffer = null; protected ByteBuffer headerBuffer = null;
/** Queue Information */
protected QueueInfo queueInfo = null;
/** Queue File Channel */
protected FileChannel channel = null;
/** Header 에서 사용하는 변수 */ /** Header 에서 사용하는 변수 */
protected byte[] headerArray = null; protected byte[] headerArray = null;
/** Queue Create Date - [Format:YYYYMMDD] */
@Getter
protected String createDate = "";
/** Queue Push Counter */
@Getter
protected int pushCounter = 0;
/** Queue File Channel */
protected FileChannel channel = null;
/** Queue Information */
@Getter
protected QueueInfo queueInfo = null;
/** pushBuffer() 함수에서 사용하는 변수 */ /** pushBuffer() 함수에서 사용하는 변수 */
protected ByteBuffer dataBuffer = null; protected ByteBuffer dataBuffer = null;
@ -53,19 +60,19 @@ public abstract class WriteQueue {
} }
} }
public void readHeader() throws Exception { protected void readHeader() throws Exception {
try { try {
initHeaderBuffer(); initHeaderBuffer();
this.channel.position(0); this.channel.position(0);
this.channel.read(this.headerBuffer); this.channel.read(this.headerBuffer);
this.headerArray = new byte[10]; this.headerArray = new byte[QueueHeaderConfig.CREATE_DATE_LENGTH];
// 생성날짜 가져오기 - 생성날짜(10) / 읽은카운트(10) / 쓴카운트(10) // 생성날짜 가져오기 - 생성날짜(10) / 읽은카운트(10) / 쓴카운트(10)
this.headerBuffer.position(0); this.headerBuffer.position(QueueHeaderConfig.CREATE_DATE_POSITION);
this.headerBuffer.get(this.headerArray); this.headerBuffer.get(this.headerArray);
this.createDate = (new String(this.headerArray)).trim(); this.createDate = (new String(this.headerArray)).trim();
// 카운트 가져오기 // 카운트 가져오기
this.headerArray = new byte[10]; this.headerArray = new byte[QueueHeaderConfig.PUSH_COUNT_LENGTH];
this.headerBuffer.position(10); this.headerBuffer.position(QueueHeaderConfig.PUSH_COUNT_POSITION);
this.headerBuffer.get(this.headerArray); this.headerBuffer.get(this.headerArray);
this.pushCounter = Integer.parseInt((new String(this.headerArray)).trim()); this.pushCounter = Integer.parseInt((new String(this.headerArray)).trim());
} catch(Exception e) { } catch(Exception e) {
@ -73,12 +80,12 @@ public abstract class WriteQueue {
} }
} }
public void writeHeader() throws Exception { protected void writeHeader() throws Exception {
try { try {
initHeaderBuffer(); initHeaderBuffer();
this.channel.position(0); this.channel.position(QueueHeaderConfig.CREATE_DATE_POSITION);
this.headerBuffer.put(this.createDate.getBytes()); this.headerBuffer.put(this.createDate.getBytes());
this.headerBuffer.position(10); this.headerBuffer.position(QueueHeaderConfig.PUSH_COUNT_POSITION);
this.headerBuffer.put(Integer.toString(this.pushCounter).getBytes()); this.headerBuffer.put(Integer.toString(this.pushCounter).getBytes());
this.headerBuffer.flip(); this.headerBuffer.flip();
this.channel.write(this.headerBuffer); this.channel.write(this.headerBuffer);
@ -87,7 +94,7 @@ public abstract class WriteQueue {
} }
} }
public void initHeaderBuffer(){ protected void initHeaderBuffer(){
this.headerBuffer.clear(); this.headerBuffer.clear();
for(int loopCnt = 0; loopCnt < QueueHeaderConfig.QUEUE_HEADER_LENGTH; loopCnt++){ for(int loopCnt = 0; loopCnt < QueueHeaderConfig.QUEUE_HEADER_LENGTH; loopCnt++){
this.headerBuffer.put(QueueConstants.SET_DEFAULT_BYTE); this.headerBuffer.put(QueueConstants.SET_DEFAULT_BYTE);
@ -95,9 +102,9 @@ public abstract class WriteQueue {
this.headerBuffer.position(0); this.headerBuffer.position(0);
} }
public void close() throws IOException { protected void close() throws IOException {
try { try {
if(channel != null && channel.isOpen()) { if (isOpen()) {
channel.close(); channel.close();
} }
} catch(IOException e) { } catch(IOException e) {
@ -105,27 +112,108 @@ public abstract class WriteQueue {
} }
} }
public void truncateQueue() throws Exception{ protected boolean isOpen() {
try { if (this.channel == null) {
//this.lock = this.channel.lock(); return false;
}
if(channel != null && channel.isOpen()) { return this.channel.isOpen();
// 헤더정보 읽기 }
readHeader();
protected void truncateQueue() throws Exception{
try {
/* 1. 날짜가 지난경우와 더이상 읽을 데이터가 없을 경우 큐를 초기화 */
String thisDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String thisDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
// 날짜가 지난경우와 더이상 읽을 데이터가 없을 경우 큐를 초기화 if (this.createDate.equals(thisDate)) {
if((this.createDate.equals(thisDate) == false)){ return;
// 파일 내용을 모두 지운다. }
if (isOpen()) {
/* 2. 헤더정보 읽기 */
readHeader();
/* 3. 파일 내용을 모두 지운다. */
channel.truncate(0); channel.truncate(0);
// 헤더 정보를 초기화한다. /* 4. 헤더 정보를 초기화한다. */
this.createDate = thisDate; this.createDate = thisDate;
this.pushCounter = 0; this.pushCounter = 0;
// 헤더에 초기데이터를 저장 /* 5. 헤더에 초기데이터를 저장 */
writeHeader(); writeHeader();
} }
}
} catch(Exception e) { } catch(Exception e) {
throw e; throw e;
} }
} }
public String getQueueName(){
if(this.queueInfo == null)
return null;
else
return this.queueInfo.getQueueName();
}
protected int isValidateMessage(BasicMessageDto messageDto) {
int result = isValidateMessageForCommon(messageDto);
if (result != ServiceCode.OK.getCode()) {
return result;
}
return isisValidateMessageForExtend(messageDto);
}
protected int isValidateMessageForCommon(BasicMessageDto messageDto) {
/* 1. 사용자 아이디 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserId(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserId(), BodyCommonConfig.USERID_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_USERID.getCode();
}
/* 2. 요금제(선불 : P / 후불 : A) */
if (MessageUtil.isEmptyForMessage(messageDto.getFeeType(), true) || MessageUtil.isOverByteForMessage(messageDto.getFeeType(), BodyCommonConfig.FEETYPE_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_FEETYPE.getCode();
}
/* 3. 단가 */
if (MessageUtil.isEmptyForMessage(messageDto.getUnitCost(), true) || MessageUtil.isOverByteForMessage(messageDto.getUnitCost(), BodyCommonConfig.UNITCOST_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_UNITCOST.getCode();
}
/* 4. MSG Group ID */
if (MessageUtil.isEmptyForMessage(messageDto.getMsgGroupID(), true) || MessageUtil.isOverByteForMessage(messageDto.getMsgGroupID(), BodyCommonConfig.MSGGROUPID_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_MSGGROUPID.getCode();
}
/* 5. MSG ID */
if (MessageUtil.isEmptyForMessage(messageDto.getUserMsgID(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserMsgID(), BodyCommonConfig.MSGID_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_USERMSGID.getCode();
}
/* 6. Service Type */
if (MessageUtil.isEmptyForMessage(messageDto.getServiceType(), true) || MessageUtil.isOverByteForMessage(messageDto.getServiceType(), BodyCommonConfig.SERVICETYPE_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_SERVICETYPE.getCode();
}
/* 7. 메시지 전송 결과 >> 성공 : 0 / 필터링 : 기타값 */
if (MessageUtil.isEmptyForMessage(messageDto.getSendStatus(), true) || MessageUtil.isOverByteForMessage(messageDto.getSendStatus(), BodyCommonConfig.SENDSTATUS_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_SENDSTATUS.getCode();
}
/* 8. 회신번호 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserSender(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserSender(), BodyCommonConfig.SENDER_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_USERSENDER.getCode();
}
/* 9. 수신번호 */
if (MessageUtil.isEmptyForMessage(messageDto.getUserReceiver(), true) || MessageUtil.isOverByteForMessage(messageDto.getUserReceiver(), BodyCommonConfig.RECEIVER_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_USERRECEIVER.getCode();
}
/* 10. 요청시간 */
if (MessageUtil.isEmptyForMessage(messageDto.getRequestDt(), true) || MessageUtil.isOverByteForMessage(messageDto.getRequestDt(), BodyCommonConfig.REQUESTDT_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_REQUESTDT.getCode();
}
/* 11. 원격 주소 */
if (MessageUtil.isEmptyForMessage(messageDto.getRemoteIP(), true) || MessageUtil.isOverByteForMessage(messageDto.getRemoteIP(), BodyCommonConfig.REMOTEIP_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_REMOTEIP.getCode();
}
/* 12. 발송망 */
if (MessageUtil.isEmptyForMessage(messageDto.getRouterSeq(), true) || MessageUtil.isOverByteForMessage(messageDto.getRouterSeq(), BodyCommonConfig.AGENT_CODE_BYTE_LENGTH, true)) {
return ServiceCode.MSG_ERROR_ROUTERSEQ.getCode();
}
return ServiceCode.OK.getCode();
}
abstract int isisValidateMessageForExtend(BasicMessageDto messageDto);
abstract void pushMessageToBuffer(BasicMessageDto messageDto) throws Exception;
abstract void initDataBuffer();
} }

View File

@ -0,0 +1,208 @@
package com.munjaon.server.server.service;
import com.munjaon.server.util.LogUtil;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public abstract class BaseService extends Thread {
boolean bEndProcess = false;
public static SimpleDateFormat sdf = new SimpleDateFormat("[MM-dd HH:mm:ss]");
public static String LOG_DATE_FORMAT = "[MM-dd HH:mm:ss]";
public boolean ready;
private boolean KILL_FLAG;
private boolean STOP_FLAG;
private boolean RUN_FLAG;
private String LOG_FILE;
public LogUtil logger;
public BaseService() {}
public BaseService(String ServiceID) {
super(ServiceID);
LOG_FILE = getProp("LOG_FILE");
}
protected void checkRun() {
RUN_FLAG = "1".equals(getProp("RUN_FLAG")) ? true : false;
}
protected boolean isRun() {
return RUN_FLAG && !STOP_FLAG && !KILL_FLAG;
}
protected void setLogFile(String sLogFile) {
if( logger != null ) {
logger.close();
logger = null;
}
logger = new LogUtil( sLogFile );
}
protected void Init() throws Exception {
LOG_FILE = getProp("LOG_FILE");
setLogFile( LOG_FILE );
SystemLog("Service Initializing...");
ready = true;
}
public synchronized void Start() {
super.start();
}
protected synchronized void Stop() {
STOP_FLAG = true;
SystemLog("Service Stoping...");
}
protected synchronized void Kill() {
if( !KILL_FLAG ) SystemLog("Service Killing...");
KILL_FLAG = true;
}
protected void startService() throws Exception {
Log("startService() called.");
}
protected void stopService() throws Exception {
Log("stopService() called.");
}
protected synchronized void Reload() throws Exception {
}
@Override
public void run() {
while (!KILL_FLAG) {
STOP_FLAG = false;
if (isRun()) {
try {
Init();
SystemLog("Service Starting.");
startService();
} catch (SQLException e) {
STOP_FLAG = true;
SystemLog("SQLErrorCode = "+e.getErrorCode());
SystemLog(e);
} catch (Exception e) {
STOP_FLAG = true;
SystemLog(e);
} finally {
ready = false;
SystemLog("Service Stoped.");
if( logger != null ) { logger.close(); logger = null; }
}
}
if( !KILL_FLAG ) {
try {
Thread.sleep(5000);
} catch (Exception e) {
}
}
}
try {
stopService();
} catch (Exception e) {
}
SystemLog("Service Killed.");
ServiceRunner.SERVICES.remove(getName());
bEndProcess = true;
}
public void stopThread() {
SystemLog("kill signal has been received.");
SystemLog("remaining tasks are handled.");
bEndProcess = true;
Kill();
int i=0;
while (true) {
try {
Thread.sleep(1*1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
if(bEndProcess) {
break;
}
SystemLog("remaining tasks - processing " + (++i) + " secs.");
}
this.interrupt();
try {
Thread.sleep(100);
} catch(InterruptedException e) {
e.printStackTrace();
}
SystemLog("Service was interrupted.");
}
protected void SystemLog(Object obj) {
Log(obj, true);
}
protected void Log(Object obj) {
Log(obj, false);
}
protected void Log(Object obj, boolean bOut) {
if( bOut ) {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern(LOG_DATE_FORMAT)) + " {{"+ getName() +"}} "+obj);
}
if( logger != null ) {
logger.log(obj);
}
else {
if( obj instanceof Throwable ) {
LogUtil.log(LOG_FILE, obj);
}
else {
LogUtil.log(LOG_FILE, "{{"+ getName() +"}} "+obj);
}
}
}
protected String getProp(String name) {
return getProp(getName(), name);
}
public static String getProp(String svc, String name) {
return PropertyLoader.getProp(svc, name);
}
}
class ShutdownService extends Thread {
private BaseService service = null;
public ShutdownService(BaseService service) {
super();
this.service = service;
}
@Override
public void run() {
service.stopThread();
}
}

View File

@ -0,0 +1,79 @@
package com.munjaon.server.server.service;
import java.io.FileInputStream;
import java.util.Properties;
/**
* PropertyLoader
* @author JDS
*/
public class PropertyLoader extends Thread {
private static Properties props = load();
private static PropertyLoader loader;
public static String getProp(String key, String sub) {
return get(key+"."+sub);
}
public static String get(String key) {
return get(key, null);
}
public static String get(String key, String dflt) {
if( props == null ) return null;
String value = props.getProperty(key, dflt);
if( value == null ) {
value = dflt;
System.err.println("Not Defined : [" + key + "]");
}
else {
value = value.replaceAll("\\$WORK_HOME", System.getProperty("WORK_HOME"));
}
return value;
}
public synchronized static Properties load() {
String propFile = System.getProperty("PROPS");
try {
Properties properties = new Properties();
properties.load( new FileInputStream (propFile) );
props = properties;
} catch(Exception e) {
Log(e);
}
if( loader == null ) {
loader = new PropertyLoader();
loader.start();
}
return props;
}
private synchronized static void Log(Object oLog) {
if ( oLog instanceof Exception ) {
System.out.println( (new java.util.Date()) );
((Exception)oLog).printStackTrace();
} else {
System.out.println( (new java.util.Date()) + (String) oLog );
}
}
@Override
public void run() {
while( true ) {
try {
Thread.sleep(1000);
load();
} catch(Exception e) {
Log(e);
}
}
}
}

View File

@ -0,0 +1,124 @@
package com.munjaon.server.server.service;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.Hashtable;
/**
*
* @author JDS
*/
public class ServiceRunner extends Thread {
public static String CLASS_DIR = PropertyLoader.get("SERVICE.CLASS_DIR");
public static Hashtable SERVICES = new Hashtable();
public void run() {
while(true) {
check();
try {
int iCheckCycle = Integer.parseInt(PropertyLoader.get("SERVICE.CHECK_CYCLE","3000"));
Thread.sleep( iCheckCycle );
} catch (Exception e) {
}
}
}
private void check() {
try {
String[] svcs = PropertyLoader.get("SERVICE.LISTS").split(",");
String svc_name;
Hashtable map = new Hashtable();
for( int i=0; i<svcs.length; i++ ) {
svc_name = svcs[i].trim();
if( svc_name.length() == 0 || svc_name.startsWith("#") ) {
continue;
}
map.put( svc_name, svc_name );
}
Enumeration enums = SERVICES.elements();
while( enums.hasMoreElements() ) {
BaseService svc = (BaseService) enums.nextElement();
svc_name = svc.getName();
if( map.containsKey(svc_name) ) {
svc.checkRun();
if( svc.isRun() && svc.ready ) {
svc.Reload();
}
map.remove(svc_name);
}
else {
svc.Kill();
}
}
enums = map.elements();
ShutdownService shutdownService = null;
while ( enums.hasMoreElements() ) {
svc_name = (String) enums.nextElement();
if( SERVICES.containsKey(svc_name) ) {
System.err.println("Already Started Service: "+ svc_name);
continue;
}
String className = PropertyLoader.get(svc_name + ".CLASS");
Class cls = LoadClass( CLASS_DIR, className );
BaseService svc = (BaseService) cls.newInstance();
svc.setName(svc_name);
svc.checkRun();
if( svc.isRun() && svc.ready ) svc.Reload();
SERVICES.put(svc_name, svc);
shutdownService = new ShutdownService(svc);
Runtime.getRuntime().addShutdownHook(shutdownService);
svc.Start();
Thread.sleep(500);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public static Class LoadClass(String className) throws Exception {
Class cls = Class.forName(className.trim());
return cls;
}
public static Class LoadClass(String path, String className) throws Exception {
/**
URL url = new File(path).toURL();
URL[] urls = new URL[]{url};
ClassLoader loader = new URLClassLoader(urls);
*/
URI uri = new File(path).toURI();
URL[] urls = new URL[]{uri.toURL()};
ClassLoader loader = new URLClassLoader(urls);
return loader.loadClass(className);
}
public static void main(String[] args) throws Exception {
new ServiceRunner().start();
}
}

View File

@ -0,0 +1,37 @@
package com.munjaon.server.util;
import java.io.File;
/**
* 파일 관련 유틸리티 클래스
* @author JDS
*/
public class FileUtil {
public static boolean exists(String sFile) {
return exists( new File(sFile) );
}
public static boolean exists(File file) {
return file.exists();
}
public static boolean mkdirs(String sPath) {
return mkdirs(sPath, false);
}
public static boolean mkdirs(String sPath, boolean isFilePath) {
File file = new File(sPath);
if( isFilePath ) {
file = file.getParentFile();
}
if( file.exists() ) {
return true;
}
return file.mkdirs();
}
}

View File

@ -0,0 +1,95 @@
package com.munjaon.server.util;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 로깅 관련 유틸리티 클래스
* @author JDS
*/
public class LogUtil {
private final static String sTimeFormat = "[HH:mm:ss.SSS] ";
private final static String sDateFormat = "_yyyyMMdd";
private final static String sFileExt = ".log";
private PrintWriter out;
private String sLogFile;
private String sDate;
public LogUtil(String sLogFile) {
this.sLogFile = sLogFile;
if ( sLogFile != null ) {
FileUtil.mkdirs(sLogFile, true);
}
}
private void open() {
close();
if (sLogFile != null) {
try {
out = new PrintWriter( new BufferedWriter( new FileWriter(sLogFile + sDate + sFileExt, true) ), true );
} catch(Exception e) {
out = null;
}
}
if( out == null ) {
out = new PrintWriter(System.out, true);
}
}
public void close() {
if (sLogFile != null && out != null) {
try {
out.close();
out = null;
} catch (Exception e) {
}
}
}
public static void log(String sFile, Object oLog) {
LogUtil logger = new LogUtil(sFile);
logger.log(oLog);
logger.close();
}
public synchronized void log(Object oLog) {
SimpleDateFormat sdf = new SimpleDateFormat();
Date date = new Date();
sdf.applyPattern(sDateFormat);
String sDates = sdf.format(date);
sdf.applyPattern(sTimeFormat);
String sTime = sdf.format(date);
try {
if (!sDates.equals(this.sDate)) {
this.sDate = sDates;
open();
}
if (oLog instanceof Exception) {
out.print( sTime );
((Exception)oLog).printStackTrace(out);
if (sLogFile == null) {
((Exception)oLog).printStackTrace();
}
} else {
out.println( sTime + oLog );
}
out.flush();
} catch ( Exception e ) {
close();
}
}
}

View File

@ -1,5 +1,12 @@
package com.munjaon.server.util; package com.munjaon.server.util;
import com.munjaon.server.queue.config.BodyCommonConfig;
import com.munjaon.server.queue.config.MediaBodyConfig;
import com.munjaon.server.queue.config.QueueHeaderConfig;
import com.munjaon.server.queue.config.SmsBodyConfig;
import com.munjaon.server.queue.dto.BasicMessageDto;
import java.nio.ByteBuffer;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -25,22 +32,22 @@ public final class MessageUtil {
} }
public static String doNumber(String spell){ public static String doNumber(String spell){
String phoneNumber = ""; StringBuilder phoneNumber = new StringBuilder();
if (spell == null){ if (spell == null){
return phoneNumber; return phoneNumber.toString();
} }
spell = spell.trim(); spell = spell.trim();
int spell_Length = spell.length(); int spell_Length = spell.length();
if (spell_Length < 1){ if (spell_Length < 1){
return phoneNumber; return phoneNumber.toString();
} }
for (int i=0; i<spell_Length; i++){ for (int i=0; i<spell_Length; i++){
char eachChar = spell.charAt(i); char eachChar = spell.charAt(i);
if( 0x30 <= eachChar && eachChar <= 0x39 ){ if( 0x30 <= eachChar && eachChar <= 0x39 ){
phoneNumber += eachChar; phoneNumber.append(eachChar);
} }
} }
return phoneNumber; return phoneNumber.toString();
} }
// 소수점 뒤에 해당하는 자리만큼 자르기 // 소수점 뒤에 해당하는 자리만큼 자르기
@ -49,15 +56,15 @@ public final class MessageUtil {
String tailNum = ""; String tailNum = "";
String retNum = ""; String retNum = "";
if(!(srcNum == null || srcNum.trim().equals(""))){ if(!(srcNum == null || srcNum.trim().isEmpty())){
srcNum = srcNum.trim(); srcNum = srcNum.trim();
int index = srcNum.indexOf("."); int index = srcNum.indexOf(".");
// 소수점 위치가 0보다 큰경우만 처리 // 소수점 위치가 0보다 큰경우만 처리
if(index > 0){ if(index > 0){
headNum = srcNum.substring(0, index); headNum = srcNum.substring(0, index);
tailNum = srcNum.substring((index + 1), srcNum.length()); tailNum = srcNum.substring((index + 1));
if(tailNum.length() == 0){ if (tailNum.isEmpty()) {
tailNum = "0"; tailNum = "0";
} }
if(tailNum.length() > digit){ if(tailNum.length() > digit){
@ -71,19 +78,120 @@ public final class MessageUtil {
} }
// 수신번호 체크하기 // 수신번호 체크하기
public static boolean CheckPhone(String src) { public static boolean checkPhone(String src) {
if(src == null || src.trim().length() < 10) { if(src == null || src.trim().length() < 10) {
return false; return false;
} }
if(!src.startsWith("0")) { return src.startsWith("0");
return false;
}
return true;
} }
// 문자열 공백 제거 // 문자열 공백 제거
public static String trim(String obj) { public static String trim(String obj) {
return StringUtil.trim(obj); return StringUtil.trim(obj);
} }
public static boolean isEmptyForMessage(String obj, boolean trimFlag) {
if (trimFlag)
return obj == null || obj.trim().isEmpty();
else
return obj == null || obj.isEmpty();
}
public static boolean isEmptyForMessage(String obj) {
return isEmptyForMessage(obj, false);
}
public static boolean isOverByteForMessage(String obj, int limitCount, boolean trimFlag) {
if (isEmptyForMessage(obj, trimFlag)) {
return true;
}
return obj.getBytes().length > limitCount;
}
public static boolean isOverByteForMessage(String obj, int limitCount) {
return isOverByteForMessage(obj, limitCount, false);
}
public static int calcWritePosition(int pushCounter, int dataByteLength) {
return pushCounter < 0 ? QueueHeaderConfig.QUEUE_HEADER_LENGTH : (QueueHeaderConfig.QUEUE_HEADER_LENGTH + pushCounter + dataByteLength);
}
public static void setBytesForCommonMessage(ByteBuffer buffer, BasicMessageDto messageDto) {
/* 1. 사용자 아이디 */
buffer.position(BodyCommonConfig.USERID_BYTE_POSITION);
buffer.put(messageDto.getUserId().getBytes());
/* 2. 요금제(선불 : P / 후불 : A) */
buffer.position(BodyCommonConfig.FEETYPE_BYTE_POSITION);
buffer.put(messageDto.getFeeType().getBytes());
/* 3. 단가 */
buffer.position(BodyCommonConfig.UNITCOST_BYTE_POSITION);
buffer.put(messageDto.getUnitCost().getBytes());
/* 4. MSG Group ID */
buffer.position(BodyCommonConfig.MSGGROUPID_BYTE_POSITION);
buffer.put(messageDto.getMsgGroupID().getBytes());
/* 5. MSG ID */
buffer.position(BodyCommonConfig.MSGID_BYTE_POSITION);
buffer.put(messageDto.getUserMsgID().getBytes());
/* 6. Service Type */
buffer.position(BodyCommonConfig.SERVICETYPE_BYTE_POSITION);
buffer.put(messageDto.getServiceType().getBytes());
/* 7. 메시지 전송 결과 >> 성공 : 0 / 필터링 : 기타값 */
buffer.position(BodyCommonConfig.SENDSTATUS_BYTE_POSITION);
buffer.put(messageDto.getSendStatus().getBytes());
/* 8. 회신번호 */
buffer.position(BodyCommonConfig.SENDER_BYTE_POSITION);
buffer.put(messageDto.getUserSender().getBytes());
/* 9. 수신번호 */
buffer.position(BodyCommonConfig.RECEIVER_BYTE_POSITION);
buffer.put(messageDto.getUserReceiver().getBytes());
/* 10. 예약시간 */
buffer.position(BodyCommonConfig.RESERVEDT_BYTE_POSITION);
buffer.put(messageDto.getReserveDt().getBytes());
/* 11. 요청시간 */
buffer.position(BodyCommonConfig.REQUESTDT_BYTE_POSITION);
buffer.put(messageDto.getRequestDt().getBytes());
/* 12. 원격 주소 */
buffer.position(BodyCommonConfig.REMOTEIP_BYTE_POSITION);
buffer.put(messageDto.getRemoteIP().getBytes());
/* 13. 발송망 */
buffer.position(BodyCommonConfig.AGENT_CODE_BYTE_POSITION);
buffer.put(messageDto.getRouterSeq().getBytes());
}
public static void setBytesForSmsMessage(ByteBuffer buffer, BasicMessageDto messageDto) {
/* 14. 메시지 */
buffer.position(SmsBodyConfig.SMS_MSG_BYTE_POSITION);
buffer.put(messageDto.getUserMessage().getBytes());
}
public static void setBytesForMediaMessage(ByteBuffer buffer, BasicMessageDto messageDto) {
/* 14. 제목 */
buffer.position(MediaBodyConfig.SUBJECT_BYTE_POSITION);
buffer.put(messageDto.getUserSubject().getBytes());
/* 15. 메시지 */
buffer.position(MediaBodyConfig.MEDIA_MSG_BYTE_POSITION);
buffer.put(messageDto.getUserMessage().getBytes());
}
public static void setBytesForMmsMessage(ByteBuffer buffer, BasicMessageDto messageDto) {
/* 16. 파일카운트 */
buffer.position(MediaBodyConfig.FILECNT_BYTE_POSITION);
buffer.put(Integer.toString(messageDto.getUserFileCnt()).getBytes());
/* 17. 파일명 #1 */
buffer.position(MediaBodyConfig.FILENAME_ONE_BYTE_POSITION);
if (messageDto.getUserFileName01() != null) {
buffer.put(messageDto.getUserFileName01().getBytes());
}
/* 18. 파일명 #2 */
buffer.position(MediaBodyConfig.FILENAME_TWO_BYTE_POSITION);
if (messageDto.getUserFileName02() != null) {
buffer.put(messageDto.getUserFileName02().getBytes());
}
/* 19. 파일명 #3 */
buffer.position(MediaBodyConfig.FILENAME_THREE_BYTE_POSITION);
if (messageDto.getUserFileName03() != null) {
buffer.put(messageDto.getUserFileName03().getBytes());
}
}
} }

View File

@ -0,0 +1,31 @@
package com.munjaon.server.util;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
public class XmlUtil {
private static Document getDOMParsedDocument(final String fileName) {
Document document = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//If want to make namespace aware.
//factory.setNamespaceAware(true);
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
document = documentBuilder.parse(new File("employee.xml"));
}
catch (IOException | SAXException | ParserConfigurationException e) {
e.printStackTrace();
}
return document;
}
public static void main(String[] args) {
}
}