From a41cb6722ffb3ae4a4d89bfa2e42975eed1aa618 Mon Sep 17 00:00:00 2001 From: urp Date: Tue, 26 May 2026 11:03:41 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B5=9C=EC=B4=88=EB=B0=98=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .classpath | 23 + .gitattributes | 6 + .gitignore | 5 + .project | 41 ++ .project.bak | 28 + .settings/org.eclipse.buildship.core.prefs | 2 + .settings/org.eclipse.jdt.core.prefs | 4 + .settings/org.eclipse.wst.common.component | 9 + ....eclipse.wst.common.project.facet.core.xml | 7 + .../org.springframework.ide.eclipse.prefs | 2 + bin/main/application-local.yml | 67 +++ bin/main/application-ncms_server.yml | 67 +++ bin/main/com/urpsys/kccfbat/Aes256Test.class | Bin 0 -> 3028 bytes .../kccfbat/common/crypto/Aes256Cipher.class | Bin 0 -> 3045 bytes .../common/exception/CustomException.class | Bin 0 -> 1851 bytes .../kccfbat/common/util/CommonUtil.class | Bin 0 -> 10404 bytes .../kccfbat/common/util/CommonUtils.class | Bin 0 -> 1584 bytes .../kccfbat/common/util/DataSourceUtil.class | Bin 0 -> 4061 bytes .../kccfbat/common/util/ResultData.class | Bin 0 -> 7508 bytes .../urpsys/kccfbat/config/EncryptConfig.class | Bin 0 -> 813 bytes .../kccfbat/config/Oauth2ResourceConfig.class | Bin 0 -> 6216 bytes .../urpsys/kccfbat/config/SwaggerConfig.class | Bin 0 -> 5513 bytes .../urpsys/kccfbat/config/iamsDbConfig.class | Bin 0 -> 3656 bytes .../urpsys/kccfbat/config/ncmsDbConfig.class | Bin 0 -> 3654 bytes .../com/urpsys/kccfbat/domain/CommonVO.class | Bin 0 -> 1279 bytes .../com/urpsys/kccfbat/domain/JWTKey.class | Bin 0 -> 2111 bytes .../com/urpsys/kccfbat/domain/TokenInfo.class | Bin 0 -> 16652 bytes .../urpsys/kccfbat/iams/dao/IamsDataDao.class | Bin 0 -> 668 bytes .../urpsys/kccfbat/ncms/dao/CommonDao.class | Bin 0 -> 402 bytes .../urpsys/kccfbat/ncms/dao/NcmsDataDao.class | Bin 0 -> 1123 bytes .../ncmsToIamsDataTransApplication.class | Bin 0 -> 1760 bytes .../kccfbat/scheduler/ConsoleScheduler.class | Bin 0 -> 1633 bytes .../kccfbat/service/CommonService.class | Bin 0 -> 985 bytes .../kccfbat/service/IamsDataService.class | Bin 0 -> 4111 bytes .../kccfbat/service/NcmsDataService.class | Bin 0 -> 2280 bytes .../service/NcmsToIamsDataTransService.class | Bin 0 -> 14811 bytes bin/main/log4jdbc.log4j2.properties | 2 + bin/main/logback-spring.xml | 98 +++ .../iamsdb/config/MybatisIamsConfig.xml | 35 ++ .../mapper/iamsdb/sqlmap/iamsDataMapper.xml | 185 ++++++ .../ncmsdb/config/MybatisNcmsConfig.xml | 33 ++ .../mapper/ncmsdb/sqlmap/CommonMapper.xml | 26 + .../mapper/ncmsdb/sqlmap/ncmsDataMapper.xml | 243 ++++++++ bin/main/secrets/UrpSystem.keystore | 1 + bin/test/UrpKeyMng/LibraryTest.class | Bin 0 -> 634 bytes build.gradle | 96 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 234 ++++++++ gradlew.bat | 89 +++ settings.gradle | 10 + settings.gradle.bak | 11 + .../java/com/urpsys/kccfbat/Aes256Test.java | 124 ++++ .../kccfbat/common/crypto/Aes256Cipher.java | 145 +++++ .../common/exception/CustomException.java | 114 ++++ .../kccfbat/common/util/CommonUtil.java | 503 ++++++++++++++++ .../kccfbat/common/util/CommonUtils.java | 76 +++ .../kccfbat/common/util/DataSourceUtil.java | 113 ++++ .../kccfbat/common/util/ResultData.java | 222 +++++++ .../urpsys/kccfbat/config/EncryptConfig.java | 38 ++ .../kccfbat/config/Oauth2ResourceConfig.java | 166 ++++++ .../urpsys/kccfbat/config/SwaggerConfig.java | 124 ++++ .../urpsys/kccfbat/config/iamsDbConfig.java | 112 ++++ .../urpsys/kccfbat/config/ncmsDbConfig.java | 112 ++++ .../com/urpsys/kccfbat/domain/CommonVO.java | 52 ++ .../com/urpsys/kccfbat/domain/JWTKey.java | 24 + .../com/urpsys/kccfbat/domain/TokenInfo.java | 46 ++ .../urpsys/kccfbat/iams/dao/IamsDataDao.java | 49 ++ .../urpsys/kccfbat/ncms/dao/CommonDao.java | 18 + .../urpsys/kccfbat/ncms/dao/NcmsDataDao.java | 57 ++ .../ncmsToIamsDataTransApplication.java | 60 ++ .../kccfbat/scheduler/ConsoleScheduler.java | 70 +++ .../urpsys/kccfbat/service/CommonService.java | 35 ++ .../kccfbat/service/IamsDataService.java | 92 +++ .../kccfbat/service/NcmsDataService.java | 67 +++ .../service/NcmsToIamsDataTransService.java | 558 ++++++++++++++++++ src/main/resources/application-local.yml | 67 +++ .../resources/application-ncms_server.yml | 67 +++ src/main/resources/log4jdbc.log4j2.properties | 2 + src/main/resources/logback-spring.xml | 98 +++ .../iamsdb/config/MybatisIamsConfig.xml | 35 ++ .../mapper/iamsdb/sqlmap/iamsDataMapper.xml | 185 ++++++ .../ncmsdb/config/MybatisNcmsConfig.xml | 33 ++ .../mapper/ncmsdb/sqlmap/CommonMapper.xml | 26 + .../mapper/ncmsdb/sqlmap/ncmsDataMapper.xml | 243 ++++++++ src/main/resources/secrets/UrpSystem.keystore | 1 + src/main/webapp/WEB-INF/jsp/bodyTest.jsp | 6 + .../WEB-INF/jsp/tilesLayout/base-main.jsp | 38 ++ .../webapp/WEB-INF/jsp/tilesLayout/footer.jsp | 10 + .../webapp/WEB-INF/jsp/tilesLayout/header.jsp | 32 + src/main/webapp/WEB-INF/tiles/tiles.xml | 26 + 91 files changed, 5175 insertions(+) create mode 100644 .classpath create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .project create mode 100644 .project.bak create mode 100644 .settings/org.eclipse.buildship.core.prefs create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.wst.common.component create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 .settings/org.springframework.ide.eclipse.prefs create mode 100644 bin/main/application-local.yml create mode 100644 bin/main/application-ncms_server.yml create mode 100644 bin/main/com/urpsys/kccfbat/Aes256Test.class create mode 100644 bin/main/com/urpsys/kccfbat/common/crypto/Aes256Cipher.class create mode 100644 bin/main/com/urpsys/kccfbat/common/exception/CustomException.class create mode 100644 bin/main/com/urpsys/kccfbat/common/util/CommonUtil.class create mode 100644 bin/main/com/urpsys/kccfbat/common/util/CommonUtils.class create mode 100644 bin/main/com/urpsys/kccfbat/common/util/DataSourceUtil.class create mode 100644 bin/main/com/urpsys/kccfbat/common/util/ResultData.class create mode 100644 bin/main/com/urpsys/kccfbat/config/EncryptConfig.class create mode 100644 bin/main/com/urpsys/kccfbat/config/Oauth2ResourceConfig.class create mode 100644 bin/main/com/urpsys/kccfbat/config/SwaggerConfig.class create mode 100644 bin/main/com/urpsys/kccfbat/config/iamsDbConfig.class create mode 100644 bin/main/com/urpsys/kccfbat/config/ncmsDbConfig.class create mode 100644 bin/main/com/urpsys/kccfbat/domain/CommonVO.class create mode 100644 bin/main/com/urpsys/kccfbat/domain/JWTKey.class create mode 100644 bin/main/com/urpsys/kccfbat/domain/TokenInfo.class create mode 100644 bin/main/com/urpsys/kccfbat/iams/dao/IamsDataDao.class create mode 100644 bin/main/com/urpsys/kccfbat/ncms/dao/CommonDao.class create mode 100644 bin/main/com/urpsys/kccfbat/ncms/dao/NcmsDataDao.class create mode 100644 bin/main/com/urpsys/kccfbat/ncmsToIamsDataTransApplication.class create mode 100644 bin/main/com/urpsys/kccfbat/scheduler/ConsoleScheduler.class create mode 100644 bin/main/com/urpsys/kccfbat/service/CommonService.class create mode 100644 bin/main/com/urpsys/kccfbat/service/IamsDataService.class create mode 100644 bin/main/com/urpsys/kccfbat/service/NcmsDataService.class create mode 100644 bin/main/com/urpsys/kccfbat/service/NcmsToIamsDataTransService.class create mode 100644 bin/main/log4jdbc.log4j2.properties create mode 100644 bin/main/logback-spring.xml create mode 100644 bin/main/mapper/iamsdb/config/MybatisIamsConfig.xml create mode 100644 bin/main/mapper/iamsdb/sqlmap/iamsDataMapper.xml create mode 100644 bin/main/mapper/ncmsdb/config/MybatisNcmsConfig.xml create mode 100644 bin/main/mapper/ncmsdb/sqlmap/CommonMapper.xml create mode 100644 bin/main/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml create mode 100644 bin/main/secrets/UrpSystem.keystore create mode 100644 bin/test/UrpKeyMng/LibraryTest.class create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 settings.gradle.bak create mode 100644 src/main/java/com/urpsys/kccfbat/Aes256Test.java create mode 100644 src/main/java/com/urpsys/kccfbat/common/crypto/Aes256Cipher.java create mode 100644 src/main/java/com/urpsys/kccfbat/common/exception/CustomException.java create mode 100644 src/main/java/com/urpsys/kccfbat/common/util/CommonUtil.java create mode 100644 src/main/java/com/urpsys/kccfbat/common/util/CommonUtils.java create mode 100644 src/main/java/com/urpsys/kccfbat/common/util/DataSourceUtil.java create mode 100644 src/main/java/com/urpsys/kccfbat/common/util/ResultData.java create mode 100644 src/main/java/com/urpsys/kccfbat/config/EncryptConfig.java create mode 100644 src/main/java/com/urpsys/kccfbat/config/Oauth2ResourceConfig.java create mode 100644 src/main/java/com/urpsys/kccfbat/config/SwaggerConfig.java create mode 100644 src/main/java/com/urpsys/kccfbat/config/iamsDbConfig.java create mode 100644 src/main/java/com/urpsys/kccfbat/config/ncmsDbConfig.java create mode 100644 src/main/java/com/urpsys/kccfbat/domain/CommonVO.java create mode 100644 src/main/java/com/urpsys/kccfbat/domain/JWTKey.java create mode 100644 src/main/java/com/urpsys/kccfbat/domain/TokenInfo.java create mode 100644 src/main/java/com/urpsys/kccfbat/iams/dao/IamsDataDao.java create mode 100644 src/main/java/com/urpsys/kccfbat/ncms/dao/CommonDao.java create mode 100644 src/main/java/com/urpsys/kccfbat/ncms/dao/NcmsDataDao.java create mode 100644 src/main/java/com/urpsys/kccfbat/ncmsToIamsDataTransApplication.java create mode 100644 src/main/java/com/urpsys/kccfbat/scheduler/ConsoleScheduler.java create mode 100644 src/main/java/com/urpsys/kccfbat/service/CommonService.java create mode 100644 src/main/java/com/urpsys/kccfbat/service/IamsDataService.java create mode 100644 src/main/java/com/urpsys/kccfbat/service/NcmsDataService.java create mode 100644 src/main/java/com/urpsys/kccfbat/service/NcmsToIamsDataTransService.java create mode 100644 src/main/resources/application-local.yml create mode 100644 src/main/resources/application-ncms_server.yml create mode 100644 src/main/resources/log4jdbc.log4j2.properties create mode 100644 src/main/resources/logback-spring.xml create mode 100644 src/main/resources/mapper/iamsdb/config/MybatisIamsConfig.xml create mode 100644 src/main/resources/mapper/iamsdb/sqlmap/iamsDataMapper.xml create mode 100644 src/main/resources/mapper/ncmsdb/config/MybatisNcmsConfig.xml create mode 100644 src/main/resources/mapper/ncmsdb/sqlmap/CommonMapper.xml create mode 100644 src/main/resources/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml create mode 100644 src/main/resources/secrets/UrpSystem.keystore create mode 100644 src/main/webapp/WEB-INF/jsp/bodyTest.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/tilesLayout/base-main.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/tilesLayout/footer.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/tilesLayout/header.jsp create mode 100644 src/main/webapp/WEB-INF/tiles/tiles.xml diff --git a/.classpath b/.classpath new file mode 100644 index 00000000..cf67b54a --- /dev/null +++ b/.classpath @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..00a51aff --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1b6985c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/.project b/.project new file mode 100644 index 00000000..b6733e9e --- /dev/null +++ b/.project @@ -0,0 +1,41 @@ + + + ncmsToIamsDataTrans + Project lib created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + org.springframework.ide.eclipse.boot.validation.springbootbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/.project.bak b/.project.bak new file mode 100644 index 00000000..5949b2c1 --- /dev/null +++ b/.project.bak @@ -0,0 +1,28 @@ + + + urpBaseResource + Project lib created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + org.springframework.ide.eclipse.boot.validation.springbootbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..e8895216 --- /dev/null +++ b/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..18ad8952 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.source=11 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 00000000..81ccd76f --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 00000000..14e5ac12 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.springframework.ide.eclipse.prefs b/.settings/org.springframework.ide.eclipse.prefs new file mode 100644 index 00000000..a12794d6 --- /dev/null +++ b/.settings/org.springframework.ide.eclipse.prefs @@ -0,0 +1,2 @@ +boot.validation.initialized=true +eclipse.preferences.version=1 diff --git a/bin/main/application-local.yml b/bin/main/application-local.yml new file mode 100644 index 00000000..8348fa60 --- /dev/null +++ b/bin/main/application-local.yml @@ -0,0 +1,67 @@ + # Service port + server: + port: 9002 + +# JPA 설정, JSP 설정 + spring: + devtools: + livereload: + enabled: true + mvc: + pathmatch: + matching-strategy: ANT_PATH_MATCHER + # 인증서버에서 JWT 보안키 확인 + security: + oauth2: + resourceserver: + jwt: + jwk-set-uri: + http://localhost:9001/oauth/token_key + +# Primary db information + ncmsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://192.168.8.138:3307/kccfnova?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: yT4l55I/Xl4v8LeoTQhh1w== + password: aqmsYeReTVvoQ4r2bfAjYg== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + iamsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://192.168.8.138:3307/uac_cltr_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: kSLzt543nkDJ/ta9rnLTCA== + password: kSLzt543nkDJ/ta9rnLTCA== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + +# SQL Log 관련 setting + log4jdbc: + spylogdelegator: + name: net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator + dump: + sql: + maxlinelength: 0 + + logging.level.jdbc.sqlonly: info + logging.level.jdbc.sqltiming: false + logging.level.jdbc.audit: false + logging.level.jdbc.resultset: false + logging.level.jdbc.resultsettable: info + logging.level.jdbc.connection: false + + file: + ncms: + basefolder : D:/z_temp_pro/kccf_temp + iams: + basefolder : D:/z_temp_pro/kccf_temp/repo + fileCpYn : N + + \ No newline at end of file diff --git a/bin/main/application-ncms_server.yml b/bin/main/application-ncms_server.yml new file mode 100644 index 00000000..29bd63eb --- /dev/null +++ b/bin/main/application-ncms_server.yml @@ -0,0 +1,67 @@ + # Service port + server: + port: 9002 + +# JPA 설정, JSP 설정 + spring: + devtools: + livereload: + enabled: true + mvc: + pathmatch: + matching-strategy: ANT_PATH_MATCHER + # 인증서버에서 JWT 보안키 확인 + security: + oauth2: + resourceserver: + jwt: + jwk-set-uri: + http://localhost:9001/oauth/token_key + +# Primary db information + ncmsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://127.0.0.1:3306/kccfnova?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: yT4l55I/Xl4v8LeoTQhh1w== + password: aqmsYeReTVvoQ4r2bfAjYg== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + iamsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://10.10.30.237:3306/uac_cltr_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: kSLzt543nkDJ/ta9rnLTCA== + password: kSLzt543nkDJ/ta9rnLTCA== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + +# SQL Log 관련 setting + log4jdbc: + spylogdelegator: + name: net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator + dump: + sql: + maxlinelength: 0 + + logging.level.jdbc.sqlonly: info + logging.level.jdbc.sqltiming: false + logging.level.jdbc.audit: false + logging.level.jdbc.resultset: false + logging.level.jdbc.resultsettable: info + logging.level.jdbc.connection: false + + file: + ncms: + basefolder : /nfs_nas/minio/amsweb-opt + iams: + basefolder : /nfs_nas/uac/repo + fileCpYn : Y + + \ No newline at end of file diff --git a/bin/main/com/urpsys/kccfbat/Aes256Test.class b/bin/main/com/urpsys/kccfbat/Aes256Test.class new file mode 100644 index 0000000000000000000000000000000000000000..c5a267f22db50e6661dcd9898150df0a0a2e5d35 GIT binary patch literal 3028 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 R-wu$E?F9MHWVH!@`7huu{0{&C literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/common/exception/CustomException.class b/bin/main/com/urpsys/kccfbat/common/exception/CustomException.class new file mode 100644 index 0000000000000000000000000000000000000000..27b35c25721b9b8e97813cdb810beaef1ffbee73 GIT binary patch literal 1851 zcmbVMT~ixn7(H)7*nA-&AyA7np;`%>NCGKs5v-+wYTBfonl^sSc(J70uqEu`X48*b z@B9VUJ1=y&#TjcIFP!m;8GnKQL2kV8&as|%vxKybH=TjqectEeoacGYo8SNa_zj%DWchYfw#G5A&Lv>j__7pG)Z7hR9Krdm+L# zt7A9xD~4R{_zRbGUiOO_D$UR9?#D?4FicCK%2lu!L1UFXIAo%t&{s&_7R$q?lJA(J+>oSs>L# zo{q!+Oop-%1x5Y=$%xz3lGoHtM*0{zre>ewoEpC%Ic7bIK9^#gP-CDfcOKlL+KBtUKez%>F?m|8^~*ZX=*^Z*j(JLDPTa_)z3Gs*0!}*GD*;0xM zC{=R@2xRwj{5-($9wPFqy7%m_+&)9PD?UwS0UBW&2;mM38f@_%OSY)MCRe@NMW`R`;N9g(c>||hfM_?s0}!}6Fgf*N M^31^GYc53PKP8fPQ2+n{ literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/common/util/CommonUtil.class b/bin/main/com/urpsys/kccfbat/common/util/CommonUtil.class new file mode 100644 index 0000000000000000000000000000000000000000..1343c58c24e31c834069e1c406b273f969fd9096 GIT binary patch literal 10404 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 Q!FvS%GQZ33^M~a5Go;daR{#J2 literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/common/util/CommonUtils.class b/bin/main/com/urpsys/kccfbat/common/util/CommonUtils.class new file mode 100644 index 0000000000000000000000000000000000000000..32078f22d0957bb9d0462c319c905e6ae36d9621 GIT binary patch literal 1584 zcma)6+fvg|6kVqjQbMp$K?FfS5lgv56uDRgp~%e^#8PH>4DA5}Y12tk2L4K4N=Ih= z06)rcpCkyhamG9(C;RNZ_S);LkvEHK#VXsEwtAM&A0KIsN}-}z zQY(&bs3~`yqopk&%+PVFoolM0l}^;%qf?%D7+MzflI|=qG{wgb7{V#Dz-2U{RY5aa z7@}#t#CIyiBW~?$M+RqzrOmu%9B7s<-u+jra9zRh9w0L&?Di)JvF@DWweTvl!7&UWN4>KvEdEO zFze6cDkCD~zgiVG%cOHjdIBHfemJKeD)=jIZIWjgdAa0)&q>&*N zj@>xJNJHzuM&SZsk*Pgiw>;^awF_jmTJaL-*-me*bOceqcpqVRFL8~I!$cLa z8XjMvKQ>s!a1Af27^hflFg8`iD+*OH^R2E!;!cMI-eT78(BpTQ_DOfv!_@<+E>OrV zpTkZ0f?wV%2*&1Xc;_*!;e9ZlnL9A#K%d1dsUk#DuCaW0g_T4NtMvqy?o6U!-JgWK z=ws{=6>$L3Yit~jUtudVL5gkP!pPJF*dl?qU8o^19Xr^iI2F2}jP_gb8GA0JFBA_U F`v>=LWXAvi literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/common/util/DataSourceUtil.class b/bin/main/com/urpsys/kccfbat/common/util/DataSourceUtil.class new file mode 100644 index 0000000000000000000000000000000000000000..4c0c6d16e906c339693aa1f5ba938b60baf7ce2c GIT binary patch literal 4061 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 DOPA9@ literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/config/Oauth2ResourceConfig.class b/bin/main/com/urpsys/kccfbat/config/Oauth2ResourceConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..79d86db06311b8966c611d77707a10feb380f58e GIT binary patch literal 6216 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 N2kTM`um8l{{{gA=W^(`l literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/config/SwaggerConfig.class b/bin/main/com/urpsys/kccfbat/config/SwaggerConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..307f7adc39d6ee97022474f8e4091e2f33b6c603 GIT binary patch literal 5513 zcmbtYiGLJl8Ga@QyIF=57m5~&hFaQ$Kn9}FmIX=(A*9`qxC;pj3QQ)G&5+H^c4n54 zs;vjLRq?*H9(Yyj)mGi4L~6C3wQ9ZZdY?uA1b;r?%esFHA_W{oNZJMWA;%7~^74XCc7S>}+DRnlW>Hmlq1-Y9|^3CmBa zr&J}Unpvf1;H0j(5~6LrUB?f!b$3XJCo8Yhu5FmvgoI_>?zpPy_Nlpo9z~sms|x*= zJ>oPR)E&2h+a)X&Li##V>8_pwQOFW%H@9qV*}|pb#omr|d#bDVp!f1B3D?Zp-|*~% z_gp+PdGXBs5|->ROvBwJp}MiDPeM(*HK@l>jg>N%<2e+VG)(U1)7- zYOYVU4KWTTYusVOkghUqAKEp0@1x%-+_!E}vLz0YtAs?lbemcNTyY)V>oHrPF6tE2iD;S)}B_0z7R zmX|7fbk$5m@O%kd!gLrY7`Z{+c9dRKNOE<1k3SQ`TC9v>9X-}oaEC41xYN^G%)d~^ z^;l0dO>U9U**MqH;Z}#9n26#=ahj&-4#^;pFvV$2GB$|QmJaHUW*d2dT?89R)i9$R zZCD>wm2Ubvm(qu#Xdw|CkAX2XW3%u*$#nI6diRMVUnJwj*h(^w1|lR3Hir9g=5e~M zo0^`uG6Zg-ro*~Qmk2#>k+EHvzARtz&cX3K`MVZ7Wb6cK9kum43Wlu@O4!zTjIRScXJcTm&9Qi8605>$mXm8HP@5ZZ7=f5 z5y}+M5m48|TY$L$-9llavJze@<7GG|A;NUkWe!;qnlHimZT@1<+!I2AD&g1y<_4T8 zZ42k=Ldqtg$ruDP&Jst@dDW(EAzi(+J0rdF{Is{zDy2Cloh)-c(|U_v^jZc~M<*6B z7#NA*q=cKpI8@GLDaIgc*M8L;%;|RN1V=^=qs&`EVy~)=s9CDMZN8-Am6fbzWpg_7 z_~GO!Izb#(%5;f@IM5_X2EGY@og?UiAJ{HdXZ{Lva0Kl!qJHTOVjUcguc zrzEt5XUoj923| zEc%YF6>P&DXD=dZri9%K^2kt}fWSeKb(Hi>3AFMIUKhbV%w&};*KXwmO1qAg8;QDS}p*HLY}((w;w632l)S-XP$SytCB)RdPP9d^g_1@Khb&y!DMoFVVjD$#}o8 zuk0F6FP)BDUaoz6{LX|KDm*FADNYpW=TR?xvcC}`XCo|O)y%Gs#USYXcFtP6<1)_P z#nSju){rpolzGpv5xF-oFottjDITAY@ku;DF1v;+TGLY2_Zse?qYe+x5b5;aIec2i zgFYg09*N*#2|L0Ja9GAl6blOt8DGSgcv7H_XcxnE zz7&B0O0+{lQN{!&z20z0E#zE5bEb2iP>DjXJjQSyUx{E!Li_(?OmMc03wVs@l!Ay& zrr-6ET>Y0-nit2fV(xi7E*!%IR+l!irs@`Kl0v{a)7Zr+TFPE!y%U0}-(brU3Qnnl zPrnPKH7n06+_zXyZ1${Ce8+1@)xicemy6*EJSjS%@3B*#p5_AL`by8Ba$gkRC)>xE znkn{&wA1@nNQ>Y{3w45lc602C;wMZ;mP)N#V|W@r6AJxY!fo>?bac_ko^cWKj8BM5 z9Wvo-tFm zdsWBb6>+eg-2^Y6hMIFaZQj76_@jh%!>*g(t|&Qi>m9Zncl#}yw`@^7$Q0M|?qJVg za|~zk7opc*#hrGp?`BajF?%d~hg_V3Jh|3O|u#*<= z;x+eHT!-DbfjP8^?=~>hTCtZm?0tN8Vn6?ScqdKab{t{LbpqYcZ~zWx@8TK(M}u!> z0LKO#!Uu3aVQJ;s58^|F=EGbiK=Wrl!Wl_iu=o^+ANIz;>M5L~`5%i%i}-kaX%U}_ z*B9}bB0eWt_uJ10Dabrq8P^)IsP~BKWrM5xBvhE literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/config/iamsDbConfig.class b/bin/main/com/urpsys/kccfbat/config/iamsDbConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..e57432bf13556f1cb8aa94e664c71405137c0924 GIT binary patch literal 3656 zcmbtX*>V#{6g@3$WXr;UiOrT30$4Iu6Lt_wjBSDw8H6QFfGo5|EqRP)VP<5kyyPK& zkS|G6sbE4?J|G{J%Iz5~V`+xim2yd=p6+|kxocnl{m-9&0k{G;i3G!G%`$k?vE7!- zUuasbB0R2HW=*eiT^Q~{W!_&TF~o3SU2F*65N4e}sH{uPW7s3j4TfyNa_Zc*9o?+g z9AU^;mh*ztIFi#oUo68T#XP78hnrN&FM_23i%OP(~CrhTI z@dq4Bz~jE7g(pf@)6q!pk?Bl9xq6ekFB^QJyF+JZBOOEm^W>%%cFi5~8J!<8DH=%} zWtfW!(R#I_@hSnhJ~S_gA6gV}lVVE&=^+;#YqK?i$W3T%4Q5vI2 zrSJ((CUJsT#{0hM>0y%|(K3xsaf-4_bENQO50v4jY2Ob)%9T8oUilaYM5J1D1Y$EF z#^)&i<_FX{klqGmf=EtOl0RIpKrRJWppKz;0%ZSs@E;P z^q{-JaAJEE7lkT&PdfjnoF6ttL$B%5A^O7`qS2HixX5r(YY5l1g|~Ly5VkEHzcW=U zoj$eP^1ZP{{tuc}ZqsOt;WDl!afKllmH3^C8FX|S*KnO-tS-G38I%RX^@v0a0utHu z$XOlP{0MFkhd2|cz{w__&GPKBZ(FuQ{#F{d@j3Oi5E1Gt`6wpOVv>o9B1}aU=$$m? zvA}RRsJ4O3VfcA>3EPLULn^z=<}uvGy(GS1m{GypVG*RUgfFSDkOPCfXgYpHkrryO z@rt$`&X1yi`$;U*RT(d`xG6Qdi=1-HmT5ddks4)bX}MTfR5!uSbtD%3A8(NyP+CE^Jot*p-$S-s}Q%h_RdZcg5i`3 z)qg5U;W;#QiB!pLyQE2xIY5(@A)Houb6J?8uI8I^OqE7=CC{M=if$yjn0S%ARkIwU z+uC4~HgNjvW6wRso zh~e@(voACxZmSqF@m{20*h3-VMbjVc`d!r?WrMl5FZveaYZ*Vh#EzI4YeFN&azu~Jt@Nl+A=NLf&Mbh+;2Gtd!RU|7P zk$WHe6cr&-*`}y|J;v9*ohR`GPl@IvdE*(rp5NbL zCY?@@{?WI1{$%DgDm`LBASynIso+qT#3(WZsI*Dc`T&EF)CT~AAYCIF1vosjg|&V# lBLvoox{7~baRLnzOu+E%J5I1Btu6Z4^fs{bB^(!-e*r+|H$4CV literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/config/ncmsDbConfig.class b/bin/main/com/urpsys/kccfbat/config/ncmsDbConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..c3adc14ece80edabdf3f915b62d4b6c832df1c5c GIT binary patch literal 3654 zcmbtX>vGdZ7(HteoH*tdnsDn4D3CbBqTC7?N<#>R)(IgFp+IkId7UU&l9A+)^iO~E z4f-T)r&FNJ^a1)%ot~BKSg|ddOeZ7BEA984^IiAL-~asi7l2RTr;!pkZMwG6@aq1C zZ#*;2YFP$`={i+w*>FtTzg?aV7ishf>|d2@(x^#i*|=X`Rc0WtOF3%-xuWYW8-Crh zoaL$~ZS}(So>7gb41PCeoHfgH9a}j;LEy+j!wD=~Em^)*uBj=8Yr! zq~jY^X$G#hVaQDZW2zCjFDy@0s5UE=fBw?tX{)}XJOQKF(=gk19mDiC>Va!a#RRBe z_jSv$f=_AF*!Yq_-?Up%8SKKoEQXL3*jKb1HP^7q%3G8qE-+klO<7x#o~75#mwmyC zMN7td<99ihz+qCLRc@P5c zXVH({`qzh93?h@k34D~sNzzUZMkBD|Ha_Gsi&HqwbTd6A1Jwo<_-QP3Oq7GAK<8T_ z!6Q9#uXjiiQz9V<863fw&WUm6a>S=AP&$D|v|~!oYbE9T^xd5(eFYi`G6{A>k)5j7 zYnB<73B#d-T^J7qWL=so%CK0smT&kGmeB>vRLIP%o2nibS{iwQ3&}B2t)0en!w+10 zQ!qcak$(T0tTogCE(u&TYtr}Y zGFZ80%X(dTVXLZ?Ta9aWBlN}`{U3F&{JLEmV#~Xl#ub5luf%VaP`9JAxCY`6EvsNb zMP(sytw$n80qNNV>8zG)VE{MCA;|<*JZ&;^IU_e4+LmjPznR5nm|~-g5n-b#^kVWf zA(>bdaVok%r?a??8G%DlwRL5Vz|T8N*baZsE7{n~@r!mK~Gg)M2U70+byv2>W%3>Z5*eFZ)X6K9a^w?XV z;&O!yN_d#YqQIGCq%GvKSi&QLQC|hORaG`>L0qA>bGz8OgJtwV&^nYxla8cxvvdT` zC1hP<3lliNeD7?K(HXbRn6ffQZD~2}yj@gwy~cAxVCikvwgsAD7o^TYKwE8fAe~I#mCuBm;?xK14|K+zx3nGJ78h&h*^BLWO|4A76R@&a#WM~+QFn+zKG_ju=UmY~)O!Fk^P;S~W9c#LfHt-@ zi01X-BXIexsTLa%x0DA%cekft+#@mJ87Ca5Q? z+4<(2o!55dE7BEsr>hJWR29cLN$ujSp5h+|E3VR9>E}TBmLpcjyMC@Ytn$8xI}APr zpZ&R)*!ycJvY&UYKz}^IyWYwT7{)<9NdzMV(=dCv8s&B9DTI&1p~9QosrQe(!I8(q z$8x{pJzgKY!ts|l^9w(u&<3~}0~px^$YBC~ILp1exqFf{y1{bzSQAJQ>pZUu8Xh5m zA1T|%-zO)|4qtqY%PE{4zWy4Yrtk{4<|bd`j=*my{(*(bHl3q{0(-E)15Tw2q%}_~ zAJV;#LW;RaWs@S6<10K4?L3JmcuJZh^v2ithQSc{7T@t1Cw(FG(Dxx}{-3Z(Iu}yD z!QCn1559qXJn<4{n^+Wxa!6t{+O$bx5IF*BZB;CH07fCHb^%5~x=I-h*gx?KE1h6= j46GG(9skJU6lxSq!4B;^Mp%bymsg!{BRikN^O5@(K8ZI6 literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/domain/CommonVO.class b/bin/main/com/urpsys/kccfbat/domain/CommonVO.class new file mode 100644 index 0000000000000000000000000000000000000000..40f2cfd495c568355d1286387453b145be4cce70 GIT binary patch literal 1279 zcmaiy&2G~`6ot8PT2u)~7X`3`{oD^ZvAF(LvrV^`&E{d|BxF)#7HgcRwycI|w zBo;gX4~4jQ>?*;Xh|QdtIrq-}=Fa^7^Ya&gS9o56A<%Y0-=0OErk|(wN5^?TlCgaq z`qB&Ri_rJOV0c+VUZ8p-Z>2qv!PveW-MCIHkiV6amjboH+`5V*FBqRC-ccgQiJT;I zDo}jw1zvnEkh6M2+Pw&`-7<2hm{^4=P#JiE`*!A!+~}PgOu!KD_Z?kT&LiSmL=ohx63v&eDZc-)k=yZ3p){YQ&3a`dnT7<>(y z84RYB5R_6erF1OmDrHc^X=AefmlmG_^&faU;WC%zatcxJpcdz literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/domain/JWTKey.class b/bin/main/com/urpsys/kccfbat/domain/JWTKey.class new file mode 100644 index 0000000000000000000000000000000000000000..2739627c99e0fe43e1317cedf16bd2c03228825a GIT binary patch literal 2111 zcma)7ZBrXn6n<{9n{2}J7J-r$6EvNOmTPhcLr9ZHohOJ=C=ABZxRKG&&@rg|ZZN9Q? z$I*qJD7qC+oeaBZ6hC#KGBvWKqDbfn~1@PV+e0V@w&pOS9ev= z?zq;z{Z+-?OE>BzC+$1kp;$BVCWaNFrP{)NwSJ(`-wweiI6HCQz*z<6(CWofP2p_r zzgk6pJJ;)0es9&P1{fm5aMdYDspBT1Fccy+Pjw<|fJs_m&>+AavA=9sPAyLN3ntQ1 zwUM{V3!)X}+a}(^U>sq*Yhnt+qPt|`6b2PkMR;wsCcwoRsML$L%SeK2)SH!h#MdhgH*YVNWLAU9E=ctlA>m;@ z=P*voY*T`C+1ojo+~Zv1=%Ag+(*$?}Nn!AM7 z8SuPBYp*8O7DW%DD1t}@&KX*V=o3jzevk7fvH0EtzD3|IIE5fdI{E52$^RQi2$nb; ze69lK59W$;FHWYuhOQk={sQ$7diZGaXQxq;{$dg z#J`VmnYu6;xPlBNje|FWEG3;YcLuYRB3{Ra5sMmsqALpZ7Y3pT^Vgs_=!-EvGx;(E z3|!_e9nl54l=pHw{f0E#NmCXj`} zzYzUQMw5%A7Tg#@A+LsBP0frSHJ~QUyjO9JIdxpZJf#rF_aey=YR>TiEKt%s8djh^ zqe3GMN)bA@XIxw7kSO}0Hw~IL+KVchF&`gzfb^z>BGR!Rv2-u7{1`U`?J?F8x48&H zkvF&;WAoqM$5;SL$u}bizC=J0yf^h2pQaKcd?eo5HsT55>onqWQ_m- literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/domain/TokenInfo.class b/bin/main/com/urpsys/kccfbat/domain/TokenInfo.class new file mode 100644 index 0000000000000000000000000000000000000000..29485bc3a9cc20096762d528a22128fca4875bec GIT binary patch literal 16652 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 literal 0 HcmV?d00001 diff --git a/bin/main/com/urpsys/kccfbat/iams/dao/IamsDataDao.class b/bin/main/com/urpsys/kccfbat/iams/dao/IamsDataDao.class new file mode 100644 index 0000000000000000000000000000000000000000..ab2e5afe72f0248e84c0d706911764a9d978a714 GIT binary patch literal 668 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 + + ${HOSTNAME} + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/main/mapper/iamsdb/config/MybatisIamsConfig.xml b/bin/main/mapper/iamsdb/config/MybatisIamsConfig.xml new file mode 100644 index 00000000..dfb0172e --- /dev/null +++ b/bin/main/mapper/iamsdb/config/MybatisIamsConfig.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/main/mapper/iamsdb/sqlmap/iamsDataMapper.xml b/bin/main/mapper/iamsdb/sqlmap/iamsDataMapper.xml new file mode 100644 index 00000000..196eed55 --- /dev/null +++ b/bin/main/mapper/iamsdb/sqlmap/iamsDataMapper.xml @@ -0,0 +1,185 @@ + + + + + + + + + + insert into rg_master + ( + master_id + , use_flag + , set_id + , reg_status + , title + , keyword + , type_div_cd + , erecord_flag + , org_nm + , creat_yyyy + , presv_term_cd + , expt_disuse_yyyy + , oper_read_range_cd + , open_div_cd + , reg_id + , reg_dd + , mod_id + , mod_dd + , mng_org_cd + , page_cnt + , series_id + , digital_yn + , oper_out_range_cd + , mng_org_nm + , asset_type + , tags + , management_code + , interface_id + , set_no + , digital_read_yn + , prsvn_proc_trgt_yn + , dtls_type_div_cd + ) + values + ( + #{master_id } + , #{use_flag } + , #{set_id } + , #{reg_status } + , #{title } + , #{keyword } + , #{type_div_cd } + , #{erecord_flag } + , #{org_nm } + , #{creat_yyyy } + , #{presv_term_cd } + , #{expt_disuse_yyyy } + , #{oper_read_range_cd } + , #{open_div_cd } + , #{reg_id } + , sysdate() + , #{mod_id } + , sysdate() + , #{mng_org_cd } + , #{page_cnt } + , #{series_id } + , #{digital_yn } + , #{oper_out_range_cd } + , #{mng_org_nm } + , #{asset_type } + , #{tag } + , #{management_code } + , #{interface_id } + , #{set_no } + , #{digital_read_yn } + , #{prsvn_proc_trgt_yn } + , '' + ) + + + + insert into j_attachfile + ( + file_mask + , file_id + , file_seq + , file_name + , file_size + , download_count + , atch_type_cd + , digital_read_yn + ) + values + ( + #{file_mask } + , #{file_id } + , #{file_seq } + , #{file_name } + , #{file_size } + , #{download_count } + , #{atch_type_cd } + , #{digital_read_yn } + ) + + + + insert into uare_master + ( + f_id + , org_name + , volume_id + , v_seq + , length + , comp_yn + , encrypt_yn + , org_date + , reg_date + , reg_time + , commit_stat + , session_key + , reg_user_id + , file_key + , f_group + , f_index + , bef_commit_stat + , repository + , clipid + , offset + ) + values + ( + #{f_id } + , #{org_name } + , #{volume_id } + , #{v_seq } + , #{length } + , #{comp_yn } + , #{encrypt_yn } + , #{org_date } + , #{reg_date } + , #{reg_time } + , #{commit_stat } + , #{session_key } + , #{reg_user_id } + , #{file_key } + , #{f_group } + , #{f_index } + , #{bef_commit_stat } + , #{repository } + , #{clipid } + , #{offset } + ) + + + + insert into uac_record + ( + record_id + , type_div_cd + , book_spcm_cpy_yn + ) + values + ( + #{record_id } + , #{type_div_cd } + , 'N' + ) + + + + + + + + + + \ No newline at end of file diff --git a/bin/main/mapper/ncmsdb/config/MybatisNcmsConfig.xml b/bin/main/mapper/ncmsdb/config/MybatisNcmsConfig.xml new file mode 100644 index 00000000..a61361c1 --- /dev/null +++ b/bin/main/mapper/ncmsdb/config/MybatisNcmsConfig.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/main/mapper/ncmsdb/sqlmap/CommonMapper.xml b/bin/main/mapper/ncmsdb/sqlmap/CommonMapper.xml new file mode 100644 index 00000000..4f9b446d --- /dev/null +++ b/bin/main/mapper/ncmsdb/sqlmap/CommonMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/main/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml b/bin/main/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml new file mode 100644 index 00000000..024e71f6 --- /dev/null +++ b/bin/main/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + /* ncmsDataDao.updateResultMultimediaAssets */ + update multimedia_assets + SET iams_tran_yn = #{iams_tran_yn} + , iams_tran_dt = sysdate() + , iams_tran_remark = #{iams_tran_remark} + , iams_tran_master_id = #{iams_tran_master_id} + WHERE id = #{id} + + + + + + \ No newline at end of file diff --git a/bin/main/secrets/UrpSystem.keystore b/bin/main/secrets/UrpSystem.keystore new file mode 100644 index 00000000..39528f7c --- /dev/null +++ b/bin/main/secrets/UrpSystem.keystore @@ -0,0 +1 @@ +aes256.key=52f48aa1c7435bc11bf909d9d7d1d5932f4bacd8184ec5c1eed6d03ee17fe126 \ No newline at end of file diff --git a/bin/test/UrpKeyMng/LibraryTest.class b/bin/test/UrpKeyMng/LibraryTest.class new file mode 100644 index 0000000000000000000000000000000000000000..822d2ac96d90a0c8804306c2677ecff92324f83d GIT binary patch literal 634 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..aa991fce --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..1b6c7873 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..504d8c91 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/7.4.2/userguide/multi_project_builds.html + */ + +rootProject.name = 'ncmsToIamsDataTrans' diff --git a/settings.gradle.bak b/settings.gradle.bak new file mode 100644 index 00000000..8d6054fc --- /dev/null +++ b/settings.gradle.bak @@ -0,0 +1,11 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/7.4.2/userguide/multi_project_builds.html + */ + +rootProject.name = 'urpBaseResource' + diff --git a/src/main/java/com/urpsys/kccfbat/Aes256Test.java b/src/main/java/com/urpsys/kccfbat/Aes256Test.java new file mode 100644 index 00000000..14d12072 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/Aes256Test.java @@ -0,0 +1,124 @@ +package com.urpsys.kccfbat; + +import java.io.InputStream; +import java.security.InvalidKeyException; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; + +/** + * Hello world! + * + */ +public class Aes256Test +{ + private static SecretKey keySpec; // keySpec + private static IvParameterSpec ivSpec; // ivSpec + + + public static void main( String[] args ) + { + InputStream fis = null; + String secretKey = null; + + System.out.println( "Hello World!" ); + + secretKey = "52f48aa1c7435bc11bf909d9d7d1d5932f4bacd8184ec5c1eed6d03ee17fe126"; + + /* + if(args.length !=2 ) + { + System.out.println("Invalid args , args length 2 input "); + System.exit(0); + } + */ + + args = new String[2]; + args[0] = "enc"; + args[1] = "uac_cltr"; + + + try + { + byte[] secretKeyBytes = Hex.decodeHex(secretKey); + + if (secretKeyBytes.length != 32) + { + System.out.println("Invalid key (key length is not valid) "); + System.exit(0); + } + + byte[] ivBytes = new byte[16]; + + System.arraycopy(secretKeyBytes, 0, ivBytes, 0, 16); + + keySpec = new SecretKeySpec(secretKeyBytes, "AES"); + ivSpec = new IvParameterSpec(ivBytes); + + if(args[0].equals("enc")) + { + System.out.println( "암호로 변경" ); + + if (args[1] == null) + { + System.out.println("변경할 문자열이 없습니다."); + } + + String encryptedStr = null; + + try + { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + byte[] encrypted = cipher.doFinal(args[1].getBytes("UTF-8")); + encryptedStr = new String(Base64.encodeBase64(encrypted)); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + System.out.println( "["+ args[1] +"] 암호화로 변경 =============>"+ encryptedStr); + } + else if(args[0].equals("dec")) + { + System.out.println( "평문으로 변경" ); + + if (args[1] == null) + { + System.out.println("변경할 문자열이 없습니다."); + } + + String decryptedStr = null; + + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); + byte[] byteStr = Base64.decodeBase64(args[1].getBytes("UTF-8")); + decryptedStr = new String(cipher.doFinal(byteStr), "UTF-8"); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + System.out.println( "["+ args[1] +"] 평문으로 변경 =============>"+ decryptedStr); + } + + + + } + catch(Exception e) + { + e.printStackTrace(); + } + + + } +} diff --git a/src/main/java/com/urpsys/kccfbat/common/crypto/Aes256Cipher.java b/src/main/java/com/urpsys/kccfbat/common/crypto/Aes256Cipher.java new file mode 100644 index 00000000..3e0d3461 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/common/crypto/Aes256Cipher.java @@ -0,0 +1,145 @@ +package com.urpsys.kccfbat.common.crypto; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.InvalidKeyException; +import java.util.Properties; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; +import org.springframework.core.io.ClassPathResource; + +import com.urpsys.kccfbat.common.util.CommonUtil; + +/** + * aes 256 암호화 클래스 + * + * @author 나혁제 + * @since 2023.02.28 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일         수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.02.28     나혁제         최초작성
+ *
+ * 
+ */ + +public class Aes256Cipher +{ + private SecretKey keySpec; // keySpec + private IvParameterSpec ivSpec; // ivSpec + + /** + * Aes256Cipher 생성자 + * + * @param keyFile 키 파일 위치를 입력 받음 + * @throws IOException 파일 io 시 발생하는 익셉션 + * @throws InvalidKeyException key가 잘못되었을 경우 발생하는 익셉션 + * @throws DecoderException 암호화된 문자열을 decoding할 때 발생하는 익셉션 + */ + public Aes256Cipher() throws IOException, InvalidKeyException, DecoderException + { + + String activeProfile = (CommonUtil.nvl(System.getProperty("spring.profiles.active"))); + + InputStream fis = null; + String secretKey = null; + + try + { + fis = new ClassPathResource("secrets/UrpSystem.keystore").getInputStream(); + + Properties props = new Properties(); + props.load(fis); + secretKey = props.getProperty("aes256.key"); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + finally + { + fis.close(); + } + + byte[] secretKeyBytes = Hex.decodeHex(secretKey); + + if (secretKeyBytes.length != 32) { + throw new InvalidKeyException("Invalid key (key length is not valid) "); + } + + byte[] ivBytes = new byte[16]; + + System.arraycopy(secretKeyBytes, 0, ivBytes, 0, 16); + + keySpec = new SecretKeySpec(secretKeyBytes, "AES"); + ivSpec = new IvParameterSpec(ivBytes); + } + + /** + * encryption 하는 메소드 + * + * @param plainStr 평문을 입력 받음 + * @return 암호화된 문자열 + */ + public String encrypt(String plainStr) + { + if (plainStr == null) { + return null; + } + + String encryptedStr = null; + + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + byte[] encrypted = cipher.doFinal(plainStr.getBytes("UTF-8")); + encryptedStr = new String(Base64.encodeBase64(encrypted)); + } catch (Exception ex) { + ex.printStackTrace(); + } + + return encryptedStr; + } + + /** + * 암호화된 문자열을 복호화하는 메소드 + * + * @param encryptedStr 암호화된 문자열 + * @return 암호화가 해제된 문자열 + */ + public String decrypt(String encryptedStr) + { + if (encryptedStr == null) + { + return null; + } + + String decryptedStr = null; + + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); + byte[] byteStr = Base64.decodeBase64(encryptedStr.getBytes("UTF-8")); + decryptedStr = new String(cipher.doFinal(byteStr), "UTF-8"); + } catch (Exception ex) { + ex.printStackTrace(); + } + + return decryptedStr; + } +} diff --git a/src/main/java/com/urpsys/kccfbat/common/exception/CustomException.java b/src/main/java/com/urpsys/kccfbat/common/exception/CustomException.java new file mode 100644 index 00000000..74f1f592 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/common/exception/CustomException.java @@ -0,0 +1,114 @@ +package com.urpsys.kccfbat.common.exception; + +import java.sql.SQLSyntaxErrorException; + +import lombok.Getter; + +/** + * Custom exception 클래스 + * + * @author 나혁제 + * @since 2023.02.28 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일        수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.02.28    나혁제         최초작성
+ *
+ * 
+ */ + +public class CustomException extends Exception +{ + private static final long serialVersionUID = 3559302713942492181L; + + @Getter + private String errorCode; + + @Getter + private String errorMsg; + + /** + * 생성자(throwable를 받아서 exception 종류에 따라 에러 코드 정의하는 클래스) + * 에러코드 처리 부분은 향후 db에서 에러코드 읽어와서 매핑하는 것으로 + * 변경 가능성 있음 + * @param throwable + */ + public CustomException(Throwable throwable) { + Throwable rootThrowable = getRootCause(throwable); + + // TODO 에러 코드는 상세 정의해서 define 해야 함 + if(rootThrowable instanceof SQLSyntaxErrorException) { + this.errorCode = "100"; + this.errorMsg = "SQL 오류"; + } else if(rootThrowable instanceof ArithmeticException) { + this.errorCode = "200"; + this.errorMsg = "연산 오류"; + } else { + this.errorCode = "900"; + this.errorMsg = "Unknown Error"; + } + } + + /** + * 생성자(에러메시지만 받을 경우 에러코드를 0을 default로 세팅) + * @param errorMsg + */ + public CustomException(String errorMsg) { + super(errorMsg); + this.errorCode = "0"; + this.errorMsg = errorMsg; + } + + /** + * 생성자(errorcode, errmsg를 받아 세팅, 소스코드에서 편하게 사용하기 위해 + * 에러코드를 int 값으로 받으면 string으로 변환하여 저장) + * @param errorCode + * @param errorMsg + */ + public CustomException(int errorCode, String errorMsg) { + super(errorMsg); + this.errorCode = String.valueOf(errorCode); + this.errorMsg = errorMsg; + } + + /** + * 생성자(에러코드, 에러메시지를 받아 세팅) + * @param errorCode + * @param errorMsg + */ + public CustomException(String errorCode, String errorMsg) { + super(errorMsg); + this.errorCode = errorCode; + this.errorMsg = errorMsg; + } + + /** + * stack에서 에러코드 중 root cause를 찾아내는 메소드 + * @param throwable + * @return + */ + private Throwable getRootCause(Throwable throwable) { + Throwable cause = throwable.getCause(); + + if (cause == null) { + return throwable; + } + + while (true) { + + if(cause.getCause() == null) { + break; + } else { + cause = cause.getCause(); + } + } + + return cause; + } +} diff --git a/src/main/java/com/urpsys/kccfbat/common/util/CommonUtil.java b/src/main/java/com/urpsys/kccfbat/common/util/CommonUtil.java new file mode 100644 index 00000000..fe2b0869 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/common/util/CommonUtil.java @@ -0,0 +1,503 @@ +package com.urpsys.kccfbat.common.util; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.SimpleTimeZone; +import java.util.Vector; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.http.HttpHeaders; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.oauth2.provider.token.RemoteTokenServices; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.urpsys.kccfbat.common.exception.CustomException; +import com.urpsys.kccfbat.domain.TokenInfo; + +/** + * 공통 유틸리티를 모아둔 클래스 + * + * @author 나혁제 + * @since 2023.02.28 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일        수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.02.28    나혁제         최초작성
+ *
+ *      
+ */ + +public class CommonUtil +{ + /** + * nvl 메소드 + * @param inputStr + * @return + */ + public static String nvl(String inputStr) { + return (inputStr != null) ? inputStr.trim() : ""; + } + + /** + * nvl 메소드 + * @param inputStr + * @param defaultValue + * @return + */ + public static String nvl(String inputStr, String defaultValue) { + return nvl(inputStr).contentEquals("") ? defaultValue : inputStr.trim(); + } + + /** + * nvl 메소드 + * @param inputObj + * @return + */ + public static String nvl(Object inputObj) { + return (inputObj != null) ? String.valueOf(inputObj).trim() : ""; + } + + /** + * long 타입의 시간을 입력받아 날짜 형태로 변환해서 리턴해주는 함수 + * + * @param longTime long type 시간 + * @param dateFormat 변환할 포맷 + * @return 변환된 날짜 String + * @throws SystemException + */ + public static String getTimeString(long longTime, String dateFormat) throws CustomException { + SimpleDateFormat sdf = new SimpleDateFormat(dateFormat, Locale.KOREA); + + if (longTime < 0) + { + return ""; + } + else { + try { + return sdf.format(new Date(longTime)); + } catch (Exception e) { + throw new CustomException("Date 변환 오류"); + } + } + } + + /** + * 현재(한국기준) 시간정보를 얻는다.
+ * (예) 입력파리미터인 format string에 "yyyyMMddhh"를 셋팅하면 1998121011과 같이 Return.
+ * (예) format string에 "yyyyMMddHHmmss"를 셋팅하면 19990114232121과 같이 + * 0~23시간 타입으로 Return.
+ * String CurrentDate = CtosUtil2.getKST("yyyyMMddHH");
+ * @param format 얻고자하는 현재시간의 Type + * @return str 현재 한국 시간. + */ + public static String getKST(String format) + { + //1hour(ms) = 60s * 60m * 1000ms + int millisPerHour = 60 * 60 * 1000; + SimpleDateFormat fmt= new SimpleDateFormat(format); + + SimpleTimeZone timeZone = new SimpleTimeZone(9*millisPerHour,"KST"); + fmt.setTimeZone(timeZone); + + long time=System.currentTimeMillis(); + String str=fmt.format(new java.util.Date(time)); + return str; + } + + /** + * 입력한 날짜 기준으로 몇일 전,후 (주의)입력날짜는 구분자가 없는 string형 + * + * @param date + * string date (19991002) + * @param Day + * 기준이 되는 시간 + * @return String + */ + public static String getDatewithSpan(String date, long Day) + { + /* + * int millisPerHour = 60 * 60 * 1000; SimpleDateFormat fmt= new + * SimpleDateFormat("yyyy/MM/dd"); SimpleTimeZone timeZone = new + * SimpleTimeZone(9*millisPerHour,"KST"); fmt.setTimeZone(timeZone); + * + * int year = Integer.valueOf(date.substring(0,4)).intValue(); int month + * = Integer.valueOf(date.substring(4,6)).intValue(); int day = + * Integer.valueOf(date.substring(6,8)).intValue(); + * + * java.util.Calendar aDay = Calendar.getInstance(); + * aDay.set(year+1900,month,day); java.util.Calendar bDay + * =Calendar.getInstance(); bDay.set(1970+1900,1,1); java.util.Date cDay + * = new java.util.Date((aDay.getTime()).getTime() - + * (bDay.getTime()).getTime() + ((Day+1)*86400000) ); + * + * return fmt.format(cDay); + */ + // 2006-09-04 7:03오후 오동원수정 + String vFORMAT = "yyyy/MM/dd"; + return getDatewithSpan(date, Day, "D", vFORMAT); + + } + + /** + * 입력한 날짜 기준으로 몇(일,시간,분) 전,후 (주의)입력날짜는 구분자가 없는 string형
+ * + * @param date + * string date (20000315/2000031509/200003150915) + * @param unit + * long unit: 몇(일,시간,분) 전, 몇(일,시간,분) 후 + * @param type + * String type: D:Day H:Hour M:Minute + * @return String 계산된 문자열의 값. + */ + public static String getDatewithSpan(String date, long unit, String type, String strFormatType) + { + /* + * String formatType = strFormatType; int ihour = 0; int itime = 0; + * + * long dhm = 24 * 60 * 60 * 1000; + * + * if (type.equals("D")) { dhm =dhm + unit * 24 * 60 * 60 * 1000; } else + * if (type.equals("H")){ dhm =dhm + unit * 60 * 60 * 1000; } else if + * (type.equals("M")){ dhm =dhm + unit * 60 * 1000; } else{ return type + * + "은 부적절한 Type값입니다"; } + * + * switch (date.length()){ case (8): if (type.equals("H") || + * type.equals("M")) { return "HM-ERROR"; } + * + * break; case (10): if (type.equals("M")) { return "M-ERROR"; } + * + * ihour = Integer.valueOf(date.substring(8,10)).intValue(); break; case + * (12): + * + * ihour = Integer.valueOf(date.substring(8,10)).intValue(); itime = + * Integer.valueOf(date.substring(10,12)).intValue(); break; default: + * return "date Length Error"; } + * + * int millisPerHour = 60 * 60 * 1000; SimpleDateFormat fmt= new + * SimpleDateFormat(formatType); SimpleTimeZone timeZone = new + * SimpleTimeZone(9*millisPerHour,"KST"); fmt.setTimeZone(timeZone); + * + * int iyear = Integer.valueOf(date.substring(0,4)).intValue(); int + * imonth = Integer.valueOf(date.substring(4,6)).intValue(); int iday = + * Integer.valueOf(date.substring(6,8)).intValue(); java.util.Calendar + * aDay = Calendar.getInstance(); + * aDay.set(iyear+1900,imonth,iday,ihour,itime); java.util.Calendar bDay + * = Calendar.getInstance(); bDay.set(1970+1900,1,1,9,0); java.util.Date + * cDay = new java.util.Date((aDay.getTime()).getTime() - + * (bDay.getTime()).getTime() + dhm); return fmt.format(cDay); + */ + // 2006-09-04 7:03오후 오동원수정 + String formatType = strFormatType; + int ihour = 0; + int itime = 0; + if(!(type.equals("D") || type.equals("H") || type.equals("M"))) + { + return type + "은 부적절한 Type값입니다"; + } + + switch(date.length()) + { + case (8): + if(type.equals("H") || type.equals("M")) + { + return "HM-ERROR"; + } + break; + case (10): + if(type.equals("M")) + { + return "M-ERROR"; + } + ihour = Integer.parseInt(date.substring(8, 10)); + // ihour = Integer.valueOf(date.substring(8, 10)).intValue(); + break; + case (12): + ihour = Integer.parseInt(date.substring(8, 10)); + itime = Integer.parseInt(date.substring(10, 12)); + + // ihour = Integer.valueOf(date.substring(8, 10)).intValue(); + // itime = Integer.valueOf(date.substring(10, 12)).intValue(); + break; + default: + return "date Length Error"; + } + int iyear = Integer.parseInt(date.substring(0, 4)); + int imonth = Integer.parseInt(date.substring(4, 6)); + int iday = Integer.parseInt(date.substring(6, 8)); + + /* + int iyear = Integer.valueOf(date.substring(0, 4)).intValue(); + int imonth = Integer.valueOf(date.substring(4, 6)).intValue(); + int iday = Integer.valueOf(date.substring(6, 8)).intValue(); + */ + + int imonth1 = imonth - 1; // 달은 0달부터 시작한다. + java.util.Calendar zDay = Calendar.getInstance(); + zDay.set(iyear, imonth1, iday, ihour, itime); + + if(type.equals("D")) + { + zDay.add(Calendar.DATE, (int) unit); + } + else if(type.equals("H")) + { + zDay.add(Calendar.HOUR_OF_DAY, (int) unit); + } + else if(type.equals("M")) + { + zDay.add(Calendar.MINUTE, (int) unit); + } + else + { + return type + "은 부적절한 Type값입니다"; + } + java.util.Date z1Day = zDay.getTime(); + java.text.SimpleDateFormat fmt2 = new java.text.SimpleDateFormat(formatType); + return fmt2.format(z1Day); + + } + + /** + * 현재 시간을 기준으로 몇 일후 시간 시간의 형태는 (yyyy/mm/dd) + * + * @param day + * 더하려는 날짜 + * @return str 현재 시간에 입력 시간을 더한 DATE형 시간 + */ + public static String getDatewithSpan(long day) + { + /* + * int millisPerHour = 60 * 60 * 1000; SimpleDateFormat fmt= new + * SimpleDateFormat("yyyy/MM/dd"); SimpleTimeZone timeZone = new + * SimpleTimeZone(9*millisPerHour,"KST"); fmt.setTimeZone(timeZone); + * + * long time = System.currentTimeMillis(); long span = ( 60 * 60 * 1000 + * * 24 ) * day; //하루에 대한 millisecond... long time2 = time + span; + * String str=fmt.format(new java.util.Date(time2)); + * + * return str; + */ + String strSYSDATE = CommonUtil.getKST("yyyyMMddHH"); // 지금 시간 + String vFORMAT = "yyyy/MM/dd"; + return getDatewithSpan(strSYSDATE, day, "D", vFORMAT); + + } + + public static long stol(String str) + { + if(str == null ) return 0; + return (Long.valueOf(str).longValue()); + } + + /** + 문자열을 중 특정 문자열을 변환시킨다. + @version 1.0 + @author Yoon Su-wan + @since JDK1.0 + @param targeter 대상문자열 + @param target_str 변환될 대상문자열 + @param replace_str 변환될 문자열 + @return target_str이 replace_str로 변환된 문자열 + */ + public static String getReplacedString(String targeter, String target_str, String replace_str) + { + if( targeter == null + || target_str == null + || replace_str == null ) + return "debug : parameter value is null"; + + if(target_str.length() == 0) + return targeter; + + StringBuffer str = new StringBuffer(); + int start_ptr = 0; + int current_ptr = 0; + int increment_size = replace_str.length(); + if(increment_size == 0 ) increment_size = 1; + + while((current_ptr = targeter.indexOf(target_str, start_ptr)) != -1) + { + str.append(targeter.substring(start_ptr, current_ptr)); + str.append(replace_str); + start_ptr = current_ptr + increment_size; + if(start_ptr >= targeter.length()) + break; + }//end while + + if(start_ptr == 0) + return targeter; + + if(start_ptr < targeter.length()) + str.append(targeter.substring(start_ptr)); + + return str.toString(); + }//getReplacedString(String targeter, String target_str, String replace_str) + + /** + 받은메세지에서 v_s1값을 찾아서 v_s2로 대치한다. + @version 1.0 + @author Yoon Su-wan + @since JDK1.0 + @param v_msg 대상문자열 + @param v_s1 변환될 대상문자열 + @param v_s2 변환될 문자열 + @return v_s1이 v_s2 변환된 문자열 + */ + + public static String getReplacedString2(String v_msg, String v_s1, String v_s2) + { + int idx = v_msg.indexOf(v_s1); + + if (idx == -1) return v_msg; + else + { + try + { + return v_msg.substring(0, idx) + v_s2 + v_msg.substring(idx+2); + } catch (Exception e) + { + return v_msg.substring(0, idx) + v_s2; + } + } + + } + + public static String getReplacedString3(String sStr, String n1, String n2) + { + int iTmp = 0; + if (sStr == null) return ""; + + String sTmp = sStr; + StringBuffer sbSave = new StringBuffer(); + sbSave.append(""); + while (sTmp.indexOf(n1) > -1) + { + iTmp = sTmp.indexOf(n1); + sbSave.append(sTmp.substring(0,iTmp)); + sbSave.append(n2); + sTmp = sTmp.substring(iTmp + n1.length()); + } + sbSave.append(sTmp); + return sbSave.toString(); + } + + public static Vector arrToDouVector(String strArray, String strDelimt) + { + String[] stArray = strArray.split(strDelimt); + + double[] dArray = Arrays.stream(stArray).mapToDouble(Double::parseDouble).toArray(); + Vector vReturn = new Vector(); + + if(dArray==null) return vReturn; + + for(double dTemp: dArray) + { + vReturn.add(dTemp); + } + + return vReturn; + + } + + public static String arrListToString(List list) + { + String strReturn=""; + + if(list == null ) return ""; + + for(int i=0; i"+strTemp); + // double dou = Double.parseDouble(strTemp); + // strReturn = strReturn+","+dou; + strReturn = strReturn+","+strTemp; + } + + strReturn = strReturn.substring(1); + + return strReturn; + + } + + /** + Map 데이터를 JSONObject로 변환. + @version 1.0 + @author Yoon Su-wan + @since JDK1.0 + @param v_msg Map + @return JSONObject + */ + public static JSONObject getJsonFromMap(Map map) throws JSONException + { + JSONObject jsonData = new JSONObject(); + + for (String key : map.keySet()) + { + Object value = map.get(key); + if (value instanceof Map) + { + value = getJsonFromMap((Map) value); + } + jsonData.put(key, value); + } + return jsonData; + } + + public static TokenInfo getAccessTokenInfo(HttpServletRequest request) + { + TokenInfo tokenInfo = null; + String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); + RemoteTokenServices tokenServices = new RemoteTokenServices(); + + if(StringUtils.startsWithIgnoreCase(authorization, "Bearer")) + { + /* + * FieldNamingPolicy 옵션 + * IDENTITY : 변경 없음 + * LOWER_CASE_WITH_DASHES : '-' 붙이기 + * LOWER_CASE_WITH_DOTS : '.' 붙이기 + * LOWER_CASE_WITH_UNDERSCORES : '_' 붙이기 + * UPPER_CAMEL_CASE : 첫문자 대문자로 + * UPPER_CAMEL_CASE_WITH_SPACES : 첫문자 대문자 + ' ' 공택붙이기 + * + */ + + String strTocken = ""; + strTocken = StringUtils.replace(authorization, "Bearer ",""); + strTocken = StringUtils.replace(authorization, "bearer ",""); + + Jwt jwt = JwtHelper.decode(strTocken); + + // Jwt jwt = JwtHelper.decode(StringUtils.replace(authorization, "Bearer ","")); + // Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); // snakecase to camelcase + Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).create(); // snakecase to camelcase + + tokenInfo = gson.fromJson(jwt.getClaims(), TokenInfo.class); + } + + return tokenInfo; + } + + + + +} diff --git a/src/main/java/com/urpsys/kccfbat/common/util/CommonUtils.java b/src/main/java/com/urpsys/kccfbat/common/util/CommonUtils.java new file mode 100644 index 00000000..4b2352cf --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/common/util/CommonUtils.java @@ -0,0 +1,76 @@ +package com.urpsys.kccfbat.common.util; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +import io.undertow.util.DateUtils; + +/** + * 통합자료관리시스펨 공통 유틸리티를 모아둔 클래스 + * + * @author 나혁제 + * @since 2026.03.03 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일        수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2026.03.03    나혁제         최초작성
+ *
+ *      
+ */ + +public class CommonUtils +{ + /** + *
+	 * - PK로 사용 가능한 유니크 키 생성
+	 * - UUID 32byte + prefix 3byte = 총 35byte
+	 * 
+ * + * @param prefix 생성된 UUID을 구분해줄수 있는 업무코드 + * @return 인자값으로 입력된 prefix와 UUID를 합친 문자열 ex) + * LR-356015096E2542779E11C946DB93B952 + */ + public static String getUUID(String prefix) + { + return prefix.toUpperCase() + "-" + UUID.randomUUID().toString().toUpperCase().replaceAll("-", ""); + } + + public static String getUUID() + { + return UUID.randomUUID().toString().toUpperCase().replaceAll("-", ""); + } + + public static String getFileMask() + { + return getSysDate("yyyyMMddHHmmss") + CommonUtils.getUUID(); + } + + /** + * 날짜 입력양식을 전달받아 현재 날짜를 반환. + * @param pattern 입력 양식. + * @return String 날짜 입력 양식. + */ + public static String getSysDate(String pattern) + { + return getDateString(new Date(), pattern); + } + + /** + * Date 객체와 입력양식을 전달받아 날짜를 반환. + * @param date Date 객체. + * @param pattern 입력 양식. + * @return String 날짜. + */ + public static String getDateString(Date date, String pattern) + { + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + return sdf.format(date); + } +} diff --git a/src/main/java/com/urpsys/kccfbat/common/util/DataSourceUtil.java b/src/main/java/com/urpsys/kccfbat/common/util/DataSourceUtil.java new file mode 100644 index 00000000..840be922 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/common/util/DataSourceUtil.java @@ -0,0 +1,113 @@ +package com.urpsys.kccfbat.common.util; + +import java.sql.Connection; + +import javax.sql.DataSource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.springframework.core.env.Environment; +import org.springframework.core.io.Resource; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import com.urpsys.kccfbat.common.crypto.Aes256Cipher; +import com.urpsys.kccfbat.common.exception.CustomException; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +/** + * Datasource 생성하는 유틸리티 + * + * @author 나혁제 + * @since 2023.02.28 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일        수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.02.28    나혁제         최초작성
+ *
+ * 
+ */ + +public class DataSourceUtil +{ + /** + * 데이터 소스 만드는 메소드 + * @param dataSourceName + * @param env + * @param cipher + * @return + */ + public static DataSource createDataSource(String dataSourceName, Environment env, Aes256Cipher cipher) + { + HikariConfig config = new HikariConfig(); + + config.setDriverClassName (env.getProperty(dataSourceName + ".driverClassName" )); + config.setJdbcUrl (env.getProperty(dataSourceName + ".jdbcUrl" )); + + config.setUsername (cipher.decrypt(env.getProperty(dataSourceName + ".username"))); + config.setPassword (cipher.decrypt(env.getProperty(dataSourceName + ".password"))); + + config.setAutoCommit(false); + + config.setMaximumPoolSize (Integer.parseInt(env.getProperty(dataSourceName + ".maximumPoolSize" ))); + config.setMinimumIdle (Integer.parseInt(env.getProperty(dataSourceName + ".minimumIdle" ))); + config.setConnectionTimeout (Long.parseLong (env.getProperty(dataSourceName + ".connectionTimeout" ))); + config.setIdleTimeout (Long.parseLong (env.getProperty(dataSourceName + ".idleTimeout" ))); + + config.addDataSourceProperty("cachePrepStmts" , "true"); + config.addDataSourceProperty("prepStmtCacheSize" , "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit" , "2048"); + + return new HikariDataSource(config); + } + + /** + * SqlSessionFactory 만드는 메소드 + * @param dataSource + * @param configLocation + * @param mapperLocation + * @return + * @throws CustomException + */ + public static SqlSessionFactory createSqlSessionFactory(DataSource dataSource, Resource configLocation, + Resource[] mapperLocation) throws CustomException + { + SqlSessionFactory sqlSessionFactory; + + try { + SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); + sessionFactoryBean.setDataSource(dataSource); + sessionFactoryBean.setConfigLocation(configLocation); + sessionFactoryBean.setMapperLocations(mapperLocation); + + sqlSessionFactory = sessionFactoryBean.getObject(); + } + catch (Exception ex) + { + throw new CustomException(ex.getMessage()); + } + + return sqlSessionFactory; + } + + /** + * 트랜잭션 처리 메소드 + * @param dataSource + * @return + */ + public static DataSourceTransactionManager createTxManager(DataSource dataSource) + { + DataSourceTransactionManager txManager = new DataSourceTransactionManager(dataSource); + txManager.setGlobalRollbackOnParticipationFailure(false); + + return txManager; + } + + //end method +} diff --git a/src/main/java/com/urpsys/kccfbat/common/util/ResultData.java b/src/main/java/com/urpsys/kccfbat/common/util/ResultData.java new file mode 100644 index 00000000..217ab5d5 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/common/util/ResultData.java @@ -0,0 +1,222 @@ +package com.urpsys.kccfbat.common.util; + +import java.util.Date; + +import org.springframework.http.ResponseEntity; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +/** + * Result Data 처리을 하는 유틸리티 + * + * @author 나혁제 + * @since 2023.02.28 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일        수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.02.28    나혁제         최초작성
+ *
+ * 
+ */ + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ResultData +{ + private Object data; + private Integer status = 200; + private Integer totalCount; + private String code = "OK"; + private String message = "Success"; + private Date timestamp = new Date(); + + /** + * + */ + public ResultData() + { + } + + /** + * @param messageOrCode + */ + public ResultData(Object data) + { + this.data = data; + } + + /** + * @param messageOrCode + */ + public ResultData(Object data, String code) + { + this.data = data; + this.code = code; + this.message = ""; + // this.message = MsgUtil.getMessage(code); + } + + /** + * Method Name : setCodeAndMessage + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public void setCodeAndMessage(String code, Object... params) + { + this.setCode(code); + this.setMessage(""); + // this.setMessage(MsgUtil.getMessage(code, params)); + } + + /** + * Method Name : ok + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity ok(Object data) + { + var resultData = new ResultData(); + resultData.setData(data); + + return ResponseEntity.ok(resultData); + } + + /** + * Method Name : ok + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity ok(ResultData resultData) + { + return ResponseEntity.ok(resultData); + } + + /** + * Method Name : ok + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity ok(int totalCount, Object data) + { + var resultData = new ResultData(); + resultData.setData(data); + resultData.setTotalCount(totalCount); + + return ResponseEntity.ok(resultData); + } + + /** + * Method Name : ok + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity ok(Object data, String code) + { + var resultData = new ResultData(); + resultData.setData(data); + resultData.setCode(code); + resultData.setMessage(""); + // resultData.setMessage(MsgUtil.getMessage(code)); + + return ResponseEntity.ok(resultData); + } + + /** + * Method Name : ok + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity ok(int totalCount, Object data, String code) + { + var resultData = new ResultData(); + resultData.setData(data); + resultData.setCode(code); + resultData.setTotalCount(totalCount); + resultData.setMessage(""); + // resultData.setMessage(MsgUtil.getMessage(code)); + + return ResponseEntity.ok(resultData); + } + + /** + * Method Name : ok + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity ok(Object data, String code, Object... params) + { + var resultData = new ResultData(); + resultData.setData(data); + resultData.setCode(code); + resultData.setMessage(""); + // resultData.setMessage(MsgUtil.getMessage(code, params)); + + return ResponseEntity.ok(resultData); + } + + /** + * Method Name : okMessage + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity okMessage(String code) + { + var resultData = new ResultData(); + resultData.setCode(code); + resultData.setMessage(""); + // resultData.setMessage(MsgUtil.getMessage(code)); + + return ResponseEntity.ok(resultData); + } + + /** + * Method Name : okMessage + * Description : + * + * @param messageOrCode 지정된 파라미터 값으로 서비스 호출시 사용 + * @param params 지정된 파라미터 값으로 서비스 호출시 사용 + * @return ResultData + */ + public static ResponseEntity okMessage(String code, Object... params) + { + var resultData = new ResultData(); + resultData.setCode(code); + resultData.setMessage(""); + + // resultData.setMessage(MsgUtil.getMessage(code, params)); + + return ResponseEntity.ok(resultData); + } +} diff --git a/src/main/java/com/urpsys/kccfbat/config/EncryptConfig.java b/src/main/java/com/urpsys/kccfbat/config/EncryptConfig.java new file mode 100644 index 00000000..1dd03f66 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/config/EncryptConfig.java @@ -0,0 +1,38 @@ +package com.urpsys.kccfbat.config; + +import java.io.IOException; +import java.security.InvalidKeyException; +import org.apache.commons.codec.DecoderException; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.urpsys.kccfbat.common.crypto.Aes256Cipher; + +/** + * 암호화 유틸리티를 등록하는 클래스 + * + * @author 나혁제 + * @since 2023.02.28 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일       수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.02.28   나혁제         최초작성
+ *
+ * 
+ */ + +@Configuration +public class EncryptConfig +{ + @Bean(name="aes256Cipher") + public Aes256Cipher aes256Cipher() throws InvalidKeyException, IOException, DecoderException + { + return new Aes256Cipher(); + } +} diff --git a/src/main/java/com/urpsys/kccfbat/config/Oauth2ResourceConfig.java b/src/main/java/com/urpsys/kccfbat/config/Oauth2ResourceConfig.java new file mode 100644 index 00000000..79eefb5a --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/config/Oauth2ResourceConfig.java @@ -0,0 +1,166 @@ +package com.urpsys.kccfbat.config; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + +import com.google.gson.Gson; + +import kong.unirest.JsonNode; +import kong.unirest.Unirest; +import lombok.extern.slf4j.Slf4j; + +import com.urpsys.kccfbat.common.exception.CustomException; +import com.urpsys.kccfbat.domain.CommonVO; +import com.urpsys.kccfbat.domain.JWTKey; +import com.urpsys.kccfbat.service.CommonService; + +/** + * Resource 서버 기본세팅 + * + * @author 나혁제 + * @since 2023.02.28 + * @version 1.0.0 + * @see + * @comment : + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일       수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.02.28  나혁제         최초작성
+ *
+ * 
+ */ + +@Slf4j +@Configuration +public class Oauth2ResourceConfig extends ResourceServerConfigurerAdapter +{ + @Autowired + CommonService commonService; // 공통 서비스 + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception + { + resources.resourceId("event"); // 최소한 리소스ID 정도는 설정 필요 + } + + @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}") + private String publicKeyUri; // key 정보를 받아오기 위한 인증서버 URL 선언 + + @Override + public void configure(HttpSecurity http) throws Exception + { + http.authorizeRequests().mvcMatchers("/test/**" ).permitAll(); // test API + http.authorizeRequests().mvcMatchers("/api/**" ).permitAll(); // test API + http.authorizeRequests().mvcMatchers("/server/**" ).permitAll(); // test API + + http.authorizeRequests().mvcMatchers("/swagger-resources/**" ).permitAll(); // api 문서 관련 + http.authorizeRequests().mvcMatchers("/swagger-ui**" ).permitAll(); // api 문서 관련 + http.authorizeRequests().mvcMatchers("/swagger-ui/**" ).permitAll(); // api 문서 관련 + http.authorizeRequests().mvcMatchers("/webjars/**" ).permitAll(); // api 문서 관련 + http.authorizeRequests().mvcMatchers("/v2/**" ).permitAll(); // api 문서 관련 + http.authorizeRequests().mvcMatchers("/swagger/**" ).permitAll(); // api 문서 관련 + + http.authorizeRequests().anyRequest().authenticated(); + } + + @Bean + public TokenStore tokenStore() + { + log.info(">>>>>>>>>> Oauth2ResourceConfig tokenStore <<<<<<<<<<"); + log.info("<<<<<<<<<< Oauth2ResourceConfig tokenStore >>>>>>>>>>"); + + return new JwtTokenStore(jwtAccessTokenConverter()); + } + + @Bean + public JwtAccessTokenConverter jwtAccessTokenConverter() + { + log.info(">>>>>>>>>> Oauth2ResourceConfig jwtAccessTokenConverter <<<<<<<<<<"); + + try + { + /*** * 직접 oauth 서버를 호출하여 공개키 읽어서 jwt 디코드 키 등록 */ + JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); + + // 보안키 획득 + String strPrivKey = getPublicKeyValue(publicKeyUri); + + // + if(strPrivKey==null || strPrivKey.equals("")) + { + throw new CustomException("보안키 획득 실패1"); + + } + + converter.setVerifierKey(strPrivKey); + + log.info("<<<<<<<<<< Oauth2ResourceConfig jwtAccessTokenConverter >>>>>>>>>>"); + + return converter; + } + catch (Exception e) + { + log.info("보안키 획득 실패2"); + log.info("<<<<<<<<<< Oauth2ResourceConfig jwtAccessTokenConverter >>>>>>>>>>"); + + return new JwtAccessTokenConverter(); + } + } + + private String getPublicKeyValue(String uriKey) + { + log.info(">>>>>>>>>> Oauth2ResourceConfig getPublicKeyValue <<<<<<<<<<"); + + String strReturn = ""; + JsonNode response = null; + + try + { + response = Unirest.get(uriKey) + .asJson().getBody(); + + strReturn = response.toString(); + } + catch(Exception e) + { + return strReturn; + } + + + if(StringUtils.isEmpty(strReturn)) + { + strReturn =""; + } + else + { + strReturn =new Gson().fromJson(response.toString(), JWTKey.class).getValue();; + } + + log.info("<<<<<<<<<< Oauth2ResourceConfig getPublicKeyValue : {} >>>>>>>>>>", strReturn); + + return strReturn; + + + } + + + + + + + +} diff --git a/src/main/java/com/urpsys/kccfbat/config/SwaggerConfig.java b/src/main/java/com/urpsys/kccfbat/config/SwaggerConfig.java new file mode 100644 index 00000000..0e757d43 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/config/SwaggerConfig.java @@ -0,0 +1,124 @@ +package com.urpsys.kccfbat.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.GrantType; +import springfox.documentation.service.OAuth; +import springfox.documentation.service.Parameter; +import springfox.documentation.service.ResourceOwnerPasswordCredentialsGrant; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * API 문서 처리 config 클래스 + * + * @author 나혁제 + * @since 2023.07.31 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일       수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2023.07.31.  나혁제         최초작성
+ *
+ * 
+ */ + +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + private static final String API_NAME = "uWorks Test API"; + private static final String API_VERSION = "0.0.1"; + private static final String API_DESCRIPTION = "uWorks Test API 명세서"; + + @Bean + public Docket api() + { + Parameter parameterBuilder = new ParameterBuilder() + .name(HttpHeaders.AUTHORIZATION) + .description("Access Tocken") + .modelRef(new ModelRef("string")) + .parameterType("header") + .required(false) + .build(); + + List globalParamters = new ArrayList<>(); + globalParamters.add(parameterBuilder); + + return new Docket(DocumentationType.SWAGGER_2) + .globalOperationParameters(globalParamters) + .apiInfo(apiInfo()) +// .ignoredParameterTypes(AuthPrincipal.class) + .select() + .apis(RequestHandlerSelectors.basePackage("com.urpsys.baseapi")) + .paths(PathSelectors.any()) + .build() + .securityContexts(Collections.singletonList(securityContext())) + .securitySchemes(Arrays.asList(securitySchema())) + ; + } + + public ApiInfo apiInfo() + { + return new ApiInfoBuilder() + .title(API_NAME) + .version(API_VERSION) + .description(API_DESCRIPTION) + .build(); + } + + private SecurityContext securityContext() + { + return SecurityContext.builder() + .securityReferences(defaultAuth()) + .build(); + } + + private List defaultAuth() + { + final AuthorizationScope[] authorizationScopes = new AuthorizationScope[] + { + new AuthorizationScope("read", "read all"), + new AuthorizationScope("write", "write all") + }; + + return Collections.singletonList(new SecurityReference("oauth2", authorizationScopes)); + } + + private OAuth securitySchema() + { + final List authorizationScopeList = new ArrayList<>(2); + + authorizationScopeList.add(new AuthorizationScope("read", "read all")); + authorizationScopeList.add(new AuthorizationScope("write", "access all")); + + final List grantTypes = new ArrayList<>(1); + // 토큰 end point (http://localhost:3000/oauth/token) + grantTypes.add(new ResourceOwnerPasswordCredentialsGrant("http://localhost:9011/oauth/token")); + + return new OAuth("oauth2", authorizationScopeList, grantTypes); + } + +} \ No newline at end of file diff --git a/src/main/java/com/urpsys/kccfbat/config/iamsDbConfig.java b/src/main/java/com/urpsys/kccfbat/config/iamsDbConfig.java new file mode 100644 index 00000000..ba68852b --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/config/iamsDbConfig.java @@ -0,0 +1,112 @@ +package com.urpsys.kccfbat.config; + +import java.io.IOException; +import java.sql.Connection; + +import javax.sql.DataSource; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.urpsys.kccfbat.common.crypto.Aes256Cipher; +import com.urpsys.kccfbat.common.exception.CustomException; +import com.urpsys.kccfbat.common.util.DataSourceUtil; + +/** + * iams(통합자료관리시스템) db config 클래스 + * + * @author 나혁제 + * @since 2026.02.24 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일        수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2026.02.24    나혁제         최초작성
+ *
+ * 
+ */ + +@Configuration +@EnableTransactionManagement +@MapperScan(value="com.urpsys.kccfbat.iams.dao", sqlSessionFactoryRef="iamsSqlSessionFactory") +public class iamsDbConfig +{ + @Autowired + private Environment env; + + @Autowired + private Aes256Cipher aes256Cipher; + + + /** + * 데이터소스 등록하는 메소드 + * @return + */ + @Bean(name="iamsDataSource") + public DataSource iamsDataSource() + { + return new LazyConnectionDataSourceProxy(DataSourceUtil.createDataSource("iamsdb", env, aes256Cipher)); + } + + /** + * sqlsessionfactory 등록하는 메소드 + * + * @param dataSource + * @param context + * @return + * @throws SchedulerException + * @throws IOException + */ + @Bean(name="iamsSqlSessionFactory") + public SqlSessionFactory iamsSqlSessionFactory( @Qualifier("iamsDataSource") DataSource dataSource + , ApplicationContext context) + throws CustomException, IOException + { + SqlSessionFactory sqlSessionFactory = DataSourceUtil.createSqlSessionFactory( dataSource + , context.getResource ("classpath:mapper/iamsdb/config/MybatisIamsConfig.xml") + , context.getResources("classpath:mapper/iamsdb/sqlmap/**/*Mapper*.xml") + ); + + sqlSessionFactory.getConfiguration().setDefaultExecutorType(ExecutorType.SIMPLE); + + return sqlSessionFactory; + } + + /** + * sqlsessiontemplate 등록하는 메소드 + * @param primarySqlSessionFactory + * @return + */ + @Bean("iamsSqlSessionTemplate") + public SqlSessionTemplate mainSqlSessionTemplate(@Qualifier("iamsSqlSessionFactory") SqlSessionFactory iamsSqlSessionFactory) + { + return new SqlSessionTemplate(iamsSqlSessionFactory); + } + + /** + * 트랜잭션 매니저 등록하는 메소드 + * @param dataSource + * @return + */ + @Bean(name="iamsTxManager") + public PlatformTransactionManager primaryTxManager(@Qualifier("iamsDataSource") DataSource dataSource) + { + return DataSourceUtil.createTxManager(dataSource); + } +} + diff --git a/src/main/java/com/urpsys/kccfbat/config/ncmsDbConfig.java b/src/main/java/com/urpsys/kccfbat/config/ncmsDbConfig.java new file mode 100644 index 00000000..5c08b882 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/config/ncmsDbConfig.java @@ -0,0 +1,112 @@ +package com.urpsys.kccfbat.config; + +import java.io.IOException; +import java.sql.Connection; + +import javax.sql.DataSource; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.urpsys.kccfbat.common.crypto.Aes256Cipher; +import com.urpsys.kccfbat.common.exception.CustomException; +import com.urpsys.kccfbat.common.util.DataSourceUtil; + +/** + * ncms(자산관리시스템) db config 클래스 + * + * @author 나혁제 + * @since 2026.02.24 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일        수정자         수정내용
+ * -----------  ---------    ------------------------
+ * 2026.02.24    나혁제         최초작성
+ *
+ * 
+ */ + +@Configuration +@EnableTransactionManagement +@MapperScan(value="com.urpsys.kccfbat.ncms.dao", sqlSessionFactoryRef="ncmsSqlSessionFactory") +public class ncmsDbConfig +{ + @Autowired + private Environment env; + + @Autowired + private Aes256Cipher aes256Cipher; + + + /** + * 데이터소스 등록하는 메소드 + * @return + */ + @Bean(name="ncmsDataSource") + public DataSource iamsDataSource() + { + return new LazyConnectionDataSourceProxy(DataSourceUtil.createDataSource("ncmsdb", env, aes256Cipher)); + } + + /** + * sqlsessionfactory 등록하는 메소드 + * + * @param dataSource + * @param context + * @return + * @throws SchedulerException + * @throws IOException + */ + @Bean(name="ncmsSqlSessionFactory") + public SqlSessionFactory ncmsSqlSessionFactory( @Qualifier("ncmsDataSource") DataSource dataSource + , ApplicationContext context) + throws CustomException, IOException + { + SqlSessionFactory sqlSessionFactory = DataSourceUtil.createSqlSessionFactory( dataSource + , context.getResource ("classpath:mapper/ncmsdb/config/MybatisNcmsConfig.xml") + , context.getResources("classpath:mapper/ncmsdb/sqlmap/**/*Mapper*.xml") + ); + + sqlSessionFactory.getConfiguration().setDefaultExecutorType(ExecutorType.SIMPLE); + + return sqlSessionFactory; + } + + /** + * sqlsessiontemplate 등록하는 메소드 + * @param primarySqlSessionFactory + * @return + */ + @Bean("ncmsSqlSessionTemplate") + public SqlSessionTemplate mainSqlSessionTemplate(@Qualifier("ncmsSqlSessionFactory") SqlSessionFactory ncmsSqlSessionFactory) + { + return new SqlSessionTemplate(ncmsSqlSessionFactory); + } + + /** + * 트랜잭션 매니저 등록하는 메소드 + * @param dataSource + * @return + */ + @Bean(name="ncmsTxManager") + public PlatformTransactionManager ncmsTxManager(@Qualifier("ncmsDataSource") DataSource dataSource) + { + return DataSourceUtil.createTxManager(dataSource); + } +} + diff --git a/src/main/java/com/urpsys/kccfbat/domain/CommonVO.java b/src/main/java/com/urpsys/kccfbat/domain/CommonVO.java new file mode 100644 index 00000000..078da708 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/domain/CommonVO.java @@ -0,0 +1,52 @@ +package com.urpsys.kccfbat.domain; + +public class CommonVO +{ + private String val1 ; // test1 + private String val2 ; // test1 + private String val3 ; // test1 + private String val4 ; // test1 + private String val5 ; // test1 + + public String getVal1() { + return val1; + } + public void setVal1(String val1) { + this.val1 = val1; + } + public String getVal2() { + return val2; + } + public void setVal2(String val2) { + this.val2 = val2; + } + public String getVal3() { + return val3; + } + public void setVal3(String val3) { + this.val3 = val3; + } + public String getVal4() { + return val4; + } + public void setVal4(String val4) { + this.val4 = val4; + } + public String getVal5() { + return val5; + } + public void setVal5(String val5) { + this.val5 = val5; + } + + + + + + + + + + + +} \ No newline at end of file diff --git a/src/main/java/com/urpsys/kccfbat/domain/JWTKey.java b/src/main/java/com/urpsys/kccfbat/domain/JWTKey.java new file mode 100644 index 00000000..8c6db14a --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/domain/JWTKey.java @@ -0,0 +1,24 @@ +package com.urpsys.kccfbat.domain; + +import org.springframework.util.StringUtils; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Data +public class JWTKey +{ + + String alg = ""; + String value = ""; + + public String getValue() + { + if (!StringUtils.isEmpty(value)) + { + return value; + } + return ""; + } +} diff --git a/src/main/java/com/urpsys/kccfbat/domain/TokenInfo.java b/src/main/java/com/urpsys/kccfbat/domain/TokenInfo.java new file mode 100644 index 00000000..8eeea8ee --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/domain/TokenInfo.java @@ -0,0 +1,46 @@ +package com.urpsys.kccfbat.domain; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Data; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +public class TokenInfo +{ + private String userName; + private String clientId; + + private String strMEM_ID; + private String strPWD; + private String strPWD_HINT; + private String strPWD_RANS; + private String strRRNO; + private String strMEM_NM; + private String strZIP_NO; + private String strADDR; + private String strREGN_NO; + private String strMEM_STACD; + private String strADDR2; + private String strEND_TELNO; + private String strMOVE_TELNO; + private String strGRP_ID; + private String strMEM_FAX_NO; + private String strMEM_EML_ADDR; + private String strMDL_TELNO; + private String strJOIN_DTM; + private String strSEX_CD; + private String strESNTL_ID; + private String strLOCK_AT; + private String strLOCK_NCNT; + private String strLAST_CHG_DTM; + private String strLAST_PWD_CHG_DTM; + private String userSe; + private String orgnztId; + + private List authorities; +} diff --git a/src/main/java/com/urpsys/kccfbat/iams/dao/IamsDataDao.java b/src/main/java/com/urpsys/kccfbat/iams/dao/IamsDataDao.java new file mode 100644 index 00000000..71320b8a --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/iams/dao/IamsDataDao.java @@ -0,0 +1,49 @@ +package com.urpsys.kccfbat.iams.dao; + +import java.util.LinkedHashMap; +import java.util.List; + +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +import com.urpsys.kccfbat.domain.CommonVO; + +/** + * 자산관리시스템에 대한 DAO 클래스를 정의 + * + * @author urp 인프라본부 나혁제 + * @since 2026.02.25 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일     수정자            수정내용
+ * -----------  ---------    ------------------------
+ * 2026.02.25   나혁제          최초작성
+ *
+ *      
+ */ + +@Mapper +@Repository +public interface IamsDataDao +{ + // 기존이관자료 여부 확인 + public String selectExistMaster(String strIn) throws Exception; + + // 자료 마스터 테이블 입력처리 + public int insertRgMaster(LinkedHashMap inMap) throws Exception; + + // file 정보 입력처리 + public int insertJattchfile(LinkedHashMap inMap) throws Exception; + + // uac 정보 입력처리 + public int insertUareMaster(LinkedHashMap inMap) throws Exception; + + // 자료건 정보 입력처리 + public int insertUacRecord(LinkedHashMap inMap) throws Exception; + +} diff --git a/src/main/java/com/urpsys/kccfbat/ncms/dao/CommonDao.java b/src/main/java/com/urpsys/kccfbat/ncms/dao/CommonDao.java new file mode 100644 index 00000000..720db28a --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/ncms/dao/CommonDao.java @@ -0,0 +1,18 @@ +package com.urpsys.kccfbat.ncms.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +import com.urpsys.kccfbat.domain.CommonVO; + +@Mapper +@Repository +public interface CommonDao +{ + public String selectTest1(String strVal1); // TestCode1 + public CommonVO selectTest2(String strVal1); // TestCode2 + + +} diff --git a/src/main/java/com/urpsys/kccfbat/ncms/dao/NcmsDataDao.java b/src/main/java/com/urpsys/kccfbat/ncms/dao/NcmsDataDao.java new file mode 100644 index 00000000..d1286d6a --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/ncms/dao/NcmsDataDao.java @@ -0,0 +1,57 @@ +package com.urpsys.kccfbat.ncms.dao; + +import java.util.LinkedHashMap; +import java.util.List; + +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +import com.urpsys.kccfbat.domain.CommonVO; + +/** + * 자산관리시스템에 대한 DAO 클래스를 정의 + * + * @author urp 인프라본부 나혁제 + * @since 2026.02.25 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일     수정자            수정내용
+ * -----------  ---------    ------------------------
+ * 2026.02.25   나혁제          최초작성
+ *
+ *      
+ */ + +@Mapper +@Repository +public interface NcmsDataDao +{ + // 이관대상 멀티미디어 자산 조회 + public List> selectMultimediaAssets() throws Exception; + + // culter_resource 추출 + public LinkedHashMap selectCulterResource(String strIn) throws Exception; + + // media 추출 + public List> selectMedia(String strIn) throws Exception; + + // 유형값 찾기 + public String selectTypeDivCd(int iIn) throws Exception; + + // 관리부서 찾기 + public String selectMngOrgCd(int iIn) throws Exception; + + // 관리부서명 찾기 + public String selectMngOrgNm(int iIn) throws Exception; + + + + // 결과값 반경 + public int updateResultMultimediaAssets(LinkedHashMap inMap) throws Exception; + +} diff --git a/src/main/java/com/urpsys/kccfbat/ncmsToIamsDataTransApplication.java b/src/main/java/com/urpsys/kccfbat/ncmsToIamsDataTransApplication.java new file mode 100644 index 00000000..f5455fa1 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/ncmsToIamsDataTransApplication.java @@ -0,0 +1,60 @@ +package com.urpsys.kccfbat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; + +import com.urpsys.kccfbat.common.util.CommonUtil; + +/** + * Resource 서버 기본 실행 클래스 + * + * @author 나혁제 + * @since 2026.02.24 + * @version 1.0.0 + * @see + * + *
+ *
+ * << 개정이력(Modification information) >>
+ *
+ *   수정일     수정자      수정내용
+ * -----------  ---------    ------------------------
+ * 2026.02.24   나혁제      최초작성
+ *
+ *      
+ */ + +@SpringBootApplication +@EnableScheduling +@ComponentScan(basePackages = {"com.urpsys.kccfbat"}) +public class ncmsToIamsDataTransApplication +{ + public static void main(String[] args) + { + String activeProfile = (CommonUtil.nvl(System.getProperty("spring.profiles.active"))); + + if(activeProfile.equals("local")) + { + System.out.println("################################################"); + System.out.println("############# local Env ########################"); + System.out.println("################################################"); + } + else if(activeProfile.equals("ncms_server")) + { + System.out.println("################################################"); + System.out.println("############# ncms_server Env ##################"); + System.out.println("################################################"); + } + else + { + System.out.println("################################################"); + System.out.println("############# No Define ########################"); + System.out.println("################################################"); + } + + SpringApplication.run(ncmsToIamsDataTransApplication.class, args); + } +} diff --git a/src/main/java/com/urpsys/kccfbat/scheduler/ConsoleScheduler.java b/src/main/java/com/urpsys/kccfbat/scheduler/ConsoleScheduler.java new file mode 100644 index 00000000..ecf178e9 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/scheduler/ConsoleScheduler.java @@ -0,0 +1,70 @@ +package com.urpsys.kccfbat.scheduler; + +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.urpsys.kccfbat.ncms.dao.NcmsDataDao; +import com.urpsys.kccfbat.service.NcmsDataService; +import com.urpsys.kccfbat.service.NcmsToIamsDataTransService; + +import lombok.extern.slf4j.Slf4j; + +/** + * 자료이관처리 스케쥴러 클래스 + * @author urp 인프라본부 나혁제 + * @since 2026.02.25 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *  수정일         수정자       수정내용
+ *  ----------   --------   ---------------------------
+ *  2026.02.25   나혁제       최초 생성
+ *
+ * 
+ * + */ + +@Slf4j +@Component +public class ConsoleScheduler +{ + @Autowired + NcmsToIamsDataTransService ncmsToIamsDataTransService; + + NcmsDataService ncmsDataService; + + + @Scheduled(cron = "1 * * * * *") + public void NcmsToIamsDataTranMain () + { + log.info(">>>>>>>>>>>>>>> NcmsToIamsDataTranMain <<<<<<<<<<<<<<<"); + + // ams => 통합자료관리 시스템 데이터이관 + + try + { + ncmsToIamsDataTransService.processNcmsToIamsDataTrans(); + } + catch(Exception e) + { + e.printStackTrace(); + log.error("데이터 이관중 오류 발생[{}] ", e); + + } + + + + + + log.info("<<<<<<<<<<<<<<< NcmsToIamsDataTranMain >>>>>>>>>>>>>>>"); + } + +} \ No newline at end of file diff --git a/src/main/java/com/urpsys/kccfbat/service/CommonService.java b/src/main/java/com/urpsys/kccfbat/service/CommonService.java new file mode 100644 index 00000000..661a5aff --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/service/CommonService.java @@ -0,0 +1,35 @@ +package com.urpsys.kccfbat.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.urpsys.kccfbat.domain.CommonVO; +import com.urpsys.kccfbat.ncms.dao.CommonDao; + +@Service +@Transactional +public class CommonService +{ + @Autowired + CommonDao commonDao; + + + // TestCode1 + public String selectTest1(String strVal1) + { + return commonDao.selectTest1(strVal1); + } + + // TestCode2 + public CommonVO selectTest2(String strVal1) + { + return commonDao.selectTest2(strVal1); + } + + + + +} diff --git a/src/main/java/com/urpsys/kccfbat/service/IamsDataService.java b/src/main/java/com/urpsys/kccfbat/service/IamsDataService.java new file mode 100644 index 00000000..d4ea73bf --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/service/IamsDataService.java @@ -0,0 +1,92 @@ +package com.urpsys.kccfbat.service; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.LinkedHashMap; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.urpsys.kccfbat.iams.dao.IamsDataDao; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class IamsDataService +{ + @Autowired + IamsDataDao iamsDataDao; + + @Value("${file.fileCpYn}") + private String strFileCpYn; // 파일처리여부 + + // 멀티미디어 자산 조회 + public String selectExistMaster(String strIn) throws Exception + { + return iamsDataDao.selectExistMaster(strIn); + } + + @Transactional(value = "iamsTxManager") + public int processIams( LinkedHashMap inRgMaster + , LinkedHashMap inUacRecord + , List> inJFile + , List> inUareMaster + ) throws Exception + { + // 파일처리 부터 먼저 시작 + // 1. 원본 File, 복사할 File 준비 + for( LinkedHashMap mapUare : inUareMaster) + { + log.info(" ncms_full_file_path [{}]", mapUare.get("ncms_full_file_path")); + log.info(" iams_full_file_path [{}]", mapUare.get("iams_full_file_path")); + + if(strFileCpYn.equals("Y")) + { + File file = new File((String)mapUare.get("ncms_full_file_path")); + File newFile = new File((String)mapUare.get("iams_full_file_path")); + + Files.copy(file.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + } + + int iRgRet = iamsDataDao.insertRgMaster (inRgMaster ); + int iRgRet2 = iamsDataDao.insertUacRecord(inUacRecord); + + for( LinkedHashMap mapUare : inUareMaster) + { + log.info(" f_id [{}]", mapUare.get("f_id")); + log.info(" length [{}]", mapUare.get("length")); + log.info(" ncms_full_file_path [{}]", mapUare.get("ncms_full_file_path")); + log.info(" iams_full_file_path [{}]", mapUare.get("iams_full_file_path")); + } + + // j_attachfile 처리 + for(LinkedHashMap inMap : inJFile) + { + int iJFRet = iamsDataDao.insertJattchfile(inMap); + } + + // uare_master 처리 + for(LinkedHashMap inMap : inUareMaster) + { + int iJFRet = iamsDataDao.insertUareMaster(inMap); + } + + return iRgRet; + } + + + // 자료 마스터 테이블 입력처리 + public int insertRgMaster(LinkedHashMap inMap) throws Exception + { + return iamsDataDao.insertRgMaster(inMap); + } + + + +} diff --git a/src/main/java/com/urpsys/kccfbat/service/NcmsDataService.java b/src/main/java/com/urpsys/kccfbat/service/NcmsDataService.java new file mode 100644 index 00000000..351fa283 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/service/NcmsDataService.java @@ -0,0 +1,67 @@ +package com.urpsys.kccfbat.service; + +import java.util.LinkedHashMap; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.urpsys.kccfbat.ncms.dao.NcmsDataDao; + +@Service +@Transactional(value = "ncmsTxManager") +public class NcmsDataService +{ + @Autowired + NcmsDataDao ncmsDataDao; + + // 멀티미디어 자산 조회 + public List> selectMultimediaAssets() throws Exception + { + return ncmsDataDao.selectMultimediaAssets(); + } + + // culter_resource 추출 + public LinkedHashMap selectCulterResource(String strIn) throws Exception + { + return ncmsDataDao.selectCulterResource(strIn); + } + + // media 추출 + public List> selectMedia(String strIn) throws Exception + { + return ncmsDataDao.selectMedia(strIn); + } + + // 유형값 찾기 + public String selectTypeDivCd(int iIn) throws Exception + { + return ncmsDataDao.selectTypeDivCd(iIn); + } + + // 관리부서 찾기 + public String selectMngOrgCd(int iIn) throws Exception + { + return ncmsDataDao.selectMngOrgCd(iIn); + } + + // 관리부서 찾기 + public String selectMngOrgNm(int iIn) throws Exception + { + return ncmsDataDao.selectMngOrgNm(iIn); + } + + + + + + // 결과값 반경 + public int updateResultMultimediaAssets(LinkedHashMap inMap) throws Exception + { + return ncmsDataDao.updateResultMultimediaAssets(inMap); + } + + + +} diff --git a/src/main/java/com/urpsys/kccfbat/service/NcmsToIamsDataTransService.java b/src/main/java/com/urpsys/kccfbat/service/NcmsToIamsDataTransService.java new file mode 100644 index 00000000..93814fb2 --- /dev/null +++ b/src/main/java/com/urpsys/kccfbat/service/NcmsToIamsDataTransService.java @@ -0,0 +1,558 @@ +package com.urpsys.kccfbat.service; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.urpsys.kccfbat.common.util.CommonUtil; +import com.urpsys.kccfbat.common.util.CommonUtils; +import com.urpsys.kccfbat.ncms.dao.NcmsDataDao; +import com.urpsys.kccfbat.scheduler.ConsoleScheduler; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class NcmsToIamsDataTransService +{ + @Autowired + NcmsDataService ncmsDataService; + + @Autowired + IamsDataService iamsDataService; + + @Value("${file.ncms.basefolder}") + private String strNcmsBaseFolder; // ncms base folder + + @Value("${file.iams.basefolder}") + private String strIcmsBaseFolder; // icms base folder + + @Value("${file.fileCpYn}") + private String strFileCpYn; // icms base folder + + // 데이터 이관작업 + public void processNcmsToIamsDataTrans() throws Exception + { + log.info(" >>>>> processNcmsToIamsDataTrans <<<<< "); + + int iNcmsTransAllCnt = 0; // 이관대상 전체 건수 + int iNcmsTransSkipCnt = 0; // 이관대상 Skip 대상 건수 + + // 이관대상 데이터 추출 + List> nCmsList = ncmsDataService.selectMultimediaAssets(); + + // 이관대상이 없는 경우 + if(nCmsList == null || nCmsList.size()==0) return; + + iNcmsTransAllCnt += nCmsList.size(); + + for(LinkedHashMap ncmsDataMap : nCmsList ) + { + LinkedHashMap inMultiResultMap = new LinkedHashMap(); + + String strMultiId = ncmsDataMap.get("id")+""; + + // 이관완료여부 체크 + String strRgYn = iamsDataService.selectExistMaster(strMultiId); + + log.info(" 기존이관여부 확인 [{}] ", strRgYn); + + // 이관자료가 있는경우 Skip + if(strRgYn.equals("Y")) + { + inMultiResultMap.put("iams_tran_yn" , "Y"); + inMultiResultMap.put("iams_tran_remark" , "이미 이관처리 완료된 자료"); + inMultiResultMap.put("id" , strMultiId ); + + ncmsDataService.updateResultMultimediaAssets(inMultiResultMap); + + continue; + } + + String strCulterResourceId = ncmsDataMap.get("culture_resource_id")+""; + LinkedHashMap mapCulterResources = ncmsDataService.selectCulterResource(strCulterResourceId); + List> listMedia = ncmsDataService.selectMedia(strMultiId); + + // 기초자료가 없는경우 Skip + if(mapCulterResources == null || mapCulterResources.get("id") == null || mapCulterResources.get("id").equals("")) + { + inMultiResultMap.put("iams_tran_yn" , "Y"); + inMultiResultMap.put("iams_tran_remark" , "CulterResources 자료없음"); + inMultiResultMap.put("id" , strMultiId ); + + ncmsDataService.updateResultMultimediaAssets(inMultiResultMap); + + continue; + } + + LinkedHashMap inRgMaster = new LinkedHashMap(); // 자료 마스터 정보 + LinkedHashMap inUacRecord = new LinkedHashMap(); // 자료 건 정보 + List> inJFile = new ArrayList(); // 파일정보 + List> inUareMaster = new ArrayList(); // 클라우드 파일정보 + + // ncmsDataMap : multimedia_assets + // mapCulterResources : culter_resources + + String strMasterId = CommonUtils.getUUID("UR"); + + String keyword = CommonUtil.nvl(mapCulterResources.get("keywords")); + + keyword = keyword.replaceAll("\"", ""); + keyword = keyword.replaceAll("\\[", ""); + keyword = keyword.replaceAll("\\]", ""); + + String creat_yyyy=""; + if( isLong(CommonUtil.nvl(mapCulterResources.get("genyear"))) ) + { + creat_yyyy = CommonUtil.nvl(mapCulterResources.get("genyear"))+"0101"; + } + + int iCouncilId = Long.valueOf((long)mapCulterResources.get("council_id")).intValue(); + String type_div_cd = ncmsDataService.selectTypeDivCd((int)ncmsDataMap.get("major_category_id")); + + // iams rg_master 세팅 + inRgMaster.put("master_id" , strMasterId ); + inRgMaster.put("use_flag" , "Y" ); + inRgMaster.put("set_id" , CommonUtils.getUUID("SE") ); + inRgMaster.put("reg_status" , "REG_ING" ); + inRgMaster.put("title" , (String)ncmsDataMap.get("title") ); + inRgMaster.put("keyword" , keyword ); + inRgMaster.put("type_div_cd" , type_div_cd ); + inRgMaster.put("erecord_flag" , "2" ); + inRgMaster.put("org_nm" , (String)ncmsDataMap.get("publisher") ); + inRgMaster.put("creat_yyyy" , creat_yyyy ); + inRgMaster.put("presv_term_cd" , "10" ); + inRgMaster.put("expt_disuse_yyyy" , "2031" ); + inRgMaster.put("oper_read_range_cd" , "01" ); + inRgMaster.put("open_div_cd" , "1" ); + inRgMaster.put("reg_id" , "U1000000000" ); + inRgMaster.put("mod_id" , "U1000000000" ); + inRgMaster.put("mng_org_cd" , ncmsDataService.selectMngOrgCd(iCouncilId) ); + inRgMaster.put("page_cnt" , ncmsDataMap.get("total_page_count")+"" ); + inRgMaster.put("series_id" , "0" ); + inRgMaster.put("digital_yn" , "N" ); + inRgMaster.put("oper_out_range_cd" , "01" ); + inRgMaster.put("mng_org_nm" , ncmsDataService.selectMngOrgNm(iCouncilId) ); + inRgMaster.put("asset_type" , "문화원소장" ); + inRgMaster.put("tag" , keyword ); + inRgMaster.put("management_code" , "KCCF" ); + inRgMaster.put("interface_id" , (long)ncmsDataMap.get("culture_resource_id")+"" ); + inRgMaster.put("set_no" , strMultiId ); + inRgMaster.put("digital_read_yn" , "Y" ); + inRgMaster.put("prsvn_proc_trgt_yn" , "N" ); + + // 자료건 정보 처리 + inUacRecord.put("record_id", strMasterId); + inUacRecord.put("type_div_cd", type_div_cd); + + // 파일처리 + String orgThumbnail2 = CommonUtil.nvl(ncmsDataMap.get("thumbnail2")); + String orgThumbnail_manual = CommonUtil.nvl(ncmsDataMap.get("thumbnail_manual")); + + String thumbnail2 = getFileName(orgThumbnail2); + String thumbnail_manual = getFileName(orgThumbnail_manual); + + log.info(" orgThumbnail2 [{}]", orgThumbnail2); + log.info(" orgThumbnail_manual [{}]", orgThumbnail_manual); + log.info(" thumbnail2 [{}]", thumbnail2); + log.info(" thumbnail_manual [{}]", thumbnail_manual); + + LinkedHashMap mapJFile = new LinkedHashMap(); + LinkedHashMap mapUareMaster = new LinkedHashMap(); + + int iSeq=1; + + // thumbnail_manual 파일처리 + if(!orgThumbnail2.equals("")) + { + String strNcmsFileFullPath = strNcmsBaseFolder + "/" + orgThumbnail2; + String strFileMask = CommonUtils.getFileMask(); + + Path path = Paths.get(strNcmsFileFullPath); + long lFileSize = 0; + if(strFileCpYn.equals("Y")) + { + lFileSize = Files.size(path); + } + + mapJFile = new LinkedHashMap(); + mapJFile.put("file_mask" , strFileMask ); + mapJFile.put("file_id" , strMasterId); + mapJFile.put("file_seq" , iSeq); + mapJFile.put("file_name" , thumbnail2); + mapJFile.put("file_size" , lFileSize+""); + mapJFile.put("download_count" , "0"); + mapJFile.put("atch_type_cd" , "image"); + mapJFile.put("digital_read_yn" , "Y"); + + String strCurFullTime = CommonUtil.getKST("yyyyMMddHHmmss"); + String strCurDate = CommonUtil.getKST("yyyyMMdd"); + String strCurTime = CommonUtil.getKST("HHmmss"); + + String strFid = CommonUtil.getKST("yyyy") +"-"+strMultiId+"-"+iSeq; + + mapUareMaster = new LinkedHashMap(); + mapUareMaster.put("f_id" , strFid); + mapUareMaster.put("org_name" , thumbnail2); + mapUareMaster.put("volume_id" , "VOL001"); + mapUareMaster.put("v_seq" , "0000"); + mapUareMaster.put("length" , lFileSize+""); + mapUareMaster.put("comp_yn" , "N"); + mapUareMaster.put("encrypt_yn" , "N"); + mapUareMaster.put("org_date" , strCurDate); + mapUareMaster.put("reg_date" , strCurDate); + mapUareMaster.put("reg_time" , strCurTime); + mapUareMaster.put("commit_stat" , "1"); + mapUareMaster.put("session_key" , "473640583"); + mapUareMaster.put("reg_user_id" , "uac"); + mapUareMaster.put("file_key" , strFileMask); + mapUareMaster.put("f_group" , "1"); + mapUareMaster.put("f_index" , iSeq); + mapUareMaster.put("bef_commit_stat", "0"); + + String strIameFileFullDir = strIcmsBaseFolder + + "/" + strCurFullTime.substring(0,4) + + "/" + strCurFullTime.substring(4,6) + + "/" + strCurFullTime.substring(6,8) + + "/" + strCurFullTime.substring(8,10) + + "/" + "0000" + ; + + String strIameFileFullPath = strIameFileFullDir +"/"+strFid+"."+getFileExt(orgThumbnail2); + + // 폴더생성 + File file = new File(strIameFileFullDir); + Files.createDirectories(file.toPath()); + + mapUareMaster.put("ncms_full_file_path", strNcmsFileFullPath ); + mapUareMaster.put("iams_full_file_path", strIameFileFullPath ); + + log.info(" lFileSize [{}]", lFileSize); + log.info(" strNcmsFileFullPath [{}]", strNcmsFileFullPath); + log.info(" strIameFileFullPath [{}]", strIameFileFullPath); + + inJFile .add(mapJFile ); + inUareMaster.add(mapUareMaster); + + iSeq++; + } + + // thumbnail_manual 파일처리 + if(!orgThumbnail_manual.equals("")) + { + String strNcmsFileFullPath = strNcmsBaseFolder + "/" + orgThumbnail_manual; + String strFileMask = CommonUtils.getFileMask(); + + Path path = Paths.get(strNcmsFileFullPath); + long lFileSize = 0; + if(strFileCpYn.equals("Y")) + { + lFileSize = Files.size(path); + } + + mapJFile = new LinkedHashMap(); + mapJFile.put("file_mask" , strFileMask ); + mapJFile.put("file_id" , strMasterId); + mapJFile.put("file_seq" , iSeq); + mapJFile.put("file_name" , thumbnail_manual); + mapJFile.put("file_size" , lFileSize+""); + mapJFile.put("download_count" , "0"); + mapJFile.put("atch_type_cd" , "image"); + mapJFile.put("digital_read_yn" , "Y"); + + String strCurFullTime = CommonUtil.getKST("yyyyMMddHHmmss"); + String strCurDate = CommonUtil.getKST("yyyyMMdd"); + String strCurTime = CommonUtil.getKST("HHmmss"); + + String strFid = CommonUtil.getKST("yyyy") +"-"+strMultiId+"-"+iSeq; + + mapUareMaster = new LinkedHashMap(); + mapUareMaster.put("f_id" , strFid); + mapUareMaster.put("org_name" , thumbnail_manual); + mapUareMaster.put("volume_id" , "VOL001"); + mapUareMaster.put("v_seq" , "0000"); + mapUareMaster.put("length" , lFileSize+""); + mapUareMaster.put("comp_yn" , "N"); + mapUareMaster.put("encrypt_yn" , "N"); + mapUareMaster.put("org_date" , strCurDate); + mapUareMaster.put("reg_date" , strCurDate); + mapUareMaster.put("reg_time" , strCurTime); + mapUareMaster.put("commit_stat" , "1"); + mapUareMaster.put("session_key" , "473640583"); + mapUareMaster.put("reg_user_id" , "uac"); + mapUareMaster.put("file_key" , strFileMask); + mapUareMaster.put("f_group" , "1"); + mapUareMaster.put("f_index" , iSeq); + mapUareMaster.put("bef_commit_stat", "0"); + + String strIameFileFullDir = strIcmsBaseFolder + + "/" + strCurFullTime.substring(0,4) + + "/" + strCurFullTime.substring(4,6) + + "/" + strCurFullTime.substring(6,8) + + "/" + strCurFullTime.substring(8,10) + + "/" + "0000" + ; + + String strIameFileFullPath = strIameFileFullDir +"/"+strFid+"."+getFileExt(orgThumbnail_manual); + + // 폴더생성 + File file = new File(strIameFileFullDir); + Files.createDirectories(file.toPath()); + + mapUareMaster.put("ncms_full_file_path", strNcmsFileFullPath ); + mapUareMaster.put("iams_full_file_path", strIameFileFullPath ); + + inJFile .add(mapJFile ); + inUareMaster.add(mapUareMaster); + + iSeq++; + } + + // media 처리 + for( LinkedHashMap mapMedia : listMedia) + { + long lCulter = (long)mapCulterResources .get("id"); + long lMulti = (long)ncmsDataMap .get("id"); + long iMe = (long)mapMedia .get("id"); + + String strNcmsFileFullPath = getFixPath(lCulter, lMulti, iMe , (String)mapMedia.get("collection_name"))+"/"+ mapMedia.get("file_name"); + String strFileMask = CommonUtils.getFileMask(); + + Path path = Paths.get(strNcmsFileFullPath); + + mapJFile = new LinkedHashMap(); + mapJFile.put("file_mask" , strFileMask ); + mapJFile.put("file_id" , strMasterId); + mapJFile.put("file_seq" , iSeq); + mapJFile.put("file_name" , (String)mapMedia.get("file_name")); + mapJFile.put("file_size" , mapMedia.get("size")+""); + mapJFile.put("download_count" , "0"); + mapJFile.put("atch_type_cd" , getAtchTypeCd((String)mapMedia.get("collection_name"))); + mapJFile.put("digital_read_yn" , "Y"); + + String strCurFullTime = CommonUtil.getKST("yyyyMMddHHmmss"); + String strCurDate = CommonUtil.getKST("yyyyMMdd"); + String strCurTime = CommonUtil.getKST("HHmmss"); + + String strFid = CommonUtil.getKST("yyyy") +"-"+strMultiId+"-"+iSeq; + + mapUareMaster = new LinkedHashMap(); + mapUareMaster.put("f_id" , strFid); + mapUareMaster.put("org_name" , (String)mapMedia.get("file_name")); + mapUareMaster.put("volume_id" , "VOL001"); + mapUareMaster.put("v_seq" , "0000"); + mapUareMaster.put("length" , mapMedia.get("size")+""); + mapUareMaster.put("comp_yn" , "N"); + mapUareMaster.put("encrypt_yn" , "N"); + mapUareMaster.put("org_date" , strCurDate); + mapUareMaster.put("reg_date" , strCurDate); + mapUareMaster.put("reg_time" , strCurTime); + mapUareMaster.put("commit_stat" , "1"); + mapUareMaster.put("session_key" , "473640583"); + mapUareMaster.put("reg_user_id" , "uac"); + mapUareMaster.put("file_key" , strFileMask); + mapUareMaster.put("f_group" , "1"); + mapUareMaster.put("f_index" , iSeq); + mapUareMaster.put("bef_commit_stat", "0"); + mapUareMaster.put("repository" , ""); + mapUareMaster.put("clipid" , ""); + mapUareMaster.put("offset" , "0"); + + String strIameFileFullDir = strIcmsBaseFolder + + "/" + strCurFullTime.substring(0,4) + + "/" + strCurFullTime.substring(4,6) + + "/" + strCurFullTime.substring(6,8) + + "/" + strCurFullTime.substring(8,10) + + "/" + "0000" + ; + + String strIameFileFullPath = strIameFileFullDir +"/"+strFid+"."+getFileExt((String)mapMedia.get("file_name")); + + // 폴더생성 + File file = new File(strIameFileFullDir); + Files.createDirectories(file.toPath()); + + mapUareMaster.put("ncms_full_file_path", strNcmsFileFullPath ); + mapUareMaster.put("iams_full_file_path", strIameFileFullPath ); + + inJFile .add(mapJFile ); + inUareMaster.add(mapUareMaster); + + iSeq++; + } + + log.info(" mapUareMaster [{}]", mapUareMaster.toString()); + + int iSucc = iamsDataService.processIams(inRgMaster, inUacRecord, inJFile, inUareMaster); + + if(iSucc>0) + { + inMultiResultMap.put("iams_tran_yn" , "Y"); + inMultiResultMap.put("iams_tran_remark" , "이관완료"); + inMultiResultMap.put("id" , strMultiId ); + inMultiResultMap.put("iams_tran_master_id" , strMasterId ); + } + else + { + inMultiResultMap.put("iams_tran_yn" , "X" ); + inMultiResultMap.put("iams_tran_remark" , "이관실패" ); + inMultiResultMap.put("id" , strMultiId );; + } + + ncmsDataService.updateResultMultimediaAssets(inMultiResultMap); + } + + + log.info(" <<<<< processNcmsToIamsDataTrans >>>>> "); + } + + // 데이터 이관작업 + public LinkedHashMap iamsDataSetting(LinkedHashMap ncmsDataMap ) throws Exception + { + LinkedHashMap returnMap = new LinkedHashMap(); + + returnMap.put("MASTER_ID", CommonUtils.getUUID("UR")); + + + return returnMap; + } + + public String getFileName(String strOrgFileName) + { + String strReFileName =""; + + int iLastIndex = strOrgFileName.lastIndexOf("/"); + + if(iLastIndex < 0) + { + strReFileName = strOrgFileName; + } + else + { + strReFileName = strOrgFileName.substring(iLastIndex+1); + } + + return strReFileName; + } + + public String getFileExt(String strOrgFileName) + { + String strReFileExt =""; + + int iLastIndex = strOrgFileName.lastIndexOf("."); + + if(iLastIndex < 0) + { + strReFileExt = ""; + } + else + { + strReFileExt = strOrgFileName.substring(iLastIndex+1); + } + + return strReFileExt; + } + + public String getAtchTypeCd(String collection_name) + { + String strReAtchTypeCd = ""; + if(collection_name.equals("media_images")) + { + strReAtchTypeCd = "image"; + } + else if(collection_name.equals("media_videos")) + { + strReAtchTypeCd = "videos"; + } + else if(collection_name.equals("media_audios")) + { + strReAtchTypeCd = "audios"; + } + else if(collection_name.equals("media_pdfs")) + { + strReAtchTypeCd = "doc"; + } + else if(collection_name.equals("media_3ds")) + { + strReAtchTypeCd = "3d"; + } + + return strReAtchTypeCd; + } + + public String getFixPath(long lculterResourceId, long lMaId, long lMediaId, String collection_name) + { + long iFreFolder = lculterResourceId%250; + + String strFixPath = ""; + String strFullFixPath = ""; + + if(collection_name.equals("media_images")) + { + strFixPath = "multimedia_assets"; + } + else if(collection_name.equals("media_videos")) + { + strFixPath = "videos"; + } + else if(collection_name.equals("media_audios")) + { + strFixPath = "audios"; + } + else if(collection_name.equals("media_pdfs")) + { + strFixPath = "pdfs"; + } + else if(collection_name.equals("media_3ds")) + { + strFixPath = "3ds"; + } + + + if(collection_name.equals("media_images")) + { + strFullFixPath = strNcmsBaseFolder + + "/" + strFixPath + + "/" + iFreFolder + + "/" + lMaId + + "/" + lMediaId + ; + } + else + { + strFullFixPath = strNcmsBaseFolder + + "/" + strFixPath + + "/" + iFreFolder + + "/" + lMaId + ; + } + + return strFullFixPath; + } + + public static boolean isLong(String strValue) + { + try + { + Long.parseLong(strValue); + return true; + } + catch (NumberFormatException ex) + { + return false; + } + } + + + + +} diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml new file mode 100644 index 00000000..8348fa60 --- /dev/null +++ b/src/main/resources/application-local.yml @@ -0,0 +1,67 @@ + # Service port + server: + port: 9002 + +# JPA 설정, JSP 설정 + spring: + devtools: + livereload: + enabled: true + mvc: + pathmatch: + matching-strategy: ANT_PATH_MATCHER + # 인증서버에서 JWT 보안키 확인 + security: + oauth2: + resourceserver: + jwt: + jwk-set-uri: + http://localhost:9001/oauth/token_key + +# Primary db information + ncmsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://192.168.8.138:3307/kccfnova?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: yT4l55I/Xl4v8LeoTQhh1w== + password: aqmsYeReTVvoQ4r2bfAjYg== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + iamsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://192.168.8.138:3307/uac_cltr_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: kSLzt543nkDJ/ta9rnLTCA== + password: kSLzt543nkDJ/ta9rnLTCA== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + +# SQL Log 관련 setting + log4jdbc: + spylogdelegator: + name: net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator + dump: + sql: + maxlinelength: 0 + + logging.level.jdbc.sqlonly: info + logging.level.jdbc.sqltiming: false + logging.level.jdbc.audit: false + logging.level.jdbc.resultset: false + logging.level.jdbc.resultsettable: info + logging.level.jdbc.connection: false + + file: + ncms: + basefolder : D:/z_temp_pro/kccf_temp + iams: + basefolder : D:/z_temp_pro/kccf_temp/repo + fileCpYn : N + + \ No newline at end of file diff --git a/src/main/resources/application-ncms_server.yml b/src/main/resources/application-ncms_server.yml new file mode 100644 index 00000000..29bd63eb --- /dev/null +++ b/src/main/resources/application-ncms_server.yml @@ -0,0 +1,67 @@ + # Service port + server: + port: 9002 + +# JPA 설정, JSP 설정 + spring: + devtools: + livereload: + enabled: true + mvc: + pathmatch: + matching-strategy: ANT_PATH_MATCHER + # 인증서버에서 JWT 보안키 확인 + security: + oauth2: + resourceserver: + jwt: + jwk-set-uri: + http://localhost:9001/oauth/token_key + +# Primary db information + ncmsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://127.0.0.1:3306/kccfnova?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: yT4l55I/Xl4v8LeoTQhh1w== + password: aqmsYeReTVvoQ4r2bfAjYg== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + iamsdb: + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbcUrl: jdbc:log4jdbc:mysql://10.10.30.237:3306/uac_cltr_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&rewriteBatchedStatements=true + username: kSLzt543nkDJ/ta9rnLTCA== + password: kSLzt543nkDJ/ta9rnLTCA== + maximumPoolSize: 35 + minimumIdle: 2 + connectionTimeout: 3000 + idleTimeout: 300000 + testOnBorrow: true + validationQuery: SELECT 1 + +# SQL Log 관련 setting + log4jdbc: + spylogdelegator: + name: net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator + dump: + sql: + maxlinelength: 0 + + logging.level.jdbc.sqlonly: info + logging.level.jdbc.sqltiming: false + logging.level.jdbc.audit: false + logging.level.jdbc.resultset: false + logging.level.jdbc.resultsettable: info + logging.level.jdbc.connection: false + + file: + ncms: + basefolder : /nfs_nas/minio/amsweb-opt + iams: + basefolder : /nfs_nas/uac/repo + fileCpYn : Y + + \ No newline at end of file diff --git a/src/main/resources/log4jdbc.log4j2.properties b/src/main/resources/log4jdbc.log4j2.properties new file mode 100644 index 00000000..85d1ede9 --- /dev/null +++ b/src/main/resources/log4jdbc.log4j2.properties @@ -0,0 +1,2 @@ +log4jdbc.spylogdelegator.name = net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator +log4jdbc.dump.sql.maxlinelength=0 \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..31ad4bcc --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,98 @@ + + + ${HOSTNAME} + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/iamsdb/config/MybatisIamsConfig.xml b/src/main/resources/mapper/iamsdb/config/MybatisIamsConfig.xml new file mode 100644 index 00000000..dfb0172e --- /dev/null +++ b/src/main/resources/mapper/iamsdb/config/MybatisIamsConfig.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/iamsdb/sqlmap/iamsDataMapper.xml b/src/main/resources/mapper/iamsdb/sqlmap/iamsDataMapper.xml new file mode 100644 index 00000000..196eed55 --- /dev/null +++ b/src/main/resources/mapper/iamsdb/sqlmap/iamsDataMapper.xml @@ -0,0 +1,185 @@ + + + + + + + + + + insert into rg_master + ( + master_id + , use_flag + , set_id + , reg_status + , title + , keyword + , type_div_cd + , erecord_flag + , org_nm + , creat_yyyy + , presv_term_cd + , expt_disuse_yyyy + , oper_read_range_cd + , open_div_cd + , reg_id + , reg_dd + , mod_id + , mod_dd + , mng_org_cd + , page_cnt + , series_id + , digital_yn + , oper_out_range_cd + , mng_org_nm + , asset_type + , tags + , management_code + , interface_id + , set_no + , digital_read_yn + , prsvn_proc_trgt_yn + , dtls_type_div_cd + ) + values + ( + #{master_id } + , #{use_flag } + , #{set_id } + , #{reg_status } + , #{title } + , #{keyword } + , #{type_div_cd } + , #{erecord_flag } + , #{org_nm } + , #{creat_yyyy } + , #{presv_term_cd } + , #{expt_disuse_yyyy } + , #{oper_read_range_cd } + , #{open_div_cd } + , #{reg_id } + , sysdate() + , #{mod_id } + , sysdate() + , #{mng_org_cd } + , #{page_cnt } + , #{series_id } + , #{digital_yn } + , #{oper_out_range_cd } + , #{mng_org_nm } + , #{asset_type } + , #{tag } + , #{management_code } + , #{interface_id } + , #{set_no } + , #{digital_read_yn } + , #{prsvn_proc_trgt_yn } + , '' + ) + + + + insert into j_attachfile + ( + file_mask + , file_id + , file_seq + , file_name + , file_size + , download_count + , atch_type_cd + , digital_read_yn + ) + values + ( + #{file_mask } + , #{file_id } + , #{file_seq } + , #{file_name } + , #{file_size } + , #{download_count } + , #{atch_type_cd } + , #{digital_read_yn } + ) + + + + insert into uare_master + ( + f_id + , org_name + , volume_id + , v_seq + , length + , comp_yn + , encrypt_yn + , org_date + , reg_date + , reg_time + , commit_stat + , session_key + , reg_user_id + , file_key + , f_group + , f_index + , bef_commit_stat + , repository + , clipid + , offset + ) + values + ( + #{f_id } + , #{org_name } + , #{volume_id } + , #{v_seq } + , #{length } + , #{comp_yn } + , #{encrypt_yn } + , #{org_date } + , #{reg_date } + , #{reg_time } + , #{commit_stat } + , #{session_key } + , #{reg_user_id } + , #{file_key } + , #{f_group } + , #{f_index } + , #{bef_commit_stat } + , #{repository } + , #{clipid } + , #{offset } + ) + + + + insert into uac_record + ( + record_id + , type_div_cd + , book_spcm_cpy_yn + ) + values + ( + #{record_id } + , #{type_div_cd } + , 'N' + ) + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ncmsdb/config/MybatisNcmsConfig.xml b/src/main/resources/mapper/ncmsdb/config/MybatisNcmsConfig.xml new file mode 100644 index 00000000..a61361c1 --- /dev/null +++ b/src/main/resources/mapper/ncmsdb/config/MybatisNcmsConfig.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ncmsdb/sqlmap/CommonMapper.xml b/src/main/resources/mapper/ncmsdb/sqlmap/CommonMapper.xml new file mode 100644 index 00000000..4f9b446d --- /dev/null +++ b/src/main/resources/mapper/ncmsdb/sqlmap/CommonMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml b/src/main/resources/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml new file mode 100644 index 00000000..024e71f6 --- /dev/null +++ b/src/main/resources/mapper/ncmsdb/sqlmap/ncmsDataMapper.xml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + /* ncmsDataDao.updateResultMultimediaAssets */ + update multimedia_assets + SET iams_tran_yn = #{iams_tran_yn} + , iams_tran_dt = sysdate() + , iams_tran_remark = #{iams_tran_remark} + , iams_tran_master_id = #{iams_tran_master_id} + WHERE id = #{id} + + + + + + \ No newline at end of file diff --git a/src/main/resources/secrets/UrpSystem.keystore b/src/main/resources/secrets/UrpSystem.keystore new file mode 100644 index 00000000..39528f7c --- /dev/null +++ b/src/main/resources/secrets/UrpSystem.keystore @@ -0,0 +1 @@ +aes256.key=52f48aa1c7435bc11bf909d9d7d1d5932f4bacd8184ec5c1eed6d03ee17fe126 \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/bodyTest.jsp b/src/main/webapp/WEB-INF/jsp/bodyTest.jsp new file mode 100644 index 00000000..ab57ea1f --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/bodyTest.jsp @@ -0,0 +1,6 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> + + + +여기는 body test jsp \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/tilesLayout/base-main.jsp b/src/main/webapp/WEB-INF/jsp/tilesLayout/base-main.jsp new file mode 100644 index 00000000..995fa00e --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/tilesLayout/base-main.jsp @@ -0,0 +1,38 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + +<% +response.setHeader("Cache-Control","no-store"); +response.setHeader("Pragma","no-cache"); +response.setDateHeader("Expires",0); +if (request.getProtocol().equals("HTTP/1.1")) response.setHeader("Cache-Control", "no-cache"); +%> + + + + + + + + 이미지 편집 시스템 + + + + + +
+ 여기는 base-main.jsp + + + + +
+ + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/tilesLayout/footer.jsp b/src/main/webapp/WEB-INF/jsp/tilesLayout/footer.jsp new file mode 100644 index 00000000..8e4b43c1 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/tilesLayout/footer.jsp @@ -0,0 +1,10 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + +
+
+ 여기는 footer +
+
+ + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/tilesLayout/header.jsp b/src/main/webapp/WEB-INF/jsp/tilesLayout/header.jsp new file mode 100644 index 00000000..4ce32cf8 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/tilesLayout/header.jsp @@ -0,0 +1,32 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + + + + + + + + + GDSC 이미지 저장 시스템 + + + + + + + + + + +
+
+
+ 여기는 header jsp +
+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/tiles/tiles.xml b/src/main/webapp/WEB-INF/tiles/tiles.xml new file mode 100644 index 00000000..61de8b5a --- /dev/null +++ b/src/main/webapp/WEB-INF/tiles/tiles.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file