();
+
+ // Check that we have a file upload request
+ boolean isMultipart = ServletFileUpload.isMultipartContent(request);
+
+ if (isMultipart) {
+ // Create a new file upload handler
+ ServletFileUpload upload = new ServletFileUpload();
+ upload.setFileSizeMax(maxFileSize); // SizeLimitExceededException
+
+ // Parse the request
+ FileItemIterator iter = upload.getItemIterator(request);
+ while (iter.hasNext()) {
+ FileItemStream item = iter.next();
+ String name = item.getFieldName();
+ InputStream stream = item.openStream();
+ if (item.isFormField()) {
+ LOGGER.info("Form field '{}' with value '{}' detected.", name, Streams.asString(stream));
+ } else {
+ LOGGER.info("File field '{}' with file name '{}' detected.", name, item.getName());
+
+ if ("".equals(item.getName())) {
+ continue;
+ }
+
+ // Process the input stream
+ EgovFormBasedFileVo vo = new EgovFormBasedFileVo();
+
+ String tmp = item.getName();
+
+ if (tmp.lastIndexOf("\\") >= 0) {
+ tmp = tmp.substring(tmp.lastIndexOf("\\") + 1);
+ }
+
+ vo.setFileName(tmp);
+ vo.setContentType(item.getContentType());
+ vo.setServerSubPath(getTodayString());
+ vo.setPhysicalName(getPhysicalFileName());
+
+ if (tmp.lastIndexOf(".") >= 0) {
+ vo.setPhysicalName(vo.getPhysicalName() + tmp.substring(tmp.lastIndexOf(".")));
+ }
+
+ long size = saveFile(stream, new File(EgovWebUtil.filePathBlackList(where) + SEPERATOR + vo.getServerSubPath() + SEPERATOR + vo.getPhysicalName()));
+
+ vo.setSize(size);
+
+ list.add(vo);
+ }
+ }
+ } else {
+ throw new IOException("form's 'enctype' attribute have to be 'multipart/form-data'");
+ }
+
+ return list;
+ }
+
+ /**
+ * 파일을 Download 처리한다.
+ *
+ * @param response
+ * @param where
+ * @param serverSubPath
+ * @param physicalName
+ * @param original
+ * @throws Exception
+ */
+ public static void downloadFile(HttpServletResponse response, String where, String serverSubPath, String physicalName, String original) throws Exception {
+ String downFileName = where + SEPERATOR + serverSubPath + SEPERATOR + physicalName;
+
+ File file = new File(EgovWebUtil.filePathBlackList(downFileName));
+
+ if (!file.exists()) {
+ throw new FileNotFoundException(downFileName);
+ }
+
+ if (!file.isFile()) {
+ throw new FileNotFoundException(downFileName);
+ }
+
+ byte[] b = new byte[BUFFER_SIZE];
+
+ original = original.replaceAll("\r", "").replaceAll("\n", "");
+ response.setContentType("application/octet-stream");
+ response.setHeader("Content-Disposition", "attachment; filename=\"" + convert(original) + "\";");
+ response.setHeader("Content-Transfer-Encoding", "binary");
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Expires", "0");
+
+ BufferedInputStream fin = null;
+ BufferedOutputStream outs = null;
+
+ try {
+ fin = new BufferedInputStream(new FileInputStream(file));
+ outs = new BufferedOutputStream(response.getOutputStream());
+
+ int read = 0;
+
+ while ((read = fin.read(b)) != -1) {
+ outs.write(b, 0, read);
+ }
+ } finally {
+ EgovResourceCloseHelper.close(outs, fin);
+ }
+ }
+
+ /**
+ * 이미지에 대한 미리보기 기능을 제공한다.
+ *
+ * mimeType의 경우는 JSP 상에서 다음과 같이 얻을 수 있다.
+ * getServletConfig().getServletContext().getMimeType(name);
+ *
+ * @param response
+ * @param where
+ * @param serverSubPath
+ * @param physicalName
+ * @param mimeType
+ * @throws Exception
+ */
+ public static void viewFile(HttpServletResponse response, String where, String serverSubPath, String physicalName, String mimeTypeParam) throws Exception {
+ String mimeType = mimeTypeParam;
+ String downFileName = where + SEPERATOR + serverSubPath + SEPERATOR + physicalName;
+
+ File file = new File(EgovWebUtil.filePathBlackList(downFileName));
+
+ if (!file.exists()) {
+ throw new FileNotFoundException(downFileName);
+ }
+
+ if (!file.isFile()) {
+ throw new FileNotFoundException(downFileName);
+ }
+
+ byte[] b = new byte[BUFFER_SIZE];
+
+ if (mimeType == null) {
+ mimeType = "application/octet-stream;";
+ }
+
+ response.setContentType(EgovWebUtil.removeCRLF(mimeType));
+ response.setHeader("Content-Disposition", "filename=image;");
+
+ BufferedInputStream fin = null;
+ BufferedOutputStream outs = null;
+
+ try {
+ fin = new BufferedInputStream(new FileInputStream(file));
+ outs = new BufferedOutputStream(response.getOutputStream());
+
+ int read = 0;
+
+ while ((read = fin.read(b)) != -1) {
+ outs.write(b, 0, read);
+ }
+ } finally {
+ EgovResourceCloseHelper.close(outs, fin);
+ }
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/egov/file/EgovFormBasedFileVo.java b/src/main/java/kcg/imis/cmmn/egov/file/EgovFormBasedFileVo.java
new file mode 100644
index 0000000..b8e3cff
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/file/EgovFormBasedFileVo.java
@@ -0,0 +1,104 @@
+package kcg.imis.cmmn.egov.file;
+
+import java.io.Serializable;
+
+/**
+ * @Class Name : EgovFormBasedFileVo.java
+ * @Description : Form-based File Upload VO
+ * @Modification Information
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2009.08.26 한성곤 최초 생성
+ *
+ * @author 공통컴포넌트 개발팀 한성곤
+ * @since 2009.08.26
+ * @version 1.0
+ * @see
+ *
+ * Copyright (C) 2008 by MOPAS All right reserved.
+ */
+@SuppressWarnings("serial")
+public class EgovFormBasedFileVo implements Serializable {
+ /** 파일명 */
+ private String fileName = "";
+ /** ContextType */
+ private String contentType = "";
+ /** 하위 디렉토리 지정 */
+ private String serverSubPath = "";
+ /** 물리적 파일명 */
+ private String physicalName = "";
+ /** 파일 사이즈 */
+ private long size = 0L;
+
+ /**
+ * fileName attribute를 리턴한다.
+ * @return the fileName
+ */
+ public String getFileName() {
+ return fileName;
+ }
+ /**
+ * fileName attribute 값을 설정한다.
+ * @param fileName the fileName to set
+ */
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+ /**
+ * contentType attribute를 리턴한다.
+ * @return the contentType
+ */
+ public String getContentType() {
+ return contentType;
+ }
+ /**
+ * contentType attribute 값을 설정한다.
+ * @param contentType the contentType to set
+ */
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+ /**
+ * serverSubPath attribute를 리턴한다.
+ * @return the serverSubPath
+ */
+ public String getServerSubPath() {
+ return serverSubPath;
+ }
+ /**
+ * serverSubPath attribute 값을 설정한다.
+ * @param serverSubPath the serverSubPath to set
+ */
+ public void setServerSubPath(String serverSubPath) {
+ this.serverSubPath = serverSubPath;
+ }
+ /**
+ * physicalName attribute를 리턴한다.
+ * @return the physicalName
+ */
+ public String getPhysicalName() {
+ return physicalName;
+ }
+ /**
+ * physicalName attribute 값을 설정한다.
+ * @param physicalName the physicalName to set
+ */
+ public void setPhysicalName(String physicalName) {
+ this.physicalName = physicalName;
+ }
+ /**
+ * size attribute를 리턴한다.
+ * @return the size
+ */
+ public long getSize() {
+ return size;
+ }
+ /**
+ * size attribute 값을 설정한다.
+ * @param size the size to set
+ */
+ public void setSize(long size) {
+ this.size = size;
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/egov/file/EgovFormBasedUUID.java b/src/main/java/kcg/imis/cmmn/egov/file/EgovFormBasedUUID.java
new file mode 100644
index 0000000..5f2b961
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/file/EgovFormBasedUUID.java
@@ -0,0 +1,529 @@
+package kcg.imis.cmmn.egov.file;
+
+import java.io.Serializable;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+/**
+ *
+ * A class that represents an immutable universally unique identifier (UUID). A
+ * UUID represents a 128-bit value.
+ *
+ *
+ * There exist different variants of these global identifiers. The methods of
+ * this class are for manipulating the Leach-Salz variant, although the
+ * constructors allow the creation of any variant of UUID (described below).
+ *
+ *
+ * The layout of a variant 2 (Leach-Salz) UUID is as follows:
+ *
+ * The most significant long consists of the following unsigned fields:
+ *
+ *
+ * 0xFFFFFFFF00000000 time_low
+ * 0x00000000FFFF0000 time_mid
+ * 0x000000000000F000 version
+ * 0x0000000000000FFF time_hi
+ *
+ *
+ * The least significant long consists of the following unsigned fields:
+ *
+ *
+ * 0xC000000000000000 variant
+ * 0x3FFF000000000000 clock_seq
+ * 0x0000FFFFFFFFFFFF node
+ *
+ *
+ *
+ * The variant field contains a value which identifies the layout of the
+ * UUID. The bit layout described above is valid only for a
+ * UUID with a variant value of 2, which indicates the Leach-Salz
+ * variant.
+ *
+ *
+ * The version field holds a value that describes the type of this UUID.
+ * There are four different basic types of UUIDs: time-based, DCE security,
+ * name-based, and randomly generated UUIDs. These types have a version value of
+ * 1, 2, 3 and 4, respectively.
+ *
+ *
+ * For more information including algorithms used to create UUIDs,
+ * see the Internet-Draft UUIDs
+ * and GUIDs or the standards body definition at ISO/IEC 11578:1996.
+ *
+ * @version 1.14, 07/12/04
+ * @since 1.5
+ */
+@SuppressWarnings("serial")
+public class EgovFormBasedUUID implements Serializable {
+ /*
+ * The most significant 64 bits of this UUID.
+ *
+ * @serial
+ */
+ private final long mostSigBits;
+
+ /*
+ * The least significant 64 bits of this UUID.
+ *
+ * @serial
+ */
+ private final long leastSigBits;
+
+ /*
+ * The version number associated with this UUID. Computed on demand.
+ */
+ private transient int version = -1;
+
+ /*
+ * The variant number associated with this UUID. Computed on demand.
+ */
+ private transient int variant = -1;
+
+ /*
+ * The timestamp associated with this UUID. Computed on demand.
+ */
+ private transient volatile long timestamp = -1;
+
+ /*
+ * The clock sequence associated with this UUID. Computed on demand.
+ */
+ private transient int sequence = -1;
+
+ /*
+ * The node number associated with this UUID. Computed on demand.
+ */
+ private transient long node = -1;
+
+ /*
+ * The hashcode of this UUID. Computed on demand.
+ */
+ private transient int hashCode = -1;
+
+ /*
+ * The random number generator used by this class to create random based
+ * UUIDs.
+ */
+ private static volatile SecureRandom numberGenerator = null;
+
+ // Constructors and Factories
+
+ /*
+ * Private constructor which uses a byte array to construct the new UUID.
+ */
+ private EgovFormBasedUUID(byte[] data) {
+ long msb = 0;
+ long lsb = 0;
+ for (int i = 0; i < 8; i++)
+ msb = (msb << 8) | (data[i] & 0xff);
+ for (int i = 8; i < 16; i++)
+ lsb = (lsb << 8) | (data[i] & 0xff);
+ this.mostSigBits = msb;
+ this.leastSigBits = lsb;
+ }
+
+ /**
+ * Constructs a new UUID using the specified data.
+ * mostSigBits is used for the most significant 64 bits of the
+ * UUID and leastSigBits becomes the least significant
+ * 64 bits of the UUID.
+ *
+ * @param mostSigBits
+ * @param leastSigBits
+ */
+ public EgovFormBasedUUID(long mostSigBits, long leastSigBits) {
+ this.mostSigBits = mostSigBits;
+ this.leastSigBits = leastSigBits;
+ }
+
+ /**
+ * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
+ *
+ * The UUID is generated using a cryptographically strong
+ * pseudo random number generator.
+ *
+ * @return a randomly generated UUID.
+ */
+ public static EgovFormBasedUUID randomUUID() {
+ SecureRandom ng = numberGenerator;
+ if (ng == null) {
+ numberGenerator = ng = new SecureRandom();
+ }
+
+ byte[] randomBytes = new byte[16];
+ ng.nextBytes(randomBytes);
+ randomBytes[6] &= 0x0f; /* clear version */
+ randomBytes[6] |= 0x40; /* set to version 4 */
+ randomBytes[8] &= 0x3f; /* clear variant */
+ randomBytes[8] |= 0x80; /* set to IETF variant */
+
+ return new EgovFormBasedUUID(randomBytes);
+ }
+
+ /**
+ * Static factory to retrieve a type 3 (name based) UUID based on
+ * the specified byte array.
+ *
+ * @param name
+ * a byte array to be used to construct a UUID.
+ * @return a UUID generated from the specified array.
+ */
+ public static EgovFormBasedUUID nameUUIDFromBytes(byte[] name) {
+ return null;
+
+/*
+ * 2106.11.18 김노민
+ * FindBugs에서 Array index is out of bounds. 문제를 제시한다.
+ * 어차피 사용하지 않으니 해당 메소드를 수정하지 않고 모두 주석처리한다.
+ *
+ *
+ MessageDigest md;
+ try {
+ // 2011.10.10 보안점검 후속조치 암호화 알고리즘 변경(MD5 -> SHA-256)
+ //md = MessageDigest.getInstance("MD5");
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException nsae) {
+ //throw new InternalError("MD5 not supported");
+ throw new InternalError("SHA-256 not supported");
+ }
+ // 2011.10.10 보안점검 후속조치
+ if (md == null) {
+ throw new RuntimeException("MessageDigest is null!!");
+ }
+ // 2014.09.20 보안점검 후속 조치
+ // Random 방식의 salt 추가
+ SecureRandom ng = new SecureRandom();
+ byte[] randomBytes = new byte[16];
+ ng.nextBytes(randomBytes);
+
+ md.reset();
+ md.update(randomBytes);
+ byte[] sha = md.digest(name);
+
+
+ byte[] md5Bytes = new byte[8];
+ System.arraycopy(sha, 0, md5Bytes, 0, 8);
+ //2011.10.10 보안점검 후속조치 끝
+
+ md5Bytes[6] &= 0x0f; clear version
+ md5Bytes[6] |= 0x30; set to version 3
+ md5Bytes[8] &= 0x3f; clear variant
+ md5Bytes[8] |= 0x80; set to IETF variant
+
+ return new EgovFormBasedUUID(md5Bytes);*/
+ }
+
+ /**
+ * Creates a UUID from the string standard representation as
+ * described in the {@link #toString} method.
+ *
+ * @param name
+ * a string that specifies a UUID.
+ * @return a UUID with the specified value.
+ * @throws IllegalArgumentException
+ * if name does not conform to the string representation as
+ * described in {@link #toString}.
+ */
+ public static EgovFormBasedUUID fromString(String name) {
+ String[] components = name.split("-");
+ if (components.length != 5)
+ throw new IllegalArgumentException("Invalid UUID string: " + name);
+ for (int i = 0; i < 5; i++)
+ components[i] = "0x" + components[i];
+
+ long mostSigBits = Long.decode(components[0]).longValue();
+ mostSigBits <<= 16;
+ mostSigBits |= Long.decode(components[1]).longValue();
+ mostSigBits <<= 16;
+ mostSigBits |= Long.decode(components[2]).longValue();
+
+ long leastSigBits = Long.decode(components[3]).longValue();
+ leastSigBits <<= 48;
+ leastSigBits |= Long.decode(components[4]).longValue();
+
+ return new EgovFormBasedUUID(mostSigBits, leastSigBits);
+ }
+
+ // Field Accessor Methods
+
+ /**
+ * Returns the least significant 64 bits of this UUID's 128 bit value.
+ *
+ * @return the least significant 64 bits of this UUID's 128 bit value.
+ */
+ public long getLeastSignificantBits() {
+ return leastSigBits;
+ }
+
+ /**
+ * Returns the most significant 64 bits of this UUID's 128 bit value.
+ *
+ * @return the most significant 64 bits of this UUID's 128 bit value.
+ */
+ public long getMostSignificantBits() {
+ return mostSigBits;
+ }
+
+ /**
+ * The version number associated with this UUID. The version
+ * number describes how this UUID was generated.
+ *
+ * The version number has the following meaning:
+ *
+ *
+ * - 1 Time-based UUID
+ *
- 2 DCE security UUID
+ *
- 3 Name-based UUID
+ *
- 4 Randomly generated UUID
+ *
+ *
+ * @return the version number of this UUID.
+ */
+ public int version() {
+ if (version < 0) {
+ // Version is bits masked by 0x000000000000F000 in MS long
+ version = (int) ((mostSigBits >> 12) & 0x0f);
+ }
+ return version;
+ }
+
+ /**
+ * The variant number associated with this UUID. The variant
+ * number describes the layout of the UUID.
+ *
+ * The variant number has the following meaning:
+ *
+ *
+ * - 0 Reserved for NCS backward compatibility
+ *
- 2 The Leach-Salz variant (used by this class)
+ *
- 6 Reserved, Microsoft Corporation backward compatibility
+ *
- 7 Reserved for future definition
+ *
+ *
+ * @return the variant number of this UUID.
+ */
+ public int variant() {
+ if (variant < 0) {
+ // This field is composed of a varying number of bits
+ if ((leastSigBits >>> 63) == 0) {
+ variant = 0;
+ } else if ((leastSigBits >>> 62) == 2) {
+ variant = 2;
+ } else {
+ variant = (int) (leastSigBits >>> 61);
+ }
+ }
+ return variant;
+ }
+
+ /**
+ * The timestamp value associated with this UUID.
+ *
+ *
+ * The 60 bit timestamp value is constructed from the time_low, time_mid,
+ * and time_hi fields of this UUID. The resulting timestamp is
+ * measured in 100-nanosecond units since midnight, October 15, 1582 UTC.
+ *
+ *
+ * The timestamp value is only meaningful in a time-based UUID, which has
+ * version type 1. If this UUID is not a time-based UUID then
+ * this method throws UnsupportedOperationException.
+ *
+ * @throws UnsupportedOperationException
+ * if this UUID is not a version 1 UUID.
+ */
+ public long timestamp() {
+ if (version() != 1) {
+ throw new UnsupportedOperationException("Not a time-based UUID");
+ }
+ long result = timestamp;
+ if (result < 0) {
+ result = (mostSigBits & 0x0000000000000FFFL) << 48;
+ result |= ((mostSigBits >> 16) & 0xFFFFL) << 32;
+ result |= mostSigBits >>> 32;
+ timestamp = result;
+ }
+ return result;
+ }
+
+ /**
+ * The clock sequence value associated with this UUID.
+ *
+ *
+ * The 14 bit clock sequence value is constructed from the clock sequence
+ * field of this UUID. The clock sequence field is used to guarantee
+ * temporal uniqueness in a time-based UUID.
+ *
+ *
+ * The clockSequence value is only meaningful in a time-based UUID, which
+ * has version type 1. If this UUID is not a time-based UUID then this
+ * method throws UnsupportedOperationException.
+ *
+ * @return the clock sequence of this UUID.
+ * @throws UnsupportedOperationException
+ * if this UUID is not a version 1 UUID.
+ */
+ public int clockSequence() {
+ if (version() != 1) {
+ throw new UnsupportedOperationException("Not a time-based UUID");
+ }
+ if (sequence < 0) {
+ sequence = (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
+ }
+ return sequence;
+ }
+
+ /**
+ * The node value associated with this UUID.
+ *
+ *
+ * The 48 bit node value is constructed from the node field of this UUID.
+ * This field is intended to hold the IEEE 802 address of the machine that
+ * generated this UUID to guarantee spatial uniqueness.
+ *
+ *
+ * The node value is only meaningful in a time-based UUID, which has version
+ * type 1. If this UUID is not a time-based UUID then this method throws
+ * UnsupportedOperationException.
+ *
+ * @return the node value of this UUID.
+ * @throws UnsupportedOperationException
+ * if this UUID is not a version 1 UUID.
+ */
+ public long node() {
+ if (version() != 1) {
+ throw new UnsupportedOperationException("Not a time-based UUID");
+ }
+ if (node < 0) {
+ node = leastSigBits & 0x0000FFFFFFFFFFFFL;
+ }
+ return node;
+ }
+
+ // Object Inherited Methods
+
+ /**
+ * Returns a String object representing this
+ * UUID.
+ *
+ *
+ * The UUID string representation is as described by this BNF :
+ *
+ *
+ * UUID = <time_low> "-" <time_mid> "-"
+ * <time_high_and_version> "-"
+ * <variant_and_sequence> "-"
+ * <node>
+ * time_low = 4*<hexOctet>
+ * time_mid = 2*<hexOctet>
+ * time_high_and_version = 2*<hexOctet>
+ * variant_and_sequence = 2*<hexOctet>
+ * node = 6*<hexOctet>
+ * hexOctet = <hexDigit><hexDigit>
+ * hexDigit =
+ * "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+ * | "a" | "b" | "c" | "d" | "e" | "f"
+ * | "A" | "B" | "C" | "D" | "E" | "F"
+ *
+ *
+ * @return a string representation of this UUID.
+ */
+ @Override
+ public String toString() {
+ return (digits(mostSigBits >> 32, 8) + "-"
+ + digits(mostSigBits >> 16, 4) + "-" + digits(mostSigBits, 4)
+ + "-" + digits(leastSigBits >> 48, 4) + "-" + digits(
+ leastSigBits, 12));
+ }
+
+ /** Returns val represented by the specified number of hex digits. */
+ private static String digits(long val, int digits) {
+ long hi = 1L << (digits * 4);
+ return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+ }
+
+ /**
+ * Returns a hash code for this UUID.
+ *
+ * @return a hash code value for this UUID.
+ */
+ @Override
+ public int hashCode() {
+ if (hashCode == -1) {
+ hashCode = (int) ((mostSigBits >> 32) ^ mostSigBits
+ ^ (leastSigBits >> 32) ^ leastSigBits);
+ }
+ return hashCode;
+ }
+
+ /**
+ * Compares this object to the specified object. The result is true
+ * if and only if the argument is not null, is a UUID
+ * object, has the same variant, and contains the same value, bit for bit,
+ * as this UUID.
+ *
+ * @param obj
+ * the object to compare with.
+ * @return true if the objects are the same;
+ * false otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ // 보안 취약점 점검 지적사항 반영 시작
+ if (obj == null)
+ return false;
+ // 보안 취약점 점검 지적사항 반영 시작 끝
+ if (!(obj instanceof EgovFormBasedUUID))
+ return false;
+ if (((EgovFormBasedUUID) obj).variant() != this.variant())
+ return false;
+ EgovFormBasedUUID id = (EgovFormBasedUUID) obj;
+ return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
+ }
+
+ // Comparison Operations
+
+ /**
+ * Compares this UUID with the specified UUID.
+ *
+ *
+ * The first of two UUIDs follows the second if the most significant field
+ * in which the UUIDs differ is greater for the first UUID.
+ *
+ * @param val
+ * UUID to which this UUID is to be
+ * compared.
+ * @return -1, 0 or 1 as this UUID is less than, equal to, or
+ * greater than val.
+ */
+ public int compareTo(EgovFormBasedUUID val) {
+ // The ordering is intentionally set up so that the UUIDs
+ // can simply be numerically compared as two numbers
+ return (this.mostSigBits < val.mostSigBits ? -1
+ : (this.mostSigBits > val.mostSigBits ? 1
+ : (this.leastSigBits < val.leastSigBits ? -1
+ : (this.leastSigBits > val.leastSigBits ? 1 : 0))));
+ }
+
+ /**
+ * Reconstitute the UUID instance from a stream (that is,
+ * deserialize it). This is necessary to set the transient fields to their
+ * correct uninitialized value so they will be recomputed on demand.
+ */
+ private void readObject(java.io.ObjectInputStream in)
+ throws java.io.IOException, ClassNotFoundException {
+
+ in.defaultReadObject();
+
+ // Set "cached computation" fields to their initial values
+ version = -1;
+ variant = -1;
+ timestamp = -1;
+ sequence = -1;
+ node = -1;
+ hashCode = -1;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/kcg/imis/cmmn/egov/filter/HTMLTagFilter.java b/src/main/java/kcg/imis/cmmn/egov/filter/HTMLTagFilter.java
new file mode 100644
index 0000000..fb804e0
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/filter/HTMLTagFilter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008-2009 MOPAS(Ministry of Public Administration and Security).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package kcg.imis.cmmn.egov.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+public class HTMLTagFilter implements Filter{
+
+ @SuppressWarnings("unused")
+ private FilterConfig config;
+
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+
+ chain.doFilter(request, response);
+ }
+
+ public void init(FilterConfig config) throws ServletException {
+ this.config = config;
+ }
+
+ public void destroy() {
+
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/egov/filter/HTMLTagFilterRequestWrapper.java b/src/main/java/kcg/imis/cmmn/egov/filter/HTMLTagFilterRequestWrapper.java
new file mode 100644
index 0000000..f3f0567
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/filter/HTMLTagFilterRequestWrapper.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2008-2009 MOPAS(Ministry of Public Administration and Security).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package kcg.imis.cmmn.egov.filter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+public class HTMLTagFilterRequestWrapper extends HttpServletRequestWrapper {
+
+ public HTMLTagFilterRequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+
+ public String[] getParameterValues(String parameter) {
+
+ String[] values = super.getParameterValues(parameter);
+
+ if(values==null){
+ return null;
+ }
+
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] != null) {
+ StringBuffer strBuff = new StringBuffer();
+ for (int j = 0; j < values[i].length(); j++) {
+ char c = values[i].charAt(j);
+ switch (c) {
+ case '<':
+ strBuff.append("<");
+ break;
+ case '>':
+ strBuff.append(">");
+ break;
+ //case '&':
+ //strBuff.append("&");
+ //break;
+ case '"':
+ strBuff.append(""");
+ break;
+ case '\'':
+ strBuff.append("'");
+ break;
+ default:
+ strBuff.append(c);
+ break;
+ }
+ }
+ values[i] = strBuff.toString();
+ } else {
+ values[i] = null;
+ }
+ }
+
+ return values;
+ }
+
+ public String getParameter(String parameter) {
+
+ String value = super.getParameter(parameter);
+
+ if(value==null){
+ return null;
+ }
+
+ StringBuffer strBuff = new StringBuffer();
+
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ switch (c) {
+ case '<':
+ strBuff.append("<");
+ break;
+ case '>':
+ strBuff.append(">");
+ break;
+ case '&':
+ strBuff.append("&");
+ break;
+ case '"':
+ strBuff.append(""");
+ break;
+ case '\'':
+ strBuff.append("'");
+ break;
+ default:
+ strBuff.append(c);
+ break;
+ }
+ }
+
+ value = strBuff.toString();
+
+ return value;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/kcg/imis/cmmn/egov/filter/RequestBodyXSSFilter.java b/src/main/java/kcg/imis/cmmn/egov/filter/RequestBodyXSSFilter.java
new file mode 100644
index 0000000..592b56b
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/filter/RequestBodyXSSFilter.java
@@ -0,0 +1,36 @@
+package kcg.imis.cmmn.egov.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class RequestBodyXSSFilter implements Filter {
+
+ @Override
+ public void destroy() {}
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // TODO Auto-generated method stub
+
+ }
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest req = (HttpServletRequest)request;
+ HttpServletResponse res = (HttpServletResponse)response;
+// RequestWrapper requestWrapper = null;
+ try{
+// requestWrapper = new RequestWrapper(req);
+ }catch(Exception e){
+ e.printStackTrace();
+ }
+ chain.doFilter(req, res);
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/egov/util/EgovStringUtil.java b/src/main/java/kcg/imis/cmmn/egov/util/EgovStringUtil.java
new file mode 100644
index 0000000..613f932
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/util/EgovStringUtil.java
@@ -0,0 +1,895 @@
+/**
+ * @Class Name : EgovStringUtil.java
+ * @Description : 문자열 데이터 처리 관련 유틸리티
+ * @Modification Information
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2009.01.13 박정규 최초 생성
+ * 2009.02.13 이삼섭 내용 추가
+ *
+ * @author 공통 서비스 개발팀 박정규
+ * @since 2009. 01. 13
+ * @version 1.0
+ * @see
+ *
+ */
+
+package kcg.imis.cmmn.egov.util;
+
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the ";License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS"; BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.security.SecureRandom;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EgovStringUtil {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(EgovStringUtil.class);
+
+ /**
+ * 빈 문자열 "".
+ */
+ public static final String EMPTY = "";
+
+ /**
+ *
Padding을 할 수 있는 최대 수치
+ */
+ // private static final int PAD_LIMIT = 8192;
+ /**
+ * An array of Strings used for padding.
+ * Used for efficient space padding. The length of each String expands as needed.
+ */
+ /*
+ private static final String[] PADDING = new String[Character.MAX_VALUE];
+
+ static {
+ // space padding is most common, start with 64 chars
+ PADDING[32] = " ";
+ }
+ */
+
+ /**
+ * 문자열이 지정한 길이를 초과했을때 지정한길이에다가 해당 문자열을 붙여주는 메서드.
+ * @param source 원본 문자열 배열
+ * @param output 더할문자열
+ * @param slength 지정길이
+ * @return 지정길이로 잘라서 더할분자열 합친 문자열
+ */
+ public static String cutString(String source, String output, int slength) {
+ String returnVal = null;
+ if (source != null) {
+ if (source.length() > slength) {
+ returnVal = source.substring(0, slength) + output;
+ } else
+ returnVal = source;
+ }
+ return returnVal;
+ }
+
+ /**
+ * 문자열이 지정한 길이를 초과했을때 해당 문자열을 삭제하는 메서드
+ * @param source 원본 문자열 배열
+ * @param slength 지정길이
+ * @return 지정길이로 잘라서 더할분자열 합친 문자열
+ */
+ public static String cutString(String source, int slength) {
+ String result = null;
+ if (source != null) {
+ if (source.length() > slength) {
+ result = source.substring(0, slength);
+ } else
+ result = source;
+ }
+ return result;
+ }
+
+ /**
+ *
+ * String이 비었거나("") 혹은 null 인지 검증한다.
+ *
+ *
+ *
+ * StringUtil.isEmpty(null) = true
+ * StringUtil.isEmpty("") = true
+ * StringUtil.isEmpty(" ") = false
+ * StringUtil.isEmpty("bob") = false
+ * StringUtil.isEmpty(" bob ") = false
+ *
+ *
+ * @param str - 체크 대상 스트링오브젝트이며 null을 허용함
+ * @return true - 입력받은 String 이 빈 문자열 또는 null인 경우
+ */
+ public static boolean isEmpty(String str) {
+ return str == null || str.length() == 0;
+ }
+
+ /**
+ * 기준 문자열에 포함된 모든 대상 문자(char)를 제거한다.
+ *
+ *
+ * StringUtil.remove(null, *) = null
+ * StringUtil.remove("", *) = ""
+ * StringUtil.remove("queued", 'u') = "qeed"
+ * StringUtil.remove("queued", 'z') = "queued"
+ *
+ *
+ * @param str 입력받는 기준 문자열
+ * @param remove 입력받는 문자열에서 제거할 대상 문자열
+ * @return 제거대상 문자열이 제거된 입력문자열. 입력문자열이 null인 경우 출력문자열은 null
+ */
+ public static String remove(String str, char remove) {
+ if (isEmpty(str) || str.indexOf(remove) == -1) {
+ return str;
+ }
+ char[] chars = str.toCharArray();
+ int pos = 0;
+ for (int i = 0; i < chars.length; i++) {
+ if (chars[i] != remove) {
+ chars[pos++] = chars[i];
+ }
+ }
+ return new String(chars, 0, pos);
+ }
+
+ /**
+ * 문자열 내부의 콤마 character(,)를 모두 제거한다.
+ *
+ *
+ * StringUtil.removeCommaChar(null) = null
+ * StringUtil.removeCommaChar("") = ""
+ * StringUtil.removeCommaChar("asdfg,qweqe") = "asdfgqweqe"
+ *
+ *
+ * @param str 입력받는 기준 문자열
+ * @return " , "가 제거된 입력문자열
+ * 입력문자열이 null인 경우 출력문자열은 null
+ */
+ public static String removeCommaChar(String str) {
+ return remove(str, ',');
+ }
+
+ /**
+ * 문자열 내부의 마이너스 character(-)를 모두 제거한다.
+ *
+ *
+ * StringUtil.removeMinusChar(null) = null
+ * StringUtil.removeMinusChar("") = ""
+ * StringUtil.removeMinusChar("a-sdfg-qweqe") = "asdfgqweqe"
+ *
+ *
+ * @param str 입력받는 기준 문자열
+ * @return " - "가 제거된 입력문자열
+ * 입력문자열이 null인 경우 출력문자열은 null
+ */
+ public static String removeMinusChar(String str) {
+ return remove(str, '-');
+ }
+
+ /**
+ * 원본 문자열의 포함된 특정 문자열을 새로운 문자열로 변환하는 메서드
+ * @param source 원본 문자열
+ * @param subject 원본 문자열에 포함된 특정 문자열
+ * @param object 변환할 문자열
+ * @return sb.toString() 새로운 문자열로 변환된 문자열
+ */
+ public static String replace(String source, String subject, String object) {
+ StringBuffer rtnStr = new StringBuffer();
+ String preStr = "";
+ String nextStr = source;
+ String srcStr = source;
+
+ while (srcStr.indexOf(subject) >= 0) {
+ preStr = srcStr.substring(0, srcStr.indexOf(subject));
+ nextStr = srcStr.substring(srcStr.indexOf(subject) + subject.length(), srcStr.length());
+ srcStr = nextStr;
+ rtnStr.append(preStr).append(object);
+ }
+ rtnStr.append(nextStr);
+ return rtnStr.toString();
+ }
+
+ /**
+ * 원본 문자열의 포함된 특정 문자열 첫번째 한개만 새로운 문자열로 변환하는 메서드
+ * @param source 원본 문자열
+ * @param subject 원본 문자열에 포함된 특정 문자열
+ * @param object 변환할 문자열
+ * @return sb.toString() 새로운 문자열로 변환된 문자열 / source 특정문자열이 없는 경우 원본 문자열
+ */
+ public static String replaceOnce(String source, String subject, String object) {
+ StringBuffer rtnStr = new StringBuffer();
+ String preStr = "";
+ String nextStr = source;
+ if (source.indexOf(subject) >= 0) {
+ preStr = source.substring(0, source.indexOf(subject));
+ nextStr = source.substring(source.indexOf(subject) + subject.length(), source.length());
+ rtnStr.append(preStr).append(object).append(nextStr);
+ return rtnStr.toString();
+ } else {
+ return source;
+ }
+ }
+
+ /**
+ * subject에 포함된 각각의 문자를 object로 변환한다.
+ *
+ * @param source 원본 문자열
+ * @param subject 원본 문자열에 포함된 특정 문자열
+ * @param object 변환할 문자열
+ * @return sb.toString() 새로운 문자열로 변환된 문자열
+ */
+ public static String replaceChar(String source, String subject, String object) {
+ StringBuffer rtnStr = new StringBuffer();
+ String preStr = "";
+ String nextStr = source;
+ String srcStr = source;
+
+ char chA;
+
+ for (int i = 0; i < subject.length(); i++) {
+ chA = subject.charAt(i);
+
+ if (srcStr.indexOf(chA) >= 0) {
+ preStr = srcStr.substring(0, srcStr.indexOf(chA));
+ nextStr = srcStr.substring(srcStr.indexOf(chA) + 1, srcStr.length());
+ srcStr = rtnStr.append(preStr).append(object).append(nextStr).toString();
+ }
+ }
+
+ return srcStr;
+ }
+
+ /**
+ * str 중 searchStr의 시작(index) 위치를 반환.
+ *
+ * 입력값 중 null이 있을 경우 -1을 반환.
+ *
+ *
+ * StringUtil.indexOf(null, *) = -1
+ * StringUtil.indexOf(*, null) = -1
+ * StringUtil.indexOf("", "") = 0
+ * StringUtil.indexOf("aabaabaa", "a") = 0
+ * StringUtil.indexOf("aabaabaa", "b") = 2
+ * StringUtil.indexOf("aabaabaa", "ab") = 1
+ * StringUtil.indexOf("aabaabaa", "") = 0
+ *
+ *
+ * @param str 검색 문자열
+ * @param searchStr 검색 대상문자열
+ * @return 검색 문자열 중 검색 대상문자열이 있는 시작 위치 검색대상 문자열이 없거나 null인 경우 -1
+ */
+ public static int indexOf(String str, String searchStr) {
+ if (str == null || searchStr == null) {
+ return -1;
+ }
+ return str.indexOf(searchStr);
+ }
+
+ /**
+ * 오라클의 decode 함수와 동일한 기능을 가진 메서드이다.
+ * sourStr과 compareStr의 값이 같으면
+ * returStr을 반환하며, 다르면 defaultStr을 반환한다.
+ *
+ *
+ *
+ * StringUtil.decode(null, null, "foo", "bar")= "foo"
+ * StringUtil.decode("", null, "foo", "bar") = "bar"
+ * StringUtil.decode(null, "", "foo", "bar") = "bar"
+ * StringUtil.decode("하이", "하이", null, "bar") = null
+ * StringUtil.decode("하이", "하이 ", "foo", null) = null
+ * StringUtil.decode("하이", "하이", "foo", "bar") = "foo"
+ * StringUtil.decode("하이", "하이 ", "foo", "bar") = "bar"
+ *
+ *
+ * @param sourceStr 비교할 문자열
+ * @param compareStr 비교 대상 문자열
+ * @param returnStr sourceStr와 compareStr의 값이 같을 때 반환할 문자열
+ * @param defaultStr sourceStr와 compareStr의 값이 다를 때 반환할 문자열
+ * @return sourceStr과 compareStr의 값이 동일(equal)할 때 returnStr을 반환하며,
+ *
다르면 defaultStr을 반환한다.
+ */
+ public static String decode(String sourceStr, String compareStr, String returnStr, String defaultStr) {
+ if (sourceStr == null && compareStr == null) {
+ return returnStr;
+ }
+
+ if (sourceStr == null && compareStr != null) {
+ return defaultStr;
+ }
+
+ if (sourceStr != null && sourceStr.trim().equals(compareStr)) {
+ return returnStr;
+ }
+
+ return defaultStr;
+ }
+
+ /**
+ * 오라클의 decode 함수와 동일한 기능을 가진 메서드이다.
+ * sourStr과 compareStr의 값이 같으면
+ * returStr을 반환하며, 다르면 sourceStr을 반환한다.
+ *
+ *
+ *
+ * StringUtil.decode(null, null, "foo") = "foo"
+ * StringUtil.decode("", null, "foo") = ""
+ * StringUtil.decode(null, "", "foo") = null
+ * StringUtil.decode("하이", "하이", "foo") = "foo"
+ * StringUtil.decode("하이", "하이 ", "foo") = "하이"
+ * StringUtil.decode("하이", "바이", "foo") = "하이"
+ *
+ *
+ * @param sourceStr 비교할 문자열
+ * @param compareStr 비교 대상 문자열
+ * @param returnStr sourceStr와 compareStr의 값이 같을 때 반환할 문자열
+ * @return sourceStr과 compareStr의 값이 동일(equal)할 때 returnStr을 반환하며,
+ *
다르면 sourceStr을 반환한다.
+ */
+ public static String decode(String sourceStr, String compareStr, String returnStr) {
+ return decode(sourceStr, compareStr, returnStr, sourceStr);
+ }
+
+ /**
+ * 객체가 null인지 확인하고 null인 경우 "" 로 바꾸는 메서드
+ * @param object 원본 객체
+ * @return resultVal 문자열
+ */
+ public static String isNullToString(Object object) {
+ String string = "";
+
+ if (object != null) {
+ string = object.toString().trim();
+ }
+
+ return string;
+ }
+
+ /**
+ *
+ * 인자로 받은 String이 null일 경우 ""로 리턴한다.
+ * @param src null값일 가능성이 있는 String 값.
+ * @return 만약 String이 null 값일 경우 ""로 바꾼 String 값.
+ *
+ */
+ public static String nullConvert(Object src) {
+ //if (src != null && src.getClass().getName().equals("java.math.BigDecimal")) {
+ if (src != null && src instanceof java.math.BigDecimal) {
+ return ((BigDecimal) src).toString();
+ }
+
+ if (src == null || src.equals("null")) {
+ return "";
+ } else {
+ return ((String) src).trim();
+ }
+ }
+
+ /**
+ *
+ * 인자로 받은 String이 null일 경우 ""로 리턴한다.
+ * @param src null값일 가능성이 있는 String 값.
+ * @return 만약 String이 null 값일 경우 ""로 바꾼 String 값.
+ *
+ */
+ public static String nullConvert(String src) {
+
+ if (src == null || src.equals("null") || "".equals(src) || " ".equals(src)) {
+ return "";
+ } else {
+ return src.trim();
+ }
+ }
+
+ /**
+ *
+ * 인자로 받은 String이 null일 경우 "0"로 리턴한다.
+ * @param src null값일 가능성이 있는 String 값.
+ * @return 만약 String이 null 값일 경우 "0"로 바꾼 String 값.
+ *
+ */
+ public static int zeroConvert(Object src) {
+
+ if (src == null || src.equals("null")) {
+ return 0;
+ } else {
+ return Integer.parseInt(((String) src).trim());
+ }
+ }
+
+ /**
+ *
+ * 인자로 받은 String이 null일 경우 ""로 리턴한다.
+ * @param src null값일 가능성이 있는 String 값.
+ * @return 만약 String이 null 값일 경우 ""로 바꾼 String 값.
+ *
+ */
+ public static int zeroConvert(String src) {
+
+ if (src == null || src.equals("null") || "".equals(src) || " ".equals(src)) {
+ return 0;
+ } else {
+ return Integer.parseInt(src.trim());
+ }
+ }
+
+ /**
+ * 문자열에서 {@link Character#isWhitespace(char)}에 정의된
+ * 모든 공백문자를 제거한다.
+ *
+ *
+ * StringUtil.removeWhitespace(null) = null
+ * StringUtil.removeWhitespace("") = ""
+ * StringUtil.removeWhitespace("abc") = "abc"
+ * StringUtil.removeWhitespace(" ab c ") = "abc"
+ *
+ *
+ * @param str 공백문자가 제거도어야 할 문자열
+ * @return the 공백문자가 제거된 문자열, null이 입력되면 null이 리턴
+ */
+ public static String removeWhitespace(String str) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ int sz = str.length();
+ char[] chs = new char[sz];
+ int count = 0;
+ for (int i = 0; i < sz; i++) {
+ if (!Character.isWhitespace(str.charAt(i))) {
+ chs[count++] = str.charAt(i);
+ }
+ }
+ if (count == sz) {
+ return str;
+ }
+
+ return new String(chs, 0, count);
+ }
+
+ /**
+ * Html 코드가 들어간 문서를 표시할때 태그에 손상없이 보이기 위한 메서드
+ *
+ * @param strString
+ * @return HTML 태그를 치환한 문자열
+ */
+ public static String checkHtmlView(String strString) {
+ String strNew = "";
+
+ StringBuffer strTxt = new StringBuffer("");
+
+ char chrBuff;
+ int len = strString.length();
+
+ for (int i = 0; i < len; i++) {
+ chrBuff = (char) strString.charAt(i);
+
+ switch (chrBuff) {
+ case '<':
+ strTxt.append("<");
+ break;
+ case '>':
+ strTxt.append(">");
+ break;
+ case '"':
+ strTxt.append(""");
+ break;
+ case 10:
+ strTxt.append("
");
+ break;
+ case ' ':
+ strTxt.append(" ");
+ break;
+ //case '&' :
+ //strTxt.append("&");
+ //break;
+ default:
+ strTxt.append(chrBuff);
+ }
+ }
+
+ strNew = strTxt.toString();
+
+ return strNew;
+ }
+
+ /**
+ * 문자열을 지정한 분리자에 의해 배열로 리턴하는 메서드.
+ * @param source 원본 문자열
+ * @param separator 분리자
+ * @return result 분리자로 나뉘어진 문자열 배열
+ */
+ public static String[] split(String source, String separator) throws NullPointerException {
+ String[] returnVal = null;
+ int cnt = 1;
+
+ int index = source.indexOf(separator);
+ int index0 = 0;
+ while (index >= 0) {
+ cnt++;
+ index = source.indexOf(separator, index + 1);
+ }
+ returnVal = new String[cnt];
+ cnt = 0;
+ index = source.indexOf(separator);
+ while (index >= 0) {
+ returnVal[cnt] = source.substring(index0, index);
+ index0 = index + 1;
+ index = source.indexOf(separator, index + 1);
+ cnt++;
+ }
+ returnVal[cnt] = source.substring(index0);
+
+ return returnVal;
+ }
+
+ /**
+ * {@link String#toLowerCase()}를 이용하여 소문자로 변환한다.
+ *
+ *
+ * StringUtil.lowerCase(null) = null
+ * StringUtil.lowerCase("") = ""
+ * StringUtil.lowerCase("aBc") = "abc"
+ *
+ *
+ * @param str 소문자로 변환되어야 할 문자열
+ * @return 소문자로 변환된 문자열, null이 입력되면 null 리턴
+ */
+ public static String lowerCase(String str) {
+ if (str == null) {
+ return null;
+ }
+
+ return str.toLowerCase();
+ }
+
+ /**
+ * {@link String#toUpperCase()}를 이용하여 대문자로 변환한다.
+ *
+ *
+ * StringUtil.upperCase(null) = null
+ * StringUtil.upperCase("") = ""
+ * StringUtil.upperCase("aBc") = "ABC"
+ *
+ *
+ * @param str 대문자로 변환되어야 할 문자열
+ * @return 대문자로 변환된 문자열, null이 입력되면 null 리턴
+ */
+ public static String upperCase(String str) {
+ if (str == null) {
+ return null;
+ }
+
+ return str.toUpperCase();
+ }
+
+ /**
+ * 입력된 String의 앞쪽에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.
+ *
+ *
+ * StringUtil.stripStart(null, *) = null
+ * StringUtil.stripStart("", *) = ""
+ * StringUtil.stripStart("abc", "") = "abc"
+ * StringUtil.stripStart("abc", null) = "abc"
+ * StringUtil.stripStart(" abc", null) = "abc"
+ * StringUtil.stripStart("abc ", null) = "abc "
+ * StringUtil.stripStart(" abc ", null) = "abc "
+ * StringUtil.stripStart("yxabc ", "xyz") = "abc "
+ *
+ *
+ * @param str 지정된 문자가 제거되어야 할 문자열
+ * @param stripChars 제거대상 문자열
+ * @return 지정된 문자가 제거된 문자열, null이 입력되면 null 리턴
+ */
+ public static String stripStart(String str, String stripChars) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return str;
+ }
+ int start = 0;
+ if (stripChars == null) {
+ while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
+ start++;
+ }
+ } else if (stripChars.length() == 0) {
+ return str;
+ } else {
+ while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
+ start++;
+ }
+ }
+
+ return str.substring(start);
+ }
+
+ /**
+ * 입력된 String의 뒤쪽에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.
+ *
+ *
+ * StringUtil.stripEnd(null, *) = null
+ * StringUtil.stripEnd("", *) = ""
+ * StringUtil.stripEnd("abc", "") = "abc"
+ * StringUtil.stripEnd("abc", null) = "abc"
+ * StringUtil.stripEnd(" abc", null) = " abc"
+ * StringUtil.stripEnd("abc ", null) = "abc"
+ * StringUtil.stripEnd(" abc ", null) = " abc"
+ * StringUtil.stripEnd(" abcyx", "xyz") = " abc"
+ *
+ *
+ * @param str 지정된 문자가 제거되어야 할 문자열
+ * @param stripChars 제거대상 문자열
+ * @return 지정된 문자가 제거된 문자열, null이 입력되면 null 리턴
+ */
+ public static String stripEnd(String str, String stripChars) {
+ int end;
+ if (str == null || (end = str.length()) == 0) {
+ return str;
+ }
+
+ if (stripChars == null) {
+ while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
+ end--;
+ }
+ } else if (stripChars.length() == 0) {
+ return str;
+ } else {
+ while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
+ end--;
+ }
+ }
+
+ return str.substring(0, end);
+ }
+
+ /**
+ * 입력된 String의 앞, 뒤에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.
+ *
+ *
+ * StringUtil.strip(null, *) = null
+ * StringUtil.strip("", *) = ""
+ * StringUtil.strip("abc", null) = "abc"
+ * StringUtil.strip(" abc", null) = "abc"
+ * StringUtil.strip("abc ", null) = "abc"
+ * StringUtil.strip(" abc ", null) = "abc"
+ * StringUtil.strip(" abcyx", "xyz") = " abc"
+ *
+ *
+ * @param str 지정된 문자가 제거되어야 할 문자열
+ * @param stripChars 제거대상 문자열
+ * @return 지정된 문자가 제거된 문자열, null이 입력되면 null 리턴
+ */
+ public static String strip(String str, String stripChars) {
+ if (isEmpty(str)) {
+ return str;
+ }
+
+ String srcStr = str;
+ srcStr = stripStart(srcStr, stripChars);
+
+ return stripEnd(srcStr, stripChars);
+ }
+
+ /**
+ * 문자열을 지정한 분리자에 의해 지정된 길이의 배열로 리턴하는 메서드.
+ * @param source 원본 문자열
+ * @param separator 분리자
+ * @param arraylength 배열 길이
+ * @return 분리자로 나뉘어진 문자열 배열
+ */
+ public static String[] split(String source, String separator, int arraylength) throws NullPointerException {
+ String[] returnVal = new String[arraylength];
+ int cnt = 0;
+ int index0 = 0;
+ int index = source.indexOf(separator);
+ while (index >= 0 && cnt < (arraylength - 1)) {
+ returnVal[cnt] = source.substring(index0, index);
+ index0 = index + 1;
+ index = source.indexOf(separator, index + 1);
+ cnt++;
+ }
+ returnVal[cnt] = source.substring(index0);
+ if (cnt < (arraylength - 1)) {
+ for (int i = cnt + 1; i < arraylength; i++) {
+ returnVal[i] = "";
+ }
+ }
+
+ return returnVal;
+ }
+
+ /**
+ * 문자열 A에서 Z사이의 랜덤 문자열을 구하는 기능을 제공 시작문자열과 종료문자열 사이의 랜덤 문자열을 구하는 기능
+ *
+ * @param startChr
+ * - 첫 문자
+ * @param endChr
+ * - 마지막문자
+ * @return 랜덤문자
+ * @exception MyException
+ * @see
+ */
+ public static String getRandomStr(char startChr, char endChr) {
+
+ int randomInt;
+ String randomStr = null;
+
+ // 시작문자 및 종료문자를 아스키숫자로 변환한다.
+ int startInt = Integer.valueOf(startChr);
+ int endInt = Integer.valueOf(endChr);
+
+ // 시작문자열이 종료문자열보가 클경우
+ if (startInt > endInt) {
+ throw new IllegalArgumentException("Start String: " + startChr + " End String: " + endChr);
+ }
+
+ // 랜덤 객체 생성
+ SecureRandom rnd = new SecureRandom();
+
+ do {
+ // 시작문자 및 종료문자 중에서 랜덤 숫자를 발생시킨다.
+ randomInt = rnd.nextInt(endInt + 1);
+ } while (randomInt < startInt); // 입력받은 문자 'A'(65)보다 작으면 다시 랜덤 숫자 발생.
+
+ // 랜덤 숫자를 문자로 변환 후 스트링으로 다시 변환
+ randomStr = (char) randomInt + "";
+
+ // 랜덤문자열를 리턴
+ return randomStr;
+ }
+
+ /**
+ * 문자열을 다양한 문자셋(EUC-KR[KSC5601],UTF-8..)을 사용하여 인코딩하는 기능 역으로 디코딩하여 원래의 문자열을
+ * 복원하는 기능을 제공함 String temp = new String(문자열.getBytes("바꾸기전 인코딩"),"바꿀 인코딩");
+ * String temp = new String(문자열.getBytes("8859_1"),"KSC5601"); => UTF-8 에서
+ * EUC-KR
+ *
+ * @param srcString
+ * - 문자열
+ * @param srcCharsetNm
+ * - 원래 CharsetNm
+ * @param charsetNm
+ * - CharsetNm
+ * @return 인(디)코딩 문자열
+ * @exception MyException
+ * @see
+ */
+ public static String getEncdDcd(String srcString, String srcCharsetNm, String cnvrCharsetNm) {
+
+ String rtnStr = null;
+
+ if (srcString == null)
+ return null;
+
+ try {
+ rtnStr = new String(srcString.getBytes(srcCharsetNm), cnvrCharsetNm);
+ } catch (UnsupportedEncodingException e) {
+ rtnStr = null;
+ }
+
+ return rtnStr;
+ }
+
+ /**
+ * 특수문자를 웹 브라우저에서 정상적으로 보이기 위해 특수문자를 처리('<' -> & lT)하는 기능이다
+ * @param srcString - '<'
+ * @return 변환문자열('<' -> "<"
+ * @exception MyException
+ * @see
+ */
+ public static String getSpclStrCnvr(String srcString) {
+
+ String rtnStr = null;
+
+ try {
+ StringBuffer strTxt = new StringBuffer("");
+
+ char chrBuff;
+ int len = srcString.length();
+
+ for (int i = 0; i < len; i++) {
+ chrBuff = (char) srcString.charAt(i);
+
+ switch (chrBuff) {
+ case '<':
+ strTxt.append("<");
+ break;
+ case '>':
+ strTxt.append(">");
+ break;
+ case '&':
+ strTxt.append("&");
+ break;
+ default:
+ strTxt.append(chrBuff);
+ }
+ }
+
+ rtnStr = strTxt.toString();
+
+ } catch (Exception e) {
+ LOGGER.debug("{}", e);
+ }
+
+ return rtnStr;
+ }
+
+ /**
+ * 응용어플리케이션에서 고유값을 사용하기 위해 시스템에서17자리의TIMESTAMP값을 구하는 기능
+ *
+ * @param
+ * @return Timestamp 값
+ * @exception MyException
+ * @see
+ */
+ public static String getTimeStamp() {
+
+ String rtnStr = null;
+
+ // 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
+ String pattern = "yyyyMMddhhmmssSSS";
+
+ SimpleDateFormat sdfCurrent = new SimpleDateFormat(pattern, Locale.KOREA);
+ Timestamp ts = new Timestamp(System.currentTimeMillis());
+
+ rtnStr = sdfCurrent.format(ts.getTime());
+
+ return rtnStr;
+ }
+
+ /**
+ * html의 특수문자를 표현하기 위해
+ *
+ * @param srcString
+ * @return String
+ * @exception Exception
+ * @see
+ */
+ public static String getHtmlStrCnvr(String srcString) {
+
+ String tmpString = srcString;
+
+ tmpString = tmpString.replaceAll("<", "<");
+ tmpString = tmpString.replaceAll(">", ">");
+ tmpString = tmpString.replaceAll("&", "&");
+ tmpString = tmpString.replaceAll(" ", " ");
+ tmpString = tmpString.replaceAll("'", "\'");
+ tmpString = tmpString.replaceAll(""", "\"");
+
+ return tmpString;
+
+ }
+
+ /**
+ * 날짜 형식의 문자열 내부에 마이너스 character(-)를 추가한다.
+ *
+ *
+ * StringUtil.addMinusChar("20100901") = "2010-09-01"
+ *
+ *
+ * @param date 입력받는 문자열
+ * @return " - "가 추가된 입력문자열
+ */
+ public static String addMinusChar(String date) {
+ if (date.length() == 8)
+ return date.substring(0, 4).concat("-").concat(date.substring(4, 6)).concat("-").concat(date.substring(6, 8));
+ else
+ return "";
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/egov/util/EgovWebUtil.java b/src/main/java/kcg/imis/cmmn/egov/util/EgovWebUtil.java
new file mode 100644
index 0000000..c521fc3
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/util/EgovWebUtil.java
@@ -0,0 +1,111 @@
+package kcg.imis.cmmn.egov.util;
+
+import java.util.regex.Pattern;
+
+/**
+ * 교차접속 스크립트 공격 취약성 방지(파라미터 문자열 교체)
+ *
+ *
+ * << 개정이력(Modification Information) >>
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2011.10.10 한성곤 최초 생성
+ *
+ *
+ */
+
+public class EgovWebUtil {
+ public static String clearXSSMinimum(String value) {
+ if (value == null || value.trim().equals("")) {
+ return "";
+ }
+
+ String returnValue = value;
+
+ returnValue = returnValue.replaceAll("&", "&");
+ returnValue = returnValue.replaceAll("<", "<");
+ returnValue = returnValue.replaceAll(">", ">");
+ returnValue = returnValue.replaceAll("\"", """);
+ returnValue = returnValue.replaceAll("\'", "'");
+ returnValue = returnValue.replaceAll("[.]", ".");
+ returnValue = returnValue.replaceAll("%2E", ".");
+ returnValue = returnValue.replaceAll("%2F", "/");
+ return returnValue;
+ }
+
+ public static String clearXSSMaximum(String value) {
+ String returnValue = value;
+ returnValue = clearXSSMinimum(returnValue);
+
+ returnValue = returnValue.replaceAll("%00", null);
+
+ returnValue = returnValue.replaceAll("%", "%");
+
+ // \\. => .
+
+ returnValue = returnValue.replaceAll("\\.\\./", ""); // ../
+ returnValue = returnValue.replaceAll("\\.\\.\\\\", ""); // ..\
+ returnValue = returnValue.replaceAll("\\./", ""); // ./
+ returnValue = returnValue.replaceAll("%2F", "");
+
+ return returnValue;
+ }
+
+ public static String filePathBlackList(String value) {
+ String returnValue = value;
+ if (returnValue == null || returnValue.trim().equals("")) {
+ return "";
+ }
+
+ returnValue = returnValue.replaceAll("\\.\\./", ""); // ../
+ returnValue = returnValue.replaceAll("\\.\\.\\\\", ""); // ..\
+ returnValue = returnValue.replaceAll("\\.\\.", ""); // ..
+
+ return returnValue;
+ }
+
+ /**
+ * 행안부 보안취약점 점검 조치 방안.
+ *
+ * @param value
+ * @return
+ */
+ public static String filePathReplaceAll(String value) {
+ String returnValue = value;
+ if (returnValue == null || returnValue.trim().equals("")) {
+ return "";
+ }
+
+ returnValue = returnValue.replaceAll("/", "");
+ // Findbugs 수정 : replaceAll은 첫 번째 인자값을 정규식으로 취급하기때문에 역슬래쉬 1개를 표현하기 위해 4개를 입력해야 한다.
+ returnValue = returnValue.replaceAll("\\\\", "");
+ returnValue = returnValue.replaceAll("\\.\\.", ""); // ..
+ returnValue = returnValue.replaceAll("&", "");
+
+ return returnValue;
+ }
+
+ public static String filePathWhiteList(String value) {
+ return value;
+ }
+
+ public static boolean isIPAddress(String str) {
+ Pattern ipPattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
+
+ return ipPattern.matcher(str).matches();
+ }
+
+ public static String removeCRLF(String parameter) {
+ return parameter.replaceAll("\r", "").replaceAll("\n", "");
+ }
+
+ public static String removeSQLInjectionRisk(String parameter) {
+ return parameter.replaceAll("\\p{Space}", "").replaceAll("\\*", "").replaceAll("%", "").replaceAll(";", "").replaceAll("-", "").replaceAll("\\+", "").replaceAll(",", "");
+ }
+
+ public static String removeOSCmdRisk(String parameter) {
+ return parameter.replaceAll("\\p{Space}", "").replaceAll("\\*", "").replaceAll("[|]", "").replaceAll(";", "");
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/kcg/imis/cmmn/egov/vo/FileVO.java b/src/main/java/kcg/imis/cmmn/egov/vo/FileVO.java
new file mode 100644
index 0000000..890f6c7
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/egov/vo/FileVO.java
@@ -0,0 +1,241 @@
+package kcg.imis.cmmn.egov.vo;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/**
+ * @Class Name : FileVO.java
+ * @Description : 파일정보 처리를 위한 VO 클래스
+ * @Modification Information
+ *
+ * 수정일 수정자 수정내용 ------- ------- ------------------- 2009. 3. 25.
+ * 이삼섭
+ *
+ * @author 공통 서비스 개발팀 이삼섭
+ * @since 2009. 3. 25.
+ * @version
+ * @see
+ *
+ */
+public class FileVO implements Serializable {
+
+ /**
+ * serialVersion UID
+ */
+ private static final long serialVersionUID = -287950405903719128L;
+ /**
+ * 첨부파일 아이디
+ */
+ public String atchFileId = "";
+ /**
+ * 생성일자
+ */
+ public String creatDt = "";
+ /**
+ * 파일내용
+ */
+ public String fileCn = "";
+ /**
+ * 파일확장자
+ */
+ public String fileExtsn = "";
+ /**
+ * 파일크기
+ */
+ public String fileMg = "";
+ /**
+ * 파일연번
+ */
+ public String fileSn = "";
+ /**
+ * 파일저장경로
+ */
+ public String fileStreCours = "";
+ /**
+ * 원파일명
+ */
+ public String orignlFileNm = "";
+ /**
+ * 저장파일명
+ */
+ public String streFileNm = "";
+
+ /**
+ * atchFileId attribute를 리턴한다.
+ *
+ * @return the atchFileId
+ */
+ public String getAtchFileId() {
+ return atchFileId;
+ }
+
+ /**
+ * atchFileId attribute 값을 설정한다.
+ *
+ * @param atchFileId
+ * the atchFileId to set
+ */
+ public void setAtchFileId(String atchFileId) {
+ this.atchFileId = atchFileId;
+ }
+
+ /**
+ * creatDt attribute를 리턴한다.
+ *
+ * @return the creatDt
+ */
+ public String getCreatDt() {
+ return creatDt;
+ }
+
+ /**
+ * creatDt attribute 값을 설정한다.
+ *
+ * @param creatDt
+ * the creatDt to set
+ */
+ public void setCreatDt(String creatDt) {
+ this.creatDt = creatDt;
+ }
+
+ /**
+ * fileCn attribute를 리턴한다.
+ *
+ * @return the fileCn
+ */
+ public String getFileCn() {
+ return fileCn;
+ }
+
+ /**
+ * fileCn attribute 값을 설정한다.
+ *
+ * @param fileCn
+ * the fileCn to set
+ */
+ public void setFileCn(String fileCn) {
+ this.fileCn = fileCn;
+ }
+
+ /**
+ * fileExtsn attribute를 리턴한다.
+ *
+ * @return the fileExtsn
+ */
+ public String getFileExtsn() {
+ return fileExtsn;
+ }
+
+ /**
+ * fileExtsn attribute 값을 설정한다.
+ *
+ * @param fileExtsn
+ * the fileExtsn to set
+ */
+ public void setFileExtsn(String fileExtsn) {
+ this.fileExtsn = fileExtsn;
+ }
+
+ /**
+ * fileMg attribute를 리턴한다.
+ *
+ * @return the fileMg
+ */
+ public String getFileMg() {
+ return fileMg;
+ }
+
+ /**
+ * fileMg attribute 값을 설정한다.
+ *
+ * @param fileMg
+ * the fileMg to set
+ */
+ public void setFileMg(String fileMg) {
+ this.fileMg = fileMg;
+ }
+
+ /**
+ * fileSn attribute를 리턴한다.
+ *
+ * @return the fileSn
+ */
+ public String getFileSn() {
+ return fileSn;
+ }
+
+ /**
+ * fileSn attribute 값을 설정한다.
+ *
+ * @param fileSn
+ * the fileSn to set
+ */
+ public void setFileSn(String fileSn) {
+ this.fileSn = fileSn;
+ }
+
+ /**
+ * fileStreCours attribute를 리턴한다.
+ *
+ * @return the fileStreCours
+ */
+ public String getFileStreCours() {
+ return fileStreCours;
+ }
+
+ /**
+ * fileStreCours attribute 값을 설정한다.
+ *
+ * @param fileStreCours
+ * the fileStreCours to set
+ */
+ public void setFileStreCours(String fileStreCours) {
+ this.fileStreCours = fileStreCours;
+ }
+
+ /**
+ * orignlFileNm attribute를 리턴한다.
+ *
+ * @return the orignlFileNm
+ */
+ public String getOrignlFileNm() {
+ return orignlFileNm;
+ }
+
+ /**
+ * orignlFileNm attribute 값을 설정한다.
+ *
+ * @param orignlFileNm
+ * the orignlFileNm to set
+ */
+ public void setOrignlFileNm(String orignlFileNm) {
+ this.orignlFileNm = orignlFileNm;
+ }
+
+ /**
+ * streFileNm attribute를 리턴한다.
+ *
+ * @return the streFileNm
+ */
+ public String getStreFileNm() {
+ return streFileNm;
+ }
+
+ /**
+ * streFileNm attribute 값을 설정한다.
+ *
+ * @param streFileNm
+ * the streFileNm to set
+ */
+ public void setStreFileNm(String streFileNm) {
+ this.streFileNm = streFileNm;
+ }
+
+ @Override
+ public String toString() {
+ return "FileVO [atchFileId=" + atchFileId + ", creatDt=" + creatDt + ", fileCn=" + fileCn + ", fileExtsn=" + fileExtsn + ", fileMg=" + fileMg + ", fileSn=" + fileSn + ", fileStreCours="
+ + fileStreCours + ", orignlFileNm=" + orignlFileNm + ", streFileNm=" + streFileNm + "]";
+ }
+
+}
diff --git a/src/main/java/kcg/imis/cmmn/excel/AbstractExcelExport.java b/src/main/java/kcg/imis/cmmn/excel/AbstractExcelExport.java
new file mode 100644
index 0000000..4414bf0
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/excel/AbstractExcelExport.java
@@ -0,0 +1,65 @@
+/**
+ * AbstractExcelGenerator.java
+ * @author 임새미
+ * @since 2016. 10. 14.
+ *
+ * 수정일 수정자 수정내용
+ * ------------- -------- ---------------------------
+ * 2016. 10. 14. 임새미 최초생성
+ *
+ */
+package kcg.imis.cmmn.excel;
+
+import java.util.Map;
+
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * @FileName : AbstractExcelExport.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+public abstract class AbstractExcelExport implements ExcelExport {
+
+ /* 기본적으로 3번 라인이 시작라인 */
+ protected int firstRow = 2;
+ protected String template = null;
+
+ /* 파라미터 맵 */
+ protected Map document = null;
+
+
+ /**
+ * 엑셀을 생성한다.
+ *
+ * @param document 엑셀 파일을 생성하기 위한 데이터셋
+ * @return Workbook 객체
+ */
+ public abstract XSSFWorkbook makeExcel(XSSFWorkbook wb);
+
+ /**
+ * 타이틀을 설정한다.
+ *
+ * @param 파라미터 파라미터설명
+ */
+ protected void setTitleRow(XSSFSheet sheet, XSSFCellStyle style, String title) {
+
+ XSSFRow row = sheet.createRow(0);
+ XSSFCell cell = row.createCell(0);
+
+ cell.setCellValue(title);
+ if (style != null) {
+
+ }
+ cell.setCellStyle(style);
+
+ }
+
+}
diff --git a/src/main/java/kcg/imis/cmmn/excel/ExcelExport.java b/src/main/java/kcg/imis/cmmn/excel/ExcelExport.java
new file mode 100644
index 0000000..f15439e
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/excel/ExcelExport.java
@@ -0,0 +1,15 @@
+package kcg.imis.cmmn.excel;
+
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * @FileName : ExcelExport.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+public interface ExcelExport {
+ public abstract XSSFWorkbook makeExcel(XSSFWorkbook wb);
+}
diff --git a/src/main/java/kcg/imis/cmmn/excel/ExcelExporter.java b/src/main/java/kcg/imis/cmmn/excel/ExcelExporter.java
new file mode 100644
index 0000000..48acf12
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/excel/ExcelExporter.java
@@ -0,0 +1,132 @@
+package kcg.imis.cmmn.excel;
+
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * 엑셀 변환 클래스.
+ *
+ * @author kimnomin
+ *
+ * @param 데이터 VO
+ */
+public class ExcelExporter extends AbstractExcelExport {
+
+ /**
+ * 헤더 맵 객체.
+ * <해당 VO의 멤버변수명, 값> 형태
+ * ex) {title: 제목}
+ *
+ * 해당 맵 객체에 입력된 순서대로 엑셀이 생성된다.
+ *
+ * !! 주의 !! 해당 맵 객체의 key가 데이터 VO의 멤버변수명과 동일해야 한다.
+ */
+ private LinkedHashMap headers;
+ /**
+ * 데이터 VO List.
+ */
+ private List list;
+ /**
+ * 엑셀 내 표현될 제목.
+ */
+ private String title;
+
+ /**
+ * 생성자.
+ *
+ * @param headers 헤더 맵 객체.
+ * @param list 데이터 VO List.
+ * @param title 엑셀 내 표현될 제목.
+ */
+ public ExcelExporter(final LinkedHashMap headers, final List list,
+ final String title) {
+ super();
+ this.headers = headers;
+ this.list = list;
+ this.title = title;
+ }
+
+ @Override
+ public XSSFWorkbook makeExcel(final XSSFWorkbook wb) {
+ if (list.size() <= 0 || headers.size() <= 0) {
+ return null;
+ }
+
+ XSSFSheet sheet = null;
+ XSSFRow row = null;
+ XSSFCell cell = null;
+
+ ExcelStyle style = new ExcelStyle(wb);
+ sheet = wb.createSheet(title);
+ setTitleRow(sheet, style.titleStyle, title);
+
+ Set keySet = headers.keySet();
+
+ // 헤더
+ int loopIdx = 0;
+ row = sheet.createRow(firstRow);
+ cell = row.createCell(loopIdx);
+ cell.setCellValue("번호");
+ cell.setCellStyle(style.headerStyle);
+ loopIdx++;
+ for (String key : keySet) {
+ cell = row.createCell(loopIdx);
+ cell.setCellValue(headers.get(key));
+ cell.setCellStyle(style.headerStyle);
+ loopIdx++;
+ }
+
+ // 값
+ for (int i = 0; i < list.size(); i++) {
+ T t = list.get(i);
+ row = sheet.createRow(firstRow + 1 + i);
+
+ loopIdx = 0;
+ cell = row.createCell(loopIdx);
+ cell.setCellValue(i + 1);
+ cell.setCellStyle(style.normalTextStyle);
+ loopIdx++;
+ for (String key : keySet) {
+ String value = "";
+
+ try {
+ if (t instanceof Map, ?>) {
+ Object o = ((Map, ?>) t).get(key);
+ if (o instanceof String) {
+ value = o.toString();
+ } else if (o instanceof Integer || o instanceof Double) {
+ value = String.valueOf(o);
+ } else if (o instanceof BigDecimal) {
+ value = ((BigDecimal) o).toString();
+ }
+ } else {
+ Field f = t.getClass().getDeclaredField(key);
+ f.setAccessible(true);
+ Object val = f.get(t);
+ if (val != null) {
+ value = val.toString();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ cell = row.createCell(loopIdx);
+ cell.setCellValue(value);
+ cell.setCellStyle(style.normalTextStyle);
+ loopIdx++;
+ }
+ }
+
+ return wb;
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/excel/ExcelStyle.java b/src/main/java/kcg/imis/cmmn/excel/ExcelStyle.java
new file mode 100644
index 0000000..71375d4
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/excel/ExcelStyle.java
@@ -0,0 +1,126 @@
+package kcg.imis.cmmn.excel;
+
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * @FileName : ExcelStyle.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+public class ExcelStyle {
+
+ private XSSFFont normalFont;
+ private XSSFFont boldFont;
+ private XSSFFont titleFont;
+
+ private XSSFColor yellowColor = new XSSFColor(new java.awt.Color(255, 255, 238));
+ private XSSFColor grayColor = new XSSFColor(new java.awt.Color(238, 238, 238));
+ private XSSFColor cyanColor = new XSSFColor(new java.awt.Color(238, 255, 255));
+
+ private DataFormat numericFormat;
+
+ public XSSFCellStyle titleStyle;
+ public XSSFCellStyle headerStyle;
+ public XSSFCellStyle firstRowTextStyle;
+ public XSSFCellStyle firstRowNumericStyle;
+ public XSSFCellStyle normalTextStyle;
+ public XSSFCellStyle normalLeftBoldTextStyle;
+ public XSSFCellStyle normalNumericStyle;
+
+
+ public ExcelStyle(XSSFWorkbook wb) {
+ defindeStyle(wb);
+ }
+
+ private void defindeStyle(XSSFWorkbook wb) {
+
+ numericFormat = wb.createDataFormat();
+
+ titleStyle = (XSSFCellStyle) wb.createCellStyle();
+ headerStyle = (XSSFCellStyle) wb.createCellStyle();
+ firstRowTextStyle = (XSSFCellStyle) wb.createCellStyle();
+ firstRowNumericStyle = (XSSFCellStyle) wb.createCellStyle();
+ normalTextStyle = (XSSFCellStyle) wb.createCellStyle();
+ normalLeftBoldTextStyle = (XSSFCellStyle) wb.createCellStyle();
+ normalNumericStyle = (XSSFCellStyle) wb.createCellStyle();
+
+ normalFont = (XSSFFont) wb.createFont();
+ normalFont.setFontName("돋음");
+ normalFont.setFontHeightInPoints((short) 9);
+ normalFont.setBoldweight(Font.BOLDWEIGHT_NORMAL);
+
+ boldFont = (XSSFFont) wb.createFont();
+ boldFont.setFontName("돋음");
+ boldFont.setFontHeightInPoints((short) 9);
+ boldFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+
+ titleFont = (XSSFFont) wb.createFont();
+ titleFont.setFontName("돋음");
+ titleFont.setFontHeightInPoints((short) 12);
+ titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+
+ titleStyle.setFont(titleFont);
+ titleStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+
+ headerStyle.setAlignment(CellStyle.ALIGN_CENTER);
+ headerStyle.setFont(boldFont);
+ headerStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+ headerStyle.setBorderTop(BorderStyle.HAIR);
+ headerStyle.setBorderLeft(BorderStyle.HAIR);
+ headerStyle.setBorderRight(BorderStyle.HAIR);
+ headerStyle.setBorderBottom(BorderStyle.HAIR);
+ headerStyle.setFillForegroundColor(grayColor);
+ headerStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
+
+ firstRowTextStyle.setAlignment(CellStyle.ALIGN_CENTER);
+ firstRowTextStyle.setFont(normalFont);
+ firstRowTextStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+ firstRowTextStyle.setBorderTop(BorderStyle.HAIR);
+ firstRowTextStyle.setBorderLeft(BorderStyle.HAIR);
+ firstRowTextStyle.setBorderRight(BorderStyle.HAIR);
+ firstRowTextStyle.setBorderBottom(BorderStyle.HAIR);
+ firstRowTextStyle.setFillForegroundColor(yellowColor);
+ firstRowTextStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
+
+ firstRowNumericStyle.setAlignment(CellStyle.ALIGN_CENTER);
+ firstRowNumericStyle.setFont(normalFont);
+ firstRowNumericStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+ firstRowNumericStyle.setBorderTop(BorderStyle.HAIR);
+ firstRowNumericStyle.setBorderLeft(BorderStyle.HAIR);
+ firstRowNumericStyle.setBorderRight(BorderStyle.HAIR);
+ firstRowNumericStyle.setBorderBottom(BorderStyle.HAIR);
+ firstRowNumericStyle.setFillForegroundColor(yellowColor);
+ firstRowNumericStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
+ firstRowNumericStyle.setDataFormat(numericFormat.getFormat("#,###"));
+
+ normalTextStyle.setAlignment(CellStyle.ALIGN_CENTER);
+ normalTextStyle.setFont(normalFont);
+ normalTextStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+ normalTextStyle.setBorderTop(BorderStyle.HAIR);
+ normalTextStyle.setBorderLeft(BorderStyle.HAIR);
+ normalTextStyle.setBorderRight(BorderStyle.HAIR);
+ normalTextStyle.setBorderBottom(BorderStyle.HAIR);
+
+
+ normalNumericStyle.setAlignment(CellStyle.ALIGN_CENTER);
+ normalNumericStyle.setFont(normalFont);
+ normalNumericStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+ normalNumericStyle.setBorderTop(BorderStyle.HAIR);
+ normalNumericStyle.setBorderLeft(BorderStyle.HAIR);
+ normalNumericStyle.setBorderRight(BorderStyle.HAIR);
+ normalNumericStyle.setBorderBottom(BorderStyle.HAIR);
+ normalNumericStyle.setDataFormat(numericFormat.getFormat("#,###"));
+
+ }
+
+}
diff --git a/src/main/java/kcg/imis/cmmn/excel/ExcelView.java b/src/main/java/kcg/imis/cmmn/excel/ExcelView.java
new file mode 100644
index 0000000..0577006
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/excel/ExcelView.java
@@ -0,0 +1,58 @@
+package kcg.imis.cmmn.excel;
+
+import java.net.URLEncoder;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import egovframework.rte.fdl.excel.util.AbstractPOIExcelView;
+
+/**
+ * @FileName : ExcelView.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+public class ExcelView extends AbstractPOIExcelView {
+
+ /**
+ * 엑셀파일을 다운로드한다.
+ *
+ * @param model Model객체
+ * @param model Model객체
+ * @param model Model객체
+ * @param model Model객체
+ */
+ @Override
+ protected void buildExcelDocument(Map model, XSSFWorkbook wb, HttpServletRequest req, HttpServletResponse res) throws Exception {
+
+ if(model.get("filename") != null){
+ String userAgent = req.getHeader("User-Agent");
+ String fileName = (String)model.get("filename");
+ if(userAgent.indexOf("MSIE") > -1){
+ fileName = URLEncoder.encode(fileName, "utf-8");
+ }else{
+ fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1");
+ }
+ model.put("filename", fileName);
+ }
+
+ ExcelExport export = (ExcelExport) model.get("excel");
+ try {
+ export.makeExcel(wb);
+ } catch (Exception e) {
+ e.printStackTrace();
+ XSSFSheet sheet = wb.createSheet("sheet1");
+ XSSFCell cell = getCell(sheet, 0, 0);
+ setText(cell, "Error");
+ }
+
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/file/FileResponser.java b/src/main/java/kcg/imis/cmmn/file/FileResponser.java
new file mode 100644
index 0000000..4a95b0e
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/file/FileResponser.java
@@ -0,0 +1,125 @@
+package kcg.imis.cmmn.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+import javax.activation.MimetypesFileTypeMap;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @FileName : FileResponser.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+public final class FileResponser {
+
+ /**
+ * 생성자.
+ */
+ private FileResponser() {
+
+ }
+
+ /**
+ * 브라우저 구분을 반환한다.
+ *
+ * @param request
+ * HttpServletRequest 객체
+ * @return 브라우저 구분
+ */
+ private static String getBrowser(final HttpServletRequest request) {
+ String header = request.getHeader("User-Agent");
+ if (header.indexOf("MSIE") > -1) {
+ return "MSIE";
+ } else if (header.indexOf("Trident") > -1) { // IE11 문자열 깨짐 방지
+ return "Trident";
+ } else if (header.indexOf("Chrome") > -1) {
+ return "Chrome";
+ } else if (header.indexOf("Opera") > -1) {
+ return "Opera";
+ }
+ return "Firefox";
+ }
+
+ /**
+ * Disposition 지정하기.
+ *
+ * @param filename
+ * 파일명
+ * @param request
+ * HttpServletRequest 객체
+ * @param response
+ * HttpServletResponse 객체
+ * @throws Exception
+ * 기본 예외 처리
+ */
+ private static void setDisposition(final String filename,
+ final HttpServletRequest request, final HttpServletResponse response)
+ throws Exception {
+ String browser = getBrowser(request);
+
+ String dispositionPrefix = "inline; filename=";
+ String encodedFilename = null;
+
+ if (browser.equals("MSIE")) {
+ encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
+ } else if (browser.equals("Trident")) { // IE11 문자열 깨짐 방지
+ encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
+ } else if (browser.equals("Firefox")) {
+ encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
+ } else if (browser.equals("Opera")) {
+ encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
+ } else if (browser.equals("Chrome")) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < filename.length(); i++) {
+ char c = filename.charAt(i);
+ if (c > '~') {
+ sb.append(URLEncoder.encode("" + c, "UTF-8"));
+ } else {
+ sb.append(c);
+ }
+ }
+ encodedFilename = sb.toString();
+ } else {
+ // throw new RuntimeException("Not supported browser");
+ throw new IOException("Not supported browser");
+ }
+
+ response.setHeader("Content-Disposition", dispositionPrefix + encodedFilename);
+
+ if ("Opera".equals(browser)) {
+ response.setContentType("application/octet-stream;charset=UTF-8");
+ }
+ }
+
+ /**
+ * 파일 반환을 위해 Response 객체를 설정한다.
+ *
+ * @param file 파일 객체
+ * @param fileOrgName 실제 파일명
+ * @param request HttpServletRequest 객체
+ * @param response HttpServletResponse 객체
+ */
+ public static void setResponse(final File file,
+ final String fileOrgName,
+ final HttpServletRequest request, final HttpServletResponse response) {
+ if (file == null || request == null || response == null) {
+ return;
+ }
+
+ MimetypesFileTypeMap mimeUtil = new MimetypesFileTypeMap();
+ String mimeType = mimeUtil.getContentType(fileOrgName);
+ response.setContentType(mimeType);
+ response.setContentLength((int) file.length());
+ try {
+ setDisposition(fileOrgName, request, response);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/file/FileUploadUtil.java b/src/main/java/kcg/imis/cmmn/file/FileUploadUtil.java
new file mode 100644
index 0000000..5225be0
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/file/FileUploadUtil.java
@@ -0,0 +1,122 @@
+package kcg.imis.cmmn.file;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.annotation.Resource;
+
+import kcg.imis.cmmn.egov.EgovResourceCloseHelper;
+import kcg.imis.cmmn.egov.file.EgovFileMngUtil;
+import kcg.imis.cmmn.egov.util.EgovStringUtil;
+import kcg.imis.cmmn.egov.util.EgovWebUtil;
+
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import egovframework.rte.fdl.property.EgovPropertyService;
+/**
+ * @FileName : FileUploadUtil.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+@Component("fileUploadUtil")
+public class FileUploadUtil extends EgovFileMngUtil {
+
+ /**
+ * 프로퍼티 서비스.
+ */
+ @Resource(name = "propertiesService")
+ protected EgovPropertyService propertyService;
+
+ /** Buffer size */
+ public static final int BUFFER_SIZE = 8192;
+
+ /**
+ * 파일 분리 문자.
+ */
+ public static final String SEPERATOR = File.separator;
+
+ /**
+ * MultipartFile을 서버에 저장한다.
+ *
+ * @param mFile
+ * 파일 객체
+ * @param path
+ * 파일이 저장될 경로 Global Property명
+ * @return 저장된 파일명
+ * @throws Exception
+ * 기본 예외 처리
+ */
+ public String uploadWithExt(final MultipartFile mFile, String path) throws Exception {
+ String storePathString = "";
+ if ("".equals(path) || path == null) {
+ storePathString = propertyService.getString("Globals.fileStorePath");
+ } else {
+ storePathString = propertyService.getString(path);
+ }
+
+ String tmp = mFile.getOriginalFilename();
+
+ if (tmp.lastIndexOf("\\") >= 0) {
+ tmp = tmp.substring(tmp.lastIndexOf("\\") + 1);
+ }
+
+ //String ext = "." + tmp.substring(tmp.lastIndexOf(".") + 1, tmp.length()).toLowerCase();
+ String ext = FilenameUtils.getExtension(tmp);
+ String saveName = EgovStringUtil.getTimeStamp() + "." + ext;
+ saveName = super.makeNewFileName(storePathString, saveName);
+ //saveName = saveName.substring(0, saveName.length() - 3) + ext;
+
+ if (mFile.getSize() > 0) {
+ InputStream is = null;
+ try {
+ is = mFile.getInputStream();
+ saveFile(is, new File(EgovWebUtil.filePathBlackList(storePathString + saveName)));
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+ return saveName;
+ }
+
+ /**
+ * Stream으로부터 파일을 저장함.
+ * @param is InputStream
+ * @param file File
+ * @throws IOException
+ */
+ private long saveFile(final InputStream is, final File file) throws IOException {
+ // 디렉토리 생성
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+
+ OutputStream os = null;
+ long size = 0L;
+
+ try {
+ os = new FileOutputStream(file);
+
+ int bytesRead = 0;
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ while ((bytesRead = is.read(buffer, 0, BUFFER_SIZE)) != -1) {
+ size += bytesRead;
+ os.write(buffer, 0, bytesRead);
+ }
+ } finally {
+ EgovResourceCloseHelper.close(os);
+ }
+
+ return size;
+ }
+}
diff --git a/src/main/java/kcg/imis/cmmn/json/CustomObjectMapper.java b/src/main/java/kcg/imis/cmmn/json/CustomObjectMapper.java
new file mode 100644
index 0000000..8704e42
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/json/CustomObjectMapper.java
@@ -0,0 +1,27 @@
+/**
+ *
+ */
+package kcg.imis.cmmn.json;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
+
+
+/**
+ * @FileName : CustomObjectMapper.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+public class CustomObjectMapper extends ObjectMapper {
+
+ private static final long serialVersionUID = 1L;
+
+ public CustomObjectMapper() {
+ DefaultSerializerProvider.Impl sp = new DefaultSerializerProvider.Impl();
+ sp.setNullValueSerializer(new NullSerializer());
+ this.setSerializerProvider(sp);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/kcg/imis/cmmn/json/NullSerializer.java b/src/main/java/kcg/imis/cmmn/json/NullSerializer.java
new file mode 100644
index 0000000..85fbb80
--- /dev/null
+++ b/src/main/java/kcg/imis/cmmn/json/NullSerializer.java
@@ -0,0 +1,27 @@
+/**
+ *
+ */
+package kcg.imis.cmmn.json;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+
+/**
+ * @FileName : NullSerializer.java
+ * @Project : 국제해양프로젝트
+ * @Date : 2018. 3. 29.
+ * @작성자 : Moon
+ * @변경이력 :
+ * @프로그램 설명 :
+ */
+public class NullSerializer extends JsonSerializer