fileMap)
+ throws Exception;
+
+ /**
+ * 한 건의 파일을 폴더에서 제거하고 파일 정보를 삭제한다.
+ *
+ * @param fileVO
+ * 제네릭 타입의 File 관련 VO
+ * @return 1-성공, 0-실패
+ * @throws Exception
+ * 기본 예외 처리
+ */
+ int deleteAndRemoveFile(T fileVO) throws Exception;
+
+ /**
+ * fileVO의 parentSeq인 모든 파일을 폴더에서 제거하고 파일 정보를 삭제한다.
+ *
+ * @param fileVO
+ * 제네릭 타입의 File 관련 VO
+ * @return 1-성공, 0-실패
+ * @throws Exception
+ * 기본 예외 처리
+ */
+ int deleteAndRemoveFiles(T fileVO) throws Exception;
+}
diff --git a/src/main/java/kcg/faics/cmmn/bbs/BaseFileVO.java b/src/main/java/kcg/faics/cmmn/bbs/BaseFileVO.java
new file mode 100644
index 0000000..91bcfb0
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/bbs/BaseFileVO.java
@@ -0,0 +1,114 @@
+package kcg.faics.cmmn.bbs;
+
+/**
+ * 게시판형 공용 첨부파일 VO.
+ *
+ * 1. 모든 게시판형 첨부파일은 해당 VO를 상속받아 사용한다.
+ * 2. 필드명이 다른 경우 Data처리 라이브러리(현재 MyBatis)의 Alias 기능을 활용하여 매칭시킨다.
+ *
+ * @author kimnomin
+ *
+ */
+public class BaseFileVO {
+ /**
+ * 파일 번호.
+ */
+ private int seq;
+ /**
+ * 파일 순서 번호.
+ */
+ private int orders;
+ /**
+ * 파일 이름.
+ */
+ private String orgName;
+ /**
+ * 파일 저장 이름.
+ */
+ private String saveName;
+ /**
+ * 게시글 번호.
+ */
+ private int parentSeq;
+
+ /**
+ * 파일 번호를 반환한다.
+ *
+ * @return 파일 번호
+ */
+ public final int getSeq() {
+ return seq;
+ }
+ /**
+ * 파일 번호를 설정한다.
+ *
+ * @param seq 파일 번호
+ */
+ public final void setSeq(final int seq) {
+ this.seq = seq;
+ }
+ /**
+ * 파일 순서 번호를 반환한다.
+ *
+ * @return 파일 순서 번호
+ */
+ public final int getOrders() {
+ return orders;
+ }
+ /**
+ * 파일 순서 번호를 설정한다.
+ *
+ * @param order 파일 순서 번호
+ */
+ public final void setOrders(final int order) {
+ this.orders = order;
+ }
+ /**
+ * 파일 이름을 반환한다.
+ *
+ * @return 파일 이름
+ */
+ public final String getOrgName() {
+ return orgName;
+ }
+ /**
+ * 파일 이름을 설정한다.
+ *
+ * @param orgName 파일 이름
+ */
+ public final void setOrgName(final String orgName) {
+ this.orgName = orgName;
+ }
+ /**
+ * 파일 저장 이름을 반환한다.
+ *
+ * @return 파일 저장 이름
+ */
+ public final String getSaveName() {
+ return saveName;
+ }
+ /**
+ * 파일 저장 이름을 설정한다.
+ *
+ * @param saveName 파일 저장 이름
+ */
+ public final void setSaveName(final String saveName) {
+ this.saveName = saveName;
+ }
+ /**
+ * 게시글 번호를 반환한다.
+ *
+ * @return 게시글 번호
+ */
+ public final int getParentSeq() {
+ return parentSeq;
+ }
+ /**
+ * 게시글 번호를 설정한다.
+ *
+ * @param parentSeq 게시글 번호
+ */
+ public final void setParentSeq(final int parentSeq) {
+ this.parentSeq = parentSeq;
+ }
+}
diff --git a/src/main/java/kcg/faics/cmmn/bbs/BaseSearchVO.java b/src/main/java/kcg/faics/cmmn/bbs/BaseSearchVO.java
new file mode 100644
index 0000000..0141e98
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/bbs/BaseSearchVO.java
@@ -0,0 +1,197 @@
+package kcg.faics.cmmn.bbs;
+
+/**
+ * 게시판형 기능에서 검색조건을 저장하는 부모 Value Object.
+ *
+ * 각 기능에서 검색조건을 지정할때는 해당 VO를 상속받아 사용하는 것을 원칙으로 한다.
+ *
+ * @author kimnomin
+ *
+ */
+public class BaseSearchVO {
+ /**
+ * 현재 페이지.
+ */
+ private int pageIndex = 1;
+
+ /**
+ * 페이지 개수.
+ */
+ private int pageUnit; // properties에서 설정
+
+ /**
+ * 페이지 사이즈.
+ */
+ private int pageSize; // properties에서 설정
+
+ /**
+ * 시작 인덱스.
+ */
+ private int firstIndex = 0;
+
+ /**
+ * 끝 인덱스.
+ */
+ private int lastIndex = 1;
+
+ /**
+ * 페이지별 레코드 개수.
+ */
+ private int recordCountPerPage = 10;
+
+ /**
+ * 검색 키워드.
+ */
+ private String searchKeyword = "";
+ /**
+ * 검색 조건.
+ */
+ private String searchCondition = "";
+
+ /**
+ * 현재 페이지를 반환한다.
+ *
+ * @return 현재 페이지
+ */
+ public final int getPageIndex() {
+ return pageIndex;
+ }
+
+ /**
+ * 현재 페이지를 설정한다.
+ *
+ * @param pageIndex
+ * 현재 페이지
+ */
+ public final void setPageIndex(final int pageIndex) {
+ this.pageIndex = pageIndex;
+ }
+
+ /**
+ * 페이지 개수를 반환한다.
+ *
+ * @return 페이지 개수
+ */
+ public final int getPageUnit() {
+ return pageUnit;
+ }
+
+ /**
+ * 페이지 개수를 설정한다.
+ *
+ * @param pageUnit
+ * 페이지 개수
+ */
+ public final void setPageUnit(final int pageUnit) {
+ this.pageUnit = pageUnit;
+ }
+
+ /**
+ * 페이지 사이즈를 반환한다.
+ *
+ * @return 페이지 사이즈
+ */
+ public final int getPageSize() {
+ return pageSize;
+ }
+
+ /**
+ * 페이지 사이즈를 설정한다.
+ *
+ * @param pageSize
+ * 페이지 사이즈
+ */
+ public final void setPageSize(final int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ /**
+ * 시작 인덱스를 반환한다.
+ *
+ * @return 시작 인덱스
+ */
+ public final int getFirstIndex() {
+ return firstIndex;
+ }
+
+ /**
+ * 시작 인덱스를 설정한다.
+ *
+ * @param firstIndex
+ * 시작 인덱스
+ */
+ public final void setFirstIndex(final int firstIndex) {
+ this.firstIndex = firstIndex;
+ }
+
+ /**
+ * 끝 인덱스를 반환한다.
+ *
+ * @return 끝 인덱스
+ */
+ public final int getLastIndex() {
+ return lastIndex;
+ }
+
+ /**
+ * 끝 인덱스를 설정한다.
+ *
+ * @param lastIndex
+ * 끝 인덱스
+ */
+ public final void setLastIndex(final int lastIndex) {
+ this.lastIndex = lastIndex;
+ }
+
+ /**
+ * 페이지별 레코드 수를 반환한다.
+ *
+ * @return 페이지별 레코드 수
+ */
+ public final int getRecordCountPerPage() {
+ return recordCountPerPage;
+ }
+
+ /**
+ * 페이지별 레코드 수를 설정한다.
+ *
+ * @param recordCountPerPage
+ * 페이지별 레코드 수
+ */
+ public final void setRecordCountPerPage(final int recordCountPerPage) {
+ this.recordCountPerPage = recordCountPerPage;
+ }
+
+ /**
+ * 검색 키워드를 반환한다.
+ *
+ * @return 검색 키워드
+ */
+ public final String getSearchKeyword() {
+ return searchKeyword;
+ }
+
+ /**
+ * 검색 키워드를 설정한다.
+ *
+ * @param searchKeyword
+ * 검색 키워드
+ */
+ public final void setSearchKeyword(final String searchKeyword) {
+ this.searchKeyword = searchKeyword;
+ }
+
+ /**
+ * @return 검색 조건을 반환한다.
+ */
+ public String getSearchCondition() {
+ return searchCondition;
+ }
+
+ /**
+ * @param 검색 조건을 설정한다.
+ */
+ public void setSearchCondition(String searchCondition) {
+ this.searchCondition = searchCondition;
+ }
+}
diff --git a/src/main/java/kcg/faics/cmmn/bbs/PageType.java b/src/main/java/kcg/faics/cmmn/bbs/PageType.java
new file mode 100644
index 0000000..9963a05
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/bbs/PageType.java
@@ -0,0 +1,34 @@
+package kcg.faics.cmmn.bbs;
+
+/**
+ * 페이지 화면 구분.
+ *
+ * @author kimnomin
+ *
+ */
+public enum PageType {
+ /**
+ * 목록화면.
+ */
+ List,
+ /**
+ * 정보조회화면.
+ */
+ View,
+ /**
+ * 입력화면.
+ */
+ Add,
+ /**
+ * 수정화면.
+ */
+ Upd,
+ /**
+ * 삭제화면.
+ */
+ Del,
+ /**
+ * 통계현황화면.
+ */
+ Stats
+}
diff --git a/src/main/java/kcg/faics/cmmn/bbs/package-info.java b/src/main/java/kcg/faics/cmmn/bbs/package-info.java
new file mode 100644
index 0000000..fda7f66
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/bbs/package-info.java
@@ -0,0 +1,8 @@
+/**
+ * 게시판 관련 공용 패키지.
+ */
+/**
+ * @author kimnomin
+ *
+ */
+package kcg.faics.cmmn.bbs;
\ No newline at end of file
diff --git a/src/main/java/kcg/faics/cmmn/ckeditor/CkFilter.java b/src/main/java/kcg/faics/cmmn/ckeditor/CkFilter.java
new file mode 100644
index 0000000..e71794e
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/ckeditor/CkFilter.java
@@ -0,0 +1,104 @@
+/*
+ * CKEditor image upload module for Java.
+ * Copyright guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ *
+ * 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.
+ *
+ * @author guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ */
+package kcg.faics.cmmn.ckeditor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+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;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Filter class
+ * @author guavatak
+ * @since 2014.12.04
+ * @version 1.0
+ * @see
+ *
+ *
+ * << 개정이력(Modification Information) >>
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2014.12.04 표준프레임워크 최초 적용 (패키지 변경 및 소스 정리)
+ *
+ */
+public class CkFilter implements Filter {
+ private static final Log log = LogFactory.getLog(CkFilter.class);
+
+ private static final String IMAGE_BASE_DIR_KEY = "ck.image.dir";
+ private static final String IMAGE_BASE_URL_KEY = "ck.image.url";
+ private static final String IMAGE_ALLOW_TYPE_KEY = "ck.image.type.allow";
+ private static final String IMAGE_SAVE_CLASS_KEY = "ck.image.save.class";
+
+ private CkImageSaver ckImageSaver;
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ String properties = filterConfig.getInitParameter("properties");
+ InputStream inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(properties);
+ Properties props = new Properties();
+ try {
+ props.load(inStream);
+ } catch (IOException e) {
+ log.error(e);
+ }
+
+ String imageBaseDir = (String) props.get(IMAGE_BASE_DIR_KEY);
+ String imageDomain = (String) props.get(IMAGE_BASE_URL_KEY);
+
+ String[] allowFileTypeArr = null;
+ String allowFileType = (String) props.get(IMAGE_ALLOW_TYPE_KEY);
+ if (StringUtils.isNotBlank(allowFileType)) {
+ allowFileTypeArr = StringUtils.split(allowFileType, ",");
+ }
+
+ String saveManagerClass = (String) props.get(IMAGE_SAVE_CLASS_KEY);
+
+ ckImageSaver = new CkImageSaver(imageBaseDir, imageDomain, allowFileTypeArr, saveManagerClass);
+
+ }
+
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest) req;
+ HttpServletResponse response = (HttpServletResponse) res;
+
+ if (request.getContentType() == null || request.getContentType().indexOf("multipart") == -1) {
+ // contentType 이 multipart 가 아니라면 스킵한다.
+ chain.doFilter(request, response);
+ } else {
+ ckImageSaver.saveAndReturnUrlToClient(request, response);
+
+ }
+ }
+
+ public void destroy() {
+ // no-op
+ }
+}
diff --git a/src/main/java/kcg/faics/cmmn/ckeditor/CkImageSaver.java b/src/main/java/kcg/faics/cmmn/ckeditor/CkImageSaver.java
new file mode 100644
index 0000000..f7ad4cd
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/ckeditor/CkImageSaver.java
@@ -0,0 +1,158 @@
+/*
+ * CKEditor image upload module for Java.
+ * Copyright guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ *
+ * 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.
+ *
+ * @author guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ */
+package kcg.faics.cmmn.ckeditor;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartRequest;
+
+/**
+ * Created by guava on 1/20/14.
+ * 이미지 저장 처리 클래스
+ * @author guavatak
+ * @since 2014.12.04
+ * @version 1.0
+ * @see
+ *
+ *
+ * << 개정이력(Modification Information) >>
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2014.12.04 표준프레임워크 최초 적용 (패키지 변경 및 소스 정리)
+ *
+ */
+public class CkImageSaver {
+ private static final Log log = LogFactory.getLog(CkFilter.class);
+
+ private static final String FUNC_NO = "CKEditorFuncNum";
+
+ private String imageBaseDir;
+ private String imageDomain;
+ private String[] allowFileTypeArr;
+
+ private FileSaveManager fileSaveManager;
+
+ public CkImageSaver(String imageBaseDir, String imageDomain, String[] allowFileTypeArr, String saveManagerClass) {
+ this.imageBaseDir = imageBaseDir;
+ if (imageBaseDir.endsWith("/")) {
+ StringUtils.removeEnd(imageBaseDir, "/");
+ }
+ if (imageBaseDir.endsWith("\\")) {
+ StringUtils.removeEnd(imageBaseDir, "\\");
+ }
+
+ this.imageDomain = imageDomain;
+ if (imageDomain.endsWith("/")) {
+ StringUtils.removeEnd(imageDomain, "/");
+ }
+
+ this.allowFileTypeArr = allowFileTypeArr;
+
+ if (StringUtils.isBlank(saveManagerClass)) {
+ fileSaveManager = new DefaultFileSaveManager();
+ } else {
+ try {
+ Class> klass = Class.forName(saveManagerClass);
+ fileSaveManager = (FileSaveManager) klass.newInstance();
+ } catch (ClassNotFoundException e) {
+ log.error(e);
+ throw new RuntimeException(e);
+ } catch (InstantiationException e) {
+ log.error(e);
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ log.error(e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * ckEditor로부터 넘어온 파일을 저장한다.
+ * 원래 소스는 Request 내의 데이터를 FileItem으로 파싱하여 파일을 저장하였으나,
+ * 파싱하지 못하는 버그가 발생하여 MultipartRequest로 변형하였다.
+ *
+ * @param request Request 객체
+ * @param response Response 객체
+ * @throws IOException IO 예외처리
+ */
+ public void saveAndReturnUrlToClient(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
+ // Parse the request
+ try {
+ MultipartRequest req = (MultipartRequest) request;
+ MultipartFile f = req.getFile("upload");
+
+ String errorMessage = null;
+ String relUrl = null;
+
+ if (isAllowFileType(FilenameUtils.getName(f.getOriginalFilename()))) {
+ relUrl = fileSaveManager.saveFile(f, imageBaseDir, imageDomain);
+
+ } else {
+ errorMessage = "Restricted Image Format";
+ }
+
+ StringBuffer sb = new StringBuffer();
+ sb.append("");
+
+ response.setContentType("text/html");
+ response.setHeader("Cache-Control", "no-cache");
+ PrintWriter out = response.getWriter();
+
+ out.print(sb.toString());
+ out.flush();
+ out.close();
+
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ protected boolean isAllowFileType(String fileName) {
+ boolean isAllow = false;
+ if (allowFileTypeArr != null && allowFileTypeArr.length > 0) {
+ for (String allowFileType : allowFileTypeArr) {
+ if (StringUtils.equalsIgnoreCase(allowFileType, StringUtils.substringAfterLast(fileName, "."))) {
+ isAllow = true;
+ break;
+ }
+ }
+ } else {
+ isAllow = true;
+ }
+
+ return isAllow;
+ }
+}
diff --git a/src/main/java/kcg/faics/cmmn/ckeditor/DefaultFileSaveManager.java b/src/main/java/kcg/faics/cmmn/ckeditor/DefaultFileSaveManager.java
new file mode 100644
index 0000000..0fe045d
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/ckeditor/DefaultFileSaveManager.java
@@ -0,0 +1,94 @@
+/*
+ * CKEditor image upload module for Java.
+ * Copyright guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ *
+ * 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.
+ *
+ * @author guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ */
+package kcg.faics.cmmn.ckeditor;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * Created by guava on 1/20/14.
+ * 이미지 저장 처리 클래스
+ * @author guavatak
+ * @since 2014.12.04
+ * @version 1.0
+ * @see
+ *
+ *
+ * << 개정이력(Modification Information) >>
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2014.12.04 표준프레임워크 최초 적용 (패키지 변경 및 소스 정리)
+ *
+ */
+public class DefaultFileSaveManager implements FileSaveManager {
+
+ @Override
+ public String saveFile(FileItem fileItem, String imageBaseDir, String imageDomain) {
+ String originalFileName = FilenameUtils.getName(fileItem.getName());
+ String relUrl;
+ // filename
+ String subDir = File.separator + DirectoryPathManager.getDirectoryPathByDateType(DirectoryPathManager.DIR_DATE_TYPE.DATE_POLICY_YYYY_MM);
+ String fileName = RandomStringUtils.randomAlphanumeric(20) + "." + StringUtils.lowerCase(StringUtils.substringAfterLast(originalFileName, "."));
+
+ File newFile = new File(imageBaseDir + subDir + fileName);
+ File fileToSave = DirectoryPathManager.getUniqueFile(newFile.getAbsoluteFile());
+
+ try {
+ FileUtils.writeByteArrayToFile(fileToSave, fileItem.get());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ String savedFileName = FilenameUtils.getName(fileToSave.getAbsolutePath());
+ relUrl = StringUtils.replace(subDir, "\\", "/") + savedFileName;
+
+ return imageDomain + relUrl;
+ }
+
+ @Override
+ public String saveFile(final MultipartFile file, final String imageBaseDir, final String imageDomain) {
+ String originalFileName = FilenameUtils.getName(file.getOriginalFilename());
+ String relUrl;
+ // filename
+ String subDir = File.separator + DirectoryPathManager.getDirectoryPathByDateType(DirectoryPathManager.DIR_DATE_TYPE.DATE_POLICY_YYYY_MM);
+ String fileName = RandomStringUtils.randomAlphanumeric(20) + "." + StringUtils.lowerCase(StringUtils.substringAfterLast(originalFileName, "."));
+
+ File newFile = new File(imageBaseDir + subDir + fileName);
+ File fileToSave = DirectoryPathManager.getUniqueFile(newFile.getAbsoluteFile());
+
+ try {
+ FileUtils.writeByteArrayToFile(fileToSave, file.getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ String savedFileName = FilenameUtils.getName(fileToSave.getAbsolutePath());
+ relUrl = StringUtils.replace(subDir, "\\", "/") + savedFileName;
+
+ return imageDomain + relUrl;
+ }
+}
diff --git a/src/main/java/kcg/faics/cmmn/ckeditor/DirectoryPathManager.java b/src/main/java/kcg/faics/cmmn/ckeditor/DirectoryPathManager.java
new file mode 100644
index 0000000..6304560
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/ckeditor/DirectoryPathManager.java
@@ -0,0 +1,83 @@
+/*
+ * CKEditor image upload module for Java.
+ * Copyright guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ *
+ * 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.
+ *
+ * @author guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ */
+package kcg.faics.cmmn.ckeditor;
+
+import java.io.File;
+import java.util.Calendar;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 이미지 저장 처리 클래스
+ * @author guavatak
+ * @since 2014.12.04
+ * @version 1.0
+ * @see
+ *
+ *
+ * << 개정이력(Modification Information) >>
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2014.12.04 표준프레임워크 최초 적용 (패키지 변경 및 소스 정리)
+ *
+ */
+public class DirectoryPathManager {
+ public enum DIR_DATE_TYPE {
+ DATE_POLICY_YYYY_MM_DD, DATE_POLICY_YYYY_MM, DATE_POLICY_YYYY
+ };
+
+ /**
+ * 2012/12/22/
+ * @param dateType
+ * @return
+ * @throws InvalidArgumentException
+ */
+ public static String getDirectoryPathByDateType(DIR_DATE_TYPE policy) {
+
+ Calendar calendar = Calendar.getInstance();
+ StringBuffer sb = new StringBuffer();
+ sb.append(calendar.get(Calendar.YEAR)).append(File.separator);
+ if (policy.ordinal() <= DIR_DATE_TYPE.DATE_POLICY_YYYY_MM.ordinal()) {
+ sb.append(StringUtils.leftPad(String.valueOf(calendar.get(Calendar.MONTH)), 2, '0')).append(File.separator);
+ }
+ if (policy.ordinal() <= DIR_DATE_TYPE.DATE_POLICY_YYYY_MM_DD.ordinal()) {
+ sb.append(StringUtils.leftPad(String.valueOf(calendar.get(Calendar.DATE)), 2, '0')).append(File.separator);
+ }
+
+ return sb.toString();
+ }
+
+ public static File getUniqueFile(final File file) {
+ if (!file.exists())
+ return file;
+
+ File tmpFile = new File(file.getAbsolutePath());
+ File parentDir = tmpFile.getParentFile();
+ int count = 1;
+ String extension = FilenameUtils.getExtension(tmpFile.getName());
+ String baseName = FilenameUtils.getBaseName(tmpFile.getName());
+ do {
+ tmpFile = new File(parentDir, baseName + "_" + count++ + "_." + extension);
+ } while (tmpFile.exists());
+ return tmpFile;
+ }
+
+}
diff --git a/src/main/java/kcg/faics/cmmn/ckeditor/FileSaveManager.java b/src/main/java/kcg/faics/cmmn/ckeditor/FileSaveManager.java
new file mode 100644
index 0000000..6d54e9a
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/ckeditor/FileSaveManager.java
@@ -0,0 +1,63 @@
+/*
+ * CKEditor image upload module for Java.
+ * Copyright guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ *
+ * 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.
+ *
+ * @author guavatak (https://github.com/guavatak/ckeditor-upload-filter-java)
+ */
+package kcg.faics.cmmn.ckeditor;
+
+import org.apache.commons.fileupload.FileItem;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * Created by guava on 1/20/14.
+ * 이미지 저장 처리 클래스
+ * @author guavatak
+ * @since 2014.12.04
+ * @version 1.0
+ * @see
+ *
+ *
+ * << 개정이력(Modification Information) >>
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2014.12.04 표준프레임워크 최초 적용 (패키지 변경 및 소스 정리)
+ *
+ */
+public interface FileSaveManager {
+ /**
+ *
+ * @param fileItem FileItem 객체
+ * @param imageBaseDir 기본 이미지 저장 디렉토리. 이 디렉토리 아래로 모든 파일을 넣어도 되고, 폴더를 구분하여 넣어도 된다. 이 파라미터에는 마지막 디렉토리 구분자는 포함되지 않는다.
+ * @param imageDomain 이미지 태그에 들어갈 기본이 되는 URL.
+ * "http://image.my.com" 과 같은 도메인이 들어갈 수도 있고, "/ckimage" 같은 상대 경로가 들어갈 수도 있다.
+ * 이 파라미터는 생략해도 된다.
+ * @return 이미지 파일을 액세스 할 수 있는 URL 을 반환한다. 반환된 URL 은 ckeditor 에게 전달되어 즉시 사용자 브라우져에 이미지가 나타나게 된다.
+ */
+ String saveFile(FileItem fileItem, String imageBaseDir, String imageDomain);
+
+ /**
+ *
+ * @param file MultipartFile 객체
+ * @param imageBaseDir 기본 이미지 저장 디렉토리. 이 디렉토리 아래로 모든 파일을 넣어도 되고, 폴더를 구분하여 넣어도 된다. 이 파라미터에는 마지막 디렉토리 구분자는 포함되지 않는다.
+ * @param imageDomain 이미지 태그에 들어갈 기본이 되는 URL.
+ * "http://image.my.com" 과 같은 도메인이 들어갈 수도 있고, "/ckimage" 같은 상대 경로가 들어갈 수도 있다.
+ * 이 파라미터는 생략해도 된다.
+ * @return 이미지 파일을 액세스 할 수 있는 URL 을 반환한다. 반환된 URL 은 ckeditor 에게 전달되어 즉시 사용자 브라우져에 이미지가 나타나게 된다.
+ */
+ String saveFile(MultipartFile file, String imageBaseDir, String imageDomain);
+}
+
diff --git a/src/main/java/kcg/faics/cmmn/egov/EgovBasicLogger.java b/src/main/java/kcg/faics/cmmn/egov/EgovBasicLogger.java
new file mode 100644
index 0000000..42f0f0f
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/egov/EgovBasicLogger.java
@@ -0,0 +1,83 @@
+package kcg.faics.cmmn.egov;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Utility class to support to logging information
+ * @author Vincent Han
+ * @since 2014.09.18
+ * @version 1.0
+ * @see
+ *
+ *
+ * << 개정이력(Modification Information) >>
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2014.09.18 표준프레임워크센터 최초 생성
+ *
+ *
+ */
+public class EgovBasicLogger {
+ private static final Level IGNORE_INFO_LEVEL = Level.OFF;
+ private static final Level DEBUG_INFO_LEVEL = Level.FINEST;
+ private static final Level INFO_INFO_LEVEL = Level.INFO;
+
+ private static final Logger ignoreLogger = Logger.getLogger("ignore");
+ private static final Logger debugLogger = Logger.getLogger("debug");
+ private static final Logger infoLogger = Logger.getLogger("info");
+
+ /**
+ * 기록이나 처리가 불필요한 경우 사용.
+ * @param message
+ * @param exception
+ */
+ public static void ignore(String message, Exception exception) {
+ if (exception == null) {
+ ignoreLogger.log(IGNORE_INFO_LEVEL, message);
+ } else {
+ ignoreLogger.log(IGNORE_INFO_LEVEL, message, exception);
+ }
+ }
+
+ /**
+ * 기록이나 처리가 불필요한 경우 사용.
+ * @param message
+ * @param exception
+ */
+ public static void ignore(String message) {
+ ignore(message, null);
+ }
+
+ /**
+ * 디버그 정보를 기록하는 경우 사용.
+ * @param message
+ * @param exception
+ */
+ public static void debug(String message, Exception exception) {
+ if (exception == null) {
+ debugLogger.log(DEBUG_INFO_LEVEL, message);
+ } else {
+ debugLogger.log(DEBUG_INFO_LEVEL, message, exception);
+ }
+ }
+
+ /**
+ * 디버그 정보를 기록하는 경우 사용.
+ * @param message
+ * @param exception
+ */
+ public static void debug(String message) {
+ debug(message, null);
+ }
+
+ /**
+ * 일반적이 정보를 기록하는 경우 사용.
+ * @param message
+ * @param exception
+ */
+ public static void info(String message) {
+ infoLogger.log(INFO_INFO_LEVEL, message);
+ }
+}
diff --git a/src/main/java/kcg/faics/cmmn/egov/EgovProperties.java b/src/main/java/kcg/faics/cmmn/egov/EgovProperties.java
new file mode 100644
index 0000000..607fcf4
--- /dev/null
+++ b/src/main/java/kcg/faics/cmmn/egov/EgovProperties.java
@@ -0,0 +1,220 @@
+package kcg.faics.cmmn.egov;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import kcg.faics.cmmn.egov.util.EgovWebUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class Name : EgovProperties.java
+ * Description : properties값들을 파일로부터 읽어와 Globals클래스의 정적변수로 로드시켜주는 클래스로
+ * 문자열 정보 기준으로 사용할 전역변수를 시스템 재시작으로 반영할 수 있도록 한다.
+ * Modification Information
+ *
+ * 수정일 수정자 수정내용
+ * ------- -------- ---------------------------
+ * 2009.01.19 박지욱 최초 생성
+ * 2011.07.20 서준식 Globals파일의 상대경로를 읽은 메서드 추가
+ * 2014.10.13 이기하 Globals.properties 값이 null일 경우 오류처리
+ * 2016.09.22 임새미 폴더 path값 변경
+ * @author 공통 서비스 개발팀 박지욱
+ * @since 2009. 01. 19
+ * @version 1.0
+ * @see
+ *
+ */
+
+public class EgovProperties {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(EgovProperties.class);
+
+ //파일구분자
+ final static String FILE_SEPARATOR = System.getProperty("file.separator");
+
+ //프로퍼티 파일의 물리적 위치
+ //public static final String GLOBALS_PROPERTIES_FILE = System.getProperty("user.home") + FILE_SEPARATOR + "egovProps" +FILE_SEPARATOR + "globals.properties";
+
+ //public static final String RELATIVE_PATH_PREFIX = EgovProperties.class.getResource("").getPath() + FILE_SEPARATOR+ ".." + FILE_SEPARATOR + ".." + FILE_SEPARATOR;
+
+ public static final String RELATIVE_PATH_PREFIX = EgovProperties.class.getResource("").getPath().substring(0, EgovProperties.class.getResource("").getPath().lastIndexOf("kcg"));
+
+ public static final String GLOBALS_PROPERTIES_FILE = RELATIVE_PATH_PREFIX + "property" + FILE_SEPARATOR + "globals.properties";
+
+ /**
+ * 인자로 주어진 문자열을 Key값으로 하는 상대경로 프로퍼티 값을 절대경로로 반환한다(Globals.java 전용)
+ * @param keyName String
+ * @return String
+ */
+ public static String getPathProperty(String keyName) {
+ String value = "";
+
+ LOGGER.debug("getPathProperty : {} = {}", GLOBALS_PROPERTIES_FILE, keyName);
+
+ FileInputStream fis = null;
+ try {
+ Properties props = new Properties();
+
+ fis = new FileInputStream(EgovWebUtil.filePathBlackList(GLOBALS_PROPERTIES_FILE));
+ props.load(new BufferedInputStream(fis));
+
+ value = props.getProperty(keyName).trim();
+ value = RELATIVE_PATH_PREFIX + "property" + System.getProperty("file.separator") + value;
+ } catch (FileNotFoundException fne) {
+ LOGGER.debug("Property file not found.", fne);
+ throw new RuntimeException("Property file not found", fne);
+ } catch (IOException ioe) {
+ LOGGER.debug("Property file IO exception", ioe);
+ throw new RuntimeException("Property file IO exception", ioe);
+ } finally {
+ EgovResourceCloseHelper.close(fis);
+ }
+
+ return value;
+ }
+
+ /**
+ * 인자로 주어진 문자열을 Key값으로 하는 프로퍼티 값을 반환한다(Globals.java 전용)
+ * @param keyName String
+ * @return String
+ */
+ public static String getProperty(String keyName) {
+ String value = "";
+
+ LOGGER.debug("getProperty : {} = {}", GLOBALS_PROPERTIES_FILE, keyName);
+
+ FileInputStream fis = null;
+ try {
+ Properties props = new Properties();
+
+ fis = new FileInputStream(EgovWebUtil.filePathBlackList(GLOBALS_PROPERTIES_FILE));
+
+ props.load(new BufferedInputStream(fis));
+ if (props.getProperty(keyName) == null) {
+ return "";
+ }
+ value = props.getProperty(keyName).trim();
+ } catch (FileNotFoundException fne) {
+ LOGGER.debug("Property file not found.", fne);
+ throw new RuntimeException("Property file not found", fne);
+ } catch (IOException ioe) {
+ LOGGER.debug("Property file IO exception", ioe);
+ throw new RuntimeException("Property file IO exception", ioe);
+ } finally {
+ EgovResourceCloseHelper.close(fis);
+ }
+
+ return value;
+ }
+
+ /**
+ * 주어진 파일에서 인자로 주어진 문자열을 Key값으로 하는 프로퍼티 상대 경로값을 절대 경로값으로 반환한다
+ * @param fileName String
+ * @param key String
+ * @return String
+ */
+ public static String getPathProperty(String fileName, String key) {
+ FileInputStream fis = null;
+ try {
+ Properties props = new Properties();
+
+ fis = new FileInputStream(EgovWebUtil.filePathBlackList(fileName));
+ props.load(new BufferedInputStream(fis));
+ fis.close();
+
+ String value = props.getProperty(key);
+ value = RELATIVE_PATH_PREFIX + "property" + System.getProperty("file.separator") + value;
+
+ return value;
+ } catch (FileNotFoundException fne) {
+ LOGGER.debug("Property file not found.", fne);
+ throw new RuntimeException("Property file not found", fne);
+ } catch (IOException ioe) {
+ LOGGER.debug("Property file IO exception", ioe);
+ throw new RuntimeException("Property file IO exception", ioe);
+ } finally {
+ EgovResourceCloseHelper.close(fis);
+ }
+ }
+
+ /**
+ * 주어진 파일에서 인자로 주어진 문자열을 Key값으로 하는 프로퍼티 값을 반환한다
+ * @param fileName String
+ * @param key String
+ * @return String
+ */
+ public static String getProperty(String fileName, String key) {
+ FileInputStream fis = null;
+ try {
+ Properties props = new Properties();
+
+ fis = new FileInputStream(EgovWebUtil.filePathBlackList(fileName));
+ props.load(new BufferedInputStream(fis));
+ fis.close();
+
+ String value = props.getProperty(key);
+
+ return value;
+ } catch (FileNotFoundException fne) {
+ LOGGER.debug("Property file not found.", fne);
+ throw new RuntimeException("Property file not found", fne);
+ } catch (IOException ioe) {
+ LOGGER.debug("Property file IO exception", ioe);
+ throw new RuntimeException("Property file IO exception", ioe);
+ } finally {
+ EgovResourceCloseHelper.close(fis);
+ }
+ }
+
+ /**
+ * 주어진 프로파일의 내용을 파싱하여 (key-value) 형태의 구조체 배열을 반환한다.
+ * @param property String
+ * @return ArrayList
+ */
+ public static ArrayList