diff --git a/build.gradle b/build.gradle index 91c724a..90dcae6 100644 --- a/build.gradle +++ b/build.gradle @@ -47,6 +47,8 @@ dependencies { implementation 'commons-beanutils:commons-beanutils:1.9.4' // https://mvnrepository.com/artifact/io.netty/netty-all 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' testAnnotationProcessor 'org.projectlombok:lombok' diff --git a/src/main/java/com/munjaon/server/config/RunnerConfiguration.java b/src/main/java/com/munjaon/server/config/RunnerConfiguration.java new file mode 100644 index 0000000..d505474 --- /dev/null +++ b/src/main/java/com/munjaon/server/config/RunnerConfiguration.java @@ -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"); + } +} diff --git a/src/main/java/com/munjaon/server/config/ServerConfig.java b/src/main/java/com/munjaon/server/config/ServerConfig.java index 0bf1ed8..90ccfcd 100644 --- a/src/main/java/com/munjaon/server/config/ServerConfig.java +++ b/src/main/java/com/munjaon/server/config/ServerConfig.java @@ -1,6 +1,7 @@ package com.munjaon.server.config; import jakarta.annotation.PostConstruct; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.builder.ConfigurationBuilderEvent; @@ -19,6 +20,7 @@ import java.util.concurrent.TimeUnit; @Slf4j @Component public class ServerConfig { + @Getter @Value("${agent.server-property-file}") private String serverProperyFile; @@ -47,4 +49,13 @@ public class ServerConfig { public int getInt(String key) throws ConfigurationException { 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); + } } diff --git a/src/main/java/com/munjaon/server/config/ServiceCode.java b/src/main/java/com/munjaon/server/config/ServiceCode.java new file mode 100644 index 0000000..06f03f8 --- /dev/null +++ b/src/main/java/com/munjaon/server/config/ServiceCode.java @@ -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"; + } +} diff --git a/src/main/java/com/munjaon/server/queue/config/MediaBodyConfig.java b/src/main/java/com/munjaon/server/queue/config/MediaBodyConfig.java index 6dcca07..39ddcf4 100644 --- a/src/main/java/com/munjaon/server/queue/config/MediaBodyConfig.java +++ b/src/main/java/com/munjaon/server/queue/config/MediaBodyConfig.java @@ -20,6 +20,8 @@ public final class MediaBodyConfig { 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; - /* Media 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; + /* LMS Body 길이 */ + 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; } diff --git a/src/main/java/com/munjaon/server/queue/dto/BasicMessageDto.java b/src/main/java/com/munjaon/server/queue/dto/BasicMessageDto.java index 8df6307..8c7a3e5 100644 --- a/src/main/java/com/munjaon/server/queue/dto/BasicMessageDto.java +++ b/src/main/java/com/munjaon/server/queue/dto/BasicMessageDto.java @@ -8,9 +8,9 @@ import lombok.ToString; @Setter @ToString public class BasicMessageDto { - protected String userId = ""; - protected String feeType = ""; - protected String unitCost = ""; + protected String userId = ""; // 사용자 아이디 + protected final String feeType = "A"; // 요금제(선불 : P / 후불 : A) + protected String unitCost = ""; // 단가 protected String msgGroupID = "0"; protected String userMsgID = ""; protected String serviceType = ""; @@ -23,5 +23,13 @@ public class BasicMessageDto { protected String routerSeq = "0"; 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; } diff --git a/src/main/java/com/munjaon/server/queue/dto/QueueInfo.java b/src/main/java/com/munjaon/server/queue/dto/QueueInfo.java index 5b0e1ed..5c6ea46 100644 --- a/src/main/java/com/munjaon/server/queue/dto/QueueInfo.java +++ b/src/main/java/com/munjaon/server/queue/dto/QueueInfo.java @@ -1,11 +1,13 @@ package com.munjaon.server.queue.dto; +import lombok.Builder; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Getter @Setter +@Builder @ToString public class QueueInfo { private String queueName = ""; diff --git a/src/main/java/com/munjaon/server/queue/pool/LmsQueuePool.java b/src/main/java/com/munjaon/server/queue/pool/LmsQueuePool.java new file mode 100644 index 0000000..f18b4f3 --- /dev/null +++ b/src/main/java/com/munjaon/server/queue/pool/LmsQueuePool.java @@ -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 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++; + } + } +} diff --git a/src/main/java/com/munjaon/server/queue/pool/MmsQueuePool.java b/src/main/java/com/munjaon/server/queue/pool/MmsQueuePool.java new file mode 100644 index 0000000..11c7188 --- /dev/null +++ b/src/main/java/com/munjaon/server/queue/pool/MmsQueuePool.java @@ -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 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++; + } + } +} diff --git a/src/main/java/com/munjaon/server/queue/pool/SmsQueuePool.java b/src/main/java/com/munjaon/server/queue/pool/SmsQueuePool.java new file mode 100644 index 0000000..9394187 --- /dev/null +++ b/src/main/java/com/munjaon/server/queue/pool/SmsQueuePool.java @@ -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 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++; + } + } +} diff --git a/src/main/java/com/munjaon/server/queue/service/KakaoWriteQueue.java b/src/main/java/com/munjaon/server/queue/service/KakaoWriteQueue.java index f527906..230e412 100644 --- a/src/main/java/com/munjaon/server/queue/service/KakaoWriteQueue.java +++ b/src/main/java/com/munjaon/server/queue/service/KakaoWriteQueue.java @@ -1,9 +1,21 @@ 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 void pushBuffer(KakaoMessageDto data) throws Exception { + + @Override + int isisValidateMessageForExtend(BasicMessageDto messageDto) { + return 0; + } + + @Override + void pushMessageToBuffer(BasicMessageDto messageDto) throws Exception { + + } + + @Override + void initDataBuffer() { } } diff --git a/src/main/java/com/munjaon/server/queue/service/LmsWriteQueue.java b/src/main/java/com/munjaon/server/queue/service/LmsWriteQueue.java index 010c1f6..24e929b 100644 --- a/src/main/java/com/munjaon/server/queue/service/LmsWriteQueue.java +++ b/src/main/java/com/munjaon/server/queue/service/LmsWriteQueue.java @@ -1,9 +1,61 @@ 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 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); } } diff --git a/src/main/java/com/munjaon/server/queue/service/MmsWriteQueue.java b/src/main/java/com/munjaon/server/queue/service/MmsWriteQueue.java index 647f4ed..8b8b414 100644 --- a/src/main/java/com/munjaon/server/queue/service/MmsWriteQueue.java +++ b/src/main/java/com/munjaon/server/queue/service/MmsWriteQueue.java @@ -1,9 +1,62 @@ 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 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); } } diff --git a/src/main/java/com/munjaon/server/queue/service/ReadQueue.java b/src/main/java/com/munjaon/server/queue/service/ReadQueue.java new file mode 100644 index 0000000..558dccb --- /dev/null +++ b/src/main/java/com/munjaon/server/queue/service/ReadQueue.java @@ -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> 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); } } diff --git a/src/main/java/com/munjaon/server/queue/service/WriteQueue.java b/src/main/java/com/munjaon/server/queue/service/WriteQueue.java index 4ea3002..7a5e8fb 100644 --- a/src/main/java/com/munjaon/server/queue/service/WriteQueue.java +++ b/src/main/java/com/munjaon/server/queue/service/WriteQueue.java @@ -1,8 +1,13 @@ 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.QueueHeaderConfig; +import com.munjaon.server.queue.dto.BasicMessageDto; import com.munjaon.server.queue.dto.QueueInfo; +import com.munjaon.server.util.MessageUtil; +import lombok.Getter; import java.io.File; import java.io.IOException; @@ -13,20 +18,22 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; 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 */ protected ByteBuffer headerBuffer = null; - /** Queue Information */ - protected QueueInfo queueInfo = null; - /** Queue File Channel */ - protected FileChannel channel = null; /** Header 에서 사용하는 변수 */ 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() 함수에서 사용하는 변수 */ protected ByteBuffer dataBuffer = null; @@ -37,13 +44,13 @@ public abstract class WriteQueue { this.channel = new RandomAccessFile(file, "rw").getChannel(); //this.lock = this.channel.lock(); - if(file.length() == 0) { + if (file.length() == 0) { // Push 및 Pop 카운트 초기화 this.createDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); this.pushCounter = 0; // 헤더 초기화 writeHeader(); - }else{ + } else { readHeader(); } }catch(Exception e){ @@ -53,19 +60,19 @@ public abstract class WriteQueue { } } - public void readHeader() throws Exception { + protected void readHeader() throws Exception { try { initHeaderBuffer(); this.channel.position(0); this.channel.read(this.headerBuffer); - this.headerArray = new byte[10]; + this.headerArray = new byte[QueueHeaderConfig.CREATE_DATE_LENGTH]; // 생성날짜 가져오기 - 생성날짜(10) / 읽은카운트(10) / 쓴카운트(10) - this.headerBuffer.position(0); + this.headerBuffer.position(QueueHeaderConfig.CREATE_DATE_POSITION); this.headerBuffer.get(this.headerArray); this.createDate = (new String(this.headerArray)).trim(); // 쓴 카운트 가져오기 - this.headerArray = new byte[10]; - this.headerBuffer.position(10); + this.headerArray = new byte[QueueHeaderConfig.PUSH_COUNT_LENGTH]; + this.headerBuffer.position(QueueHeaderConfig.PUSH_COUNT_POSITION); this.headerBuffer.get(this.headerArray); this.pushCounter = Integer.parseInt((new String(this.headerArray)).trim()); } catch(Exception e) { @@ -73,12 +80,12 @@ public abstract class WriteQueue { } } - public void writeHeader() throws Exception { + protected void writeHeader() throws Exception { try { initHeaderBuffer(); - this.channel.position(0); + this.channel.position(QueueHeaderConfig.CREATE_DATE_POSITION); 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.flip(); this.channel.write(this.headerBuffer); @@ -87,7 +94,7 @@ public abstract class WriteQueue { } } - public void initHeaderBuffer(){ + protected void initHeaderBuffer(){ this.headerBuffer.clear(); for(int loopCnt = 0; loopCnt < QueueHeaderConfig.QUEUE_HEADER_LENGTH; loopCnt++){ this.headerBuffer.put(QueueConstants.SET_DEFAULT_BYTE); @@ -95,9 +102,9 @@ public abstract class WriteQueue { this.headerBuffer.position(0); } - public void close() throws IOException { + protected void close() throws IOException { try { - if(channel != null && channel.isOpen()) { + if (isOpen()) { channel.close(); } } catch(IOException e) { @@ -105,27 +112,108 @@ public abstract class WriteQueue { } } - public void truncateQueue() throws Exception{ - try { - //this.lock = this.channel.lock(); + protected boolean isOpen() { + if (this.channel == null) { + return false; + } - if(channel != null && channel.isOpen()) { - // 헤더정보 읽기 + return this.channel.isOpen(); + } + + protected void truncateQueue() throws Exception{ + try { + /* 1. 날짜가 지난경우와 더이상 읽을 데이터가 없을 경우 큐를 초기화 */ + String thisDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); + if (this.createDate.equals(thisDate)) { + return; + } + + if (isOpen()) { + /* 2. 헤더정보 읽기 */ readHeader(); - String thisDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); - // 날짜가 지난경우와 더이상 읽을 데이터가 없을 경우 큐를 초기화 - if((this.createDate.equals(thisDate) == false)){ - // 파일 내용을 모두 지운다. - channel.truncate(0); - // 헤더 정보를 초기화한다. - this.createDate = thisDate; - this.pushCounter = 0; - // 헤더에 초기데이터를 저장 - writeHeader(); - } + /* 3. 파일 내용을 모두 지운다. */ + channel.truncate(0); + /* 4. 헤더 정보를 초기화한다. */ + this.createDate = thisDate; + this.pushCounter = 0; + /* 5. 헤더에 초기데이터를 저장 */ + writeHeader(); } } catch(Exception 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(); } diff --git a/src/main/java/com/munjaon/server/server/service/BaseService.java b/src/main/java/com/munjaon/server/server/service/BaseService.java new file mode 100644 index 0000000..5e9ef94 --- /dev/null +++ b/src/main/java/com/munjaon/server/server/service/BaseService.java @@ -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(); + } +} diff --git a/src/main/java/com/munjaon/server/server/service/PropertyLoader.java b/src/main/java/com/munjaon/server/server/service/PropertyLoader.java new file mode 100644 index 0000000..99aad05 --- /dev/null +++ b/src/main/java/com/munjaon/server/server/service/PropertyLoader.java @@ -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); + } + } + } + +} diff --git a/src/main/java/com/munjaon/server/server/service/ServiceRunner.java b/src/main/java/com/munjaon/server/server/service/ServiceRunner.java new file mode 100644 index 0000000..d4c6661 --- /dev/null +++ b/src/main/java/com/munjaon/server/server/service/ServiceRunner.java @@ -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 0){ 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"; } 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) { return false; } - if(!src.startsWith("0")) { - return false; - } - - return true; + return src.startsWith("0"); } // 문자열 공백 제거 public static String trim(String 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()); + } + } } diff --git a/src/main/java/com/munjaon/server/util/XmlUtil.java b/src/main/java/com/munjaon/server/util/XmlUtil.java new file mode 100644 index 0000000..0e98084 --- /dev/null +++ b/src/main/java/com/munjaon/server/util/XmlUtil.java @@ -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) { + + } +}