commit 6c0a57c237f66c2a749d98c96e9f6d78c134da45 Author: Rinjae Date: Thu Jun 4 14:07:01 2026 +0900 - damo-manager Gradle 프로젝트 초기 구성 - scpdb 부재 시 fake 모드 자동 fallback - ScpEncB64/DecB64/HashB64 래핑 + 유틸 보존 - RealBridge 격리로 NoClassDefFoundError 방지 Co-Authored-By: Claude Opus 4.7 (1M context) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6acc4e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.gradle/ +build/ +.idea/ +*.iml +.classpath +.project +.settings/ +bin/ +out/ +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..9b3cab6 --- /dev/null +++ b/README.md @@ -0,0 +1,180 @@ +# damo-manager + +Penta scpdb 라이브러리 래퍼. **단일 jar (`damo-manager.jar`)** 로 운영/로컬 양쪽 환경에서 동작한다. + +- **운영**: 클래스패스에 `com.penta.scpdb.ScpDbAgent` 가 존재 → 실제 `ScpEncB64` / `ScpDecB64` / `ScpHashB64` 호출 +- **로컬 개발**: scpdb 라이브러리 없음 → 자동으로 **fake 모드** 진입, 시작 시 `System.err` 에 강한 경고 배너 출력. 암복호화는 단순 Base64 round-trip, 해시는 JRE `MessageDigest` 로 대체 + +## 빌드 + +```bash +cd damo-manager +gradle clean build # 또는 ./gradlew clean build (wrapper 추가 시) +ls build/libs/ # damo-manager.jar +``` + +JDK 8 toolchain 을 요구한다 (`build.gradle` 의 `JavaLanguageVersion.of(8)`). `JAVA_HOME` 이 JDK 8 이거나 Gradle 이 시스템에서 JDK 8 을 auto-detect 할 수 있어야 한다. + +Fake 모드 스모크 검증: + +```bash +gradle runFakeSmoke +``` + +## 소스 코드 커스터마이즈 + +`src/main/java/com/eactive/apim/custom/djb/damomanager/DamoManager.java` 상단 상수 영역을 수정한다. + +| 상수 | 의미 | 기본값 | +|---|---|---| +| `INI_FILE` | scpdb 에 전달할 ini 경로 | `/prod/damo/ba_scp/scpdb_agent.ini` | +| `KEY` | `ScpEncB64`/`ScpDecB64` 의 키 이름 | `KEY1` | +| `CHARSET` | scpdb 호출 시 charset 인자 | `EUC-KR` | +| `SHA256`, `SHA512` | 해시 type 상수 | `71`, `73` | + +새 scpdb 메서드를 래핑하려면 다음 4 곳을 동기화한다. + +1. `src/stub/java/com/penta/scpdb/ScpDbAgent.java` — 새 시그니처를 추가 (컴파일 통과용) +2. `DamoManager.RealBridge` — 실제 호출 메서드 추가 +3. `DamoManager` 공개 메서드 — `if (REAL_MODE) bridge.xxx(...) else fakeXxx(...)` +4. fake 분기 로직 작성 (보통 Base64 또는 JRE 기능) + +> Stub 은 `compileOnly` 로만 사용되므로 산출 jar 에 포함되지 않는다. 운영의 진짜 ScpDbAgent 메서드 시그니처와 stub 시그니처가 다르면 운영에서 `NoSuchMethodError` 가 발생하므로 정확히 일치시켜야 한다. + +## 결과물 사용 방법 + +### 권장: 빌드된 jar 직접 참조 + +타 Gradle 프로젝트에서는 `damo-manager.jar` 를 lib 폴더에 복사하여 직접 참조하는 방식을 권장한다. (Nexus 배포 없이 즉시 사용 가능) + +**Gradle**: + +```groovy +dependencies { + // 권장. 산출 jar 를 본인 프로젝트의 libs/ 에 복사 후 참조 + compileOnly files('libs/damo-manager.jar') + // 또는 다른 위치를 직접 가리킨다면 + // compileOnly files('../damo-manager/build/libs/damo-manager.jar') +} +``` + +WAS lib 폴더에서 클래스를 로드하므로 의존성 scope 는 반드시 **`compileOnly`** (또는 Maven 의 `provided`) 로 둔다. `implementation`/`api` 로 두면 war 에 중복 포함되어 ClassLoader 충돌 위험. + +`api` 로 다른 모듈에 노출이 필요하다면 동일하게 `files(...)` 를 `api` scope 로 (단, 위 충돌 가능성 인지). + +**Maven**: + +```xml + + com.eactive.apim.custom.djb + damo-manager + 1.0.0 + system + ${project.basedir}/libs/damo-manager.jar + +``` + +또는 사내 Nexus 등에 배포 시 `provided`. + +### WAS (Tomcat) 설치 + +운영 / 로컬에 따라 lib 폴더 구성이 다르다. + +**운영 (Tomcat)**: + +``` +$CATALINA_HOME/lib/ +├── damo-manager.jar +└── libs_scpdb-*.jar ← penta scpdb 라이브러리 (실 암복호화) +``` + +`libs_scpdb-*.jar` 와 함께 네이티브 .so/.dll 및 `/prod/damo/ba_scp/scpdb_agent.ini` 도 준비되어 있어야 한다. + +**로컬 개발**: + +``` +$CATALINA_HOME/lib/ +└── damo-manager.jar ← 단독. scpdb 라이브러리 없음 +``` + +WAS 기동 시 콘솔(`catalina.out` 또는 stderr)에 다음과 같은 배너가 출력되면 정상 동작이다. + +``` +============================================================ + *** DAMO-MANAGER FAKE MODE *** + com.penta.scpdb.ScpDbAgent NOT FOUND on classpath. + Fallback: + encrypt/decrypt -> Base64 (NO ENCRYPTION) + hash -> JRE MessageDigest (SHA-256 / SHA-512) + *** DO NOT use this build for production! *** +============================================================ +``` + +> Fake 모드는 **암호화가 전혀 없는 단순 Base64 통과** 이므로 운영 절대 금지. + +## 주요 메서드 + +```java +import com.eactive.apim.custom.djb.damomanager.DamoManager; + +DamoManager damo = new DamoManager(); // 클래스 로딩 시점에 모드 감지 + +String cipher = damo.encrypt("hello"); // Base64 cipher text +String plain = damo.decrypt(cipher); // → "hello" +String h256 = damo.hash(DamoManager.SHA256, "password"); // SHA-256 base64 +String h512 = damo.hash(DamoManager.SHA512, "password"); // SHA-512 base64 + +boolean fake = damo.isFakeMode(); // 디버깅 / 분기용 +int rc = damo.getReturnCode(); // 0: 성공, -1: 실패 +``` + +| 메서드 | 운영 동작 | Fake 동작 | +|---|---|---| +| `String encrypt(String plain)` | `ScpEncB64(INI_FILE, "KEY1", plain, "EUC-KR")` | `Base64.encode(plain.getBytes("EUC-KR"))` | +| `String decrypt(String b64)` | `ScpDecB64(INI_FILE, "KEY1", b64, "EUC-KR")` | `new String(Base64.decode(b64), "EUC-KR")` | +| `String hash(int type, String src)` | `ScpHashB64(type, src, "EUC-KR")` | `MessageDigest(SHA-256/512).digest(src) → Base64` | + +해시 `type` 상수: + +| 상수 | 값 | 알고리즘 | +|---|---|---| +| `DamoManager.SHA256` | 71 | SHA-256 | +| `DamoManager.SHA512` | 73 | SHA-512 | + +기타 유틸 (원본 DamoManager 호환): + +- `Base64Encode(byte[])`, `Base64Decode(String)` +- `byteToHex(byte[])`, `byteArrayToHex(byte[])` +- `checkHangul(char)` +- `getReturnCode()`, `getRevision()` + +## 검증 + +스모크 main 이 포함되어 있다. + +```bash +java -cp build/libs/damo-manager.jar com.eactive.apim.custom.djb.damomanager.DamoManager +``` + +또는: + +```bash +gradle runFakeSmoke +``` + +예상 출력: + +``` +============================================================ + *** DAMO-MANAGER FAKE MODE *** + ... +============================================================ + +revision = 20160503 +fakeMode = true +encrypt = aGVsbG8sIL3M3sCw +decrypt = hello, 다모 +roundtrip = true +sha256 b64 = ... (len=44) +sha512 b64 = ... (len=88) +``` diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..f279532 --- /dev/null +++ b/build.gradle @@ -0,0 +1,50 @@ +plugins { + id 'java-library' +} + +group = 'com.eactive.apim.custom.djb' +version = '1.0.0' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } +} + +sourceSets { + stub { + java { + srcDirs = ['src/stub/java'] + } + } +} + +dependencies { + // scpdb 가짜 시그니처. 메인 컴파일 통과 전용. 최종 jar 에는 포함되지 않음. + compileOnly sourceSets.stub.output +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' +} + +jar { + archiveBaseName = 'damo-manager' + archiveVersion = '' + manifest { + attributes( + 'Implementation-Title' : 'damo-manager', + 'Implementation-Version': project.version, + 'Built-By' : 'damo-manager gradle build' + ) + } +} + +// Fake 모드 스모크 검증용. 실행: ./gradlew runFakeSmoke +tasks.register('runFakeSmoke', JavaExec) { + group = 'verification' + description = 'Run DamoManager main() with no scpdb on classpath (fake mode smoke test)' + classpath = sourceSets.main.runtimeClasspath + mainClass = 'com.eactive.apim.custom.djb.damomanager.DamoManager' + dependsOn 'classes' +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..1dfe1f9 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'damo-manager' diff --git a/src/main/java/com/eactive/apim/custom/djb/damomanager/DamoManager.java b/src/main/java/com/eactive/apim/custom/djb/damomanager/DamoManager.java new file mode 100644 index 0000000..e28a794 --- /dev/null +++ b/src/main/java/com/eactive/apim/custom/djb/damomanager/DamoManager.java @@ -0,0 +1,363 @@ +package com.eactive.apim.custom.djb.damomanager; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; + +/** + * 운영(penta scpdb 라이브러리 존재) / 로컬(scpdb 부재) 양쪽에서 동작하는 단일 클래스. + * + * 클래스패스에 {@code com.penta.scpdb.ScpDbAgent} 가 존재하면 실 호출, 아니면 fake 모드로 자동 fallback. + * fake 모드 진입 시 클래스 로딩 시점에 System.err 로 강한 경고 배너 출력. + * + * fake 모드 동작: + * - encrypt(s) : Base64.encode(s.getBytes(EUC-KR)) -- 암호화 없음 + * - decrypt(s) : new String(Base64.decode(s), EUC-KR) + * - hash(t, s) : SHA-256(71) / SHA-512(73) JRE MessageDigest -> Base64 + */ +public class DamoManager { + + public static final int SHA256 = 71; + public static final int SHA512 = 73; + + private static final String INI_FILE = "/prod/damo/ba_scp/scpdb_agent.ini"; + private static final String KEY = "KEY1"; + private static final String CHARSET = "EUC-KR"; + + private static final int SCP_OK = 0; + private static final int SCP_FAIL = -1; + + private static final boolean REAL_MODE; + + static { + boolean real; + try { + Class.forName("com.penta.scpdb.ScpDbAgent", false, + DamoManager.class.getClassLoader()); + real = true; + } catch (Throwable t) { + real = false; + printFakeBanner(); + } + REAL_MODE = real; + } + + private static void printFakeBanner() { + String line = "============================================================"; + System.err.println(); + System.err.println(line); + System.err.println(" *** DAMO-MANAGER FAKE MODE ***"); + System.err.println(" com.penta.scpdb.ScpDbAgent NOT FOUND on classpath."); + System.err.println(" Fallback:"); + System.err.println(" encrypt/decrypt -> Base64 (NO ENCRYPTION)"); + System.err.println(" hash -> JRE MessageDigest (SHA-256 / SHA-512)"); + System.err.println(" *** DO NOT use this build for production! ***"); + System.err.println(line); + System.err.println(); + System.err.flush(); + } + + private final String szRevision = "20160503"; + private int nReturn; + private final RealBridge bridge; + + public DamoManager() { + if (REAL_MODE) { + this.bridge = new RealBridge(); + int rc = this.bridge.init(); + if (rc == 0 || rc == 118) { + this.nReturn = SCP_OK; + } else { + this.nReturn = rc; + } + } else { + this.bridge = null; + this.nReturn = SCP_OK; + } + } + + public String getRevision() { + return this.szRevision; + } + + public int getReturnCode() { + return this.nReturn; + } + + public boolean isFakeMode() { + return !REAL_MODE; + } + + // ----------------------------------------------------------------- + // 운영: ScpEncB64 / ScpDecB64 / ScpHashB64 래핑 + // ----------------------------------------------------------------- + + /** + * 평문 문자열을 ScpEncB64 로 암호화하여 Base64 cipher text 반환. + * fake 모드: 단순 Base64 인코딩. + */ + public String encrypt(String plain) { + if (plain == null) { + this.nReturn = SCP_FAIL; + return ""; + } + if (REAL_MODE) { + try { + String out = this.bridge.encB64(plain); + this.nReturn = SCP_OK; + return out; + } catch (Throwable t) { + t.printStackTrace(); + this.nReturn = SCP_FAIL; + return ""; + } + } + try { + this.nReturn = SCP_OK; + return Base64.getEncoder().encodeToString(plain.getBytes(CHARSET)); + } catch (UnsupportedEncodingException e) { + this.nReturn = SCP_FAIL; + return Base64.getEncoder().encodeToString(plain.getBytes()); + } + } + + /** + * Base64 cipher text 를 ScpDecB64 로 복호화하여 평문 반환. + * fake 모드: 단순 Base64 디코딩. + */ + public String decrypt(String base64Cipher) { + if (base64Cipher == null) { + this.nReturn = SCP_FAIL; + return ""; + } + if (REAL_MODE) { + try { + String out = this.bridge.decB64(base64Cipher); + this.nReturn = SCP_OK; + return out; + } catch (Throwable t) { + t.printStackTrace(); + this.nReturn = SCP_FAIL; + return ""; + } + } + try { + byte[] decoded = Base64.getDecoder().decode(base64Cipher); + this.nReturn = SCP_OK; + try { + return new String(decoded, CHARSET); + } catch (UnsupportedEncodingException e) { + return new String(decoded); + } + } catch (IllegalArgumentException e) { + this.nReturn = SCP_FAIL; + return ""; + } + } + + /** + * 단방향 해시. type 71 = SHA-256, 73 = SHA-512. 결과는 Base64 문자열. + * fake 모드: JRE MessageDigest 사용 (실제 SHA-256/512 결과를 Base64 로 반환). + */ + public String hash(int type, String src) { + if (src == null) { + this.nReturn = SCP_FAIL; + return ""; + } + if (REAL_MODE) { + try { + String out = this.bridge.hashB64(type, src); + this.nReturn = SCP_OK; + return out; + } catch (Throwable t) { + t.printStackTrace(); + this.nReturn = SCP_FAIL; + return ""; + } + } + String algo; + if (type == SHA256) { + algo = "SHA-256"; + } else if (type == SHA512) { + algo = "SHA-512"; + } else { + this.nReturn = SCP_FAIL; + return ""; + } + try { + MessageDigest md = MessageDigest.getInstance(algo); + byte[] bytes; + try { + bytes = md.digest(src.getBytes(CHARSET)); + } catch (UnsupportedEncodingException e) { + bytes = md.digest(src.getBytes()); + } + this.nReturn = SCP_OK; + return Base64.getEncoder().encodeToString(bytes); + } catch (NoSuchAlgorithmException e) { + this.nReturn = SCP_FAIL; + return ""; + } + } + + // ----------------------------------------------------------------- + // Utility (원본 DamoManager 에서 그대로 보존) + // ----------------------------------------------------------------- + + public String Base64Encode(byte[] var1) { + char[] var2 = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; + StringBuilder var3 = new StringBuilder(); + int var4 = 0; + + for (int var5 = 0; var5 < var1.length; var5 += 3) { + int var6 = (var1[var5] & 255) << 16 & 16777215; + if (var5 + 1 < var1.length) { + var6 |= (var1[var5 + 1] & 255) << 8; + } else { + ++var4; + } + + if (var5 + 2 < var1.length) { + var6 |= var1[var5 + 2] & 255; + } else { + ++var4; + } + + for (int var7 = 0; var7 < 4 - var4; ++var7) { + int var8 = (var6 & 16515072) >> 18; + var3.append(var2[var8]); + var6 <<= 6; + } + } + + for (int var9 = 0; var9 < var4; ++var9) { + var3.append("="); + } + + return var3.toString(); + } + + public byte[] Base64Decode(String var1) { + int[] var2 = new int[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + byte[] var3 = var1.getBytes(); + ByteArrayOutputStream var4 = new ByteArrayOutputStream(); + int var5 = 0; + + while (var5 < var3.length) { + int var6 = 0; + if (var2[var3[var5]] != -1) { + var6 = (var2[var3[var5]] & 255) << 18; + int var7 = 0; + if (var5 + 1 < var3.length && var2[var3[var5 + 1]] != -1) { + var6 |= (var2[var3[var5 + 1]] & 255) << 12; + ++var7; + } + + if (var5 + 2 < var3.length && var2[var3[var5 + 2]] != -1) { + var6 |= (var2[var3[var5 + 2]] & 255) << 6; + ++var7; + } + + if (var5 + 3 < var3.length && var2[var3[var5 + 3]] != -1) { + var6 |= var2[var3[var5 + 3]] & 255; + ++var7; + } + + while (var7 > 0) { + int var8 = (var6 & 16711680) >> 16; + var4.write((char) var8); + var6 <<= 8; + --var7; + } + + var5 += 4; + } else { + ++var5; + } + } + + return var4.toByteArray(); + } + + public String byteToHex(byte[] var1) { + String var2 = ""; + String var3 = ""; + + for (int var4 = 0; var4 < var1.length; ++var4) { + var3 = Integer.toHexString(var1[var4]); + if (var3.length() >= 2) { + var3 = var3.substring(var3.length() - 2); + } else { + for (int var5 = 0; var5 < 2 - var3.length(); ++var5) { + var3 = "0" + var3; + } + } + + var2 = var2 + " " + var3; + } + + return var2.toUpperCase(); + } + + public String byteArrayToHex(byte[] var1) { + StringBuilder var2 = new StringBuilder(); + + for (byte var6 : var1) { + var2.append(String.format("%02x ", var6 & 255)); + } + + return var2.toString(); + } + + public boolean checkHangul(char var1) { + return var1 >= '가' && var1 <= '힣'; + } + + // ----------------------------------------------------------------- + // 운영 ScpDbAgent 호출 격리. REAL_MODE == true 일 때만 인스턴스화되어 + // ScpDbAgent 심볼이 JVM 에 resolve 된다. fake 모드에서는 이 클래스 자체가 + // 로딩되지 않으므로 NoClassDefFoundError 가 발생하지 않는다. + // ----------------------------------------------------------------- + private static final class RealBridge { + private final com.penta.scpdb.ScpDbAgent agt = new com.penta.scpdb.ScpDbAgent(); + + int init() { + return agt.AgentInit(INI_FILE); + } + + String encB64(String src) { + return agt.ScpEncB64(INI_FILE, KEY, src, CHARSET); + } + + String decB64(String src) { + return agt.ScpDecB64(INI_FILE, KEY, src, CHARSET); + } + + String hashB64(int type, String src) { + return agt.ScpHashB64(type, src, CHARSET); + } + } + + // ----------------------------------------------------------------- + // Smoke test 용 main. 운영 코드에서는 호출되지 않음. + // ----------------------------------------------------------------- + public static void main(String[] args) { + DamoManager m = new DamoManager(); + System.out.println("revision = " + m.getRevision()); + System.out.println("fakeMode = " + m.isFakeMode()); + + String plain = "hello, 다모"; + String enc = m.encrypt(plain); + String dec = m.decrypt(enc); + System.out.println("encrypt = " + enc); + System.out.println("decrypt = " + dec); + System.out.println("roundtrip = " + plain.equals(dec)); + + String h256 = m.hash(SHA256, plain); + String h512 = m.hash(SHA512, plain); + System.out.println("sha256 b64 = " + h256 + " (len=" + h256.length() + ")"); + System.out.println("sha512 b64 = " + h512 + " (len=" + h512.length() + ")"); + } +} diff --git a/src/stub/java/com/penta/scpdb/ScpDbAgent.java b/src/stub/java/com/penta/scpdb/ScpDbAgent.java new file mode 100644 index 0000000..193f6d6 --- /dev/null +++ b/src/stub/java/com/penta/scpdb/ScpDbAgent.java @@ -0,0 +1,29 @@ +package com.penta.scpdb; + +/** + * Stub. DamoManager 컴파일 통과 전용으로, 운영에서는 실제 penta scpdb 라이브러리의 동일 FQCN 클래스가 사용된다. + * 본 stub 은 산출 jar 에 포함되지 않는다 (build.gradle 의 compileOnly). + * + * DamoManager 가 호출하는 시그니처만 노출한다. + */ +public class ScpDbAgent { + + public ScpDbAgent() { + } + + public int AgentInit(String iniFile) { + return 0; + } + + public String ScpEncB64(String iniFile, String key, String src, String charset) throws ScpDbAgentException { + return null; + } + + public String ScpDecB64(String iniFile, String key, String src, String charset) throws ScpDbAgentException { + return null; + } + + public String ScpHashB64(int type, String src, String charset) throws ScpDbAgentException { + return null; + } +} diff --git a/src/stub/java/com/penta/scpdb/ScpDbAgentException.java b/src/stub/java/com/penta/scpdb/ScpDbAgentException.java new file mode 100644 index 0000000..4228587 --- /dev/null +++ b/src/stub/java/com/penta/scpdb/ScpDbAgentException.java @@ -0,0 +1,29 @@ +package com.penta.scpdb; + +/** + * Stub. 운영 환경에서는 실제 penta scpdb 라이브러리의 동일 클래스로 대체된다. + * 본 stub 은 컴파일 통과 전용이며 산출 jar 에는 포함되지 않는다. + */ +public class ScpDbAgentException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + private int returnedValue; + + public ScpDbAgentException() { + super(); + } + + public ScpDbAgentException(String message) { + super(message); + } + + public ScpDbAgentException(String message, int returnedValue) { + super(message); + this.returnedValue = returnedValue; + } + + public int returnedValue() { + return returnedValue; + } +}