commit aacc1a389e145453cf92c18e9d7ffef568cf89e7
Author: Rinjae
Date: Fri Sep 5 18:57:45 2025 +0900
init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0aaaf8c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,234 @@
+gradle.properties
+
+# Package Files #
+*.war
+
+src/main/generated
+
+# Eclipse #
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+.classpath
+.project
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# CDT- autotools
+.autotools
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/
+
+# Annotation Processing
+.apt_generated/
+.apt_generated_test/
+
+# Scala IDE specific (Scala & Java development for Eclipse)
+.cache-main
+.scala_dependencies
+.worksheet
+
+# Uncomment this line if you wish to ignore the project description file.
+# Typically, this file would be tracked if it contains build/dependency configurations:
+#.project
+### Intellij ###
+.idea
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator/
+
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### Gradle ###
+.gradle
+build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Cache of project
+.gradletasknamecache
+
+# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
+# gradle/wrapper/gradle-wrapper.properties
+
+### Gradle Patch ###
+**/build/
+
+# End of https://www.gitignore.io/api/java,macos,gradle,intellij
+/EAISIMWeb/
+/.apt_generated_tests/
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..ad821c2
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,221 @@
+plugins {
+ id 'java-library'
+ id 'maven-publish'
+ id 'eclipse-wtp'
+ id 'idea'
+ id 'com.diffplug.eclipse.apt' version '3.41.1'
+}
+group 'com.eactive'
+version '4.5.1-SNAPSHOT'
+
+def springVersion = "5.3.27"
+def quartzVersion = "2.3.2"
+def undertowVersion = "1.4.28.Final"
+def queryDslVersion = "5.0.0"
+def hibernateVersion = "5.6.15.Final"
+
+def nexusUrl = "https://nexus.eactive.synology.me:8090"
+def generatedJavaDir = "$buildDir/generated/java"
+
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(8)
+ }
+}
+
+compileJava {
+ options.encoding = 'UTF-8'
+ sourceSets.main.java { srcDir generatedJavaDir }
+ options.generatedSourceOutputDirectory = project.file(generatedJavaDir)
+
+ aptOptions {
+ processorArgs = [ 'querydsl.generatedAnnotationClass' : 'com.querydsl.core.annotations.Generated' ]
+ }
+}
+
+jar {
+ exclude '**/persistence.xml'
+}
+
+tasks.withType(JavaCompile) {
+ options.encoding = 'UTF-8'
+}
+
+dependencies {
+
+ annotationProcessor "org.projectlombok:lombok:1.18.28", "org.projectlombok:lombok-mapstruct-binding:0.2.0", "org.mapstruct:mapstruct-processor:1.5.5.Final"
+ annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jpa", "jakarta.persistence:jakarta.persistence-api:2.2.3", "jakarta.annotation:jakarta.annotation-api:1.3.5"
+
+ //implementation project(':elink-online-core')
+ //implementation project(':elink-online-transformer')
+ api project(':elink-online-transformer')
+
+ compileOnly fileTree(dir: 'libs', include: ['*.jar'])
+
+ api (group: 'org.apache.activemq', name: 'activemq-console', version: '5.14.5'){
+ exclude group: 'com.fasterxml.jackson.core'
+ }
+ api group: 'org.apache.activemq', name: 'activemq-spring', version: '5.14.5'
+
+ api 'backport-util-concurrent:backport-util-concurrent:3.0'
+
+ api 'com.github.vladimir-bukhtoyarov:bucket4j-jcache:6.0.2'
+ api 'io.github.resilience4j:resilience4j-core:1.7.1'
+ api 'io.github.resilience4j:resilience4j-circuitbreaker:1.7.1'
+ api 'io.github.resilience4j:resilience4j-micrometer:1.7.1'
+ api 'io.micrometer:micrometer-core:1.5.17'
+ api 'io.micrometer:micrometer-registry-prometheus:1.5.17'
+
+ //api "com.eactive:mina-core-1.0.10-custom:1.0:custom@jar"
+ api ("org.apache.mina:mina-filter-ssl:1.0.10") {
+ exclude module: 'mina-core'
+ }
+
+ api group: 'commons-fileupload', name: 'commons-fileupload', version: '1.5'
+
+ api 'org.snmp4j:snmp4j:1.9.1f'
+ api group: 'com.lmax', name: 'disruptor', version: '3.4.4'
+ api group: 'commons-httpclient', name: 'commons-httpclient', version: '3.1'
+// api group: 'log4j', name: 'log4j', version: '1.2.17'
+
+ api 'com.nimbusds:nimbus-jose-jwt:9.24.3'
+
+ api "io.undertow:undertow-servlet:${undertowVersion}"
+ api 'org.java-websocket:Java-WebSocket:1.3.9'
+ api 'javax.cache:cache-api:1.1.1'
+
+ api 'org.apache.ignite:ignite-slf4j:2.14.0'
+ api 'org.apache.ignite:ignite-kubernetes:2.14.0'
+
+ //api 'com.eactive:xc3:1.0'
+ //api 'com.eactive:xc2:1.0'
+ //api 'com.eactive:INICrypto:v4.1.22'
+ //api 'com.eactive:INISAFECore:v2.2.28'
+ //api 'com.eactive:INISAFENet:v7.2.51_NS'
+ //api 'com.eactive:INISAFEPKI:v1.1.33'
+
+ //api 'com.eactive:Egloan_aes:1.0'
+ //api 'com.eactive:ExafeiE2E:1.0'
+ //api 'com.eactive:tcseed:1.0'
+ //api "com.eactive:backport-util-concurrent:1.0"
+
+ api "org.quartz-scheduler:quartz:${quartzVersion}"
+
+ api group: 'commons-cli', name: 'commons-cli', version: '1.1'
+ api "org.springframework:spring-web:${springVersion}"
+ api "org.springframework:spring-jms:${springVersion}"
+ api "org.springframework.security.oauth:spring-security-oauth2:2.3.8.RELEASE"
+
+ api 'org.yaml:snakeyaml:1.30'
+ implementation 'org.codehaus.groovy:groovy:3.0.18'
+
+ api 'org.slf4j:jul-to-slf4j:1.7.35'
+ api 'org.slf4j:jcl-over-slf4j:1.7.35'
+ api 'org.slf4j:log4j-over-slf4j:1.7.35'
+ api 'org.slf4j:slf4j-api:1.7.35'
+
+ //compileOnly "tmax:webt:7.0.2.0-r11661-forJEUS8.0"
+ //compileOnly "tmax:webtasync:2.0.3.1-r11801-forJEUS8.1"
+ //compileOnly "tmax:jeus:1.0"
+
+ api 'org.apache.httpcomponents.client5:httpclient5:5.1'
+ api 'org.apache.httpcomponents.core5:httpcore5:5.1'
+
+ compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
+ compileOnly group: 'javax.servlet.jsp', name: 'javax.servlet.jsp-api', version: '2.3.3'
+ compileOnly 'javax.resource:javax.resource-api:1.7'
+ compileOnly 'javax.jms:javax.jms-api:2.0.1'
+
+ compileOnly group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.13.1'
+
+ testRuntimeOnly 'com.h2database:h2:2.1.214'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.15'
+ testImplementation 'junit:junit:4.4'
+}
+
+test {
+ useJUnitPlatform()
+}
+
+publishing {
+ repositories {
+ maven {
+ name = 'eactiveRepository'
+ def releasesRepoUrl = "${nexusUrl}/repository/maven-releases/"
+ def snapshotsRepoUrl = "${nexusUrl}/repository/maven-snapshots/"
+ url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
+ credentials(PasswordCredentials)
+ }
+ }
+
+ publications {
+ mavenJava(MavenPublication) {
+ from components.java
+ pom {
+ description = "eLink common module"
+ licenses {
+ license {
+ name = "Commercial License"
+ url = "http://eactive.co.kr"
+ }
+ }
+ }
+ }
+ }
+}
+
+task sourcesJar(type: Jar, dependsOn: classes) {
+ archiveClassifier = 'sources'
+ from sourceSets.main.allSource
+}
+
+artifacts {
+ archives sourcesJar
+}
+
+configurations.all {
+ exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jta_1.0.1B_spec'
+// exclude group: 'javax.transaction', module: 'javax.transaction-api'
+ resolutionStrategy {
+ // 동적 버전 탐색을 10분 캐시
+ cacheDynamicVersionsFor 10, 'minutes'
+ // 변하는 모듈(Changing Module)을 캐시하지 않음
+ cacheChangingModulesFor 0, 'seconds'
+ }
+}
+
+task settingEclipseEncoding {
+ if (project.file('.settings').exists()) {
+ File f = file('.settings/org.eclipse.core.resources.prefs')
+ f.write('eclipse.preferences.version=1\n')
+ f.append('encoding/=utf-8')
+ }
+}
+
+task initDirs() {
+ file(generatedJavaDir).mkdirs()
+}
+
+eclipse {
+ synchronizationTasks settingEclipseEncoding, initDirs
+ jdt {
+ apt {
+ // generated 된 패스 경로를 .setting/org.eclipse.jdt.apt.core.prefs 의 org.eclipse.jdt.apt.genSrcDir에 적용한다.
+ // project > properties > Java Compiler > Annoation Processing 화면에서 확인 가능하다.
+ genSrcDir = file(generatedJavaDir)
+ }
+ }
+ project {
+ natures = ['org.eclipse.buildship.core.gradleprojectnature',
+ 'org.eclipse.jdt.core.javanature',
+ 'org.eclipse.wst.common.project.facet.core.nature',
+ 'org.eclipse.wst.common.modulecore.ModuleCoreNature',
+ 'org.eclipse.jem.workbench.JavaEMFNature']
+ buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
+ buildCommand 'org.eclipse.wst.validation.validationbuilder'
+ buildCommand 'org.eclipse.wst.common.project.facet.core.builder'
+ buildCommand 'org.eclipse.jdt.core.javabuilder'
+ }
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..41d9927
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..54228ea
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+networkTimeout=10000
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..1b6c787
--- /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 0000000..107acd3
--- /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/libs/Egloan_aes-1.0.jar b/libs/Egloan_aes-1.0.jar
new file mode 100644
index 0000000..db2be2c
Binary files /dev/null and b/libs/Egloan_aes-1.0.jar differ
diff --git a/libs/ExafeiE2E-1.0.jar b/libs/ExafeiE2E-1.0.jar
new file mode 100644
index 0000000..065331d
Binary files /dev/null and b/libs/ExafeiE2E-1.0.jar differ
diff --git a/libs/INICrypto-v4.1.22.jar b/libs/INICrypto-v4.1.22.jar
new file mode 100644
index 0000000..9208a07
Binary files /dev/null and b/libs/INICrypto-v4.1.22.jar differ
diff --git a/libs/INISAFECore-v2.2.28.jar b/libs/INISAFECore-v2.2.28.jar
new file mode 100644
index 0000000..92da7c6
Binary files /dev/null and b/libs/INISAFECore-v2.2.28.jar differ
diff --git a/libs/INISAFENet-v7.2.51_NS.jar b/libs/INISAFENet-v7.2.51_NS.jar
new file mode 100644
index 0000000..92bbc05
Binary files /dev/null and b/libs/INISAFENet-v7.2.51_NS.jar differ
diff --git a/libs/INISAFEPKI-v1.1.33.jar b/libs/INISAFEPKI-v1.1.33.jar
new file mode 100644
index 0000000..c3daa57
Binary files /dev/null and b/libs/INISAFEPKI-v1.1.33.jar differ
diff --git a/libs/asm-9.3.jar b/libs/asm-9.3.jar
new file mode 100644
index 0000000..bd8b948
Binary files /dev/null and b/libs/asm-9.3.jar differ
diff --git a/libs/jeus-1.0.jar b/libs/jeus-1.0.jar
new file mode 100644
index 0000000..5609e28
Binary files /dev/null and b/libs/jeus-1.0.jar differ
diff --git a/libs/json-path-2.9.0.jar b/libs/json-path-2.9.0.jar
new file mode 100644
index 0000000..f731408
Binary files /dev/null and b/libs/json-path-2.9.0.jar differ
diff --git a/libs/json-simple-1.1.1-custom-1.2.jar b/libs/json-simple-1.1.1-custom-1.2.jar
new file mode 100644
index 0000000..d7fd255
Binary files /dev/null and b/libs/json-simple-1.1.1-custom-1.2.jar differ
diff --git a/libs/json-smart-2.5.0.jar b/libs/json-smart-2.5.0.jar
new file mode 100644
index 0000000..2685e03
Binary files /dev/null and b/libs/json-smart-2.5.0.jar differ
diff --git a/libs/mina-core-1.0.10-custom-1.0-custom.jar b/libs/mina-core-1.0.10-custom-1.0-custom.jar
new file mode 100644
index 0000000..3add5c8
Binary files /dev/null and b/libs/mina-core-1.0.10-custom-1.0-custom.jar differ
diff --git a/libs/tcseed-1.0.jar b/libs/tcseed-1.0.jar
new file mode 100644
index 0000000..f23ad49
Binary files /dev/null and b/libs/tcseed-1.0.jar differ
diff --git a/libs/webt-7.0.2.0-r11661-forJEUS8.0.jar b/libs/webt-7.0.2.0-r11661-forJEUS8.0.jar
new file mode 100644
index 0000000..f5b6c66
Binary files /dev/null and b/libs/webt-7.0.2.0-r11661-forJEUS8.0.jar differ
diff --git a/libs/webtasync-2.0.3.1-r11801-forJEUS8.1.jar b/libs/webtasync-2.0.3.1-r11801-forJEUS8.1.jar
new file mode 100644
index 0000000..a057b7f
Binary files /dev/null and b/libs/webtasync-2.0.3.1-r11801-forJEUS8.1.jar differ
diff --git a/libs/xc2-1.0.jar b/libs/xc2-1.0.jar
new file mode 100644
index 0000000..676cb03
Binary files /dev/null and b/libs/xc2-1.0.jar differ
diff --git a/libs/xc3-1.0.jar b/libs/xc3-1.0.jar
new file mode 100644
index 0000000..7f53f93
Binary files /dev/null and b/libs/xc3-1.0.jar differ
diff --git a/resources/standard-layout-sample.csv b/resources/standard-layout-sample.csv
new file mode 100644
index 0000000..7a289f0
--- /dev/null
+++ b/resources/standard-layout-sample.csv
@@ -0,0 +1,29 @@
+#-----------------------------------------------------------------------------
+# comment start with #
+# level; // 0 : root ~ n
+# type; // 0: Message, 1: Field, 2:Group 3, Grid, 4 : Field Array, 9 : BIZ DATA
+# size // 0 : variable, > 0 fixed
+# fieldType; // 0: ELEMENT, 1: ATTRIBUTE,
+# length;
+# dataType; // 1: String, 2: Number,11: ZZ String, 12: LL Number
+#-----------------------------------------------------------------------------
+# name ,level ,type ,size ,fieldType ,length ,dataType ,,refPath, refValue,value
+#-----------------------------------------------------------------------------
+ElinkHeader ,0,0,1,0, 0,0,,,
+Header ,1,2,1,1, 0,0,,,
+StndCicsTrncd ,2,1,1,1,10,0,,,
+StndIntnlStndTelgmLen,2,1,1,1,10,11,,,0
+StndTranBaseYmd ,2,1,1,1,10,0,,,
+Common ,1,2,0,0, 0,0,Header.StndCicsTrncd,JI6H,null
+TranInfo ,2,2,1,0, 0,0,,,
+StndCicsTrncd ,3,1,1,0, 3,0,,,
+StndTelgmRecvTranCd ,3,1,1,0,10,0,,,
+StndPrcssRtdTranCd ,3,1,1,0,10,0,,,
+Array ,1,3,0,0, 3,0,,,
+Item1 ,2,1,1,0,10,0,,,JI6H
+Group ,2,3,1,0, 1,0,,,
+gitem1 ,3,1,1,0,10,1,,,726
+gitem2 ,3,1,1,0,10,0,,,20220905
+FArray ,1,4,0,0,10,0,,,
+bizData ,1,9,1,0, 0,0,,,
+zzData ,1,1,1,0, 2,10,,,ZZ
\ No newline at end of file
diff --git a/resources/standard-layout.csv b/resources/standard-layout.csv
new file mode 100644
index 0000000..0a22fef
--- /dev/null
+++ b/resources/standard-layout.csv
@@ -0,0 +1,41 @@
+#-----------------------------------------------------------------------------
+# comment start with #
+# level; // 0 : root ~ n
+# type; // 0: Message, 1: Field, 2:Group 3, Grid, 4 : Field Array, 9 : BIZ DATA
+# size // 0 : variable, > 0 fixed
+# fieldType; // 0: ELEMENT, 1: ATTRIBUTE,
+# length;
+# dataType; // 1: String, 2: Number,11: ZZ String, 12: LL Number
+#-----------------------------------------------------------------------------
+# name ,level ,type ,size ,fieldType ,length ,dataType ,,refPath, refValue,value
+#-----------------------------------------------------------------------------
+# name ,level ,type ,size ,fieldType ,length ,dataType ,refPath, refValue, value
+STD_HNCPHEADER_REQ ,0 ,1 ,1 ,1 ,0 ,1 , , ,,표준헤더
+msg_len ,1 ,2 ,1 ,1 ,6 ,12 , , ,199,전문길이
+global_id ,1 ,2 ,1 ,1 ,29 ,1 , , ,GIDNO00000000001111,Global아이디
+service_id ,1 ,2 ,1 ,1 ,10 ,1 , , ,ELINKSVC01,거래코드
+service_cmt ,1 ,2 ,1 ,1 ,100 ,1 , , ,ELINK TEST Service,거래코드설명
+service_tn ,1 ,2 ,1 ,1 ,1 ,1 , , ,1,거래구분
+Session_id ,1 ,2 ,1 ,1 ,100 ,1 , , ,SESSIONID001,Session아이디
+encrypt_yn ,1 ,2 ,1 ,1 ,2 ,1 , , ,NO,전문암호화여부
+http_url ,1 ,2 ,1 ,1 ,100 ,1 , , ,,HTTPURL정보
+screen_id ,1 ,2 ,1 ,1 ,13 ,1 , , ,SCREEN0000001,화면ID
+scr_no ,1 ,2 ,1 ,1 ,30 ,1 , , ,000000000100000000020000000003,화면번호
+scr_dsc ,1 ,2 ,1 ,1 ,100 ,1 , , ,,화면명
+usr_id ,1 ,2 ,1 ,1 ,10 ,1 , , ,USER000001,사용자ID
+ip_addr ,1 ,2 ,1 ,1 ,47 ,1 , , ,,IPAddress
+ip_mac ,1 ,2 ,1 ,1 ,12 ,1 , , ,,ClientMAC Address
+com_code ,1 ,2 ,1 ,1 ,4 ,1 , , ,EACT,그룹사코드
+head_code ,1 ,2 ,1 ,1 ,7 ,1 , , ,EACT001,본부코드
+dept_cd ,1 ,2 ,1 ,1 ,7 ,1 , , ,ELINK01,부서코드
+conn_tp ,1 ,2 ,1 ,1 ,2 ,1 , , ,CH,요청채널구분
+Inter_chn ,1 ,2 ,1 ,1 ,2 ,1 , , ,EA,시스템구분
+recv_tm ,1 ,2 ,1 ,1 ,17 ,1 , , ,20220928000000000,전문수신시간
+send_tm ,1 ,2 ,1 ,1 ,17 ,1 , , ,,전문송신시간
+return_gubun ,1 ,2 ,1 ,1 ,1 ,1 , , ,S,전문응답구분
+return_value ,1 ,2 ,1 ,1 ,1 ,1 , , ,,처리결과
+msg_id ,1 ,2 ,1 ,1 ,7 ,1 , , ,,오류코드
+msg_nm ,1 ,2 ,1 ,1 ,250 ,1 , , ,,오류메시지
+filler ,1 ,2 ,1 ,1 ,125 ,1 , , ,,Filler
+bizData ,1 ,9 ,0 ,1 ,0 ,1 , , ,,업무데이터
+zzData ,1 ,2 ,0 ,1 ,2 ,11 , , ,,ZZ플래그
\ No newline at end of file
diff --git a/resources/standard-message-config-test.properties b/resources/standard-message-config-test.properties
new file mode 100644
index 0000000..ec9b993
--- /dev/null
+++ b/resources/standard-message-config-test.properties
@@ -0,0 +1,11 @@
+layout.file.type=CSV
+layout.file.path=./resources/standard-layout-sample.csv
+mapper.class=com.eactive.eai.message.test.TestInterfaceMapper
+mapper.definition=./resources/standard-message-mapping-config.properties
+reader.JSON=com.eactive.eai.message.parser.JsonReader
+reader.JSN=com.eactive.eai.message.parser.JsonReader
+reader.UJN=com.eactive.eai.message.parser.JsonReader
+reader.XML=com.eactive.eai.message.parser.XmlReader
+reader.UXL=com.eactive.eai.message.parser.XmlReader
+reader.ASC=com.eactive.eai.message.parser.FlatReader
+reader.FLAT=com.eactive.eai.message.parser.FlatReader
\ No newline at end of file
diff --git a/resources/standard-message-config.properties b/resources/standard-message-config.properties
new file mode 100644
index 0000000..7a827b7
--- /dev/null
+++ b/resources/standard-message-config.properties
@@ -0,0 +1,20 @@
+# layout : StandardMessage layout definition
+layout.file.type=CSV
+layout.file.path=./resources/standard-layout.csv
+layout.filter.FLAT=com.eactive.eai.message.filter.FlatMessageFilter
+# mapper : StandardMessage's fields getter/setter interface
+mapper.class=com.eactive.eai.message.service.DefaultInterfaceMapper
+mapper.definition=./resources/standard-message-mapping-config.properties
+# reader : parsing input data to StandardMessage
+reader.JSON=com.eactive.eai.message.parser.JsonReader
+reader.JSN=com.eactive.eai.message.parser.JsonReader
+reader.UJN=com.eactive.eai.message.parser.JsonReader
+reader.XML=com.eactive.eai.message.parser.XmlReader
+reader.UXL=com.eactive.eai.message.parser.XmlReader
+reader.ASC=com.eactive.eai.message.parser.FlatReader
+reader.FLAT=com.eactive.eai.message.parser.FlatReader
+encode.flat=euc-kr
+encode.value=euc-kr
+encode.xml=utf-8
+# version.layout.name=VERSION_SAMPLE
+# version.mapper.definition=./resources/version-message-mapping-config.properties
\ No newline at end of file
diff --git a/resources/standard-message-mapping-config-sample.properties b/resources/standard-message-mapping-config-sample.properties
new file mode 100644
index 0000000..63b7432
--- /dev/null
+++ b/resources/standard-message-mapping-config-sample.properties
@@ -0,0 +1,28 @@
+REQ_SYS_CODE=systemHeader.DMND_SYS_CD
+CHANNEL_TYPE_CD=stdcommon.chnlTycd
+CHANNEL_DETAIL_CD=stdcommon.chnlDtlsClcd
+SEND_TIME=stdheader.send_tm
+GUID=stdheader.global_id
+SYSTEM_TYPE=stdheader.Inter_chn
+RECV_TIME=stdheader.recv_tm
+RETURN_VALUE=stdheader.return_value
+GUID_ORG=stdcommon.ortrGuid
+GUID_SEQ=stdheader.global_id
+#SERVICE_ID=stdheader.service_id
+SERVICE_ID=service_id
+RETURN_SERVICE_ID=stdcommon.procsRsltRcmsSrvcId
+INTERFACE_ID=stdheader.service_id
+SESSION_ID=stdheader.Session_id
+#SEND_RECV_DIVISION=stdheader.return_gubun
+SEND_RECV_DIVISION=service_tn
+IN_EX_DIVISION=stdcommon.hmabDvcd
+OPERATION_ENV=stdcommon.sysOprtEnvDvcd
+FIRST_REQ_IP=stdheader.ip_addr
+RECOVER_YN=stdcommon.ortrRestrYn
+INST_CODE=stdheader.com_code
+TIMEOUT=stdheader.gnrzTmotTktm
+ERROR_CODE=stdheader.msg_id
+ERROR_MSG=stdheader.msg_nm
+USER_ID=stdheader.usr_id
+RESPONSE_TYPE=stdcommon.procsRsltDvcd
+SYNC_ASYNC_TYPE=stdcommon.txSynzDvcd
diff --git a/resources/standard-message-mapping-config.properties b/resources/standard-message-mapping-config.properties
new file mode 100644
index 0000000..a24deaf
--- /dev/null
+++ b/resources/standard-message-mapping-config.properties
@@ -0,0 +1,26 @@
+REQ_SYS_CODE=Inter_chn
+CHANNEL_TYPE_CD=
+CHANNEL_DETAIL_CD=conn_tp
+SEND_TIME=send_tm
+GUID=global_id
+SYSTEM_TYPE=service_tn
+RECV_TIME=recv_tm
+RETURN_VALUE=return_value
+GUID_ORG=stdcommon.ortrGuid
+GUID_SEQ=stdheader.global_id
+SERVICE_ID=service_id
+RETURN_SERVICE_ID=stdcommon.procsRsltRcmsSrvcId
+INTERFACE_ID=service_id
+SESSION_ID=Session_id
+SEND_RECV_DIVISION=service_tn
+IN_EX_DIVISION=stdcommon.hmabDvcd
+OPERATION_ENV=stdcommon.sysOprtEnvDvcd
+FIRST_REQ_IP=ip_addr
+RECOVER_YN=stdcommon.ortrRestrYn
+INST_CODE=stdheader.com_code
+TIMEOUT=stdheader.gnrzTmotTktm
+ERROR_CODE=msg_id
+ERROR_MSG=msg_nm
+USER_ID=usr_id
+RESPONSE_TYPE=stdcommon.procsRsltDvcd
+SYNC_ASYNC_TYPE=stdcommon.txSynzDvcd
diff --git a/resources/version-message-mapping-config.properties b/resources/version-message-mapping-config.properties
new file mode 100644
index 0000000..97e97e7
--- /dev/null
+++ b/resources/version-message-mapping-config.properties
@@ -0,0 +1,4 @@
+service_id=header.if_id
+global_id=header.guid
+service_tn=header.req_type
+bizData=bizData
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..0791851
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,9 @@
+rootProject.name = 'elink-online-common'
+
+include 'elink-online-core-jpa'
+include 'elink-online-core'
+include 'elink-online-transformer'
+
+project (':elink-online-core-jpa').projectDir = new File(settingsDir, "../elink-online-core-jpa")
+project (':elink-online-core').projectDir = new File(settingsDir, "../elink-online-core")
+project (':elink-online-transformer').projectDir = new File(settingsDir, "../elink-online-transformer")
\ No newline at end of file
diff --git a/src/main/java/META-INF/persistence.xml b/src/main/java/META-INF/persistence.xml
new file mode 100644
index 0000000..549f8be
--- /dev/null
+++ b/src/main/java/META-INF/persistence.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/AdapterDAO.java b/src/main/java/com/eactive/eai/adapter/AdapterDAO.java
new file mode 100644
index 0000000..73ba812
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/AdapterDAO.java
@@ -0,0 +1,82 @@
+package com.eactive.eai.adapter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.eactive.eai.adapter.loader.AdapterGroupLoader;
+import com.eactive.eai.adapter.loader.AdapterLoader;
+import com.eactive.eai.adapter.mapper.AdapterGroupMapper;
+import com.eactive.eai.adapter.mapper.AdapterMapper;
+import com.eactive.eai.common.dao.BaseDAO;
+import com.eactive.eai.common.dao.DAOException;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.data.entity.onl.adapter.Adapter;
+import com.eactive.eai.data.entity.onl.adapter.AdapterGroup;
+
+@Service
+@Transactional
+public class AdapterDAO extends BaseDAO {
+
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ @Autowired
+ private AdapterGroupLoader adapterGroupLoader;
+
+ @Autowired
+ private AdapterLoader adapterLoader;
+
+ @Autowired
+ private AdapterGroupMapper adapterGroupMapper;
+
+ @Autowired
+ private AdapterMapper adapterMapper;
+
+ public List getAllAdapterGroups() throws DAOException {
+ try {
+ List adapterGroups = adapterGroupLoader.selectAllGroups();
+ return adapterGroups.stream().map(adapterGroupMapper::toVo).collect(Collectors.toList());
+ } catch (Exception e) {
+ throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAIAAC001"));
+ }
+ }
+
+ public List getAllAdapters(String adapterGroupName) throws DAOException {
+ List al = new ArrayList<>();
+
+ try {
+ Iterable adapters = adapterLoader.selectAdaptersByGroup(
+ com.eactive.eai.common.server.Keys.DEFAULT_SERVER, adapterGroupName,
+ EAIServerManager.getInstance().getLocalServerName());
+
+ for (Adapter adapter : adapters) {
+ AdapterVO vo = adapterMapper.toVo(adapter);
+ al.add(vo);
+ }
+ return al;
+ } catch (Exception e) {
+ throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAIAAC002"));
+ }
+ }
+
+ public AdapterGroupVO getAdapterGroup(String adapterGroupName) throws DAOException {
+ try {
+ AdapterGroup adapterGroup = adapterGroupLoader.getById(adapterGroupName);
+ AdapterGroupVO gvo = adapterGroupMapper.toVo(adapterGroup);
+ List adapterVos = adapterGroup.getAdapters().stream().map(adapterMapper::toVo)
+ .collect(Collectors.toList());
+
+ adapterVos.forEach(gvo::addAdapterVO);
+ return gvo;
+ } catch (Exception e) {
+ throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAIAAC009"));
+ }
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/AdapterGroupVO.java b/src/main/java/com/eactive/eai/adapter/AdapterGroupVO.java
new file mode 100644
index 0000000..b790e16
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/AdapterGroupVO.java
@@ -0,0 +1,569 @@
+package com.eactive.eai.adapter;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.lifecycle.LifecycleSupport;
+import com.eactive.eai.common.util.Logger;
+
+public class AdapterGroupVO implements Serializable, Lifecycle {
+ private static final long serialVersionUID = -8613631838169562236L;
+
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private String name; // 어뎁터업무그룹명[TSEAIAD01.ADPTRBZWKGROUPNAME]
+ private String adptrMsgPtrnCd; // 어댑터메시지유형코드[TSEAIAD01.ADPTRMSGPTRNCD] //[K, N, S] 값을 가짐
+ private String eaiBizCode; // EAI업무구분코드[TSEAIAD01.EAIBZWKDSTCD]
+ private String type; // 어댑터코드[TSEAIAD01.ADPTRCD]
+ private String messageType; // 어댑터메시지구분코드[TSEAIAD01.ADPTRMSGDSTCD]
+ private String messageEncode; // 어댑터메시지구분코드[TSEAIAD01.MSGENCODE]
+ private String gubun; // 어뎁터입출력구분코드[TSEAIAD01.ADPTRIODSTCD]
+ private String refClass; // 참고클래스명[TSEAIAD01.REFCLSNAME]
+ private boolean srLogFlag; // 송수신시각로그여부[TSEAIAD01.SNDRCVHMSLOGYN]
+ private boolean usedFlag; // 어댑터사용여부[TSEAIAD01.ADPTRUSEYN]
+ private boolean spcfcLUUseYn; // 특정LU사용여부[TSEAIAD01.SPCFCLUUSEYN] -> 용도변경 : 로그밸런싱 방식으로 사용 RR/LC
+ private String description; // 어댑터업무그룹설명[TSEAIAD01.ADPTRBZWKGROUPDESC]
+ private String osidInstiNo; // 대외기관번호[TSEAIAD01.OSIDINSTINO]
+ // KESA F/W사용여부[TSEAIAD01.KESAUSEYN]
+ // 0 : KESA 미사용, 1: nKESA 사용, 2: uKESA 사용, 3: zKESA 사용
+ private String kesaUseYn;
+
+ // 0 : 기본어댑터, 1: TAS어댑터, 2: TAS참조대표어댑터
+ private String testMasterYn;
+ private String adptrNickName;
+ private Map adapters;
+
+ private Vector actives;
+ private Vector disables;
+
+ private List adapterNames;
+ private String companyCodeData; // 업체코드데이터 (업체코드 추출정보 등록)
+ private String adptrInstiCode; // 어댑터업체코드
+ private String bidInterface; // MCI에서 bid 거래시의 대표 인터페이스
+ private AtomicInteger idx = new AtomicInteger(0);
+ private boolean started;
+ private LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+ private int currentTx;
+ private long successTx;
+ private long errorTx;
+
+ private String linkedAdapterGroup;
+ private String sameSessionYn;
+ private String pairAdapterYn;
+ private String clientId;
+
+ private boolean weighted = false;
+
+
+ public AdapterGroupVO() {
+ this("");
+ }
+
+ public AdapterGroupVO(String name) {
+ this.name = name;
+ this.adapters = new ConcurrentHashMap<>();
+ this.actives = new Vector<>();
+ this.disables = new Vector<>();
+ this.adapterNames = new ArrayList<>();
+ }
+
+ public boolean isWeighted() {
+ return weighted;
+ }
+
+ public void setWeighted(boolean weighted) {
+ this.weighted = weighted;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setEaiBizCode(String eaiBizCode) {
+ this.eaiBizCode = eaiBizCode;
+ }
+
+ public String getEaiBizCode() {
+ return this.eaiBizCode;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public void setGubun(String gubun) {
+ this.gubun = gubun;
+ }
+
+ public String getGubun() {
+ return this.gubun;
+ }
+
+ public void setMessageType(String messageType) {
+ this.messageType = messageType;
+ }
+
+ public String getMessageType() {
+ return this.messageType;
+ }
+
+ public String getMessageEncode() {
+ return messageEncode;
+ }
+
+ public void setMessageEncode(String messageEncode) {
+ this.messageEncode = messageEncode;
+ }
+
+ public void setRefClass(String refClass) {
+ this.refClass = refClass;
+ }
+
+ public String getRefClass() {
+ return this.refClass;
+ }
+
+ public void setSrLogFlag(boolean srLogFlag) {
+ this.srLogFlag = srLogFlag;
+ }
+
+ public boolean isSrLogFlag() {
+ return this.srLogFlag;
+ }
+
+ public void setUsedFlag(boolean usedFlag) {
+ this.usedFlag = usedFlag;
+ }
+
+ public boolean isUsedFlag() {
+ return this.usedFlag;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public void setSpcfcLUUseYn(boolean spcfcLUUseYn) {
+ this.spcfcLUUseYn = spcfcLUUseYn;
+ }
+
+ public boolean isSpcfcLUUseYn() {
+ return this.spcfcLUUseYn;
+ }
+
+ public void setAdptrMsgPtrnCd(String adptrMsgPtrnCd) {
+ this.adptrMsgPtrnCd = adptrMsgPtrnCd;
+ }
+
+ public String getAdptrMsgPtrnCd() {
+ return this.adptrMsgPtrnCd;
+ }
+
+ public String getOsidInstiNo() {
+ return osidInstiNo;
+ }
+
+ public void setOsidInstiNo(String osidInstiNo) {
+ this.osidInstiNo = osidInstiNo;
+ }
+
+ public String getKesaUseYn() {
+ return kesaUseYn;
+ }
+
+ public void setKesaUseYn(String kesaUseYn) {
+ this.kesaUseYn = kesaUseYn;
+ }
+
+ public String getTestMasterYn() {
+ return testMasterYn;
+ }
+
+ public void setTestMasterYn(String testMasterYn) {
+ this.testMasterYn = testMasterYn;
+ }
+
+ public String getAdptrNickName() {
+ return adptrNickName;
+ }
+
+ public void setAdptrNickName(String adptrNickName) {
+ this.adptrNickName = adptrNickName;
+ }
+
+ public String getCompanyCodeData() {
+ return companyCodeData;
+ }
+
+ public void setCompanyCodeData(String companyCodeData) {
+ this.companyCodeData = companyCodeData;
+ }
+
+ public String getAdptrInstiCode() {
+ return adptrInstiCode;
+ }
+
+ public void setAdptrInstiCode(String adptrInstiCode) {
+ this.adptrInstiCode = adptrInstiCode;
+ }
+
+ public String getBidInterface() {
+ return bidInterface;
+ }
+
+ public void setBidInterface(String bidInterface) {
+ this.bidInterface = bidInterface;
+ }
+
+ public String getClientId() { return clientId; }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public synchronized void addAdapterVO(AdapterVO avo) {
+ this.adapters.put(avo.getName(), avo);
+ this.adapterNames.add(avo.getName());
+ }
+
+ public AdapterVO getAdapterVO(String adapterName) {
+ return adapters.get(adapterName);
+ }
+
+ public synchronized void increase() {
+ ++currentTx;
+ }
+
+ public synchronized void decrease() {
+ --currentTx;
+ }
+
+ public int currentTx() {
+ return this.currentTx;
+ }
+
+ // GW관련 어댑터 카운터 추가-시작
+ public synchronized void increaseSuccess() {
+ ++successTx;
+ }
+
+ public synchronized void increaseError() {
+ ++errorTx;
+ }
+
+ public long successTx() {
+ return this.successTx;
+ }
+
+ public long errorTx() {
+ return this.errorTx;
+ }
+
+ public synchronized void resetCount() {
+ this.successTx = 0;
+ this.errorTx = 0;
+ }
+ // GW관련 어댑터 카운터 추가-종료
+
+ public String getLinkedAdapterGroup() {
+ return linkedAdapterGroup;
+ }
+
+ public void setLinkedAdapterGroup(String linkedAdapterGroup) {
+ this.linkedAdapterGroup = linkedAdapterGroup;
+ }
+
+ public String getSameSessionYn() {
+ return sameSessionYn;
+ }
+
+ public void setSameSessionYn(String sameSessionYn) {
+ this.sameSessionYn = sameSessionYn;
+ }
+
+ public String getPairAdapterYn() {
+ return pairAdapterYn;
+ }
+
+ public void setPairAdapterYn(String pairAdapterYn) {
+ this.pairAdapterYn = pairAdapterYn;
+ }
+
+ public void start() throws LifecycleException {
+ if (started)
+ throw new LifecycleException("RECEAIAAC030");
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
+
+ if (!this.usedFlag) {
+ String code = "RECEAIAAC040";
+ String[] msgArgs = new String[1];
+ msgArgs[0] = name;
+ String errText = ExceptionUtil.make(code, msgArgs);
+ if (logger.isError())
+ logger.error(errText);
+ throw new LifecycleException(errText);
+ }
+
+ setWeighted(false);
+ idx.set(0);
+
+ AdapterVO avo = null;
+ Iterator it = adapters.values().iterator();
+ while (it.hasNext()) {
+ avo = it.next();
+ if (avo instanceof Lifecycle) {
+ try {
+ LifecycleListener[] listeners = this.lifecycle.findLifecycleListeners();
+ if (listeners != null) {
+ for (int j = 0; j < listeners.length; j++) {
+ avo.addLifecycleListener(listeners[j]);
+ }
+ }
+
+ // 어댑터 프라퍼티에 active_onstartup = false 일 경우
+ // EAI 서버 기동시에 Adapter를 start하지 않는다.
+ boolean activeOnstartup = true;
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ String activeOnstartupValue = manager.getProperty(avo.getPropGroupName(), "active_onstartup");
+
+ if (activeOnstartupValue != null && "false".equals(activeOnstartupValue.trim())) {
+ activeOnstartup = false;
+ }
+
+ String lbWeight = manager.getProperty(avo.getPropGroupName(), Keys.LB_WEIGHT);
+ if(StringUtils.isNoneEmpty(lbWeight)) {
+ int weight = 1;
+ try {
+ weight = Integer.parseInt(lbWeight);
+ }
+ catch(NumberFormatException ex) {
+ weight = 1;
+ }
+
+ if(weight > 1) setWeighted(true);
+ avo.setWeight(weight);
+ }
+
+ avo.setAdapterGroupVO(this);
+ if (activeOnstartup) {
+ avo.start();
+ } else {
+ disable(avo);
+ }
+ } catch (Exception e) {
+ disable(avo);
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIAAC031") + " : " + this.name, e);
+ }
+ }
+ }
+ started = true;
+ lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
+ }
+
+ public void stop() throws LifecycleException {
+ if (!started)
+ throw new LifecycleException("RECEAIAAC032");
+
+ lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
+
+ AdapterVO avo = null;
+ Iterator it = adapters.values().iterator();
+ while (it.hasNext()) {
+ avo = it.next();
+ if (!avo.isStarted())
+ continue;
+ if (avo instanceof Lifecycle) {
+ try {
+ avo.stop();
+ } catch (Exception e) {
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIAAC033") + " : " + this.name, e);
+ }
+ }
+ }
+
+ started = false;
+ lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
+ }
+
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ public void active(AdapterVO vo) {
+ if (!this.actives.contains(vo) && vo.isStatus()) {
+ this.actives.add(vo);
+ this.disables.remove(vo);
+ }
+ }
+
+ public void disable(AdapterVO vo) {
+ if (!this.disables.contains(vo) && !vo.isStatus()) {
+ this.disables.add(vo);
+ this.actives.remove(vo);
+ }
+ }
+
+ public boolean isAlive() {
+ return !this.actives.isEmpty();
+ }
+
+ public void addLifecycleListener(LifecycleListener listener) {
+ lifecycle.addLifecycleListener(listener);
+ }
+
+ public LifecycleListener[] findLifecycleListeners() {
+ return lifecycle.findLifecycleListeners();
+ }
+
+ public void removeLifecycleListener(LifecycleListener listener) {
+ lifecycle.removeLifecycleListener(listener);
+ }
+
+ public Iterator getAdapters() {
+ return this.adapters.values().iterator();
+ }
+
+ public String[] getAdapterNames() {
+ String[] names = new String[this.adapterNames.size()];
+ for (int i = 0; i < names.length; i++) {
+ names[i] = this.adapterNames.get(i);
+ }
+ return names;
+ }
+
+ public synchronized AdapterVO nextAdapterVO() {
+ if (this.actives.isEmpty()) {
+ return null;
+ }
+
+ if (this.actives.size() == 1) {
+ return this.actives.get(0);
+ }
+
+ if(spcfcLUUseYn) {
+ if(logger.isDebug()) logger.debug("nextAdapterVO selectWithLeastConnection");
+ return selectWithLeastConnection();
+ }
+ else {
+ if(isWeighted()) {
+ if(logger.isDebug()) logger.debug("nextAdapterVO selectWithWeightedRoundRobin");
+ return selectWithWeightedRoundRobin();
+ }
+ else {
+ if(logger.isDebug()) logger.debug("nextAdapterVO selectWithRoundRobin");
+ return selectWithRoundRobin();
+ }
+ }
+ }
+
+ private AdapterVO selectWithRoundRobin() {
+ try {
+ if (idx.get() >= this.actives.size())
+ idx.set(0);
+ return this.actives.get(idx.getAndIncrement());
+ } catch (Exception e) {
+ if (this.actives.isEmpty())
+ return null;
+ idx.set(0);
+ return this.actives.get(idx.getAndIncrement());
+ }
+ }
+
+ private AdapterVO selectWithWeightedRoundRobin() {
+ try {
+ int totalWeight = actives.stream().mapToInt(AdapterVO::getWeight).sum();
+ int currentIndex = idx.getAndIncrement() % totalWeight;
+
+ for (AdapterVO adapter : actives) {
+ currentIndex -= adapter.getWeight();
+ if (currentIndex < 0) {
+ return adapter;
+ }
+ }
+ return this.actives.get(0);
+ } catch (Exception e) {
+ if (this.actives.isEmpty())
+ return null;
+ idx.set(0);
+ return this.actives.get(idx.getAndIncrement());
+ }
+ }
+
+ private AdapterVO selectWithLeastConnection() {
+ try {
+ AdapterVO selected = this.actives.get(0);
+ for (AdapterVO adapter : this.actives) {
+ if (adapter.getRequestCount() < selected.getRequestCount()) {
+ selected = adapter;
+ }
+ }
+ return selected;
+ } catch (Exception e) {
+ if (this.actives.isEmpty())
+ return null;
+ return this.actives.get(0);
+ }
+ }
+
+ public synchronized void removeAdapterVO(String name) {
+ adapters.remove(name);
+ this.adapterNames.remove(name);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("AdapterGroupVO[ name=").append(name);
+ sb.append(", adptrMsgPtrnCd=").append(adptrMsgPtrnCd);
+ sb.append(", eaiBizCode=").append(eaiBizCode);
+ sb.append(", type=").append(type);
+ sb.append(", messageType=").append(messageType);
+ sb.append(", messageEncode=").append(messageEncode);
+ sb.append(", gubun=").append(gubun);
+ sb.append(", refClass=").append(refClass);
+ sb.append(", srLogFlag=").append(srLogFlag);
+ sb.append(", usedFlag=").append(usedFlag);
+ sb.append(", spcfcLUUseYn=").append(spcfcLUUseYn);
+ sb.append(", description=").append(description);
+ sb.append(", osidInstiNo=").append(osidInstiNo);
+ sb.append(", kesaUseYn=").append(kesaUseYn);
+ sb.append(", testMasterYn=").append(testMasterYn);
+ sb.append(", adptrNickName=").append(adptrNickName);
+ sb.append(", companyCodeData=").append(companyCodeData);
+ sb.append(", adptrInstiCode=").append(adptrInstiCode);
+ sb.append(", bidInterface=").append(bidInterface);
+ sb.append(", actives=").append(this.actives.size());
+ sb.append(", disables=").append(this.disables.size());
+ sb.append(", AdapterList=").append(adapters);
+ sb.append(", clientId=").append(clientId);
+ sb.append(" ]");
+
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/AdapterManager.java b/src/main/java/com/eactive/eai/adapter/AdapterManager.java
new file mode 100644
index 0000000..84bec69
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/AdapterManager.java
@@ -0,0 +1,217 @@
+package com.eactive.eai.adapter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.eactive.eai.common.dao.DAOException;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.lifecycle.LifecycleSupport;
+import com.eactive.eai.common.util.ApplicationContextProvider;
+import com.eactive.eai.common.util.Logger;
+
+@Component
+public class AdapterManager implements Lifecycle {
+
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private boolean started;
+
+ private HashMap adapterGroups = new HashMap<>();
+
+ private LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+ @Autowired
+ private AdapterDAO adapterDAO;
+
+ public static AdapterManager getInstance() {
+ return ApplicationContextProvider.getContext().getBean(AdapterManager.class);
+ }
+
+ public void start() throws LifecycleException {
+ if (started)
+ throw new LifecycleException("RECEAIAAC015");
+
+ lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
+
+ this.adapterGroups.clear();
+
+ List groups = null;
+ try {
+ adapterDAO = ApplicationContextProvider.getContext().getBean(AdapterDAO.class);
+ groups = adapterDAO.getAllAdapterGroups();
+ } catch (Exception e) {
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIAAC016"));
+ }
+
+ for (AdapterGroupVO gvo : groups) {
+ List adapterVos = null;
+ try {
+ adapterVos = adapterDAO.getAllAdapters(gvo.getName());
+ for (AdapterVO vo : adapterVos) {
+ gvo.addAdapterVO(vo);
+ }
+ } catch (DAOException e) {
+ if (logger.isError())
+ logger.error(ExceptionUtil.getErrorCode(e, "RECEAIAAC017"));
+ continue;
+ }
+
+ if (logger.isDebug()) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = gvo.toString();
+ logger.debug(ExceptionUtil.make("RDCEAIAAC018", msgArgs));
+ }
+ addAdapterGroupVO(gvo);
+
+ try {
+ LifecycleListener[] listeners = this.lifecycle.findLifecycleListeners();
+ if (listeners != null) {
+ for (int j = 0; j < listeners.length; j++) {
+ gvo.addLifecycleListener(listeners[j]);
+ }
+ }
+
+ if (!gvo.isUsedFlag()) {
+ if (logger.isDebug())
+ logger.debug("Not Used Adapter>> " + gvo);
+ continue;
+ }
+ gvo.start();
+ } catch (Exception e) {
+ if (logger.isError())
+ logger.error(ExceptionUtil.getErrorCode(e, "RECEAIAAC019"));
+ }
+ }
+ started = true;
+ lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
+ }
+
+ public void stop() throws LifecycleException {
+ if (!started)
+ throw new LifecycleException("RECEAIAAC020");
+
+ lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
+
+ logger.warn("Stop Inbound Adapters ...");
+ for (Iterator it = this.adapterGroups.values().iterator(); it.hasNext();) {
+ AdapterGroupVO vo = it.next();
+ if ("I".equals(vo.getGubun())) {
+ try {
+ if (!vo.isStarted()) {
+ logger.warn("AdapterGroup not started skip stop. - " + vo);
+ continue;
+ }
+ if (vo instanceof Lifecycle) {
+ vo.stop();
+ }
+ } catch (LifecycleException e) {
+ String[] msgArgs = { vo.toString() };
+ String errText = ExceptionUtil.make("RECEAIAAC021", msgArgs);
+ if (logger.isError())
+ logger.error(errText);
+ }
+ }
+ }
+
+ logger.warn("Stop Outbound Adapters ...");
+ for (Iterator it = this.adapterGroups.values().iterator(); it.hasNext();) {
+ AdapterGroupVO vo = it.next();
+ if (!"I".equals(vo.getGubun())) {
+ try {
+ if (!vo.isStarted())
+ continue;
+ if (vo instanceof Lifecycle) {
+ vo.stop();
+ }
+ } catch (LifecycleException e) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = vo.toString();
+ String errText = ExceptionUtil.make("RECEAIAAC021", msgArgs);
+ if (logger.isError())
+ logger.error(errText);
+ }
+ }
+ }
+
+ started = false;
+ lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
+ }
+
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ public void addLifecycleListener(LifecycleListener listener) {
+ lifecycle.addLifecycleListener(listener);
+ }
+
+ public LifecycleListener[] findLifecycleListeners() {
+ return lifecycle.findLifecycleListeners();
+ }
+
+ public void removeLifecycleListener(LifecycleListener listener) {
+ lifecycle.removeLifecycleListener(listener);
+ }
+
+ public AdapterVO getAdapterVO(String adapterGroupName, String adapterName) {
+ AdapterGroupVO gvo = adapterGroups.get(adapterGroupName);
+ if (gvo == null)
+ return null;
+ return gvo.getAdapterVO(adapterName);
+ }
+
+ public AdapterGroupVO getAdapterGroupVO(String adapterGroupName) {
+ return adapterGroups.get(adapterGroupName);
+ }
+
+ public AdapterGroupVO getAdapterGroup(String adapterGroupName) throws DAOException {
+ return adapterGroups.get(adapterGroupName);
+ }
+
+ public AdapterGroupVO loadAdapterGroup(String adapterGroupName) throws DAOException {
+ return adapterDAO.getAdapterGroup(adapterGroupName);
+ }
+
+ public void addAdapterGroupVO(AdapterGroupVO vo) {
+ if (vo != null) {
+ adapterGroups.put(vo.getName(), vo);
+ }
+ }
+
+ public HashMap getAllAdapterGroupVO() {
+ return adapterGroups;
+ }
+
+ public List getAllAdapterGroupNames() {
+ ArrayList al = new ArrayList<>();
+ Iterator it = this.adapterGroups.keySet().iterator();
+ while (it.hasNext()) {
+ al.add(it.next());
+ }
+ Collections.sort(al);
+ return al;
+ }
+
+ public void updateAdapterGroupVO(AdapterGroupVO vo) {
+ if (vo != null)
+ adapterGroups.put(vo.getName(), vo);
+ }
+
+ public void removeAdapterGroupVO(String name) {
+ adapterGroups.remove(name);
+ }
+
+ public void print() {
+ if (logger.isDebug())
+ logger.debug("AdapterManager] All Adapter List>> " + this.adapterGroups);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/AdapterPropGroupDAO.java b/src/main/java/com/eactive/eai/adapter/AdapterPropGroupDAO.java
new file mode 100644
index 0000000..e87f7c9
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/AdapterPropGroupDAO.java
@@ -0,0 +1,65 @@
+package com.eactive.eai.adapter;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.eactive.eai.adapter.loader.AdapterPropGroupLoader;
+import com.eactive.eai.common.dao.BaseDAO;
+import com.eactive.eai.common.dao.DAOException;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.data.entity.onl.adapter.AdapterPropGroup;
+
+@Service
+@Transactional
+public class AdapterPropGroupDAO extends BaseDAO {
+
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ @Autowired
+ private AdapterPropGroupLoader adapterPropGroupLoader;
+
+ public Map getAllProperties() throws DAOException {
+
+ Map adapterPropGroupVos = new HashMap<>();
+ try {
+ logger.info("[ @@ Load Adapter Properties Configuration - starting >>>>>>>>>>>>>>>>> ]");
+
+ Iterable adapterPropGroups = adapterPropGroupLoader
+ .loadAll()
+ .collect(Collectors.toList());
+
+ for (AdapterPropGroup adapterPropGroup : adapterPropGroups) {
+ AdapterPropGroupVO adapterPropGroupVO = getProperties(adapterPropGroup);
+ adapterPropGroupVos.put(adapterPropGroup.getPrptygroupname(), adapterPropGroupVO);
+ }
+
+ logger.info("[>>Load Adapter Properties Configuration - ended ]");
+ return adapterPropGroupVos;
+ } catch (Exception e) {
+ throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICPM101"));
+ }
+ }
+
+ private AdapterPropGroupVO getProperties(AdapterPropGroup adapterPropGroup) {
+ AdapterPropGroupVO adapterPropGroupVO = new AdapterPropGroupVO(adapterPropGroup.getPrptygroupname());
+ adapterPropGroup.getAdapterProps().forEach(adapterProp -> adapterPropGroupVO
+ .addProperty(adapterProp.getId().getPrptyname(), adapterProp.getPrpty2val()));
+ return adapterPropGroupVO;
+ }
+
+ public AdapterPropGroupVO getProperties(String grpNm) throws DAOException {
+ try {
+ AdapterPropGroup adapterPropGroup = adapterPropGroupLoader.getById(grpNm);
+ return getProperties(adapterPropGroup);
+ } catch (Exception e) {
+ throw new DAOException(ExceptionUtil.make("RECEAICPM103", grpNm));
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/AdapterPropGroupVO.java b/src/main/java/com/eactive/eai/adapter/AdapterPropGroupVO.java
new file mode 100644
index 0000000..fd9ae39
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/AdapterPropGroupVO.java
@@ -0,0 +1,106 @@
+package com.eactive.eai.adapter;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Properties;
+
+import com.eactive.eai.common.util.NullControl;
+
+/**
+* 1. 기능 : 어뎁터 프라퍼티 정보를 를 정의한 Java Value Object 클래스
+* 2. 처리 개요 : 어뎁터 프라퍼티 정보를 정의한다.
+* * -
+* 3. 주의사항
+*
+* @author :
+* @version : v 1.0.0
+* @see : 관련 기능을 참조
+* @since :
+* :
+*/
+public class AdapterPropGroupVO implements Serializable
+{
+ private String name; //어뎁터 프라퍼티 그룹명[TSEAIAD14.PrptyGroupName]
+ private String description; //어뎁터 프라퍼티 그룹설명[TSEAIAD14.PrptyGroupDesc]
+ private Properties props; //어뎁터 프라퍼티 명, 프라퍼티2값[TSEAIAD15.PrptyName, TSEAIAD15.Prpty2Val]
+
+ public AdapterPropGroupVO() {
+ this("");
+ }
+
+ public AdapterPropGroupVO(String name) {
+ this(name,"");
+ }
+
+ public AdapterPropGroupVO(String name, String description) {
+ this.name = name;
+ this.description = description;
+ this.props = new Properties();
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return NullControl.trimSpace(this.description);
+ }
+
+ public String getProperty(String key) {
+ return (String)props.get(key);
+ }
+
+ public String getProperty(String key, String defaultValue) {
+ String value = (String)props.get(key);
+ return (value==null) ? defaultValue : value;
+ }
+
+ public void addProperty(String key, String value) {
+ props.put(key, NullControl.trimSpace(value));
+ }
+
+ public void setProperty(String key, String value) {
+ props.put(key,value);
+ }
+
+ public void removeProperty(String key) {
+ props.remove(key);
+ }
+
+ public String[] keys() {
+ Iterator it = this.props.keySet().iterator();
+ String[] propKeys = new String[this.props.size()];
+ for(int i = 0; it.hasNext(); i++){
+ propKeys[i] = (String)it.next();
+ }
+ Arrays.sort(propKeys);
+ return propKeys;
+ }
+
+ public Properties getProperties() {
+ return props;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("AdapterPropGroupVO[ name=").append(name);
+ sb.append(", description=").append(description);
+ sb.append(", Properties=").append(props);
+ sb.append(" ]");
+
+ return sb.toString();
+ }
+
+ public void setProperties(Properties prop){
+ this.props = prop;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/AdapterPropManager.java b/src/main/java/com/eactive/eai/adapter/AdapterPropManager.java
new file mode 100644
index 0000000..f566276
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/AdapterPropManager.java
@@ -0,0 +1,185 @@
+package com.eactive.eai.adapter;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.lifecycle.LifecycleSupport;
+import com.eactive.eai.common.util.ApplicationContextProvider;
+import com.eactive.eai.common.util.Logger;
+
+@Component
+public class AdapterPropManager implements Lifecycle {
+
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+ private PropertyChangeSupport property = new PropertyChangeSupport(this);
+
+ private Map groups;
+
+ private boolean started;
+
+ @Autowired
+ private AdapterPropGroupDAO adapterPropGroupDAO;
+
+ public static AdapterPropManager getInstance() {
+ return ApplicationContextProvider.getContext().getBean(AdapterPropManager.class);
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ property.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ property.removePropertyChangeListener(listener);
+ }
+
+ private PropertyChangeEvent createEvent(AdapterPropGroupVO source, String propertyName, Object oldValue,
+ Object newValue) {
+ return new PropertyChangeEvent(source, propertyName, oldValue, newValue);
+ }
+
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ public void start() throws LifecycleException {
+ if (started)
+ throw new LifecycleException("RECEAICPM201");
+
+ lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
+
+ try {
+ init();
+ } catch (Exception e) {
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAICPM201"));
+ }
+
+ started = true;
+ if (logger.isWarn()) {
+ logger.warn("AdapterPropManager] It is started.");
+ }
+ lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
+ }
+
+ private void init() throws Exception {
+ this.groups = adapterPropGroupDAO.getAllProperties();
+ }
+
+ public synchronized void reload() throws Exception {
+ if (logger.isWarn()) {
+ logger.warn("AdapterPropManager] reload all Started ...");
+ }
+ init();
+ if (logger.isWarn()) {
+ logger.warn("AdapterPropManager] reload all finished ...");
+ }
+ }
+
+ public synchronized void reload(String keyName) throws Exception {
+ AdapterPropGroupVO vo = adapterPropGroupDAO.getProperties(keyName);
+ if (vo != null) {
+ this.groups.put(keyName, vo);
+ } else {
+ throw new Exception("AdapterPropManager not found in Database : key[" + keyName + "]");
+ }
+ }
+
+ public void stop() throws LifecycleException {
+ if (!started)
+ throw new LifecycleException("RECEAICPM203");
+
+ lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
+
+ started = false;
+
+ if (logger.isWarn()) {
+ logger.warn("AdapterPropManager] It is stopped.");
+ }
+ lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
+ }
+
+ public void addLifecycleListener(LifecycleListener listener) {
+ lifecycle.addLifecycleListener(listener);
+ }
+
+ public LifecycleListener[] findLifecycleListeners() {
+ return lifecycle.findLifecycleListeners();
+ }
+
+ public void removeLifecycleListener(LifecycleListener listener) {
+ lifecycle.removeLifecycleListener(listener);
+ }
+
+ public void addAdapterPropGroupVO(String name, String description) {
+ groups.put(name, new AdapterPropGroupVO(name, description));
+ }
+
+ public AdapterPropGroupVO getAdapterPropGroupVO(String name) {
+ return groups.get(name);
+ }
+
+ public String getProperty(String key) {
+
+ return getProperty(com.eactive.eai.common.server.Keys.DEFAULT_SERVER, key);
+ }
+
+ public String getProperty(String group, String key) {
+ AdapterPropGroupVO vo = groups.get(group);
+ if (vo == null)
+ return null;
+ return vo.getProperty(key);
+ }
+
+ public Properties getProperties(String group) {
+ AdapterPropGroupVO vo = groups.get(group);
+ if (vo == null)
+ throw new RuntimeException("Cannot find the Property Group in AdapterPropManager. - " + group);
+ if (vo.getProperties() == null) {
+ return new Properties();
+ }
+ return (Properties) vo.getProperties().clone();
+ }
+
+ public void setProperty(String group, String key, String value) {
+ AdapterPropGroupVO gvo = groups.get(group);
+ String oldValue = gvo.getProperty(key);
+ gvo.setProperty(key, value);
+
+ if (oldValue != null && !oldValue.equals(value)) {
+ property.firePropertyChange(createEvent(gvo, key, oldValue, value));
+ }
+ }
+
+ public void setAdapterPropGroupVO(String group, AdapterPropGroupVO vo) {
+ groups.put(group, vo);
+ }
+
+ public void removeAdapterPropGroupVO(String name) {
+ groups.remove(name);
+ }
+
+ public String[] getAllPropGroupNames() {
+ Iterator it = this.groups.keySet().iterator();
+ String[] name = new String[this.groups.size()];
+ for (int i = 0; it.hasNext(); i++) {
+ name[i] = it.next();
+ }
+
+ Arrays.sort(name);
+ return name;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/AdapterVO.java b/src/main/java/com/eactive/eai/adapter/AdapterVO.java
new file mode 100644
index 0000000..b98600f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/AdapterVO.java
@@ -0,0 +1,271 @@
+package com.eactive.eai.adapter;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.eactive.eai.adapter.listener.AdapterException;
+import com.eactive.eai.adapter.listener.AdapterListener;
+import com.eactive.eai.adapter.listener.ListenerUtil;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.lifecycle.LifecycleSupport;
+import com.eactive.eai.common.testcall.TestCallManager;
+import com.eactive.eai.common.util.Logger;
+
+public class AdapterVO implements Serializable, Lifecycle {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private AdapterGroupVO adapterGroupVO; // 어댑터 그룹
+
+ private String adapterGroupName; // 어뎁터업무그룹명[TSEAIAD02.AdptrBzwkGroupName]
+ private String name; // 어뎁터업무명[TSEAIAD02.AdptrBzwkName]
+ private String eaiSevrInstncName; // 서버인스탄스명[TSEAIAD02.EAISevrInstncName] - migration added.
+ private String listenerClass; // 리스너클래스명[TSEAIAD02.LstnerClsName]
+ private String testCallClass; // 테스터클래스명[TSEAIAD02.TestClsName]
+ private String propGroupName; // 프라퍼티그룹명[TSEAIAD02.PrptyGroupName]
+ private String description; // 어댑터설명[TSEAIAD02.AdptrDesc]
+ private String propGroupDesc; // 프라퍼티그룹설명
+
+ private boolean status;
+ private transient AdapterListener adapterListener;
+ private boolean started;
+ private LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+ private int requestCount;
+ private int weight;
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public void setWeight(int weight) {
+ this.weight = weight;
+ }
+
+ public int getRequestCount() {
+ return requestCount;
+ }
+
+ public synchronized void incrementRequestCount() {
+ requestCount++;
+ }
+
+ public synchronized void decrementRequestCount() {
+ requestCount--;
+ }
+
+ public AdapterVO() {
+ this.requestCount = 0;
+ this.weight = 1;
+ }
+
+ public AdapterVO(String name) {
+ this.name = name;
+ this.requestCount = 0;
+ this.weight = 1;
+ }
+
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ public void setAdapterGroupName(String adapterGroupName) {
+ this.adapterGroupName = adapterGroupName;
+ }
+
+ public String getAdapterGroupName() {
+ return this.adapterGroupName;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setListenerClass(String listenerClass) {
+ this.listenerClass = listenerClass;
+ }
+
+ public String getListenerClass() {
+ return this.listenerClass;
+ }
+
+ public void setTestCallClass(String testCallClass) {
+ this.testCallClass = testCallClass;
+ }
+
+ public String getTestCallClass() {
+ return this.testCallClass;
+ }
+
+ public void setPropGroupName(String propGroupName) {
+ this.propGroupName = propGroupName;
+ }
+
+ public String getPropGroupName() {
+ return this.propGroupName;
+ }
+
+ public void setAdapterGroupVO(AdapterGroupVO group) {
+ this.adapterGroupVO = group;
+ }
+
+ public AdapterGroupVO getAdapterGroupVO() {
+ return this.adapterGroupVO;
+ }
+
+ private void setStatus(boolean status, boolean checkTestCall) {
+ this.status = status;
+
+ if (checkTestCall && !this.status && this.testCallClass != null && !this.testCallClass.equals("")) {
+ TestCallManager tmanager = TestCallManager.getInstance();
+ try {
+ tmanager.addTester(this);
+
+ String[] msgArgs = new String[1];
+ msgArgs[0] = this.toString();
+ if (logger.isInfo())
+ logger.info(ExceptionUtil.make("RICEAIAAC034", msgArgs));
+ } catch (Exception e) {
+ throw new RuntimeException(ExceptionUtil.getErrorCode(e, "RICEAIAAC035"), e);
+ }
+ }
+
+ if (this.status) {
+ this.adapterGroupVO.active(this);
+ } else {
+ this.adapterGroupVO.disable(this);
+ }
+ }
+
+ public synchronized void setStatus(boolean status) {
+ setStatus(status, true);
+ }
+
+ public synchronized void setStatusForcely(boolean status) {
+ setStatus(status, false);
+ }
+
+ public synchronized boolean isStatus() {
+ return this.status;
+ }
+
+ public void start() throws LifecycleException {
+ if (started)
+ throw new LifecycleException("RECEAIAAC036");
+
+ lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
+
+ if (StringUtils.isEmpty(listenerClass)) {
+ listenerClass = ListenerUtil.getDefaultListenerClass(adapterGroupVO.getType(), adapterGroupVO.getGubun());
+ if(logger.isWarn() && StringUtils.isNotEmpty(listenerClass)) {
+ logger.warn("Use DefaultListenerClass {} - {}",adapterGroupVO.getName(), listenerClass);
+ }
+ }
+
+ if (StringUtils.isNotEmpty(listenerClass)) {
+ try {
+ adapterListener = (AdapterListener) Class.forName(listenerClass).newInstance();
+ adapterListener.setAdapterInfo(this);
+ adapterListener.start();
+ } catch (Exception e) {
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIAAC037"), e);
+ }
+ }
+
+ started = true;
+ // SocketAdapter 기동시에 설정하므로
+ // socket2일 때는 status 를 setting 하지 않음.
+ if (adapterListener == null) {
+ status = true;
+ this.adapterGroupVO.active(this);
+ } else {
+ if (!(adapterListener instanceof com.eactive.eai.adapter.socket2.SocketAdapterListener)) {
+ status = true;
+ } else {
+ this.adapterGroupVO.active(this);
+ }
+ }
+ lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
+ if(logger.isWarn()) {
+ logger.warn("Adapter started {} {} - {}",adapterGroupVO.getName(), getName(), listenerClass);
+ }
+ }
+
+ public void stop() throws LifecycleException {
+ if (!started)
+ throw new LifecycleException("RECEAIAAC038");
+
+ lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
+
+ try {
+ if (adapterListener != null)
+ adapterListener.stop();
+ } catch (AdapterException e) {
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIAAC039"), e);
+ }
+
+ started = false;
+ status = false;
+ this.adapterGroupVO.disable(this);
+ lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
+ }
+
+ public void addLifecycleListener(LifecycleListener listener) {
+ lifecycle.addLifecycleListener(listener);
+ }
+
+ public LifecycleListener[] findLifecycleListeners() {
+ return lifecycle.findLifecycleListeners();
+ }
+
+ public void removeLifecycleListener(LifecycleListener listener) {
+ lifecycle.removeLifecycleListener(listener);
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("AdapterVO[ name=").append(name);
+ sb.append(", adapterGroupName=").append(adapterGroupName);
+ sb.append(", eaiSevrInstncName=").append(eaiSevrInstncName);
+ sb.append(", listenerClass=").append(listenerClass);
+ sb.append(", testCallClass=").append(testCallClass);
+ sb.append(", propGroupName=").append(propGroupName);
+ sb.append(", description=").append(description);
+ sb.append(", status=").append(status);
+ sb.append(", requestCount=").append(requestCount);
+ sb.append(" ]");
+
+ return sb.toString();
+ }
+
+ public void setEaiSevrInstncName(String eaiSevrInstncName) {
+ this.eaiSevrInstncName = eaiSevrInstncName;
+ }
+
+ public String getEaiSevrInstncName() {
+ return this.eaiSevrInstncName;
+ }
+
+ public void setPropGroupDesc(String propGroupDesc) {
+ this.propGroupDesc = propGroupDesc;
+ }
+
+ public String getPropGroupDesc() {
+ return this.propGroupDesc;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/EAIException.java b/src/main/java/com/eactive/eai/adapter/EAIException.java
new file mode 100644
index 0000000..367b934
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/EAIException.java
@@ -0,0 +1,26 @@
+package com.eactive.eai.adapter;
+
+public class EAIException extends Exception {
+ private String code;
+
+ public EAIException(String code, String msg) {
+ super(msg);
+ this.code = code;
+ }
+
+ public EAIException(String msg) {
+ this("", msg);
+ }
+
+ public EAIException(Throwable cause) {
+ super(cause);
+ }
+
+ public EAIException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ public String getExceptionCode() {
+ return this.code;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/ElinkAdapter.java b/src/main/java/com/eactive/eai/adapter/ElinkAdapter.java
new file mode 100644
index 0000000..b6f4396
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/ElinkAdapter.java
@@ -0,0 +1,11 @@
+package com.eactive.eai.adapter;
+
+import java.util.Properties;
+
+// EAI 엔진에서 어댑터을 common하게 접근하기 위한 Interface
+public interface ElinkAdapter {
+ public Object callService(String adapterGroupName, Properties prop, Object message, Properties tempProp)
+ throws Exception;
+
+ public Object execute(Properties prop, Object message, Properties tempProp) throws Exception;
+}
diff --git a/src/main/java/com/eactive/eai/adapter/ElinkAdapterFactory.java b/src/main/java/com/eactive/eai/adapter/ElinkAdapterFactory.java
new file mode 100644
index 0000000..121a550
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/ElinkAdapterFactory.java
@@ -0,0 +1,75 @@
+package com.eactive.eai.adapter;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.eactive.eai.adapter.amq.AMQSenderAdapter;
+import com.eactive.eai.adapter.app.BusinessApplicationAdapter;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterMain;
+import com.eactive.eai.adapter.jtc.JtcClientAdapter;
+import com.eactive.eai.adapter.socket2.SocketAdapterFacade;
+import com.eactive.eai.adapter.wca.SNAAdapterClient;
+import com.eactive.eai.adapter.websocket.WebSocketAdapterFacade;
+import com.eactive.eai.adapter.webt.WebTClientAdapter;
+import com.eactive.eai.common.util.Logger;
+
+public class ElinkAdapterFactory {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+ private static final ElinkAdapterFactory factory = new ElinkAdapterFactory();
+ private ConcurrentHashMap adapterMap;
+
+ private ElinkAdapterFactory() {
+ adapterMap = new ConcurrentHashMap<>();
+ }
+
+ public static ElinkAdapterFactory newInstance() {
+ return factory;
+ }
+
+ public ElinkAdapter getElinkAdapter(String adapterTypeName) throws Exception {
+ ElinkAdapter adapter = adapterMap.get(adapterTypeName);
+ if (adapter == null) {
+ adapter = createAdapter(adapterTypeName);
+ }
+ if (adapter == null) {
+ throw new RuntimeException("등록된 어댑터 타입을 찾을 수 없습니다. - " + adapterTypeName);
+ }
+ return adapter;
+ }
+
+ private ElinkAdapter createAdapter(String adapterTypeName) throws Exception {
+ if (adapterTypeName == null) {
+ return null;
+ }
+
+ ElinkAdapter adapter = null;
+
+ if (adapterTypeName.equals(Keys.TYPE_HTTP)) {
+ adapter = new HttpClientAdapterMain();
+ adapterMap.put(Keys.TYPE_HTTP, adapter);
+ } else if (adapterTypeName.equals(Keys.TYPE_NET2)) {
+ adapter = SocketAdapterFacade.getInstance();
+ adapterMap.put(Keys.TYPE_NET2, adapter);
+ } else if (adapterTypeName.equals(Keys.TYPE_WSK)) {
+ adapter = WebSocketAdapterFacade.getInstance();
+ adapterMap.put(Keys.TYPE_WSK, adapter);
+ } else if (adapterTypeName.equals(Keys.TYPE_WBT)) {
+ adapter = new WebTClientAdapter();
+ adapterMap.put(Keys.TYPE_WBT, adapter);
+ } else if (adapterTypeName.equals(Keys.TYPE_JTC)) {
+ adapter = new JtcClientAdapter();
+ adapterMap.put(Keys.TYPE_JTC, adapter);
+ } else if (adapterTypeName.equals(Keys.TYPE_APP)) {
+ adapter = new BusinessApplicationAdapter();
+ adapterMap.put(Keys.TYPE_APP, adapter);
+ } else if (adapterTypeName.equals(Keys.TYPE_SNA)) {
+ adapter = new SNAAdapterClient();
+ adapterMap.put(Keys.TYPE_SNA, adapter);
+ } else if (adapterTypeName.equals(Keys.TYPE_AMQ)) {
+ adapter = new AMQSenderAdapter();
+ adapterMap.put(Keys.TYPE_SNA, adapter);
+ } else {
+ logger.warn("Unknown adapter type : " + adapterTypeName);
+ }
+ return adapter;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/ElinkDefaultAdapter.java b/src/main/java/com/eactive/eai/adapter/ElinkDefaultAdapter.java
new file mode 100644
index 0000000..800ec72
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/ElinkDefaultAdapter.java
@@ -0,0 +1,65 @@
+package com.eactive.eai.adapter;
+
+import java.net.SocketTimeoutException;
+import java.nio.charset.Charset;
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.Logger;
+
+public class ElinkDefaultAdapter implements ElinkAdapter {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+ private AdapterManager manager;
+
+ public ElinkDefaultAdapter() {
+ this.manager = AdapterManager.getInstance();
+ }
+
+ public Object callService(String adapterGroupName, Properties prop, Object message, Properties tempProp)
+ throws Exception {
+ String adapterName = tempProp.getProperty(com.eactive.eai.adapter.Keys.OUT_ADAPTER_NAME);
+ AdapterGroupVO group = this.manager.getAdapterGroupVO(adapterGroupName);
+ if (group == null) {
+ String code = "RECEAIAAC027";
+ String[] msgArgs = new String[1];
+ msgArgs[0] = adapterGroupName;
+ String errText = ExceptionUtil.make(code, msgArgs);
+ if (logger.isError())
+ logger.error(errText);
+ throw new Exception(errText);
+ }
+
+ AdapterVO adapterVO = null;
+ if(StringUtils.isNotEmpty(adapterName)) {
+ adapterVO = group.getAdapterVO(adapterName);
+ }
+
+ group.increase();
+
+ tempProp.setProperty(com.eactive.eai.adapter.Keys.OUT_ADAPTER_GROUP_NAME, adapterGroupName);
+ // set AdapterGroup charset
+ tempProp.setProperty(com.eactive.eai.adapter.Keys.CHARSET_KEY_OUT,
+ StringUtils.defaultIfBlank(group.getMessageEncode(), Charset.defaultCharset().name()));
+
+ try {
+ if(adapterVO != null) adapterVO.incrementRequestCount();
+ return execute(prop, message, tempProp);
+ } catch (SocketTimeoutException ste) {
+ throw ste;
+ } catch (HttpStatusException hse) {
+ throw hse;
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ group.decrease();
+ if(adapterVO != null) adapterVO.decrementRequestCount();
+ }
+ }
+
+ public Object execute(Properties prop, Object message, Properties tempProp) throws Exception {
+ throw new java.lang.UnsupportedOperationException("RECEAIAAC029");
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/Keys.java b/src/main/java/com/eactive/eai/adapter/Keys.java
new file mode 100644
index 0000000..eeae7aa
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/Keys.java
@@ -0,0 +1,48 @@
+package com.eactive.eai.adapter;
+
+// adapter 패키지에서 사용하는 상수를 정의한 Interface
+public interface Keys {
+ public static final String OUT_ADAPTER_GROUP_NAME = "OUT_ADAPTER_GROUP_NAME";
+ public static final String OUT_ADAPTER_NAME = "OUT_ADAPTER_NAME";
+
+ public static final String GUBUN_IN = "INBOUND";
+ public static final String GUBUN_OUT = "OUTBOUND";
+
+ public static final String LB_WEIGHT = "LB_WEIGHT";
+
+ // inbound adapter charset
+ public static final String CHARSET_KEY_IN = "CHARSET_IN";
+ // outbound adapter charset
+ public static final String CHARSET_KEY_OUT = "CHARSET_OUT";
+
+ public static final String TYPE_HTTP = "HTT";
+ //HTTP custom port - undertow
+ public static final String TYPE_HTTP_CUSTOM = "HTC";
+ public static final String TYPE_REST = "RST";
+ public static final String TYPE_NET2 = "NET";
+ public static final String TYPE_SNA = "SNA";
+ public static final String TYPE_WSK = "WSK";
+ public static final String TYPE_WBT = "WBT";
+ public static final String TYPE_JTC = "JTC";
+ public static final String TYPE_JCO = "JCO";
+ public static final String TYPE_APP = "APP";
+ public static final String TYPE_AMQ = "AMQ";
+
+ public static final String IF_NONSTANDARD = "N";
+ public static final String IF_STANDARD = "K";
+ public static final String IF_SUBSTANDARD = "B";
+
+ public static final String TESTMASTER_DEFAULT = "0";
+ public static final String TESTMASTER_TAS = "1";
+ public static final String TESTMASTER_TAS_INFO = "2";
+
+ public static final String ADAPTRER_IN = "I";
+ public static final String ADAPTER_OUT = "O";
+
+ public static final String NO_KESA = "0";
+ public static final String N_KESA = "1";
+ public static final String U_KESA = "2";
+ public static final String Z_KESA = "3";
+ public static final String CARD_KESA = "C";
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/RequestDispatcher.java b/src/main/java/com/eactive/eai/adapter/RequestDispatcher.java
new file mode 100644
index 0000000..3eb57d7
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/RequestDispatcher.java
@@ -0,0 +1,136 @@
+package com.eactive.eai.adapter;
+
+import java.nio.charset.Charset;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.state.ElinkState;
+import com.eactive.eai.common.state.ElinkStateException;
+import com.eactive.eai.common.state.ElinkStateManager;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.inbound.processor.Processor;
+import com.eactive.eai.inbound.processor.ProcessorFactory;
+
+public class RequestDispatcher {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private static boolean isTASEnabledEAIServer = true;
+ static {
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ isTASEnabledEAIServer = eaiServerManager.isTASEnabledEAIServer();
+ }
+
+ private static ConcurrentHashMap dispatchers = new ConcurrentHashMap<>();
+
+ private String adapterGroupName;
+ private Processor processor;
+
+ private RequestDispatcher(String adapterGroupName) {
+ this.adapterGroupName = adapterGroupName;
+ processor = ProcessorFactory.newInstance();
+ }
+
+ public static RequestDispatcher getRequestDispatcher(String adapterGroupName) {
+ return dispatchers.computeIfAbsent(adapterGroupName, k -> new RequestDispatcher(adapterGroupName));
+ }
+
+ public Object handle(String adapterName, Object message, Properties prop) throws Exception {
+ AdapterManager manager = AdapterManager.getInstance();
+
+ String inAdapterGroupName = this.adapterGroupName;
+ String actionClass = "";
+ String adptrMsgPtrnCd = "";
+ String messageType = MessageType.ASC;
+
+ AdapterGroupVO group = manager.getAdapterGroupVO(inAdapterGroupName);
+ if (group == null) {
+ String code = "RECEAIAAC042";
+ String[] msgArgs = new String[2];
+ msgArgs[0] = adapterGroupName;
+ msgArgs[1] = adapterName;
+ String errText = ExceptionUtil.make(code, msgArgs);
+ if (logger.isError()) {
+ logger.error(errText);
+ }
+ throw new Exception(errText);
+ }
+
+ AdapterVO adapter = group.getAdapterVO(adapterName);
+ if (adapter == null) {
+ String code = "RECEAIAAC022";
+ String[] msgArgs = { adapterGroupName, adapterName, group.toString() };
+ String errText = ExceptionUtil.make(code, msgArgs);
+ if (logger.isError()) {
+ logger.error(errText);
+ }
+ throw new Exception(errText);
+ }
+
+ if (prop == null) {
+ prop = new Properties();
+ }
+
+ actionClass = group.getRefClass();
+ adptrMsgPtrnCd = group.getAdptrMsgPtrnCd();
+ messageType = group.getMessageType();
+ try {
+ prop.put(Processor.ADAPTER_GROUP_NAME, inAdapterGroupName);
+ prop.put(Processor.ADAPTER_NAME, adapterName);
+ prop.put(Processor.STD_MESSAGE, adptrMsgPtrnCd);
+ prop.put(Processor.REQUEST_ACTION, actionClass);
+ prop.put(Processor.MESSAGE_TYPE, messageType);
+
+ // set Inbound AdapterGroup charset
+ prop.setProperty(com.eactive.eai.adapter.Keys.CHARSET_KEY_IN,
+ StringUtils.defaultIfBlank(group.getMessageEncode(), Charset.defaultCharset().name()));
+ } catch (Exception e) {
+ throw new Exception(ExceptionUtil.getErrorCode(e, "RECEAIAAC024"));
+ }
+
+ Object obj = null;
+
+ // Check Elink lifecycle is STARTED
+ // otherwise reject this request
+ if(ElinkStateManager.getInstance().getState() != ElinkState.STARTED) {
+ logger.error("Elink STATE FAIL - " + ElinkStateManager.getInstance().getState());
+ throw new ElinkStateException("Elink STATE FAIL - " + ElinkStateManager.getInstance().getState());
+ }
+
+ try {
+ ElinkStateManager.getInstance().startRequest();
+ group.increase();
+ adapter.incrementRequestCount();
+ obj = processor.execute(message, prop);
+ group.increaseSuccess();
+ } catch (HttpStatusException e) {
+ group.increaseError();
+ throw e;
+ } catch (Exception e) {
+ group.increaseError();
+ throw new Exception(ExceptionUtil.getErrorCode(e, "RECEAIAAC025"));
+ } finally {
+ group.decrease();
+ adapter.decrementRequestCount();
+ ElinkStateManager.getInstance().completeRequest();
+ }
+
+ if (obj != null) {
+ return obj;
+ }
+ else {
+ if (message instanceof byte[]) {
+ return new byte[0];
+ } else if (message instanceof String) {
+ return "";
+ } else {
+ return new Object();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterConstants.java b/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterConstants.java
new file mode 100644
index 0000000..10626fb
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterConstants.java
@@ -0,0 +1,30 @@
+package com.eactive.eai.adapter.amq;
+
+public class AMQAdapterConstants {
+
+ // adapter properties
+ public static final String PROP_BROKER_URL = "BROKER_URL";
+ public static final String PROP_USER_NAME = "BROKER_USER_NAME";
+ public static final String PROP_PASSWORD = "BROKER_PASSWORD";
+ public static final String PROP_POOL_MAX_CONNECTIONS = "POOL_MAX_CONNECTIONS";
+ public static final String PROP_POOL_IDLE_TIMEOUT = "POOL_IDLE_TIMEOUT";
+ public static final String PROP_POOL_EXPIRY_TIMEOUT = "POOL_EXPIRY_TIMEOUT";
+ public static final String PROP_REQUEST_QUEUE_NAME = "REQUEST_QUEUE_NAME";
+ public static final String PROP_REPLY_QUEUE_NAME = "REPLY_QUEUE_NAME";
+ public static final String PROP_MESSAGE_TIME_TO_LIVE = "MESSAGE_TIME_TO_LIVE";
+ public static final String PROP_MESSAGE_RECEIVE_TIMEOUT = "REPLY_MESSAGE_RECEIVE_TIMEOUT";
+ public static final String PROP_RECEIVE_QUEUE_NAME = "RECEIVE_QUEUE_NAME";
+ public static final String PROP_RECEIVE_MAX_CONCURRENT_CONSUMERS = "RECEIVE_MAX_CONCURRENT_CONSUMERS";
+ public static final String PROP_REPLY_POOL_MAX_CONNECTIONS = "REPLY_POOL_MAX_CONNECTIONS";
+ public static final String PROP_REPLY_POOL_IDLE_TIMEOUT = "REPLY_POOL_IDLE_TIMEOUT";
+ public static final String PROP_REPLY_POOL_EXPIRY_TIMEOUT = "REPLY_POOL_EXPIRY_TIMEOUT";
+ public static final String PROP_RELAY_PROPERTY_GROUP = "RELAY_PROPERTY_GROUP";
+ public static final String PROP_RELAY_REQUEST_PROPERTY_KEYS = "RELAY_REQUEST_PROPERTY_KEYS";
+ public static final String PROP_RELAY_RESPONSE_PROPERTY_KEYS = "RELAY_RESPONSE_PROPERTY_KEYS";
+
+ public static final String TEMP_INTERFACE_RESPONSE_TYPE = "INTERFACE_RESPONSE_TYPE";
+ public static final String TEMP_MESSAGE_TYPE = "MESSAGE_TYPE";
+
+ public static final int DEFAULT_POOL_MAX_CONNECTIONS = 8;
+ public static final long DEFAULT_MESSAGE_RECEIVE_TIMEOUT = 30;
+}
diff --git a/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterListener.java b/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterListener.java
new file mode 100644
index 0000000..8ac32ad
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterListener.java
@@ -0,0 +1,53 @@
+package com.eactive.eai.adapter.amq;
+
+import com.eactive.eai.adapter.listener.AdapterException;
+import com.eactive.eai.adapter.listener.AdapterListenerSupport;
+import com.eactive.eai.common.util.Logger;
+
+/**
+ * @formatter:off
+ * ActiveMQ 어댑터 LISTENER 클래스
+ * ActiveMQ 어댑터를 기동/중지한다
+ * @formatter:on
+ */
+public class AMQAdapterListener extends AdapterListenerSupport {
+ public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ @Override
+ public void start() throws AdapterException {
+ if (logger.isInfo()) {
+ logger.info("= AMQAdapterListener start.........");
+ }
+
+ try {
+ if (info == null) {
+ throw new Exception("AMQAdapterListener | AdapterVO가 NULL입니다.");
+ }
+
+ AMQAdapterManager manager = AMQAdapterManager.getInstance();
+ info.setStatus(true);
+ manager.start(info);
+ } catch (Throwable e) {
+ logger.error("[" + info.getName() + "] 구동 실패", e);
+ }
+ }
+
+ @Override
+ public void stop() throws AdapterException {
+ if (logger.isInfo()) {
+ logger.info("= AMQAdapterListener stop.........");
+ }
+
+ try {
+ if (info == null) {
+ throw new Exception("AMQAdapterListener | AdapterVO가 NULL입니다.");
+ }
+
+ AMQAdapterManager manager = AMQAdapterManager.getInstance();
+ manager.stop(info);
+ info.setStatus(false);
+ } catch (Throwable e) {
+ logger.error("[" + info.getName() + "] 중지 실패", e);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterManager.java b/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterManager.java
new file mode 100644
index 0000000..e8875b9
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/amq/AMQAdapterManager.java
@@ -0,0 +1,127 @@
+package com.eactive.eai.adapter.amq;
+
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.jms.pool.PooledConnectionFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.agent.command.CommandException;
+import com.eactive.eai.common.util.Logger;
+
+public class AMQAdapterManager {
+ public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ private static AMQAdapterManager instance = new AMQAdapterManager();
+
+ // adapterName - Outbound Queue PooledConnectionFactory
+ private ConcurrentHashMap adapterConFacMap = new ConcurrentHashMap<>();
+
+ // adapterName - Inbound Queue Listener
+ private ConcurrentHashMap receiverAdapterMap = new ConcurrentHashMap<>();
+
+ public static AMQAdapterManager getInstance() {
+ return instance;
+ }
+
+ public PooledConnectionFactory getOutboundPooledConnectionFactory(String adapterName) {
+ return adapterConFacMap.get(adapterName);
+ }
+
+ public void start(AdapterVO adapterVO) throws Exception {
+ if (logger.isDebug()) {
+ logger.debug("= AMQAdapterManager.start...");
+ }
+
+ AdapterGroupVO adapterGroupVO = adapterVO.getAdapterGroupVO();
+ AdapterPropManager propManager = AdapterPropManager.getInstance();
+ Properties queueProp = propManager.getProperties(adapterVO.getPropGroupName());
+ String brokerUrl = queueProp.getProperty(AMQAdapterConstants.PROP_BROKER_URL);
+ if (StringUtils.isBlank(brokerUrl)) {
+ throw new CommandException(AMQAdapterConstants.PROP_BROKER_URL + " is a required.");
+ }
+
+ if (StringUtils.equals(adapterGroupVO.getGubun(), "I")) {
+ AMQReceiverAdapter receiverAdapter = new AMQReceiverAdapter(adapterVO);
+ receiverAdapter.start();
+ receiverAdapterMap.put(adapterVO.getName(), receiverAdapter);
+
+ // Sync 거래일 경우 응답 Queue 연결
+ String replyQueue = queueProp.getProperty(AMQAdapterConstants.PROP_REPLY_QUEUE_NAME);
+ if (StringUtils.isNotBlank(replyQueue)) {
+ String userName = queueProp.getProperty(AMQAdapterConstants.PROP_USER_NAME);
+ String password = queueProp.getProperty(AMQAdapterConstants.PROP_PASSWORD);
+ String maxConnections = queueProp.getProperty(AMQAdapterConstants.PROP_REPLY_POOL_MAX_CONNECTIONS);
+ String idleTimeout = queueProp.getProperty(AMQAdapterConstants.PROP_REPLY_POOL_IDLE_TIMEOUT);
+ String expiryTimeout = queueProp.getProperty(AMQAdapterConstants.PROP_REPLY_POOL_EXPIRY_TIMEOUT);
+ adapterConFacMap.put(adapterVO.getName(), getPooledConnectionFactory(brokerUrl, userName, password,
+ maxConnections, idleTimeout, expiryTimeout));
+ }
+ } else {
+ String userName = queueProp.getProperty(AMQAdapterConstants.PROP_USER_NAME);
+ String password = queueProp.getProperty(AMQAdapterConstants.PROP_PASSWORD);
+ String maxConnections = queueProp.getProperty(AMQAdapterConstants.PROP_POOL_MAX_CONNECTIONS);
+ String idleTimeout = queueProp.getProperty(AMQAdapterConstants.PROP_POOL_IDLE_TIMEOUT);
+ String expiryTimeout = queueProp.getProperty(AMQAdapterConstants.PROP_POOL_EXPIRY_TIMEOUT);
+ adapterConFacMap.put(adapterVO.getName(), getPooledConnectionFactory(brokerUrl, userName, password,
+ maxConnections, idleTimeout, expiryTimeout));
+ }
+ }
+
+ public void stop(AdapterVO adapterVO) throws Exception {
+ AdapterGroupVO adapterGroupVO = adapterVO.getAdapterGroupVO();
+
+ if (StringUtils.equals(adapterGroupVO.getGubun(), "I")) {
+ AMQReceiverAdapter receiverAdapter = receiverAdapterMap.get(adapterVO.getName());
+ if (receiverAdapter != null) {
+ receiverAdapterMap.remove(adapterVO.getName());
+ receiverAdapter.stop();
+ }
+
+ // Sync 거래일 경우 응답 Queue 연결 해제
+ PooledConnectionFactory connectionFactory = adapterConFacMap.get(adapterVO.getName());
+ if (connectionFactory != null) {
+ adapterConFacMap.remove(adapterVO.getName());
+ connectionFactory.clear();
+ }
+ } else {
+ PooledConnectionFactory connectionFactory = adapterConFacMap.get(adapterVO.getName());
+ if (connectionFactory != null) {
+ adapterConFacMap.remove(adapterVO.getName());
+ connectionFactory.clear();
+ }
+ }
+
+ if (logger.isDebug()) {
+ logger.debug("= AMQAdapterManager.stoped...");
+ }
+ }
+
+ private PooledConnectionFactory getPooledConnectionFactory(String brokerUrl, String userName, String password,
+ String maxConnections, String idleTimeout, String expiryTimeout) throws Exception {
+ // Queue Connection pool 생성
+ ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(brokerUrl);
+ if (StringUtils.isNotBlank(userName)) {
+ activeMQConnectionFactory.setUserName(userName);
+ activeMQConnectionFactory.setPassword(StringUtils.defaultString(password));
+ }
+ activeMQConnectionFactory.setTrustAllPackages(true);
+
+ PooledConnectionFactory connectionFactory = new PooledConnectionFactory();
+ connectionFactory.setConnectionFactory(activeMQConnectionFactory);
+ connectionFactory
+ .setMaxConnections(NumberUtils.toInt(maxConnections, AMQAdapterConstants.DEFAULT_POOL_MAX_CONNECTIONS));
+ if (NumberUtils.isParsable(idleTimeout)) {
+ connectionFactory.setIdleTimeout(NumberUtils.toInt(idleTimeout) * 1000);
+ }
+ if (NumberUtils.isParsable(expiryTimeout)) {
+ connectionFactory.setExpiryTimeout(NumberUtils.toLong(expiryTimeout) * 1000);
+ }
+
+ return connectionFactory;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/amq/AMQReceiverAdapter.java b/src/main/java/com/eactive/eai/adapter/amq/AMQReceiverAdapter.java
new file mode 100644
index 0000000..6e0c907
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/amq/AMQReceiverAdapter.java
@@ -0,0 +1,220 @@
+package com.eactive.eai.adapter.amq;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.jms.pool.PooledConnectionFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+import org.springframework.jms.listener.DefaultMessageListenerContainer;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.RequestDispatcher;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
+import com.eactive.eai.agent.command.CommandException;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.util.Logger;
+
+public class AMQReceiverAdapter {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ private AdapterVO adapterVo;
+ DefaultMessageListenerContainer listenerContainer = null;
+
+ public AMQReceiverAdapter(AdapterVO adapterVo) {
+ this.adapterVo = adapterVo;
+ }
+
+ public void start() throws Exception {
+ AdapterPropManager propManager = AdapterPropManager.getInstance();
+ Properties queueProp = propManager.getProperties(adapterVo.getPropGroupName());
+ String brokerUrl = queueProp.getProperty(AMQAdapterConstants.PROP_BROKER_URL);
+ if (StringUtils.isBlank(brokerUrl)) {
+ throw new CommandException(AMQAdapterConstants.PROP_BROKER_URL + " is a required.");
+ }
+ String userName = queueProp.getProperty(AMQAdapterConstants.PROP_USER_NAME);
+ String password = queueProp.getProperty(AMQAdapterConstants.PROP_PASSWORD);
+ String receiveQueue = queueProp.getProperty(AMQAdapterConstants.PROP_RECEIVE_QUEUE_NAME);
+ if (StringUtils.isBlank(receiveQueue)) {
+ throw new Exception("No have receive Queue name");
+ }
+ String concurrency = queueProp.getProperty(AMQAdapterConstants.PROP_RECEIVE_MAX_CONCURRENT_CONSUMERS);
+ String replyQueue = queueProp.getProperty(AMQAdapterConstants.PROP_REPLY_QUEUE_NAME);
+ String relayPropertyGroup = queueProp.getProperty(AMQAdapterConstants.PROP_RELAY_PROPERTY_GROUP);
+ String relayRequestPropertyKeys = queueProp.getProperty(AMQAdapterConstants.PROP_RELAY_REQUEST_PROPERTY_KEYS);
+
+ // Queue Connection pool 생성
+ ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
+ if (StringUtils.isNotBlank(userName)) {
+ connectionFactory.setUserName(userName);
+ connectionFactory.setPassword(StringUtils.defaultString(password));
+ }
+ connectionFactory.setTrustAllPackages(true);
+
+ listenerContainer = new DefaultMessageListenerContainer();
+ listenerContainer.setConnectionFactory(connectionFactory);
+ listenerContainer.setDestinationName(receiveQueue);
+ if (NumberUtils.isParsable(concurrency)) {
+ listenerContainer.setConcurrency(concurrency);
+ }
+ listenerContainer.setMessageListener(new MessageListener() {
+ @Override
+ public void onMessage(Message message) {
+ try {
+ if (message instanceof TextMessage) {
+ if (logger.isDebug()) {
+ logger.debug("Received from " + receiveQueue + ": " + ((TextMessage) message).getText());
+ }
+
+ String receivedMsg = convertMessageToString(message);
+
+ Properties prop = new Properties();
+ // RestDataAdapterGroupParseRequestAction 오류 방지 위해 set
+ prop.setProperty(HttpAdapterServiceKey.INBOUND_METHOD, "QUEUE");
+
+ Object returnObject = RequestDispatcher.getRequestDispatcher(adapterVo.getAdapterGroupName())
+ .handle(adapterVo.getName(), receivedMsg, prop);
+
+ // reply queue가 설정되어 있으면(Sync) 전송
+ if (StringUtils.isNotBlank(replyQueue)) {
+ replyMessage((String) returnObject, replyQueue, relayPropertyGroup);
+ }
+ } else {
+ logger.error("Only supports TextMessage.");
+ throw new IllegalArgumentException(
+ "Only supports TextMessage: " + message.getClass().getName());
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ throw new RuntimeException(e);
+ }
+ }
+
+ @SuppressWarnings({ "deprecation", "unchecked" })
+ private String convertMessageToString(Message message) throws Exception {
+ String strMsg = ((TextMessage) message).getText();
+
+ // Queue property relay
+ if (MessageType.JSON.equals(adapterVo.getAdapterGroupVO().getMessageType())
+ && StringUtils.isNotBlank(relayPropertyGroup)
+ && StringUtils.isNotBlank(relayRequestPropertyKeys)) {
+ JSONObject jsonMessage = (JSONObject) JSONValue.parse(StringUtils.defaultString(strMsg));
+ JSONObject propertyJson = new JSONObject();
+ if (StringUtils.equalsIgnoreCase(relayRequestPropertyKeys, "ALL")) {
+ Enumeration propertyNames = message.getPropertyNames();
+ while (propertyNames.hasMoreElements()) {
+ try {
+ String propertyName = propertyNames.nextElement();
+ propertyJson.put(propertyName, message.getStringProperty(propertyName));
+ } catch (Exception e) {
+ if (logger.isWarn()) {
+ logger.warn(e.getMessage());
+ }
+ }
+ }
+ } else {
+ String[] relayKeyArr = org.springframework.util.StringUtils
+ .tokenizeToStringArray(relayRequestPropertyKeys, ",");
+ for (String key : relayKeyArr) {
+ try {
+ String propertyValue = message.getStringProperty(key);
+ if (StringUtils.isNotBlank(propertyValue)) {
+ propertyJson.put(key, propertyValue);
+ }
+ } catch (Exception e) {
+ if (logger.isWarn()) {
+ logger.warn(e.getMessage());
+ }
+ }
+ }
+ }
+
+ if (propertyJson.size() > 0) {
+ jsonMessage.put(relayPropertyGroup, propertyJson);
+ strMsg = jsonMessage.toJSONString();
+ }
+ }
+
+ return strMsg;
+ }
+
+ private void replyMessage(String replyMessage, String replyQueue, String relayPropertyGroup)
+ throws Exception {
+ PooledConnectionFactory connectionFactory = AMQAdapterManager.getInstance()
+ .getOutboundPooledConnectionFactory(adapterVo.getName());
+
+ JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
+ jmsTemplate.setExplicitQosEnabled(true);
+ jmsTemplate.setDeliveryPersistent(false);
+
+ jmsTemplate.send(replyQueue, new MessageCreator() {
+ @SuppressWarnings("deprecation")
+ public Message createMessage(Session session) throws JMSException {
+ String strMsg = replyMessage;
+
+ // relay to Queue property
+ HashMap properties = new HashMap<>();
+ if (MessageType.JSON.equals(adapterVo.getAdapterGroupVO().getMessageType())
+ && StringUtils.isNotBlank(relayPropertyGroup)
+ && StringUtils.contains(replyMessage, relayPropertyGroup)) {
+ try {
+ JSONObject dataObject = (JSONObject) JSONValue.parse(replyMessage);
+ JSONObject propertyObject = (JSONObject) dataObject.get(relayPropertyGroup);
+ if (propertyObject != null) {
+ for (Object key : propertyObject.keySet()) {
+
+ Object obj = propertyObject.get(key);
+ if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) {
+ continue;
+ }
+
+ properties.put((String) key, (String) obj);
+ }
+
+ dataObject.remove(relayPropertyGroup);
+ strMsg = dataObject.toJSONString();
+ }
+ } catch (Exception e) {
+ if (logger.isWarn()) {
+ logger.warn(e.getMessage());
+ }
+ }
+ }
+
+ Message ms = session.createTextMessage(strMsg);
+ for (Map.Entry entry : properties.entrySet()) {
+ ms.setStringProperty(entry.getKey(), entry.getValue());
+ }
+
+ return ms;
+ }
+ });
+ }
+ });
+
+ listenerContainer.afterPropertiesSet();
+ listenerContainer.start();
+ }
+
+ public void stop() throws Exception {
+ if (listenerContainer != null) {
+ listenerContainer.stop();
+ listenerContainer.shutdown();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/amq/AMQSenderAdapter.java b/src/main/java/com/eactive/eai/adapter/amq/AMQSenderAdapter.java
new file mode 100644
index 0000000..4945765
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/amq/AMQSenderAdapter.java
@@ -0,0 +1,358 @@
+package com.eactive.eai.adapter.amq;
+
+import java.nio.charset.Charset;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.jms.pool.PooledConnectionFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+import org.springframework.jms.core.SessionCallback;
+import org.springframework.jms.support.JmsUtils;
+import org.springframework.jms.support.destination.DestinationResolver;
+
+import com.eactive.eai.adapter.ElinkDefaultAdapter;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.common.message.EAIMessageKeys;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.env.ElinkConfig;
+
+public class AMQSenderAdapter extends ElinkDefaultAdapter {
+ public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public static final String ADAPTER_NAME = "ADAPTER_NAME";
+
+ private static final class ProducerConsumer implements SessionCallback {
+ private final String msg;
+ private final DestinationResolver destinationResolver;
+ private final String queue;
+ private final String receiveQueue;
+ private final Long receiveTimeoutSeconds;
+ private final Long timeToLiveSeconds;
+ private final String messageType;
+ private final String relayPropertyGroup;
+
+ public ProducerConsumer(final String msg, String queue, String receiveQueue,
+ final DestinationResolver destinationResolver, Long receiveTimeoutSeconds, Long timeToLiveSeconds,
+ String messageType, String relayPropertyGroup) {
+ this.msg = msg;
+ this.queue = queue;
+ this.receiveQueue = receiveQueue;
+ this.destinationResolver = destinationResolver;
+ this.receiveTimeoutSeconds = receiveTimeoutSeconds;
+ this.timeToLiveSeconds = timeToLiveSeconds;
+ this.messageType = messageType;
+ this.relayPropertyGroup = relayPropertyGroup;
+ }
+
+ public Message doInJms(final Session session) throws JMSException {
+ MessageConsumer consumer = null;
+ MessageProducer producer = null;
+ try {
+ final String correlationId = UUID.randomUUID().toString();
+ if (logger.isDebug()) {
+ logger.debug("correlationId=====" + correlationId);
+ }
+ final Destination requestQueue = destinationResolver.resolveDestinationName(session, queue, false);
+ final Destination replyQueue = destinationResolver.resolveDestinationName(session, receiveQueue, false);
+
+ // Create the consumer first!
+ consumer = session.createConsumer(replyQueue, "JMSCorrelationID = '" + correlationId + "'");
+
+ JSONObject propObject = new JSONObject();
+ String strMsg = AMQSenderAdapter.extractRequestProperties(propObject, msg, messageType,
+ relayPropertyGroup);
+ final Message textMessage = session.createTextMessage(strMsg);
+ textMessage.setJMSCorrelationID(correlationId);
+ textMessage.setJMSReplyTo(replyQueue);
+ AMQSenderAdapter.assignRequestProperties(textMessage, propObject);
+
+ // Send the request second!
+ producer = session.createProducer(requestQueue);
+ if (timeToLiveSeconds != null) {
+ producer.setTimeToLive(timeToLiveSeconds.longValue() * 1000);
+ }
+ producer.send(requestQueue, textMessage);
+
+ // Block on receiving the response with a timeout
+ if (receiveTimeoutSeconds != null && receiveTimeoutSeconds.longValue() > 0) {
+ return consumer.receive(receiveTimeoutSeconds.longValue() * 1000);
+ } else {
+ return consumer.receive(AMQAdapterConstants.DEFAULT_MESSAGE_RECEIVE_TIMEOUT * 1000);
+ }
+ } catch (JMSException jmse) {
+ throw jmse;
+ } catch (Exception e) {
+ throw new JMSException(e.getMessage());
+ } finally {
+ JmsUtils.closeMessageConsumer(consumer);
+ JmsUtils.closeMessageProducer(producer);
+ }
+ }
+ }
+
+ @Override
+ public Object execute(Properties prop, Object message, Properties tempProp) throws Exception {
+ String syncAsync = tempProp.getProperty(AMQAdapterConstants.TEMP_INTERFACE_RESPONSE_TYPE);
+ if (StringUtils.equals(syncAsync, EAIMessageKeys.ASYNC_SVC)) {
+ return executeAsync(prop, message, tempProp);
+ }
+
+ String sendQueue = prop.getProperty(AMQAdapterConstants.PROP_REQUEST_QUEUE_NAME);
+ if (StringUtils.isBlank(sendQueue)) {
+ throw new Exception("No have send Queue name");
+ }
+
+ String replyQueue = prop.getProperty(AMQAdapterConstants.PROP_REPLY_QUEUE_NAME);
+ if (StringUtils.isBlank(replyQueue)) {
+ throw new Exception("No have reply Queue name");
+ }
+
+ String timeToLive = prop.getProperty(AMQAdapterConstants.PROP_MESSAGE_TIME_TO_LIVE);
+ Long timeToLiveSeconds = null;
+ if (NumberUtils.isParsable(timeToLive)) {
+ timeToLiveSeconds = new Long(timeToLive);
+ }
+
+ String receiveTimeout = prop.getProperty(AMQAdapterConstants.PROP_MESSAGE_RECEIVE_TIMEOUT);
+ Long receiveTimeoutSeconds = AMQAdapterConstants.DEFAULT_MESSAGE_RECEIVE_TIMEOUT;
+ if (NumberUtils.isParsable(receiveTimeout)) {
+ receiveTimeoutSeconds = new Long(receiveTimeout);
+ }
+
+ // 인터페이스 정보에 설정된 타임아웃이 우선
+ String interfaceTimeout = tempProp.getProperty(com.eactive.eai.common.routing.Process.INTERFACE_TIME_OUT);
+ if (NumberUtils.isParsable(interfaceTimeout)) {
+ long miliseconds = NumberUtils.toLong(interfaceTimeout);
+ if (miliseconds >= 1000) {
+ receiveTimeoutSeconds = new Long(miliseconds / 1000);
+ }
+ }
+
+ String encode = tempProp.getProperty(Keys.CHARSET_KEY_OUT, Charset.defaultCharset().name());
+ String sendMsg = "";
+ if (message instanceof String) {
+ sendMsg = (String) message;
+ } else if (message instanceof byte[]) {
+ sendMsg = new String((byte[]) message, encode);
+ }
+
+ String relayPropertyGroup = prop.getProperty(AMQAdapterConstants.PROP_RELAY_PROPERTY_GROUP);
+ String relayResponsePropertyKeys = prop.getProperty(AMQAdapterConstants.PROP_RELAY_RESPONSE_PROPERTY_KEYS);
+ String messageType = tempProp.getProperty(AMQAdapterConstants.TEMP_MESSAGE_TYPE);
+
+ String adapterName = tempProp.getProperty(ADAPTER_NAME);
+
+ try {
+ PooledConnectionFactory connectionFactory = AMQAdapterManager.getInstance()
+ .getOutboundPooledConnectionFactory(adapterName);
+
+ JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
+ jmsTemplate.setExplicitQosEnabled(true);
+ jmsTemplate.setDeliveryPersistent(false);
+ jmsTemplate.setReceiveTimeout(receiveTimeoutSeconds.longValue() * 1000);
+ if (timeToLiveSeconds != null) {
+ jmsTemplate.setTimeToLive(timeToLiveSeconds.longValue() * 1000);
+ }
+
+ Message receiveMessage = jmsTemplate
+ .execute(new ProducerConsumer(sendMsg, sendQueue, replyQueue, jmsTemplate.getDestinationResolver(),
+ receiveTimeoutSeconds, timeToLiveSeconds, messageType, relayPropertyGroup), true);
+
+ String returnMsg = "";
+ if (receiveMessage != null) {
+ returnMsg = assignResponseProperties(receiveMessage, messageType, relayPropertyGroup,
+ relayResponsePropertyKeys);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("AMQSenderAdapter] Received message: {}", returnMsg);
+ }
+ } else {
+ throw new JMSException(
+ "Received NULL(The timeout expires or this message consumer is concurrently closed)");
+ }
+
+ return returnMsg;
+ } catch (Exception e) {
+ logger.error("AMQSenderAdapter] Exception (" + adapterName + ") : " + e.getMessage(), e);
+ throw e;
+ } catch (Throwable t) {
+ logger.error("AMQSenderAdapter] Throwable (" + adapterName + ") : " + t.getMessage(), t);
+ throw t;
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private String assignResponseProperties(Message receiveMessage, String messageType, String relayPropertyGroup,
+ String relayResponsePropertyKeys) throws Exception {
+ if (!(receiveMessage instanceof TextMessage)) {
+ return receiveMessage.toString();
+ }
+
+ String returnMsg = ((TextMessage) receiveMessage).getText();
+
+ // Queue property to JSON
+ try {
+ if (MessageType.JSON.equals(messageType) && StringUtils.isNotBlank(relayPropertyGroup)
+ && StringUtils.isNotBlank(relayResponsePropertyKeys)) {
+ String[] relayKeyArr = org.springframework.util.StringUtils
+ .tokenizeToStringArray(relayResponsePropertyKeys, ",");
+ JSONObject propertyJson = new JSONObject();
+ if (StringUtils.equalsIgnoreCase(relayResponsePropertyKeys, "ALL")) {
+ Enumeration propertyNames = receiveMessage.getPropertyNames();
+ while (propertyNames.hasMoreElements()) {
+ String propertyName = propertyNames.nextElement();
+ propertyJson.put(propertyName, receiveMessage.getStringProperty(propertyName));
+ }
+ } else {
+ for (String key : relayKeyArr) {
+ String value = receiveMessage.getStringProperty(key);
+ if (value != null) {
+ propertyJson.put(key, value);
+ }
+ }
+ }
+
+ if (propertyJson.size() <= 0) {
+ return returnMsg;
+ }
+
+ JSONObject bodyJson = null;
+ if (StringUtils.isBlank(returnMsg)) {
+ bodyJson = new JSONObject();
+ } else {
+ bodyJson = (JSONObject) JSONValue.parse(returnMsg);
+ }
+
+ // malformed json message
+ if (bodyJson == null) {
+ return returnMsg;
+ }
+
+ bodyJson.put(relayPropertyGroup, propertyJson);
+ return bodyJson.toJSONString();
+ }
+ } catch (Exception e) {
+ if (logger.isWarn()) {
+ logger.warn(e.getMessage());
+ }
+ }
+
+ return returnMsg;
+ }
+
+ private Object executeAsync(Properties prop, Object message, Properties tempProp) throws Exception {
+ String sendQueue = prop.getProperty(AMQAdapterConstants.PROP_REQUEST_QUEUE_NAME);
+ if (StringUtils.isBlank(sendQueue)) {
+ throw new Exception("No have send Queue name");
+ }
+
+ String relayPropertyGroup = prop.getProperty(AMQAdapterConstants.PROP_RELAY_PROPERTY_GROUP);
+ String messageType = tempProp.getProperty(AMQAdapterConstants.TEMP_MESSAGE_TYPE);
+ String timeToLive = prop.getProperty(AMQAdapterConstants.PROP_MESSAGE_TIME_TO_LIVE);
+
+ String encode = tempProp.getProperty(Keys.CHARSET_KEY_OUT, Charset.defaultCharset().name());
+ final String sendMsg;
+ if (message instanceof String) {
+ sendMsg = (String) message;
+ } else if (message instanceof byte[]) {
+ sendMsg = new String((byte[]) message, encode);
+ } else {
+ sendMsg = "";
+ }
+
+ String adapterName = tempProp.getProperty(ADAPTER_NAME);
+
+ try {
+ PooledConnectionFactory connectionFactory = AMQAdapterManager.getInstance()
+ .getOutboundPooledConnectionFactory(adapterName);
+
+ JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
+ jmsTemplate.setExplicitQosEnabled(true);
+ jmsTemplate.setDeliveryPersistent(false);
+ if (NumberUtils.isParsable(timeToLive)) {
+ jmsTemplate.setTimeToLive(NumberUtils.toLong(timeToLive) * 1000);
+ }
+
+ jmsTemplate.send(sendQueue, new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ JSONObject propObject = new JSONObject();
+ String strMsg = AMQSenderAdapter.extractRequestProperties(propObject, sendMsg, messageType,
+ relayPropertyGroup);
+ Message ms = session.createTextMessage(strMsg);
+ AMQSenderAdapter.assignRequestProperties(ms, propObject);
+
+ return ms;
+ }
+ });
+
+ return ElinkConfig.getAsyncDummyData(null);
+ } catch (Exception e) {
+ logger.error("AMQSenderAdapter Async] Exception (" + adapterName + ") : " + e.getMessage(), e);
+ throw e;
+ } catch (Throwable t) {
+ logger.error("AMQSenderAdapter Async] Throwable (" + adapterName + ") : " + t.getMessage(), t);
+ throw t;
+ }
+ }
+
+ @SuppressWarnings({ "deprecation", "unchecked" })
+ protected static String extractRequestProperties(JSONObject propObject, String sendMsg, String messageType,
+ String relayPropertyGroup) {
+ String strMsg = sendMsg;
+ if (MessageType.JSON.equals(messageType) && StringUtils.isNotBlank(relayPropertyGroup)
+ && StringUtils.contains(strMsg, relayPropertyGroup)) {
+ try {
+ JSONObject dataObject = (JSONObject) JSONValue.parse(strMsg);
+ JSONObject tmpPropObject = (JSONObject) dataObject.get(relayPropertyGroup);
+ if (tmpPropObject != null) {
+ propObject.putAll(tmpPropObject);
+ dataObject.remove(relayPropertyGroup);
+ strMsg = dataObject.toJSONString();
+ }
+ } catch (Exception e) {
+ if (logger.isWarn()) {
+ logger.warn(e.getMessage());
+ }
+ }
+ }
+
+ return strMsg;
+ }
+
+ protected static void assignRequestProperties(Message ms, JSONObject propObject) {
+ if (propObject == null || propObject.size() == 0) {
+ return;
+ }
+
+ for (Object key : propObject.keySet()) {
+ Object obj = propObject.get(key);
+ if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) {
+ continue;
+ }
+
+ try {
+ ms.setStringProperty((String) key, (String) obj);
+ } catch (Exception e) {
+ if (logger.isWarn()) {
+ logger.warn(e.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/app/BusinessApplication.java b/src/main/java/com/eactive/eai/adapter/app/BusinessApplication.java
new file mode 100644
index 0000000..6680918
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/app/BusinessApplication.java
@@ -0,0 +1,9 @@
+package com.eactive.eai.adapter.app;
+
+import java.util.Properties;
+
+public interface BusinessApplication {
+ public static final String EAI_SVC_NAME = "eaiSvcName";
+
+ public Object executeApplication(Properties prop, Object message, Properties tempProp) throws Exception;
+}
diff --git a/src/main/java/com/eactive/eai/adapter/app/BusinessApplicationAdapter.java b/src/main/java/com/eactive/eai/adapter/app/BusinessApplicationAdapter.java
new file mode 100644
index 0000000..e57d0c4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/app/BusinessApplicationAdapter.java
@@ -0,0 +1,45 @@
+package com.eactive.eai.adapter.app;
+
+import com.eactive.eai.adapter.ElinkDefaultAdapter;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.lang3.StringUtils;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import java.util.Properties;
+
+public class BusinessApplicationAdapter extends ElinkDefaultAdapter {
+ public static final String ADAPTER_PROP_CLASS_NAME = "BUSINESS_CLASS_NAME";
+ public static final String REST_OPTION_CLASS_NAME = "businessClassName";
+
+ @Override
+ public Object execute(Properties prop, Object message, Properties tempProp) throws Exception {
+ String restOption = prop.getProperty(HttpClientAdapterServiceKey.REST_OPTION);
+ JSONObject restOptionObject = parseJson(restOption);
+
+ String businessClassName = null;
+ if (restOptionObject != null) {
+ businessClassName = (String) restOptionObject.get(REST_OPTION_CLASS_NAME);
+ }
+
+ if (StringUtils.isBlank(businessClassName)) {
+ businessClassName = prop.getProperty(ADAPTER_PROP_CLASS_NAME);
+ if (StringUtils.isBlank(businessClassName)) {
+ throw new Exception(ADAPTER_PROP_CLASS_NAME + " is not set.");
+ }
+ }
+
+ BusinessApplication app = BusinessApplicationFactory.createApplication(businessClassName);
+ return app.executeApplication(prop, message, tempProp);
+ }
+
+ @SuppressWarnings("deprecation")
+ private JSONObject parseJson(String message) {
+ if (StringUtils.isBlank(message)) {
+ return null;
+ }
+
+ return (JSONObject) JSONValue.parse(message);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/app/BusinessApplicationFactory.java b/src/main/java/com/eactive/eai/adapter/app/BusinessApplicationFactory.java
new file mode 100644
index 0000000..bc690c4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/app/BusinessApplicationFactory.java
@@ -0,0 +1,26 @@
+package com.eactive.eai.adapter.app;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+public class BusinessApplicationFactory {
+ static private ConcurrentHashMap h = new ConcurrentHashMap();
+
+ @SuppressWarnings("rawtypes")
+ public static BusinessApplication createApplication(String className) throws Exception {
+ if (h.containsKey(className)) {
+ return (BusinessApplication) h.get(className);
+ }
+
+ BusinessApplication app = null;
+ try {
+ Class cl = Class.forName(className);
+ app = (BusinessApplication) cl.newInstance();
+ if (app != null) {
+ h.put(className, app);
+ }
+ } catch (Exception e) {
+ throw new Exception("Cannot create a BusinessApplication. - " + className);
+ }
+ return app;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/app/impl/OnlineToFileWriter.java b/src/main/java/com/eactive/eai/adapter/app/impl/OnlineToFileWriter.java
new file mode 100644
index 0000000..411d216
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/app/impl/OnlineToFileWriter.java
@@ -0,0 +1,84 @@
+package com.eactive.eai.adapter.app.impl;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+import org.json.simple.JSONObject;
+
+import com.eactive.eai.adapter.app.BusinessApplication;
+import com.eactive.eai.common.util.DatetimeUtil;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.StringUtil;
+
+public class OnlineToFileWriter implements BusinessApplication {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ public static final String CLASS_PROPS = "BUSINESS_CLASS_PROPS";
+ public static final String CLASS_PROPS_BASE_FILE_PATH = "baseFilePath";
+ public static final String CLASS_PROPS_ENCODE = "encode";
+ public static final String CLASS_PROPS_FILE_PATH_EXT = "fileExt";
+
+ /**
+ * @formatter:off
+ * Adapter property ¼³Á¤: BUSINESS_CLASS_PROPS
+ * - ex) baseFilePath=/data/onlineToJson, fileExt=json
+ * @formatter:on
+ */
+ @Override
+ public Object executeApplication(Properties prop, Object message, Properties tempProp) throws Exception {
+ String classPropsStr = prop.getProperty(CLASS_PROPS);
+ Properties classProp = StringUtil.getProperties(classPropsStr);
+ String baseFilePath = classProp.getProperty(CLASS_PROPS_BASE_FILE_PATH);
+ if (StringUtils.isBlank(baseFilePath)) {
+ throw new Exception(String.format("Property(%s) is not setted", CLASS_PROPS_BASE_FILE_PATH));
+ }
+
+ String encode = classProp.getProperty(CLASS_PROPS_ENCODE, "UTF-8");
+ String fileExt = classProp.getProperty(CLASS_PROPS_FILE_PATH_EXT, "txt");
+ String eaiSvcName = tempProp.getProperty(BusinessApplication.EAI_SVC_NAME);
+ if (StringUtils.isBlank(eaiSvcName)) {
+ throw new Exception("Can not find serviceId");
+ }
+ String dirStr = StringUtils.removeEnd(baseFilePath, "/") + "/" + eaiSvcName;
+ File dir = new File(dirStr);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+
+ String fileName = DatetimeUtil.getFormattedDate("yyyyMMdd-HHmmssSSS") + "." + fileExt;
+ File file = new File(dir, fileName);
+
+ Map resultMap = new HashMap<>();
+
+ try (
+ FileWriter fw = new FileWriter(file);
+ BufferedWriter bw = new BufferedWriter(fw);
+ ){
+ if (message == null) {
+ logger.warn("message is null");
+ } else if (message instanceof byte[]) {
+ byte[] buff = (byte[]) message;
+ bw.write(new String(buff, encode));
+ } else {
+ bw.write(message.toString());
+ }
+ bw.flush();
+
+ resultMap.put("RESULTCD", "000");
+ resultMap.put("RESULTMSG", "Success");
+ resultMap.put("FILENAME", fileName);
+ } catch (Exception e) {
+ logger.error("OnlineToFileWriter error", e);
+ throw e;
+ }
+
+ JSONObject resultJsonObject = new JSONObject();
+ resultJsonObject.putAll(resultMap);
+ return resultJsonObject.toJSONString().getBytes();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/db/DBAdapterKeys.java b/src/main/java/com/eactive/eai/adapter/db/DBAdapterKeys.java
new file mode 100644
index 0000000..65b06e4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/db/DBAdapterKeys.java
@@ -0,0 +1,29 @@
+package com.eactive.eai.adapter.db;
+
+public class DBAdapterKeys {
+ public static final String ADAPTER_GROUPNAME = "adapterGroupName";
+ public static final String ADAPTER_NAME = "adapterName";
+ public static final String ADAPTER_PROPGN = "propGroupName";
+
+ // jdbc common
+ public static final String DRIVER = "jdbc.driver";
+ public static final String URL = "jdbc.url";
+ public static final String USER = "jdbc.user";
+ public static final String PVAL = "jdbc.pval";
+ public static final String DATASOURCE = "jdbc.datasource"; // optional
+ public static final String ENCODE = "encode"; // optional
+
+ // inbound query
+ public static final String SELECT = "jdbc.select"; // select query
+ public static final String UPDATE = "jdbc.update"; // update query
+ // inbound scheduler
+ public static final String RUN_CRONEXP = "run.cronexp"; // Quartz [ 0/10 * * * * ? ]
+ public static final String RUN_INTVL = "run.interval"; // 0...N
+ public static final String RUN_RETRY = "run.retry"; // Y|N
+ public static final String RUN_RETRYCNT = "run.retrycnt"; // 0...N
+ public static final String RUN_RETRYINTVL = "run.retryinterval"; //ms
+ public static final String RUN_MSGTYPE = "run.msgtype"; // XML | JSON
+
+ // Outbound
+ public static final String QUERY = "query";
+}
diff --git a/src/main/java/com/eactive/eai/adapter/db/sql/AdapterUtils.java b/src/main/java/com/eactive/eai/adapter/db/sql/AdapterUtils.java
new file mode 100644
index 0000000..28279ec
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/db/sql/AdapterUtils.java
@@ -0,0 +1,50 @@
+package com.eactive.eai.adapter.db.sql;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Properties;
+
+public class AdapterUtils {
+
+ public static void main(String[] args) {
+ String updateSql = "update EAIINF01 set RFLAG = 'C' where UNID = '%UNID%'";
+ LinkedHashMap map = new LinkedHashMap();
+ map.put("Unid", "ID00000001");
+
+ String prefix = "%", surfix = "%";
+ System.out.println(updateSql);
+ System.out.println(getUpdateQuery(updateSql, map, prefix, surfix));
+ }
+
+ public static Properties getAdapterProerties(String propGroupName) {
+ AdapterPropManager pmanager = AdapterPropManager.getInstance();
+ Properties prop = null;
+ if(pmanager == null) {
+ prop = new Properties();
+ }
+ else {
+ prop = pmanager.getProperties(propGroupName);
+ }
+ return prop;
+ }
+
+ public static String getUpdateQuery(String updateSql, HashMap map) {
+ return getUpdateQuery(updateSql, map, "%", "%");
+ }
+
+ public static String getUpdateQuery(String updateSql, HashMap map, String prefix, String surfix) {
+ String convertedSql = updateSql;
+
+ String paramName = null;
+ for(String colName : map.keySet()) {
+ paramName = prefix+colName.toUpperCase()+surfix;
+ if(updateSql.indexOf(paramName) > -1) {
+ convertedSql = convertedSql.replaceAll(paramName, (String)map.get(colName));
+ }
+ }
+ return convertedSql;
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapter.java b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapter.java
new file mode 100644
index 0000000..7a4797b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapter.java
@@ -0,0 +1,284 @@
+package com.eactive.eai.adapter.db.sql;
+
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.RequestDispatcher;
+import com.eactive.eai.adapter.db.DBAdapterKeys;
+import com.eactive.eai.adapter.wca.jdbc.JDBCException;
+import com.eactive.eai.common.message.EAIMessageKeys;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.ServiceLocator;
+
+import javax.sql.DataSource;
+import java.sql.*;
+import java.util.LinkedHashMap;
+import java.util.Properties;
+
+public class DBInboudSqlAdapter {
+ public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ private boolean isLocalTest = false;
+
+
+ private String logPrefix = "";
+ private boolean isRunning = false;
+ private boolean stopRunning = false;
+
+ private AdapterVO vo;
+ private Properties configProperties = null;
+
+ public boolean isRunningState() {
+ return isRunning;
+ }
+
+ public void setAdapterVO(AdapterVO vo) {
+ this.vo = vo;
+ }
+
+ public void setProperties(Properties p) {
+ this.configProperties = p;
+ }
+
+ public void stop() {
+ stopRunning = true;
+ }
+
+ public DBInboudSqlAdapter(AdapterVO vo, Properties configProperties) {
+ super();
+ this.vo = vo;
+ this.configProperties = configProperties;
+ if(vo == null) {
+ logPrefix = this.getClass().getSimpleName() +"] ";
+ }
+ else {
+ logPrefix = vo.getName() +"] ";
+ }
+ String isLocal = System.getProperty("isLocal");
+ if(isLocal != null && "true".equalsIgnoreCase(isLocal)) {
+ isLocalTest = true;
+ }
+ System.out.println("$$$ DBInboudSqlAdapter] isLocalTest = " + isLocalTest);
+ }
+
+ public boolean execute() {
+ isRunning = true;
+ int chunkSize = 15;
+ Connection con = null;
+ PreparedStatement pstmt = null;
+ PreparedStatement pstmtUpdate = null;
+ ResultSet rs = null;
+
+ String datasoureName = configProperties.getProperty(DBAdapterKeys.DATASOURCE) ;
+ String selectQuery = configProperties.getProperty(DBAdapterKeys.SELECT) ;
+ String updateQuery = configProperties.getProperty(DBAdapterKeys.UPDATE) ;
+
+ int runInterval = 0;
+ String runIntervalStr = configProperties.getProperty(DBAdapterKeys.RUN_INTVL) ;
+ try {
+ runInterval = Integer.parseInt(runIntervalStr);
+ }
+ catch(Exception e) {
+ runInterval = 0;
+ }
+
+ String runRetry = configProperties.getProperty(DBAdapterKeys.RUN_RETRY, "N") ; // Y | N
+
+ int runRetryCnt = 0;
+ String runRetryCntStr = configProperties.getProperty(DBAdapterKeys.RUN_RETRYCNT, "0") ;
+ try {
+ runRetryCnt = Integer.parseInt(runRetryCntStr);
+ }
+ catch(Exception e) {
+ runRetryCnt = 0;
+ }
+
+ int runRetryInterval = 0;
+ String runRetryIntervalStr = configProperties.getProperty(DBAdapterKeys.RUN_RETRYINTVL, "0") ;
+ try {
+ runRetryInterval = Integer.parseInt(runRetryIntervalStr);
+ }
+ catch(Exception e) {
+ runRetryInterval = 0;
+ }
+
+ int rowIndex = 0;
+ int colCount = 0;
+ try {
+ if(datasoureName != null && datasoureName.trim().length() > 0) {
+ con = getDataSourceConnection(datasoureName);
+ }
+ else {
+ con = getJDBCConnection(configProperties);
+ }
+ // default : row unit commit
+ con.setAutoCommit(true);
+
+ // select chunk record
+ pstmt = con.prepareStatement(selectQuery);
+ rs = pstmt.executeQuery();
+
+ rowIndex = 0;
+ colCount = rs.getMetaData().getColumnCount();
+ debug(String.format("$$$ RUNNING Query [%s] - colCount = %s", selectQuery, colCount) );
+
+ String rowString = null;
+
+ // LOOP - Inbound Call
+ LinkedHashMap map = new LinkedHashMap();
+ boolean isSuccess = false;
+ int retryExecCounter = 0;
+ boolean retryFailed = false;
+ while(rs.next() && !retryFailed){
+ debug(String.format("==> run [%s]", (rowIndex+1)) );
+ if(stopRunning) {
+ debug(String.format("$$$ STOP RUNNING stopRunning[%s]", stopRunning) );
+ break;
+ }
+
+ for(int i = 1; i <= colCount; i++){
+ String key = rs.getMetaData().getColumnName(i);
+ String value = rs.getString(i);
+ if(value == null){
+ value = "";
+ }
+ map.put(key, value);
+ }
+
+ if("JSON".equals(configProperties.getProperty(DBAdapterKeys.RUN_MSGTYPE))) {
+ rowString = ResultParser.toJsonString(map);
+ }
+ if("XML".equals(configProperties.getProperty(DBAdapterKeys.RUN_MSGTYPE))) {
+ rowString = ResultParser.toXmlString(map);
+ }
+
+ debug(String.format("==> run [%s] : ", (rowIndex+1)) + rowString);
+ //-- start sudo test code
+// debug(String.format("Sleep 1 secs - run [%s/%s]", (rowIndex+1), chunkSize) );
+
+ //-- end sudo test code
+
+ byte[] request = rowString.getBytes();
+ byte[] response = null;
+ String elinkResponseCode = null;
+ while(true) {
+ try {
+ isSuccess = false;
+ RequestDispatcher dispatcher = RequestDispatcher.getRequestDispatcher(vo.getAdapterGroupName());
+ response = (byte[]) dispatcher.handle(vo.getName(), request, this.configProperties);
+
+ elinkResponseCode = configProperties.getProperty(EAIMessageKeys.ELINK_RET_CODE);
+ debug("RequestProcessor.ELINK_RET_CODE ["+ elinkResponseCode +"]" );
+
+ // Sunncess check with elink F/W response code ESBEAI111111
+ if(EAIMessageKeys.EAI_SUCCESS_CODE.equals(elinkResponseCode)
+ || EAIMessageKeys.EAI_DEFAULT_CODE.equals(elinkResponseCode)) {
+ isSuccess = true;
+ }
+ } catch (Exception e) {
+ logger.error("RequestDispatcher call error",e);
+ }
+
+ if(isSuccess) {
+ // check response
+ if(response != null) debug("Response Message : " + new String(response));
+
+ // if success, update CHK column
+ String mappedUpdate = AdapterUtils.getUpdateQuery(updateQuery, map);
+ debug("mappedUpdate - "+ mappedUpdate);
+ pstmtUpdate = con.prepareStatement(mappedUpdate);
+ int cnt = pstmtUpdate.executeUpdate();
+ debug("mappedUpdate result - "+ cnt);
+ // if success, skip retry
+ break;
+ }
+ else {
+ // if failed, retry or break, check retry options
+ if("Y".equals(runRetry)) {
+ debug(String.format(">> RETRY [%s / %s]", retryExecCounter, runRetryCnt) );
+
+ if(retryExecCounter < runRetryCnt) {
+ debug(String.format(">> RETRY runRetry=%s", runRetry) );
+ ++retryExecCounter;
+ if(runRetryInterval > 0) {
+ debug("Sleep run.retryinterval - " +runRetryInterval);
+ Thread.sleep(runRetryInterval);
+ }
+ continue;
+ }
+ else {
+ debug(String.format(">> RETRY COMPLETED [%s / %s], STOP JOB", retryExecCounter, runRetryCnt) );
+ retryFailed = true;
+ break;
+ }
+ }
+ else {
+ debug(String.format(">> RETRY Disabled, runRetry=%s", runRetry) );
+ retryFailed = true;
+ break;
+ }
+ }
+ } // end retry LOOP
+ rowIndex++;
+ if(runInterval > 0) {
+ debug("Sleep run.interval - " +runInterval);
+ Thread.sleep(runInterval);
+ }
+ }
+ // end row LOOP
+ }
+ catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ isRunning = false;
+ debug(String.format("JOB Completed. isRunning=%s, executed ROWCount=%s", isRunning, rowIndex) );
+ return isRunning;
+ }
+
+ private Connection getJDBCConnection(Properties p) throws SQLException {
+ try {
+ Class.forName(p.getProperty(DBAdapterKeys.DRIVER));
+ Connection con = DriverManager.getConnection(p.getProperty(DBAdapterKeys.URL),
+ p.getProperty(DBAdapterKeys.USER), p.getProperty(DBAdapterKeys.PVAL));
+ return con;
+ } catch (Exception e) {
+ throw new SQLException("DBAdapter] Cannot create a JDBC Connection. - " + e.getMessage());
+ }
+ }
+
+ private Connection getDataSourceConnection(String dataSourceName) throws JDBCException
+ {
+ DataSource dataSource = null;
+ try {
+ ServiceLocator sl = ServiceLocator.getInstance();
+ dataSource = sl.getDataSource(dataSourceName);
+ return dataSource.getConnection();
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ throw new JDBCException("["+dataSourceName+"]을 얻을 수 없습니다.");
+ }
+ }
+
+ private java.sql.Date toDate(String sDate) throws Exception {
+ java.sql.Date s = null;
+ if(sDate.length() == 10 && sDate.indexOf("-") > 0) {
+ s = java.sql.Date.valueOf(sDate);
+ }
+ else if(sDate.length() == 8) {
+ java.util.Date d = new java.text.SimpleDateFormat("yyyyMMdd").parse(sDate);
+ s = new java.sql.Date(d.getTime());
+ }
+ else {
+ throw new Exception("Invalid Date String - "+sDate);
+ }
+ return s;
+ }
+
+ private void debug(String msg) {
+ if(isLocalTest) {
+ System.out.println (logPrefix + msg);
+ }
+ else {
+ logger.info(logPrefix + msg);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterJob.java b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterJob.java
new file mode 100644
index 0000000..aac4008
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterJob.java
@@ -0,0 +1,62 @@
+package com.eactive.eai.adapter.db.sql;
+
+import com.eactive.eai.adapter.db.DBAdapterKeys;
+import com.eactive.eai.common.util.Logger;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.utils.Key;
+
+public class DBInboudSqlAdapterJob implements Job {
+
+ public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ private static boolean isLocalTest = false;
+
+ static {
+ String isLocal = System.getProperty("isLocalTest");
+ if(isLocal != null && "true".equalsIgnoreCase(isLocal)) {
+ isLocalTest = true;
+ }
+ }
+
+ private void debug(String msg) {
+ if(isLocalTest) {
+ System.out.println (msg);
+ }
+ else {
+ logger.info(msg);
+ }
+ }
+
+// private DBInboudSqlAdapter adapter = null;
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ // JobKey jobKey = context.getJobDetail().getKey();
+ Key jobKey = context.getJobDetail().getKey();
+ String data = "";
+ for (String key : context.getJobDetail().getJobDataMap().getKeys()) {
+ data = data + key + "=" + context.getJobDetail().getJobDataMap().getString(key) + ",";
+ }
+ debug( jobKey + " start data(" + data + ")");
+ logger.warn(">> " + jobKey + " start data(" + data + ")");
+ String jobKeyName = jobKey.getName();
+
+ String adapterName = context.getJobDetail().getJobDataMap().getString(DBAdapterKeys.ADAPTER_NAME);
+ String propGroupName = context.getJobDetail().getJobDataMap().getString(DBAdapterKeys.ADAPTER_PROPGN);
+ debug("adapterName=" + adapterName + ", propGroupName"+ propGroupName );
+
+
+ DBInboudSqlAdapter adapter = DBInboudSqlAdapterManager.getInstance().get(adapterName);
+ if(adapter == null) {
+ debug(jobKey + " : @@@@ Adapter not found in JobDataMap");
+ }
+ else {
+ if(adapter.isRunningState()) {
+ debug(jobKey + " : Adapter already RUNNING with previous scledule");
+ }
+ else {
+ debug(jobKey + " : Adapter Called.");
+ adapter.execute();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterListener.java b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterListener.java
new file mode 100644
index 0000000..bfc888c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterListener.java
@@ -0,0 +1,208 @@
+package com.eactive.eai.adapter.db.sql;
+
+import com.eactive.eai.adapter.db.DBAdapterKeys;
+import com.eactive.eai.adapter.listener.AdapterException;
+import com.eactive.eai.adapter.listener.AdapterListenerSupport;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import org.quartz.*;
+import org.quartz.impl.StdSchedulerFactory;
+
+import java.util.Date;
+import java.util.Properties;
+
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.JobBuilder.newJob;
+import static org.quartz.TriggerBuilder.newTrigger;
+
+public class DBInboudSqlAdapterListener extends AdapterListenerSupport {
+
+ String className = this.getClass().getName();
+ Scheduler scheduler = null;
+ private static boolean isLocalTest = false;
+ private String SCHE_GROUP_NAME = "DBQ_GROUP";
+
+ public boolean startScheduler(Properties prop) {
+ boolean isStart = false;
+ try {
+ debug(className + " Scheduler start");
+ logger.warn(className + " Scheduler start");
+ if(scheduler != null) {
+ logger.warn("Scheduler shutdown previous RUN !");
+ scheduler.shutdown();
+ }
+ String adapterName = prop.getProperty("adapterName");
+ scheduler = new StdSchedulerFactory().getScheduler();
+ String jobName = "DBInboudSqlAdapterJob";
+ String jobClassName = "com.eactive.eai.adapter.db.sql.DBInboudSqlAdapterJob";
+ String cronExp = prop.getProperty( DBAdapterKeys.RUN_CRONEXP ); // "0/10 * * * * ?";
+ registJob(jobName, jobClassName, cronExp, prop);
+ scheduler.start();
+ isStart = true;
+ }
+ catch(SchedulerException se) {
+ logger.error("Scheduler start failed", se);
+ }
+ catch(Exception e) {
+ logger.error("Scheduler start failed", e);
+ }
+ return isStart;
+ }
+
+ private String getTriggerName(String jobName) {
+ return jobName + "-trigger";
+ }
+
+ public boolean registJob(String jobName, String jobClassName, String cronExp, Properties p) {
+ try {
+ //configure the scheduler time
+ Class jobClass = Class.forName(jobClassName);
+
+ JobBuilder jobBuilder = newJob(jobClass);
+
+ jobBuilder = jobBuilder.withIdentity(jobName, Scheduler.DEFAULT_GROUP);
+
+ // pass adapter name : not used this time
+ jobBuilder.usingJobData(DBAdapterKeys.ADAPTER_NAME, p.getProperty(DBAdapterKeys.ADAPTER_NAME));
+ jobBuilder.usingJobData(DBAdapterKeys.ADAPTER_PROPGN, p.getProperty(DBAdapterKeys.ADAPTER_PROPGN));
+
+ JobDetail job = jobBuilder.build();
+
+ CronTrigger trigger = newTrigger().withIdentity( getTriggerName(jobName), SCHE_GROUP_NAME )
+ .withSchedule(cronSchedule(cronExp))
+ .build();
+
+ Date ft = scheduler.scheduleJob(job, trigger);
+ logger.warn(String.format("%s has been scheduled to run at: %s and repeat based on expression: %s", job.getKey(), ft,
+ trigger.getCronExpression()) );
+
+ return true;
+ }
+ catch(Exception e) {
+ logger.warn("registJob failed", e);
+ return false;
+ }
+ }
+
+ private void printProperties(Properties prop) throws Exception {
+ if(prop == null) {
+ debug("printProperties - Properties is null");
+ return;
+ }
+ for (Object key: prop.keySet()) {
+ debug(key + ": " + prop.getProperty(key.toString()));
+ }
+// prop.forEach((key, value) -> debug("Key : " + key + ", Value : " + value));
+ }
+
+ private void init(Properties prop) throws Exception {
+ debug("Start init");
+ printProperties(prop);
+ startScheduler(prop);
+ }
+
+ public void start() throws AdapterException {
+ Properties prop = null;
+ String adapterName = null;
+ if(info != null) {
+ String propGroupName = info.getPropGroupName();
+ prop = AdapterUtils.getAdapterProerties(propGroupName);
+ adapterName = info.getName();
+ prop.setProperty(DBAdapterKeys.ADAPTER_PROPGN, propGroupName);
+ }
+ // TODO : Application Test Code.
+ // in real system, remove this block
+ else {
+ prop = new Properties();
+
+ prop.setProperty(DBAdapterKeys.RUN_CRONEXP, "0/10 * * * * ?");
+ prop.setProperty(DBAdapterKeys.RUN_INTVL, "1000");
+ prop.setProperty(DBAdapterKeys.RUN_RETRY, "N");
+ prop.setProperty(DBAdapterKeys.RUN_RETRYCNT, "2");
+ prop.setProperty(DBAdapterKeys.RUN_RETRYINTVL, "5000");
+ prop.setProperty(DBAdapterKeys.RUN_MSGTYPE, "JSON");
+
+ prop.setProperty(DBAdapterKeys.DRIVER, "oracle.jdbc.driver.OracleDriver");
+ prop.setProperty(DBAdapterKeys.URL, "jdbc:oracle:thin:@localhost:1521:XE");
+ prop.setProperty(DBAdapterKeys.USER, "eai");
+ prop.setProperty(DBAdapterKeys.PVAL, "eaiadmin");
+// prop.setProperty(DBAdapterKeys.SELECT, "select * from APIJOBSCHE");
+ prop.setProperty(DBAdapterKeys.SELECT, "select * from EAIINF01 where RFLAG IS null ORDER BY UNID");
+ prop.setProperty(DBAdapterKeys.UPDATE, "update EAIINF01 set RFLAG = 'C' where UNID = '%UNID%' ");
+
+ debug("Start Scheduler");
+ adapterName = "_EAI_IN_DBQ_SyC";
+ }
+ // TODO : Application Test Code End.
+
+ prop.setProperty(DBAdapterKeys.ADAPTER_NAME, adapterName);
+ // Start Scheduler
+ try{
+ logger.warn(className + " STARTING");
+ init(prop);
+ DBInboudSqlAdapterManager maanger = DBInboudSqlAdapterManager.getInstance();
+ // init adapter configuration values
+ DBInboudSqlAdapter adapter = new DBInboudSqlAdapter(info, prop);
+ maanger.put(adapterName, adapter);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void stop() throws AdapterException {
+ try {
+ String adapterName = "";
+ if (info == null) {
+ adapterName = "_EAI_IN_DBQ_SyC";
+// throw new Exception(this.getClass().getName() +" | AdapterVO°¡ NULLÀÔ´Ï´Ù.");
+ }
+ else {
+ adapterName = info.getName();
+ }
+ if(scheduler != null) {
+ try {
+ DBInboudSqlAdapterManager manager = DBInboudSqlAdapterManager.getInstance();
+ DBInboudSqlAdapter adapter = manager.get(adapterName);
+ logger.warn("stop adapter - " + adapterName);
+ adapter.stop();
+ // Stop Scheduler
+ logger.warn("stop scheduler - " + scheduler.getSchedulerName());
+ JobKey key = new JobKey(adapterName, SCHE_GROUP_NAME );
+ scheduler.deleteJob(key);
+ scheduler.shutdown();
+ }
+ catch(SchedulerException se) {
+ logger.error("stop scheduler failed", se);
+ }
+ }
+ } catch (Exception e) {
+ String errCode = ExceptionUtil.getErrorCode(e, "RECEAIOIA009");
+ throw new AdapterException(errCode);
+ }
+ }
+
+ private void debug(String msg) {
+ if(isLocalTest) {
+ System.out.println (msg);
+ }
+ else {
+ logger.info(msg);
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ isLocalTest = true;
+ System.setProperty("isLocal", "true");
+ DBInboudSqlAdapterListener listener = new DBInboudSqlAdapterListener();
+ int testSecs = 60;
+ System.out.println (String.format(">> Test while %s secs ...", testSecs));
+ listener.start();
+ Thread.sleep(testSecs * 1000);
+ System.out.println ("<< Test end.");
+ listener.stop();
+ }
+ catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterManager.java b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterManager.java
new file mode 100644
index 0000000..85fa0a1
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/db/sql/DBInboudSqlAdapterManager.java
@@ -0,0 +1,21 @@
+package com.eactive.eai.adapter.db.sql;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DBInboudSqlAdapterManager {
+ private static DBInboudSqlAdapterManager instance = new DBInboudSqlAdapterManager();
+
+ private static ConcurrentHashMap adapters = new ConcurrentHashMap();
+
+ public static DBInboudSqlAdapterManager getInstance() {
+ return instance;
+ }
+
+ public synchronized void put(String adapterName, DBInboudSqlAdapter adapter) {
+ adapters.put(adapterName, adapter);
+ }
+
+ public synchronized DBInboudSqlAdapter get(String adapterName) {
+ return adapters.get(adapterName);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/db/sql/ResultParser.java b/src/main/java/com/eactive/eai/adapter/db/sql/ResultParser.java
new file mode 100644
index 0000000..72d3095
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/db/sql/ResultParser.java
@@ -0,0 +1,27 @@
+package com.eactive.eai.adapter.db.sql;
+
+import org.json.simple.JSONObject;
+
+import java.util.LinkedHashMap;
+
+public class ResultParser {
+ public static String toJsonString(LinkedHashMap map) {
+ JSONObject jsonObject = new JSONObject();
+ for (String key : map.keySet()) {
+ jsonObject.put(key, map.get(key));
+ }
+ return jsonObject.toJSONString();
+ }
+
+ public static String toXmlString(LinkedHashMap map) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("");
+ for (String key : map.keySet()) {
+ sb.append("<").append(key).append(">");
+ sb.append(map.get(key));
+ sb.append("").append(key).append(">");
+ }
+ sb.append("
");
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/handler/AdapterErrorMessageHandler.java b/src/main/java/com/eactive/eai/adapter/handler/AdapterErrorMessageHandler.java
new file mode 100644
index 0000000..7699f95
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/handler/AdapterErrorMessageHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.handler;
+
+import java.util.Properties;
+
+import com.eactive.eai.message.StandardMessage;
+
+public interface AdapterErrorMessageHandler {
+ public Object generateNonStandardErrorResponseMessage(String inboudnAdapterGroupName, String inboudnAdapterName, Properties callProp, Object outboundRequestData, StandardMessage resStandardMessage) throws Exception;
+}
+
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/handler/AdapterErrorMessageHandlerFactory.java b/src/main/java/com/eactive/eai/adapter/handler/AdapterErrorMessageHandlerFactory.java
new file mode 100644
index 0000000..69143c4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/handler/AdapterErrorMessageHandlerFactory.java
@@ -0,0 +1,31 @@
+package com.eactive.eai.adapter.handler;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.eactive.eai.common.util.Logger;
+
+public class AdapterErrorMessageHandlerFactory {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ static private ConcurrentHashMap h = new ConcurrentHashMap();
+
+ @SuppressWarnings("rawtypes")
+ public static AdapterErrorMessageHandler createHandler(String handlerClassName) {
+ if (h.containsKey(handlerClassName)) {
+ return (AdapterErrorMessageHandler) h.get(handlerClassName);
+ }
+
+ AdapterErrorMessageHandler handler = null;
+ try {
+ Class cl = Class.forName(handlerClassName);
+ handler = (AdapterErrorMessageHandler) cl.newInstance();
+ } catch (Exception e) {
+ logger.error("Cannot create a AdapterErrorMessageHandler. - {}", handlerClassName);
+ }
+ if (handler != null) {
+ h.put(handlerClassName, handler);
+ return handler;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/handler/DefaultAdapterErrorMessageHandler.java b/src/main/java/com/eactive/eai/adapter/handler/DefaultAdapterErrorMessageHandler.java
new file mode 100644
index 0000000..35275fb
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/handler/DefaultAdapterErrorMessageHandler.java
@@ -0,0 +1,15 @@
+package com.eactive.eai.adapter.handler;
+
+import java.util.Properties;
+
+import com.eactive.eai.message.StandardMessage;
+
+public class DefaultAdapterErrorMessageHandler implements AdapterErrorMessageHandler {
+
+ @Override
+ public Object generateNonStandardErrorResponseMessage(String inboudnAdapterGroupName, String inboudnAdapterName,
+ Properties callProp, Object outboundRequestData, StandardMessage resStandardMessage) throws Exception {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/EntityEnclosingDeleteMethod.java b/src/main/java/com/eactive/eai/adapter/http/EntityEnclosingDeleteMethod.java
new file mode 100644
index 0000000..3ade5f6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/EntityEnclosingDeleteMethod.java
@@ -0,0 +1,18 @@
+package com.eactive.eai.adapter.http;
+
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+
+public class EntityEnclosingDeleteMethod extends EntityEnclosingMethod {
+
+ public EntityEnclosingDeleteMethod() {
+ }
+
+ public EntityEnclosingDeleteMethod(String uri) {
+ super(uri);
+ }
+
+ @Override
+ public String getName() {
+ return "DELETE";
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/EntityEnclosingGetMethod.java b/src/main/java/com/eactive/eai/adapter/http/EntityEnclosingGetMethod.java
new file mode 100644
index 0000000..db949a8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/EntityEnclosingGetMethod.java
@@ -0,0 +1,25 @@
+package com.eactive.eai.adapter.http;
+
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+
+import com.eactive.eai.common.util.Logger;
+
+public class EntityEnclosingGetMethod extends EntityEnclosingMethod {
+ public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public EntityEnclosingGetMethod() {
+ setFollowRedirects(true);
+ }
+
+ public EntityEnclosingGetMethod(String uri) {
+ super(uri);
+ if (logger.isDebugEnabled()) {
+ logger.debug("enter GetMethod(String)");
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "GET";
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpAdapter.java b/src/main/java/com/eactive/eai/adapter/http/HttpAdapter.java
new file mode 100644
index 0000000..552b83b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpAdapter.java
@@ -0,0 +1,154 @@
+//package com.eactive.eai.adapter.http;
+//
+//import java.net.URLDecoder;
+//import java.net.URLEncoder;
+//import java.util.Properties;
+//import javax.naming.Context;
+//import javax.naming.InitialContext;
+//import javax.servlet.ServletException;
+//import javax.servlet.http.HttpServlet;
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//
+//import com.eactive.eai.adapter.RequestDispatcher;
+//import com.eactive.eai.common.exception.ExceptionUtil;
+//import com.eactive.eai.common.util.LogKeys;
+//import com.eactive.eai.common.util.Logger;
+//import com.eactive.eai.common.util.StringUtil;
+//
+///**
+//* 1. 기능 : HTTP 웹 요청을 수신해 EAI 프레임웍에 전달하는 HTTP 어댑터
+//* 2. 처리 개요 :
+//* * - 약속된 URL 파라미터(“_message_”)의 값을 얻어 RequestDispatcher의 handle() 메서드를 호출한다.
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see : EAIHttpAdapter.java, RequestDispatcher.java
+//* @since :
+//* :
+//*/
+//public class HttpAdapter extends HttpServlet
+//{
+// /*
+// * URL 파리미터 이름
+// */
+// static final String PARAMETER_MESSAGE = "_message_";
+// /*
+// * Http Adapter 이름
+// */
+// static final String HTTP_ADAPTER_NAME = "HTTP_ADAPTER_NAME";
+// /*
+// * Http Adapter Group 이름
+// */
+// static final String HTTP_ADAPTER_GROUP_NAME = "HTTP_ADAPTER_GROUP_NAME";
+//
+// private String adapterGroupName;
+// private String adapterName;
+// /*
+// * Adapter Logger
+// */
+// static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+//
+// /**
+// * 1. 기능 : Http Adapter의 property 속성을 설정한다.
+// * 2. 처리 개요 :
+// * -
+// * 3. 주의사항
+// *
+// **/
+// public void init() {
+// //-------------------------------------------------------
+// // Edited 2007.09.12 : DHLEE
+// //-------------------------------------------------------
+// this.adapterName = this.getInitParameter(HTTP_ADAPTER_NAME);
+// this.adapterGroupName = this.getInitParameter(HTTP_ADAPTER_GROUP_NAME);
+// //-------------------------------------------------------
+//
+// if(this.adapterName == null) this.adapterName = "IN_HTTP_STD_Sync01";
+// if(this.adapterGroupName == null) this.adapterGroupName = "HttpAdapter{STD}";
+//
+// String[] msgArgs = new String[2];
+// msgArgs[0] = this.adapterGroupName;
+// msgArgs[1] = this.adapterName;
+// String resMsg = ExceptionUtil.make("RDCEAIAHA004", msgArgs);
+// if(logger.isDebug()){
+// logger.debug("HttpAdapter] " + resMsg);
+// }
+// }
+//
+// /**
+// * 1. 기능 : 로컬 서비스 호출하는 비지니스 로직
+// * 2. 처리 개요 :
+// * - 로컬 서비스를 호출 하여 업무를 처리하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param message 요청 메시지
+// * @return prop Http Adapter 속성 정보
+// * @exception Exception 리턴 Object의 타입이 틀릴 경우
+// **/
+// protected byte[] service(byte[] message, Properties prop) throws Exception {
+// Object obj = RequestDispatcher.getRequestDispatcher(this.adapterGroupName).handle(adapterName,message,prop);
+// if(obj == null) return null;
+// if(obj instanceof byte[]) {
+// return (byte[])obj;
+// } else if(obj instanceof String) {
+// return ((String)obj).getBytes();
+// } else {
+// throw new Exception("RECEAIAHA001");
+// }
+// }
+//
+// /**
+// * 1. 기능 : Http Servlet service 구현 메소드
+// * 2. 처리 개요 :
+// * - 로컬 서비스 호출
+// * 3. 주의사항
+// *
+// * @param request Http Servlet Request
+// * @return response Http Servlet Response
+// * @exception Exception PARAMETER_MESSAGE가 null 이거나 로컬 서비스 호출 중 오류가 발생할 경우
+// **/
+// public void service(HttpServletRequest request, HttpServletResponse response) {
+// try {
+//
+// String paramValue = request.getParameter(PARAMETER_MESSAGE);
+// if(paramValue==null)
+// throw new ServletException("RECEAIAHA002");
+//
+// //byte[] message = StringUtil.hex2Bytes(hexMessage);
+// String message = URLDecoder.decode(paramValue);
+// //logger.info("HttpAdapter] "+this.adapterGroupName+" (RCEV) - "+message);
+// String[] msgArgs = new String[2];
+// msgArgs[0] = this.adapterGroupName;
+// msgArgs[1] = message;
+// String resMsg = ExceptionUtil.make("RICEAIAHA005", msgArgs);
+//
+// if(logger.isInfo()){
+// logger.info("HttpAdapter] " + resMsg);
+// }
+//
+// Properties prop = new Properties();
+// // 로컬 서비스 호출
+// byte[] result = service(message.getBytes(),prop);
+// if(message != null) {
+// //response.getWriter().print(message);
+// //hexMessage = StringUtil.bytes2Hex(message);
+// paramValue = URLEncoder.encode(new String(result));
+// response.getWriter().print(paramValue);
+// }
+//
+// } catch (Exception e) {
+// logger.error("HttpAdapter] "+adapterGroupName+"-"+adapterName+">>"+e.getMessage(),e);
+// response.setStatus(500);
+// try {
+// response.getWriter().println(e.getMessage());
+// String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
+// throw new Exception(errCode);
+// } catch (Exception ex) {
+// // IGNORE
+// }
+// }
+//
+// }
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpAdapterTestCall.java b/src/main/java/com/eactive/eai/adapter/http/HttpAdapterTestCall.java
new file mode 100644
index 0000000..040e678
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpAdapterTestCall.java
@@ -0,0 +1,82 @@
+package com.eactive.eai.adapter.http;
+
+import com.eactive.eai.adapter.*;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.testcall.TestCallException;
+import com.eactive.eai.common.testcall.TestCallManager;
+import com.eactive.eai.common.testcall.TestCallSupport;
+import com.eactive.eai.common.util.Logger;
+
+import java.util.Properties;
+
+public class HttpAdapterTestCall extends TestCallSupport
+{
+ public static final String MESSAGE = "EAI TestCall Message";
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ public boolean isAlive() throws TestCallException
+ {
+// int nConnected = 0 ;
+ try {
+ ElinkAdapterFactory factory = ElinkAdapterFactory.newInstance();
+ ElinkAdapter adapter = factory.getElinkAdapter(Keys.TYPE_HTTP);
+ AdapterVO vo = this.getAdapterInfo();
+ String pgoName = vo.getPropGroupName();
+ //PropManager manager = PropManager.getInstance();
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties prop = (Properties)(manager.getProperties(pgoName)).clone();
+
+ String testCallUrl = (String)prop.get("TEST_CALL_URL");
+
+ // MFC_FAILOVER : FAILOVER = Y 일 경우 무조건 2센터로 테스트콜을 처리한다 (2020-10-16)
+ PropManager pmanager = PropManager.getInstance();
+ String mfcFailOver = pmanager.getProperty("MFC_FAILOVER", "FAILOVER");
+
+ if(mfcFailOver != null && "Y".equals(mfcFailOver.toUpperCase())) {
+ String testCallUrl2Grp = (String)prop.get("TEST_CALL_URL_2GRP");
+ if (testCallUrl2Grp != null && testCallUrl2Grp.trim().length() > 0) {
+ testCallUrl = testCallUrl2Grp;
+ if (logger.isWarn()) logger.warn(pgoName + " - USE TEST_CALL_URL_2GRP - " + testCallUrl );
+ }
+ }
+ // MFC_FAILOVER : FAILOVER = Y 일 경우 무조건 2센터로 테스트콜을 처리한다 (2020-10-16)
+
+ if (testCallUrl != null && testCallUrl.trim().length() > 0) {
+ prop.put("URL", testCallUrl);
+ }
+
+ Properties testCallProp = PropManager.getInstance().getProperties(TestCallManager.PROP_GROUP);
+ String responseType = testCallProp.getProperty(TestCallManager.RESPONSE_TYPE, "SYNC");
+ String httpTimeout = testCallProp.getProperty(TestCallManager.HTTP_TIME_OUT, "5000");
+ String connectionTimeout = testCallProp.getProperty(TestCallManager.CONNECTION_TIMEOUT, "3000");
+
+ prop.setProperty(TestCallManager.RESPONSE_TYPE,responseType);
+ prop.setProperty(TestCallManager.HTTP_TIME_OUT, httpTimeout);
+ prop.setProperty(TestCallManager.CONNECTION_TIMEOUT, connectionTimeout);
+ Properties tempProp = new Properties();
+ tempProp.setProperty(TestCallManager.TESTCALL_YN, "Y");
+
+ if(logger.isWarn()) {
+ logger.warn("HttpAdapterTestCall] TestCall ["+vo.getAdapterGroupName()+"] URL = " + prop.getProperty("URL") );
+ logger.warn("HttpAdapterTestCall] TestCall ["+vo.getAdapterGroupName()+"] " + TestCallManager.RESPONSE_TYPE +" = " + prop.getProperty(TestCallManager.RESPONSE_TYPE) );
+ logger.warn("HttpAdapterTestCall] TestCall ["+vo.getAdapterGroupName()+"] " + TestCallManager.HTTP_TIME_OUT +" = " + prop.getProperty(TestCallManager.HTTP_TIME_OUT) );
+ logger.warn("HttpAdapterTestCall] TestCall ["+vo.getAdapterGroupName()+"] " + TestCallManager.CONNECTION_TIMEOUT +" = " + prop.getProperty(TestCallManager.CONNECTION_TIMEOUT) );
+ logger.warn("HttpAdapterTestCall] TestCall ["+vo.getAdapterGroupName()+"] " + TestCallManager.TESTCALL_YN +" = " + tempProp.getProperty(TestCallManager.TESTCALL_YN) );
+
+ }
+
+ Object result = adapter.callService(vo.getAdapterGroupName(),prop,MESSAGE.getBytes(), tempProp);
+ if(logger.isWarn()) {
+ logger.warn("HttpAdapterTestCall] TestCall["+vo.getAdapterGroupName()+"], result ="+ result );
+ }
+ return true;
+ } catch(HttpStatusException hse) {
+ logger.warn("HttpAdapterTestCall] Error - "+hse.getClass().getName()+" : "+hse.getMessage());
+ return true;
+ } catch(Exception e) {
+ //e.printStackTrace();
+ logger.warn("HttpAdapterTestCall] Error - "+e.getClass().getName()+" : "+e.getMessage());
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpClientAdapter.java b/src/main/java/com/eactive/eai/adapter/http/HttpClientAdapter.java
new file mode 100644
index 0000000..e762108
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpClientAdapter.java
@@ -0,0 +1,915 @@
+//
+//package com.eactive.eai.adapter.http;
+//
+//import java.net.ConnectException;
+//import java.net.SocketTimeoutException;
+//import java.util.Properties;
+//import org.apache.commons.httpclient.HttpClient;
+//import org.apache.commons.httpclient.HttpMethod;
+//import org.apache.commons.httpclient.HttpMethodRetryHandler;
+//import org.apache.commons.httpclient.HttpStatus;
+//import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+//import org.apache.commons.httpclient.NoHttpResponseException;
+//import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+//import org.apache.commons.httpclient.methods.GetMethod;
+//import org.apache.commons.httpclient.methods.PostMethod;
+//import org.apache.commons.httpclient.params.HttpClientParams;
+//import org.apache.commons.httpclient.params.HttpMethodParams;
+//
+//import com.eactive.eai.adapter.WLIDefaultAdapter;
+//import com.eactive.eai.common.errorcode.ErrorCodeHandler;
+//import com.eactive.eai.common.exception.ExceptionUtil;
+//import com.eactive.eai.common.property.PropManager;
+//import com.eactive.eai.common.util.Logger;
+//
+//
+///**
+//* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+//* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+//* 2. 처리 개요 :
+//* * - 2009.11.24 retry 로직 제거 : 강길수차장요청
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
+//* @since :
+//
+//*/
+//public class HttpClientAdapter extends WLIDefaultAdapter
+//{
+// public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+//
+// public static final String URL = "URL";
+// public static final String METHOD = "METHOD";
+// public static final String PARAMETER_NAME = "PARAMETER_NAME";
+//
+// // encode 추가 : 20071207
+// public static final String ENCODE = "ENCODE";
+//
+// public static final String METHOD_GET = "GET";
+// public static final String METHOD_POST = "POST";
+//
+// //-------------------------------------------------
+// // 전자무역 상태조회 :
+// // 2009.01.09
+// public static final String METHOD_SOAP = "SOAP";
+// public static final String METHOD_SOAP_ACTION = "SOAPAction";
+// //-------------------------------------------------
+//
+// public static final String HTTP_CONNECTION_STALE_CHECKING_ENABLED = "HTTP_CONNECTION_STALE_CHECKING_ENABLED";
+// /*
+// * 호스트 마다 최대 연결 수
+// */
+// public static final String HTTP_MAX_CONNECTION_PER_HOST = "HTTP_MAX_CONNECTION_PER_HOST";
+// /*
+// * 최대 HTTP 연결 수
+// */
+// public static final String HTTP_MAX_TOTAL_CONNECTIONS = "HTTP_MAX_TOTAL_CONNECTIONS";
+//
+// static final String PARAMETER_MESSAGE = "_message_";
+//
+// private HttpClient client;
+//
+// // 2008.01.21 이동훈
+// // HttpClient 2.0 Timeout Setting
+// public static final String HTTP_TIME_OUT = "HTTP_TIME_OUT";
+// public static final int DEFAULT_TIME_OUT = 30 *1000;
+// // HttpClient 2.0 Timeout Setting
+//
+// /**
+// * 1. 기능 : HttpClientAdapter default 생성자
+// * 2. 처리 개요 :
+// * - property 정보를 가져와 MultiThreadedHttpConnectionManager 속성 설정
+// * - HttpClient의 instance 생성
+// * 3. 주의사항
+// *
+// **/
+// public HttpClientAdapter() {
+// MultiThreadedHttpConnectionManager cm = new MultiThreadedHttpConnectionManager();
+// PropManager manager = PropManager.getInstance();
+// String enabled = manager.getProperty(HTTP_CONNECTION_STALE_CHECKING_ENABLED);
+//
+// if(enabled==null) {
+//
+// enabled="true";
+//
+// String code = "RWCEAIAHA006";
+// String msg = ErrorCodeHandler.getMessage(code);
+// if(logger.isWarn()){
+// logger.warn(ExceptionUtil.make(code, msg));
+// }
+// }
+//
+//
+// try {
+//
+// cm.getParams().setStaleCheckingEnabled(new Boolean(enabled).booleanValue());
+//
+// } catch(Exception e) {
+// e.printStackTrace();
+// String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA007");
+// throw new RuntimeException(errCode);
+// }
+//
+//
+// String connPerHost = manager.getProperty(HTTP_MAX_CONNECTION_PER_HOST);
+//
+// if(connPerHost==null) {
+// connPerHost = "10";
+// String code = "RWCEAIAHA008";
+// String msg = ErrorCodeHandler.getMessage(code);
+// if(logger.isWarn()){
+// logger.warn(ExceptionUtil.make(code, msg));
+// }
+// }
+//
+//
+// try {
+// //cm.setMaxConnectionsPerHost(new Integer(connPerHost).intValue());
+// cm.getParams().setDefaultMaxConnectionsPerHost(new Integer(connPerHost).intValue());
+// } catch(Exception e) {
+// String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA009");
+// throw new RuntimeException(errCode);
+// }
+//
+//
+// String totalConnections = manager.getProperty(HTTP_MAX_TOTAL_CONNECTIONS);
+// if(totalConnections==null) {
+// totalConnections = "50";
+// String code = "RWCEAIAHA010";
+// String msg = ErrorCodeHandler.getMessage(code);
+// if(logger.isWarn()){
+// logger.warn(ExceptionUtil.make(code, msg));
+// }
+// }
+//
+//
+// try {
+// //cm.setMaxTotalConnections(new Integer(totalConnections).intValue());
+// cm.getParams().setMaxTotalConnections(new Integer(totalConnections).intValue());
+// } catch(Exception e) {
+// String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA011");
+// throw new RuntimeException(errCode);
+// }
+//
+// this.client = new HttpClient(cm);
+//
+//
+// }
+//
+// /**
+// * 1. 기능 : 현재 사용중인 Connection 수
+// * 2. 처리 개요 :
+// * -
+// * 3. 주의사항
+// *
+// * @return int 사용중인 Connection 수
+// **/
+// public int getConnectionsInPool() {
+// MultiThreadedHttpConnectionManager mgr = (MultiThreadedHttpConnectionManager)this.client.getHttpConnectionManager();
+// return mgr.getConnectionsInPool();
+// }
+//
+// /**
+// * 1. 기능 : 생성된 총 Connection 수
+// * 2. 처리 개요 :
+// * -
+// * 3. 주의사항
+// *
+// * @return int 총 Connection 수
+// **/
+// public int getMaxTotalConnections() {
+// MultiThreadedHttpConnectionManager mgr = (MultiThreadedHttpConnectionManager)this.client.getHttpConnectionManager();
+// return mgr.getParams().getMaxTotalConnections();
+// }
+//
+// /**
+// * 1. 기능 : 호스트 당 할당된 총 Connection 수
+// * 2. 처리 개요 :
+// * -
+// * 3. 주의사항
+// *
+// * @return int 총 Connection 수
+// **/
+// public int getMaxConnectionsPerHost() {
+// MultiThreadedHttpConnectionManager mgr = (MultiThreadedHttpConnectionManager)this.client.getHttpConnectionManager();
+// return mgr.getParams().getDefaultMaxConnectionsPerHost();
+// }
+//
+// /**
+// * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+// * 2. 처리 개요 :
+// * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+// * 3. 주의사항
+// *
+// * @param prop Http Adapter 속성 정보
+// * @param message 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// public Object execute(Properties prop, Object message) throws Exception
+// {
+//
+// byte[] data = null;
+// if(message instanceof byte[]) {
+// data = (byte[])message;
+// } else if( message instanceof String) {
+// data = ((String)message).getBytes();
+// } else {
+// throw new Exception("RECEAIAHA011");
+// }
+// String url = prop.getProperty(URL);
+// String parameterName = prop.getProperty(PARAMETER_NAME);
+// String httpMethod = prop.getProperty(METHOD);
+// String encode = prop.getProperty(ENCODE);
+// String httpTimeOut = prop.getProperty(HTTP_TIME_OUT);
+//
+// String soapAction = prop.getProperty(METHOD_SOAP_ACTION);
+//
+// //-------------------------------------------
+// // trim 처리 : 2009.03.27
+// //-------------------------------------------
+// if(url != null) {
+// url = url.trim();
+// }
+//
+// if(parameterName != null) {
+// parameterName = parameterName.trim();
+// }
+//
+// if(httpMethod != null) {
+// httpMethod = httpMethod.trim();
+// }
+//
+// if(encode != null) {
+// encode = encode.trim();
+// }
+//
+// if(soapAction != null) {
+// soapAction = soapAction.trim();
+// }
+//
+// //----------------------------------
+// // 2008.02.15 이동훈
+// // 설정값이 없을 경우 무한대로 기다리도록
+// // 0 으로 설정하도록 함
+// //----------------------------------
+// if(httpTimeOut == null) {
+// httpTimeOut = "0";
+// }
+// else {
+// httpTimeOut = httpTimeOut.trim();
+// }
+//
+// int timeout = -1;
+// try {
+// timeout = new Integer(httpTimeOut).intValue();
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] HTTP TIMEOUT SET ["+httpTimeOut+"]");
+// }
+// } catch(Exception e) {
+// if(logger.isWarn()){
+// logger.warn("HttpClientAdapter] HTTP TIMEOUT 설정값을 확인하세요. ["+httpTimeOut+"]");
+// }
+// }
+//
+//
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] Send("+httpMethod+") Data ["+new String(data)+"]");
+// }
+//
+// if(httpMethod!=null && httpMethod.equals(METHOD_POST)) {
+// return callPostService(url, parameterName, data, encode, timeout);
+// }
+// else if(httpMethod!=null && httpMethod.equals(METHOD_SOAP)) {
+// return callSoapService(url, soapAction, data, encode, timeout);
+// }
+// else if(httpMethod!=null && httpMethod.equals("MEMO")) {
+// return callMemoService(url, data, encode, timeout);
+// }
+// else if(httpMethod!=null && httpMethod.equals("ANN")) {
+// return callAnnounceService(url, data, encode, timeout);
+// }
+// else if(httpMethod!=null && httpMethod.equals("POPUP")) {
+// return callPopupService(url, data, encode, timeout);
+// }
+// else if(httpMethod!=null && httpMethod.equals("CDSVC")) {
+// return callChangeDateService(url, data, encode, timeout);
+// }
+// else {
+// return callGetService(url, parameterName, data, encode, timeout);
+// }
+// }
+//
+// /**
+// * 1. 기능 : 수동 시스템에 Post 방식으로 서비스 호출
+// * 2. 처리 개요 :
+// * - 수동 시스템에 서비스 요청 하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param url 수동 시스템 웹 컴포넌트 URL
+// * @param parameterName URL 파리미터 이름
+// * @param data 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// private byte[] callPostService(String url, String parameterName, byte[] data, String encode, int timeout)
+// throws Exception {
+// PostMethod method = new PostMethod(url);
+//
+// //2008.02.15 : Timeout 처리로직 변경 (0 : 무한대 설정가능하게 함)
+// if(timeout > -1) {
+// method.getParams().setSoTimeout(timeout);
+// }
+//
+// //method.setRequestHeader("Content-Type","text/html; charset=euc-kr");
+//
+// String sendData = null;
+// HttpClient mclient = new HttpClient(new MultiThreadedHttpConnectionManager());
+//
+// if(encode != null && encode.length() > 0) {
+//
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] ENCODE("+encode+") ");
+// }
+//
+// try {
+// mclient.getParams().setContentCharset(encode);
+// sendData = new String(data,encode);
+// } catch(Exception e) {
+// if(logger.isError()){
+// logger.error("HttpClientAdapter] ENCODE("+encode+") ERROR : "+ e.toString());
+// logger.error("HttpClientAdapter] ENCODE("+encode+") SKIP ");
+// }
+// sendData = new String(data);
+// }
+// }
+// else {
+// //신용보증기금에 필요 분기 - 조현덕 추가(2008.11.04)
+// if(parameterName.equals("SHINBO")){
+// ;
+// }else{
+// sendData = java.net.URLEncoder.encode(new String(data));
+// }
+// }
+//
+//
+// if(parameterName==null || parameterName.equals("")) {
+// method.addParameter(PARAMETER_MESSAGE, sendData);
+//
+// //신용보증기금에 필요 분기 - 조현덕 추가(2008.05.06)
+// } else if(parameterName.equals("SHINBO")){
+// method.setRequestBody(sendData);
+// } else {
+// method.addParameter(parameterName, sendData);
+// }
+//
+//
+// int status = -1;
+//
+//
+// try {
+// status = mclient.executeMethod(method);
+// //----------------------------------------------------------
+// // 2008.01.23 : 응답이 깨지는 것 수정
+// //----------------------------------------------------------
+// //String responseMessage = method.getResponseBodyAsString();
+// String responseMessage = new String(method.getResponseBody());
+// //----------------------------------------------------------
+//
+// return responseMessage.getBytes();
+//
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// ste.printStackTrace();
+// System.out.println("HttpClientAdapter] SocketTimeoutException : " + ste.toString() );
+// throw ste;
+// } catch(ConnectException ce) {
+// ce.printStackTrace();
+// System.out.println("HttpClientAdapter] Connection Exception : " + ce.toString() );
+// throw ce;
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+// /**
+// * 1. 기능 : 수동 시스템에 Get 방식으로 서비스 호출
+// * 2. 처리 개요 :
+// * - 수동 시스템에 서비스 요청 하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param url 수동 시스템 웹 컴포넌트 URL
+// * @param parameterName URL 파리미터 이름
+// * @param data 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// private byte[] callGetService(String url, String parameterName, byte[] data, String encode, int timeout)
+// throws Exception {
+// GetMethod method = new GetMethod(url);
+//
+// //2008.02.15 : Timeout 처리로직 변경 (0 : 무한대 설정가능하게 함)
+// if(timeout > -1) {
+// method.getParams().setSoTimeout(timeout);
+// }
+//
+// String sendData = null;
+//
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] GET Method URLEncoder");
+// }
+// sendData = java.net.URLEncoder.encode(new String(data));
+//
+// /*
+// if(encode != null && encode.length() > 0) {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] ENCODE("+encode+") ");
+// }
+//
+// try {
+// sendData = new String(data, encode);
+// } catch(Exception e) {
+// if(logger.isError()){
+// logger.error("HttpClientAdapter] ENCODE("+encode+") ERROR : "+ e.toString());
+// logger.error("HttpClientAdapter] ENCODE("+encode+") SKIP ");
+// }
+// sendData = new String(data);
+// }
+// }
+// else {
+// sendData = new String(data);
+//
+// }
+// */
+//
+// method.setQueryString(parameterName+"=" + sendData);
+//
+// int status = -1;
+// try {
+// status = client.executeMethod(method);
+// //----------------------------------------------------------
+// // 2008.01.23 : 응답이 깨지는 것 수정
+// //----------------------------------------------------------
+// //String responseMessage = method.getResponseBodyAsString();
+// String responseMessage = new String(method.getResponseBody());
+// //----------------------------------------------------------
+// return responseMessage.getBytes();
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// ste.printStackTrace();
+// System.out.println("HttpClientAdapter] SocketTimeoutException : " + ste.toString() );
+// throw ste;
+// } catch(ConnectException ce) {
+// ce.printStackTrace();
+// System.out.println("HttpClientAdapter] Connection Exception : " + ce.toString() );
+// throw ce;
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status!=HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA014", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+// /**
+// * 1. 기능 : 수동 시스템에 SOAP 방식으로 서비스 호출
+// * 2. 처리 개요 :
+// * - 수동 시스템에 서비스 요청 하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param url 수동 시스템 웹 컴포넌트 URL
+// * @param soapAction soapAction 이름
+// * @param data 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// private byte[] callSoapService(String url, String soapAction, byte[] data, String encode, int timeout)
+// throws Exception {
+// PostMethod method = new PostMethod(url);
+//
+// if(timeout > -1) {
+// method.getParams().setSoTimeout(timeout);
+// }
+//
+// ByteArrayRequestEntity entity = new ByteArrayRequestEntity(data);
+//
+// method.setRequestEntity(entity);
+// method.setRequestHeader("SOAPAction", soapAction);
+//
+// int status = -1;
+//
+//
+// try {
+// status = client.executeMethod(method);
+// //----------------------------------------------------------
+// // 2008.01.23 : 응답이 깨지는 것 수정
+// //----------------------------------------------------------
+// //String responseMessage = method.getResponseBodyAsString();
+// String responseMessage = new String(method.getResponseBody());
+// //----------------------------------------------------------
+//
+// return responseMessage.getBytes();
+//
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// ste.printStackTrace();
+// System.out.println("HttpClientAdapter] SocketTimeoutException : " + ste.toString() );
+// throw ste;
+// } catch(ConnectException ce) {
+// ce.printStackTrace();
+// System.out.println("HttpClientAdapter] Connection Exception : " + ce.toString() );
+// throw ce;
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+// /**
+// * 1. 기능 : 수동 시스템에 Post 방식으로 메신저 연계서비스 호출
+// * 2. 처리 개요 :
+// * - 수동 시스템에 서비스 요청 하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param url 수동 시스템 웹 컴포넌트 URL
+// * @param data 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// private byte[] callMemoService(String url, byte[] data, String encode, int timeout)
+// throws Exception {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callMemoService called ");
+// }
+//
+// PostMethod method = new PostMethod(url);
+//
+// //2008.02.15 : Timeout 처리로직 변경 (0 : 무한대 설정가능하게 함)
+// if(timeout > -1) {
+// method.getParams().setSoTimeout(timeout);
+// }
+//
+// // 2009.08.24 강길수차장 요청
+// // MEMO Data Size : 161 Bytes -> 587 (항목 및 길이가 변경됨)
+// int memoMinSize = 587;
+//
+// if(data.length >= memoMinSize) {
+// if(encode != null && encode.length() > 0) {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callMemoService ENCODE("+encode+") ");
+// }
+// method.addParameter("SRV_CODE", new String(data, 0, 6, encode) );
+// method.addParameter("SER_TYPE", new String(data, 6, 1, encode) );
+// method.addParameter("RECIPIENT", new String(data, 7, 7, encode) );
+// method.addParameter("SEND", new String(data, 14, 7, encode) );
+// method.addParameter("TITLE", new String(data, 21, 40, encode) );
+// method.addParameter("BODY", new String(data, 61,500, encode) );
+// method.addParameter("URGENT", new String(data,561, 1, encode) );
+// method.addParameter("SAVEOPTION", new String(data,562, 1, encode) );
+// method.addParameter("RCV_IP", new String(data,563, 24, encode) );
+// }
+// else {
+// method.addParameter("SRV_CODE", new String(data, 0, 6) );
+// method.addParameter("SER_TYPE", new String(data, 6, 1) );
+// method.addParameter("RECIPIENT", new String(data, 7, 7) );
+// method.addParameter("SEND", new String(data, 14, 7) );
+// method.addParameter("TITLE", new String(data, 21, 40) );
+// method.addParameter("BODY", new String(data, 61,500) );
+// method.addParameter("URGENT", new String(data,561, 1) );
+// method.addParameter("SAVEOPTION", new String(data,562, 1) );
+// method.addParameter("RCV_IP", new String(data,563, 24) );
+// }
+// }
+// else {
+// if(logger.isError()){
+// logger.error("HttpClientAdapter] callMemoService Invalid Data Length (" + data.length + ") < "+memoMinSize);
+// }
+// throw new Exception("HttpClientAdapter.callMemoService Error : MessageSize("+(data.length)+" Bytes) too small < "+memoMinSize);
+// }
+//
+// int status = -1;
+//
+//
+// try {
+// HttpClient mclient = new HttpClient(new MultiThreadedHttpConnectionManager());
+// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+// mclient.getParams().setContentCharset("EUC_KR");
+// status = mclient.executeMethod(method);
+// String responseMessage = new String(method.getResponseBody());
+//
+// return responseMessage.getBytes();
+//
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// ste.printStackTrace();
+// System.out.println("HttpClientAdapter] SocketTimeoutException : " + ste.toString() );
+// throw ste;
+// } catch(ConnectException ce) {
+// ce.printStackTrace();
+// System.out.println("HttpClientAdapter] Connection Exception : " + ce.toString() );
+// throw ce;
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+// /**
+// * 1. 기능 : 수동 시스템에 Post 방식으로 메신저 연계서비스 호출
+// * 2. 처리 개요 :
+// * - 수동 시스템에 서비스 요청 하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param url 수동 시스템 웹 컴포넌트 URL
+// * @param data 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// private byte[] callAnnounceService(String url, byte[] data, String encode, int timeout)
+// throws Exception {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callAnnounceService called ");
+// }
+//
+// PostMethod method = new PostMethod(url);
+//
+// //2008.02.15 : Timeout 처리로직 변경 (0 : 무한대 설정가능하게 함)
+// if(timeout > -1) {
+// method.getParams().setSoTimeout(timeout);
+// }
+//
+// // Announce Data Size : 113 Bytes
+// int annMinSize = 113;
+//
+// if(data.length >= annMinSize) {
+// if(encode != null && encode.length() > 0) {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callAnnounceService ENCODE("+encode+") ");
+// }
+// method.addParameter("SRV_CODE", new String(data, 0, 6, encode) );
+// method.addParameter("RECIPIENT", new String(data, 6, 7, encode) );
+// method.addParameter("BODY", new String(data, 13,100, encode) );
+// if(data.length > 153) {
+// method.addParameter("URL", new String(data, 113, data.length-annMinSize,encode) );
+// }
+// }
+// else {
+// method.addParameter("SRV_CODE", new String(data, 0, 6) );
+// method.addParameter("RECIPIENT", new String(data, 6, 7) );
+// method.addParameter("BODY", new String(data, 13,100) );
+// if(data.length > 153) {
+// method.addParameter("URL", new String(data,113, data.length-annMinSize) );
+// }
+// }
+// }
+// else {
+// if(logger.isError()){
+// logger.error("HttpClientAdapter] callAnnounceService Invalid Data Length (" + data.length + ") < "+annMinSize);
+// }
+// throw new Exception("HttpClientAdapter.callAnnounceService Error : MessageSize("+(data.length)+" Bytes) too small < "+annMinSize);
+// }
+//
+// int status = -1;
+//
+//
+// try {
+// HttpClient mclient = new HttpClient(new MultiThreadedHttpConnectionManager());
+// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+// mclient.getParams().setContentCharset("EUC_KR");
+// status = mclient.executeMethod(method);
+// String responseMessage = new String(method.getResponseBody());
+//
+// return responseMessage.getBytes();
+//
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// ste.printStackTrace();
+// System.out.println("HttpClientAdapter] SocketTimeoutException : " + ste.toString() );
+// throw ste;
+// } catch(ConnectException ce) {
+// ce.printStackTrace();
+// System.out.println("HttpClientAdapter] Connection Exception : " + ce.toString() );
+// throw ce;
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+// /**
+// * 1. 기능 : 수동 시스템에 Post 방식으로 메신저 연계서비스 호출
+// * 2. 처리 개요 :
+// * - 수동 시스템에 서비스 요청 하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param url 수동 시스템 웹 컴포넌트 URL
+// * @param data 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// private byte[] callPopupService(String url, byte[] data, String encode, int timeout)
+// throws Exception {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callPopupService called ");
+// }
+//
+// PostMethod method = new PostMethod(url);
+//
+//
+// //2008.02.15 : Timeout 처리로직 변경 (0 : 무한대 설정가능하게 함)
+// if(timeout > -1) {
+// method.getParams().setSoTimeout(timeout);
+// }
+//
+// // Popup Data Size : 153 Bytes
+// int popupMinSize = 153;
+//
+// if(data.length >= popupMinSize) {
+// if(encode != null && encode.length() > 0) {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callPopupService ENCODE("+encode+") ");
+// }
+// method.addParameter("SRV_CODE", new String(data, 0, 6, encode) );
+// method.addParameter("RECIPIENT", new String(data, 6, 7, encode) );
+// method.addParameter("TITLE", new String(data, 13, 40, encode) );
+// method.addParameter("BODY", new String(data, 53,100, encode) );
+// }
+// else {
+// method.addParameter("SRV_CODE", new String(data, 0, 6) );
+// method.addParameter("RECIPIENT", new String(data, 6, 7) );
+// method.addParameter("TITLE", new String(data, 13, 40) );
+// method.addParameter("BODY", new String(data, 53,100) );
+// }
+// }
+// else {
+// if(logger.isError()){
+// logger.error("HttpClientAdapter] callPopupService Invalid Data Length (" + data.length + ") < "+popupMinSize);
+// }
+// throw new Exception("HttpClientAdapter.callPopupService Error : MessageSize("+(data.length)+" Bytes) too small < "+popupMinSize);
+// }
+//
+// int status = -1;
+//
+//
+// try {
+// HttpClient mclient = new HttpClient(new MultiThreadedHttpConnectionManager());
+// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+// mclient.getParams().setContentCharset("EUC_KR");
+// status = mclient.executeMethod(method);
+// String responseMessage = new String(method.getResponseBody());
+//
+// return responseMessage.getBytes();
+//
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// ste.printStackTrace();
+// System.out.println("HttpClientAdapter] SocketTimeoutException : " + ste.toString() );
+// throw ste;
+// } catch(ConnectException ce) {
+// ce.printStackTrace();
+// System.out.println("HttpClientAdapter] Connection Exception : " + ce.toString() );
+// throw ce;
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+// /**
+// * 1. 기능 : 수동 시스템에 Post 방식으로 일자전환이벤트 호출
+// * 2. 처리 개요 :
+// * - 수동 시스템에 서비스 요청 하고 결과를 리턴 한다.
+// * 3. 주의사항
+// *
+// * @param url 수동 시스템 웹 컴포넌트 URL
+// * @param data 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// private byte[] callChangeDateService(String url, byte[] data, String encode, int timeout)
+// throws Exception {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callChangeDateService called ");
+// }
+//
+// PostMethod method = new PostMethod(url);
+//
+// //2008.02.15 : Timeout 처리로직 변경 (0 : 무한대 설정가능하게 함)
+// if(timeout > -1) {
+// method.getParams().setSoTimeout(timeout);
+// }
+//
+// // Data Size : 15 Bytes
+// int popupMinSize = 15;
+//
+// if(data.length >= popupMinSize) {
+// if(encode != null && encode.length() > 0) {
+// if(logger.isDebug()){
+// logger.debug("HttpClientAdapter] callChangeDateService ENCODE("+encode+") ");
+// }
+// method.addParameter("req", new String(data, 0, 7, encode).trim() );
+// method.addParameter("date", new String(data, 7, 8, encode) );
+// }
+// else {
+// method.addParameter("req", new String(data, 0, 7).trim() );
+// method.addParameter("date", new String(data, 7, 8) );
+// }
+// }
+// else {
+// if(logger.isError()){
+// logger.error("HttpClientAdapter] callChangeDateService Invalid Data Length (" + data.length + ") < "+popupMinSize);
+// }
+// throw new Exception("HttpClientAdapter.callChangeDateService Error : MessageSize("+(data.length)+" Bytes) too small < "+popupMinSize);
+// }
+//
+// int status = -1;
+//
+//
+// try {
+// HttpClient mclient = new HttpClient(new MultiThreadedHttpConnectionManager());
+// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+// mclient.getParams().setContentCharset("EUC_KR");
+// status = mclient.executeMethod(method);
+// String responseMessage = new String(method.getResponseBody());
+//
+// return responseMessage.getBytes();
+//
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// ste.printStackTrace();
+// System.out.println("HttpClientAdapter] SocketTimeoutException : " + ste.toString() );
+// throw ste;
+// } catch(ConnectException ce) {
+// ce.printStackTrace();
+// System.out.println("HttpClientAdapter] Connection Exception : " + ce.toString() );
+// throw ce;
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpClientTest.java b/src/main/java/com/eactive/eai/adapter/http/HttpClientTest.java
new file mode 100644
index 0000000..17fca07
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpClientTest.java
@@ -0,0 +1,94 @@
+package com.eactive.eai.adapter.http;
+//import org.apache.commons.httpclient.params.HttpClientParams;
+
+
+public class HttpClientTest
+{
+// public static void main(String args[]) throws Exception {
+// MultiThreadedHttpConnectionManager cm = new MultiThreadedHttpConnectionManager();
+//
+//
+// cm.setConnectionStaleCheckingEnabled(false);
+// cm.setMaxConnectionsPerHost(10);
+// cm.setMaxTotalConnections(1);
+//
+// // 2.0
+// HttpClient client = new HttpClient(cm);
+//
+// //---------------------------------------------
+// // 3.1
+// //---------------------------------------------
+// /*
+// HttpClientParams params = new HttpClientParams();
+// params.setSoTimeout(10 * 1000);
+// HttpClient client = new HttpClient(params, cm);
+// */
+// //---------------------------------------------
+//
+// // Client Timeout 2.0
+// //client.setTimeout(1000);
+// String url = "http://172.29.65.69:7001/servlets/knova/svc/servlet/KBServlet";
+// //String url = "http://search.empas.com/error.html";
+// //String url = "http://172.17.33.237:7001/servlets/knova/svc/servlet/KBServlet";
+//
+// PostMethod method = new PostMethod(url);
+// DefaultMethodRetryHandler retryhandler = new DefaultMethodRetryHandler();
+// retryhandler.setRequestSentRetryEnabled(false);
+// retryhandler.setRetryCount(3);
+// method.setMethodRetryHandler(retryhandler);
+//
+// method.getParams().setSoTimeout(5000);
+//
+// System.out.println("HttpClientAdapter] getContentCharset("+client.getParams().getContentCharset()+") ");
+// //client.getParams().setContentCharset("KSC5601");
+// System.out.println("HttpClientAdapter] getContentCharset("+client.getParams().getContentCharset()+") ");
+//
+// String encode = "ISO8859_1";
+// byte[] data = "000924KCO.11YE#0803249920000026 0200NOV01500001 20080324175117 HOSTDOM NOVDOM BB2B YE#0803249920000026 4001 000306604151345551013205062155211 이기옥 EL08022500020000000000000000056020080324200902261 ? 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 "
+// .getBytes();
+// String sendData = null;
+// if(encode != null && encode.length() > 0) {
+// System.out.println("HttpClientAdapter] ENCODE("+encode+") ");
+//
+// try {
+// sendData = new String(data,encode);
+// } catch(Exception e) {
+// System.out.println("HttpClientAdapter] ENCODE("+encode+") ERROR : "+ e.toString());
+// System.out.println("HttpClientAdapter] ENCODE("+encode+") SKIP ");
+// sendData = new String(data);
+// }
+// }
+// else {
+// sendData = java.net.URLEncoder.encode(new String(data));
+// }
+//
+// method.addParameter("_ELD_", sendData);
+//
+// int status = -1;
+// try {
+// status = client.executeMethod(method);
+// //String responseMessage = method.getResponseBodyAsString();
+// byte[] responseBytes = method.getResponseBody();
+// System.out.println("method.getRequestCharSet() [" + method.getRequestCharSet() +"]");
+// System.out.println("method.getResponseCharSet() [" + method.getResponseCharSet() +"]");
+// System.out.println("responseMessage [" +new String(responseBytes) +"]");
+// System.out.println("ISO8859_1 [" + new String(responseBytes, "ISO8859_1") +"]");
+// System.out.println("EUC-KR [" + new String(responseBytes, "EUC-KR") +"]");
+// } catch(ConnectException ce) {
+// System.out.println("Connection Exception : " + ce.toString() );
+// } catch(HttpRecoverableException hre) { // HttpClient 2.0일 경우에 발생
+// System.out.println("HttpRecoverableException : " + hre.toString() );
+// } catch(SocketTimeoutException ste) { // HttpClient 3.1일 경우에 발생
+// System.out.println("SocketTimeoutException : " + ste.toString() );
+// } catch(Exception e) {
+// e.printStackTrace();
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// System.out.println("HttpStatus ["+status+"]");
+// }
+// }
+// }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpExtOrgClientAdapterTestCall.java b/src/main/java/com/eactive/eai/adapter/http/HttpExtOrgClientAdapterTestCall.java
new file mode 100644
index 0000000..1cb51a3
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpExtOrgClientAdapterTestCall.java
@@ -0,0 +1,79 @@
+package com.eactive.eai.adapter.http;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.common.testcall.TestCallException;
+import com.eactive.eai.common.testcall.TestCallSupport;
+import com.eactive.eai.common.util.Logger;
+
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+
+//HttpQuicsClientAdapter의 통신상태를 체크하는 클래스
+public class HttpExtOrgClientAdapterTestCall extends TestCallSupport
+{
+
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ public boolean isAlive() throws TestCallException
+ {
+ logger.debug("HttpExtOrgClientAdapterTestCall started");
+
+ try {
+ AdapterVO vo = this.getAdapterInfo();
+ String pgoName = vo.getPropGroupName();
+ //PropManager manager = PropManager.getInstance();
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties prop = manager.getProperties(pgoName);
+
+
+ String url = prop.getProperty("URL");
+ //String url = "101.88.50.120:8285";
+ logger.debug("HttpExtOrgClientAdapterTestCall URL]["+url+"s]");
+
+ URL u = null;
+ try {
+ logger.debug("HttpExtOrgClientAdapterTestCall] url - ["+url+"]");
+ u = new URL(url);
+ } catch (MalformedURLException e) {
+ logger.warn("HttpExtOrgClientAdapterTestCall] Error at new URL - "+e.getClass().getName()+" : "+e.getMessage());
+ return false;
+ }
+
+ HttpURLConnection conn = null;
+
+ try {
+ conn = (HttpURLConnection) u.openConnection();
+ } catch (Exception e) {
+ logger.warn("HttpExtOrgClientAdapterTestCall] Error at openConnection - "+e.getClass().getName()+" : "+e.getMessage());
+ return false;
+ }
+
+ if(conn == null){
+ logger.warn("HttpExtOrgClientAdapterTestCall] Error at HttpURLConnection is null ");
+ return false;
+ }
+ logger.debug("HttpExtOrgClientAdapterTestCall ] try HttpURLConnection connect");
+ conn.connect();
+ logger.debug("HttpExtOrgClientAdapterTestCall end");
+ return true;
+
+ } catch(Exception e) {
+ //e.printStackTrace();
+ logger.warn("HttpExtOrgClientAdapterTestCall] Error - "+e.getClass().getName()+" : "+e.getMessage());
+ return false;
+ }
+ }
+
+// public static void main(String args[]) throws Exception {
+// test();
+//}
+
+// private static void test() throws Exception {
+// HttpExtOrgClientAdapterTestCall test = new HttpExtOrgClientAdapterTestCall();
+// System.out.println("HttpExtOrgClientAdapterTestCall ] isAlive - ["+test.isAlive()+"]");
+// }
+}
+
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpMemoryLogger.java b/src/main/java/com/eactive/eai/adapter/http/HttpMemoryLogger.java
new file mode 100644
index 0000000..d1c580d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpMemoryLogger.java
@@ -0,0 +1,127 @@
+package com.eactive.eai.adapter.http;
+
+import com.eactive.eai.transformer.util.CircularQueue;
+import com.eactive.eai.transformer.util.ExceptionStackTrace;
+
+import java.util.LinkedHashMap;
+
+
+public class HttpMemoryLogger {
+ final static int MAX_LOG_MESSAGE_SIZE = 500000;
+
+ static LinkedHashMap txQueues = new LinkedHashMap();
+ static LinkedHashMap errorQueues = new LinkedHashMap();
+ static LinkedHashMap errorCounts = new LinkedHashMap();
+ static LinkedHashMap txCounts = new LinkedHashMap();
+
+ static private void checkTxQueue(String adapterGroupName){
+ if (txQueues.get(adapterGroupName) == null){
+ txQueues.put(adapterGroupName,new CircularQueue(20));
+ }
+ }
+ static private void checkErrorQueue(String adapterGroupName){
+ if (errorQueues.get(adapterGroupName) == null){
+ errorQueues.put(adapterGroupName,new CircularQueue(20));
+ }
+ }
+ static private void checkErrorCount(String adapterGroupName){
+ if (errorCounts.get(adapterGroupName) == null){
+ errorCounts.put(adapterGroupName,new Long(0));
+ }
+ }
+ static private void checkTxCount(String adapterGroupName){
+ if (txCounts.get(adapterGroupName) == null){
+ txCounts.put(adapterGroupName,new Long(0));
+ }
+ }
+ static public long getTransactionCount(String adapterGroupName) {
+ checkTxCount(adapterGroupName);
+ if (txCounts.get(adapterGroupName) == null)
+ return 0;
+ return txCounts.get(adapterGroupName);
+ }
+
+ static public String[] getTransactions(String adapterGroupName) {
+ checkTxQueue(adapterGroupName);
+ return txQueues.get(adapterGroupName).getRecords();
+ }
+
+
+// static public void txlog(String adapterGroupName, String message) {
+// if (message == null)
+// return;
+// if (message.length() > MAX_LOG_MESSAGE_SIZE)
+// message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+// checkTxQueue(adapterGroupName);
+// txQueues.get(adapterGroupName).addRecord(message);
+// }
+
+ static public void txlog(String adapterGroupName, String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+ synchronized(HttpMemoryLogger.class) {
+ checkTxCount(adapterGroupName);
+ checkTxQueue(adapterGroupName);
+ Long l = txCounts.get(adapterGroupName);
+ txCounts.put(adapterGroupName,++l);
+ }
+ txQueues.get(adapterGroupName).addRecord(message);
+ }
+
+
+ static public long getErrorCount(String adapterGroupName) {
+ checkErrorCount(adapterGroupName);
+ if (errorCounts.get(adapterGroupName) == null)
+ return 0;
+ return errorCounts.get(adapterGroupName);
+ }
+
+ static public String[] getErrors(String adapterGroupName) {
+ checkErrorQueue(adapterGroupName);
+ return errorQueues.get(adapterGroupName).getRecords();
+ }
+
+ static public void error(String adapterGroupName, String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+
+ synchronized(HttpMemoryLogger.class) {
+ checkErrorCount(adapterGroupName);
+ checkErrorQueue(adapterGroupName);
+ Long l = errorCounts.get(adapterGroupName);
+ errorCounts.put(adapterGroupName,++l);
+ }
+ errorQueues.get(adapterGroupName).addRecord(message);
+ //txQueues.get(adapterGroupName).addRecord("" + message + " ");
+ }
+
+ static public void error(String adapterGroupName,String message, Throwable t) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+
+ synchronized(HttpMemoryLogger.class) {
+ checkErrorCount(adapterGroupName);
+ checkErrorQueue(adapterGroupName);
+ Long l = errorCounts.get(adapterGroupName);
+ errorCounts.put(adapterGroupName,++l);
+ }
+ errorQueues.get(adapterGroupName).addRecord(message + " | " + ExceptionStackTrace.dump(t));
+ //txQueues.get(adapterGroupName).addRecord("" + message + "\n" + ExceptionStackTrace.dump(t) + " ");
+ }
+ static public boolean isMemoryLogEnabled(String adapterGroupName) {
+ return true;
+// PropGroupVO propGroupVO = PropManager.getInstance().getPropGroupVO("Transformer");
+// if (propGroupVO == null)
+// return false;
+// String value = propGroupVO.getProperty("memory.log");
+// if ("1".equals(value))
+// return true;
+// return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpMethodType.java b/src/main/java/com/eactive/eai/adapter/http/HttpMethodType.java
new file mode 100644
index 0000000..5631af6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpMethodType.java
@@ -0,0 +1,26 @@
+package com.eactive.eai.adapter.http;
+
+public enum HttpMethodType {
+ POST,
+ PUT,
+ DELETE,
+ GET,
+ UNKNOWN;
+ public static HttpMethodType getValue(String value) {
+ try {
+ return valueOf(value.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+
+// public static void main(String[] args) throws Exception {
+//
+// if ("DELETE".equals(HttpMethodType.DELETE.toString())){
+// System.out.println("delete");
+// }else{
+//
+// System.out.println("not delete");
+// }
+// }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/HttpStatusException.java b/src/main/java/com/eactive/eai/adapter/http/HttpStatusException.java
new file mode 100644
index 0000000..b8a82cf
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/HttpStatusException.java
@@ -0,0 +1,63 @@
+package com.eactive.eai.adapter.http;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class HttpStatusException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private int status = 200;
+ private String code;
+
+ /**
+ * 1. 기능 : Default Constructor
+ * 2. 처리 개요 : Default Constructor
+ * 3. 주의사항
+ *
+ **/
+ public HttpStatusException() {
+ super("HttpStatusException is occured.");
+ }
+
+ /**
+ * 1. 기능 : Exception message를 초기화하는 Constructor
+ * 2. 처리 개요 : Exception message를 초기화하는 Constructor
+ * -
+ * 3. 주의사항
+ *
+ * @param msg Exception message
+ **/
+ public HttpStatusException(String msg) {
+ super(msg);
+ }
+ public HttpStatusException(String msg, int status) {
+ super(msg);
+ this.status = status;
+ }
+ public HttpStatusException(String msg, String code, int status) {
+ super(msg);
+ this.setCode(code);
+ this.status = status;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public void setStatus(int status) {
+ this.status = status;
+ }
+
+ public String getCode() {
+ if (StringUtils.isBlank(code)) {
+ return String.format("Http Status: %d", status);
+ } else {
+ return code;
+ }
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/async/AppAsyncListener.java b/src/main/java/com/eactive/eai/adapter/http/async/AppAsyncListener.java
new file mode 100644
index 0000000..3d1a9b5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/async/AppAsyncListener.java
@@ -0,0 +1,39 @@
+package com.eactive.eai.adapter.http.async;
+
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+//@WebListener
+public class AppAsyncListener implements AsyncListener {
+
+ @Override
+ public void onComplete(AsyncEvent asyncEvent) throws IOException {
+// System.out.println("AppAsyncListener onComplete");
+ // we can do resource cleanup activity here
+ }
+
+ @Override
+ public void onError(AsyncEvent asyncEvent) throws IOException {
+// System.out.println("AppAsyncListener onError");
+ //we can return error response to client
+ }
+
+ @Override
+ public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
+// System.out.println("AppAsyncListener onStartAsync");
+ //we can log the event here
+ }
+
+ @Override
+ public void onTimeout(AsyncEvent asyncEvent) throws IOException {
+// System.out.println("AppAsyncListener onTimeout");
+ //we can send appropriate response to client
+ ServletResponse response = asyncEvent.getAsyncContext().getResponse();
+ PrintWriter out = response.getWriter();
+ out.write("TimeOut Error in Processing");
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/async/AppContextListener.java b/src/main/java/com/eactive/eai/adapter/http/async/AppContextListener.java
new file mode 100644
index 0000000..ef9fae5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/async/AppContextListener.java
@@ -0,0 +1,28 @@
+package com.eactive.eai.adapter.http.async;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+//@WebListener
+public class AppContextListener implements ServletContextListener {
+
+ public void contextInitialized(ServletContextEvent servletContextEvent) {
+ // Default Timeout Setting 60sec
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 200, 60000L,
+ TimeUnit.MILLISECONDS, new ArrayBlockingQueue(100));
+ servletContextEvent.getServletContext().setAttribute("executor",
+ executor);
+// System.out.println("AppContextListener contextInitialized::set ThreadPoolExecutor");
+ }
+
+ public void contextDestroyed(ServletContextEvent servletContextEvent) {
+ ThreadPoolExecutor executor = (ThreadPoolExecutor) servletContextEvent
+ .getServletContext().getAttribute("executor");
+ executor.shutdown();
+// System.out.println("AppContextListener contextDestroyed::shutdown ThreadPoolExecutor");
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/async/AsyncRequestProcessor.java b/src/main/java/com/eactive/eai/adapter/http/async/AsyncRequestProcessor.java
new file mode 100644
index 0000000..289690a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/async/AsyncRequestProcessor.java
@@ -0,0 +1,92 @@
+package com.eactive.eai.adapter.http.async;
+
+import com.eactive.eai.adapter.RequestDispatcher;
+import com.eactive.eai.common.util.Logger;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.util.Properties;
+
+public class AsyncRequestProcessor implements Runnable {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+ private AsyncContext asyncContext;
+
+ private String adapterGroupName;
+ private String adapterName;
+ private String encode = "euc-kr";
+
+ public AsyncRequestProcessor() {
+ }
+
+ public AsyncRequestProcessor(AsyncContext asyncCtx) {
+ this.asyncContext = asyncCtx;
+
+ // TODO : define adapter name rule
+ this.adapterGroupName = "_EAI_IN_HTT_SyS";
+ this.adapterName = "_EAI_IN_HTT_SyS{ALL}";
+ }
+
+ @Override
+ public void run() {
+// System.out.println("Async Supported? "
+// + asyncContext.getRequest().isAsyncSupported());
+
+ ServletRequest request = asyncContext.getRequest();
+
+ ServletInputStream sis;
+ byte[] requestBytes = null;
+ byte[] result = null;
+ try {
+ sis = request.getInputStream();
+
+ ByteBuffer bb = ByteBuffer.allocate(1024);
+ int i=0;
+ byte[] cbuf = new byte[1024];
+ while( ( i = sis.read(cbuf, 0, 1024) ) != -1 ) {
+ if (i==1024){
+ bb.put(cbuf);
+ }else{
+ byte[] tail = new byte[i];
+ System.arraycopy(cbuf, 0, tail, 0, i);
+ bb.put(tail);
+ }
+ }
+ requestBytes = new byte[bb.position()];
+ bb.position(0);
+ bb.get(requestBytes);
+
+ Properties prop = new Properties();
+ // call Inbound Proxy
+ result = service(requestBytes, prop);
+ PrintWriter out = asyncContext.getResponse().getWriter();
+ String encodedResponse = new String(result, encode);
+ out.write(encodedResponse);
+ } catch (IOException e1) {
+ logger.error("AsyncRequestProcessor IOException", e1);
+ } catch (Exception e) {
+ logger.error("AsyncRequestProcessor Exception", e);
+ }
+ finally {
+ if(asyncContext != null) {
+ asyncContext.complete();
+ }
+ }
+ }
+
+ protected byte[] service(byte[] message, Properties prop) throws Exception {
+ Object obj = RequestDispatcher.getRequestDispatcher(this.adapterGroupName).handle(adapterName, message, prop);
+ if(obj == null) return null;
+ if(obj instanceof byte[]) {
+ return (byte[])obj;
+ } else if(obj instanceof String) {
+ return ((String)obj).getBytes();
+ } else {
+ throw new Exception("RECEAIAHA001");
+ }
+ }
+}
+
diff --git a/src/main/java/com/eactive/eai/adapter/http/async/AsyncServlet.java b/src/main/java/com/eactive/eai/adapter/http/async/AsyncServlet.java
new file mode 100644
index 0000000..d9bbd3d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/async/AsyncServlet.java
@@ -0,0 +1,54 @@
+package com.eactive.eai.adapter.http.async;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.concurrent.ThreadPoolExecutor;
+
+//@WebServlet(urlPatterns = "/AsyncServlet", asyncSupported = true)
+public class AsyncServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void doPost(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ handle(request, response);
+ }
+ @Override
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ handle(request, response);
+ }
+
+ private void handle(HttpServletRequest request,
+ HttpServletResponse response) {
+// long startTime = System.currentTimeMillis();
+// System.out.println("AsyncServlet Start::Name="
+// + Thread.currentThread().getName() + "::ID="
+// + Thread.currentThread().getId());
+
+ request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
+
+ AsyncContext asyncCtx = request.startAsync();
+ AppAsyncListener asyncListener = new AppAsyncListener();
+ asyncCtx.addListener(asyncListener);
+ asyncCtx.setTimeout(30000); // Async Timeout 30 secs
+
+// ThreadPoolExecutor executor = (ThreadPoolExecutor) request
+// .getServletContext().getAttribute("executor");
+// executor.execute(new AsyncRequestProcessor(asyncCtx));
+
+ asyncCtx.start(new AsyncRequestProcessor(asyncCtx));
+
+// long endTime = System.currentTimeMillis();
+// System.out.println("AsyncServlet End::Name="
+// + Thread.currentThread().getName() + "::ID="
+// + Thread.currentThread().getId() + "::Time Taken="
+// + (endTime - startTime) + " ms.");
+
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClient5AdapterServiceSupport.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClient5AdapterServiceSupport.java
new file mode 100644
index 0000000..80655b5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClient5AdapterServiceSupport.java
@@ -0,0 +1,538 @@
+
+package com.eactive.eai.adapter.http.client;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
+import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
+import org.apache.hc.client5.http.ssl.TrustAllStrategy;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpRequestInterceptor;
+import org.apache.hc.core5.http.HttpResponseInterceptor;
+import org.apache.hc.core5.ssl.SSLContextBuilder;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.secure.HttpClient5SSLContextFactory;
+import com.eactive.eai.common.TransactionContextKeys;
+import com.eactive.eai.common.util.HttpAdapterExtraLogUtil;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
+import com.eactive.eai.util.TestModeChecker;
+
+public abstract class HttpClient5AdapterServiceSupport implements HttpClientAdapterService, HttpClientAdapterServiceKey {
+ protected static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ protected HttpClient client;
+ PoolingHttpClientConnectionManager connectionManager;
+
+ private static boolean testMode = TestModeChecker.isTestMode();
+
+ public synchronized void close() {
+ if(connectionManager != null) {
+ connectionManager.close();
+ }
+ }
+
+ protected HttpClientAdapterVO setting(Properties prop, Properties tempProp) {
+ String url = null;
+ String parameterName = null;
+ String method = null;
+ String contentType = null;
+ String encode = null;
+ String testCallYn = null;
+ String adapterGroupName = null;
+ String adapterName = null;
+ String responseType = null;
+ String urlEncodeYn = null;
+ String adapterHeader = null;
+
+ boolean useMtls = false;
+ String keyStorePath = null;
+ String keyStorePassword = null;
+ String trustStorePath = null;
+ String trustStorePassword = null;
+
+ int connectionTimeout = 0;
+ int timeout = -1;
+ int traceLevel = 0;
+ long slowTranTime = 2000L;
+
+ url = prop.getProperty(URL);
+
+ String url2grp = tempProp.getProperty(URL);
+ if (!StringUtils.isEmpty(url2grp)) {
+ url = url2grp;
+ }
+ method = prop.getProperty(METHOD);
+ parameterName = prop.getProperty(PARAMETER_NAME, PARAMETER_MESSAGE);
+ contentType = prop.getProperty(CONTENT_TYPE, "");
+ responseType = prop.getProperty(RESPONSE_TYPE, "SYNC");
+ urlEncodeYn = prop.getProperty(URL_ENCODE_YN, "N");
+ String connectionTimeoutTemp = prop.getProperty(CONNECTION_TIMEOUT, "0");
+
+ String httpVersion = prop.getProperty(HTTP_VERSION);
+ adapterHeader = prop.getProperty(ADAPTER_HEADER, "");
+
+ String traceLevelTemp = prop.getProperty(TRACE_LEVEL, "0");
+ String timeoutTemp = prop.getProperty(HTTP_TIME_OUT, "0");
+
+ useMtls = StringUtils.equalsIgnoreCase(prop.getProperty(HttpClientAdapterServiceKey.USE_MTLS),"Y");
+ keyStorePath = prop.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PATH);
+ keyStorePassword = prop.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PWD);
+ trustStorePath = prop.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PATH);
+ trustStorePassword = prop.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PWD);
+
+ encode = tempProp.getProperty(Keys.CHARSET_KEY_OUT, Charset.defaultCharset().name());
+ testCallYn = tempProp.getProperty(TESTCALL_YN, "N");
+ adapterGroupName = tempProp.getProperty(ADAPTER_GROUP_NAME);
+ adapterName = tempProp.getProperty(ADAPTER_NAME);
+ // 인터페이스 정보에 설정된 타임아웃
+ String interfaceTimeout = tempProp.getProperty("INTERFACE_TIME_OUT");
+ if (StringUtils.isNotBlank(interfaceTimeout) && NumberUtils.toInt(interfaceTimeout) > 0) {
+ timeoutTemp = interfaceTimeout;
+ }
+
+ url = StringUtils.trim(url);
+ parameterName = StringUtils.trim(parameterName);
+ method = StringUtils.trim(method);
+ encode = StringUtils.trim(encode);
+ contentType = StringUtils.trim(contentType);
+
+ try {
+ connectionTimeout = Integer.parseInt(connectionTimeoutTemp);
+ } catch (Exception e) {
+ logger.debug("HttpClientAdapterSupport] connectionTimeoutTemp not int");
+ }
+
+ try {
+ timeout = Integer.parseInt(timeoutTemp);
+ } catch (NumberFormatException e) {
+ logger.warn("HttpClientAdapterSupport] timeoutTemp not int", e);
+ }
+
+ try {
+ traceLevel = Integer.parseInt(traceLevelTemp);
+ } catch (Exception e) {
+ logger.warn("HttpClientAdapterSupport] traceLevelTemp not int", e);
+ }
+
+ // client 중 BODY,POST,GET,NexCore 방식만 적용
+ HashMap adapterHeaders = new HashMap<>();
+ try {
+ Matcher matcher = Pattern
+ .compile("\\{[ ]*\"[ ]*([a-zA-Z0-9_-]+)[ ]*\"[ ]*,[ ]*\"[ ]*([a-zA-Z0-9/;,\\*=_ -]+)[ ]*\"[ ]*\\}[ ]*")
+ .matcher(adapterHeader.trim());
+ while (matcher.find()) {
+ String key = matcher.group(1).trim();
+ String value = matcher.group(2).trim();
+ adapterHeaders.put(key, value);
+ }
+ } catch (Exception e) {
+ if(logger.isDebug()) logger.debug("HttpClientAdapterSupport] adapter header parsing error " + adapterHeader);
+ }
+ // GW 전달 로직 추가
+ // tempProp로 넘겨서 하는 이유는 outboundProp가 clone 안하는 로직이라 outboundProp로 넘길시 문제의 소지가있음
+ String transactionId = tempProp.getProperty(HttpClientAdapterServiceKey.TRANSACTION_ID);
+ String instanceId = tempProp.getProperty(HttpClientAdapterServiceKey.INSTANCE_ID);
+ if (StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(instanceId)) {
+ adapterHeaders.put(HttpClientAdapterServiceKey.TRANSACTION_ID, transactionId);
+ adapterHeaders.put(HttpClientAdapterServiceKey.INSTANCE_ID, instanceId);
+ }
+
+ HttpClientAdapterVO vo = new HttpClientAdapterVO();
+ vo.setUrl(url);
+ vo.setMethod(method);
+ vo.setParameterName(parameterName);
+ vo.setEncode(encode);
+ vo.setContentType(contentType);
+ vo.setTestCallYn(testCallYn);
+ vo.setResponseType(responseType);
+ vo.setUrlEncodeYn(urlEncodeYn);
+ vo.setAdapterGroupName(adapterGroupName);
+ vo.setAdapterName(adapterName);
+
+ vo.setMaxTotalConnections(getMaxTotalConnections());
+ vo.setMaxHostConnections(getMaxConnectionsPerHost());
+ vo.setConnectionTimeout(connectionTimeout);
+
+ vo.setTimeout(timeout);
+ vo.setTraceLevel(traceLevel);
+ vo.setSlowTranTime(slowTranTime);
+ vo.setAdapterHeaders(adapterHeaders);
+ if (StringUtils.equalsAny(httpVersion, HTTP_VERSION_FULL_1_1, HTTP_VERSION_1_1)) {
+ vo.setHttpVersion(HTTP_VERSION_1_1);
+ }
+ else if (StringUtils.equals(httpVersion, HTTP_VERSION_2_0)) {
+ vo.setHttpVersion(HTTP_VERSION_2_0);
+ }
+ else {
+ vo.setHttpVersion(HTTP_VERSION_1_0);
+ }
+ vo.setUseMtls(useMtls);
+ vo.setKeyStorePath(keyStorePath);
+ vo.setKeyStorePassword(keyStorePassword);
+ vo.setTrustStorePath(trustStorePath);
+ vo.setTrustStorePassword(trustStorePassword);
+ if (logger.isDebug()) {
+ logger.debug(vo.toString());
+ }
+ return vo;
+ }
+
+ protected HttpClient5AdapterServiceSupport() {
+ }
+
+ public synchronized void init(String adapterName,
+ boolean useMtls, HttpOutTlsInfoVO mtlsInfo,
+ int maxTotalConnections, int maxHostConnections) {
+
+ if(connectionManager != null) {
+ if( (connectionManager.getMaxTotal() == maxTotalConnections)
+ && (connectionManager.getDefaultMaxPerRoute() == maxHostConnections) ) {
+ if(logger.isInfo()) {
+ logger.info("ConnectionManager REUSE : AdapterName=" + adapterName
+ + " MaxTotalConnection (" + connectionManager.getMaxTotal()
+ + ") MaxHostConnections (" + connectionManager.getDefaultMaxPerRoute()
+ + ")"
+ );
+ }
+ return;
+ }
+ else {
+ if(logger.isWarn()) {
+ logger.warn("ConnectionManager RELOAD : AdapterName=" + adapterName
+ + " MaxTotalConnection (" + connectionManager.getMaxTotal() + " -> " + maxTotalConnections
+ + ") MaxHostConnections (" + connectionManager.getDefaultMaxPerRoute() + " -> " + maxHostConnections
+ + ")"
+ );
+ }
+ connectionManager.close();
+ connectionManager = null;
+ this.client = null;
+ }
+ }
+ if(logger.isWarn()) {
+ logger.warn("ConnectionManager INIT : AdapterName=" + adapterName
+ + " MaxTotalConnection (" + maxTotalConnections
+ + ") MaxHostConnections (" + maxHostConnections
+ + ")"
+ );
+ }
+
+ PoolingHttpClientConnectionManagerBuilder cmBuilder = PoolingHttpClientConnectionManagerBuilder.create();
+
+
+
+ try {
+ if(logger.isWarn()) {
+ logger.warn("mTLS Config : AdapterName=" + adapterName
+ + " useMtls (" + useMtls + ") mtlsInfo - " + mtlsInfo);
+ }
+
+ SSLContext sslContext = null;
+ if (useMtls && mtlsInfo != null) {
+ String storeType = mtlsInfo.getStoreType();
+ String keyStoreInfo = mtlsInfo.getKeystoreInfo();
+ String keyStorePassword = mtlsInfo.getKeystorePassword();
+ String trustStoreInfo = mtlsInfo.getTruststoreInfo();
+ String trustStorePassword = mtlsInfo.getTruststorePassword();
+
+ String[] tlsVersions = null;
+// {
+// "TLSv1.0"
+// , "TLSv1.1"
+// , "TLSv1.2"
+// , "TLSv1.3"
+// };
+ String[] cipherSuites = null;
+// {
+// "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+// "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+// "TLS_RSA_WITH_AES_256_CBC_SHA256",
+// "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
+// "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
+// "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+// "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+// "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+// "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+// "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+// "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+// "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+// "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+// "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+// "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+// "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+// "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
+// };
+
+ if( StringUtils.isAnyEmpty(keyStoreInfo, keyStorePassword) ) {
+ throw new Exception("mTLS keyStore config error");
+ }
+
+ boolean skipTrust = false;
+ // kbank에서는 trustStore를 사용하지 않음
+ if( StringUtils.isAnyEmpty(trustStoreInfo, trustStorePassword) ) {
+// throw new Exception("mTLS trustStore config error");
+ if(logger.isWarn()) logger.warn("Skip trustStore validation adapterName : " + adapterName);
+ skipTrust = true;
+ }
+
+ sslContext = HttpClient5SSLContextFactory.createMTLSContextFromContent(
+ storeType,
+ keyStoreInfo, keyStorePassword,
+ trustStoreInfo, trustStorePassword, skipTrust
+ ,tlsVersions, cipherSuites);
+
+ // SSLConnectionSocketFactory 생성
+// Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: Certificate for doesn't match common name of the certificate subject: elink
+// at org.apache.hc.client5.http.ssl.DefaultHostnameVerifier.matchCN(DefaultHostnameVerifier.java:180)
+// at org.apache.hc.client5.http.ssl.DefaultHostnameVerifier.verify(DefaultHostnameVerifier.java:118)
+// at org.apache.hc.client5.http.ssl.TlsSessionValidator.verifySession(TlsSessionValidator.java:112)
+// => NoopHostnameVerifier.INSTANCE
+
+ SSLConnectionSocketFactory sslSocketFactory = null;
+ if(testMode) {
+ // Hostname verifier 비활성화 (테스트용)
+ sslSocketFactory = new SSLConnectionSocketFactory(
+ sslContext
+ , NoopHostnameVerifier.INSTANCE
+ );
+ }
+ else {
+ sslSocketFactory = new SSLConnectionSocketFactory(
+ sslContext
+ );
+ }
+ cmBuilder.setSSLSocketFactory(sslSocketFactory);
+ }
+ else {
+ sslContext = SSLContextBuilder.create().loadTrustMaterial(new TrustAllStrategy()).build();
+ SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
+ cmBuilder.setSSLSocketFactory(csf);
+ }
+
+ } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException
+ | CertificateException | IOException | UnrecoverableKeyException e) {
+ throw new RuntimeException(e);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ this.connectionManager = cmBuilder.build();
+
+ connectionManager.setMaxTotal(maxTotalConnections);
+ connectionManager.setDefaultMaxPerRoute(maxHostConnections);
+
+
+ HttpRequestInterceptor requestLogInterceptor = (request, entity, context) -> {
+ try {
+ String uuid = (String) context.getAttribute(TransactionContextKeys.TRANSACTION_UUID);
+ String contextAdapterGroupName = (String) context.getAttribute(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME);
+ String contextAdapterName = (String) context.getAttribute(HttpClientAdapterServiceKey.ADAPTER_NAME);
+ String url = request.getUri().toString();
+
+ Integer logProcessNo = (Integer) context.getAttribute(HttpClientAdapterServiceKey.LOG_PROCESS_NO);
+ if (logProcessNo == null || logProcessNo <= 0) {
+ logProcessNo = 200;
+ }
+
+ HttpAdapterExtraLogUtil.insertHttpAdapterExtraLog(uuid, logProcessNo,
+ contextAdapterGroupName, contextAdapterName, request.getHeaders(), url, request.getMethod());
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ };
+
+ HttpResponseInterceptor responseLogInterceptor = (response, entity, context) -> {
+ try{
+ HttpRequest request = (HttpRequest)context.getAttribute("http.request");
+ String url = request.getUri().toString();
+ String uuid = (String) context.getAttribute(TransactionContextKeys.TRANSACTION_UUID);
+ String contextAdapterGroupName = (String) context.getAttribute(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME);
+ String contextAdapterName = (String) context.getAttribute(HttpClientAdapterServiceKey.ADAPTER_NAME);
+ Integer logProcessNo = (Integer) context.getAttribute(HttpClientAdapterServiceKey.LOG_PROCESS_NO);
+ if (logProcessNo == null || logProcessNo <= 0) {
+ logProcessNo = 300;
+ }else if(logProcessNo == 400){
+ return;
+ }else{
+ logProcessNo += 100;
+ }
+
+ HttpAdapterExtraLogUtil.insertHttpAdapterExtraLog(uuid, logProcessNo,
+ contextAdapterGroupName, contextAdapterName, response.getHeaders(), url, request.getMethod(), response.getCode());
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ };
+
+ this.client = HttpClients.custom()
+ .addRequestInterceptorLast(requestLogInterceptor)
+ .addResponseInterceptorFirst(responseLogInterceptor)
+ .setConnectionManager(connectionManager)
+ .build();
+ }
+
+ public int getConnectionsInPool() {
+ if (this.client == null || this.connectionManager == null)
+ return 0;
+ return this.connectionManager.getTotalStats().getAvailable() + this.connectionManager.getTotalStats().getLeased();
+ }
+
+ public int getMaxTotalConnections() {
+ if (this.client == null || this.connectionManager == null)
+ return 0;
+ return this.connectionManager.getMaxTotal();
+ }
+
+ public int getMaxConnectionsPerHost() {
+ if (this.client == null || this.connectionManager == null)
+ return 0;
+ return this.connectionManager.getDefaultMaxPerRoute();
+ }
+
+ public String getResponseCharSet(String httpResponseCharset, String adapterGroupName) {
+ if (StringUtils.isNotBlank(httpResponseCharset)) {
+ return httpResponseCharset;
+ } else {
+ AdapterManager m = AdapterManager.getInstance();
+ AdapterGroupVO agvo = m.getAdapterGroupVO(adapterGroupName);
+ return agvo.getMessageEncode();
+ }
+ }
+
+ /**
+ * encoding에 대한 정의 필요 고려할 문제
+ * 1. 어댑터그룹이 UJN 타입일경우 return 은 UTF-8 로 getBytes 된
+ * 데이터여야됨.
+ * 2. http response에 받은 encoding 타입은 고려대상임. 결론 : response Encoding 과
+ * 어댑터의 MESSAGE_TYPE 다르면 변환, 나머지면 return 어댑터의 ENCODE은 요청전문 encoding에서만 사용
+ *
+ * 예) 어댑터의 ENCODE, 어댑터의 MESSAGE TYPE, RESPNSE ENCODING TYPE, 처리내용
+ * 예) ,ECU-KR ,JSN , EUC-KR , 응답받은 메시지를 return 예) ,ECU-KR , JSN , UTF-8 , 응답받은 메시지를 new
+ * String(xxx,"UTF-8") => getBytes("EUC-KR") 예) ,ECU-KR , UJN , EUC-KR , 응답받은
+ * 메시지를 new String(xxx,"EUC-KR") => getBytes("UTF-8") 예) ,ECU-KR , UJN , UTF-8 ,
+ * 응답받은 메시지를 return 예) ,UTF-8 , JSN , EUC-KR , 응답받은 메시지를 return
+ * 예) ,UTF-8 , JSN , UTF-8 , 응답받은 메시지를 new String(xxx,"UTF-8") => getBytes(EUC-KR") 예) ,UTF-8 ,
+ * UJN , EUC-KR , 응답받은 메시지를 new String(xxx,"EUC-KR") => getBytes("UTF-8") 예)
+ * ,UTF-8 , UJN , UTF-8 , 응답받은 메시지를 return
+ *
+ *
+ */
+ public byte[] getEncodingConvert(String httpResponseCharset, String adapterGroupName, byte[] message) {
+ byte[] responseMessage = null;
+ if (StringUtils.isNotBlank(httpResponseCharset)) {
+ AdapterManager m = AdapterManager.getInstance();
+ AdapterGroupVO agvo = m.getAdapterGroupVO(adapterGroupName);
+ String adapterTypeEncoding = StringUtils.defaultIfBlank(agvo.getMessageEncode(),
+ Charset.defaultCharset().name());
+ Charset responseCharset = null;
+ Charset adapterCharset = null;
+ try {
+ responseCharset = Charset.forName(httpResponseCharset);
+ adapterCharset = Charset.forName(adapterTypeEncoding);
+ if (responseCharset.compareTo(adapterCharset) == 0) {
+ responseMessage = message;
+ } else {// http 응답 charset 과 어댑터의 charset 이 다를경우 charset 변환 필요
+ String encodingString = new String(message, httpResponseCharset);
+ responseMessage = encodingString.getBytes(adapterTypeEncoding);
+ }
+ } catch (UnsupportedCharsetException | UnsupportedEncodingException e) {
+ responseMessage = message;
+ }
+ } else {
+ responseMessage = message;
+ }
+ return responseMessage;
+ }
+
+ public void configureHttpClient(RequestConfig.Builder requestConfigBuilder, HttpClientAdapterVO vo, HttpUriRequestBase method) {
+
+ if (vo.getConnectionTimeout() != 0) {
+ requestConfigBuilder.setConnectTimeout(vo.getConnectionTimeout(), TimeUnit.MILLISECONDS);
+ }
+
+ if (vo.getTimeout() > -1) {
+ requestConfigBuilder.setResponseTimeout(vo.getTimeout(), TimeUnit.MILLISECONDS);
+ }
+
+ /*
+ if (HTTP_VERSION_1_1.equals(vo.getHttpVersion())) {
+ method.addHeader("Connection", "close");
+ }
+ */
+
+ org.apache.hc.core5.http.HttpVersion httpVersion ;
+ if (HTTP_VERSION_1_0.equals(vo.getHttpVersion())) {
+ httpVersion = org.apache.hc.core5.http.HttpVersion.HTTP_1_0;
+ }
+ else if (HTTP_VERSION_2_0.equals(vo.getHttpVersion())) {
+ httpVersion = org.apache.hc.core5.http.HttpVersion.HTTP_2_0;
+ }
+ else {
+ httpVersion = org.apache.hc.core5.http.HttpVersion.HTTP_1_1;
+ method.addHeader("Connection", "close");
+ }
+ method.setVersion(httpVersion);
+
+ RequestConfig requestConfig = requestConfigBuilder
+ .setConnectTimeout(vo.getConnectionTimeout(), TimeUnit.MILLISECONDS) // 연결 시간 초과를 5초로 설정
+ .setResponseTimeout(vo.getTimeout(), TimeUnit.MILLISECONDS) // 응답 시간 초과를 5초로 설정
+ .build();
+
+ method.setConfig(requestConfig);
+ }
+
+ public abstract Object execute(Properties prop, Object message, Properties tempProp) throws Exception;
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterListener.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterListener.java
new file mode 100644
index 0000000..99593b0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterListener.java
@@ -0,0 +1,55 @@
+package com.eactive.eai.adapter.http.client;
+
+import java.util.Properties;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.http.dynamic.HttpLoggerManager;
+import com.eactive.eai.adapter.listener.AdapterException;
+import com.eactive.eai.adapter.listener.AdapterListenerSupport;
+import com.eactive.eai.common.util.Logger;
+
+public class HttpClientAdapterListener extends AdapterListenerSupport {
+ final static Logger logger2 = HttpLoggerManager.getInstance().getLogger();
+ final static Logger errLogger = HttpLoggerManager.getInstance().getErrLogger();
+
+ public void start() throws AdapterException {
+
+ try {
+ if (info == null) {
+ throw new Exception("HttpClientAdapterListener | AdapterVO가 NULL입니다.");
+ }
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties outboundProp = manager.getProperties(info.getPropGroupName());
+ String adapterGroupName = info.getAdapterGroupName();
+ String adapterName = info.getName();
+ String httpType = outboundProp.getProperty(HttpClientAdapterServiceKey.HTTP_TYPE);
+ HttpClientAdapterServiceFactory.createFactory(httpType, adapterGroupName, adapterName);
+ if(logger2.isInfo()) {
+ logger2.info("[HttpClientAdapterListener] AdapterName [" + info.getAdapterGroupName() + "." + info.getName()
+ + "] httpType [" + httpType + "] start");
+ }
+ info.setStatus(true);
+ } catch (Exception e) {
+ logger.error(info.getName() + " | HttpClientAdapterListener | cannot start : " + e.getMessage(), e);
+ throw new AdapterException(info.getName() + " | HttpClientAdapterListener | cannot start - " + e.getMessage());
+ }
+ }
+
+ public void stop() throws AdapterException {
+ try {
+ if (info == null) {
+ throw new Exception("HttpClientAdapterListener | AdapterVO가 NULL입니다.");
+ }
+ String adapterName = info.getName();
+ HttpClientAdapterServiceFactory.removeFactory(adapterName);
+ if(logger2.isInfo()) {
+ logger2.info("[HttpClientAdapterListener] AdapterName [" + info.getAdapterGroupName() + "." + info.getName()
+ + "] adapter info [" + info + "] stop");
+ }
+ info.setStatus(false);
+ } catch (Exception e) {
+ logger.error(info.getName() + " | HttpClientAdapterListener | cannot stop : " + e.getMessage(), e);
+ throw new AdapterException(info.getName() + " | HttpClientAdapterListener | cannot stop - " + e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterMain.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterMain.java
new file mode 100644
index 0000000..5189c54
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterMain.java
@@ -0,0 +1,22 @@
+
+package com.eactive.eai.adapter.http.client;
+
+import java.util.Properties;
+
+import com.eactive.eai.adapter.ElinkDefaultAdapter;
+import com.eactive.eai.common.util.Logger;
+
+public class HttpClientAdapterMain extends ElinkDefaultAdapter {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public Object execute(Properties prop, Object message, Properties tempProp) throws Exception {
+ String httpType = prop.getProperty(HttpClientAdapterServiceKey.HTTP_TYPE); // Http Type에 대한 class name
+ String adapterGroupName = tempProp.getProperty(com.eactive.eai.adapter.Keys.OUT_ADAPTER_GROUP_NAME);
+ String adapterName = tempProp.getProperty(com.eactive.eai.adapter.Keys.OUT_ADAPTER_NAME);
+ HttpClientAdapterService service = HttpClientAdapterServiceFactory.createFactory(httpType, adapterGroupName, adapterName);
+ if (service == null) {
+ throw new Exception("Can not create HttpClientAdapterService httpType=" + httpType +" adapterName="+adapterName);
+ }
+ return service.execute(prop, message, tempProp);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterService.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterService.java
new file mode 100644
index 0000000..ed5b2ef
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterService.java
@@ -0,0 +1,14 @@
+
+package com.eactive.eai.adapter.http.client;
+
+import java.util.Properties;
+
+import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
+
+public interface HttpClientAdapterService {
+ public Object execute(Properties prop, Object message, Properties tempProp) throws Exception;
+ public void close();
+ public void init(String adapterName,
+ boolean useMtls, HttpOutTlsInfoVO mtlsInfo,
+ int maxTotalConnections, int maxHostConnections);
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceFactory.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceFactory.java
new file mode 100644
index 0000000..c8d4f5f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceFactory.java
@@ -0,0 +1,119 @@
+package com.eactive.eai.adapter.http.client;
+
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoManager;
+import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
+
+public class HttpClientAdapterServiceFactory {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ private static ConcurrentHashMap adapters = new ConcurrentHashMap<>();
+ private static ConcurrentHashMap adapterClass = new ConcurrentHashMap<>();
+
+ private HttpClientAdapterServiceFactory() {
+ super();
+ }
+
+ public static HttpClientAdapterService createFactory(String className, String adapterGroupName, String adapterName) throws Exception {
+ HttpClientAdapterService service = null;
+ if (adapters.containsKey(adapterName)) {
+ service = adapters.get(adapterName);
+ if (className.equals(adapterClass.get(adapterName))) {
+ return service;
+ }
+ else {
+ service.close();
+ service = null;
+ }
+ }
+
+ try {
+ Class cl = Class.forName(className);
+ service = (HttpClientAdapterService) cl.newInstance();
+
+ boolean useMtls = false;
+
+ int maxTotalConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_TOTAL_CONNECTIONS;
+ int maxHostConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_CONNECTION_PER_HOST;
+ AdapterVO adapterVo = AdapterManager.getInstance().getAdapterVO(adapterGroupName, adapterName);
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties outboundProp = manager.getProperties(adapterVo.getPropGroupName());
+
+ try {
+ maxTotalConnections = Integer.parseInt(outboundProp.getProperty(HttpClientAdapterServiceKey.MAX_TOTAL_CONNECTIONS));
+ }
+ catch(NumberFormatException ex) {
+ maxTotalConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_TOTAL_CONNECTIONS;
+ if(logger.isWarn()) {
+ logger.warn("HttpClientAdapterService. : {}, adatperName : {} UseDefault {}={}, {}"
+ , className, adapterName,HttpClientAdapterServiceKey.MAX_TOTAL_CONNECTIONS, maxTotalConnections, ex.toString());
+ }
+ }
+
+ try {
+ maxHostConnections = Integer.parseInt(outboundProp.getProperty(HttpClientAdapterServiceKey.MAX_CONNECTION_PER_HOST));
+ }
+ catch(NumberFormatException ex) {
+ maxHostConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_CONNECTION_PER_HOST;
+ if(logger.isWarn()) {
+ logger.warn("HttpClientAdapterService. : {}, adatperName : {} UseDefault {}={}, {}"
+ , className, adapterName,HttpClientAdapterServiceKey.MAX_CONNECTION_PER_HOST, maxHostConnections, ex.toString());
+ }
+ }
+
+ // clientID -> mTLS 인증정보 획득
+ useMtls = StringUtils.equalsIgnoreCase(outboundProp.getProperty(HttpClientAdapterServiceKey.USE_MTLS),"Y");
+
+ AdapterGroupVO adapterGroup = AdapterManager.getInstance().getAdapterGroup(adapterGroupName);
+ // outboundProp.getProperty(HttpClientAdapterServiceKey.CLIENT_ID);
+ String clientId = adapterGroup.getClientId();
+
+ if(logger.isInfo()) {
+ logger.info("MTLS adapterName. : {}, useMtls. : {}, clientId : {}", adapterName, useMtls, clientId);
+ }
+ HttpOutTlsInfoVO mtlsInfo = null;
+ if(useMtls) {
+ HttpOutTlsInfoManager tlsManager = HttpOutTlsInfoManager.getInstance();
+ if(StringUtils.isNotEmpty(clientId)) {
+ mtlsInfo = tlsManager.getHttpOutTlsInfo(clientId);
+ }
+ }
+// keyStorePath = outboundProp.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PATH);
+// keyStorePassword = outboundProp.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PWD);
+// trustStorePath = outboundProp.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PATH);
+// trustStorePassword = outboundProp.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PWD);
+
+ service.init(adapterName,
+ useMtls, mtlsInfo,
+ maxTotalConnections, maxHostConnections);
+
+ if (service != null) {
+ adapters.put(adapterName, service);
+ adapterClass.put(adapterName, className);
+ }
+ } catch (Exception e) {
+ logger.error("Cannot create a HttpClientAdapterService. : {}, adatperName : {}", className, adapterName, e);
+ throw e;
+ }
+ return service;
+ }
+
+ public static void removeFactory(String adapterName) {
+ String className = null;
+ if (adapters.containsKey(adapterName)) {
+ adapters.remove(adapterName);
+ className = adapterClass.remove(adapterName);
+ if(logger.isWarn()) {
+ logger.warn("Remove HttpClientAdapterService. : {}, adatperName : {}", className, adapterName);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceKey.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceKey.java
new file mode 100644
index 0000000..0238cbc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceKey.java
@@ -0,0 +1,90 @@
+
+package com.eactive.eai.adapter.http.client;
+
+public interface HttpClientAdapterServiceKey {
+
+ public static final String ADAPTER_GROUP_NAME = "ADAPTER_GROUP_NAME";
+ public static final String ADAPTER_NAME = "ADAPTER_NAME";
+
+ public static final String HTTP_TYPE = "HTTP_TYPE";
+ public static final String URL = "URL";
+ public static final String URL_2GRP = "URL_2GRP";
+
+ public static final String METHOD = "METHOD";
+ public static final String PARAMETER_NAME = "PARAMETER_NAME";
+
+ public static final String TRAN_CODE = "TRAN_CODE";
+ public static final String LOCAL_CALL = "LOCAL_CALL";
+ public static final String LOCAL_CALL_Y = "Y";
+ public static final String LOG_PROCESS_NO = "LOG_PROCESS_NO";
+ public static final String LOCAL_IP = "LOCAL_IP";
+
+ public static final String ENCODE = "ENCODE";
+
+ public static final String CONTENT_TYPE = "CONTENT_TYPE";
+ public static final String CONTENT_TYPE_KEY = "Content-Type";
+
+ public static final String METHOD_GET = "GET";
+ public static final String METHOD_POST = "POST";
+
+ public static final String RESPONSE_TYPE = "RESPONSE_TYPE";
+ public static final String RESPONSE_TYPE_SYNC = "SYNC";
+ public static final String RESPONSE_TYPE_ASYNC = "ASYN";
+
+ public static final String METHOD_SOAP = "SOAP";
+ public static final String METHOD_SOAP_ACTION = "SOAPAction";
+
+ public static final String REST_OPTION = "REST_OPTION";
+ public static final String TOUTVAL = "TOUTVAL";
+
+ public static final String CONNECTION_STALE_CHECKING_ENABLED = "CONNECTION_STALE_CHECKING_ENABLED";
+
+ // 호스트 마다 최대 연결 수
+ public static final int DEFAULT_MAX_CONNECTION_PER_HOST = 10;
+ public static final String MAX_CONNECTION_PER_HOST = "MAX_CONNECTION_PER_HOST";
+ // 최대 HTTP 연결 수
+ public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;
+ public static final String MAX_TOTAL_CONNECTIONS = "MAX_TOTAL_CONNECTIONS";
+
+ static final String PARAMETER_MESSAGE = "_message_";
+
+ static final String URL_ENCODE_YN = "URL_ENCODE_YN";
+
+ static final String CONNECTION_TIMEOUT = "CONNECTION_TIMEOUT";
+ static final String ADAPTER_HEADER = "ADAPTER_HEADER";
+
+ public static final String HTTP_TIME_OUT = "HTTP_TIME_OUT";
+ public static final int DEFAULT_TIME_OUT = 30 * 1000;
+
+ public static final String TESTCALL_URL = "TESTCALL_URL";
+ public static final String TESTCALL_YN = "TESTCALL_YN";
+ public static final String TRACE_LEVEL = "TRACE_LEVEL";
+
+ public static final String HEALTHCHECK_URL = "HEALTHCHECK_URL";
+ public static final String HEALTHCHECK_TIMEOUTMS = "HEALTHCHECK_TIMEOUTMS";
+
+ public static final String INBOUND_METHOD = "INBOUND_METHOD";
+ public static final String INBOUND_URI = "INBOUND_URI";
+ public static final String INBOUND_EXTURI = "INBOUND_EXTURI";
+ public static final String INBOUND_HEADER = "INBOUND_HEADER";
+
+ public static final String HTTP_VERSION = "HTTP_VERSION";
+ public static final String HTTP_VERSION_1_0 = "1.0";
+ public static final String HTTP_VERSION_1_1 = "1.1";
+ public static final String HTTP_VERSION_2_0 = "2.0";
+
+ public static final String HTTP_VERSION_FULL_1_1 = "HTTP_1_1";
+ public static final String HTTP_VERSION_FULL_1_0 = "HTTP_1_0";
+
+ public static final String USE_MTLS = "USE_MTLS";
+ public static final String CLIENT_ID = "CLIENT_ID";
+ public static final String KEYSTORE_PATH = "KEYSTORE_PATH";
+ public static final String KEYSTORE_PWD = "KEYSTORE_PWD";
+ public static final String TRUSTSTORE_PATH = "TRUSTSTORE_PATH";
+ public static final String TRUSTSTORE_PWD = "TRUSTSTORE_PWD";
+
+ public static final String TRANSACTION_ID = "transactionId";
+ public static final String INSTANCE_ID = "instanceId";
+
+ public static final String TRANSACTION_SVC_PATTERN ="TRANSACTION_SVC_PATTERN";//(SYNC/ASYN)-(SYNC/ASYN)
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceSupport.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceSupport.java
new file mode 100644
index 0000000..941a92b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceSupport.java
@@ -0,0 +1,439 @@
+
+package com.eactive.eai.adapter.http.client;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpVersion;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.CustomSSLProtocolSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.adapter.http.secure.SSLContextFactory;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoManager;
+import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
+
+public abstract class HttpClientAdapterServiceSupport implements HttpClientAdapterService, HttpClientAdapterServiceKey {
+ protected static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ protected HttpClient client;
+ private MultiThreadedHttpConnectionManager connectionManager;
+
+ public synchronized void close() {
+ if (connectionManager != null) {
+ connectionManager.shutdown();
+ }
+ }
+
+ protected HttpClientAdapterVO setting(Properties prop, Properties tempProp) {
+ String url = null;
+ String parameterName = null;
+ String method = null;
+ String contentType = null;
+ String encode = null;
+ String testCallYn = null;
+ String adapterGroupName = null;
+ String adapterName = null;
+ String responseType = null;
+ String urlEncodeYn = null;
+ String adapterHeader = null;
+
+ boolean useMtls = false;
+ String keyStorePath = null;
+ String keyStorePassword = null;
+ String trustStorePath = null;
+ String trustStorePassword = null;
+
+ int connectionTimeout = 0;
+ int timeout = -1;
+ int traceLevel = 0;
+ long slowTranTime = 2000L;
+
+ url = prop.getProperty(URL);
+
+ String url2grp = tempProp.getProperty(URL);
+ if (!StringUtils.isEmpty(url2grp)) {
+ url = url2grp;
+ }
+ method = prop.getProperty(METHOD);
+ parameterName = prop.getProperty(PARAMETER_NAME, PARAMETER_MESSAGE);
+ contentType = prop.getProperty(CONTENT_TYPE, "");
+ responseType = prop.getProperty(RESPONSE_TYPE, "SYNC");
+ urlEncodeYn = prop.getProperty(URL_ENCODE_YN, "N");
+ String connectionTimeoutTemp = prop.getProperty(CONNECTION_TIMEOUT, "0");
+
+ String httpVersion = prop.getProperty(HTTP_VERSION);
+ adapterHeader = prop.getProperty(ADAPTER_HEADER, "");
+
+ String traceLevelTemp = prop.getProperty(TRACE_LEVEL, "0");
+ String timeoutTemp = prop.getProperty(HTTP_TIME_OUT);
+
+ useMtls = StringUtils.equalsIgnoreCase(prop.getProperty(HttpClientAdapterServiceKey.USE_MTLS), "Y");
+ keyStorePath = prop.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PATH);
+ keyStorePassword = prop.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PWD);
+ trustStorePath = prop.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PATH);
+ trustStorePassword = prop.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PWD);
+
+ encode = tempProp.getProperty(Keys.CHARSET_KEY_OUT, Charset.defaultCharset().name());
+ testCallYn = tempProp.getProperty(TESTCALL_YN, "N");
+ adapterGroupName = tempProp.getProperty(ADAPTER_GROUP_NAME);
+ adapterName = tempProp.getProperty(ADAPTER_NAME);
+ // 인터페이스 정보에 설정된 타임아웃
+ String interfaceTimeout = tempProp.getProperty("INTERFACE_TIME_OUT");
+ if (StringUtils.isNotBlank(interfaceTimeout) && NumberUtils.toInt(interfaceTimeout) > 0) {
+ timeoutTemp = interfaceTimeout;
+ }
+
+ url = StringUtils.trim(url);
+ parameterName = StringUtils.trim(parameterName);
+ method = StringUtils.trim(method);
+ encode = StringUtils.trim(encode);
+ contentType = StringUtils.trim(contentType);
+
+ if (timeoutTemp == null) {
+ timeoutTemp = "0";
+ } else {
+ timeoutTemp = timeoutTemp.trim();
+ }
+
+ try {
+ connectionTimeout = Integer.parseInt(connectionTimeoutTemp);
+ } catch (Exception e) {
+ logger.debug("HttpClientAdapterSupport] connectionTimeoutTemp not int");
+ }
+ try {
+ timeout = Integer.parseInt(timeoutTemp);
+ } catch (NumberFormatException e) {
+ logger.warn("HttpClientAdapterSupport] timeoutTemp not int", e);
+ }
+
+ try {
+ traceLevel = Integer.parseInt(traceLevelTemp);
+ } catch (Exception e) {
+ logger.warn("HttpClientAdapterSupport] traceLevelTemp not int", e);
+ }
+
+ // client 중 BODY,POST,GET,NexCore 방식만 적용
+ HashMap adapterHeaders = new HashMap<>();
+ try {
+ Matcher matcher = Pattern.compile(
+ "\\{[ ]*\"[ ]*([a-zA-Z0-9_-]+)[ ]*\"[ ]*,[ ]*\"[ ]*([a-zA-Z0-9/;,\\*=_ -]+)[ ]*\"[ ]*\\}[ ]*")
+ .matcher(adapterHeader.trim());
+ while (matcher.find()) {
+ String key = matcher.group(1).trim();
+ String value = matcher.group(2).trim();
+ adapterHeaders.put(key, value);
+ }
+ } catch (Exception e) {
+ if (logger.isDebug())
+ logger.debug("HttpClientAdapterSupport] adapter header parsing error " + adapterHeader);
+ }
+ // GW 전달 로직 추가
+ // tempProp로 넘겨서 하는 이유는 outboundProp가 clone 안하는 로직이라 outboundProp로 넘길시 문제의 소지가있음
+ String transactionId = tempProp.getProperty(HttpClientAdapterServiceKey.TRANSACTION_ID);
+ String instanceId = tempProp.getProperty(HttpClientAdapterServiceKey.INSTANCE_ID);
+ if (StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(instanceId)) {
+ adapterHeaders.put(HttpClientAdapterServiceKey.TRANSACTION_ID, transactionId);
+ adapterHeaders.put(HttpClientAdapterServiceKey.INSTANCE_ID, instanceId);
+ }
+
+ HttpClientAdapterVO vo = new HttpClientAdapterVO();
+ vo.setUrl(url);
+ vo.setMethod(method);
+ vo.setParameterName(parameterName);
+ vo.setEncode(encode);
+ vo.setContentType(contentType);
+ vo.setTestCallYn(testCallYn);
+ vo.setResponseType(responseType);
+ vo.setUrlEncodeYn(urlEncodeYn);
+ vo.setAdapterGroupName(adapterGroupName);
+ vo.setAdapterName(adapterName);
+
+ vo.setMaxTotalConnections(getMaxTotalConnections());
+ vo.setMaxHostConnections(getMaxConnectionsPerHost());
+ vo.setConnectionTimeout(connectionTimeout);
+
+ vo.setTimeout(timeout);
+ vo.setTraceLevel(traceLevel);
+ vo.setSlowTranTime(slowTranTime);
+ vo.setAdapterHeaders(adapterHeaders);
+ if (StringUtils.equalsAny(httpVersion, HTTP_VERSION_FULL_1_1, HTTP_VERSION_1_1)) {
+ vo.setHttpVersion(HTTP_VERSION_1_1);
+ } else {
+ vo.setHttpVersion(HTTP_VERSION_1_0);
+ }
+ vo.setUseMtls(useMtls);
+ vo.setKeyStorePath(keyStorePath);
+ vo.setKeyStorePassword(keyStorePassword);
+ vo.setTrustStorePath(trustStorePath);
+ vo.setTrustStorePassword(trustStorePassword);
+
+ if (logger.isDebug()) {
+ logger.debug(vo.toString());
+ }
+ return vo;
+ }
+
+ protected HttpClientAdapterServiceSupport() {
+
+ }
+
+ public synchronized void init(String adapterName, boolean useMtls, HttpOutTlsInfoVO mtlsInfo,
+ int maxTotalConnections, int maxHostConnections) {
+ if (connectionManager != null) {
+ if ((connectionManager.getParams().getMaxTotalConnections() == maxTotalConnections)
+ && (connectionManager.getParams().getDefaultMaxConnectionsPerHost() == maxHostConnections)) {
+ if (logger.isInfo()) {
+ logger.info("ConnectionManager REUSE : AdapterName=" + adapterName + " MaxTotalConnection ("
+ + connectionManager.getParams().getMaxTotalConnections() + ") MaxHostConnections ("
+ + connectionManager.getParams().getDefaultMaxConnectionsPerHost() + ")");
+ }
+ return;
+ } else {
+ if (logger.isWarn()) {
+ logger.warn("ConnectionManager RELOAD : AdapterName=" + adapterName + " MaxTotalConnection ("
+ + connectionManager.getParams().getMaxTotalConnections() + " -> " + maxTotalConnections
+ + ") MaxHostConnections (" + connectionManager.getParams().getDefaultMaxConnectionsPerHost()
+ + " -> " + maxHostConnections + ")");
+ }
+ connectionManager.shutdown();
+ connectionManager = null;
+ this.client = null;
+ }
+ }
+
+ if (logger.isWarn()) {
+ logger.warn("ConnectionManager INIT : AdapterName=" + adapterName + " MaxTotalConnection ("
+ + maxTotalConnections + ") MaxHostConnections (" + maxHostConnections + ")");
+ }
+ connectionManager = new MultiThreadedHttpConnectionManager();
+ connectionManager.getParams().setStaleCheckingEnabled(true);
+ connectionManager.getParams().setMaxTotalConnections(maxTotalConnections);
+ connectionManager.getParams().setDefaultMaxConnectionsPerHost(maxHostConnections);
+
+ this.client = new HttpClient(connectionManager);
+ }
+
+ public int getConnectionsInPool() {
+ if (this.client == null)
+ return 0;
+ MultiThreadedHttpConnectionManager mgr = (MultiThreadedHttpConnectionManager) this.client
+ .getHttpConnectionManager();
+ return mgr.getConnectionsInPool();
+ }
+
+ public int getMaxTotalConnections() {
+ if (this.client == null)
+ return 0;
+ MultiThreadedHttpConnectionManager mgr = (MultiThreadedHttpConnectionManager) this.client
+ .getHttpConnectionManager();
+ return mgr.getParams().getMaxTotalConnections();
+ }
+
+ public int getMaxConnectionsPerHost() {
+ if (this.client == null)
+ return 0;
+ MultiThreadedHttpConnectionManager mgr = (MultiThreadedHttpConnectionManager) this.client
+ .getHttpConnectionManager();
+ return mgr.getParams().getDefaultMaxConnectionsPerHost();
+ }
+
+ public String getResponseCharSet(String httpResponseCharset, String adapterGroupName) {
+ if (StringUtils.isNotBlank(httpResponseCharset)) {
+ return httpResponseCharset;
+ } else {
+ AdapterManager m = AdapterManager.getInstance();
+ AdapterGroupVO agvo = m.getAdapterGroupVO(adapterGroupName);
+ return agvo.getMessageEncode();
+ }
+ }
+
+ /**
+ * encoding에 대한 정의 필요 고려할 문제 1. 어댑터그룹이 UJN 타입일경우 return 은 UTF-8 로 getBytes 된
+ * 데이터여야됨. 2. http response에 받은 encoding 타입은 고려대상임. 결론 : response Encoding 과
+ * 어댑터의 MESSAGE_TYPE 다르면 변환, 나머지면 return 어댑터의 ENCODE은 요청전문 encoding에서만 사용
+ *
+ * 예) 어댑터의 ENCODE, 어댑터의 MESSAGE TYPE, RESPNSE ENCODING TYPE, 처리내용 예) ,ECU-KR
+ * ,JSN , EUC-KR , 응답받은 메시지를 return 예) ,ECU-KR , JSN , UTF-8 , 응답받은 메시지를 new
+ * String(xxx,"UTF-8") => getBytes("EUC-KR") 예) ,ECU-KR , UJN , EUC-KR , 응답받은
+ * 메시지를 new String(xxx,"EUC-KR") => getBytes("UTF-8") 예) ,ECU-KR , UJN , UTF-8 ,
+ * 응답받은 메시지를 return 예) ,UTF-8 , JSN , EUC-KR , 응답받은 메시지를 return 예) ,UTF-8 , JSN
+ * , UTF-8 , 응답받은 메시지를 new String(xxx,"UTF-8") => getBytes(EUC-KR") 예) ,UTF-8 ,
+ * UJN , EUC-KR , 응답받은 메시지를 new String(xxx,"EUC-KR") => getBytes("UTF-8") 예)
+ * ,UTF-8 , UJN , UTF-8 , 응답받은 메시지를 return
+ *
+ *
+ */
+ public byte[] getEncodingConvert(String httpResponseCharset, String adapterGroupName, byte[] message) {
+ byte[] responseMessage = null;
+ if (StringUtils.isNotBlank(httpResponseCharset)) {
+ AdapterManager m = AdapterManager.getInstance();
+ AdapterGroupVO agvo = m.getAdapterGroupVO(adapterGroupName);
+ String adapterTypeEncoding = StringUtils.defaultIfBlank(agvo.getMessageEncode(),
+ Charset.defaultCharset().name());
+ Charset responseCharset = null;
+ Charset adapterCharset = null;
+ try {
+ responseCharset = Charset.forName(httpResponseCharset);
+ adapterCharset = Charset.forName(adapterTypeEncoding);
+ if (responseCharset.compareTo(adapterCharset) == 0) {
+ responseMessage = message;
+ } else {// http 응답 charset 과 어댑터의 charset 이 다를경우 charset 변환 필요
+ String encodingString = new String(message, httpResponseCharset);
+ responseMessage = encodingString.getBytes(adapterTypeEncoding);
+ }
+ } catch (UnsupportedCharsetException | UnsupportedEncodingException e) {
+ responseMessage = message;
+ }
+ } else {
+ responseMessage = message;
+ }
+ return responseMessage;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void configureHttpClient(HttpClient mclient, HttpMethodBase method, HttpClientAdapterVO vo, String url,
+ String contentType) throws Exception {
+ if (StringUtils.isNotBlank(vo.getEncode())) {
+ mclient.getParams().setContentCharset(vo.getEncode());
+ }
+
+ if (vo.getConnectionTimeout() != 0) {
+ mclient.getHttpConnectionManager().getParams().setConnectionTimeout(vo.getConnectionTimeout());
+ }
+
+ if (vo.getTimeout() > -1) {
+ mclient.getHttpConnectionManager().getParams().setSoTimeout(vo.getTimeout());
+ }
+
+ if (HTTP_VERSION_1_1.equals(vo.getHttpVersion())) {
+ method.setRequestHeader("Connection", "close");
+ method.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_1);
+ } else {
+ method.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
+ }
+
+ method.setFollowRedirects(false);
+
+ if (StringUtils.startsWith(url, "https")) {
+ if (vo.isUseMtls()) {
+ HttpOutTlsInfoManager tlsManager = HttpOutTlsInfoManager.getInstance();
+ String clientId = vo.getClientId();
+ HttpOutTlsInfoVO mtlsInfo = tlsManager.getHttpOutTlsInfo(clientId);
+ String storeType = mtlsInfo.getStoreType();
+ String keyStoreInfo = mtlsInfo.getKeystoreInfo();
+ String keyStorePassword = mtlsInfo.getKeystorePassword();
+ String trustStoreInfo = mtlsInfo.getTruststoreInfo();
+ String trustStorePassword = mtlsInfo.getTruststorePassword();
+
+ // Server negotiation 에 의해 변경될 수 있음
+ String[] tlsVersions = null;
+// {
+// "TLSv1.0"
+// , "TLSv1.1"
+// , "TLSv1.2"
+// , "TLSv1.3"
+// };
+ String[] cipherSuites = null;
+// {
+// "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+// "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+// "TLS_RSA_WITH_AES_256_CBC_SHA256",
+// "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
+// "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
+// "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+// "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+// "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+// "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+// "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+// "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+// "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+// "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+// "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+// "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+// "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+// "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+// "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+// "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+// "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+// "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+// "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+// "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+// "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
+// };
+
+ if (StringUtils.isAnyEmpty(keyStoreInfo, keyStorePassword)) {
+ throw new Exception("mTLS keyStore config error");
+ }
+
+ boolean skipTrust = false;
+ // kbank에서는 trustStore를 사용하지 않음
+ if (StringUtils.isAnyEmpty(trustStoreInfo, trustStorePassword)) {
+// throw new Exception("mTLS trustStore config error");
+ if (logger.isWarn())
+ logger.warn("Skip trustStore validation adapterName : " + vo.getAdapterName());
+ skipTrust = true;
+ }
+
+ SSLContext sslContext = SSLContextFactory.createMTLSContextFromContent(storeType, keyStoreInfo,
+ keyStorePassword, trustStoreInfo, trustStorePassword, skipTrust, tlsVersions, cipherSuites);
+ // SSLProtocolSocketFactory 생성
+ ProtocolSocketFactory socketFactory = new CustomSSLProtocolSocketFactory(sslContext);
+ Protocol.registerProtocol("https", new Protocol("https", socketFactory, 443));
+ } else {
+ Protocol.registerProtocol("https",
+ new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+ }
+ }
+
+ if (StringUtils.equalsIgnoreCase(method.getName(), "POST")
+ || StringUtils.equalsIgnoreCase(method.getName(), "PUT")) {
+ if (StringUtils.isNotBlank(contentType)) {
+ if (StringUtils.isBlank(vo.getEncode())) {
+ method.setRequestHeader("Content-Type", contentType);
+ } else {
+ method.setRequestHeader("Content-Type",
+ String.format("%s; charset=%s", contentType, vo.getEncode()));
+ }
+ }
+ }
+ }
+
+ public abstract Object execute(Properties prop, Object message, Properties tempProp) throws Exception;
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceType.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceType.java
new file mode 100644
index 0000000..2112740
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterServiceType.java
@@ -0,0 +1,16 @@
+package com.eactive.eai.adapter.http.client;
+
+public enum HttpClientAdapterServiceType {
+ STANDARD,
+ EXTORG,
+ QUICS,
+ REST,
+ UNKNOWN;
+ public static HttpClientAdapterServiceType getValue(String value) {
+ try {
+ return valueOf(value.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterVO.java b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterVO.java
new file mode 100644
index 0000000..d1be29c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/HttpClientAdapterVO.java
@@ -0,0 +1,268 @@
+
+package com.eactive.eai.adapter.http.client;
+
+import java.util.HashMap;
+
+public class HttpClientAdapterVO {
+ protected String url = null;
+ protected String parameterName = null;
+ protected String method = null;
+
+ protected String contentType = null;
+
+ protected String encode = null;
+ protected String testCallYn = null;
+
+ protected String adapterGroupName = null;
+ protected String adapterName = null;
+ protected String responseType = null;
+ protected String urlEncodeYn = null;
+
+ protected int connectionTimeout = 0;
+ protected int maxTotalConnections = 50;
+ protected int maxHostConnections = 10;
+ protected int timeout = -1;
+ protected int traceLevel = 0;
+
+ protected long slowTranTime = 2000L;
+
+ protected String httpVersion = null;
+
+ // client header 값 추가
+ protected HashMap adapterHeaders = null;
+
+ // mTLS
+ boolean useMtls = false;
+ String clientId = null;
+ String keyStorePath = null;
+ String keyStorePassword = null;
+ String trustStorePath = null;
+ String trustStorePassword = null;
+
+ public int getMaxTotalConnections() {
+ return maxTotalConnections;
+ }
+
+ public void setMaxTotalConnections(int maxTotalConnections) {
+ this.maxTotalConnections = maxTotalConnections;
+ }
+
+ public int getMaxHostConnections() {
+ return maxHostConnections;
+ }
+
+ public void setMaxHostConnections(int maxHostConnections) {
+ this.maxHostConnections = maxHostConnections;
+ }
+
+ public String getHttpVersion() {
+ return httpVersion;
+ }
+
+ public void setHttpVersion(String httpVersion) {
+ this.httpVersion = httpVersion;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getParameterName() {
+ return parameterName;
+ }
+
+ public void setParameterName(String parameterName) {
+ this.parameterName = parameterName;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public String getEncode() {
+ return encode;
+ }
+
+ public void setEncode(String encode) {
+ this.encode = encode;
+ }
+
+ public String getTestCallYn() {
+ return testCallYn;
+ }
+
+ public void setTestCallYn(String testCallYn) {
+ this.testCallYn = testCallYn;
+ }
+
+ public String getAdapterGroupName() {
+ return adapterGroupName;
+ }
+
+ public void setAdapterGroupName(String adapterGroupName) {
+ this.adapterGroupName = adapterGroupName;
+ }
+
+ public String getAdapterName() {
+ return adapterName;
+ }
+
+ public void setAdapterName(String adapterName) {
+ this.adapterName = adapterName;
+ }
+
+ public String getResponseType() {
+ return responseType;
+ }
+
+ public void setResponseType(String responseType) {
+ this.responseType = responseType;
+ }
+
+ public String getUrlEncodeYn() {
+ return urlEncodeYn;
+ }
+
+ public void setUrlEncodeYn(String urlEncodeYn) {
+ this.urlEncodeYn = urlEncodeYn;
+ }
+
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
+
+ public void setConnectionTimeout(int connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public int getTraceLevel() {
+ return traceLevel;
+ }
+
+ public void setTraceLevel(int traceLevel) {
+ this.traceLevel = traceLevel;
+ }
+
+ public long getSlowTranTime() {
+ return slowTranTime;
+ }
+
+ public void setSlowTranTime(long slowTranTime) {
+ this.slowTranTime = slowTranTime;
+ }
+
+ public HashMap getAdapterHeaders() {
+ return adapterHeaders;
+ }
+
+ public void setAdapterHeaders(HashMap adapterHeaders) {
+ this.adapterHeaders = adapterHeaders;
+ }
+
+
+ public boolean isUseMtls() {
+ return useMtls;
+ }
+
+ public void setUseMtls(boolean useMtls) {
+ this.useMtls = useMtls;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getKeyStorePath() {
+ return keyStorePath;
+ }
+
+ public void setKeyStorePath(String keyStorePath) {
+ this.keyStorePath = keyStorePath;
+ }
+
+ public String getKeyStorePassword() {
+ return keyStorePassword;
+ }
+
+ public void setKeyStorePassword(String keyStorePassword) {
+ this.keyStorePassword = keyStorePassword;
+ }
+
+ public String getTrustStorePath() {
+ return trustStorePath;
+ }
+
+ public void setTrustStorePath(String trustStorePath) {
+ this.trustStorePath = trustStorePath;
+ }
+
+ public String getTrustStorePassword() {
+ return trustStorePassword;
+ }
+
+ public void setTrustStorePassword(String trustStorePassword) {
+ this.trustStorePassword = trustStorePassword;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("HttpClientAdapterVO [adapterGroupName=" + adapterGroupName + ", adapterGroupName=" + adapterGroupName + ", responseType=" + responseType );
+ sb.append("\n");
+ sb.append("url=" + url + ", parameterName=" + parameterName + ", method=" + method );
+ sb.append("\n");
+ sb.append(", contentType=" + contentType + ", encode=" + encode + ", testCallYn=" + testCallYn );
+ sb.append("\n");
+ sb.append(", urlEncodeYn=" + urlEncodeYn + ", connectionTimeout=" + connectionTimeout );
+ sb.append("\n");
+ sb.append(", maxTotalConnections=" + maxTotalConnections + ", maxHostConnections=" + maxHostConnections );
+ sb.append("\n");
+ sb.append(", timeout=" + timeout + ", traceLevel=" + traceLevel + ", slowTranTime=" + slowTranTime );
+ sb.append("\n");
+ sb.append(", httpVersion=" + httpVersion + "]" );
+ if(adapterHeaders != null) {
+ sb.append("\nadapter header [\n");
+ for (String key : adapterHeaders.keySet()) {
+ sb.append(key).append("=").append(adapterHeaders.get(key));
+ sb.append("\n");
+ }
+ sb.append("\n]");
+ }
+ sb.append("\n");
+ sb.append(", useMtls=" + useMtls + ", clientId=" + clientId);
+ sb.append(", keyStorePath=" + keyStorePath + ", keyStorePassword=" + keyStorePassword );
+ sb.append(", trustStorePath=" + trustStorePath + ", trustStorePassword=" + trustStorePassword );
+ return sb.toString();
+
+ }
+
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceBody.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceBody.java
new file mode 100644
index 0000000..5bfc866
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceBody.java
@@ -0,0 +1,206 @@
+package com.eactive.eai.adapter.http.client.impl;
+
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.client.HttpClient5AdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.common.TransactionContextKeys;
+import com.eactive.eai.common.util.CommonLib;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.hc.core5.http.protocol.BasicHttpContext;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Properties;
+
+public class HttpClient5AdapterServiceBody extends HttpClient5AdapterServiceSupport {
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+
+ boolean isAsync = false;
+ if (RESPONSE_TYPE_ASYNC.equals(vo.getResponseType())) {
+ isAsync = true;
+ }
+
+ RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
+
+ boolean useForwardProxy = StringUtils.equalsIgnoreCase(prop.getProperty("FORWARD_PROXY_USE_YN", "N"), "Y");
+ String forwardProxyUrl = prop.getProperty("FORWARD_PROXY_URL");
+
+ if(useForwardProxy) {
+ java.net.URL url = new java.net.URL(forwardProxyUrl);
+
+ // 프로토콜, 호스트, 포트 추출
+ String protocol = url.getProtocol();
+ String host = url.getHost();
+ int port = url.getPort();
+ HttpHost proxy = new HttpHost(protocol,host, port);
+ requestConfigBuilder.setProxy(proxy);
+ }
+
+ String sendData = "";
+ if (data instanceof String) {
+ sendData = (String) data;
+ } else if (data instanceof byte[]) {
+ sendData = new String((byte[]) data, vo.getEncode());
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode jsonNode = (ObjectNode) mapper.readTree(sendData);
+ ObjectNode headerPart = (ObjectNode) jsonNode.get("header_part");
+
+ if( headerPart.get("mciIntfId") != null && headerPart.get("mciIntfId").asText().trim().length() > 0 ) {
+ headerPart.put("eaiIntfId", "");
+ sendData = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
+ }
+
+ if ("Y".equals(vo.getUrlEncodeYn())) {
+ sendData = java.net.URLEncoder.encode(sendData);
+ }
+
+ ContentType contentTypeObj ;
+ if (StringUtils.isNotEmpty(vo.getContentType())) {
+ //주석이유 : ContentType.create에서 "application/json;charset=UTF-8" 이런 형태면 오류발생
+// String contentTypeValue ;
+// if (StringUtils.isNotEmpty(vo.getEncode())) {
+// contentTypeValue = vo.getContentType() + "; charset=" + vo.getEncode();
+// } else {
+// contentTypeValue = vo.getContentType();
+// }
+ contentTypeObj = ContentType.create(vo.getContentType(), vo.getEncode());
+ }else{
+ contentTypeObj = ContentType.APPLICATION_JSON;
+ }
+
+ HttpPost method = new HttpPost(vo.getUrl());
+ // POST 요청 본문 설정
+ if (sendData != null) {
+ method.setEntity(new StringEntity(sendData, contentTypeObj));
+ }
+
+ if (vo.getAdapterHeaders() != null) {
+ for (String key : vo.getAdapterHeaders().keySet()) {
+ method.setHeader(key, vo.getAdapterHeaders().get(key));
+ }
+ }
+ if (logger.isInfoEnabled()) {
+ logger.info("" + CONTENT_TYPE_KEY + "(" + contentTypeObj + ")");
+ }
+
+ configureHttpClient(requestConfigBuilder, vo, method);
+
+ int status = -1;
+
+ try {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug(
+ "SEND (" + vo.getAdapterGroupName() + ") = [" + sendData + "]");
+ logger.debug("SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(sendData));
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [" + sendData + "]" + CommonLib.getDumpMessage(sendData));
+ }
+
+ String uuid = tempProp.getProperty(TransactionContextKeys.TRANSACTION_UUID);
+ HttpContext context = new BasicHttpContext();
+ context.setAttribute(TransactionContextKeys.TRANSACTION_UUID, uuid);
+ context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME, vo.getAdapterGroupName());
+ context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_NAME, vo.getAdapterName());
+ Integer logProcessNo = (Integer) tempProp.get(HttpClientAdapterServiceKey.LOG_PROCESS_NO);
+ if (logProcessNo != null && logProcessNo > 0) {
+ context.setAttribute(HttpClientAdapterServiceKey.LOG_PROCESS_NO, logProcessNo);
+ }
+
+ byte[] responseMessage = null;
+ String responseString = "";
+ try (CloseableHttpResponse response = (CloseableHttpResponse) this.client.execute(method, context)) {
+ status = response.getCode();
+ responseMessage = EntityUtils.toByteArray(response.getEntity());
+ responseString = new String(responseMessage, vo.getEncode());
+ if (logger.isDebug()) {
+ logger.debug("[received status]" + status);
+ logger.debug("HttpClientAdapterServiceBody] RECV (" + vo.getAdapterGroupName() + ") = [" + responseString + "]");
+ }
+ } catch (ConnectException e) {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceBody] responseType =" + vo.getResponseType());
+ }
+ throw new Exception("excuteMethod java.net.ConnectException = " + e.getMessage());
+ }
+
+ stopWatch.stop();
+
+
+ if (status >= 400 && status < 500) {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), vo.getUrl(), "post", responseString);
+ throw new Exception(errMsg);
+ } else if(status != HttpStatus.SC_OK) {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), vo.getUrl(), "post", responseString);
+ throw new Exception(errMsg);
+ }
+
+ if (isAsync && stopWatch.getTime() > vo.getSlowTranTime() && (logger.isWarn())) {
+ logger.warn("URL[" + vo.getUrl() + "] lazy async response time = "
+ + stopWatch.toString() + " responseMessage=" + responseString);
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [" + responseString + "]"
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ return responseMessage;
+
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SocketTimeoutException : " + ste.toString(), ste);
+ }
+ if (logger.isError()) {
+ logger.error("SocketTimeoutException : " + ste.toString(), ste);
+ }
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "Connection Exception : " + ce.toString(), ce);
+ }
+ if (logger.isError()) {
+ logger.error("Connection Exception : " + ce.toString(), ce);
+ }
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "Exception : " + e.toString(), e);
+ }
+ if (logger.isError()) {
+ logger.error("Exception : " + e.toString(), e);
+ }
+ throw e;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceRest.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceRest.java
new file mode 100644
index 0000000..2605db0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClient5AdapterServiceRest.java
@@ -0,0 +1,895 @@
+package com.eactive.eai.adapter.http.client.impl;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.eactive.eai.common.property.PropManager;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.classic.methods.HttpDelete;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.classic.methods.HttpPut;
+import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
+import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.hc.core5.http.message.BasicNameValuePair;
+import org.apache.hc.core5.http.protocol.BasicHttpContext;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.net.URIBuilder;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpMethodType;
+import com.eactive.eai.adapter.http.client.HttpClient5AdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
+import com.eactive.eai.common.TransactionContextKeys;
+import com.eactive.eai.common.authoutbound.AccessTokenManagerByDB;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.util.CommonLib;
+import com.jayway.jsonpath.DocumentContext;
+import com.jayway.jsonpath.JsonPath;
+import com.openbanking.eai.common.token.AccessTokenManager;
+import com.openbanking.eai.common.token.AccessTokenVO;
+import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
+
+/**
+ * 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를 GET/POST 방식으로 호출할 수 있는
+ * 기능을 제공한다.
+ * 2. 처리 개요 :
+ * * - 2020-09-25: Http Header 받아서 처리할 수 있게 기능 추가
+ * 3. 주의사항
+ *
+ * @author :
+ * @version : v 1.0.0
+ * @see : HttpClientAdapterServiceFactory.java,
+ * HttpClientAdapterServiceSupport.java
+ * @since :
+ *
+ */
+public class HttpClient5AdapterServiceRest extends HttpClient5AdapterServiceSupport
+ implements HttpClientAdapterServiceKey {
+ public static final String TYPE_VARIABLE_URL_REQUEST = "variableUrlRequest";
+ public static final String TYPE_SIMPLE_REQUEST = "simpleRequest";
+ public static final String REST_OPTION = "REST_OPTION";
+ //public static final String HEADER_CONTENT_TYPE = "Content-Type";
+ public static final String HEADER_GROUP = "HEADER_GROUP";
+ public static final String HTTP_STATUS = "HTTP_STATUS";
+ public static final String HEADER_KEYS = "HEADER_KEYS";
+ public static final String AUTH_TOKEN = "AUTH_TOKEN";
+
+ /**
+ * 1. 기능 : REST API 통신에 사용
+ * 2. 처리 개요 : - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+ * 3. 주의사항
+ *
+ * @param prop Http Adapter 속성 정보
+ * @return 반환 된 Object
+ * @exception Exception 수동 시스템 간 통신 중 발생
+ **/
+ @SuppressWarnings({ "unchecked" })
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+
+ // 2025.04.09 Authorization 헤더값을 프로퍼티(AUTH_TOKEN)에서 지정하여 설정할 수 있도록 수정
+ // 2025.05.29 프로퍼티 그룹 AUTH_TOKEN이 없을때 Null Point Exception 발생하여 수정
+ String bizCode = "";
+ String authToken = "";
+ try {
+ Properties authProp = PropManager.getInstance().getProperties(AUTH_TOKEN); //Authorization
+ bizCode = vo.getAdapterGroupName().substring(1, 4);
+ authToken = authProp.getProperty(bizCode, "");
+ } catch (Exception e) {
+ logger.debug("Property Group AUTH_TOKEN is not Exist !!");
+ }
+
+ logger.debug("authToken :::::::::::::::::::::::::::::::::::" + authToken);
+
+ String headerGroupName = prop.getProperty(HEADER_GROUP);
+ String relayResponseHeaderKeys = prop.getProperty(HEADER_KEYS, "");
+ boolean useAdapterToken = StringUtils.equalsIgnoreCase(prop.getProperty("ADAPTER_TOKEN_USE_YN", "N"), "Y");
+
+ boolean useForwardProxy = StringUtils.equalsIgnoreCase(prop.getProperty("FORWARD_PROXY_USE_YN", "N"), "Y");
+ String forwardProxyUrl = prop.getProperty("FORWARD_PROXY_URL");
+
+ // ex) $.dataHeader.GW_RSLT_CD
+ String tokenErrorCodeKey = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_KEY");
+ String tokenErrorCodeValues = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_VALUES");
+ String tokenErrorHttpStatusCode = prop.getProperty("ADAPTER_TOKEN_ERROR_HTTP_STATUS_CODE"); // 200 or 400번대
+
+ // 레이아웃 메시지 타입 REST URL 추출 시 활용. Default JSON
+ String messageType = prop.getProperty("MESSAGE_TYPE", MessageType.JSON);
+ String inboundMethod = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_METHOD, "POST");
+
+ /**
+ * @formatter:off
+ * TSEAIHE02.RESTOPTION 정보 => JSON 형태로 구성
+ * - type : simpleRequest, variableUrlRequest
+ * - extraPath : 어댑터 프로퍼티 URL에 추가될 HTTP REST URL
+ * - method : get, delete, post, put
+ * - contentType: application/json(default), application/x-www-form-urlencoded
+ * - adapterTokenUseYn: Y, N(default)
+ * ex)
+ * {"type":"simpleRequest","extraPath":"v2.0/accout/balance","method":"post"}
+ * @formatter:on
+ */
+
+ String restOptionData = tempProp.getProperty(REST_OPTION);
+
+ JSONObject restOptionObject = parseJson(restOptionData);
+ if (restOptionObject == null) {
+ throw new Exception("OptionData parsing result is NULL");
+ }
+
+ String rmethod = (String) restOptionObject.getOrDefault("method", inboundMethod);
+ String contentType = (String) restOptionObject.getOrDefault("contentType", "application/json");
+ String adapterTokenUseYn = (String) restOptionObject.get("adapterTokenUseYn");
+ if (StringUtils.isNotBlank(adapterTokenUseYn)) { // interface 에 설정된게 우선한다.
+ useAdapterToken = StringUtils.equalsIgnoreCase(adapterTokenUseYn, "Y");
+ }
+
+ HttpClient mclient = this.client;
+ String sendData = "";
+ if (data instanceof String) {
+ sendData = (String) data;
+ } else if (data instanceof byte[]) {
+ sendData = new String((byte[]) data, vo.getEncode());
+ }
+
+ ////mclient.getParams().setContentCharset(vo.getEncode());
+
+ JSONObject dataObject = null;
+ Object httpHeader = null;
+ Object dataContent = null;
+
+ if (MessageType.JSON.equals(messageType)) {
+
+ Object parsed = parseJsonGeneric(sendData);
+
+ if(parsed instanceof JSONObject) {
+ dataObject = parseJson(sendData);
+ if (dataObject != null && StringUtils.isNotBlank(headerGroupName)) {
+ httpHeader = dataObject.get(headerGroupName);
+ dataObject.remove(headerGroupName);
+ }
+
+ dataContent = dataObject;
+ if (dataObject.containsKey("innerList")) {
+ JSONArray innerList = (JSONArray) dataObject.get("innerList");
+ dataContent = innerList;
+ }
+ }
+ }
+
+// if (MessageType.JSON.equals(messageType)) {
+// dataObject = parseJson(sendData);
+// if (dataObject != null && StringUtils.isNotBlank(headerGroupName)) {
+// httpHeader = dataObject.get(headerGroupName);
+// dataObject.remove(headerGroupName);
+// }
+// }
+
+ logger.debug("HttpClientAdapterServiceRest] dataObject1 = [" + dataObject + "]");
+
+ // interface 에 설정된게 우선한다.
+ String uri = null;
+ if (dataObject == null) {
+ uri = changeUrl(messageType, vo.getUrl(), restOptionData, sendData);
+ } else {
+ uri = changeUrl(messageType, vo.getUrl(), restOptionData, dataObject);
+ }
+
+ logger.debug("HttpClientAdapterServiceRest] dataObject2 = [" + dataObject + "]");
+
+// ////if (vo.getConnectionTimeout() != 0) {
+// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(vo.getConnectionTimeout());
+// }
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL=[" + vo.getUrl() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") PARAMETER_NAME=[" + vo.getParameterName() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") ENCODE=[" + vo.getEncode() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") RESPONSE_TYPE=[" + vo.getResponseType() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL_ENCODE_YN=[" + vo.getUrlEncodeYn() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") CONNECTION_TIMEOUT=[" + vo.getConnectionTimeout() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") REST_OPTION=[" + restOptionData + "] ");
+ }
+
+ HttpUriRequestBase method = null;
+
+
+ // 메소드 타입에 따라 HttpRequestBase 인스턴스 생성
+ switch (HttpMethodType.getValue(rmethod)) {
+ case GET:
+ method = new HttpGet(uri);
+ break;
+ case DELETE:
+ method = new HttpDelete(uri);
+ break;
+ case POST:
+ method = new HttpPost(uri);
+ break;
+ case PUT:
+ method = new HttpPut(uri);
+ break;
+ default:
+ method = new HttpGet(uri);
+ break;
+ }
+
+ RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
+
+ if(useForwardProxy) {
+ java.net.URL url = new java.net.URL(forwardProxyUrl);
+
+ // 프로토콜, 호스트, 포트 추출
+ String protocol = url.getProtocol();
+ String host = url.getHost();
+ int port = url.getPort();
+ HttpHost proxy = new HttpHost(protocol,host, port);
+ requestConfigBuilder.setProxy(proxy);
+ }
+
+ configureHttpClient(requestConfigBuilder, vo, method);
+
+ switch (HttpMethodType.getValue(rmethod)) {
+ case GET:
+ case DELETE:
+ HashMap h = getParameters(dataObject);
+ URIBuilder uriBuilder = new URIBuilder(uri);
+ for (Map.Entry entry : h.entrySet()) {
+ uriBuilder.addParameter(entry.getKey(), entry.getValue());
+ }
+ URI fullUri = uriBuilder.build();
+ if (method instanceof HttpGet) {
+ ((HttpGet) method).setUri(fullUri);
+ } else if (method instanceof HttpDelete) {
+ ((HttpDelete) method).setUri(fullUri);
+ }
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceRest] (get Method) QueryString = [" + fullUri.getQuery() + "]");
+ }
+ break;
+ case PUT:
+ case POST:
+// assignPostBody(dataObject, contentType, vo.getEncode(), method);
+ assignPostBody(dataContent, contentType, vo.getEncode(), method);
+ break;
+ default:
+ break;
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") method.getParams()=["
+ + method.getEntity() + "] ");
+ }
+
+ OAuth2AccessTokenVO accessToken = null;
+ if (useAdapterToken) {
+ AccessTokenManagerByDB tokenManager = AccessTokenManagerByDB.getInstance();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.getAccessTokenVO(vo.getAdapterGroupName());
+
+ // 토큰이 없거나 만료 됐으면 재발급
+ if (accessToken == null || accessToken.isExpired()) {
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop,
+ oldToken);
+ }
+
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") TOKEN = ["
+ + accessToken + "]");
+ }
+
+ setAuthHeaders(method, accessToken);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName()
+ + ") RequestHeader [Authorization=" + method.getHeader("Authorization") + "]");
+ }
+ }
+
+ if(!StringUtils.isBlank(authToken)) {
+ setAuthHeaders(method, authToken);
+ }
+
+ // 전달 header 셋팅
+ // Adapter 레벨 header 보다 data로 넘어온 httpHeader를 우선 적용(header명이 같다면 덮어씀)
+ assignRequestHeaders(method, httpHeader);
+
+ int status = -1;
+
+ try {
+ byte[] responseMessage = null;
+ Header[] responseHeaders;
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ if (dataObject != null) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = ["
+ + dataObject.toJSONString() + "]");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(dataObject.toJSONString()));
+ } else {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = [" + sendData
+ + "]");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(sendData));
+ }
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [" + sendData + "]" + CommonLib.getDumpMessage(sendData));
+ }
+
+ String uuid = tempProp.getProperty(TransactionContextKeys.TRANSACTION_UUID);
+ HttpContext context = new BasicHttpContext();
+ context.setAttribute(TransactionContextKeys.TRANSACTION_UUID, uuid);
+ context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME, vo.getAdapterGroupName());
+ context.setAttribute(HttpClientAdapterServiceKey.ADAPTER_NAME, vo.getAdapterName());
+ Integer logProcessNo = (Integer) tempProp.get(HttpClientAdapterServiceKey.LOG_PROCESS_NO);
+ if (logProcessNo != null && logProcessNo > 0) {
+ context.setAttribute(HttpClientAdapterServiceKey.LOG_PROCESS_NO, logProcessNo);
+ }
+
+ try {
+ if (logger.isDebug()) {
+ logger.debug("[method getName]" + method.getMethod());
+ logger.debug("[method getEntity]" + method.getEntity());
+ logger.debug("[method getRequestHeaders]" + method.getHeaders().toString());
+ logger.debug("[method getURI]" + method.getPath());
+ }
+ try (CloseableHttpResponse response = (CloseableHttpResponse) mclient.execute(method, context)) {
+ status = response.getCode();
+
+ responseMessage = EntityUtils.toByteArray(response.getEntity());
+ responseHeaders = response.getHeaders();
+
+ if (logger.isDebug()) {
+ logger.debug("[received status]" + status);
+ logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = [" + responseMessage + "]");
+ }
+ }
+ } catch (ConnectException e) {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType());
+ }
+ throw new Exception("excuteMethod java.net.ConnectException = " + e.getMessage());
+ }
+
+ stopWatch.stop();
+
+ /**
+ * @formatter:off
+ * OAuth 토큰 응답 체크(Adapter properties로 설정)
+ * 응답코드에 따라 유효한 토큰 확인(토큰 재발급 여부 확인)
+ * API 서비스 마다 정책이 다름(보통 400대에서 체크하나 200에서도 체크할 수 있음)
+ *
+ * TOKEN_ERROR_CODE_KEY: 응답 json error code key
+ * __ex) $.dataHeader.resultCode
+ * TOKEN_ERROR_CODE_VALUES: 토큰 재발급이 필요한 응답 error codes(ex: O0001,O0002,O0003)
+ * TOKEN_ERROR_HTTP_STATUS_CODE: 보통 400대에서 체크하나 API 제공자에 따라 200에서도 체클할수 있음
+ * ex) TOKEN_ERROR_HTTP_STATUS_CODE = 200
+ * @formatter:on
+ */
+ boolean needReissue = false;
+
+ Properties responseHeaderProp = assignRelayDataToInbound(tempProp, responseHeaders);
+ String responseString = new String(responseMessage, vo.getEncode());
+
+ Map map = new HashMap();
+ tempProp.put(HttpAdapterServiceKey.OUTBOUND_PROPERTY_MAP, map);
+ map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_HEADERS, responseHeaderProp);
+ map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_MESSAGE, responseString);
+ map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_STATUS, status);
+
+ if (status >= 200 && status <= 207) {
+ if (useAdapterToken && StringUtils.equals(tokenErrorHttpStatusCode, "200")) {
+ needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues,
+ vo.getEncode());
+ }
+ } else if (status == 302) {
+ if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) {
+ relayResponseHeaderKeys += ",Location";
+ }
+ } else {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseString);
+// logger.error(errMsg);
+
+ if (status >= 400 && status < 500) {
+ if (useAdapterToken) {
+ needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues,
+ vo.getEncode());
+ }
+
+ if (!needReissue) {
+ throw new Exception(errMsg);
+ }
+ } else {
+
+ throw new Exception(errMsg);
+ }
+ }
+
+ // ----------------------------------------------------------
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceRest] RECV " + vo.getEncode() + "(" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) + "]");
+// logger.debug("HttpClientAdapterServiceRest] RECV MS949 (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, "MS949") + "]");
+// logger.debug("HttpClientAdapterServiceRest] RECV euc-kr (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, "euc-kr") + "]");
+ logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = " + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ if (useAdapterToken) {
+ if (responseMessage == null) {
+ throw new Exception("responseMessage is NULL, HttpStatus=" + status);
+ }
+
+ // OAuth 토큰 재요청 코드 확인
+ if (needReissue) {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] retry access token response code = ["
+ + vo.getResponseType() + "] message = [" + new String(responseMessage, vo.getEncode())
+ + "]");
+ }
+
+ // 토큰 재발급
+ AccessTokenManager tokenManager = AccessTokenManager.getInstance();
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ OAuth2AccessTokenVO newaccessToken = (OAuth2AccessTokenVO) tokenManager
+ .retryAccessTokenVO(vo.getAdapterGroupName(), prop, oldToken);
+ method.setHeader("Authorization", newaccessToken.getAuthorization());
+
+ setAuthHeaders(method, newaccessToken);
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName()
+ + ") RETRY TOKEN = [" + newaccessToken + "]");
+ }
+
+ try (CloseableHttpResponse response = (CloseableHttpResponse) mclient.execute(method)) {
+ status = response.getCode();
+ responseMessage = EntityUtils.toByteArray(response.getEntity());
+
+ if (logger.isDebug()) {
+ logger.debug("[received status]" + status);
+ logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode()) + "]");
+ }
+ }catch (IOException e){
+ throw new Exception("retry excuteMethod Exceptioin = " + e.getMessage());
+ }
+
+
+ if (status == 302) {
+ if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) {
+ relayResponseHeaderKeys += ",Location";
+ }
+ } else {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseMessage);
+ throw new Exception(errMsg);
+ }
+
+ // ----------------------------------------------------------
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] RETRY responseType =" + vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceRest] RETRY RECV " + vo.getEncode() + "("
+ + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode())
+ + "]");
+ logger.debug("HttpClientAdapterServiceRest] RETRY RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+ // ----------------------------------------------------------
+ }
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [" + new String(responseMessage, vo.getEncode()) + "]"
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+
+ return assignResponseHeaders(method, responseMessage, headerGroupName, vo.getEncode(), messageType,
+ relayResponseHeaderKeys, status, responseHeaderProp);
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : "
+ + ste.toString(),
+ ste);
+ }
+ logger.error("HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : "
+ + ste.toString(), ste);
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : "
+ + ce.toString(),
+ ce);
+ }
+ logger.error("HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : "
+ + ce.toString(), ce);
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), e.toString(), e);
+ }
+ logger.error("HttpClientAdapterServiceRest] Exception (" + vo.getAdapterGroupName() + ") : " + e.toString(),
+ e);
+ throw e;
+ } finally {
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+ }
+
+ private Properties assignRelayDataToInbound(Properties prop, Header[] responseHeaders) {
+ Properties headerProp = new Properties();
+ if (responseHeaders == null || responseHeaders.length == 0) {
+ return headerProp;
+ }
+
+ for (Header header : responseHeaders) {
+ headerProp.put(header.getName(), header.getValue());
+ }
+
+ return headerProp;
+ }
+
+ /**
+ * 현재 1단계 레이아웃에만 적용되도록 구현됨.
+ *
+ * @param method
+ * @param responseMessage
+ * @param headerGroupName
+ * @param encode
+ * @param messageType
+ * @param relayHeaderKeys
+ * @return
+ * @throws Exception
+ */
+ @SuppressWarnings("unchecked")
+ private String assignResponseHeaders(HttpUriRequestBase method, byte[] responseMessage, String headerGroupName,
+ String encode, String messageType, String relayHeaderKeys, int status, Properties responseHeaderProp) throws Exception {
+ if (!MessageType.JSON.equals(messageType) || StringUtils.isBlank(headerGroupName)
+ || StringUtils.isBlank(relayHeaderKeys)) {
+ return new String(responseMessage, encode);
+ }
+
+ String[] relayKeyArr = org.springframework.util.StringUtils.tokenizeToStringArray(relayHeaderKeys, ",");
+ JSONObject headerJson = new JSONObject();
+ for (String key : relayKeyArr) {
+ String value = responseHeaderProp.getProperty(key);
+ if (StringUtils.isNotBlank(value)) {
+ headerJson.put(key, value);
+ }
+ }
+
+ headerJson.put(HTTP_STATUS, String.valueOf(status));
+
+ if (headerJson.size() <= 0) {
+ return new String(responseMessage, encode);
+ }
+
+ JSONObject message = null;
+ if (responseMessage == null || responseMessage.length == 0) {
+ message = new JSONObject();
+ } else {
+ message = parseJson(new String(responseMessage, encode));
+ if (message == null) {
+ message = new JSONObject();
+ message.put("Malformed_Response_Message", new String(responseMessage, encode));
+ }
+ }
+
+ if (StringUtils.isNotBlank(headerGroupName) && message != null)
+ message.put(headerGroupName, headerJson);
+ return message.toJSONString();
+ }
+
+ private void setAuthHeaders(HttpUriRequestBase method, String authorization) throws Exception {
+ method.setHeader("Authorization",
+ String.format("%s", authorization));
+ }
+
+ private void setAuthHeaders(HttpUriRequestBase method, OAuth2AccessTokenVO accessToken) throws Exception {
+ method.setHeader("Authorization",
+ String.format("%s %s", AccessTokenVO.BEARER_TYPE, accessToken.getAccessToken()));
+ }
+
+ private boolean checkTokenRetry(byte[] responseMessage, String tokenErrorCodeKey, String tokenErrorCodeValues,
+ String encode) {
+ if (responseMessage == null) {
+ return false;
+ }
+
+ if (StringUtils.isBlank(tokenErrorCodeKey)) {
+ return false;
+ }
+
+ if (StringUtils.isBlank(tokenErrorCodeValues)) {
+ return false;
+ }
+
+ try {
+ DocumentContext jsonContext = JsonPath.parse(new String(responseMessage, encode));
+ String responseCode = jsonContext.read(tokenErrorCodeKey);
+ if (StringUtils.isBlank(responseCode)) {
+ return false;
+ }
+
+ String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenErrorCodeValues, ",");
+ return ArrayUtils.contains(arr, responseCode);
+ } catch (Exception e) {
+ logger.error("HttpClientAdapterServiceRest] checkTokenRetry error=" + e.getMessage());
+ }
+
+ return false;
+ }
+
+ private void assignRequestHeaders(HttpUriRequestBase method, Object httpHeader) {
+ if (httpHeader == null) {
+ return;
+ }
+
+ if (httpHeader instanceof JSONObject) {
+ JSONObject jsonObject = (JSONObject) httpHeader;
+ for (Object key : jsonObject.keySet()) {
+ Object obj = jsonObject.get(key);
+ if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) {
+ continue;
+ }
+
+ method.setHeader((String) key, (String) obj);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Request Header :" + (String) key + "=[" + (String) obj + "]");
+ }
+
+ }
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void assignPostBody(Object eaiBody, String contentType, String charset, HttpUriRequestBase method) {
+ if (eaiBody == null) {
+ return;
+ }
+
+ if (StringUtils.contains(contentType, "application/x-www-form-urlencoded")) {
+ if (eaiBody instanceof JSONObject) {
+ List params = new ArrayList<>();
+ JSONObject jsonObject = (JSONObject) eaiBody;
+ for (Object key : jsonObject.keySet()) {
+ params.add(new BasicNameValuePair((String) key, (String) jsonObject.get(key)));
+ }
+
+ UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);
+ method.setEntity(entity);
+ }
+ } else {
+ ContentType contentTypeObj = ContentType.create(contentType, charset);
+
+ // 요청 본문을 StringEntity 객체로 생성
+ StringEntity entity = new StringEntity(eaiBody.toString(), contentTypeObj);
+
+ // 요청에 본문 추가
+ method.setEntity(entity);
+ }
+ }
+
+ private HashMap getParameters(Object message) throws Exception {
+
+ HashMap result = new HashMap();
+
+ if (message != null) {
+ if (message instanceof JSONObject) {
+ JSONObject jsonObject = (JSONObject) message;
+ for (Object key : jsonObject.keySet()) {
+ Object obj = jsonObject.get(key);
+ if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) {
+ continue;
+ }
+ result.put((String) key, getStringValue(obj));
+ }
+ } else {
+ String[] messages = ((String) message).split("&");
+ String[] data = null;
+
+ for (int i = 0; i < messages.length; i++) {
+ data = messages[i].split("=", 2);
+ if (data.length == 2) {
+ result.put(data[0], data[1]);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public String getStringValue(Object obj) {
+ if (obj == null) {
+ return null;
+ }
+
+ if (obj instanceof String) {
+ return (String) obj;
+ } else if (obj instanceof Long) {
+ return Long.toString((Long) obj);
+ } else if (obj instanceof BigDecimal) {
+ return ((BigDecimal) obj).toPlainString();
+ } else {
+ return (String) obj;
+ }
+ }
+
+ public static Object parseJsonGeneric(String jsonData) {
+ if (StringUtils.isBlank(jsonData)) {
+ return null;
+ }
+
+ try {
+ JSONParser parser = new JSONParser();
+ Object parsedObj = parser.parse(jsonData);
+ return parsedObj;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private JSONObject parseJson(String message) throws Exception {
+ if (message == null) {
+ return null;
+ }
+
+ return (JSONObject) JSONValue.parse(message);
+ }
+
+ private Document convertXmlDocument(String message) throws Exception {
+ SAXReader builder = new SAXReader();
+ Document document = builder.read(new StringReader(message));
+ return document;
+ }
+
+ @SuppressWarnings("deprecation")
+ private String changeUrl(String messageType, String url, String restOption, Object sendData) {
+ if ((MessageType.JSON.equals(messageType) || MessageType.XML.equals(messageType))) {
+ try {
+ if (StringUtils.isBlank(restOption)) {
+ return url;
+ }
+ List urlVariableList = new ArrayList();
+ JSONObject restOptionObject = parseJson(restOption);
+
+ if (restOptionObject == null)
+ throw new Exception("restOption is NULL");
+
+ String type = (String) restOptionObject.get("type");
+ String requestExtraPath = (String) restOptionObject.get("extraPath");
+ url = getUrl(url, requestExtraPath);
+ if (TYPE_VARIABLE_URL_REQUEST.equals(type)) {
+ Pattern p = Pattern.compile("\\{(.*?)\\}");
+ Matcher m = p.matcher(requestExtraPath);
+ List uriVariables = new ArrayList<>();
+ while(m.find()) {
+ String fieldName = m.group(1);
+ uriVariables.add(fieldName);
+ }
+ if (MessageType.JSON.equals(messageType)) {
+ JSONObject jsonObject;
+ if (sendData instanceof JSONObject) {
+ jsonObject = (JSONObject) sendData;
+ } else {
+ jsonObject = (JSONObject) JSONValue.parse((String) sendData);
+ }
+ for (Object tempObject : uriVariables) {
+ String urlVaribleId = (String) tempObject;
+ String uriVariable = (String) jsonObject.get(urlVaribleId);
+ urlVariableList.add(uriVariable);
+ jsonObject.remove(urlVaribleId);
+ }
+ } else if (MessageType.XML.equals(messageType)) {
+ Document doc;
+ if (sendData instanceof Document) {
+ doc = (Document) sendData;
+ } else {
+ doc = convertXmlDocument((String) sendData);
+ }
+ for (Object tempObject : uriVariables) {
+ String urlVaribleId = (String) tempObject;
+ Element element = (Element) doc.selectSingleNode("//" + urlVaribleId);
+ urlVariableList.add(element.getText());
+ if (doc.getRootElement() == element) {
+ doc = null;
+ } else {
+ element.getParent().remove(element);
+ }
+ }
+ }
+ if (urlVariableList.size() > 0) {
+ UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).build();
+ Object[] urls = urlVariableList.toArray();
+ url = uriComponents.expand(urls).toUriString();
+ logger.debug("HttpClientAdapterServiceRest] after extand url=[" + url + "] ");
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Failed to change url", e);
+ }
+ }
+ return url;
+ }
+
+ private String getUrl(String baseUrl, String extraPath) {
+ if (StringUtils.isBlank(extraPath)) {
+ return baseUrl;
+ }
+
+ if (StringUtils.contains(extraPath, "http://") || StringUtils.contains(extraPath, "https://")) {
+ return extraPath;
+ }
+
+ String targetUrl = baseUrl;
+ if (!targetUrl.endsWith("/")) {
+ targetUrl += "/";
+ }
+ if (extraPath.startsWith("/")) {
+ targetUrl += extraPath.substring(1);
+ } else {
+ targetUrl += extraPath;
+ }
+
+ logger.debug("HttpClientAdapterServiceRest] after concatenate url=[" + targetUrl + "] ");
+ return targetUrl;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceAnnounce.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceAnnounce.java
new file mode 100644
index 0000000..7c284de
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceAnnounce.java
@@ -0,0 +1,183 @@
+//
+//package com.eactive.eai.adapter.http.client.impl;
+//
+//import com.eactive.eai.adapter.http.HttpMemoryLogger;
+//import com.eactive.eai.adapter.http.HttpStatusException;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+//import com.eactive.eai.common.exception.ExceptionUtil;
+//import com.eactive.eai.common.util.CommonLib;
+//import org.apache.commons.httpclient.HttpClient;
+//import org.apache.commons.httpclient.HttpStatus;
+//import org.apache.commons.httpclient.HttpVersion;
+//import org.apache.commons.httpclient.methods.PostMethod;
+//
+//import java.net.ConnectException;
+//import java.net.SocketTimeoutException;
+//import java.util.Properties;
+//
+//
+///**
+//* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+//* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+//* 2. 처리 개요 :
+//* * - 2009.11.24 retry 로직 제거 : 요청
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
+//* @since :
+//
+//*/
+//public class HttpClientAdapterServiceAnnounce extends HttpClientAdapterServiceSupport{
+//
+// /**
+// * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+// * 2. 처리 개요 :
+// * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+// * 3. 주의사항
+// *
+// * @param prop Http Adapter 속성 정보
+// * @param message 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// public Object execute(Properties prop, byte[] data, Properties tempProp) throws Exception {
+//
+// HttpClientAdapterVO vo = super.setting(prop, tempProp);
+//
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceAnnounce] SEND (" + vo.getMethod() + ") ");
+// }
+// PostMethod method = new PostMethod(vo.getUrl());
+// if (vo.getTimeout() > -1) {
+// method.getParams().setSoTimeout(vo.getTimeout());
+// }
+// HttpClient mclient = this.client;
+// if ( vo.getConnectionTimeout() != 0){
+// mclient.getParams().setParameter("http.connection.timeout", vo.getConnectionTimeout());
+// }
+// method.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
+//
+// // Announce Data Size : 113 Bytes
+// int annMinSize = 113;
+//
+// String srvCode = "";
+// String recipient = "";
+// String body = "";
+// String inurl = "";
+//
+// if (data.length >= annMinSize) {
+// if (vo.getEncode() != null && vo.getEncode().length() > 0) {
+// if (logger.isDebug()) {
+// logger.debug("HttpClientAdapterServiceAnnounce] ENCODE(" + vo.getEncode() + ") ");
+// }
+// srvCode = new String(data, 0, 6, vo.getEncode());
+// recipient = new String(data, 6, 7, vo.getEncode());
+// body = new String(data, 13, 100, vo.getEncode());
+// if (data.length > 153) {
+// inurl = new String(data, 113, data.length - annMinSize, vo.getEncode());
+// }
+// } else {
+// srvCode = new String(data, 0, 6);
+// recipient = new String(data, 6, 7);
+// body = new String(data, 13, 100);
+// if (data.length > 153) {
+// inurl = new String(data, 113, data.length - annMinSize);
+// }
+// }
+// method.addParameter("SRV_CODE", srvCode);
+// method.addParameter("RECIPIENT", recipient);
+// method.addParameter("BODY", body);
+// if (data.length > 153) {
+// method.addParameter("URL", inurl);
+// }
+//
+// } else {
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServiceAnnounce] Invalid Data Length (" + data.length + ") < " + annMinSize);
+// }
+// throw new Exception("HttpClientAdapterServiceAnnounce Error : MessageSize(" + (data.length) + " Bytes) too small < " + annMinSize);
+// }
+//
+// int status = -1;
+//
+// try {
+// if (vo.getTraceLevel() >= 3){
+// if (data.length > 153){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),
+// "[URL]"+ inurl + "\n"
+// + "[SRV_CODE]" + srvCode + "\n"
+// + "[RECIPIENT]" + recipient + "\n"
+// + "[BODY]" + body + "\n"
+// + "SEND ["+new String(data)+"]"+CommonLib.getDumpMessage(data) +"\n"
+// );
+// }else{
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),
+// "[SRV_CODE]" + srvCode + "\n"
+// + "[RECIPIENT]" + recipient + "\n"
+// + "[BODY]" + body + "\n"
+// + "SEND ["+new String(data)+"]"+CommonLib.getDumpMessage(data) +"\n"
+// );
+//
+// }
+// }
+// //mclient.getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
+// //mclient.getParams().setContentCharset("EUC_KR");
+// status = mclient.executeMethod(method);
+//
+// //status 200(정상) 이외에는 error 처리
+// if (status !=200){
+// try{
+// logger.error("HttpClientAdapterServiceAnnounce] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
+// }catch(Exception e){
+// logger.error(e);
+// }
+// throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
+// }
+// byte[] responseMessage = method.getResponseBody();
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage) );
+// }
+// return responseMessage;
+//
+// } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceAnnounce] SocketTimeoutException : " + ste.toString() ,ste);
+// }
+// if (logger.isError()){
+// logger.error("HttpClientAdapterServiceAnnounce] SocketTimeoutException : " + ste.toString() ,ste);
+// }
+// throw ste;
+// } catch(ConnectException ce) {
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceAnnounce] Connection Exception : " + ce.toString() ,ce);
+// }
+// if (logger.isError()){
+// logger.error("HttpClientAdapterServiceAnnounce] Connection Exception : " + ce.toString() ,ce);
+// }
+// throw ce;
+// } catch(Exception e) {
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceAnnounce] Exception : " + e.toString() ,e);
+// }
+// if (logger.isError()){
+// logger.error("HttpClientAdapterServiceAnnounce] Exception : " + e.toString() ,e);
+// }
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if (status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if (logger.isDebug()) {
+// logger.debug(resMsg);
+// }
+// }
+// }
+//
+// }
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceBody.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceBody.java
new file mode 100644
index 0000000..011bb38
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceBody.java
@@ -0,0 +1,160 @@
+package com.eactive.eai.adapter.http.client.impl;
+
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.HttpVersion;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.CommonLib;
+
+public class HttpClientAdapterServiceBody extends HttpClientAdapterServiceSupport {
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+
+ boolean isAsync = false;
+ if (RESPONSE_TYPE_ASYNC.equals(vo.getResponseType())) {
+ isAsync = true;
+ }
+ PostMethod method = new PostMethod(vo.getUrl());
+ HttpClient mclient = this.client;
+
+ configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
+
+ String sendData = "";
+ if (data instanceof String) {
+ sendData = (String) data;
+ } else if (data instanceof byte[]) {
+ sendData = new String((byte[]) data, vo.getEncode());
+ }
+
+ mclient.getParams().setContentCharset(vo.getEncode());
+
+ String contentTypeValue = null;
+ if (StringUtils.isNotEmpty(vo.getContentType())) {
+ if (StringUtils.isNotEmpty(vo.getEncode())) {
+ contentTypeValue = vo.getContentType() + "; charset=" + vo.getEncode();
+ } else {
+ contentTypeValue = vo.getContentType();
+ }
+ method.setRequestHeader(CONTENT_TYPE_KEY, contentTypeValue);
+ }
+ if (vo.getAdapterHeaders() != null) {
+ for (String key : vo.getAdapterHeaders().keySet()) {
+ method.addRequestHeader(key, vo.getAdapterHeaders().get(key));
+ }
+ }
+ if (logger.isInfoEnabled()) {
+ logger.info("HttpClientAdapterServiceBody] " + CONTENT_TYPE_KEY + "(" + contentTypeValue + ")");
+ }
+
+ if ("Y".equals(vo.getUrlEncodeYn())) {
+ sendData = java.net.URLEncoder.encode(sendData);
+ }
+
+ method.setRequestBody(sendData);
+
+ int status = -1;
+
+ try {
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug(
+ "HttpClientAdapterServiceBody] SEND (" + vo.getAdapterGroupName() + ") = [" + sendData + "]");
+ logger.debug("HttpClientAdapterServiceBody] SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(sendData));
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [" + sendData + "]" + CommonLib.getDumpMessage(sendData));
+ }
+ if (vo.getUrl() != null && vo.getUrl().startsWith("https")) {
+ Protocol.registerProtocol("https",
+ new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+ }
+ status = mclient.executeMethod(method);
+ stopWatch.stop();
+
+ String responseCharSet = getResponseCharSet(method.getResponseCharSet(), vo.getAdapterGroupName());
+
+ byte[] responseMessage = method.getResponseBody();
+ // status 200(정상) 이외에는 error 처리
+ if (status != 200) {
+ logger.error("HttpClientAdapterServiceBody] receive status[" + status + "] data["
+ + new String(responseMessage) + "]");
+ throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="
+ + vo.getAdapterGroupName() + "." + vo.getAdapterName(), status);
+ }
+
+ if (isAsync && stopWatch.getTime() > vo.getSlowTranTime() && (logger.isWarn())) {
+ logger.warn("HttpClientAdapterServiceBody] URL[" + vo.getUrl() + "] lazy async response time = "
+ + stopWatch.toString() + " responseMessage=" + new String(responseMessage, responseCharSet));
+
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [" + new String(responseMessage, vo.getEncode()) + "]"
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ return responseMessage;
+
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceBody] SocketTimeoutException : " + ste.toString(), ste);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceBody] SocketTimeoutException : " + ste.toString(), ste);
+ }
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceBody] Connection Exception : " + ce.toString(), ce);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceBody] Connection Exception : " + ce.toString(), ce);
+ }
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceBody] Exception : " + e.toString(), e);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceBody] Exception : " + e.toString(), e);
+ }
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceBypass.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceBypass.java
new file mode 100644
index 0000000..5a3db4d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceBypass.java
@@ -0,0 +1,667 @@
+package com.eactive.eai.adapter.http.client.impl;
+
+import java.io.ByteArrayInputStream;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import com.eactive.eai.adapter.http.EntityEnclosingDeleteMethod;
+import com.eactive.eai.adapter.http.EntityEnclosingGetMethod;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpMethodType;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
+import com.eactive.eai.adapter.http.dynamic.impl.HttpAdapterServiceBypass;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.CommonLib;
+import com.jayway.jsonpath.DocumentContext;
+import com.jayway.jsonpath.JsonPath;
+import com.openbanking.eai.common.token.AccessTokenManager;
+import com.openbanking.eai.common.token.AccessTokenVO;
+import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
+
+public class HttpClientAdapterServiceBypass extends HttpClientAdapterServiceSupport
+ implements HttpClientAdapterServiceKey {
+ public static final String TYPE_BYPASS_REQUEST = "bypassRequest";
+ public static final String REST_OPTION = "REST_OPTION";
+
+ protected boolean doSendUrlFragment = true;
+ protected boolean doHandleCompression = false;
+ protected boolean doForwardIP = true;
+
+ @SuppressWarnings({ "deprecation", "unchecked" })
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+
+ boolean useAdapterToken = StringUtils.equalsIgnoreCase(prop.getProperty("ADAPTER_TOKEN_USE_YN", "N"), "Y");
+
+ // ex) $.dataHeader.GW_RSLT_CD
+ String tokenErrorCodeKey = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_KEY");
+ String tokenErrorCodeValues = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_VALUES");
+ String tokenErrorHttpStatusCode = prop.getProperty("ADAPTER_TOKEN_ERROR_HTTP_STATUS_CODE"); // 200 or 400번대
+
+ /**
+ * @formatter:off
+ * TSEAIHE02.RESTOPTION 정보 => JSON 형태로 구성
+ * - type : simpleRequest, variableUrlRequest
+ * - extraPath : 어댑터 프로퍼티 URL에 추가될 HTTP REST URL
+ * - method : get, delete, post, put
+ * - contentType : application/json, application/x-www-form-urlencoded
+ * - adapterTokenUseYn: Y, N(default)
+ * ex)
+ * {"type":"variableUrlRequest","extraPath":"/aaa/{userId}","uriVariables":["userId"]}
+ * @formatter:on
+ */
+ String restOptionData = tempProp.getProperty(REST_OPTION, "{}");
+
+ JSONObject restOptionObject = parseJson(restOptionData);
+
+ String adapterTokenUseYn = (String) restOptionObject.get("adapterTokenUseYn");
+ if (StringUtils.isNotBlank(adapterTokenUseYn)) { // interface 에 설정된게 우선한다.
+ useAdapterToken = StringUtils.equalsIgnoreCase(adapterTokenUseYn, "Y");
+ }
+
+ String inboundMethod = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_METHOD, "POST");
+ String inboundRewritePath = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_REWRITE_PATH, "");
+ String inboundQueryString = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_QUERY_STRING, "");
+ Properties inboundHeaders = (Properties) tempProp.get(HttpAdapterServiceKey.INBOUND_HEADER);
+ Map inboundPathVariables = (Map) tempProp
+ .get(HttpAdapterServiceKey.INBOUND_PATH_VARIABLES);
+
+ String restMethod = (String) restOptionObject.get("method");
+ if (StringUtils.isBlank(restMethod)) {
+ restMethod = inboundMethod;
+ }
+
+ String url = getRewriteUrl(vo, inboundRewritePath, inboundQueryString, restOptionObject, inboundPathVariables);
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceBypass] url = [" + url + "]");
+ }
+
+ HttpClient mclient = this.client;
+
+ HttpMethodBase method = generateMethod(restMethod, url);
+
+ assignRequestHeaders(method, inboundHeaders, tempProp);
+
+ if (hasBody(data, inboundHeaders)) {
+ if (data instanceof byte[]) {
+ ((EntityEnclosingMethod) method).setRequestBody(new ByteArrayInputStream((byte[]) data));
+ } else if (data instanceof String) {
+ ((EntityEnclosingMethod) method).setRequestBody((String) data);
+ }
+ }
+
+ String contentType = (String) restOptionObject.get("contentType");
+ if (StringUtils.isBlank(contentType) && inboundHeaders != null) {
+ contentType = getIgnoreCaseProp(inboundHeaders, HttpHeaders.CONTENT_TYPE);
+ contentType = StringUtils.substringBefore(contentType, ";");
+ }
+ configureHttpClient(mclient, method, vo, url, contentType);
+
+ OAuth2AccessTokenVO accessToken = null;
+ if (useAdapterToken) {
+ AccessTokenManager tokenManager = AccessTokenManager.getInstance();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.getAccessTokenVO(vo.getAdapterGroupName());
+
+ // 토큰이 없거나 만료 됐으면 재발급
+ if (accessToken == null || accessToken.isExpired()) {
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop,
+ oldToken);
+ }
+
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceBypass] SEND (" + vo.getAdapterGroupName() + ") TOKEN = ["
+ + accessToken + "]");
+ }
+
+ setAuthHeaders(method, accessToken);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceBypass] SEND (" + vo.getAdapterGroupName()
+ + ") RequestHeader [Authorization=" + method.getRequestHeader("Authorization") + "]");
+ }
+ }
+
+ int status = -1;
+
+ try {
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ byte[] responseMessage = null;
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [Bypass Request..]" + CommonLib.getDumpMessage(data));
+ }
+ try {
+ if (logger.isDebug()) {
+ logger.debug("[method getName]" + method.getName());
+ logger.debug("[method getRequestCharSet]" + method.getRequestCharSet());
+ logger.debug("[method getRequestHeaders]" + method.getRequestHeaders().toString());
+ logger.debug("[method getQueryString]" + method.getQueryString());
+ logger.debug("[method getParams]" + method.getParams().toString());
+ logger.debug("[method getURI]" + method.getURI());
+ }
+ if (vo.getUrl() != null && vo.getUrl().startsWith("https")) {
+ Protocol.registerProtocol("https",
+ new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+ }
+ status = mclient.executeMethod(method);
+ if (logger.isDebug()) {
+ logger.debug("[received status]" + status);
+ }
+ } catch (ConnectException e) {
+ responseMessage = method.getResponseBody();
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceBypass] responseType =" + vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceBypass] RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+ throw new Exception("excuteMethod java.net.ConnectException = " + e.getMessage());
+ }
+
+ stopWatch.stop();
+
+ /**
+ * @formatter:off
+ * OAuth 토큰 응답 체크(Adapter properties로 설정)
+ * 응답코드에 따라 유효한 토큰 확인(토큰 재발급 여부 확인)
+ * API 서비스 마다 정책이 다름(보통 400대에서 체크하나 200에서도 체크할 수 있음)
+ *
+ * TOKEN_ERROR_CODE_KEY: 응답 json error code key
+ * __ex) $.dataHeader.resultCode
+ * TOKEN_ERROR_CODE_VALUES: 토큰 재발급이 필요한 응답 error codes(ex: O0001,O0002,O0003)
+ * TOKEN_ERROR_HTTP_STATUS_CODE: 보통 400대에서 체크하나 API 제공자에 따라 200에서도 체클할수 있음
+ * ex) TOKEN_ERROR_HTTP_STATUS_CODE = 200
+ * @formatter:on
+ */
+ boolean needReissue = false;
+
+ if (status == 200) {
+ responseMessage = method.getResponseBody();
+ if (useAdapterToken && StringUtils.equals(tokenErrorHttpStatusCode, "200")) {
+ needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues,
+ vo.getEncode());
+ }
+ } else if (status >= 400 && status < 500) {
+ responseMessage = method.getResponseBody();
+ if (useAdapterToken) {
+ needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues,
+ vo.getEncode());
+ }
+
+ if (!needReissue) {
+ // body 값이 없을때만 exception 처리하고, body가 있으면 bypass 한다.
+ if (responseMessage == null || responseMessage.length == 0) {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), url, method, responseMessage);
+ throw new Exception(errMsg);
+ }
+ }
+ } else {
+ responseMessage = method.getResponseBody();
+ // body 값이 없을때만 exception 처리하고, body가 있으면 bypass 한다.
+ if (responseMessage == null || responseMessage.length == 0) {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), url, method, responseMessage);
+ throw new Exception(errMsg);
+ }
+ }
+
+ if (useAdapterToken) {
+ if (responseMessage == null) {
+ throw new Exception("responseMessage is NULL, HttpStatus=" + status);
+ }
+
+ // OAuth 토큰 재요청 코드 확인
+ if (needReissue) {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceBypass] retry access token response code = ["
+ + vo.getResponseType() + "] message = [" + new String(responseMessage, vo.getEncode())
+ + "]");
+ }
+
+ // 토큰 재발급
+ AccessTokenManager tokenManager = AccessTokenManager.getInstance();
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ OAuth2AccessTokenVO newAccessToken = (OAuth2AccessTokenVO) tokenManager
+ .retryAccessTokenVO(vo.getAdapterGroupName(), prop, oldToken);
+ method.setRequestHeader("Authorization", newAccessToken.getAuthorization());
+
+ setAuthHeaders(method, newAccessToken);
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceBypass] SEND (" + vo.getAdapterGroupName()
+ + ") RETRY TOKEN = [" + newAccessToken + "]");
+ }
+
+ try {
+ status = mclient.executeMethod(method);
+ } catch (ConnectException e) {
+ throw new Exception("retry excuteMethod Exceptioin = " + e.getMessage());
+ }
+
+ if (status == 200) {
+ responseMessage = method.getResponseBody();
+ } else {
+ responseMessage = method.getResponseBody();
+ // body 값이 없을때만 exception 처리하고, body가 있으면 bypass 한다.
+ if (responseMessage == null || responseMessage.length == 0) {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), url, method,
+ responseMessage);
+ throw new Exception(errMsg);
+ }
+ }
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceBypass] RETRY responseType =" + vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceBypass] RETRY RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+ }
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [Bypass Request..]" + CommonLib.getDumpMessage(responseMessage));
+ }
+ assignRelayDataToInbound(tempProp, method.getResponseHeaders(), status);
+ return responseMessage;
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceBypass] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : "
+ + ste.toString(),
+ ste);
+ }
+ logger.error("HttpClientAdapterServiceBypass] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : "
+ + ste.toString(), ste);
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceBypass] Connection Exception (" + vo.getAdapterGroupName() + ") : "
+ + ce.toString(),
+ ce);
+ }
+ logger.error("HttpClientAdapterServiceBypass] Connection Exception (" + vo.getAdapterGroupName() + ") : "
+ + ce.toString(), ce);
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), e.toString(), e);
+ }
+ logger.error(
+ "HttpClientAdapterServiceBypass] Exception (" + vo.getAdapterGroupName() + ") : " + e.toString(),
+ e);
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+ }
+
+ private boolean hasBody(Object data, Properties inboundHeaders) {
+ if (data == null) {
+ return false;
+ }
+
+// // spec: RFC 2616, sec 4.3
+// String contentLength = getIgnoreCaseProp(inboundHeaders, HttpHeaders.CONTENT_LENGTH);
+// String transferEncoding = getIgnoreCaseProp(inboundHeaders, HttpHeaders.TRANSFER_ENCODING);
+// if (StringUtils.isNotBlank(contentLength) || StringUtils.isNotBlank(transferEncoding)) {
+// return true;
+// }
+// return false;
+
+ // client adapter 단독으로 사용 가능하게 수정
+ return true;
+ }
+
+ private HttpMethodBase generateMethod(String restMethod, String url) {
+ HttpMethodBase method = null;
+ switch (HttpMethodType.getValue(restMethod)) {
+ case GET:
+ method = new EntityEnclosingGetMethod(url);
+ break;
+ case DELETE:
+ method = new EntityEnclosingDeleteMethod(url);
+ break;
+ case POST:
+ method = new PostMethod(url);
+ break;
+ case PUT:
+ method = new PutMethod(url);
+ break;
+ default:
+ // set default method
+ method = new PostMethod(url);
+ break;
+ }
+ return method;
+ }
+
+ private String getRewriteUrl(HttpClientAdapterVO vo, String inboundRewritePath, String queryString,
+ JSONObject restOptionObject, Map inboundPathVariables) {
+ String fragment = null;
+ if (StringUtils.isNotBlank(queryString)) {
+ int fragIdx = queryString.indexOf('#');
+ if (fragIdx >= 0) {
+ fragment = queryString.substring(fragIdx + 1);
+ queryString = queryString.substring(0, fragIdx);
+ }
+ }
+
+ String restExtraPath = (String) restOptionObject.get("extraPath");
+ if (StringUtils.isBlank(restExtraPath)) {
+ StringBuilder uri = new StringBuilder(500);
+ uri.append(vo.getUrl()).append(inboundRewritePath);
+
+ if (StringUtils.isNotBlank(queryString)) {
+ uri.append('?');
+ uri.append(encodeUriQuery(queryString, false));
+ }
+
+ if (doSendUrlFragment && fragment != null) {
+ uri.append('#');
+ uri.append(encodeUriQuery(fragment, false));
+ }
+
+ return uri.toString();
+ } else {
+ String type = (String) restOptionObject.get("type");
+ String url = getUrl(vo.getUrl(), restExtraPath);
+
+ if (StringUtils.equalsIgnoreCase(type, HttpClientAdapterServiceRest.TYPE_VARIABLE_URL_REQUEST)) {
+ inboundPathVariables = mergeInboundPathVariables(inboundPathVariables, queryString);
+ List urlVariableValueList = new ArrayList<>();
+ JSONArray uriVariables = (JSONArray) restOptionObject.get("uriVariables");
+ if (uriVariables != null && !uriVariables.isEmpty() && inboundPathVariables != null
+ && !inboundPathVariables.isEmpty()) {
+ for (Object tempObject : uriVariables) {
+ String urlVaribleId = (String) tempObject;
+ String uriVariableValue = inboundPathVariables.get(urlVaribleId);
+ urlVariableValueList.add(uriVariableValue);
+ }
+
+ if (!urlVariableValueList.isEmpty()) {
+ UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).build();
+ Object[] urls = urlVariableValueList.toArray();
+ url = uriComponents.expand(urls).toUriString();
+ }
+ }
+ } else {
+ if (StringUtils.isNotBlank(queryString)) {
+ url += "?" + encodeUriQuery(queryString, false);
+ }
+
+ if (doSendUrlFragment && fragment != null) {
+ url += "#" + encodeUriQuery(fragment, false);
+ }
+ }
+
+ return url;
+ }
+ }
+
+ private Map mergeInboundPathVariables(Map inboundPathVariables,
+ String queryString) {
+ if (StringUtils.isBlank(queryString)) {
+ return inboundPathVariables;
+ }
+
+ if (inboundPathVariables == null) {
+ inboundPathVariables = new LinkedHashMap<>();
+ }
+
+ String[] pairs = queryString.split("&");
+ for (String pair : pairs) {
+ int idx = pair.indexOf("=");
+ // URLDecoder.decode 필요??
+ inboundPathVariables.put(pair.substring(0, idx), pair.substring(idx + 1));
+ }
+
+ return inboundPathVariables;
+ }
+
+ private String getUrl(String baseUrl, String extraPath) {
+ if (StringUtils.isBlank(extraPath)) {
+ return baseUrl;
+ }
+
+ if (StringUtils.contains(extraPath, "http://") || StringUtils.contains(extraPath, "https://")) {
+ return extraPath;
+ }
+
+ String targetUrl = baseUrl;
+ if (!targetUrl.endsWith("/")) {
+ targetUrl += "/";
+ }
+ if (extraPath.startsWith("/")) {
+ targetUrl += extraPath.substring(1);
+ } else {
+ targetUrl += extraPath;
+ }
+
+ return targetUrl;
+ }
+
+ protected CharSequence encodeUriQuery(CharSequence in, boolean encodePercent) {
+ // Note that I can't simply use URI.java to encode because it will escape
+ // pre-existing escaped things.
+ StringBuilder outBuf = null;
+ Formatter formatter = null;
+ for (int i = 0; i < in.length(); i++) {
+ char c = in.charAt(i);
+ boolean escape = true;
+ if (c < 128) {
+ if (asciiQueryChars.get(c) && !(encodePercent && c == '%')) {
+ escape = false;
+ }
+ } else if (!Character.isISOControl(c) && !Character.isSpaceChar(c)) {// not-ascii
+ escape = false;
+ }
+ if (!escape) {
+ if (outBuf != null)
+ outBuf.append(c);
+ } else {
+ // escape
+ if (outBuf == null) {
+ outBuf = new StringBuilder(in.length() + 5 * 3);
+ outBuf.append(in, 0, i);
+ formatter = new Formatter(outBuf);
+ }
+ // leading %, 0 padded, width 2, capital hex
+ formatter.format("%%%02X", (int) c);// TODO
+ }
+ }
+ return outBuf != null ? outBuf : in;
+ }
+
+ protected static final BitSet asciiQueryChars;
+ static {
+ char[] c_unreserved = "_-!.~'()*".toCharArray();// plus alphanum
+ char[] c_punct = ",;:$&+=".toCharArray();
+ char[] c_reserved = "/@".toCharArray();// plus punct. Exclude '?'; RFC-2616 3.2.2. Exclude '[', ']';
+ // https://www.ietf.org/rfc/rfc1738.txt, unsafe characters
+ asciiQueryChars = new BitSet(128);
+ for (char c = 'a'; c <= 'z'; c++)
+ asciiQueryChars.set(c);
+ for (char c = 'A'; c <= 'Z'; c++)
+ asciiQueryChars.set(c);
+ for (char c = '0'; c <= '9'; c++)
+ asciiQueryChars.set(c);
+ for (char c : c_unreserved)
+ asciiQueryChars.set(c);
+ for (char c : c_punct)
+ asciiQueryChars.set(c);
+ for (char c : c_reserved)
+ asciiQueryChars.set(c);
+
+ asciiQueryChars.set('%');// leave existing percent escapes in place
+ }
+
+ private void assignRelayDataToInbound(Properties prop, Header[] responseHeaders, int status) {
+ if (responseHeaders == null || responseHeaders.length == 0) {
+ return;
+ }
+
+ Properties headerProp = new Properties();
+ for (Header header : responseHeaders) {
+ headerProp.put(header.getName(), header.getValue());
+ }
+
+ headerProp.put(HttpAdapterServiceBypass.HTTP_STATUS, String.valueOf(status));
+
+ Map map = new HashMap();
+ map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_HEADERS, headerProp);
+
+ prop.put(HttpAdapterServiceKey.OUTBOUND_PROPERTY_MAP, map);
+ }
+
+ private void setAuthHeaders(HttpMethodBase method, OAuth2AccessTokenVO accessToken) throws Exception {
+ method.setRequestHeader("Authorization",
+ String.format("%s %s", AccessTokenVO.BEARER_TYPE, accessToken.getAccessToken()));
+ }
+
+ private boolean checkTokenRetry(byte[] responseMessage, String tokenErrorCodeKey, String tokenErrorCodeValues,
+ String encode) {
+ if (responseMessage == null) {
+ return false;
+ }
+
+ if (StringUtils.isBlank(tokenErrorCodeKey)) {
+ return false;
+ }
+
+ if (StringUtils.isBlank(tokenErrorCodeValues)) {
+ return false;
+ }
+
+ try {
+ DocumentContext jsonContext = JsonPath.parse(new String(responseMessage, encode));
+ String responseCode = jsonContext.read(tokenErrorCodeKey);
+ if (StringUtils.isBlank(responseCode)) {
+ return false;
+ }
+
+ String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenErrorCodeValues, ",");
+ return ArrayUtils.contains(arr, responseCode);
+ } catch (Exception e) {
+ logger.error("HttpClientAdapterServiceBypass] checkTokenRetry error=" + e.getMessage());
+ }
+
+ return false;
+ }
+
+ private void assignRequestHeaders(HttpMethodBase method, Properties headerProp, Properties inProp) {
+ if (headerProp == null) {
+ return;
+ }
+
+ for (Entry e : headerProp.entrySet()) {
+ String key = (String) e.getKey();
+ String value = (String) e.getValue();
+
+ if (StringUtils.equalsAnyIgnoreCase(key, HttpAdapterServiceBypass.HOP_BY_HOP_HEADERS)
+ || StringUtils.equalsIgnoreCase(key, HttpHeaders.CONTENT_LENGTH)) {
+ continue;
+ }
+
+ if (doHandleCompression && StringUtils.equalsIgnoreCase(key, HttpHeaders.ACCEPT_ENCODING)) {
+ continue;
+ }
+
+ method.setRequestHeader(key, value);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Request Header :" + key + "=[" + value + "]");
+ }
+ }
+
+ if (doForwardIP) {
+ String forHeaderName = "X-Forwarded-For";
+ String forHeader = inProp.getProperty(HttpAdapterServiceKey.INBOUND_REMOTE_ADDR);
+ if (StringUtils.isNotBlank(forHeader)) {
+ String existingForHeader = headerProp.getProperty(forHeaderName);
+ if (existingForHeader != null) {
+ forHeader = existingForHeader + ", " + forHeader;
+ }
+ method.setRequestHeader(forHeaderName, forHeader);
+ }
+
+ String protoHeaderName = "X-Forwarded-Proto";
+ String protoHeader = inProp.getProperty(HttpAdapterServiceKey.INBOUND_SCHEME);
+ if (StringUtils.isNotBlank(protoHeader)) {
+ method.setRequestHeader(protoHeaderName, protoHeader);
+ }
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private JSONObject parseJson(String message) throws Exception {
+ if (message == null) {
+ return null;
+ }
+
+ return (JSONObject) JSONValue.parse(message);
+ }
+
+ public static final String getIgnoreCaseProp(Properties prop, String key) {
+ if (prop == null) {
+ return null;
+ }
+
+ for (Entry e : prop.entrySet()) {
+ if (StringUtils.equalsIgnoreCase(key, (String) e.getKey())) {
+ return (String) e.getValue();
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceChangedate.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceChangedate.java
new file mode 100644
index 0000000..c3767f6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceChangedate.java
@@ -0,0 +1,157 @@
+//
+//package com.eactive.eai.adapter.http.client.impl;
+//
+//import com.eactive.eai.adapter.http.HttpMemoryLogger;
+//import com.eactive.eai.adapter.http.HttpStatusException;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+//import com.eactive.eai.common.exception.ExceptionUtil;
+//import com.eactive.eai.common.util.CommonLib;
+//import org.apache.commons.httpclient.HttpClient;
+//import org.apache.commons.httpclient.HttpStatus;
+//import org.apache.commons.httpclient.HttpVersion;
+//import org.apache.commons.httpclient.methods.PostMethod;
+//
+//import java.net.ConnectException;
+//import java.net.SocketTimeoutException;
+//import java.util.Properties;
+//
+//
+///**
+//* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+//* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+//* 2. 처리 개요 :
+//* * - 2009.11.24 retry 로직 제거 : 요청
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
+//* @since :
+//
+//*/
+//public class HttpClientAdapterServiceChangedate extends HttpClientAdapterServiceSupport{
+//
+// /**
+// * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+// * 2. 처리 개요 :
+// * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+// * 3. 주의사항
+// *
+// * @param prop Http Adapter 속성 정보
+// * @param message 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// public Object execute(Properties prop, byte[] data, Properties tempProp) throws Exception {
+//
+// HttpClientAdapterVO vo = super.setting(prop, tempProp);
+//
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceChangedate] SEND (" + vo.getMethod() + ") ");
+// }
+// PostMethod method = new PostMethod(vo.getUrl());
+// if (vo.getTimeout() > -1) {
+// method.getParams().setSoTimeout(vo.getTimeout());
+// }
+// HttpClient mclient = this.client;
+// if ( vo.getConnectionTimeout() != 0){
+// mclient.getParams().setParameter("http.connection.timeout", vo.getConnectionTimeout());
+// }
+// method.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
+//
+// // Data Size : 15 Bytes
+// int popupMinSize = 15;
+//
+// String req = "";
+// String date = "";
+//
+// if (data.length >= popupMinSize) {
+// if (vo.getEncode() != null && vo.getEncode().length() > 0) {
+// if (logger.isDebug()) {
+// logger.debug("HttpClientAdapterServiceChangedate] ENCODE(" + vo.getEncode() + ") ");
+// }
+// req = new String(data, 0, 7, vo.getEncode()).trim();
+// date = new String(data, 7, 8, vo.getEncode());
+// } else {
+// req = new String(data, 0, 7 ).trim();
+// date = new String(data, 7, 8 );
+// }
+// method.addParameter("req", req);
+// method.addParameter("date", date);
+//
+// } else {
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServiceChangedate] Invalid Data Length (" + data.length + ") < "
+// + popupMinSize);
+// }
+// throw new Exception("HttpClientAdapterServiceChangedate Error : MessageSize(" + (data.length)
+// + " Bytes) too small < " + popupMinSize);
+// }
+//
+// int status = -1;
+//
+// try {
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),
+// "[req]"+ req + "\n"
+// + "[date]" + date + "\n"
+// + "SEND ["+new String(data)+"]"+CommonLib.getDumpMessage(data) +"\n"
+// );
+// }
+// //mclient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+// //mclient.getParams().setContentCharset("EUC_KR");
+// status = mclient.executeMethod(method);
+// //status 200(정상) 이외에는 error 처리
+// if (status !=200){
+// try{
+// logger.error("HttpClientAdapterServiceChangedate] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
+// }catch(Exception e){
+// logger.error(e);
+// }
+// throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
+// }
+// byte[] responseMessage = method.getResponseBody();
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage) );
+// }
+// return responseMessage;
+//
+// } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient// 3.1일 경우
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceChangedate] SocketTimeoutException : " + ste.toString() ,ste);
+// }
+// if (logger.isError()){
+// logger.error("HttpClientAdapterServiceChangedate] SocketTimeoutException : " + ste.toString() ,ste);
+// }
+// throw ste;
+// } catch(ConnectException ce) {
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceChangedate] Connection Exception : " + ce.toString() ,ce);
+// }
+// if (logger.isError()){
+// logger.error("HttpClientAdapterServiceChangedate] Connection Exception : " + ce.toString() ,ce);
+// }
+// throw ce;
+// } catch(Exception e) {
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceChangedate] Exception : " + e.toString() ,e);
+// }
+// if (logger.isError()){
+// logger.error("HttpClientAdapterServiceChangedate] Exception : " + e.toString() ,e);
+// }
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if (status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if (logger.isDebug()) {
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceExtorg.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceExtorg.java
new file mode 100644
index 0000000..fe797c7
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceExtorg.java
@@ -0,0 +1,152 @@
+//
+//package com.eactive.eai.adapter.http.client.impl;
+//
+//import com.eactive.eai.adapter.http.HttpMemoryLogger;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+//import com.eactive.eai.common.util.CommonLib;
+//
+//import java.util.Hashtable;
+//import java.util.Map;
+//import java.util.Properties;
+//
+////import k4m.eCross.client.Context;
+//
+//
+///**
+//* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+//* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+//* 2. 처리 개요 :
+//* * - 2009.11.24 retry 로직 제거 : 요청
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
+//* @since :
+//
+//*/
+//public class HttpClientAdapterServiceExtorg extends HttpClientAdapterServiceSupport{
+//
+// @Override
+// protected void init(){
+// ;
+// }
+// /**
+// * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+// * 2. 처리 개요 :
+// * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+// * 3. 주의사항
+// *
+// * @param prop Http Adapter 속성 정보
+// * @param message 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// public Object execute(Properties prop, byte[] data, Properties tempProp) throws Exception
+// {
+// HttpClientAdapterVO vo = super.setting(prop, tempProp);
+// String msgNumber = "";
+// String ReceiverID = "";
+//
+// if (logger.isDebug()){
+// logger.debug("HttpClientAdapterServiceExtorg: Body Size] ["+data.length+"]");
+// }
+//
+// if(data.length > 23){
+// msgNumber = new String(data, 19, 4);
+// if (logger.isDebug()){
+// logger.debug("HttpClientAdapterServiceExtorg: msgNumber] ["+msgNumber+"]");
+// }
+// //String ReceiverID = "770000";
+//
+// /* 20081124 add MP at KIBO start------------------------------------*/
+// /* ReceiverID extract Message */
+// ReceiverID = new String(data, 12, 7).trim();
+// /* 20081124 add MP at KIBO start------------------------------------*/
+//
+// if (logger.isDebug()){
+// logger.debug("HttpClientAdapterServiceExtorg: ReceiverID] ["+ReceiverID+"]");
+// }
+// }else{
+// logger.warn("Invalid message length - Length["+data.length+"]");
+// }
+//
+//
+// String url = prop.getProperty(URL);
+//
+// //flat데이타
+// String inputLine = " "+new String(data);
+// String outputString = "";
+//
+//
+// try
+// {
+// Map inputStream = new Hashtable();
+// Map outStream = new Hashtable();
+// String serviceName = "MPS.Send.FlatSender";
+// inputStream.put("MessageNumber",msgNumber);
+// inputStream.put("ReceiverID",ReceiverID);
+// // 트랜젝션 ID 15바이트를 처리
+// inputStream.put("FlatStream",inputLine);
+//
+//
+// if(logger.isDebug()){
+// logger.debug( "[serviceName]"+ serviceName + "\n"
+// + "[MessageNumber]" + msgNumber + "\n"
+// + "[ReceiverID]" + ReceiverID + "\n"
+// + "[FlatStream]" + inputLine + "\n"
+// + "SEND ["+new String(data)+"]"+CommonLib.getDumpMessage(data) +"\n");
+// }
+//
+// try{
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),
+// "[serviceName]"+ serviceName + "\n"
+// + "[MessageNumber]" + msgNumber + "\n"
+// + "[ReceiverID]" + ReceiverID + "\n"
+// + "[FlatStream]" + inputLine + "\n"
+// + "SEND ["+new String(data)+"]"+CommonLib.getDumpMessage(data) +"\n"
+// );
+// }
+// //eCross Partner 주소
+//// Context ctx = new Context(url,"demo","demo");
+//// outStream = ctx.CallService(serviceName,inputStream);
+// //결과전문
+// outputString = (String)outStream.get("ReplyStream");
+//
+// // 트렌젝션 ID 15바이트를 처리
+// try {
+// outputString = outputString.substring(15);
+// }catch(Exception ex){
+// logger.warn("substring error", ex);
+// }
+//
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),
+// "RECV ["+outputString+"]"+CommonLib.getDumpMessage(outputString.getBytes()) +"\n"
+// );
+// }
+// }catch(Exception ee){
+// if(logger.isError()){
+// logger.error("HttpClientAdapterServiceExtorg] Exception"+ ee.getMessage(),ee);
+// }
+// }
+// } catch (Exception e) {
+// if(logger.isError()){
+// logger.error("HttpClientAdapterServiceExtorg] Exception"+ e.getMessage(),e);
+// }
+// }
+//
+// if(logger.isDebug()){
+// logger.debug("RECV ["+outputString+"]"+CommonLib.getDumpMessage(outputString.getBytes()) +"\n");
+// }
+//
+// if (outputString == null){
+// throw new Exception("HttpClientAdapterServiceExtorg ] execute - input message parse fail");
+// }
+//
+// return outputString.getBytes();
+// }
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceGet.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceGet.java
new file mode 100644
index 0000000..7af4846
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceGet.java
@@ -0,0 +1,167 @@
+
+package com.eactive.eai.adapter.http.client.impl;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.common.util.MessageUtil;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.HttpVersion;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.URLEncoder;
+import java.util.Properties;
+
+public class HttpClientAdapterServiceGet extends HttpClientAdapterServiceSupport {
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+ boolean isAsync = false;
+
+ GetMethod method = new GetMethod(vo.getUrl());
+ HttpClient mclient = this.client;
+
+ configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
+
+ String sendData = "";
+ if (data instanceof String) {
+ sendData = URLEncoder.encode((String) data, vo.getEncode());
+ } else if (data instanceof byte[]) {
+ sendData = URLEncoder.encode(new String((byte[]) data, vo.getEncode()), vo.getEncode());
+ }
+ StringBuilder querySb = new StringBuilder();
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceGet] GET Method URLEncoder");
+ }
+
+ if (RESPONSE_TYPE_ASYNC.equals(vo.getResponseType())) {
+ isAsync = true;
+ querySb.append("type=async&");
+ }
+ querySb.append(vo.getParameterName()).append("=");
+ querySb.append(sendData);
+ method.setQueryString(querySb.toString());
+
+ String contentTypeValue = null;
+ if (StringUtils.isNotEmpty(vo.getContentType())) {
+ if (StringUtils.isNotEmpty(vo.getEncode())) {
+ contentTypeValue = vo.getContentType() + "; charset=" + vo.getEncode();
+ } else {
+ contentTypeValue = vo.getContentType();
+ }
+ method.setRequestHeader(CONTENT_TYPE_KEY, contentTypeValue);
+ }
+ if (vo.getAdapterHeaders() != null) {
+ for (String key : vo.getAdapterHeaders().keySet()) {
+ method.addRequestHeader(key, vo.getAdapterHeaders().get(key));
+ }
+ }
+ if (logger.isInfoEnabled()) {
+ logger.info("HttpClientAdapterServiceGet] " + CONTENT_TYPE_KEY + "(" + contentTypeValue + ")");
+ }
+
+ int status = -1;
+ try {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [" + sendData + "]" + CommonLib.getDumpMessage(sendData));
+ }
+
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+ if (vo.getUrl() != null && vo.getUrl().startsWith("https")) {
+ Protocol.registerProtocol("https",
+ new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+ }
+ status = mclient.executeMethod(method);
+ stopWatch.stop();
+
+ String responseCharSet = getResponseCharSet(method.getResponseCharSet(), vo.getAdapterGroupName());
+
+ // status 200(정상) 이외에는 error 처리
+ if (status != 200) {
+ try {
+ logger.error("HttpClientAdapterServiceGet] receive status[" + status + "] data["
+ + new String(method.getResponseBody()) + "]");
+ } catch (Exception e) {
+ logger.error(e);
+ }
+ throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="
+ + vo.getAdapterGroupName() + "." + vo.getAdapterName(), status);
+ }
+
+ byte[] responseMessage = method.getResponseBody();
+ if (isAsync && stopWatch.getTime() > vo.getSlowTranTime() && logger.isWarn()) {
+ logger.warn("HttpClientAdapterServiceGet] URL[" + vo.getUrl() + "] lazy async response time = "
+ + stopWatch.toString() + " responseMessage=" + new String(responseMessage, responseCharSet));
+ }
+
+ responseMessage = getEncodingConvert(responseCharSet, vo.getAdapterGroupName(), responseMessage);
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [" + new String(responseMessage, responseCharSet) + "]"
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+ AdapterManager m = AdapterManager.getInstance();
+ AdapterGroupVO agvo = m.getAdapterGroupVO(vo.getAdapterGroupName());
+ if (MessageUtil.isBytesMessage(agvo.getMessageType())) {
+ return responseMessage;
+ } else {
+ return new String(responseMessage, vo.getEncode());
+ }
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceGet] SocketTimeoutException : " + ste.toString(), ste);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceGet] SocketTimeoutException : " + ste.toString(), ste);
+ }
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceGet] Connection Exception : " + ce.toString(), ce);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceGet] Connection Exception : " + ce.toString(), ce);
+ }
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceGet] Exception : " + e.toString(), e);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceGet] Exception : " + e.toString(), e);
+ }
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA014", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceMemo.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceMemo.java
new file mode 100644
index 0000000..40ec674
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceMemo.java
@@ -0,0 +1,203 @@
+//
+//package com.eactive.eai.adapter.http.client.impl;
+//
+//import com.eactive.eai.adapter.http.HttpMemoryLogger;
+//import com.eactive.eai.adapter.http.HttpStatusException;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+//import com.eactive.eai.common.exception.ExceptionUtil;
+//import com.eactive.eai.common.util.CommonLib;
+//import org.apache.commons.httpclient.HttpClient;
+//import org.apache.commons.httpclient.HttpStatus;
+//import org.apache.commons.httpclient.HttpVersion;
+//import org.apache.commons.httpclient.methods.PostMethod;
+//
+//import java.net.ConnectException;
+//import java.net.SocketTimeoutException;
+//import java.util.Properties;
+//
+//
+///**
+//* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+//* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+//* 2. 처리 개요 :
+//* * - 2009.11.24 retry 로직 제거 : 요청
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
+//* @since :
+//
+//*/
+//public class HttpClientAdapterServiceMemo extends HttpClientAdapterServiceSupport{
+//
+// /**
+// * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+// * 2. 처리 개요 :
+// * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+// * 3. 주의사항
+// *
+// * @param prop Http Adapter 속성 정보
+// * @param message 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// public Object execute(Properties prop, byte[] data, Properties tempProp) throws Exception {
+//
+// HttpClientAdapterVO vo = super.setting(prop, tempProp);
+//
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceMemo] SEND (" + vo.getMethod() + ") ");
+// }
+// PostMethod method = new PostMethod(vo.getUrl());
+// if (vo.getTimeout() > -1) {
+// method.getParams().setSoTimeout(vo.getTimeout());
+// }
+// HttpClient mclient = this.client;
+// if ( vo.getConnectionTimeout() != 0){
+// mclient.getParams().setParameter("http.connection.timeout", vo.getConnectionTimeout());
+// }
+// method.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
+// int memoMinSize = 587;
+//
+// String srvCode = "";
+// String serType = "";
+// String recipient = "";
+// String send = "";
+// String title = "";
+// String body = "";
+// String urgent = "";
+// String saveOption = "";
+// String rcvIp = "";
+//
+// if (data.length >= memoMinSize) {
+// if (vo.getEncode() != null && vo.getEncode().length() > 0) {
+// if (logger.isDebug()) {
+// logger.debug("HttpClientAdapterServiceMemo] ENCODE(" + vo.getEncode() + ") ");
+// }
+// srvCode = new String(data, 0, 6, vo.getEncode());
+// serType = new String(data, 6, 1, vo.getEncode());
+// recipient = new String(data, 7, 7, vo.getEncode());
+// send = new String(data, 14, 7, vo.getEncode());
+// title = new String(data, 21, 40, vo.getEncode());
+// body = new String(data, 61, 500, vo.getEncode());
+// urgent = new String(data, 561, 1, vo.getEncode());
+// saveOption = new String(data, 562, 1, vo.getEncode());
+// rcvIp = new String(data, 563, 24, vo.getEncode());
+//
+// } else {
+// srvCode = new String(data, 0, 6);
+// serType = new String(data, 6, 1);
+// recipient = new String(data, 7, 7);
+// send = new String(data, 14, 7);
+// title = new String(data, 21, 40);
+// body = new String(data, 61, 500);
+// urgent = new String(data, 561, 1);
+// saveOption = new String(data, 562, 1);
+// rcvIp = new String(data, 563, 24);
+// }
+// method.addParameter("SRV_CODE", srvCode );
+// method.addParameter("SER_TYPE", serType );
+// method.addParameter("RECIPIENT", recipient );
+// method.addParameter("SEND", send );
+// method.addParameter("TITLE", title );
+// method.addParameter("BODY", body );
+// method.addParameter("URGENT", urgent );
+// method.addParameter("SAVEOPTION", saveOption);
+// method.addParameter("RCV_IP", rcvIp );
+//
+// } else {
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServiceMemo] Invalid Data Length (" + data.length + ") < "
+// + memoMinSize);
+// }
+// throw new Exception("HttpClientAdapterServiceMemo Error : MessageSize(" + (data.length)
+// + " Bytes) too small < " + memoMinSize);
+// }
+//
+// int status = -1;
+//
+// try {
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),
+// "[SRV_CODE] "+ srvCode + "\n"
+// + "[SER_TYPE] "+ serType + "\n"
+// + "[RECIPIENT] "+ recipient + "\n"
+// + "[SEND] "+ send + "\n"
+// + "[TITLE] "+ title + "\n"
+// + "[BODY] "+ body + "\n"
+// + "[URGENT] "+ urgent + "\n"
+// + "[SAVEOPTION] "+ saveOption + "\n"
+// + "[RCV_IP] "+ rcvIp + "\n"
+// + "SEND ["+new String(data)+"]"+CommonLib.getDumpMessage(data) );
+// }
+// //mclient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+// if (vo.getEncode() != null && vo.getEncode().length() > 0) {
+// mclient.getParams().setContentCharset(vo.getEncode());
+// }
+// else {
+// // ASIS 에서 DEFAULT로 EUC_KR로 설정했음
+// mclient.getParams().setContentCharset("EUC_KR");
+// }
+//
+// status = mclient.executeMethod(method);
+// //status 200(정상) 이외에는 error 처리
+// if (status !=200){
+// try{
+// logger.error("HttpClientAdapterServiceMemo] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
+// }catch(Exception e){
+// logger.error(e);
+// }
+// throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
+// }
+// byte[] responseMessage = method.getResponseBody();
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage) );
+// }
+// return responseMessage;
+//
+// } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient
+// // 3.1일 경우
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+// "HttpClientAdapterServiceMemo] SocketTimeoutException : " + ste.toString(), ste);
+// }
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServiceMemo] SocketTimeoutException : " + ste.toString(), ste);
+// }
+// throw ste;
+// } catch (ConnectException ce) {
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+// "HttpClientAdapterServiceMemo] Connection Exception : " + ce.toString(), ce);
+// }
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServiceMemo] Connection Exception : " + ce.toString(), ce);
+// }
+// throw ce;
+// } catch (Exception e) {
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+// "HttpClientAdapterServiceMemo] Exception : " + e.toString(), e);
+// }
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServiceMemo] Exception : " + e.toString(), e);
+// }
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if (status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if (logger.isDebug()) {
+// logger.debug(resMsg);
+// }
+// }
+// }
+//
+// }
+//
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceMsa.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceMsa.java
new file mode 100644
index 0000000..8dd2cdc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceMsa.java
@@ -0,0 +1,227 @@
+
+package com.eactive.eai.adapter.http.client.impl;
+
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.util.UrlUtil;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.HttpVersion;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Properties;
+
+// Msa 는 LG Micro Service Architecture F/W과 통신하기 위한 Adapter로 관련 Site 전용
+public class HttpClientAdapterServiceMsa extends HttpClientAdapterServiceSupport {
+
+ public static String DEFAULT_ENCODE = "UTF-8";
+
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+ String svcName = tempProp.getProperty(TRAN_CODE, "");
+
+ if (StringUtils.isEmpty(svcName)) {
+ throw new Exception("service name is empty");
+ }
+
+ boolean isAsync = false;
+
+ if (vo.getUrl() == null) {
+ throw new Exception("URL is NULL");
+ }
+
+ if (vo.getUrl().endsWith(".ajmd") || vo.getUrl().endsWith(".axmd")) {
+ isAsync = true;
+ }
+
+ String msaUrl = vo.getUrl().replace("%" + TRAN_CODE + "%", svcName);
+
+ // ENVR_INFO_DVSN_CD = L
+ // FRST_DMND_SYS_IP_VAL 로 라우팅하도록 함
+ boolean localCall = LOCAL_CALL_Y.equals(tempProp.getProperty(LOCAL_CALL, "N"));
+ if (localCall) {
+ String newIp = tempProp.getProperty(LOCAL_IP);
+ if (newIp == null) {
+ if (logger.isWarn()) {
+ logger.warn("HttpClientAdapterServiceMsa] LOCAL_CALL FRST_DMND_SYS_IP_VAL is empty, SKIP : "
+ + msaUrl);
+ }
+ } else {
+ String newPort = PropManager.getInstance().getProperty("LOCAL", "port", "7001");
+ msaUrl = UrlUtil.replaceIpAddress(msaUrl, newIp, newPort);
+ if (logger.isWarn()) {
+ logger.warn("HttpClientAdapterServiceMsa] LOCAL_CALL REPLACED_URL : " + msaUrl);
+ }
+ }
+ }
+
+ PostMethod method = new PostMethod(msaUrl);
+ HttpClient mclient = this.client;
+
+ configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
+
+ logger.debug("HttpClientAdapterServiceMsa] ENCODE(" + vo.getEncode() + ")");
+
+ try {
+ mclient.getParams().setContentCharset(vo.getEncode());
+ } catch (Exception e) {
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceMsa] ENCODE(" + vo.getEncode() + ") ERROR : " + e.toString());
+ logger.error("HttpClientAdapterServiceMsa] ENCODE(" + vo.getEncode() + ") SKIP ");
+ }
+ }
+
+ String contentTypeValue = null;
+ if (StringUtils.isNotEmpty(vo.getContentType())) {
+ if (StringUtils.isNotEmpty(vo.getEncode())) {
+ contentTypeValue = vo.getContentType() + "; charset=" + vo.getEncode();
+ } else {
+ contentTypeValue = vo.getContentType();
+ }
+ method.setRequestHeader(CONTENT_TYPE_KEY, contentTypeValue);
+ }
+ if (vo.getAdapterHeaders() != null) {
+ for (String key : vo.getAdapterHeaders().keySet()) {
+ method.addRequestHeader(key, vo.getAdapterHeaders().get(key));
+ }
+ }
+ if (logger.isInfoEnabled()) {
+ logger.info("HttpClientAdapterServiceMsa] " + CONTENT_TYPE_KEY + "(" + contentTypeValue + ")");
+ }
+
+ byte[] sendBytes = null;
+ if (data instanceof String) {
+ sendBytes = ((String) data).getBytes(vo.getEncode());
+ } else if (data instanceof byte[]) {
+ sendBytes = (byte[]) data;
+ }
+
+ InputStream in = new ByteArrayInputStream(sendBytes); // "utf-8"
+ method.setRequestBody(in);
+
+ int status = -1;
+
+ try {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceMsa] SEND (" + vo.getAdapterGroupName() + ") = ["
+ + new String(sendBytes, vo.getEncode()) + "]");
+ logger.debug("HttpClientAdapterServiceMsa] SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(sendBytes));
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [" + new String(sendBytes, vo.getEncode()) + "]" + CommonLib.getDumpMessage(sendBytes));
+ }
+ if (vo.getUrl() != null && vo.getUrl().startsWith("https")) {
+ Protocol.registerProtocol("https",
+ new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+ }
+ status = mclient.executeMethod(method);
+ stopWatch.stop();
+
+ String responseCharSet = getResponseCharSet(method.getResponseCharSet(), vo.getAdapterGroupName());
+
+ if (status != 200) {
+ try {
+ logger.error("HttpClientAdapterServiceMsa] receive status[" + status + "] data["
+ + new String(method.getResponseBody()) + "]");
+ } catch (Exception e) {
+ logger.error(e);
+ }
+ throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="
+ + vo.getAdapterGroupName() + "." + vo.getAdapterName(), status);
+ }
+
+ // 응답으로 온 byte[]를 그대로 전달한다.
+ byte[] responseMessage = method.getResponseBody();
+ ;
+ if (isAsync && stopWatch.getTime() > vo.getSlowTranTime()) {
+ if (logger.isWarn()) {
+ logger.warn("HttpClientAdapterServiceMsa] URL[" + msaUrl + "] lazy async response time = "
+ + stopWatch.toString() + " responseMessage="
+ + new String(responseMessage, responseCharSet));
+ }
+ }
+
+ responseMessage = getEncodingConvert(responseCharSet, vo.getAdapterGroupName(), responseMessage);
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceMsa] responseType =" + vo.getResponseType()
+ + ", responseCharSet=" + responseCharSet);
+ logger.debug("HttpClientAdapterServiceMsa] RECV (" + vo.getAdapterGroupName() + ") = ["
+ + new String(responseMessage, responseCharSet) + "]");
+ logger.debug("HttpClientAdapterServiceMsa] RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [" + new String(responseMessage, responseCharSet) + "]"
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ return responseMessage;
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceMsa] SocketTimeoutException : " + ste.toString() + " url="
+ + msaUrl,
+ ste);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceMsa] SocketTimeoutException : " + ste.toString() + " url="
+ + msaUrl, ste);
+ }
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceMsa] Connection Exception : " + ce.toString() + " url=" + msaUrl,
+ ce);
+ }
+ if (logger.isError()) {
+ logger.error(
+ "HttpClientAdapterServiceMsa] Connection Exception : " + ce.toString() + " url=" + msaUrl,
+ ce);
+ }
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceMsa] Exception : " + e.toString() + " url=" + msaUrl, e);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceMsa] Exception : " + e.toString() + " url=" + msaUrl, e);
+ }
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceNexCore.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceNexCore.java
new file mode 100644
index 0000000..4d2dbae
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceNexCore.java
@@ -0,0 +1,227 @@
+
+package com.eactive.eai.adapter.http.client.impl;
+
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.util.UrlUtil;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.HttpVersion;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Properties;
+
+// NexCore F/W과 통신하기 위한 Adapter로 관련 Site 전용
+public class HttpClientAdapterServiceNexCore extends HttpClientAdapterServiceSupport {
+
+ public static String DEFAULT_ENCODE = "UTF-8";
+
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+ String svcName = tempProp.getProperty(TRAN_CODE, "");
+
+ if (StringUtils.isEmpty(svcName)) {
+ throw new Exception("service name is empty");
+ }
+
+ boolean isAsync = false;
+
+ if (vo.getUrl() == null) {
+ throw new Exception("URL is NULL");
+ }
+
+ if (vo.getUrl().endsWith(".ajmd") || vo.getUrl().endsWith(".axmd")) {
+ isAsync = true;
+ }
+
+ String nKesaUrl = vo.getUrl().replace("%" + TRAN_CODE + "%", svcName);
+
+ // ENVR_INFO_DVSN_CD = L
+ // FRST_DMND_SYS_IP_VAL 로 라우팅하도록 함
+ boolean localCall = LOCAL_CALL_Y.equals(tempProp.getProperty(LOCAL_CALL, "N"));
+ if (localCall) {
+ String newIp = tempProp.getProperty(LOCAL_IP);
+ if (newIp == null) {
+ if (logger.isWarn()) {
+ logger.warn("HttpClientAdapterServiceNexCore] LOCAL_CALL FRST_DMND_SYS_IP_VAL is empty, SKIP : "
+ + nKesaUrl);
+ }
+ } else {
+ String newPort = PropManager.getInstance().getProperty("LOCAL", "port", "7001");
+ nKesaUrl = UrlUtil.replaceIpAddress(nKesaUrl, newIp, newPort);
+ if (logger.isWarn()) {
+ logger.warn("HttpClientAdapterServiceNexCore] LOCAL_CALL REPLACED_URL : " + nKesaUrl);
+ }
+ }
+ }
+
+ PostMethod method = new PostMethod(nKesaUrl);
+ HttpClient mclient = this.client;
+
+ configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
+
+ logger.debug("HttpClientAdapterServiceNexCore] ENCODE(" + vo.getEncode() + ")");
+
+ try {
+ mclient.getParams().setContentCharset(vo.getEncode());
+ } catch (Exception e) {
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceNexCore] ENCODE(" + vo.getEncode() + ") ERROR : " + e.toString());
+ logger.error("HttpClientAdapterServiceNexCore] ENCODE(" + vo.getEncode() + ") SKIP ");
+ }
+ }
+
+ String contentTypeValue = null;
+ if (StringUtils.isNotEmpty(vo.getContentType())) {
+ if (StringUtils.isNotEmpty(vo.getEncode())) {
+ contentTypeValue = vo.getContentType() + "; charset=" + vo.getEncode();
+ } else {
+ contentTypeValue = vo.getContentType();
+ }
+ method.setRequestHeader(CONTENT_TYPE_KEY, contentTypeValue);
+ }
+ if (vo.getAdapterHeaders() != null) {
+ for (String key : vo.getAdapterHeaders().keySet()) {
+ method.addRequestHeader(key, vo.getAdapterHeaders().get(key));
+ }
+ }
+ if (logger.isInfoEnabled()) {
+ logger.info("HttpClientAdapterServiceNexCore] " + CONTENT_TYPE_KEY + "(" + contentTypeValue + ")");
+ }
+
+ byte[] sendBytes = null;
+ if (data instanceof String) {
+ sendBytes = ((String) data).getBytes(vo.getEncode());
+ } else if (data instanceof byte[]) {
+ sendBytes = (byte[]) data;
+ }
+
+ InputStream in = new ByteArrayInputStream(sendBytes); // "utf-8"
+ method.setRequestBody(in);
+
+ int status = -1;
+
+ try {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceNexCore] SEND (" + vo.getAdapterGroupName() + ") = ["
+ + new String(sendBytes, vo.getEncode()) + "]");
+ logger.debug("HttpClientAdapterServiceNexCore] SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(sendBytes));
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [" + new String(sendBytes, vo.getEncode()) + "]" + CommonLib.getDumpMessage(sendBytes));
+ }
+ if (vo.getUrl() != null && vo.getUrl().startsWith("https")) {
+ Protocol.registerProtocol("https",
+ new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+ }
+ status = mclient.executeMethod(method);
+ stopWatch.stop();
+
+ String responseCharSet = getResponseCharSet(method.getResponseCharSet(), vo.getAdapterGroupName());
+
+ if (status != 200) {
+ try {
+ logger.error("HttpClientAdapterServiceNexCore] receive status[" + status + "] data["
+ + new String(method.getResponseBody()) + "]");
+ } catch (Exception e) {
+ logger.error(e);
+ }
+ throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="
+ + vo.getAdapterGroupName() + "." + vo.getAdapterName(), status);
+ }
+
+ // 응답으로 온 byte[]를 그대로 전달한다.
+ byte[] responseMessage = method.getResponseBody();
+ ;
+ if (isAsync && stopWatch.getTime() > vo.getSlowTranTime()) {
+ if (logger.isWarn()) {
+ logger.warn("HttpClientAdapterServiceNexCore] URL[" + nKesaUrl + "] lazy async response time = "
+ + stopWatch.toString() + " responseMessage="
+ + new String(responseMessage, responseCharSet));
+ }
+ }
+
+ responseMessage = getEncodingConvert(responseCharSet, vo.getAdapterGroupName(), responseMessage);
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceNexCore] responseType =" + vo.getResponseType()
+ + ", responseCharSet=" + responseCharSet);
+ logger.debug("HttpClientAdapterServiceNexCore] RECV (" + vo.getAdapterGroupName() + ") = ["
+ + new String(responseMessage, responseCharSet) + "]");
+ logger.debug("HttpClientAdapterServiceNexCore] RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [" + new String(responseMessage, responseCharSet) + "]"
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ return responseMessage;
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceNexCore] SocketTimeoutException : " + ste.toString() + " url="
+ + nKesaUrl,
+ ste);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceNexCore] SocketTimeoutException : " + ste.toString() + " url="
+ + nKesaUrl, ste);
+ }
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceNexCore] Connection Exception : " + ce.toString() + " url=" + nKesaUrl,
+ ce);
+ }
+ if (logger.isError()) {
+ logger.error(
+ "HttpClientAdapterServiceNexCore] Connection Exception : " + ce.toString() + " url=" + nKesaUrl,
+ ce);
+ }
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceNexCore] Exception : " + e.toString() + " url=" + nKesaUrl, e);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceNexCore] Exception : " + e.toString() + " url=" + nKesaUrl, e);
+ }
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServicePopup.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServicePopup.java
new file mode 100644
index 0000000..7c739e1
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServicePopup.java
@@ -0,0 +1,169 @@
+//
+//package com.eactive.eai.adapter.http.client.impl;
+//
+//import com.eactive.eai.adapter.http.HttpMemoryLogger;
+//import com.eactive.eai.adapter.http.HttpStatusException;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+//import com.eactive.eai.common.exception.ExceptionUtil;
+//import com.eactive.eai.common.util.CommonLib;
+//import org.apache.commons.httpclient.HttpClient;
+//import org.apache.commons.httpclient.HttpStatus;
+//import org.apache.commons.httpclient.HttpVersion;
+//import org.apache.commons.httpclient.methods.PostMethod;
+//
+//import java.net.ConnectException;
+//import java.net.SocketTimeoutException;
+//import java.util.Properties;
+//
+//
+///**
+//* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+//* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+//* 2. 처리 개요 :
+//* * - 2009.11.24 retry 로직 제거 : 요청
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
+//* @since :
+//
+//*/
+//public class HttpClientAdapterServicePopup extends HttpClientAdapterServiceSupport{
+//
+// /**
+// * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+// * 2. 처리 개요 :
+// * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+// * 3. 주의사항
+// *
+// * @param prop Http Adapter 속성 정보
+// * @param message 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// public Object execute(Properties prop, byte[] data, Properties tempProp) throws Exception {
+//
+// HttpClientAdapterVO vo = super.setting(prop, tempProp);
+//
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapter] SEND (" + vo.getMethod() + ") ");
+// }
+// PostMethod method = new PostMethod(vo.getUrl());
+// if (vo.getTimeout() > -1) {
+// method.getParams().setSoTimeout(vo.getTimeout());
+// }
+// HttpClient mclient = this.client;
+// if ( vo.getConnectionTimeout() != 0){
+// mclient.getParams().setParameter("http.connection.timeout", vo.getConnectionTimeout());
+// }
+// method.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
+//
+// // Popup Data Size : 153 Bytes
+// int popupMinSize = 153;
+// String srvCode = "";
+// String recipient = "";
+// String title = "";
+// String body = "";
+//
+//
+// if (data.length >= popupMinSize) {
+// if (vo.getEncode() != null && vo.getEncode().length() > 0) {
+// if (logger.isDebug()) {
+// logger.debug("HttpClientAdapterServicePopup] ENCODE(" + vo.getEncode() + ") ");
+// }
+// srvCode = new String(data, 0, 6, vo.getEncode());
+// recipient = new String(data, 6, 7, vo.getEncode());
+// title = new String(data, 13, 40, vo.getEncode());
+// body = new String(data, 53, 100, vo.getEncode());
+// } else {
+// srvCode = new String(data, 0, 6);
+// recipient = new String(data, 6, 7);
+// title = new String(data, 13, 40);
+// body = new String(data, 53, 100);
+// }
+// method.addParameter("SRV_CODE", srvCode);
+// method.addParameter("RECIPIENT", recipient);
+// method.addParameter("TITLE", title);
+// method.addParameter("BODY", body);
+// } else {
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServicePopup] Invalid Data Length (" + data.length + ") < "
+// + popupMinSize);
+// }
+// throw new Exception("HttpClientAdapterServicePopup Error : MessageSize(" + (data.length)
+// + " Bytes) too small < " + popupMinSize);
+// }
+//
+// int status = -1;
+//
+// try {
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),
+// "[SRV_CODE] "+ srvCode + "\n"
+// + "[RECIPIENT] "+ recipient + "\n"
+// + "[TITLE] "+ title + "\n"
+// + "[BODY] "+ body + "\n"
+// + "SEND ["+new String(data)+"]"+CommonLib.getDumpMessage(data) );
+// }
+// //mclient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
+// //mclient.getParams().setContentCharset("EUC_KR");
+// status = mclient.executeMethod(method);
+// //status 200(정상) 이외에는 error 처리
+// if (status !=200){
+// try{
+// logger.error("HttpClientAdapterServicePopup] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
+// }catch(Exception e){
+// logger.error(e);
+// }
+// throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
+// }
+// byte[] responseMessage = method.getResponseBody();
+// if (vo.getTraceLevel() >= 3){
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage) );
+// }
+// return responseMessage;
+//
+// } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+// "HttpClientAdapterServicePopup] SocketTimeoutException : " + ste.toString(), ste);
+// }
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServicePopup] SocketTimeoutException : " + ste.toString(), ste);
+// }
+// throw ste;
+// } catch (ConnectException ce) {
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+// "HttpClientAdapterServicePopup] Connection Exception : " + ce.toString(), ce);
+// }
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServicePopup] Connection Exception : " + ce.toString(), ce);
+// }
+// throw ce;
+// } catch (Exception e) {
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+// "HttpClientAdapterServicePopup] Exception : " + e.toString(), e);
+// }
+// if (logger.isError()) {
+// logger.error("HttpClientAdapterServicePopup] Exception : " + e.toString(), e);
+// }
+// throw e;
+// } finally {
+// method.releaseConnection();
+// if (status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if (logger.isDebug()) {
+// logger.debug(resMsg);
+// }
+// }
+// }
+// }
+//
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServicePost.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServicePost.java
new file mode 100644
index 0000000..b121c63
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServicePost.java
@@ -0,0 +1,224 @@
+
+package com.eactive.eai.adapter.http.client.impl;
+
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.common.util.MessageUtil;
+
+
+/**
+* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+* 2. 처리 개요 :
+* * - 2009.11.24 retry 로직 제거 : 요청
+* 3. 주의사항
+*
+* @author :
+* @version : v 1.0.0
+* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
+* @since :
+
+*/
+public class HttpClientAdapterServicePost extends HttpClientAdapterServiceSupport{
+
+ /**
+ * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+ * 2. 처리 개요 :
+ * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+ * 3. 주의사항
+ *
+ * @param prop Http Adapter 속성 정보
+ * @param message 송신 전문
+ * @return 반환 된 byte[] Object
+ * @exception Exception 수동 시스템 간 통신 중 발생
+ **/
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception
+ {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+ boolean isAsync = false;
+
+ PostMethod method = new PostMethod(vo.getUrl());
+ HttpClient mclient = this.client;
+
+ configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
+
+ String sendData = "";
+ if (data instanceof String) {
+ sendData = (String) data;
+ } else if (data instanceof byte[]) {
+ sendData = new String((byte[]) data, vo.getEncode());
+ }
+
+ mclient.getParams().setContentCharset(vo.getEncode());
+
+ if ("Y".equals(vo.getUrlEncodeYn())){
+ sendData = java.net.URLEncoder.encode(sendData);
+ }
+
+ if(RESPONSE_TYPE_ASYNC.equals(vo.getResponseType())) {
+ isAsync = true;
+ method.addParameter("type", "async");
+ }
+
+ method.addParameter(vo.getParameterName(), sendData);
+
+ String contentTypeValue = null;
+ if(StringUtils.isNotEmpty(vo.getContentType())) {
+ if(StringUtils.isNotEmpty(vo.getEncode())) {
+ contentTypeValue = vo.getContentType() +"; charset=" + vo.getEncode();
+ }
+ else {
+ contentTypeValue = vo.getContentType();
+ }
+ method.setRequestHeader(CONTENT_TYPE_KEY, contentTypeValue);
+ }
+ if (vo.getAdapterHeaders() != null){
+ for(String key : vo.getAdapterHeaders().keySet()){
+ method.addRequestHeader(key, vo.getAdapterHeaders().get(key));
+ }
+ }
+ if(logger.isInfoEnabled()) {
+ logger.info("HttpClientAdapterServicePost] "+CONTENT_TYPE_KEY+"("+contentTypeValue+")");
+ }
+
+ int status = -1;
+
+ try {
+
+ if(logger.isDebug() && "N".equals(vo.getTestCallYn())){
+ logger.debug("HttpClientAdapterServicePost] SEND ("+vo.getAdapterGroupName()+") = ["+sendData+"]");
+ logger.debug("HttpClientAdapterServicePost] SEND ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(sendData));
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3){
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "SEND ["+sendData+"]"+CommonLib.getDumpMessage(sendData));
+ }
+ if (vo.getUrl() != null && vo.getUrl().startsWith("https")) {
+ Protocol.registerProtocol("https",
+ new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+ }
+ status = mclient.executeMethod(method);
+
+ stopWatch.stop();
+
+ String responseCharSet = getResponseCharSet(method.getResponseCharSet(),vo.getAdapterGroupName());
+
+ //status 200(정상) 이외에는 error 처리
+ if (status !=200){
+ try{
+ logger.error("HttpClientAdapterServicePost] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
+ }catch(Exception e){
+ logger.error(e);
+ }
+ throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
+ }
+
+ byte[] responseMessage = method.getResponseBody();
+ if (isAsync && stopWatch.getTime() > vo.getSlowTranTime()) {
+ if (logger.isWarn()){
+ logger.warn("HttpClientAdapterServicePost] URL[" + vo.getUrl() + "] lazy response time = " + stopWatch.toString()+ " responseMessage=" + new String(responseMessage,responseCharSet));
+ }
+ }
+ responseMessage = getEncodingConvert(responseCharSet, vo.getAdapterGroupName(), responseMessage);
+// if(vo.getEncode() != null && vo.getEncode().length() > 0) {
+// Charset res = null;
+// Charset adpt = null;
+// byte[] orgResponse = method.getResponseBody();
+// try{
+// res = Charset.forName(responseCharSet);
+// adpt = Charset.forName(vo.getEncode());
+// if (res.compareTo(adpt)==0){
+// responseMessage = orgResponse;
+// }else{
+// String encodingString = new String(orgResponse, responseCharSet);
+// responseMessage = encodingString.getBytes(vo.getEncode());
+// }
+// }catch(UnsupportedCharsetException e){
+// responseMessage = orgResponse;
+// }
+// }
+// else {
+// responseMessage = method.getResponseBody();
+// }
+ //----------------------------------------------------------
+
+
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())){
+ logger.debug("HttpClientAdapterServicePost] responseType ="+ vo.getResponseType());
+ logger.debug("HttpClientAdapterServicePost] RECV ("+vo.getAdapterGroupName()+") = ["+new String(responseMessage,responseCharSet)+"]");
+ logger.debug("HttpClientAdapterServicePost] RECV ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(responseMessage));
+ }
+
+ if (vo.getTraceLevel() >= 3){
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage,responseCharSet)+"]"+CommonLib.getDumpMessage(responseMessage));
+ }
+
+ AdapterManager m = AdapterManager.getInstance();
+ AdapterGroupVO agvo= m.getAdapterGroupVO(vo.getAdapterGroupName());
+ if (MessageUtil.isBytesMessage(agvo.getMessageType())) {
+ return responseMessage;
+ } else {
+ return new String(responseMessage, vo.getEncode());
+ }
+ } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3){
+ HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServicePost] SocketTimeoutException : " + ste.toString() ,ste);
+ }
+ if (logger.isError()){
+ logger.error("HttpClientAdapterServicePost] SocketTimeoutException : " + ste.toString() ,ste);
+ }
+ throw ste;
+ } catch(ConnectException ce) {
+ if (vo.getTraceLevel() >= 3){
+ HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServicePost] Connection Exception : " + ce.toString() ,ce);
+ }
+ if (logger.isError()){
+ logger.error("HttpClientAdapterServicePost] Connection Exception : " + ce.toString() ,ce);
+ }
+ throw ce;
+ } catch(Exception e) {
+ if (vo.getTraceLevel() >= 3){
+ HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServicePost] Exception : " + e.toString() ,e);
+ }
+ if (logger.isError()){
+ logger.error("HttpClientAdapterServicePost] Exception : " + e.toString() ,e);
+ }
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if(status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if(logger.isDebug()){
+ logger.debug(resMsg);
+ }
+ }
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRest.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRest.java
new file mode 100644
index 0000000..27cd348
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRest.java
@@ -0,0 +1,829 @@
+package com.eactive.eai.adapter.http.client.impl;
+
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpMethodType;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.util.CommonLib;
+import com.jayway.jsonpath.DocumentContext;
+import com.jayway.jsonpath.JsonPath;
+import com.openbanking.eai.common.token.AccessTokenManager;
+import com.openbanking.eai.common.token.AccessTokenVO;
+import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
+
+/**
+ * 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를 GET/POST 방식으로 호출할 수 있는
+ * 기능을 제공한다.
+ * 2. 처리 개요 :
+ * * - 2020-09-25: Http Header 받아서 처리할 수 있게 기능 추가
+ * 3. 주의사항
+ *
+ * @author :
+ * @version : v 1.0.0
+ * @see : HttpClientAdapterServiceFactory.java,
+ * HttpClientAdapterServiceSupport.java
+ * @since :
+ *
+ */
+public class HttpClientAdapterServiceRest extends HttpClientAdapterServiceSupport
+ implements HttpClientAdapterServiceKey {
+ public static final String TYPE_VARIABLE_URL_REQUEST = "variableUrlRequest";
+ public static final String TYPE_SIMPLE_REQUEST = "simpleRequest";
+
+ public static final String REST_OPTION = "REST_OPTION";
+
+ ////public static final String HEADER_CONTENT_TYPE = "Content-Type";
+ public static final String HEADER_GROUP = "HEADER_GROUP";
+ public static final String HTTP_STATUS = "HTTP_STATUS";
+ public static final String HEADER_KEYS = "HEADER_KEYS";
+
+ /**
+ * 1. 기능 : REST API 통신에 사용
+ * 2. 처리 개요 : - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+ * 3. 주의사항
+ *
+ * @param prop Http Adapter 속성 정보
+ * @param message 송신 전문(JSON)
+ * @return 반환 된 Object
+ * @exception Exception 수동 시스템 간 통신 중 발생
+ **/
+ @SuppressWarnings({ "unchecked" })
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+
+ String headerGroupName = prop.getProperty(HEADER_GROUP);
+ String relayResponseHeaderKeys = prop.getProperty(HEADER_KEYS, "");
+ boolean useAdapterToken = StringUtils.equalsIgnoreCase(prop.getProperty("ADAPTER_TOKEN_USE_YN", "N"), "Y");
+
+ // ex) $.dataHeader.GW_RSLT_CD
+ String tokenErrorCodeKey = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_KEY");
+ String tokenErrorCodeValues = prop.getProperty("ADAPTER_TOKEN_ERROR_CODE_VALUES");
+ String tokenErrorHttpStatusCode = prop.getProperty("ADAPTER_TOKEN_ERROR_HTTP_STATUS_CODE"); // 200 or 400번대
+
+ // 레이아웃 메시지 타입 REST URL 추출 시 활용. Default JSON
+ String messageType = prop.getProperty("MESSAGE_TYPE", MessageType.JSON);
+ String inboundMethod = tempProp.getProperty(HttpAdapterServiceKey.INBOUND_METHOD, "POST");
+
+ /**
+ * @formatter:off
+ * TSEAIHE02.RESTOPTION 정보 => JSON 형태로 구성
+ * - type : simpleRequest, variableUrlRequest
+ * - extraPath : 어댑터 프로퍼티 URL에 추가될 HTTP REST URL
+ * - method : get, delete, post, put
+ * - contentType: application/json(default), application/x-www-form-urlencoded
+ * - adapterTokenUseYn: Y, N(default)
+ * ex)
+ * {"type":"simpleRequest","extraPath":"v2.0/accout/balance","method":"post"}
+ * @formatter:on
+ */
+
+ String restOptionData = tempProp.getProperty(REST_OPTION);
+
+ JSONObject restOptionObject = parseJson(restOptionData);
+ if (restOptionObject == null) {
+ throw new Exception("OptionData parsing result is NULL");
+ }
+
+ String rmethod = (String) restOptionObject.getOrDefault("method", inboundMethod);
+ String contentType = (String) restOptionObject.getOrDefault("contentType", "application/json");
+ String adapterTokenUseYn = (String) restOptionObject.get("adapterTokenUseYn");
+ if (StringUtils.isNotBlank(adapterTokenUseYn)) { // interface 에 설정된게 우선한다.
+ useAdapterToken = StringUtils.equalsIgnoreCase(adapterTokenUseYn, "Y");
+ }
+
+ HttpClient mclient = this.client;
+ String sendData = "";
+ if (data instanceof String) {
+ sendData = (String) data;
+ } else if (data instanceof byte[]) {
+ sendData = new String((byte[]) data, vo.getEncode());
+ }
+
+ ////mclient.getParams().setContentCharset(vo.getEncode());
+
+ JSONObject dataObject = null;
+ Object httpHeader = null;
+ if (MessageType.JSON.equals(messageType)) {
+ dataObject = parseJson(sendData);
+ if (dataObject != null && StringUtils.isNotBlank(headerGroupName)) {
+ httpHeader = dataObject.get(headerGroupName);
+ dataObject.remove(headerGroupName);
+ }
+ }
+
+ logger.debug("HttpClientAdapterServiceRest] dataObject1 = [" + dataObject + "]");
+
+ // interface 에 설정된게 우선한다.
+ String uri = null;
+ if (dataObject == null) {
+ uri = changeUrl(messageType, vo.getUrl(), restOptionData, sendData);
+ } else {
+ uri = changeUrl(messageType, vo.getUrl(), restOptionData, dataObject);
+ }
+
+ logger.debug("HttpClientAdapterServiceRest] dataObject2 = [" + dataObject + "]");
+
+// ////if (vo.getConnectionTimeout() != 0) {
+// mclient.getHttpConnectionManager().getParams().setConnectionTimeout(vo.getConnectionTimeout());
+// }
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug(
+ "HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL=[" + vo.getUrl() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") PARAMETER_NAME=["
+ + vo.getParameterName() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") ENCODE=["
+ + vo.getEncode() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") RESPONSE_TYPE=["
+ + vo.getResponseType() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") URL_ENCODE_YN=["
+ + vo.getUrlEncodeYn() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") CONNECTION_TIMEOUT=["
+ + vo.getConnectionTimeout() + "] ");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") REST_OPTION=["
+ + restOptionData + "] ");
+ }
+
+ HttpMethodBase method = null;
+ switch (HttpMethodType.getValue(rmethod)) {
+ case GET:
+ method = new GetMethod(uri);
+ break;
+ case DELETE:
+ method = new DeleteMethod(uri);
+ break;
+ case POST:
+ method = new PostMethod(uri);
+ break;
+ case PUT:
+ method = new PutMethod(uri);
+ break;
+ default:
+ // set default method
+ method = new GetMethod(uri);
+ break;
+ }
+
+ configureHttpClient(mclient, method, vo, uri, contentType);
+
+ switch (HttpMethodType.getValue(rmethod)) {
+ case GET:
+ case DELETE:
+ HashMap h = getParameters(dataObject);
+ NameValuePair[] params = new NameValuePair[h.size()];
+ int count = 0;
+ for (String key : h.keySet()) {
+ String value = h.get(key);
+ params[count] = new NameValuePair(key, value);
+ count++;
+ }
+ method.setQueryString(params);
+ if (logger.isDebug()) {
+ logger.debug(
+ "HttpClientAdapterServiceRest] (get Method) QueryString = [" + method.getQueryString() + "]");
+ }
+
+ break;
+ case PUT:
+ case POST:
+ assignPostBody(dataObject, contentType, method);
+ break;
+ default:
+ break;
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") method.getParams()=["
+ + method.getParams().toString() + "] ");
+ }
+
+ OAuth2AccessTokenVO accessToken = null;
+ if (useAdapterToken) {
+ AccessTokenManager tokenManager = AccessTokenManager.getInstance();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.getAccessTokenVO(vo.getAdapterGroupName());
+
+ // 토큰이 없거나 만료 됐으면 재발급
+ if (accessToken == null || accessToken.isExpired()) {
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop,
+ oldToken);
+ }
+
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") TOKEN = ["
+ + accessToken + "]");
+ }
+
+ setAuthHeaders(method, accessToken);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName()
+ + ") RequestHeader [Authorization=" + method.getRequestHeader("Authorization") + "]");
+ }
+ }
+
+ // 전달 header 셋팅
+ // Adapter 레벨 header 보다 data로 넘어온 httpHeader를 우선 적용(header명이 같다면 덮어씀)
+ assignRequestHeaders(method, httpHeader);
+
+ int status = -1;
+
+ try {
+ byte[] responseMessage = null;
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ if (dataObject != null) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = ["
+ + dataObject.toJSONString() + "]");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(dataObject.toJSONString()));
+ } else {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = [" + sendData
+ + "]");
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(sendData));
+ }
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "SEND [" + sendData + "]" + CommonLib.getDumpMessage(sendData));
+ }
+ try {
+ if (logger.isDebug()) {
+ logger.debug("[method getName]" + method.getName());
+ logger.debug("[method getRequestCharSet]" + method.getRequestCharSet());
+ logger.debug("[method getRequestHeaders]" + method.getRequestHeaders().toString());
+ logger.debug("[method getQueryString]" + method.getQueryString());
+ logger.debug("[method getParams]" + method.getParams().toString());
+ logger.debug("[method getURI]" + method.getURI());
+ }
+ status = mclient.executeMethod(method);
+ if (logger.isDebug()) {
+ logger.debug("[received status]" + status);
+ }
+ } catch (ConnectException e) {
+ responseMessage = method.getResponseBody();
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = ["
+ + new String(responseMessage, vo.getEncode()) + "]");
+ logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+ throw new Exception("excuteMethod java.net.ConnectException = " + e.getMessage());
+ }
+
+ stopWatch.stop();
+
+ /**
+ * @formatter:off
+ * OAuth 토큰 응답 체크(Adapter properties로 설정)
+ * 응답코드에 따라 유효한 토큰 확인(토큰 재발급 여부 확인)
+ * API 서비스 마다 정책이 다름(보통 400대에서 체크하나 200에서도 체크할 수 있음)
+ *
+ * TOKEN_ERROR_CODE_KEY: 응답 json error code key
+ * __ex) $.dataHeader.resultCode
+ * TOKEN_ERROR_CODE_VALUES: 토큰 재발급이 필요한 응답 error codes(ex: O0001,O0002,O0003)
+ * TOKEN_ERROR_HTTP_STATUS_CODE: 보통 400대에서 체크하나 API 제공자에 따라 200에서도 체클할수 있음
+ * ex) TOKEN_ERROR_HTTP_STATUS_CODE = 200
+ * @formatter:on
+ */
+ boolean needReissue = false;
+
+ if (status == 200) {
+ responseMessage = method.getResponseBody();
+ if (useAdapterToken && StringUtils.equals(tokenErrorHttpStatusCode, "200")) {
+ needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues,
+ vo.getEncode());
+ }
+ } else if (status == 302) {
+ responseMessage = method.getResponseBody();
+ if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) {
+ relayResponseHeaderKeys += ",Location";
+ }
+ } else if (status >= 400 && status < 500) {
+ responseMessage = method.getResponseBody();
+ if (useAdapterToken) {
+ needReissue = checkTokenRetry(responseMessage, tokenErrorCodeKey, tokenErrorCodeValues,
+ vo.getEncode());
+ }
+
+ if (!needReissue) {
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseMessage);
+ throw new Exception(errMsg);
+ }
+ } else {
+ responseMessage = method.getResponseBody();
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseMessage);
+ throw new Exception(errMsg);
+ }
+
+ // ----------------------------------------------------------
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] responseType =" + vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceRest] RECV " + vo.getEncode() + "(" + vo.getAdapterGroupName()
+ + ") = [" + new String(responseMessage, vo.getEncode()) + "]");
+ logger.debug("HttpClientAdapterServiceRest] RECV MS949 (" + vo.getAdapterGroupName() + ") = ["
+ + new String(responseMessage, "MS949") + "]");
+ logger.debug("HttpClientAdapterServiceRest] RECV euc-kr (" + vo.getAdapterGroupName() + ") = ["
+ + new String(responseMessage, "euc-kr") + "]");
+ logger.debug("HttpClientAdapterServiceRest] RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ if (useAdapterToken) {
+ if (responseMessage == null) {
+ throw new Exception("responseMessage is NULL, HttpStatus=" + status);
+ }
+
+ // OAuth 토큰 재요청 코드 확인
+ if (needReissue) {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] retry access token response code = ["
+ + vo.getResponseType() + "] message = [" + new String(responseMessage, vo.getEncode())
+ + "]");
+ }
+
+ // 토큰 재발급
+ AccessTokenManager tokenManager = AccessTokenManager.getInstance();
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ OAuth2AccessTokenVO newaccessToken = (OAuth2AccessTokenVO) tokenManager
+ .retryAccessTokenVO(vo.getAdapterGroupName(), prop, oldToken);
+ method.setRequestHeader("Authorization", newaccessToken.getAuthorization());
+
+ setAuthHeaders(method, newaccessToken);
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] SEND (" + vo.getAdapterGroupName()
+ + ") RETRY TOKEN = [" + newaccessToken + "]");
+ }
+
+ try {
+ status = mclient.executeMethod(method);
+ } catch (ConnectException e) {
+ throw new Exception("retry excuteMethod Exceptioin = " + e.getMessage());
+ }
+
+ if (status == 200) {
+ responseMessage = method.getResponseBody();
+ } else if (status == 302) {
+ responseMessage = method.getResponseBody();
+ if (!StringUtils.contains(relayResponseHeaderKeys, "Location")) {
+ relayResponseHeaderKeys += ",Location";
+ }
+ } else {
+ responseMessage = method.getResponseBody();
+ String errMsg = String.format(
+ "http receive status fail value=%d adapterName=%s.%s uri=%s method=%s response Data=%s",
+ status, vo.getAdapterGroupName(), vo.getAdapterName(), uri, rmethod, responseMessage);
+ throw new Exception(errMsg);
+ }
+
+ // ----------------------------------------------------------
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRest] RETRY responseType =" + vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceRest] RETRY RECV " + vo.getEncode() + "("
+ + vo.getAdapterGroupName() + ") = [" + new String(responseMessage, vo.getEncode())
+ + "]");
+ logger.debug("HttpClientAdapterServiceRest] RETRY RECV (" + vo.getAdapterGroupName() + ") = "
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+ // ----------------------------------------------------------
+ }
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "RECV [" + new String(responseMessage, vo.getEncode()) + "]"
+ + CommonLib.getDumpMessage(responseMessage));
+ }
+
+ assignRelayDataToInbound(tempProp, method.getResponseHeaders());
+
+ return assignResponseHeaders(method, responseMessage, headerGroupName, vo.getEncode(), messageType,
+ relayResponseHeaderKeys, status);
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : "
+ + ste.toString(),
+ ste);
+ }
+ logger.error("HttpClientAdapterServiceRest] SocketTimeoutException (" + vo.getAdapterGroupName() + ") : "
+ + ste.toString(), ste);
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : "
+ + ce.toString(),
+ ce);
+ }
+ logger.error("HttpClientAdapterServiceRest] Connection Exception (" + vo.getAdapterGroupName() + ") : "
+ + ce.toString(), ce);
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(), e.toString(), e);
+ }
+ logger.error("HttpClientAdapterServiceRest] Exception (" + vo.getAdapterGroupName() + ") : " + e.toString(),
+ e);
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+ }
+
+ private void assignRelayDataToInbound(Properties prop, Header[] responseHeaders) {
+ if (responseHeaders == null || responseHeaders.length == 0) {
+ return;
+ }
+
+ Properties headerProp = new Properties();
+ for (Header header : responseHeaders) {
+ headerProp.put(header.getName(), header.getValue());
+ }
+
+ Map map = new HashMap();
+ map.put(HttpAdapterServiceKey.OUTBOUND_RESPONSE_HEADERS, headerProp);
+
+ prop.put(HttpAdapterServiceKey.OUTBOUND_PROPERTY_MAP, map);
+ }
+
+ /**
+ * 현재 1단계 레이아웃에만 적용되도록 구현됨.
+ *
+ * @param method
+ * @param responseMessage
+ * @param headerGroupName
+ * @param encode
+ * @param messageType
+ * @param relayHeaderKeys
+ * @return
+ * @throws Exception
+ */
+ @SuppressWarnings("unchecked")
+ private String assignResponseHeaders(HttpMethodBase method, byte[] responseMessage, String headerGroupName,
+ String encode, String messageType, String relayHeaderKeys, int status) throws Exception {
+ if (!MessageType.JSON.equals(messageType) || StringUtils.isBlank(headerGroupName)
+ || StringUtils.isBlank(relayHeaderKeys)) {
+ return new String(responseMessage, encode);
+ }
+
+ String[] relayKeyArr = org.springframework.util.StringUtils.tokenizeToStringArray(relayHeaderKeys, ",");
+ JSONObject headerJson = new JSONObject();
+ for (String key : relayKeyArr) {
+ Header header = method.getResponseHeader(key);
+ if (header != null) {
+ headerJson.put(header.getName(), header.getValue());
+ }
+ }
+
+ headerJson.put(HTTP_STATUS, String.valueOf(status));
+
+ if (headerJson.size() <= 0) {
+ return new String(responseMessage, encode);
+ }
+
+ JSONObject message = null;
+ if (responseMessage == null || responseMessage.length == 0) {
+ message = new JSONObject();
+ } else {
+ message = parseJson(new String(responseMessage, encode));
+ if (message == null) {
+ message = new JSONObject();
+ message.put("Malformed_Response_Message", new String(responseMessage, encode));
+ }
+ }
+
+ if (StringUtils.isNotBlank(headerGroupName) && message != null)
+ message.put(headerGroupName, headerJson);
+ return message.toJSONString();
+ }
+
+ private void setAuthHeaders(HttpMethodBase method, OAuth2AccessTokenVO accessToken) throws Exception {
+ method.setRequestHeader("Authorization",
+ String.format("%s %s", AccessTokenVO.BEARER_TYPE, accessToken.getAccessToken()));
+ }
+
+ private boolean checkTokenRetry(byte[] responseMessage, String tokenErrorCodeKey, String tokenErrorCodeValues,
+ String encode) {
+ if (responseMessage == null) {
+ return false;
+ }
+
+ if (StringUtils.isBlank(tokenErrorCodeKey)) {
+ return false;
+ }
+
+ if (StringUtils.isBlank(tokenErrorCodeValues)) {
+ return false;
+ }
+
+ try {
+ DocumentContext jsonContext = JsonPath.parse(new String(responseMessage, encode));
+ String responseCode = jsonContext.read(tokenErrorCodeKey);
+ if (StringUtils.isBlank(responseCode)) {
+ return false;
+ }
+
+ String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenErrorCodeValues, ",");
+ return ArrayUtils.contains(arr, responseCode);
+ } catch (Exception e) {
+ logger.error("HttpClientAdapterServiceRest] checkTokenRetry error=" + e.getMessage());
+ }
+
+ return false;
+ }
+
+ private void assignRequestHeaders(HttpMethodBase method, Object httpHeader) {
+ if (httpHeader == null) {
+ return;
+ }
+
+ if (httpHeader instanceof JSONObject) {
+ JSONObject jsonObject = (JSONObject) httpHeader;
+ for (Object key : jsonObject.keySet()) {
+ Object obj = jsonObject.get(key);
+ if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) {
+ continue;
+ }
+
+ method.setRequestHeader((String) key, (String) obj);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Request Header :" + (String) key + "=[" + (String) obj + "]");
+ }
+
+ }
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void assignPostBody(Object eaiBody, String contentType, HttpMethodBase method) {
+ if (eaiBody == null) {
+ return;
+ }
+
+ if (StringUtils.contains(contentType, "application/x-www-form-urlencoded")) {
+ handleJsonValue("", eaiBody, method);
+ } else {
+ ((EntityEnclosingMethod) method).setRequestBody(eaiBody.toString());
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void handleJsonValue(String keyPath, Object value, HttpMethodBase method) {
+ if (value == null) {
+ return;
+ }
+
+ if (value instanceof JSONObject) {
+ handleJsonObject(keyPath, (JSONObject) value, method);
+ } else if (value instanceof JSONArray) {
+ handleJsonArray(keyPath, (JSONArray) value, method);
+ } else {
+ String valueStr = String.valueOf(value);
+ if (StringUtils.isBlank(keyPath)) {
+ ((EntityEnclosingMethod) method).setRequestBody(valueStr);
+ } else {
+ if (keyPath.endsWith("]")) {
+ ((PostMethod) method).addParameter(keyPath, valueStr);
+ } else {
+ ((PostMethod) method).setParameter(keyPath, valueStr);
+ }
+ }
+ logger.debug(keyPath + "=" + valueStr);
+ }
+ }
+
+ /**
+ * req_list[0].tran_no=12345
+ * req_list[0].org_tran_amt=12000
+ * req_list[1].tran_no=12445
+ * req_list[1].org_tran_amt=11000
+ */
+ private void handleJsonArray(String keyPath, JSONArray jsonArray, HttpMethodBase method) {
+ for (int i = 0; i < jsonArray.size(); i++) {
+ Object object = jsonArray.get(i);
+ String newKeyPath = null;
+ if (StringUtils.isBlank(keyPath)) {
+ newKeyPath = "NA[" + i + "]";
+ } else {
+ newKeyPath = keyPath + "[" + i + "]";
+ }
+ handleJsonValue(newKeyPath, object, method);
+ }
+ }
+
+ /**
+ * obj.aaa=111
+ * obj.bbb=222
+ */
+ private void handleJsonObject(String keyPath, JSONObject jsonObject, HttpMethodBase method) {
+ for (Object key : jsonObject.keySet()) {
+ Object object = jsonObject.get(key);
+ String newKeyPath = StringUtils.isBlank(keyPath) ? "" : keyPath + ".";
+ newKeyPath += key;
+ handleJsonValue(newKeyPath, object, method);
+ }
+ }
+
+ private HashMap getParameters(Object message) throws Exception {
+
+ HashMap result = new HashMap();
+
+ if (message != null) {
+ if (message instanceof JSONObject) {
+ JSONObject jsonObject = (JSONObject) message;
+ for (Object key : jsonObject.keySet()) {
+ Object obj = jsonObject.get(key);
+ if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) {
+ continue;
+ }
+ result.put((String) key, getStringValue(obj));
+ }
+ } else {
+ String[] messages = ((String) message).split("&");
+ String[] data = null;
+
+ for (int i = 0; i < messages.length; i++) {
+ data = messages[i].split("=", 2);
+ if (data.length == 2) {
+ result.put(data[0], data[1]);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public String getStringValue(Object obj) {
+ if (obj == null) {
+ return null;
+ }
+
+ if (obj instanceof String) {
+ return (String) obj;
+ } else if (obj instanceof Long) {
+ return Long.toString((Long) obj);
+ } else if (obj instanceof BigDecimal) {
+ return ((BigDecimal) obj).toPlainString();
+ } else {
+ return (String) obj;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private JSONObject parseJson(String message) throws Exception {
+ if (message == null) {
+ return null;
+ }
+
+ return (JSONObject) JSONValue.parse(message);
+ }
+
+ private Document convertXmlDocument(String message) throws Exception {
+ SAXReader builder = new SAXReader();
+ Document document = builder.read(new StringReader(message));
+ return document;
+ }
+
+ @SuppressWarnings("deprecation")
+ private String changeUrl(String messageType, String url, String restOption, Object sendData) {
+ if ((MessageType.JSON.equals(messageType) || MessageType.XML.equals(messageType))) {
+ try {
+ if (StringUtils.isBlank(restOption)) {
+ return url;
+ }
+ List urlVariableList = new ArrayList();
+ JSONObject restOptionObject = parseJson(restOption);
+
+ if (restOptionObject == null)
+ throw new Exception("restOption is NULL");
+
+ String type = (String) restOptionObject.get("type");
+ String requestExtraPath = (String) restOptionObject.get("extraPath");
+ url = getUrl(url, requestExtraPath);
+ if (TYPE_VARIABLE_URL_REQUEST.equals(type)) {
+ JSONArray uriVariables = (JSONArray) restOptionObject.get("uriVariables");
+ if (MessageType.JSON.equals(messageType)) {
+ JSONObject jsonObject;
+ if (sendData instanceof JSONObject) {
+ jsonObject = (JSONObject) sendData;
+ } else {
+ jsonObject = (JSONObject) JSONValue.parse((String) sendData);
+ }
+ for (Object tempObject : uriVariables) {
+ String urlVaribleId = (String) tempObject;
+ String uriVariable = (String) jsonObject.get(urlVaribleId);
+ urlVariableList.add(uriVariable);
+ jsonObject.remove(urlVaribleId);
+ }
+ } else if (MessageType.XML.equals(messageType)) {
+ Document doc;
+ if (sendData instanceof Document) {
+ doc = (Document) sendData;
+ } else {
+ doc = convertXmlDocument((String) sendData);
+ }
+ for (Object tempObject : uriVariables) {
+ String urlVaribleId = (String) tempObject;
+ Element element = (Element) doc.selectSingleNode("//" + urlVaribleId);
+ urlVariableList.add(element.getText());
+ if (doc.getRootElement() == element) {
+ doc = null;
+ } else {
+ element.getParent().remove(element);
+ }
+ }
+ }
+ if (urlVariableList.size() > 0) {
+ UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).build();
+ Object[] urls = urlVariableList.toArray();
+ url = uriComponents.expand(urls).toUriString();
+ logger.debug("HttpClientAdapterServiceRest] after extand url=[" + url + "] ");
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Failed to change url", e);
+ }
+ }
+ return url;
+ }
+
+ private String getUrl(String baseUrl, String extraPath) {
+ if (StringUtils.isBlank(extraPath)) {
+ return baseUrl;
+ }
+
+ if (StringUtils.contains(extraPath, "http://") || StringUtils.contains(extraPath, "https://")) {
+ return extraPath;
+ }
+
+ String targetUrl = baseUrl;
+ if (!targetUrl.endsWith("/")) {
+ targetUrl += "/";
+ }
+ if (extraPath.startsWith("/")) {
+ targetUrl += extraPath.substring(1);
+ } else {
+ targetUrl += extraPath;
+ }
+
+ logger.debug("HttpClientAdapterServiceRest] after concatenate url=[" + targetUrl + "] ");
+ return targetUrl;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRestForCODEF.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRestForCODEF.java
new file mode 100644
index 0000000..f7fdc09
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRestForCODEF.java
@@ -0,0 +1,546 @@
+//
+//package com.eactive.eai.adapter.http.client.impl;
+//
+//import java.io.StringReader;
+//import java.net.ConnectException;
+//import java.net.SocketTimeoutException;
+//import java.net.URLDecoder;
+//import java.net.URLEncoder;
+//import java.util.Arrays;
+//import java.util.HashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Properties;
+//
+//import org.apache.commons.httpclient.HttpClient;
+//import org.apache.commons.httpclient.HttpMethodBase;
+//import org.apache.commons.httpclient.HttpStatus;
+//import org.apache.commons.httpclient.HttpVersion;
+//import org.apache.commons.httpclient.NameValuePair;
+//import org.apache.commons.httpclient.methods.DeleteMethod;
+//import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+//import org.apache.commons.httpclient.methods.GetMethod;
+//import org.apache.commons.httpclient.methods.PostMethod;
+//import org.apache.commons.httpclient.methods.PutMethod;
+//import org.apache.commons.httpclient.protocol.Protocol;
+//import org.apache.commons.lang.StringUtils;
+//import org.apache.commons.lang.time.StopWatch;
+//import org.dom4j.Document;
+//import org.dom4j.Element;
+//import org.dom4j.io.SAXReader;
+//import org.json.simple.JSONObject;
+//import org.json.simple.JSONValue;
+//import org.springframework.web.util.UriComponents;
+//import org.springframework.web.util.UriComponentsBuilder;
+//
+//import com.eactive.eai.adapter.http.HttpMemoryLogger;
+//import com.eactive.eai.adapter.http.HttpMethodType;
+//import com.eactive.eai.adapter.http.HttpStatusException;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+//import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+//import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+//import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+//import com.eactive.eai.common.exception.ExceptionUtil;
+//import com.eactive.eai.common.message.MessageType;
+//import com.eactive.eai.common.util.CommonLib;
+//import com.openbanking.eai.common.token.AccessTokenManager;
+//import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
+//
+//
+///**
+//* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를
+//* GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
+//* 2. 처리 개요 :
+//* * - 2009.11.24 retry 로직 제거 : 요청
+//* 3. 주의사항
+//*
+//* @author :
+//* @version : v 1.0.0
+//* @see :
+//* @since :
+//
+//*/
+//public class HttpClientAdapterServiceRestForCODEF extends HttpClientAdapterServiceSupport implements HttpClientAdapterServiceKey {
+//
+// public static final String TYPE_VARIABLE_URL_REQUEST = "variableUrlRequest";
+// public static final String TYPE_SIMPLE_REQUEST = "simpleRequest";
+//
+// public static final String HTTP_HEADER = "HTTP_HEADER";
+// public static final String EAI_HEADER = "EAI_HEADER";
+// public static final String EAI_BODY = "EAI_BODY";
+//
+// public static final String REST_OPTION = "REST_OPTION";
+// public static final String REST_TYPE = "type";
+// public static final String REST_EXTRA_PATH = "extraPath";
+// public static final String REST_METHOD = "method";
+//
+// public static final String HEADER_CONTENT_TYPE = "Content-Type";
+// public static final String HEADER_ACEPT = "Acept";
+//
+// public static final List RETRY_RESPONSE_CODE = Arrays.asList("invalid_token");
+//
+// /**
+// * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+// * 2. 처리 개요 :
+// * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+// * 3. 주의사항
+// *
+// * @param prop Http Adapter 속성 정보
+// * @param message 송신 전문
+// * @return 반환 된 byte[] Object
+// * @exception Exception 수동 시스템 간 통신 중 발생
+// **/
+// public Object execute(Properties prop, byte[] data, Properties tempProp) throws Exception {
+// HttpClientAdapterVO vo = super.setting(prop, tempProp);
+//
+// // 레이아웃 메세지 타입 REST URL 추출 시 활용. Default JSON
+// String messageType = prop.getProperty("MESSAGE_TYPE", MessageType.JSON);
+// /* TSEAIHE02.RESTOPTION 정보 -> JSON 형태로 구성
+// * type : simpleRequest, variableUrlRequest
+// * extraPath : 어댑터 프로퍼티 URL에 추가될 HTTP REST URL
+// * method : get, delete, post, put
+// *
+// * ex) {"type":"simpleRequest", "extraPath":"v2.0/account/balance", "method": "post"}
+// */
+//// String restOptionData = tempProp.getProperty(REST_OPTION);
+// String restOptionData = prop.getProperty(REST_OPTION);
+//
+// JSONObject restOptionObject = parseJson(restOptionData);
+// if(restOptionObject == null) {
+// throw new Exception("OptionData parsing result is NULL");
+// }
+// String rmethod = restOptionObject.containsKey("method")
+// ? StringUtils.upperCase((String) restOptionObject.get("method"))
+// : "POST";
+//
+// String sendData = new String(data);
+// Object eaiHeader = null;
+// Object eaiBody = null;
+// HttpClient mclient = this.client;
+//
+// HashMap header = new HashMap();
+//// for(Object obj : headerObject.keySet()){
+//// String key = (String)obj;
+//// header.put(key, (String)headerObject.get(key));
+//// }
+// //interface 에 설정된게 우선한다.
+// String uri = changeUrl(messageType, vo.getUrl(), restOptionData, sendData);
+//
+// HttpMethodBase method = null;
+// switch (HttpMethodType.getValue(rmethod)) {
+// case GET :
+// method = new GetMethod(uri);
+// break;
+// case DELETE :
+// method = new DeleteMethod(uri);
+// break;
+// case POST :
+// method = new PostMethod(uri);
+// break;
+// case PUT :
+// method = new PutMethod(uri);
+// break;
+// default :
+// // set default method
+// method = new GetMethod(uri);
+// break;
+// }
+//
+// //2008.02.15 : Timeout 처리로직 변경 (0 : 무한대 설정가능하게 함)
+// if(vo.getTimeout() > -1) {
+// method.getParams().setSoTimeout(vo.getTimeout());
+// }
+//
+// if ( vo.getConnectionTimeout() != 0) {
+// method.getParams().setParameter("http.connection.timeout", vo.getConnectionTimeout());
+// }
+// method.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
+//
+// if(uri != null && uri.startsWith("https")){
+// Protocol.registerProtocol("https", new Protocol("https",
+// new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
+// }
+//
+// if (logger.isDebug()&& "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") URL=["+vo.getUrl()+"] ");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") PARAMETER_NAME=["+vo.getParameterName()+"] ");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") ENCODE=["+vo.getEncode()+"] ");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") RESPONSE_TYPE=["+vo.getResponseType()+"] ");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") URL_ENCODE_YN=["+vo.getUrlEncodeYn()+"] ");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") CONNECTION_TIMEOUT=["+vo.getConnectionTimeout()+"] ");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") REST_OPTION=["+restOptionData+"] ");
+// }
+//
+// if(vo.getEncode() != null && vo.getEncode().length() > 0) {
+// try {
+// mclient.getParams().setContentCharset(vo.getEncode());
+// sendData = new String(data, vo.getEncode());
+// } catch(Exception e) {
+// if(logger.isError()){
+// logger.error("HttpClientAdapterServiceRestForCODEF] ENCODE("+vo.getEncode()+") ERROR : "+ e.toString());
+// logger.error("HttpClientAdapterServiceRestForCODEF] ENCODE("+vo.getEncode()+") SKIP ");
+// }
+// }
+// }
+//
+//// if ("Y".equals(urlEncodeYn)) {
+//// sendData = java.net.URLEncoder.encode(sendData);
+//// }
+//
+// /* 레이아웃 메시지 타입이 JSON 형태만 처리 구현. REST를 처리하기 위해 아래 구성을 따라야함
+// * REST 레이아웃 구성
+// * HTTP_HEADER (X) : HTTP 헤더에 추가 정보가 필요할 경우 정의
+// * EAI_HEADER
+// * EAI_BODY
+// */
+// if (MessageType.JSON.equals(messageType)) {
+// JSONObject dataObject = parseJson(sendData);
+// if(dataObject != null) {
+// eaiHeader = dataObject.containsKey(EAI_HEADER) ? dataObject.get(EAI_HEADER) : null;
+// eaiBody = dataObject.containsKey(EAI_BODY) ? dataObject.get(EAI_BODY) : null;
+// }
+// }
+//
+// switch (HttpMethodType.getValue(rmethod)) {
+// case GET :
+// case DELETE :
+// HashMap h = getParameters(eaiHeader);
+// NameValuePair[] params = new NameValuePair[h.size()];
+// int count =0;
+// for(String key : h.keySet()){
+// String value = h.get(key);
+// params[count] = new NameValuePair(key, URLEncoder.encode(value, vo.getEncode()));
+// count++;
+// }
+// method.setQueryString(params);
+// break;
+// case PUT :
+// case POST :
+// // OpenAPI는 json 타입. type이 다른 경우 헤더정보를 별도로 받아야함
+// method.setRequestHeader(HEADER_CONTENT_TYPE, "application/json; charset="+vo.getEncode());
+// if(eaiBody != null) {
+// ((EntityEnclosingMethod) method).setRequestBody(URLEncoder.encode(eaiBody.toString(), vo.getEncode()));
+// }
+//
+// break;
+// default :
+// break;
+// }
+//
+// AccessTokenManager tokenManager = AccessTokenManager.getInstance();
+// OAuth2AccessTokenVO accessToken = (OAuth2AccessTokenVO) tokenManager.getAccessTokenVO(vo.getAdapterGroupName());
+//
+// // 토큰이 없거나 토큰이 만료 됐으면 재발급
+// if (accessToken == null || accessToken.isExpired()) {
+// accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop);
+// }
+//
+// method.setRequestHeader("Authorization", accessToken.getAuthorization());
+//
+// if (logger.isDebug()&& "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") TOKEN=["+accessToken+"] ");
+// }
+//
+// // header 셋팅
+// if (header.size() > 0) {
+// for (String key : header.keySet()) {
+// method.setRequestHeader(key, header.get(key));
+// }
+// }
+//
+// int status = -1;
+//
+// try {
+//
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName()+") = ["+sendData+"]");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(sendData.getBytes()));
+// }
+// StopWatch stopWatch = new StopWatch();
+// stopWatch.start();
+//
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "SEND ["+sendData+"]"+CommonLib.getDumpMessage(sendData.getBytes()));
+// }
+// status = mclient.executeMethod(method);
+//
+// stopWatch.stop();
+//
+// //status 200(정상) 이외에는 error 처리
+// if (status !=200){
+// try{
+// logger.error("HttpClientAdapterServiceRestForCODEF] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
+// }catch(Exception e){
+// logger.error(e);
+// }
+// throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
+// }
+//
+// byte[] responseMessage = method.getResponseBody();
+//
+// //----------------------------------------------------------
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceRestForCODEF] responseType ="+ vo.getResponseType());
+// logger.debug("HttpClientAdapterServiceRestForCODEF] RECV ("+vo.getAdapterGroupName()+") = ["+new String(responseMessage)+"]");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] RECV ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(responseMessage));
+// }
+// if ("ASYNC".equals(vo.getResponseType())) {
+// if (stopWatch.getTime() > vo.getSlowTranTime()) {
+// if (logger.isInfo()){
+// logger.info("HttpClientAdapterServiceRestForCODEF] dummy response time = " + stopWatch.toString()+ " responseMessage=" + new String(responseMessage));
+// }
+// }
+// if ( ! java.util.Arrays.equals(ElinkConfig.getAsyncDummyDataForAdapterGroup(adptGrpName).getBytes(), responseMessage)){
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"http return fail value= ["+responseMessage+"]" + CommonLib.getDumpMessage(responseMessage));
+// }
+// throw new Exception ("http return fail value= " + new String(responseMessage));
+// }
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),"RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage));
+// }
+// return null;
+// } else {
+// /* OAuth 토큰 응답 체크
+// *
+// * OAuth 응답 코드
+// * invalid_token
+// */
+// JSONObject message = parseJson(URLDecoder.decode(new String(responseMessage), vo.getEncode()));
+// if(message == null) {
+// throw new Exception("responseMessage parsing result is NULL");
+// }
+//
+// String rspCode = (String) message.get("error");
+// String rspMessage = (String) message.get("message");
+//
+// // OAuth 토큰 재요청 코드 확인
+// if (RETRY_RESPONSE_CODE.contains(rspCode)) {
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceRestForCODEF] retry access token response code= ["+rspCode+"] message= ["+rspMessage+"]");
+// }
+//
+// // 토큰 재발급
+// accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop);
+// method.setRequestHeader("Authorization", accessToken.getAuthorization());
+//
+// if (logger.isDebug()&& "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceRestForCODEF] SEND ("+vo.getAdapterGroupName() +") RETRY TOKEN=["+accessToken+"] ");
+// }
+//
+// try {
+// status = mclient.executeMethod(method);
+// } catch (java.net.ConnectException e ) {
+// throw new Exception ("retry excuteMethod Exceptioin = " + e.toString());
+// }
+//
+// //status 200(정상) 이외에는 error 처리
+// if (status !=200) {
+// throw new Exception ("retry http receive status fail value= " + status + " adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName() + " uri =" +uri +" method=" +rmethod);
+// }
+//
+// responseMessage = method.getResponseBody();
+//
+// if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+// logger.debug("HttpClientAdapterServiceRestForCODEF] responseType ="+ vo.getResponseType());
+// logger.debug("HttpClientAdapterServiceRestForCODEF] retry RECV ("+vo.getAdapterGroupName()+") = ["+new String(responseMessage)+"]");
+// logger.debug("HttpClientAdapterServiceRestForCODEF] retry RECV ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(responseMessage));
+// }
+// }
+// }
+//
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage));
+// }
+//
+// String decodedMsg = URLDecoder.decode(new String(responseMessage), vo.getEncode());
+//
+// return decodedMsg.getBytes(vo.getEncode());
+// } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceRestForCODEF] SocketTimeoutException ("+vo.getAdapterGroupName()+") : " + ste.toString(),ste);
+// }
+// logger.error("HttpClientAdapterServiceRestForCODEF] SocketTimeoutException ("+vo.getAdapterGroupName()+") : " + ste.toString() ,ste);
+// throw ste;
+// } catch(ConnectException ce) {
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceRestForCODEF] Connection Exception ("+vo.getAdapterGroupName()+") : " + ce.toString(),ce);
+// }
+// logger.error("HttpClientAdapterServiceRestForCODEF] Connection Exception ("+vo.getAdapterGroupName()+") : " + ce.toString() ,ce);
+// throw ce;
+// } catch(Exception e) {
+// if (vo.getTraceLevel() >= 3) {
+// HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),e.toString(),e);
+// }
+// logger.error("HttpClientAdapterServiceRestForCODEF] Exception ("+vo.getAdapterGroupName()+") : " + e.toString() ,e);
+// throw e;
+// } finally {
+// if(method != null) method.releaseConnection();
+// if(status != HttpStatus.SC_OK) {
+// String[] msgArgs = new String[1];
+// msgArgs[0] = String.valueOf(status);
+// String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+// if(logger.isDebug()){
+// logger.debug(resMsg);
+// }
+// }
+// }
+//
+// }
+//
+// private HashMap getParameters(Object message) throws Exception {
+//
+// HashMap result = new HashMap();
+//
+// if (message != null) {
+// if (message instanceof JSONObject) {
+// JSONObject jsonObject = (JSONObject) message;
+// for (Object key : jsonObject.keySet()) {
+// result.put((String) key, (String) jsonObject.get(key));
+// }
+// } else {
+// String[] messages = ((String) message).split("&");
+// String[] data = null;
+//
+// for (int i=0; i< messages.length;i++) {
+// data = messages[i].split("=",2);
+// if (data.length == 2 ){
+// result.put(data[0], data[1]);
+// }
+// }
+// }
+// }
+//
+// return result;
+// }
+//
+// private JSONObject parseJson(String message) throws Exception {
+// if (message == null) return null;
+//
+// return (JSONObject) JSONValue.parse(message);
+// }
+//
+// private Document convertXmlDocument(String message) throws Exception{
+// SAXReader builder = new SAXReader();
+// Document document = builder.read(new StringReader(message));
+// return document;
+// }
+//
+//// private Map changeUrlWithMessage(String messageType, String url, String extraPath, String sendData){
+//// Map responseMap = new HashMap();
+////
+//// try {
+//// if (MessageType.JSON.equals(messageType)) {
+//// JSONObject jsonObject = parseJson(sendData);
+//// url = changeUrl(messageType, url, extraPath, jsonObject);
+//// responseMap.put(URL, url);
+//// } else if (MessageType.XML.equals(messageType)) {
+//// Document doc = convertXmlDocument(sendData);
+//// url = changeUrl(messageType, url, extraPath, doc);
+//// responseMap.put(URL, url);
+//// }
+//// } catch (Exception e) {
+//// logger.error("Failed to change url",e);
+//// }
+//// return responseMap;
+//// }
+//
+// private String changeUrl(String messageType, String url, String restOption, Object sendData) {
+// if ((MessageType.JSON.equals(messageType) || MessageType.XML.equals(messageType))) {
+// try {
+// if(StringUtils.isBlank(restOption)) {
+// return url;
+// }
+// JSONObject restOptionObject = parseJson(restOption);
+// if(restOptionObject == null) throw new Exception("restOption is null");
+//
+// String type = (String) restOptionObject.get("type");
+// String extraPath = (String) restOptionObject.get("extraPath") ;
+// String method = (String) restOptionObject.get("method");
+// url = getUrl(url, extraPath);
+// if (TYPE_VARIABLE_URL_REQUEST.equals(type)) {
+// HashMap uriVariables = new HashMap();
+// if (MessageType.JSON.equals(messageType)) {
+// JSONObject jsonObject = null;
+// JSONObject dataObject = null;
+// if (sendData instanceof JSONObject) {
+// jsonObject = (JSONObject) sendData;
+// } else {
+// jsonObject = (JSONObject) JSONValue.parse((String)sendData);
+// }
+//
+// switch (HttpMethodType.getValue(method)) {
+// case GET :
+// case DELETE :
+// dataObject = jsonObject.containsKey(EAI_HEADER) ? (JSONObject) jsonObject.get(EAI_HEADER) : null;
+// break;
+// case PUT :
+// case POST :
+// dataObject = jsonObject.containsKey(EAI_BODY) ? (JSONObject) jsonObject.get(EAI_BODY) : null;
+// break;
+// }
+//
+// if(dataObject != null) {
+// for (Object key : dataObject.keySet()) {
+// if (url.indexOf("{" + (String) key + "}") > 0) {
+// uriVariables.put((String) key, (String) dataObject.get(key));
+// }
+// }
+// }
+// } else if(MessageType.XML.equals(messageType)) {
+// Document doc ;
+// if (sendData instanceof Document) {
+// doc = (Document) sendData;
+// } else {
+// doc = convertXmlDocument((String)sendData);
+// }
+// if(doc !=null) {
+// for (Object branch : doc.content()) {
+// Element element = (Element) branch;
+//
+// if (url.indexOf("{" + element.getName() + "}") > 0) {
+// uriVariables.put(element.getName(), element.getText());
+// }
+// }
+//
+//// for (Object tempObject : uriVariables) {
+//// String urlVaribleId = (String) tempObject;
+//// Element element = (Element) doc.selectSingleNode("//"+urlVaribleId);
+//// urlVariableList.add(element.getText());
+//// if (doc.getRootElement() == element) {
+////// doc = null;
+//// break;
+//// } else {
+//// element.getParent().remove(element);
+//// }
+//// }
+// }
+// }
+//
+// if (uriVariables.size() > 0) {
+// UriComponents uriComponents = UriComponentsBuilder.fromUriString(url).buildAndExpand(uriVariables);
+// url = uriComponents.toUriString();
+// logger.debug("HttpClientAdapterServiceRestForCODEF] after extand url=["+url+"] ");
+// }
+// }
+// } catch(Exception e) {
+// logger.error("Failed to change url",e);
+// }
+// }
+// return url;
+// }
+//
+// private String getUrl(String baseUrl, String extraPath) {
+// if (StringUtils.isBlank(extraPath)) {
+// return baseUrl;
+// }
+// if (baseUrl != null && baseUrl.endsWith("/") == false) {
+// baseUrl += "/";
+// }
+// String targetUrl = baseUrl + extraPath;
+// logger.debug("HttpClientAdapterServiceRestForCODEF] after concatenate url=["+targetUrl+"] ");
+// return targetUrl;
+// }
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRestForKFTC.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRestForKFTC.java
new file mode 100644
index 0000000..415fefc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceRestForKFTC.java
@@ -0,0 +1,492 @@
+package com.eactive.eai.adapter.http.client.impl;
+
+import java.io.StringReader;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.HttpVersion;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.time.StopWatch;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpMethodType;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.env.ElinkConfig;
+import com.openbanking.eai.common.token.AccessTokenManager;
+import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
+
+public class HttpClientAdapterServiceRestForKFTC extends HttpClientAdapterServiceSupport
+ implements HttpClientAdapterServiceKey {
+
+ public static final String TYPE_VARIABLE_URL_REQUEST = "variableUrlRequest";
+ public static final String TYPE_SIMPLE_REQUEST = "simpleRequest";
+
+ public static final String HTTP_HEADER = "HTTP_HEADER";
+ public static final String EAI_HEADER = "EAI_HEADER";
+ public static final String EAI_BODY = "EAI_BODY";
+
+ public static final String REST_OPTION = "REST_OPTION";
+ public static final String REST_TYPE = "type";
+ public static final String REST_EXTRA_PATH = "extraPath";
+ public static final String REST_METHOD = "method";
+
+ public static final String HEADER_CONTENT_TYPE = "Content-Type";
+
+ public static final List RETRY_RESPONSE_CODE = Arrays.asList("O0001", "O0002", "O0003");
+
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+
+ // 레이아웃 메세지 타입 REST URL 추출 시 활용. Default JSON
+ String messageType = prop.getProperty("MESSAGE_TYPE", MessageType.JSON);
+ /* TSEAIHE02.RESTOPTION 정보 -> JSON 형태로 구성
+ * type : simpleRequest, variableUrlRequest
+ * extraPath : 어댑터 프로퍼티 URL에 추가될 HTTP REST URL
+ * method : get, delete, post, put
+ *
+ * ex) {"type":"simpleRequest", "extraPath":"v2.0/account/balance", "method": "post"}
+ */
+
+ String restOptionData = tempProp.getProperty(REST_OPTION);
+
+ JSONObject restOptionObject = parseJson(restOptionData);
+ if (restOptionObject == null) {
+ throw new Exception("OptionData parsing result is NULL");
+ }
+ String rmethod = restOptionObject.containsKey("method")
+ ? StringUtils.upperCase((String) restOptionObject.get("method"))
+ : "POST";
+
+ Object eaiHeader = null;
+ Object eaiBody = null;
+ HttpClient mclient = this.client;
+
+
+
+ String sendData = "";
+ if (data instanceof byte[]) {
+ sendData = new String((byte[]) data, vo.getEncode());
+ } else if (data instanceof String) {
+ sendData = (String) data;
+ }
+
+ HashMap header = new HashMap();
+ //interface 에 설정된게 우선한다.
+ String uri = changeUrl(messageType, vo.getUrl(), restOptionData, sendData);
+
+ HttpMethodBase method = null;
+ switch (HttpMethodType.getValue(rmethod)) {
+ case GET :
+ method = new GetMethod(uri);
+ break;
+ case DELETE :
+ method = new DeleteMethod(uri);
+ break;
+ case POST :
+ method = new PostMethod(uri);
+ break;
+ case PUT :
+ method = new PutMethod(uri);
+ break;
+ default :
+ // set default method
+ method = new GetMethod(uri);
+ break;
+ }
+
+
+
+ if (logger.isDebug()&& "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") URL=["+vo.getUrl()+"] ");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") PARAMETER_NAME=["+vo.getParameterName()+"] ");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") ENCODE=["+vo.getEncode()+"] ");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") RESPONSE_TYPE=["+vo.getResponseType()+"] ");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") URL_ENCODE_YN=["+vo.getUrlEncodeYn()+"] ");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") CONNECTION_TIMEOUT=["+vo.getConnectionTimeout()+"] ");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") REST_OPTION=["+restOptionData+"] ");
+ }
+
+ configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
+
+ if ("Y".equals(vo.getUrlEncodeYn())) {
+ sendData = java.net.URLEncoder.encode(sendData);
+ }
+
+ /* 레이아웃 메시지 타입이 JSON 형태만 처리 구현. REST를 처리하기 위해 아래 구성을 따라야함
+ * REST 레이아웃 구성
+ * HTTP_HEADER (X) : HTTP 헤더에 추가 정보가 필요할 경우 정의
+ * EAI_HEADER
+ * EAI_BODY
+ */
+ if (MessageType.JSON.equals(messageType)) {
+ JSONObject dataObject = parseJson(sendData);
+ if(dataObject != null) {
+ eaiHeader = dataObject.containsKey(EAI_HEADER) ? dataObject.get(EAI_HEADER) : null;
+ eaiBody = dataObject.containsKey(EAI_BODY) ? dataObject.get(EAI_BODY) : null;
+ }
+ }
+
+ switch (HttpMethodType.getValue(rmethod)) {
+ case GET :
+ case DELETE :
+ HashMap h = getParameters(eaiHeader);
+ NameValuePair[] params = new NameValuePair[h.size()];
+ int count =0;
+ for(String key : h.keySet()){
+ String value = h.get(key);
+ params[count] = new NameValuePair(key,value);
+ count++;
+ }
+ method.setQueryString(params);
+ break;
+ case PUT :
+ case POST :
+ // OpenAPI는 json 타입. type이 다른 경우 헤더정보를 별도로 받아야함
+ method.setRequestHeader(HEADER_CONTENT_TYPE, "application/json; charset="+vo.getEncode());
+ if(eaiBody != null) {
+ ((EntityEnclosingMethod) method).setRequestBody(eaiBody.toString());
+ }
+
+ break;
+ default :
+ break;
+ }
+
+ AccessTokenManager tokenManager = AccessTokenManager.getInstance();
+ OAuth2AccessTokenVO accessToken = (OAuth2AccessTokenVO) tokenManager.getAccessTokenVO(vo.getAdapterGroupName());
+
+ // 토큰이 없거나 토큰이 만료 됐으면 재발급
+ if (accessToken == null || accessToken.isExpired()) {
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop, oldToken);
+ }
+
+ method.setRequestHeader("Authorization", accessToken.getAuthorization());
+
+ if (logger.isDebug()&& "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") TOKEN=["+accessToken+"] ");
+ }
+
+ // header 셋팅
+ if (header.size() > 0) {
+ for (String key : header.keySet()) {
+ method.setRequestHeader(key, header.get(key));
+ }
+ }
+
+ int status = -1;
+
+ try {
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName()+") = ["+sendData+"]");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(sendData));
+ }
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "SEND ["+sendData+"]"+CommonLib.getDumpMessage(sendData));
+ }
+ status = mclient.executeMethod(method);
+
+ stopWatch.stop();
+
+ //status 200(정상) 이외에는 error 처리
+ if (status !=200){
+ try{
+ logger.error("HttpClientAdapterServiceRestForKFTC] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
+ }catch(Exception e){
+ logger.error(e);
+ }
+ throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
+ }
+
+ byte[] responseMessage = method.getResponseBody();
+
+ //----------------------------------------------------------
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRestForKFTC] responseType ="+ vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceRestForKFTC] RECV ("+vo.getAdapterGroupName()+") = ["+new String(responseMessage)+"]");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] RECV ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(responseMessage));
+ }
+ if ("ASYNC".equals(vo.getResponseType())) {
+ if (stopWatch.getTime() > vo.getSlowTranTime()) {
+ if (logger.isInfo()){
+ logger.info("HttpClientAdapterServiceRestForKFTC] dummy response time = " + stopWatch.toString()+ " responseMessage=" + new String(responseMessage));
+ }
+ }
+ if ( ! java.util.Arrays.equals(ElinkConfig.getAsyncDummyDataForAdapterGroup(vo.getAdapterGroupName()).getBytes(), responseMessage)){
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"http return fail value= ["+responseMessage+"]" + CommonLib.getDumpMessage(responseMessage));
+ }
+ throw new Exception ("http return fail value= " + new String(responseMessage));
+ }
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(),"RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage));
+ }
+ return null;
+ } else {
+ /* OAuth 토큰 응답 체크
+ *
+ * OAuth 응답 코드
+ * O0001 인증요청 거부-인증 파라미터 오류([error_code])
+ * O0002 Access Token 거부
+ * O0003 Access Token 만료
+ */
+ JSONObject message = parseJson(new String(responseMessage, vo.getEncode()));
+ if(message == null) {
+ throw new Exception("responseMessage parsing result is NULL");
+ }
+
+ String rspCode = (String) message.get("rsp_code");
+ String rspMessage = (String) message.get("rsp_message");
+
+ // OAuth 토큰 재요청 코드 확인
+ if (RETRY_RESPONSE_CODE.contains(rspCode)) {
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRestForKFTC] retry access token response code= ["+rspCode+"] message= ["+rspMessage+"]");
+ }
+
+ // 토큰 재발급
+ String oldToken = accessToken == null ? null : accessToken.getAccessToken();
+ accessToken = (OAuth2AccessTokenVO) tokenManager.retryAccessTokenVO(vo.getAdapterGroupName(), prop, oldToken);
+ method.setRequestHeader("Authorization", accessToken.getAuthorization());
+
+ if (logger.isDebug()&& "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRestForKFTC] SEND ("+vo.getAdapterGroupName() +") RETRY TOKEN=["+accessToken+"] ");
+ }
+
+ try {
+ status = mclient.executeMethod(method);
+ } catch (java.net.ConnectException e ) {
+ throw new Exception ("retry excuteMethod Exceptioin = " + e.toString());
+ }
+
+ if (status !=200) {
+ throw new Exception ("retry http receive status fail value= " + status + " adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName() + " uri =" +uri +" method=" +rmethod);
+ }
+
+ responseMessage = method.getResponseBody();
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapterServiceRestForKFTC] responseType ="+ vo.getResponseType());
+ logger.debug("HttpClientAdapterServiceRestForKFTC] retry RECV ("+vo.getAdapterGroupName()+") = ["+new String(responseMessage)+"]");
+ logger.debug("HttpClientAdapterServiceRestForKFTC] retry RECV ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(responseMessage));
+ }
+ }
+ }
+
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage)+"]"+CommonLib.getDumpMessage(responseMessage));
+ }
+
+ return responseMessage;
+
+ } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceRestForKFTC] SocketTimeoutException ("+vo.getAdapterGroupName()+") : " + ste.toString(),ste);
+ }
+ logger.error("HttpClientAdapterServiceRestForKFTC] SocketTimeoutException ("+vo.getAdapterGroupName()+") : " + ste.toString() ,ste);
+ throw ste;
+ } catch(ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServiceRestForKFTC] Connection Exception ("+vo.getAdapterGroupName()+") : " + ce.toString(),ce);
+ }
+ logger.error("HttpClientAdapterServiceRestForKFTC] Connection Exception ("+vo.getAdapterGroupName()+") : " + ce.toString() ,ce);
+ throw ce;
+ } catch(Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),e.toString(),e);
+ }
+ logger.error("HttpClientAdapterServiceRestForKFTC] Exception ("+vo.getAdapterGroupName()+") : " + e.toString() ,e);
+ throw e;
+ } finally {
+ if(method != null) method.releaseConnection();
+ if(status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if(logger.isDebug()){
+ logger.debug(resMsg);
+ }
+ }
+ }
+
+ }
+
+ private HashMap getParameters(Object message) throws Exception {
+ HashMap result = new HashMap();
+ if (message != null) {
+ if (message instanceof JSONObject) {
+ JSONObject jsonObject = (JSONObject) message;
+ for (Object key : jsonObject.keySet()) {
+ result.put((String) key, (String) jsonObject.get(key));
+ }
+ } else {
+ String[] messages = ((String) message).split("&");
+ String[] data = null;
+
+ for (int i=0; i< messages.length;i++) {
+ data = messages[i].split("=",2);
+ if (data.length == 2 ){
+ result.put(data[0], data[1]);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private JSONObject parseJson(String message) throws Exception {
+ if (message == null) return null;
+
+ return (JSONObject) JSONValue.parse(message);
+ }
+
+ private Document convertXmlDocument(String message) throws Exception{
+ SAXReader builder = new SAXReader();
+ Document document = builder.read(new StringReader(message));
+ return document;
+ }
+
+// private Map changeUrlWithMessage(String messageType, String url, String extraPath, String sendData){
+// Map responseMap = new HashMap();
+//
+// try {
+// if (MessageType.JSON.equals(messageType)) {
+// JSONObject jsonObject = parseJson(sendData);
+// url = changeUrl(messageType, url, extraPath, jsonObject);
+// responseMap.put(URL, url);
+// } else if (MessageType.XML.equals(messageType)) {
+// Document doc = convertXmlDocument(sendData);
+// url = changeUrl(messageType, url, extraPath, doc);
+// responseMap.put(URL, url);
+// }
+// } catch (Exception e) {
+// logger.error("Failed to change url",e);
+// }
+// return responseMap;
+// }
+
+ private String changeUrl(String messageType, String url, String restOption, Object sendData) {
+ if ((MessageType.JSON.equals(messageType) || MessageType.XML.equals(messageType))) {
+ try {
+ if (StringUtils.isBlank(restOption)) {
+ return url;
+ }
+ JSONObject restOptionObject = parseJson(restOption);
+ if (restOptionObject == null)
+ throw new Exception("restOption is null");
+
+ String type = (String) restOptionObject.get("type");
+ String extraPath = (String) restOptionObject.get("extraPath");
+ String method = (String) restOptionObject.get("method");
+ url = getUrl(url, extraPath);
+ if (TYPE_VARIABLE_URL_REQUEST.equals(type)) {
+ HashMap uriVariables = new HashMap();
+ if (MessageType.JSON.equals(messageType)) {
+ JSONObject jsonObject = null;
+ JSONObject dataObject = null;
+ if (sendData instanceof JSONObject) {
+ jsonObject = (JSONObject) sendData;
+ } else {
+ jsonObject = (JSONObject) JSONValue.parse((String) sendData);
+ }
+
+ switch (HttpMethodType.getValue(method)) {
+ case GET:
+ case DELETE:
+ dataObject = jsonObject.containsKey(EAI_HEADER) ? (JSONObject) jsonObject.get(EAI_HEADER)
+ : null;
+ break;
+ case PUT:
+ case POST:
+ dataObject = jsonObject.containsKey(EAI_BODY) ? (JSONObject) jsonObject.get(EAI_BODY)
+ : null;
+ break;
+ }
+
+ if (dataObject != null) {
+ for (Object key : dataObject.keySet()) {
+ if (url.indexOf("{" + (String) key + "}") > 0) {
+ uriVariables.put((String) key, (String) dataObject.get(key));
+ }
+ }
+ }
+ } else if (MessageType.XML.equals(messageType)) {
+ Document doc;
+ if (sendData instanceof Document) {
+ doc = (Document) sendData;
+ } else {
+ doc = convertXmlDocument((String) sendData);
+ }
+ if (doc != null) {
+ for (Object branch : doc.content()) {
+ Element element = (Element) branch;
+
+ if (url.indexOf("{" + element.getName() + "}") > 0) {
+ uriVariables.put(element.getName(), element.getText());
+ }
+ }
+ }
+ }
+
+ if (uriVariables.size() > 0) {
+ UriComponents uriComponents = UriComponentsBuilder.fromUriString(url)
+ .buildAndExpand(uriVariables);
+ url = uriComponents.toUriString();
+ logger.debug("HttpClientAdapterServiceRestForKFTC] after extand url=[" + url + "] ");
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Failed to change url", e);
+ }
+ }
+ return url;
+ }
+
+ private String getUrl(String baseUrl, String extraPath) {
+ if (StringUtils.isBlank(extraPath)) {
+ return baseUrl;
+ }
+ if (baseUrl != null && baseUrl.endsWith("/") == false) {
+ baseUrl += "/";
+ }
+ String targetUrl = baseUrl + extraPath;
+ logger.debug("HttpClientAdapterServiceRestForKFTC] after concatenate url=[" + targetUrl + "] ");
+ return targetUrl;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceSoap.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceSoap.java
new file mode 100644
index 0000000..f2dc8d5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/HttpClientAdapterServiceSoap.java
@@ -0,0 +1,134 @@
+package com.eactive.eai.adapter.http.client.impl;
+
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+import org.apache.commons.httpclient.methods.PostMethod;
+
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
+import com.eactive.eai.common.exception.ExceptionUtil;
+
+public class HttpClientAdapterServiceSoap extends HttpClientAdapterServiceSupport {
+
+ public Object execute(Properties prop, Object data, Properties tempProp) throws Exception {
+
+ HttpClientAdapterVO vo = super.setting(prop, tempProp);
+ String soapAction = prop.getProperty(METHOD_SOAP_ACTION);
+ if (soapAction != null)
+ soapAction = soapAction.trim();
+
+ if (logger.isDebug() && "N".equals(vo.getTestCallYn())) {
+ logger.debug("HttpClientAdapter] SEND (" + vo.getMethod() + ") ");
+ }
+ PostMethod method = new PostMethod(vo.getUrl());
+ if (vo.getTimeout() > -1) {
+ method.getParams().setSoTimeout(vo.getTimeout());
+ }
+ HttpClient mclient = this.client;
+
+ byte[] sendBytes = null;
+ if (data instanceof String) {
+ sendBytes = ((String) data).getBytes(vo.getEncode());
+ } else if (data instanceof byte[]) {
+ sendBytes = (byte[]) data;
+ }
+ ByteArrayRequestEntity entity = new ByteArrayRequestEntity(sendBytes);
+
+ method.setRequestEntity(entity);
+ method.setRequestHeader("SOAPAction", soapAction);
+
+ int status = -1;
+
+ configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
+
+ try {
+ status = mclient.executeMethod(method);
+ // status 200(정상) 이외에는 error 처리
+ if (status != 200) {
+ try {
+ logger.error("HttpClientAdapterServiceSoap] receive status[" + status + "] data["
+ + new String(method.getResponseBody()) + "]");
+ } catch (Exception e) {
+ logger.error(e);
+ }
+ throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="
+ + vo.getAdapterGroupName() + "." + vo.getAdapterName(), status);
+ }
+ byte[] responseMessage = method.getResponseBody();
+ return responseMessage;
+
+ // return removeSoap(responseMessage,function).getBytes();
+
+ } catch (SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceSoap] SocketTimeoutException : " + ste.toString(), ste);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceSoap] SocketTimeoutException : " + ste.toString(), ste);
+ }
+ throw ste;
+ } catch (ConnectException ce) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceSoap] Connection Exception : " + ce.toString(), ce);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceSoap] Connection Exception : " + ce.toString(), ce);
+ }
+ throw ce;
+ } catch (Exception e) {
+ if (vo.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(vo.getAdapterGroupName() + vo.getAdapterName(),
+ "HttpClientAdapterServiceSoap] Exception : " + e.toString(), e);
+ }
+ if (logger.isError()) {
+ logger.error("HttpClientAdapterServiceSoap] Exception : " + e.toString(), e);
+ }
+ throw e;
+ } finally {
+ method.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ String[] msgArgs = new String[1];
+ msgArgs[0] = String.valueOf(status);
+ String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
+ if (logger.isDebug()) {
+ logger.debug(resMsg);
+ }
+ }
+ }
+
+ }
+// private String addSoap(String message) throws Exception {
+// StringBuffer sb = new StringBuffer();
+// sb.append("");
+// sb.append("");
+// sb.append(message);
+// sb.append(" ");
+// sb.append(" ");
+// return sb.toString();
+// }
+// private String getFunction(String message) throws Exception {
+// DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+// dbFactory.setIgnoringElementContentWhitespace(true);
+// DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
+// Document doc = docBuilder.parse(new InputSource(new StringReader(message.trim())));
+// return doc.getDocumentElement().getNodeName();
+// }
+// private String removeSoap(String result,String function) throws Exception {
+// DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+// dbFactory.setIgnoringElementContentWhitespace(true);
+// DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
+// Document doc = docBuilder.parse(new InputSource(new StringReader(result.trim())));
+// NodeList nodes = doc.getElementsByTagName(function + "Return");
+// return nodes.item(0).getFirstChild().getNodeValue();
+// }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterCustom.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterCustom.java
new file mode 100644
index 0000000..76b7414
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterCustom.java
@@ -0,0 +1,129 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.util.DatetimeUtil;
+import com.eactive.eai.common.util.InboundErrorLogger;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.UUIDGenerator;
+import com.eactive.eai.inbound.error.InboundErrorInfoVO;
+import io.undertow.servlet.handlers.DefaultServlet;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Date;
+
+public class HttpAdapterCustom extends DefaultServlet implements HttpAdapterServiceKey {
+
+ private static final long serialVersionUID = 1L;
+
+ // Adapter Logger
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ protected void service(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpDynamicPortInAdapterManager manager = HttpDynamicPortInAdapterManager.getInstance();
+ Integer localPort = request.getLocalPort();
+ String requestUrl = request.getRequestURI(); // /api/v1/public/getUserInfo.svc
+
+ HttpDynamicInAdapterUri adptUri = findAdptUri(localPort, requestUrl, manager);
+
+ if (logger.isDebug()) {
+ logger.debug("[HttpAdapterCustom] request adapter info : " + adptUri);
+ }
+
+ if (adptUri == null) {
+ logError(request, response, null);
+ return;
+ }
+
+ HttpAdapterService service = HttpAdapterServiceFactory.createFactory(adptUri.getAdptType());
+ service.service(adptUri.getAdptGrpName(), adptUri.getAdptName(), request, response);
+ }
+
+ /**
+ * url에서 뒤쪽 /이후를 제거하면서 찾는다.
+ * /api/v1/public/getUserInfo.svc
+ *
+ * @param apiUri
+ * @return
+ */
+ private HttpDynamicInAdapterUri findAdptUri(Integer localPort, String apiUri,
+ HttpDynamicPortInAdapterManager manager) {
+ apiUri = StringUtils.removeEnd(apiUri, "/");
+ if (StringUtils.isBlank(apiUri)) {
+ return null;
+ }
+
+ HttpDynamicInAdapterUri adptUri = null;
+ for (int i = 0; i < 10; i++) {
+ adptUri = manager.getAdptUri(localPort, apiUri);
+ if (adptUri != null) {
+ return adptUri;
+ }
+
+ // /api/v1/public
+ apiUri = StringUtils.substringBeforeLast(apiUri, "/");
+ if (StringUtils.isBlank(apiUri)) {
+ return manager.getAdptUri(localPort, "/");
+ }
+ }
+
+ return null;
+ }
+
+ private void logError(HttpServletRequest request, HttpServletResponse response, String msg) {
+
+ InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO();
+
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ String serverName = eaiServerManager.getLocalServerName();
+ String uuid = null;
+ StringBuffer sb = new StringBuffer();
+
+ String instanceid1 = serverName.substring(0,2);
+ String instanceid2 = serverName.substring(serverName.length()-2, serverName.length());
+ String instid = instanceid1 + instanceid2;
+ uuid = instid + UUIDGenerator.getUUID();
+
+ String[] msgArgs = new String[1];
+ msgArgs[0] = request.getRequestURI();
+
+ String errorCode = "RECEAIIRP010";
+ String errorMsg = null;
+ if (msg == null) {
+ errorMsg = ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs);
+ } else {
+ errorMsg = ExceptionUtil.make(new Exception(msg), errorCode, msgArgs);
+ }
+
+ errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호
+ errorInfoVO.setAdptBwkGrpNm("HTTP_IN_NO_URI"); // 어댑터업무그룹명
+ errorInfoVO.setErrCd(errorCode); // 에러코드
+ errorInfoVO.setErrTxt(errorMsg); // 에러내용
+ errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각
+ errorInfoVO.setErrDstcd(" ");
+ sb.append("Remote Addr : ").append(request.getRemoteAddr()).append("\n")
+ .append("Request URI : ").append(request.getRequestURI());
+ errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용
+ errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명
+
+ InboundErrorLogger.error(errorInfoVO);
+
+ response.setStatus(404);
+ try {
+ if (msg == null) {
+ response.getWriter().println("can not find uri '"+request.getRequestURI()+"'");
+ } else {
+ response.getWriter().println(msg);
+ }
+ } catch (Exception ex) {
+ // IGNORE
+ }
+
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterListener.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterListener.java
new file mode 100644
index 0000000..28b1fd4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterListener.java
@@ -0,0 +1,54 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import com.eactive.eai.adapter.listener.AdapterException;
+import com.eactive.eai.adapter.listener.AdapterListenerSupport;
+import com.eactive.eai.common.util.Logger;
+
+public class HttpAdapterListener extends AdapterListenerSupport {
+
+ final static Logger logger2 = HttpLoggerManager.getInstance().getLogger();
+ final static Logger errLogger = HttpLoggerManager.getInstance().getErrLogger();
+
+ public void start() throws AdapterException {
+ HttpDynamicPortInAdapterManager manager = HttpDynamicPortInAdapterManager.getInstance();
+ try {
+ if (info == null) {
+ throw new Exception("HttpAdapterListener | AdapterVO가 NULL입니다.");
+ }
+ manager.addAdapter(info);
+
+ try {
+ manager.start(info);
+ if(logger2.isInfo()) {
+ logger2.info("[HttpAdapterListener] AdapterName [" + info.getAdapterGroupName() + "." + info.getName()
+ + "] config [" + info + "] start");
+ }
+ } catch (Exception e) {
+ manager.removeAdapter(info);
+ throw e;
+ }
+ } catch (Exception e) {
+ logger.error(info.getName() + " | HttpAdapterListener | cannot start : " + e.getMessage(), e);
+ throw new AdapterException(info.getName() + " | HttpAdapterListener | cannot start - " + e.getMessage());
+ }
+ }
+
+ public void stop() throws AdapterException {
+ HttpDynamicPortInAdapterManager manager = HttpDynamicPortInAdapterManager.getInstance();
+ try {
+ if (info == null) {
+ throw new Exception("HttpAdapterListener | AdapterVO가 NULL입니다.");
+ }
+
+ manager.removeAdapter(info);
+ manager.stop(info);
+ if(logger2.isInfo()) {
+ logger2.info("[HttpAdapterListener] AdapterName [" + info.getAdapterGroupName() + "." + info.getName()
+ + "] adapter info [" + info + "] stop");
+ }
+ } catch (Exception e) {
+ logger.error(info.getName() + " | HttpAdapterListener | cannot stop : " + e.getMessage(), e);
+ throw new AdapterException(info.getName() + " | HttpAdapterListener | cannot stop - " + e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterMain.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterMain.java
new file mode 100644
index 0000000..498a360
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterMain.java
@@ -0,0 +1,123 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.util.DatetimeUtil;
+import com.eactive.eai.common.util.InboundErrorLogger;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.UUIDGenerator;
+import com.eactive.eai.inbound.error.InboundErrorInfoVO;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+public class HttpAdapterMain extends HttpServlet implements HttpAdapterServiceKey {
+ public void init() {
+ }
+
+ public void service(HttpServletRequest request, HttpServletResponse response) {
+ Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ HttpDynamicInAdapterManager manager = HttpDynamicInAdapterManager.getInstance();
+ String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), "");// context path 제거
+
+ String customUri = getCustomUri(orgUri, 3); // adapter name 이후 제거
+ HttpDynamicInAdapterUri adptUri = manager.getAdptUri(customUri);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpDynamicInAdapter] service request uri : " + request.getRequestURI());
+ }
+
+ if (adptUri == null) {
+ logError(request, response);
+ return;
+ }
+
+ // rest일때만 하위 uri 허용
+ if (!orgUri.equals(customUri) && !HttpAdapterServiceType.REST.toString().equals(adptUri.getAdptType())) {
+ logError(request, response);
+ return;
+ }
+
+ HttpAdapterService service = HttpAdapterServiceFactory.createFactory(adptUri.getAdptType());
+ if (service == null) {
+ logger.debug("HttpDynamicInAdapter] HttpAdapterService create Error : " + adptUri.getAdptType());
+ logError(request, response);
+ } else {
+ service.service(adptUri.getAdptGrpName(), adptUri.getAdptName(), request, response);
+ }
+ }
+
+ private void logError(HttpServletRequest request, HttpServletResponse response) {
+ Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO();
+
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+
+ String serverName = eaiServerManager.getLocalServerName();
+ String uuid = null;
+ StringBuffer sb = new StringBuffer();
+//
+// String instanceid1 = "";
+// String instanceid2 = "";
+// if(serverName != null) {
+// //juns 서버명 변경에 따른 인스턴스 룰 추출변경
+// //ex)EAIDSG_i11 => EAIDS01_i01 결과 EA11
+// instanceid1 = serverName.substring(0,2);
+// // String instanceid2 = serverName.substring(serverName.length()-2, serverName.length());
+// instanceid2 = serverName.substring(serverName.length()-5, serverName.length()-4)
+// + serverName.substring(serverName.length()-1, serverName.length());
+// }
+ String instid = eaiServerManager.getGroupInstId();
+ uuid = instid + UUIDGenerator.getUUID();
+
+ String[] msgArgs = new String[1];
+ msgArgs[0] = request.getRequestURI();
+
+ String errorCode = "RECEAIIRP010";
+ String errorMsg = ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs);
+
+ errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호
+ errorInfoVO.setAdptBwkGrpNm("HTTP_IN_NO_URI"); // 어댑터업무그룹명
+ errorInfoVO.setErrCd(errorCode); // 에러코드
+ errorInfoVO.setErrTxt(errorMsg); // 에러내용
+ errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각
+ errorInfoVO.setErrDstcd(" ");
+ sb.append("Remote Addr : ").append(request.getRemoteAddr()).append("\n").append("Request URI : ")
+ .append(request.getRequestURI());
+ errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용
+ errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명
+
+ InboundErrorLogger.error(errorInfoVO);
+
+ response.setStatus(404);
+ try {
+ response.getWriter().println("can not find uri '" + request.getRequestURI() + "'");
+ } catch (Exception ex) {
+ logger.error("write error", ex);
+ }
+
+ }
+// public static void main(String args[]) throws Exception {
+// test();
+//}
+
+// private static void test() throws Exception {
+// String orgUri = "/HTT/CbsInHttpSys/ABC/DEF";
+//// System.out.println(getCustomUri(orgUri,3));
+//
+// }
+ public static String getCustomUri(String url, int length) {
+ // return
+ // Stream.of(url.split("/")).limit(length).collect(Collectors.joining("/")) ;
+ String[] urls = url.split("/");
+ List newUrls = new ArrayList<>();
+ Collections.addAll(newUrls, urls);
+ return StringUtils.join(newUrls.subList(0, length).toArray(), "/");
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterService.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterService.java
new file mode 100644
index 0000000..d0259af
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterService.java
@@ -0,0 +1,9 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public interface HttpAdapterService {
+ public abstract void service(String adptGrpName, String adptName, HttpServletRequest request,
+ HttpServletResponse response);
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceFactory.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceFactory.java
new file mode 100644
index 0000000..6a7cf33
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceFactory.java
@@ -0,0 +1,43 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.eactive.eai.common.util.Logger;
+
+public class HttpAdapterServiceFactory {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ static private ConcurrentHashMap h = new ConcurrentHashMap();
+
+ /**
+ *
+ */
+ public HttpAdapterServiceFactory() {
+ super();
+ }
+
+ /**
+ * 공통코드 HTTP_ADAPTER_SERVICE_CLASS 에 정의된 구현체를 생성 한다.
+ *
+ * @param className
+ * @return
+ */
+ @SuppressWarnings("rawtypes")
+ public static HttpAdapterService createFactory(String className) {
+ if (h.containsKey(className)) {
+ return h.get(className);
+ }
+
+ HttpAdapterService service = null;
+ try {
+ Class cl = Class.forName(className);
+ service = (HttpAdapterService) cl.newInstance();
+ if (service != null) {
+ h.put(className, service);
+ }
+ } catch (Exception e) {
+ logger.error("Cannot create a HttpAdapterService. - {}", className);
+ }
+
+ return service;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceKey.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceKey.java
new file mode 100644
index 0000000..4bc9084
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceKey.java
@@ -0,0 +1,77 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+public interface HttpAdapterServiceKey {
+ // URL 파리미터 DEFAULT 이름
+ static final String PARAMETER_MESSAGE = "_message_";
+
+ // URL 파리미터 이름
+ static final String PARAMETER_NAME = "PARAMETER_NAME";
+
+ // Http Adapter 이름
+ static final String HTTP_ADAPTER_NAME = "HTTP_ADAPTER_NAME";
+
+ // Http Adapter Group 이름
+ static final String HTTP_ADAPTER_GROUP_NAME = "HTTP_ADAPTER_GROUP_NAME";
+
+ // Http Response Type 이름
+ static final String RESPONSE_TYPE = "RESPONSE_TYPE";
+
+ public static final String RESPONSE_TYPE_SYNC = "SYNC";
+ public static final String RESPONSE_TYPE_ASYNC = "ASYN";
+
+ // Http Encode 이름
+ static final String ENCODE = "ENCODE";
+
+ // Http URL Decode 여부
+ static final String URL_DECODE_YN = "URL_DECODE_YN";
+
+ // Body data 사용 여부
+ static final String REQUEST_BODY_YN = "REQUEST_BODY_YN";
+
+ // 삭제할 데이타 길이
+ static final String REMOVE_LENGTH = "REMOVE_LENGTH";
+
+ // 추가할 데이타
+ static final String ADD_DATA = "ADD_DATA";
+
+ // 거래 로그
+ static final String TRACE_LEVEL = "TRACE_LEVEL";
+
+ static final String ERROR_RESPONSE_FORMAT = "ERROR_RESPONSE_FORMAT";
+
+ // REST용 전달값
+ static final String INBOUND_METHOD = "INBOUND_METHOD";
+ static final String INBOUND_URI = "INBOUND_URI";
+ static final String INBOUND_EXTURI = "INBOUND_EXTURI";
+ static final String INBOUND_HEADER = "INBOUND_HEADER";
+ static final String INBOUND_QUERY_STRING = "INBOUND_QUERY_STRING";
+ static final String INBOUND_REWRITE_PATH = "INBOUND_REWRITE_PATH";
+ static final String INBOUND_REMOTE_ADDR = "INBOUND_REMOTE_ADDR";
+ static final String INBOUND_SCHEME = "INBOUND_SCHEME";
+ static final String INBOUND_PATH_VARIABLES = "INBOUND_PATH_VARIABLES";
+ static final String INBOUND_REQUEST_MESSAGE = "INBOUND_REQUEST_MESSAGE";
+ static final String INBOUND_CLIENT_IP = "INBOUND_CLIENT_IP";
+
+ static final String INBOUND_SYNC_ASYNC_TYPE = "INBOUND_SYNC_ASYNC_TYPE";
+
+ public static final String OUTBOUND_RESPONSE_HEADERS = "OUTBOUND_RESPONSE_HEADERS";
+ public static final String OUTBOUND_RESPONSE_MESSAGE = "OUTBOUND_RESPONSE_MESSAGE";
+ public static final String OUTBOUND_RESPONSE_STATUS = "OUTBOUND_RESPONSE_STATUS";
+ public static final String OUTBOUND_PROPERTY_MAP = "OUTBOUND_PROPERTY_MAP";
+
+ // API path
+ static final String API_PATH = "API_PATH";
+
+ // 요청전 수행할 필터(쉼표(,)로 구분)
+ static final String PRE_FILTERS = "PRE_FILTERS";
+
+ // 요청후 수행할 필터(쉼표(,)로 구분)
+ static final String POST_FILTERS = "POST_FILTERS";
+
+ static final String ALLOW_IP = "ALLOW_IP";
+
+ static final String ENC_PATHS = "ENC_PATHS";
+
+ //응답 처리 용 표준 전문 오브젝트
+ static final String STANDARD_MESSAGE_OBJECT = "STANDARD_MESSAGE_OBJECT";
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceSupport.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceSupport.java
new file mode 100644
index 0000000..0077de4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceSupport.java
@@ -0,0 +1,122 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.RequestDispatcher;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilter;
+import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilterFactory;
+import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilterType;
+import com.eactive.eai.data.entity.onl.adapter.AdapterProp;
+
+public abstract class HttpAdapterServiceSupport implements HttpAdapterService, HttpAdapterServiceKey {
+ protected long slowTranTime = 2000L;
+ public static final String HEADER_NAME_CLIENT_ID = "x-elink-client-id";
+ public static final String PROPERTIES_NAME_CLIENT_ID = "clientId";
+
+ public Object service(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ try {
+ String clientId = request.getHeader(HEADER_NAME_CLIENT_ID);
+ if (StringUtils.isNotBlank(clientId)) {
+ prop.put(PROPERTIES_NAME_CLIENT_ID, clientId);
+ }
+
+ String transactionId = request.getHeader(HttpClientAdapterServiceKey.TRANSACTION_ID);
+ if (StringUtils.isNotBlank(transactionId)) {
+ prop.put(HttpClientAdapterServiceKey.TRANSACTION_ID, transactionId);
+ }
+
+ String instanceId = request.getHeader(HttpClientAdapterServiceKey.INSTANCE_ID);
+ if (StringUtils.isNotBlank(instanceId)) {
+ prop.put(HttpClientAdapterServiceKey.INSTANCE_ID, instanceId);
+ }
+ } catch (Exception e) {
+ }
+
+ message = doPreFilters(adptGrpName, adptName, message, prop, request, response);
+ Object obj = RequestDispatcher.getRequestDispatcher(adptGrpName).handle(adptName, message, prop);
+ obj = doPostFilters(adptGrpName, adptName, obj, prop, request, response);
+ if (obj == null) {
+ return null;
+ } else if (obj instanceof byte[]) {
+ return (byte[]) obj;
+ } else if (obj instanceof String) {
+ return (String) obj;
+ } else {
+ throw new Exception("RECEAIAHA001");
+ }
+ }
+
+ private Object doPreFilters(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ AdapterManager manager = AdapterManager.getInstance();
+ AdapterGroupVO group = manager.getAdapterGroup(adptGrpName);
+
+ if (!"HTC".equals(group.getType())) {
+ String allowIp = prop.getProperty(ALLOW_IP,"");
+ if (StringUtils.isNotBlank(allowIp)) {
+ HttpAdapterFilter adapterFilter = HttpAdapterFilterFactory.createFilter(HttpAdapterFilterType.ADAPTERALLOWIPLISTFILTER.toString());
+ if (adapterFilter != null) {
+ message = adapterFilter.doPreFilter(adptGrpName, adptName, message, prop, request, response);
+ }
+ }
+ }
+
+ String preFiltersStr = prop.getProperty(PRE_FILTERS);
+ if (StringUtils.isBlank(preFiltersStr)) {
+ return message;
+ }
+
+ String[] preFilters = StringUtils.split(preFiltersStr, ",");
+ for (String filterName : preFilters) {
+ if (StringUtils.isBlank(filterName)) {
+ continue;
+ }
+
+ HttpAdapterFilter adapterFilter = HttpAdapterFilterFactory.createFilter(filterName.trim());
+ if (adapterFilter != null) {
+ message = adapterFilter.doPreFilter(adptGrpName, adptName, message, prop, request, response);
+ } else {
+ throw new Exception("Failed get Filter Class: " + filterName);
+ }
+ }
+ return message;
+ }
+
+ private Object doPostFilters(String adptGrpName, String adptName, Object resultMessage, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String postFiltersStr = prop.getProperty(POST_FILTERS);
+ if (StringUtils.isBlank(postFiltersStr)) {
+ return resultMessage;
+ }
+
+ String[] postFilters = StringUtils.split(postFiltersStr, ",");
+ for (String filterName : postFilters) {
+ if (StringUtils.isBlank(filterName)) {
+ continue;
+ }
+
+ HttpAdapterFilter adapterFilter = HttpAdapterFilterFactory.createFilter(filterName.trim());
+ if (adapterFilter != null) {
+ resultMessage = adapterFilter.doPostFilter(adptGrpName, adptName, resultMessage, prop, request,
+ response);
+ } else {
+ throw new Exception("Failed get Filter Class: " + filterName);
+ }
+ }
+ return resultMessage;
+ }
+
+ public abstract void service(String adptGrpName, String adptName, HttpServletRequest request,
+ HttpServletResponse response);
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceType.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceType.java
new file mode 100644
index 0000000..a61a8ce
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpAdapterServiceType.java
@@ -0,0 +1,17 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+public enum HttpAdapterServiceType {
+ STANDARD,
+ CHNL,
+ PASS,
+ REST,
+ UNKNOWN
+ ;
+ public static HttpAdapterServiceType getValue(String value) {
+ try {
+ return valueOf(value.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicInAdapterManager.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicInAdapterManager.java
new file mode 100644
index 0000000..cba7002
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicInAdapterManager.java
@@ -0,0 +1,199 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import com.eactive.eai.adapter.*;
+import com.eactive.eai.agent.command.CommandException;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.util.CamelCaseUtil;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class HttpDynamicInAdapterManager implements Lifecycle {
+
+ public static String HTTP_PARAM_TYPE = "HTTP_TYPE";
+ public static String API_PATH = "API_PATH";
+
+ Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private static HttpDynamicInAdapterManager instance = new HttpDynamicInAdapterManager();
+
+ private ConcurrentHashMap adptUriMap = new ConcurrentHashMap();
+
+ public static HttpDynamicInAdapterManager getInstance() {
+ return instance;
+ }
+
+ public HttpDynamicInAdapterUri getAdptUri(String uri) {
+ return adptUriMap.get( uri );
+ }
+
+ public void removeAdptUri(AdapterVO avo) {
+ try {
+ AdapterGroupVO gvo = avo.getAdapterGroupVO();
+ if ( gvo.getType().equals(Keys.TYPE_HTTP) && gvo.getGubun().equals("I") ) {
+ removeAdptUri(avo.getAdapterGroupName(), avo.getName());
+ }
+ } catch (Exception e) {
+ logger.error("HttpDynamicInAdapterManager] dynamic HTTP adpater remove error." + avo.toString(), e);
+ }
+ }
+
+ public void removeAdptUri(String adptGrpName, String adptName) {
+ for( HttpDynamicInAdapterUri adptUri : adptUriMap.values() ) {
+ if ( adptUri.isEqualsAdpt(adptGrpName, adptName) ) {
+ adptUriMap.remove( adptUri.getUri() );
+ if ( logger.isDebug() ) {
+ logger.debug("HttpDynamicInAdapterManager] remove " + adptGrpName + "-" + adptName );
+ }
+
+ break;
+ }
+ }
+ }
+
+ public void setDynamicUrl(AdapterVO avo) throws Exception {
+ try {
+ AdapterGroupVO gvo = avo.getAdapterGroupVO();
+
+ if(gvo == null){
+ removeAdptUriMapByAdapterGroupName(avo.getAdapterGroupName());
+ }
+ else if ( gvo.getType().equals(Keys.TYPE_HTTP) && gvo.getGubun().equals("I") ) {
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties httpProp = manager.getProperties(avo.getPropGroupName());
+ String httpType = httpProp.getProperty(HTTP_PARAM_TYPE,"STANDARD");
+ String httpUrl = "/HTT/"+CamelCaseUtil.converCamelCaseWithBrace(avo.getAdapterGroupName(),"_");
+ adptUriMap.put( httpUrl, new HttpDynamicInAdapterUri(avo.getAdapterGroupName(), avo.getName(), httpUrl, httpType));
+ if ( logger.isDebug() ) {
+ logger.debug("HttpDynamicInAdapterManager] set " + avo.getAdapterGroupName() + "-" + avo.getName() + ", uri:" + httpUrl );
+ }
+ } else if (gvo.getType().equals(Keys.TYPE_REST) && gvo.getGubun().equals("I")) {
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties httpProp = manager.getProperties(avo.getPropGroupName());
+ String httpType = httpProp.getProperty(HTTP_PARAM_TYPE, "REST");
+ String httpUrl = httpProp.getProperty(API_PATH);
+ httpUrl = StringUtils.removeEnd(httpUrl, "/");
+ if (StringUtils.isNotBlank(httpUrl)) {
+ // /api/vi/public
+ if (!StringUtils.startsWith(httpUrl, "/")) {
+ httpUrl = "/" + httpUrl;
+ }
+
+ // 1. URL이 이미 있는데, 그 URL이 다른 어댑터에 이미 설정되어 있다면 오류처리(기존 어댑터 보호)
+ HttpDynamicInAdapterUri adapterUri = adptUriMap.get(httpUrl);
+
+ logger.debug("#### setDynamicUrl:"+adptUriMap.toString());
+
+ if (adapterUri != null
+ && !StringUtils.equals(avo.getAdapterGroupName(), adapterUri.getAdptGrpName())) {
+ throw new CommandException("The URI is already in use by another adapter, "+adapterUri.getAdptGrpName());
+ }
+
+ // 2. 어댑터 기준 기존 데이터 삭제
+ removeAdptUriMapByAdapterGroupName(avo.getAdapterGroupName());
+
+ // 3. 새로 추가
+ adptUriMap.put(httpUrl,
+ new HttpDynamicInAdapterUri(avo.getAdapterGroupName(), avo.getName(), httpUrl, httpType));
+ if (logger.isDebug()) {
+ logger.debug("HttpDynamicInAdapterManager] set " + avo.getAdapterGroupName() + "-"
+ + avo.getName() + ", uri:" + httpUrl);
+ logger.debug("HttpDynamicInAdapterManager] adptUriMap " + adptUriMap.toString());
+ }
+ }
+ }
+ } catch (CommandException e) {
+ throw new Exception(e.getMessage());
+ } catch (Exception e) {
+ logger.error("HttpDynamicInAdapterManager] dynamic HTTP adapter add error." + avo.toString(), e);
+ }
+ }
+
+ public void removeAdptUriMapByAdapterGroupName(String adapterGroupName) throws Exception {
+ for (HttpDynamicInAdapterUri adptUri : adptUriMap.values()) {
+ if (StringUtils.equals(adptUri.getAdptGrpName(), adapterGroupName)) {
+ adptUriMap.remove(adptUri.getUri());
+ if (logger.isDebug()) {
+ logger.debug("HttpDynamicInAdapterManager] remove " + adptUri.toString() + " for "+adapterGroupName);
+ }
+
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void addLifecycleListener(LifecycleListener listener) {
+
+
+ }
+
+ @Override
+ public LifecycleListener[] findLifecycleListeners() {
+
+ return null;
+ }
+
+ @Override
+ public void removeLifecycleListener(LifecycleListener listener) {
+
+
+ }
+
+ @Override
+ public void start() throws LifecycleException {
+
+ AdapterManager adptManager = AdapterManager.getInstance();
+ HashMap adptGrps = null;
+
+ try {
+ adptGrps = adptManager.getAllAdapterGroupVO();
+
+ for(Object obj : adptGrps.values()) {
+ AdapterGroupVO gvo = (AdapterGroupVO)obj;
+ if(logger.isDebug()){
+ logger.debug("adpter : "+gvo.getName()+"-->"+gvo.toString());
+ }
+ if ((gvo.getType().equals(Keys.TYPE_HTTP) || gvo.getType().equals(Keys.TYPE_REST))
+ && gvo.getGubun().equals("I")) {
+ ArrayList adpts = null;
+ Iterator i = gvo.getAdapters();
+
+ while ( i.hasNext() ) {
+ AdapterVO avo = (AdapterVO)i.next();
+ setDynamicUrl( avo );
+ }
+ }
+ }
+ } catch (Exception e) {
+ logger.error("HttpDynamicInAdapterManager] start error", e);
+ }
+ }
+
+ @Override
+ public void stop() throws LifecycleException {
+
+ }
+
+ @Override
+ public boolean isStarted() {
+
+ return false;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void reloadAdapterUrl(AdapterGroupVO reloadGroupVO) throws Exception {
+ Iterator i = reloadGroupVO.getAdapters();
+ while (i.hasNext()) {
+ AdapterVO avo = (AdapterVO) i.next();
+ setDynamicUrl(avo);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicInAdapterUri.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicInAdapterUri.java
new file mode 100644
index 0000000..91af6ce
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicInAdapterUri.java
@@ -0,0 +1,99 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+public class HttpDynamicInAdapterUri {
+
+ public String adptGrpName = null;
+ public String adptName = null;
+ public String uri = null;
+ public String adptType = null;
+ public Integer listenPort = 0;
+
+ public HttpDynamicInAdapterUri(String adptGrpName, String adptName, Integer port, String uri, String adptType) {
+ this.adptGrpName = adptGrpName;
+ this.adptName = adptName;
+ this.uri = uri;
+ this.adptType = adptType;
+ this.listenPort = port;
+ }
+
+ public HttpDynamicInAdapterUri(String adptGrpName, String adptName, String uri, String adptType) {
+ this.adptGrpName = adptGrpName;
+ this.adptName = adptName;
+ this.uri = uri;
+ this.adptType = adptType;
+ this.listenPort = 0;
+ }
+
+ public boolean isEqualsAdpt(HttpDynamicInAdapterUri other) {
+ return isEqualsAdpt(other.getAdptGrpName(), other.getAdptName());
+ }
+
+ public boolean isEqualsAdpt(String adptGrpName, String adptNamer) {
+ if ( adptGrpName != null && adptGrpName.equals(this.adptGrpName)
+ && adptName != null && adptName.equals(this.adptName) ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isEqualsAdpt(String adptGrpName) {
+ if ( adptGrpName != null && adptGrpName.equals(this.adptGrpName)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public String getAdptGrpName() {
+ return adptGrpName;
+ }
+
+ public void setAdptGrpName(String adptGrpName) {
+ this.adptGrpName = adptGrpName;
+ }
+
+ public String getAdptName() {
+ return adptName;
+ }
+
+ public void setAdptName(String adptName) {
+ this.adptName = adptName;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public String getAdptType() {
+ return adptType;
+ }
+
+ public void setAdptType(String adptType) {
+ this.adptType = adptType;
+ }
+
+ public Integer getListenPort() {
+ return listenPort;
+ }
+
+ public void setListenPort(Integer listenPort) {
+ this.listenPort = listenPort;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("HttpDynamicInAdapterUri[ adptGrpName=").append(adptGrpName);
+ sb.append(", adptName=").append(adptName);
+ sb.append(", port=").append(listenPort);
+ sb.append(", uri=").append(uri);
+ sb.append(", adptType=").append(adptType);
+ sb.append(" ]");
+
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicPortInAdapterManager.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicPortInAdapterManager.java
new file mode 100644
index 0000000..d008925
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpDynamicPortInAdapterManager.java
@@ -0,0 +1,511 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import com.eactive.eai.adapter.*;
+import com.eactive.eai.adapter.http.dynamic.wrapper.KeepAliveFalseWrapper;
+import com.eactive.eai.adapter.http.dynamic.wrapper.KeepAliveTrueWrapper;
+import com.eactive.eai.adapter.http.util.HttpsGenerator;
+import com.eactive.eai.agent.command.CommandException;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.util.Logger;
+import io.undertow.Handlers;
+import io.undertow.Undertow;
+import io.undertow.UndertowOptions;
+import io.undertow.server.handlers.*;
+import io.undertow.servlet.Servlets;
+import io.undertow.servlet.api.DeploymentInfo;
+import io.undertow.servlet.api.DeploymentManager;
+import io.undertow.servlet.api.ServletInfo;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.net.ssl.SSLContext;
+import javax.servlet.ServletException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class HttpDynamicPortInAdapterManager implements Lifecycle {
+ public String HTTP_PARAM_TYPE = "HTTP_TYPE";
+ public String HTTP_LISTEN_PORT = "LISTEN_PORT";
+ public String API_PATH = "API_PATH";
+
+ public String HTTPS_USE_YN = "HTTPS_USE_YN";
+ public String HTTPS_KEY_STORE = "HTTPS_KEY_STORE";
+ public String HTTPS_KEY_PASS = "HTTPS_KEY_PASS";
+
+ public String MAX_CONNECTION = "MAX_CONNECTION";
+ public String QUEUE_SIZE = "QUEUE_SIZE";
+ public String ALLOW_IP = "ALLOW_IP";
+
+ public final String IO_THREADS = "IO_THREADS";
+ public final String WORKER_THREADS = "WORKER_THREADS";
+
+ //keep alive 관련
+ public final String KEEP_ALIVE_YN = "KEEP_ALIVE_YN";
+ public final String KEEP_ALIVE_TIMEOUT = "KEEP_ALIVE_TIMEOUT";
+ public final String MAX_REQUEST_COUNT = "MAX_REQUEST_COUNT";
+
+ Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private static HttpDynamicPortInAdapterManager instance = new HttpDynamicPortInAdapterManager();
+
+ // url - Adapter Map
+ private ConcurrentHashMap adptUriMap = new ConcurrentHashMap();
+
+ // adapter Name - Adapter Map
+ private ConcurrentHashMap adptNameMap = new ConcurrentHashMap();
+
+ // Listen Port - Adapter Map
+ private ConcurrentHashMap adptPortMap = new ConcurrentHashMap();
+
+ // Listen Port - Adapter Map
+ private ConcurrentHashMap svrPortMap = new ConcurrentHashMap();
+
+ @SuppressWarnings("unchecked")
+ public void addAdapter(AdapterVO adapter) throws Exception {
+ String adapterFullName;
+
+ HttpDynamicInAdapterUri oldAdapterUri, newAdapterUri;
+
+ String oldUri, newUri;
+
+ // Port별 Adapter 목록 매핑
+ ConcurrentHashMap adptPortSubMap;
+
+ // 기존 Port Listener
+ Undertow oldListener;
+
+ AdapterGroupVO gvo = adapter.getAdapterGroupVO();
+
+ if (gvo != null & gvo.getType().equals(Keys.TYPE_HTTP_CUSTOM) && gvo.getGubun().equals("I")) {
+ // Server Adapter인 경우 초기화
+ adapterFullName = adapter.getAdapterGroupName() + "." + adapter.getName();
+ oldAdapterUri = adptNameMap.get(adapterFullName);
+
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties httpProp = manager.getProperties(adapter.getPropGroupName());
+ String httpType = httpProp.getProperty(HTTP_PARAM_TYPE, "STANDARD");
+ String portString = httpProp.getProperty(HTTP_LISTEN_PORT, "0");
+ Integer listenPort = Integer.valueOf(portString);
+ if (listenPort.intValue() == 0) {
+ throw new CommandException("LISTEN_PORT is required.");
+ }
+
+ newUri = httpProp.getProperty(API_PATH);
+ if (!StringUtils.equals(newUri, "/")) {
+ newUri = StringUtils.removeEnd(newUri, "/");
+ }
+ if (StringUtils.isBlank(newUri)) {
+ throw new CommandException("API_PATH is required.");
+ }
+
+ // /api/vi/public
+ if (!StringUtils.startsWith(newUri, "/")) {
+ newUri = "/" + newUri;
+ }
+
+ newAdapterUri = new HttpDynamicInAdapterUri(adapter.getAdapterGroupName(), adapter.getName(), listenPort,
+ newUri, httpType);
+
+ adptPortSubMap = null;
+ oldListener = null;
+ } else {
+ // Client Adapter 인 경우 무시
+ return;
+ }
+
+ // 1. Adapter 명으로 기 등록된 Adapter인지 확인
+ // -- 이미 등록된 Adapter 이면
+ if (oldAdapterUri != null) {
+
+ if (oldAdapterUri.getListenPort() != 0) {
+ oldUri = adapterFullName + "/" + oldAdapterUri.getUri();
+
+ // 2. Port별 Adapter 정보 확인 및 제거
+ Integer listenPort = oldAdapterUri.getListenPort();
+
+ adptPortSubMap = adptPortMap.get(listenPort);
+ if (adptPortSubMap != null) {
+ adptPortSubMap.remove(adapterFullName);
+ }
+
+ // 2.1 해당 Port에 추가 Adapter가 없는 경우 해당 Listener 제거
+ if (adptPortSubMap == null || adptPortSubMap.size() == 0) {
+
+ // 2.1.1 해당 Port에 추가 Adapter가 없는 경우 Port 매핑 제거
+ adptPortMap.remove(listenPort);
+ // 2.1.2 해당 Port에 추가 Adapter가 없는 경우 해당 Listener 제거
+ oldListener = svrPortMap.get(listenPort);
+ svrPortMap.remove(listenPort);
+ if (oldListener != null)
+ oldListener.stop();
+ }
+
+ // 3. Adapter명 별 Adapter 정보 확인 및 제거
+ adptNameMap.remove(adapterFullName);
+ } else {
+ oldUri = oldAdapterUri.getUri();
+ // Default Adapter (WAS) 처리
+ // adptUriMap만 처리
+ adptUriMap.remove(oldUri);
+ }
+
+ }
+
+ // 신규 Adapter 추가
+ if (newAdapterUri.getListenPort() != 0) {
+ // Port 별 Adapter 정보 등록
+ adptPortSubMap = adptPortMap.get(newAdapterUri.getListenPort());
+ if (adptPortSubMap == null) {
+ adptPortSubMap = new ConcurrentHashMap();
+ adptPortMap.put(newAdapterUri.getListenPort(), adptPortSubMap);
+ }
+ adptPortSubMap.put(newAdapterUri.getUri(), newAdapterUri);
+
+ // Adapter명 별 Adapter 정보 등록
+ adptNameMap.put(adapterFullName, newAdapterUri);
+ } else {
+ // Default Adapter (WAS) 처리
+ // adptUriMap만 등록
+ adptUriMap.put(newUri, newAdapterUri);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void removeAdapter(AdapterVO adapter) throws Exception {
+
+ String adapterFullName;
+ HttpDynamicInAdapterUri oldAdapterUri;
+
+ // Port별 Adapter 목록 매핑
+ ConcurrentHashMap adptPortSubMap;
+
+ // 기존 Port Listener
+ Undertow oldListener;
+
+ AdapterGroupVO gvo = adapter.getAdapterGroupVO();
+
+ if (gvo != null && gvo.getType().equals(Keys.TYPE_HTTP_CUSTOM) && gvo.getGubun().equals("I")) {
+ // Server Adapter 인 경우 초기화
+ adapterFullName = adapter.getAdapterGroupName() + "." + adapter.getName();
+ oldAdapterUri = adptNameMap.get(adapterFullName);
+ adptPortSubMap = null;
+ oldListener = null;
+ } else {
+ // Client Adapter 인 경우 무시
+ return;
+ }
+
+ if (oldAdapterUri != null) {
+ if (oldAdapterUri.getListenPort() != 0) {
+
+ // 2. Port 별 Adapter 정보 확인 및 제거
+ Integer listenPort = oldAdapterUri.getListenPort();
+
+ adptPortSubMap = adptPortMap.get(listenPort);
+ HttpDynamicInAdapterUri httpDynamicInAdapterUri = adptPortSubMap.get(oldAdapterUri.getUri());
+
+ // 20211201 어댑터 그룹체크, 동일하면 삭제
+ if (httpDynamicInAdapterUri.getAdptGrpName().equals(oldAdapterUri.getAdptGrpName())) {
+ adptPortSubMap.remove(oldAdapterUri.getUri());
+ }
+
+ // 2.1 해당 Port에 추가 Adapter 없는 경우 해당 Listener 제거
+ if (adptPortSubMap.size() == 0) {
+ // 2.1.1 해당 Port에 추가 Adapter 없는 경우 Port 매핑 제거
+ adptPortMap.remove(listenPort);
+ // 2.1.2 해당 Port에 추가 Adapter 없는 경우 해당 Listener 제거
+ oldListener = svrPortMap.get(listenPort);
+ try {
+ if (oldListener != null) {
+ oldListener.stop();
+ }
+ } catch (Throwable t) {
+ // 중지 실패시 원복
+ adptPortSubMap.put(oldAdapterUri.getUri(), oldAdapterUri);
+ adptPortMap.put(listenPort, adptPortSubMap);
+ throw t;
+ }
+
+ // stop 성공후 삭제
+ svrPortMap.remove(listenPort);
+ }
+
+ // 3. Adapter명 별 Adapter 정보 확인 및 제거
+ adptNameMap.remove(adapterFullName);
+ } else {
+ // Default Adapter(WAS) 처리
+ // adptUriMap만 처리
+ adptUriMap.remove(oldAdapterUri.getUri());
+ }
+ }
+ }
+
+ public static HttpDynamicPortInAdapterManager getInstance() {
+ return instance;
+ }
+
+ public HttpDynamicInAdapterUri getAdptUri(String uri) {
+ return adptUriMap.get(uri);
+ }
+
+ @SuppressWarnings("unchecked")
+ public HttpDynamicInAdapterUri getAdptUri(Integer port, String uri) {
+ ConcurrentHashMap tmpAdptUriMap = adptPortMap.get(port);
+ if (tmpAdptUriMap != null)
+ return tmpAdptUriMap.get(uri);
+ return null;
+ }
+
+ @Override
+ public void addLifecycleListener(LifecycleListener listener) {
+
+ }
+
+ @Override
+ public LifecycleListener[] findLifecycleListeners() {
+
+ return null;
+ }
+
+ @Override
+ public void removeLifecycleListener(LifecycleListener listener) {
+
+ }
+
+ public void start(AdapterVO adapter) throws Exception {
+ AdapterGroupVO gvo = adapter.getAdapterGroupVO();
+
+ if (gvo != null && gvo.getType().equals(Keys.TYPE_HTTP_CUSTOM) && gvo.getGubun().equals("I")) {
+ // Server Adapter 인 경우 정보 확인
+ AdapterPropManager adapterManager = AdapterPropManager.getInstance();
+ Properties httpProp = adapterManager.getProperties(adapter.getPropGroupName());
+
+ String httpsUseYn = httpProp.getProperty(HTTPS_USE_YN, "N");
+ String httpsKeyStore = httpProp.getProperty(HTTPS_KEY_STORE, null);
+ String httpsKeyPass = httpProp.getProperty(HTTPS_KEY_PASS, null);
+
+ Integer listenPort = Integer.valueOf(httpProp.getProperty(HTTP_LISTEN_PORT, "0"));
+ Integer max_connection = Integer.valueOf(httpProp.getProperty(MAX_CONNECTION, "100"));
+ Integer max_queue = Integer.valueOf(httpProp.getProperty(QUEUE_SIZE, "3000"));
+ String allowIp = httpProp.getProperty(ALLOW_IP, null);
+
+ Integer ioThreads = Integer.valueOf(httpProp.getProperty(IO_THREADS, "2"));
+ Integer workerThreads = Integer.valueOf(httpProp.getProperty(WORKER_THREADS, "16"));
+
+ String keepAliveYn = httpProp.getProperty(KEEP_ALIVE_YN, "Y");
+ Integer keepAliveTimeout = Integer.valueOf(httpProp.getProperty(KEEP_ALIVE_TIMEOUT, "15"));
+ Integer maxRequestCount = Integer.valueOf(httpProp.getProperty(MAX_REQUEST_COUNT, "-1"));
+
+ boolean isKeepAlive = false;
+ if ("Y".equals(keepAliveYn)) {
+ isKeepAlive = true;
+ }
+
+ // Custom Adapter 인 경우 재시작
+ if (listenPort != 0) {
+ Undertow server = svrPortMap.get(listenPort);
+ if (server != null) {
+ // server.stop();
+ // svrPortMap.remove(listenPort);
+
+ return;
+ }
+
+ ServletInfo servletInfo = Servlets.servlet(HttpAdapterCustom.class);
+ servletInfo.addMapping("/*");
+ ServletInfo healthCheckServletInfo = Servlets.servlet(UndertowHealthCheckServlet.class);
+ healthCheckServletInfo.addMapping("healthcheck.html");
+
+ DeploymentInfo servletBuilder = Servlets.deployment()
+ .setClassLoader(HttpDynamicPortInAdapterManager.class.getClassLoader())
+ .setDeploymentName("HttpDynamicCustomAdapter").setContextPath("/")
+ .addServlet(healthCheckServletInfo).addServlet(servletInfo);
+ if (isKeepAlive) {
+ KeepAliveTrueWrapper wrapper = new KeepAliveTrueWrapper();
+ wrapper.setKeepAliveTimeout(keepAliveTimeout);
+ wrapper.setMaxRequestCount(maxRequestCount);
+ servletBuilder.addInitialHandlerChainWrapper(wrapper);
+ } else {
+ servletBuilder.addInitialHandlerChainWrapper(new KeepAliveFalseWrapper());
+ }
+ DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder);
+ manager.deploy();
+
+ PathHandler path = null;
+ IPAddressAccessControlHandler ipAddressAccessControlHandler = null;
+ RequestLimitingHandler requestLimitHandler = null;
+
+ try {
+ path = Handlers.path(Handlers.redirect("/")).addPrefixPath("/", manager.start());
+ if (allowIp != null && allowIp.length() > 1) {
+ String[] allowIps = allowIp.split(",");
+ ipAddressAccessControlHandler = Handlers.ipAccessControl(path, false);
+ for (int i = 0; i < allowIps.length; i++) {
+ ipAddressAccessControlHandler.addAllow(allowIps[i]);
+ }
+ }
+
+ RequestLimit requestLimit = new RequestLimit(max_connection, max_queue);
+ requestLimit.setFailureHandler(ResponseCodeHandler.HANDLE_500);
+
+ if (ipAddressAccessControlHandler != null) {
+ requestLimitHandler = Handlers.requestLimitingHandler(requestLimit,
+ ipAddressAccessControlHandler);
+ } else {
+ requestLimitHandler = Handlers.requestLimitingHandler(requestLimit, path);
+ }
+
+ } catch (ServletException e) {
+ logger.error(e.getMessage(), e);
+ }
+
+ SSLContext sslContext = null;
+ if (StringUtils.equalsIgnoreCase(httpsUseYn, "Y")) {
+// if ((httpsKeyStore != null && httpsKeyStore.length() > 1)
+// && (httpsKeyPass != null && httpsKeyPass.length() > 1)) {
+ sslContext = HttpsGenerator.createSSLContext(httpsKeyStore, httpsKeyPass);
+// }
+ }
+
+ logger.debug("####[" + adapter.getName() + "] ioThreads-->" + ioThreads);
+ logger.debug("####[" + adapter.getName() + "] workerThreads-->" + workerThreads);
+ Undertow.Builder builder = Undertow.builder().setIoThreads(ioThreads).setWorkerThreads(workerThreads);
+ if (sslContext != null) {
+ builder.addHttpsListener(listenPort, "0.0.0.0", sslContext);
+// server = Undertow.builder().setIoThreads(ioThreads).setWorkerThreads(workerThreads)
+// .addHttpsListener(listenPort, "0.0.0.0", sslContext).setHandler(requestLimitHandler)
+// .build();
+ } else {
+ builder.addHttpListener(listenPort, "0.0.0.0");
+// server = Undertow.builder().setIoThreads(ioThreads).setWorkerThreads(workerThreads)
+// .addHttpListener(listenPort, "0.0.0.0").setHandler(requestLimitHandler).build();
+ }
+ if (isKeepAlive){
+ builder.setServerOption(UndertowOptions.NO_REQUEST_TIMEOUT, keepAliveTimeout * 1000);
+ }
+ builder.setHandler(requestLimitHandler);
+ server = builder.build();
+
+ try {
+ server.start();
+ } catch (Throwable t) {
+ logger.error(t.getMessage());
+ String adapterFullName = adapter.getAdapterGroupName() + "." + adapter.getName();
+ throw new Exception("failed start: " + adapterFullName);
+ }
+
+ svrPortMap.put(listenPort, server);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void stop(AdapterVO adapter) throws Exception {
+ AdapterGroupVO gvo = adapter.getAdapterGroupVO();
+
+ if (gvo != null && gvo.getType().equals(Keys.TYPE_HTTP_CUSTOM) && gvo.getGubun().equals("I")) {
+ // Server Adapter 인 경우 정보 확인
+ AdapterPropManager adapterManager = AdapterPropManager.getInstance();
+
+ Properties httpProp = adapterManager.getProperties(adapter.getPropGroupName());
+ String portString = httpProp.getProperty(HTTP_LISTEN_PORT, "0");
+ Integer listenPort = Integer.valueOf(portString);
+
+ // Custom Adapter 인 경우 재시작
+ if (listenPort != 0) {
+ ConcurrentHashMap uriMap = adptPortMap.get(listenPort);
+ // 해당 Port로 수신하는 Adapter가 1개 이상 존재하는 경우 재시작 하지 않음 - 성능/안전성 이슈
+ if (uriMap != null && uriMap.size() > 0)
+ return;
+
+ Undertow server = svrPortMap.get(listenPort);
+ if (server != null) {
+ server.stop();
+ svrPortMap.remove(listenPort);
+ }
+ }
+ }
+ }
+
+ @Override
+ @SuppressWarnings({ "rawtypes" })
+ public void start() throws LifecycleException {
+ try {
+ AdapterManager adptManager = AdapterManager.getInstance();
+ HashMap adptGrps = adptManager.getAllAdapterGroupVO();
+
+ for (Object obj : adptGrps.values()) {
+ AdapterGroupVO gvo = (AdapterGroupVO) obj;
+ if (gvo.getType().equals(Keys.TYPE_HTTP_CUSTOM) && gvo.getGubun().equals("I")) {
+ Iterator i = gvo.getAdapters();
+ while (i.hasNext()) {
+ AdapterVO avo = (AdapterVO) i.next();
+ addAdapter(avo);
+ }
+ }
+ }
+
+// adptPortMap.forEach((port,uriList) -> {
+// Undertow server = svrPortMap.get(port);
+//
+// if (server == null) {
+// ConcurrentHashMap uriMap = uriList;
+// ServletInfo servletInfo = Servlets.servlet(com.eactive.eai.adapter.http.dynamic.HttpAdapterCustom.class);
+// uriMap.forEach((url,adapterUri) -> {
+// //servletInfo.addMapping(adapterUri.getUri());
+// servletInfo.addMapping(adapterUri.getUri() + "/*");
+// });
+//
+// DeploymentInfo servletBuilder = Servlets
+// .deployment()
+// .setClassLoader(HttpDynamicPortInAdapterManager.class.getClassLoader())
+// .setDeploymentName("HttpDynamicCustomAdapter")
+// .setContextPath("/")
+// .addServlet(servletInfo);
+// DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder);
+// manager.deploy();
+//
+// PathHandler path = null;
+//
+// try {
+// path = Handlers.path(Handlers.redirect("/")).addPrefixPath("/", manager.start());
+// } catch (ServletException e) {
+// logger.error(e.getMessage(), e);
+// }
+//
+// server = Undertow.builder().addHttpListener(port, "0.0.0.0").setHandler(path).build();
+//
+// svrPortMap.put(port, server);
+// server.start();
+//
+// }
+// });
+ } catch (Exception e) {
+ logger.error("HttpDynamicPortInAdapterManager] start error", e);
+ }
+ }
+
+ @Override
+ public void stop() throws LifecycleException {
+
+ try {
+ adptPortMap.forEach((port, UriList) -> {
+ Undertow server = svrPortMap.get(port);
+
+ if (server != null) {
+ server.stop();
+ }
+ });
+ } catch (Exception e) {
+ logger.error("HttpDynamicPortInAdapterManager] stop error", e);
+ }
+ }
+
+ @Override
+ public boolean isStarted() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpLoggerManager.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpLoggerManager.java
new file mode 100644
index 0000000..0417b65
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/HttpLoggerManager.java
@@ -0,0 +1,123 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.util.Logger;
+
+import java.util.HashMap;
+import java.util.Properties;
+
+public class HttpLoggerManager {
+
+ private static HttpLoggerManager instance = new HttpLoggerManager();
+
+ private HashMap pool = new HashMap(); // KEY:adapterGroupName, VALUE:Logger
+ private String eaiServer;
+ private static String DEFAULT_LOGGER_NAME = "HTT";
+ private static String ERROR_LOGGER_NAME = "ERRORHTT";
+
+ public HttpLoggerManager() {
+ eaiServer = EAIServerManager.getInstance().getLocalServerName();
+ if (eaiServer == null) eaiServer = "";
+ }
+
+ public static HttpLoggerManager getInstance() {
+ return instance;
+ }
+
+ public void stop() {
+ this.stop();
+ }
+
+ public void removeAll() {
+ pool.clear();
+ }
+
+ public void start(String adapterGroupName) {
+ this.addLogger(adapterGroupName);
+ }
+
+ public synchronized void addLogger(String adapterGroupName) {
+ String loggerName = this.getLoggerName( adapterGroupName );
+ Logger logger = pool.get( loggerName );
+ if (logger == null) {
+ synchronized (pool) {
+ logger = pool.get(loggerName);
+ if (logger == null) {
+ Logger logger2 = Logger.getLogger(loggerName);
+ pool.put(loggerName, logger2);
+ }
+ }
+ }
+ }
+
+ private String getLoggerName(String adapterGroupName) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("FileLogger{").append(adapterGroupName).append("}_").append(this.eaiServer);
+
+ return sb.toString();
+ }
+
+ private String getLoggerBase(String adapterGroupName) {
+ StringBuffer strBuff = new StringBuffer();
+ strBuff.append("FileLogger{").append(adapterGroupName).append("}");
+
+ return strBuff.toString();
+ }
+
+ public void removeLogger(String adapterGroupName) {
+ pool.remove(this.getLoggerName(adapterGroupName));
+ }
+
+ public void stop(String adapterGroupName) {
+ // adapterGroupNameÀÇ Session Stop & Clear
+ this.removeLogger(adapterGroupName);
+ }
+
+ public Logger getLogger(String adapterGroupName) {
+ return getLoggerGroup(adapterGroupName);
+ }
+
+ public Logger getErrLogger() {
+ return getLoggerGroup(ERROR_LOGGER_NAME);
+ }
+
+ public Logger getLoggerGroup(String adapterGroupName) {
+
+ Logger logger = pool.get(this.getLoggerName(adapterGroupName));
+ if (logger == null) {
+ if (DEFAULT_LOGGER_NAME.equals(adapterGroupName)) {
+ this.addLogger(adapterGroupName);
+ logger = pool.get(this.getLoggerName(adapterGroupName));
+ } else {
+ AdapterPropManager propManager = AdapterPropManager.getInstance();
+ Properties loggerInfo = null;
+
+ try {
+ loggerInfo = propManager.getProperties(getLoggerBase(adapterGroupName));
+ } catch(Exception e) {
+ // ¹«½Ã
+ }
+
+ if (loggerInfo == null) {
+ logger = getLogger();
+ } else {
+ this.addLogger(adapterGroupName);
+ logger = pool.get(this.getLoggerName(adapterGroupName));
+ }
+ }
+ }
+
+ return logger;
+ }
+
+ public Logger getLogger() {
+ Logger logger = pool.get(this.getLoggerName(this.DEFAULT_LOGGER_NAME));
+ if (logger == null) {
+ this.addLogger(DEFAULT_LOGGER_NAME);
+ logger = pool.get(this.getLoggerName(DEFAULT_LOGGER_NAME));
+ }
+
+ return logger;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/RestApiAdapterMain.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/RestApiAdapterMain.java
new file mode 100644
index 0000000..d522e03
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/RestApiAdapterMain.java
@@ -0,0 +1,112 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.util.DatetimeUtil;
+import com.eactive.eai.common.util.InboundErrorLogger;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.UUIDGenerator;
+import com.eactive.eai.inbound.error.InboundErrorInfoVO;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+
+@SuppressWarnings("serial")
+public class RestApiAdapterMain extends HttpServlet implements HttpAdapterServiceKey {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public void init() {
+ }
+
+ public void service(HttpServletRequest request, HttpServletResponse response) {
+ HttpDynamicInAdapterManager manager = HttpDynamicInAdapterManager.getInstance();
+ // /ONLWeb/api/v1/public/getUserInfo.svc
+ String apiUri = request.getRequestURI();
+ // /api/v1/public/getUserInfo.svc
+ apiUri = StringUtils.removeStart(apiUri, request.getContextPath());
+ apiUri = StringUtils.removeEnd(apiUri, "/");
+ HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, manager);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpDynamicInAdapter] service request uri : " + request.getRequestURI());
+ }
+
+ if (adptUri == null) {
+ logError(request, response);
+ return;
+ }
+ HttpAdapterService service = HttpAdapterServiceFactory.createFactory(adptUri.getAdptType());
+ service.service(adptUri.getAdptGrpName(), adptUri.getAdptName(), request, response);
+ }
+
+ /**
+ * url에서 뒤쪽 /이후를 제거하면서 찾는다.
+ * /api/v1/public/getUserInfo.svc
+ *
+ * @param apiUri
+ * @return
+ */
+ private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager) {
+ if (StringUtils.isBlank(apiUri)) {
+ return null;
+ }
+
+ for (int i = 0; i < 10; i++) {
+ HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri);
+ if (adptUri != null) {
+ return adptUri;
+ }
+
+ // /api/v1/public
+ apiUri = StringUtils.substringBeforeLast(apiUri, "/");
+ if (apiUri.length() < 4) { // /api
+ return null;
+ }
+ }
+
+ return null;
+ }
+
+ private void logError(HttpServletRequest request, HttpServletResponse response) {
+ InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO();
+
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ String serverName = eaiServerManager.getLocalServerName();
+ String uuid = null;
+ StringBuffer sb = new StringBuffer();
+
+ String instanceid1 = serverName.substring(0, 2);
+ String instanceid2 = serverName.substring(serverName.length() - 2, serverName.length());
+ String instid = instanceid1 + instanceid2;
+ uuid = instid + UUIDGenerator.getUUID();
+
+ String[] msgArgs = new String[1];
+ msgArgs[0] = request.getRequestURI();
+
+ String errorCode = "RECEAIIRP010";
+ String errorMsg = ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs);
+
+ errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호
+ errorInfoVO.setAdptBwkGrpNm("HTTP_IN_NO_URI"); // 어댑터업무그룹명
+ errorInfoVO.setErrCd(errorCode); // 에러코드
+ errorInfoVO.setErrTxt(errorMsg); // 에러내용
+ errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각
+ errorInfoVO.setErrDstcd(" ");
+ sb.append("Remote Addr : ").append(request.getRemoteAddr()).append("\n").append("Request URI : ")
+ .append(request.getRequestURI());
+ errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용
+ errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명
+
+ InboundErrorLogger.error(errorInfoVO);
+
+ response.setStatus(404);
+ try {
+ response.getWriter().println("can not find uri '" + request.getRequestURI() + "'");
+ } catch (Exception ex) {
+ // IGNORE
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/UndertowHealthCheckServlet.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/UndertowHealthCheckServlet.java
new file mode 100644
index 0000000..3826833
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/UndertowHealthCheckServlet.java
@@ -0,0 +1,17 @@
+package com.eactive.eai.adapter.http.dynamic;
+
+import io.undertow.servlet.handlers.DefaultServlet;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@SuppressWarnings("serial")
+public class UndertowHealthCheckServlet extends DefaultServlet {
+
+ protected void service(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ response.getWriter().print("");
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/AdapterAllowIPListFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/AdapterAllowIPListFilter.java
new file mode 100644
index 0000000..ec2c703
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/AdapterAllowIPListFilter.java
@@ -0,0 +1,79 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.util.IpUtil;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpStatus;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class AdapterAllowIPListFilter implements HttpAdapterFilter {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ @Override
+ public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ String requestIp = getClientIp(request);
+ try {
+ String allowedIps = prop.getProperty(HttpAdapterServiceKey.ALLOW_IP, "");
+ if (StringUtils.isBlank(allowedIps)) {
+ return message;
+ }
+
+ if (!IpUtil.isMatchIp(allowedIps, requestIp)) {
+ throw new HttpStatusException("This IP was not allowed-" + requestIp, HttpStatus.FORBIDDEN.value());
+ }
+ } catch (HttpStatusException e) {
+ logger.debug(e.getMessage());
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL, "Client IP check failed-" + requestIp);
+ }
+
+ return message;
+ }
+
+ private String getClientIp(HttpServletRequest request) {
+ String ipAddress = request.getHeader("X-FORWARDED-FOR");
+ if (ipAddress == null) {
+ ipAddress = request.getRemoteAddr();
+ }
+ if(ipAddress.indexOf(",") >= 0) {
+ ipAddress = org.springframework.util.StringUtils.tokenizeToStringArray(ipAddress, ",")[0];
+ }
+ return ipAddress;
+ }
+
+ private String assignClientId(Properties prop, HttpServletRequest request) {
+ String clientId = null;
+ try {
+ // 이전 filter에서 셋팅한 clientId 확보
+ clientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
+
+ // 이전 filter에서 셋팅한 값이 없다면 header 정보에서 확보
+ if (StringUtils.isBlank(clientId)) {
+ clientId = request.getHeader(HttpAdapterServiceSupport.HEADER_NAME_CLIENT_ID);
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+
+ return clientId;
+ }
+
+ @Override
+ public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return resultMessage;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/ApiAuthFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/ApiAuthFilter.java
new file mode 100644
index 0000000..c3458e6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/ApiAuthFilter.java
@@ -0,0 +1,258 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.authserver.service.OAuth2Manager;
+import com.eactive.eai.authserver.vo.ClientVO;
+import com.eactive.eai.common.message.EAIMessage;
+import com.eactive.eai.common.message.EAIMessageManager;
+import com.eactive.eai.common.property.PropGroupVO;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.stdmessage.STDMessageManager;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.inbound.action.ActionFactory;
+import com.eactive.eai.inbound.action.RequestAction;
+import com.eactive.eai.inbound.processor.Processor;
+import com.eactive.eai.message.StandardMessage;
+import com.eactive.eai.message.StandardMessageUtil;
+import com.eactive.eai.message.manager.StandardMessageManager;
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.util.IOUtils;
+import com.nimbusds.jwt.SignedJWT;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.text.ParseException;
+import java.util.Base64;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Properties;
+
+public class ApiAuthFilter implements HttpAdapterFilter {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public static final String PROP_GROUP_AUTH_SERVER = "OAuthServer";
+ public static final String PROP_KEYSTORE_PATH = "certification.publicKeyPath";
+
+ public static final String ERROR_AUTHENTICATION_FAIL = "E.AUTHENTICATION_FAIL";
+ public static final String ERROR_AUTHORIZATION_FAIL = "E.AUTHORIZATION_FAIL";
+ public static final String ERROR_TOKEN_EXPIRED = "E.TOKEN_EXPIRED";
+
+ public static final String PAYLOAD_PARAM_NAME_SCOPE = "scope";
+ public static final String PAYLOAD_PARAM_NAME_CLIENT_ID = "client_id";
+
+ private JWSVerifier jwsVerifier;
+
+ public ApiAuthFilter() {
+ super();
+
+ PropGroupVO vo = PropManager.getInstance().getPropGroupVO(PROP_GROUP_AUTH_SERVER);
+ String publicKeyPath = "/certificate/elink-oauth-dev.pub";
+ if (vo != null) {
+ publicKeyPath = vo.getProperty(PROP_KEYSTORE_PATH);
+ } else {
+ logger.warn("The properties has not been set.[" + PROP_GROUP_AUTH_SERVER + "]");
+ }
+
+ Resource resource = new ClassPathResource(publicKeyPath);
+ String publicKey = null;
+ try {
+ publicKey = IOUtils.readInputStreamToString(resource.getInputStream());
+ publicKey = StringUtils.replace(publicKey, "-----BEGIN PUBLIC KEY-----", "");
+ publicKey = StringUtils.replace(publicKey, "-----END PUBLIC KEY-----", "");
+ publicKey = StringUtils.remove(publicKey, "\r");
+ publicKey = StringUtils.remove(publicKey, "\n");
+
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ jwsVerifier = new RSASSAVerifier((RSAPublicKey) keyFactory.generatePublic(keySpec));
+ } catch (IOException | NoSuchAlgorithmException | RuntimeException | InvalidKeySpecException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String apiId = assignApiId(adptGrpName, adptName, message, prop, request);
+ if (StringUtils.isBlank(apiId)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Can not find apiId(apiCode) info");
+ }
+
+ /**
+ * TODO: 중복되는 표준메시지 조회로 리소드 낭비가 있을 수 있으므로 체크 자체를 추후 RequestProcessor혹은 RestProcessor로 이동 필요 해 보임
+ * ApiRequestProcessor을 만드는것도 괜찮을 수 있을 것 같으나 관리가 안될 것 같음
+ */
+ StandardMessage standardMessage = STDMessageManager.getInstance().getSTDMessage(apiId);
+ String eaiSvcCd = StandardMessageManager.getInstance().getMapper().getEaiSvcCode(standardMessage);
+ EAIMessage eaiMessage = EAIMessageManager.getInstance().getEAIMessage(eaiSvcCd);
+
+ if(StringUtils.isBlank(eaiMessage.getAuthType())){
+ return message;
+ }
+
+ switch (eaiMessage.getAuthType()){
+ case "oauth":
+ try {
+ String token = ApiAuthFilter.extractJWTToken(request);
+ SignedJWT signedJWT = SignedJWT.parse(token);
+
+ if (new Date().after(signedJWT.getJWTClaimsSet().getExpirationTime())) {
+ throw new JwtAuthException(ERROR_TOKEN_EXPIRED, "Access token expired");
+ }
+
+ if (!signedJWT.verify(jwsVerifier)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
+ }
+
+ OAuth2Manager manager = OAuth2Manager.getInstance();
+ HashSet scopeSet = manager.getApiScopeMap().get(apiId);
+ if (!verifyScope(scopeSet, signedJWT)) {
+ throw new JwtAuthException(ERROR_AUTHORIZATION_FAIL,
+ String.format("Insufficient [Scope](Allowed Scope=%s)", scopeSet.toString()));
+ }
+
+ // header 값으로 전송된 clientId와 토큰 소유 clientId check
+ if (!verifyClientId(prop, signedJWT)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "client_id not matched(header/token)");
+ }
+ } catch (JwtAuthException e) {
+ logger.debug(e.getMessage());
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
+ }
+ break;
+ case "api_key":
+ String apiKeyName = PropManager.getInstance().getProperty("ApiConfig", "api.key.name", "x-api-key");
+ String apiKey = request.getHeader(apiKeyName);
+ if(apiKey == null){
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Invalid or missing API key \""+apiKeyName+"\" in Http Header");
+ }
+ prop.setProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID, apiKey);
+ break;
+ case "none":
+ return message;
+ }
+
+ String clientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
+ ClientVO clientVO = OAuth2Manager.getInstance().getClientVO(clientId);
+ if(clientVO == null){
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Unregistered APP");
+ }
+
+ if(clientVO.getApiMap().containsKey(eaiSvcCd) == false){
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Unregistered API ["+eaiSvcCd+"] in ["+clientVO.getClientName()+"] APP");
+ }
+
+ return message;
+ }
+
+ private boolean verifyClientId(Properties prop, SignedJWT signedJWT) {
+ try {
+ // 이전 filter에서 셋팅한 clientId 확보
+ String headerClientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
+ String tokenClientId = (String) signedJWT.getJWTClaimsSet().getClaim(PAYLOAD_PARAM_NAME_CLIENT_ID);
+
+ // 이전 filter에서 셋팅한 값이 없다면 token 정보에서 확보
+ if (StringUtils.isBlank(headerClientId)) {
+ if (StringUtils.isNotBlank(tokenClientId)) {
+ prop.put(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID, tokenClientId);
+ }
+ } else { // header로 전달된 clientId가 있을때만 비교
+ if (!headerClientId.equals(tokenClientId)) {
+ return false;
+ }
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+
+ return true;
+ }
+
+ private String assignApiId(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request) {
+ String apiId = null;
+ try {
+ String actionName = prop.getProperty(Processor.REQUEST_ACTION);
+ RequestAction action = ActionFactory.createAction(actionName);
+ action.setAdapterInfo(adptGrpName, adptName, prop);
+ String[] keys = action.perform(message);
+ apiId = keys[0];
+
+ // PathVariable 지원 추가
+ apiId = StandardMessageUtil.getMatchedKey(apiId, actionName);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+
+// // header 에서 확보
+// String apiId = request.getHeader(HEADER_NAME_API_CODE);
+// if (StringUtils.isBlank(apiId)) {
+// // url에서 확보
+// // /ONLWeb/api/v1/public/getUserInfo.svc/
+// apiId = request.getRequestURI();
+// // /ONLWeb/api/v1/public/getUserInfo.svc
+// apiId = StringUtils.removeEnd(apiId, "/");
+// // getUserInfo.svc
+// apiId = StringUtils.substringAfterLast(apiId, "/");
+// }
+
+ return apiId;
+ }
+
+ @Override
+ public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return resultMessage;
+ }
+
+ private boolean verifyScope(HashSet scopeSet, SignedJWT signedJWT) throws ParseException {
+ if (scopeSet == null || scopeSet.isEmpty()) {
+ return true; // If no scope is specified in the api, all are allowed
+ }
+
+ String[] scopeArr = signedJWT.getJWTClaimsSet().getStringArrayClaim(PAYLOAD_PARAM_NAME_SCOPE);
+ if (scopeArr == null || scopeArr.length == 0) {
+ return false;
+ }
+
+ for (String scope : scopeArr) {
+ if (scopeSet.contains(scope)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static String extractJWTToken(HttpServletRequest request) throws JwtAuthException {
+ String authorization = request.getHeader("Authorization");
+ if (StringUtils.isBlank(authorization)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "No have header info: Authorization");
+ }
+
+ String[] components = authorization.split("\\s");
+
+ if (components.length != 2) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Malformat [Authorization] content");
+ }
+
+ if (!StringUtils.equalsIgnoreCase(components[0], "Bearer")) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "[Bearer] is needed");
+ }
+
+ return components[1].trim();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilter.java
new file mode 100644
index 0000000..600ed1a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilter.java
@@ -0,0 +1,15 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public interface HttpAdapterFilter {
+
+ public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception;
+
+ public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception;
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilterFactory.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilterFactory.java
new file mode 100644
index 0000000..0f1837b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilterFactory.java
@@ -0,0 +1,52 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.eactive.eai.common.util.Logger;
+
+public class HttpAdapterFilterFactory {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ static private ConcurrentHashMap h = new ConcurrentHashMap();
+
+ public HttpAdapterFilterFactory() {
+ super();
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static HttpAdapterFilter createFilter(String type) {
+ if (h.containsKey(type)) {
+ return (HttpAdapterFilter) h.get(type);
+ }
+
+ HttpAdapterFilter filter = null;
+ switch (HttpAdapterFilterType.getValue(type)) {
+ case APIAUTHFILTER:
+ filter = new ApiAuthFilter();
+ break;
+ case JWTAUTHFILTER:
+ filter = new JwtAuthFilter();
+ break;
+ case IPWHITELISTFILTER:
+ filter = new IpWhiteListFilter();
+ break;
+ case ADAPTERALLOWIPLISTFILTER:
+ filter = new AdapterAllowIPListFilter();
+ break;
+ default:
+ try {
+ Class cl = Class.forName(type);
+ filter = (HttpAdapterFilter) cl.newInstance();
+ } catch (Exception e) {
+ logger.error("Cannot create a HttpAdapterFilter. - {}", type);
+ }
+ break;
+ }
+
+ if (filter != null) {
+ h.put(type, filter);
+ return filter;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilterType.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilterType.java
new file mode 100644
index 0000000..6231c74
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/HttpAdapterFilterType.java
@@ -0,0 +1,17 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+public enum HttpAdapterFilterType {
+ APIAUTHFILTER,
+ JWTAUTHFILTER,
+ IPWHITELISTFILTER,
+ ADAPTERALLOWIPLISTFILTER,
+ UNKNOWN;
+
+ public static HttpAdapterFilterType getValue(String type) {
+ try {
+ return valueOf(type.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/IpWhiteListFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/IpWhiteListFilter.java
new file mode 100644
index 0000000..28e00e6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/IpWhiteListFilter.java
@@ -0,0 +1,90 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.authserver.service.OAuth2Manager;
+import com.eactive.eai.authserver.vo.ClientVO;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.util.IpUtil;
+
+public class IpWhiteListFilter implements HttpAdapterFilter {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ @Override
+ public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String clientId = assignClientId(prop, request);
+ if (StringUtils.isBlank(clientId)) {
+ throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL, "Can not find clientId info");
+ }
+
+ String requestIp = getClientIp(request);
+ try {
+ ClientVO client = (ClientVO) OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId);
+ if (client == null) {
+ throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL, "Can not find client info");
+ }
+
+ String allowedIps = client.getAllowedIp();
+ if (StringUtils.isBlank(allowedIps)) {
+ throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL,
+ "Allowed IP is not set in client info");
+ }
+
+ if (!IpUtil.isMatchIp(allowedIps, requestIp)) {
+ throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL,
+ "This IP was not allowed-" + requestIp);
+ }
+ } catch (JwtAuthException e) {
+ logger.debug(e.getMessage());
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL, "Client IP check failed-" + requestIp);
+ }
+
+ return message;
+ }
+
+ private String getClientIp(HttpServletRequest request) {
+ String ipAddress = request.getHeader("X-FORWARDED-FOR");
+ if (ipAddress == null) {
+ ipAddress = request.getRemoteAddr();
+ }
+ if(ipAddress.indexOf(",") >= 0) {
+ ipAddress = org.springframework.util.StringUtils.tokenizeToStringArray(ipAddress, ",")[0];
+ }
+ return ipAddress;
+ }
+
+ private String assignClientId(Properties prop, HttpServletRequest request) {
+ String clientId = null;
+ try {
+ // 이전 filter에서 셋팅한 clientId 확보
+ clientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
+
+ // 이전 filter에서 셋팅한 값이 없다면 header 정보에서 확보
+ if (StringUtils.isBlank(clientId)) {
+ clientId = request.getHeader(HttpAdapterServiceSupport.HEADER_NAME_CLIENT_ID);
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+
+ return clientId;
+ }
+
+ @Override
+ public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return resultMessage;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/JwtAuthException.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/JwtAuthException.java
new file mode 100644
index 0000000..3dbf36b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/JwtAuthException.java
@@ -0,0 +1,28 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+@SuppressWarnings("serial")
+public class JwtAuthException extends Exception {
+ private String code;
+
+ public JwtAuthException(String message) {
+ super(message);
+ }
+
+ public JwtAuthException(String code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+ public JwtAuthException(String code, String message, Throwable cause) {
+ super(message, cause);
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String toString() {
+ return getClass().getName() + ": [" + code + "] " + getLocalizedMessage();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/JwtAuthFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/JwtAuthFilter.java
new file mode 100644
index 0000000..1de5a38
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/JwtAuthFilter.java
@@ -0,0 +1,218 @@
+package com.eactive.eai.adapter.http.dynamic.filter;
+
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.text.ParseException;
+import java.util.Base64;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.authserver.service.OAuth2Manager;
+import com.eactive.eai.common.property.PropGroupVO;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.inbound.action.ActionFactory;
+import com.eactive.eai.inbound.action.RequestAction;
+import com.eactive.eai.inbound.processor.Processor;
+import com.eactive.eai.message.StandardMessageUtil;
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.util.IOUtils;
+import com.nimbusds.jwt.SignedJWT;
+
+public class JwtAuthFilter implements HttpAdapterFilter {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public static final String PROP_GROUP_AUTH_SERVER = "OAuthServer";
+ public static final String PROP_KEYSTORE_PATH = "certification.publicKeyPath";
+
+ public static final String ERROR_AUTHENTICATION_FAIL = "E.AUTHENTICATION_FAIL";
+ public static final String ERROR_AUTHORIZATION_FAIL = "E.AUTHORIZATION_FAIL";
+ public static final String ERROR_TOKEN_EXPIRED = "E.TOKEN_EXPIRED";
+
+ public static final String PAYLOAD_PARAM_NAME_SCOPE = "scope";
+ public static final String PAYLOAD_PARAM_NAME_CLIENT_ID = "client_id";
+
+ private JWSVerifier jwsVerifier;
+
+ public JwtAuthFilter() {
+ super();
+
+ PropGroupVO vo = PropManager.getInstance().getPropGroupVO(PROP_GROUP_AUTH_SERVER);
+ String publicKeyPath = "/certificate/elink-oauth-dev.pub";
+ if (vo != null) {
+ publicKeyPath = vo.getProperty(PROP_KEYSTORE_PATH);
+ } else {
+ logger.warn("The properties has not been set.[" + PROP_GROUP_AUTH_SERVER + "]");
+ }
+
+ Resource resource = new ClassPathResource(publicKeyPath);
+ String publicKey = null;
+ try {
+ publicKey = IOUtils.readInputStreamToString(resource.getInputStream());
+ publicKey = StringUtils.replace(publicKey, "-----BEGIN PUBLIC KEY-----", "");
+ publicKey = StringUtils.replace(publicKey, "-----END PUBLIC KEY-----", "");
+ publicKey = StringUtils.remove(publicKey, "\r");
+ publicKey = StringUtils.remove(publicKey, "\n");
+
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ jwsVerifier = new RSASSAVerifier((RSAPublicKey) keyFactory.generatePublic(keySpec));
+ } catch (IOException | NoSuchAlgorithmException | RuntimeException | InvalidKeySpecException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ String apiId = assignApiId(adptGrpName, adptName, message, prop, request);
+ if (StringUtils.isBlank(apiId)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Can not find apiId(apiCode) info");
+ }
+
+ try {
+ String token = JwtAuthFilter.extractJWTToken(request);
+ SignedJWT signedJWT = SignedJWT.parse(token);
+
+ if (new Date().after(signedJWT.getJWTClaimsSet().getExpirationTime())) {
+ throw new JwtAuthException(ERROR_TOKEN_EXPIRED, "Access token expired");
+ }
+
+ if (!signedJWT.verify(jwsVerifier)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
+ }
+
+ OAuth2Manager manager = OAuth2Manager.getInstance();
+ HashSet scopeSet = manager.getApiScopeMap().get(apiId);
+ if (!verifyScope(scopeSet, signedJWT)) {
+ throw new JwtAuthException(ERROR_AUTHORIZATION_FAIL,
+ String.format("Insufficient [Scope](Allowed Scope=%s)", scopeSet.toString()));
+ }
+
+ // header 값으로 전송된 clientId와 토큰 소유 clientId check
+ if (!verifyClientId(prop, signedJWT)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "client_id not matched(header/token)");
+ }
+ } catch (JwtAuthException e) {
+ logger.debug(e.getMessage());
+ throw e;
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Token invalid");
+ }
+
+ return message;
+ }
+
+ private boolean verifyClientId(Properties prop, SignedJWT signedJWT) {
+ try {
+ // 이전 filter에서 셋팅한 clientId 확보
+ String headerClientId = prop.getProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID);
+ String tokenClientId = (String) signedJWT.getJWTClaimsSet().getClaim(PAYLOAD_PARAM_NAME_CLIENT_ID);
+
+ // 이전 filter에서 셋팅한 값이 없다면 token 정보에서 확보
+ if (StringUtils.isBlank(headerClientId)) {
+ if (StringUtils.isNotBlank(tokenClientId)) {
+ prop.put(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID, tokenClientId);
+ }
+ } else { // header로 전달된 clientId가 있을때만 비교
+ if (!headerClientId.equals(tokenClientId)) {
+ return false;
+ }
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+
+ return true;
+ }
+
+ private String assignApiId(String adptGrpName, String adptName, Object message, Properties prop,
+ HttpServletRequest request) {
+ String apiId = null;
+ try {
+ String actionName = prop.getProperty(Processor.REQUEST_ACTION);
+ RequestAction action = ActionFactory.createAction(actionName);
+ action.setAdapterInfo(adptGrpName, adptName, prop);
+ String[] keys = action.perform(message);
+ apiId = keys[0];
+
+ // PathVariable 지원 추가
+ apiId = StandardMessageUtil.getMatchedKey(apiId, actionName);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+
+// // header 에서 확보
+// String apiId = request.getHeader(HEADER_NAME_API_CODE);
+// if (StringUtils.isBlank(apiId)) {
+// // url에서 확보
+// // /ONLWeb/api/v1/public/getUserInfo.svc/
+// apiId = request.getRequestURI();
+// // /ONLWeb/api/v1/public/getUserInfo.svc
+// apiId = StringUtils.removeEnd(apiId, "/");
+// // getUserInfo.svc
+// apiId = StringUtils.substringAfterLast(apiId, "/");
+// }
+
+ return apiId;
+ }
+
+ @Override
+ public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return resultMessage;
+ }
+
+ private boolean verifyScope(HashSet scopeSet, SignedJWT signedJWT) throws ParseException {
+ if (scopeSet == null || scopeSet.isEmpty()) {
+ return true; // If no scope is specified in the api, all are allowed
+ }
+
+ String[] scopeArr = signedJWT.getJWTClaimsSet().getStringArrayClaim(PAYLOAD_PARAM_NAME_SCOPE);
+ if (scopeArr == null || scopeArr.length == 0) {
+ return false;
+ }
+
+ for (String scope : scopeArr) {
+ if (scopeSet.contains(scope)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static String extractJWTToken(HttpServletRequest request) throws JwtAuthException {
+ String authorization = request.getHeader("Authorization");
+ if (StringUtils.isBlank(authorization)) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "No have header info: Authorization");
+ }
+
+ String[] components = authorization.split("\\s");
+
+ if (components.length != 2) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Malformat [Authorization] content");
+ }
+
+ if (!StringUtils.equalsIgnoreCase(components[0], "Bearer")) {
+ throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "[Bearer] is needed");
+ }
+
+ return components[1].trim();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceBypass.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceBypass.java
new file mode 100644
index 0000000..0d47483
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceBypass.java
@@ -0,0 +1,508 @@
+package com.eactive.eai.adapter.http.dynamic.impl;
+
+import java.net.HttpCookie;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.apache.mina.common.ByteBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.util.AntPathMatcher;
+
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.MessageUtil;
+import com.eactive.eai.env.ElinkConfig;
+import com.eactive.eai.inbound.action.ActionFactory;
+import com.eactive.eai.inbound.action.RequestAction;
+import com.eactive.eai.inbound.processor.Processor;
+import com.eactive.eai.message.StandardMessageUtil;
+
+public class HttpAdapterServiceBypass extends HttpAdapterServiceSupport {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public static final String HTTP_STATUS = "HTTP_STATUS";
+ public static final String PROPERTIES_NAME_HTTP_REQUEST_METHOD = "httpRequestMethod";
+ public static final String[] HOP_BY_HOP_HEADERS = new String[] { "Connection", "Keep-Alive", "Proxy-Authenticate",
+ "Proxy-Authorization", "TE", "Trailers", "Transfer-Encoding", "Upgrade" };
+
+ protected boolean doPreserveCookies = false;
+ protected boolean doPreserveCookiePath = false;
+
+ /**
+ * 1. 기능 : Header 값과 Body 값을 Bypass 한다.
+ *
+ * @param request Http Servlet Request
+ * @return response Http Servlet Response
+ * @exception Exception
+ **/
+ public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) {
+ int traceLevel = 0;
+
+ AdapterVO adptVO = null;
+ AdapterPropManager manager = null;
+
+ Properties httpProp = null;
+ String responseType = null;
+ String encode = null;
+
+ String traceLevelTemp = null;
+
+ StopWatch stopWatch = null;
+ Properties prop = null;
+ String errorResponseFormat = null;
+
+ try {
+ AdapterManager adapterManager = AdapterManager.getInstance();
+ adptVO = adapterManager.getAdapterVO(adptGrpName, adptName);
+ if (adptVO == null) {
+ throw new Exception("Adapter not found error");
+ }
+
+ manager = AdapterPropManager.getInstance();
+
+ httpProp = manager.getProperties(adptVO.getPropGroupName());
+ responseType = httpProp.getProperty(RESPONSE_TYPE, "SYNC");
+ encode = StringUtils.defaultIfBlank(adptVO.getAdapterGroupVO().getMessageEncode(), "UTF-8");
+ traceLevelTemp = httpProp.getProperty(TRACE_LEVEL, "0");
+ errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT);
+
+ try {
+ traceLevel = Integer.parseInt(traceLevelTemp);
+ } catch (Exception e) {
+ logger.warn("traceLevel parsing error - " + traceLevelTemp);
+ }
+
+ stopWatch = new StopWatch();
+ stopWatch.start();
+
+ logger.debug("시작 >> encode = [" + encode + "]");
+
+ String requestData = "";
+ if (request.getHeader(HttpHeaders.CONTENT_LENGTH) != null
+ || request.getHeader(HttpHeaders.TRANSFER_ENCODING) != null) {
+ ServletInputStream sis = request.getInputStream();
+ ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true);
+ int i = 0;
+ byte[] cbuf = new byte[1024];
+ while ((i = sis.read(cbuf, 0, 1024)) != -1) {
+ if (i == 1024) {
+ bb.put(cbuf);
+ } else {
+ byte[] tail = new byte[i];
+ System.arraycopy(cbuf, 0, tail, 0, i);
+ bb.put(tail);
+ }
+ }
+ byte[] data = new byte[bb.position()];
+ bb.position(0);
+ bb.get(data);
+ requestData = new String(data, encode);
+
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName,
+ "RECV " + "[Bypass Request..]" + CommonLib.getDumpMessage(requestData));
+ }
+ }
+
+ prop = new Properties();
+ prop.put(INBOUND_METHOD, request.getMethod());
+ prop.put(INBOUND_URI, request.getRequestURI());
+ prop.put(INBOUND_QUERY_STRING, StringUtils.defaultString(request.getQueryString()));
+ prop.put(INBOUND_HEADER, getHeaders(request));
+ if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)
+ || StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) {
+ // /api/v1/public/getUserInfo.svc
+ String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath());
+ prop.put(INBOUND_EXTURI, extUrl);
+ } else {
+ prop.put(INBOUND_EXTURI, getExtUri(request));
+ }
+ prop.put(Processor.REQUEST_ACTION, adptVO.getAdapterGroupVO().getRefClass());
+ prop.put(API_PATH, httpProp.getProperty(API_PATH, ""));
+ prop.put(INBOUND_REWRITE_PATH,
+ getRewritePath(prop.getProperty(INBOUND_EXTURI), prop.getProperty(API_PATH)));
+ prop.put(INBOUND_REMOTE_ADDR, request.getRemoteAddr());
+ prop.put(INBOUND_SCHEME, request.getScheme());
+ prop.put(PRE_FILTERS, httpProp.getProperty(PRE_FILTERS, ""));
+ prop.put(POST_FILTERS, httpProp.getProperty(POST_FILTERS, ""));
+ prop.put(PROPERTIES_NAME_HTTP_REQUEST_METHOD, request.getMethod());
+ prop.put(ALLOW_IP, httpProp.getProperty(ALLOW_IP, ""));
+
+ Map pathVariables = assignPathVariables(request, adptGrpName, adptName, null, prop);
+ if (pathVariables != null) {
+ prop.put(INBOUND_PATH_VARIABLES, pathVariables);
+ }
+
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceBypass] INBOUND_METHOD= " + prop.getProperty(INBOUND_METHOD));
+ logger.debug("HttpAdapterServiceBypass] INBOUND_URI= " + prop.getProperty(INBOUND_URI));
+ logger.debug("HttpAdapterServiceBypass] INBOUND_EXTURI= " + prop.getProperty(INBOUND_EXTURI));
+ logger.debug(
+ "HttpAdapterServiceBypass] INBOUND_QUERY_STRING= " + prop.getProperty(INBOUND_QUERY_STRING));
+ }
+
+// // check(현재 어댑터 = 서비스정보의 기동어댑터)
+// if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)) {
+// validateServiceAndAdapter(adptGrpName, adptName, message.getBytes(encode), prop);
+// }
+
+ // 로컬 서비스 호출
+ String result = (String) service(adptGrpName, adptName, requestData, prop, request, response);
+
+ stopWatch.stop();
+ logger.info("종료 >> encode = [" + encode + "]");
+
+ if (RESPONSE_TYPE_ASYNC.equals(responseType)) {
+ String responseData = "";
+ if (stopWatch.getTime() > slowTranTime) {
+ if (logger.isWarn()) {
+ logger.warn("HttpAdapterServiceBypass] lazy async response time = " + stopWatch.toString()
+ + ", message = " + requestData);
+ }
+ }
+
+ if (result == null) {
+ responseData = ElinkConfig.getAsyncDummyDataForAdapterGroup(adptGrpName);;
+ } else {
+ responseData = result;
+ }
+
+ long contentLength = result.getBytes(encode).length;
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));
+ response.setCharacterEncoding(encode);
+ response.getWriter().print(responseData);
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName, "SEND " + "[" + responseData + "]"
+ + ((responseData == null) ? "" : CommonLib.getDumpMessage(responseData)));
+ }
+ } else {
+ assignResponseHeaders(request, response, prop);
+
+ if (result != null) {
+
+ long contentLength = result.getBytes(encode).length;
+ response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));
+ if (logger.isDebug()) {
+ logger.debug("Response Content Lenght(Reset)=" + contentLength);
+ }
+
+ response.setCharacterEncoding(encode);
+ response.getWriter().print(result);
+ }
+
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName,
+ "SEND " + "[Bypass Response..]" + CommonLib.getDumpMessage(result));
+ }
+ }
+ } catch (HttpStatusException e) {
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.warn("HttpAdapter] " + adptGrpName + "-" + adptName + ">>" + e.getMessage());
+ response.setStatus(e.getStatus());
+ try {
+ String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptVO.getAdapterGroupVO().getMessageType(),
+ encode, e.getCode(), e.getMessage(), errorResponseFormat);
+ response.getWriter().println(errorMsg);
+ } catch (Exception ex) {
+ // IGNORE
+ }
+ } catch (JwtAuthException e) {
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.error("HttpAdapterServiceRest] " + adptGrpName + "-" + adptName + ">>" + e.getMessage(), e);
+ response.setStatus(HttpStatus.UNAUTHORIZED.value());
+ try {
+ String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptVO.getAdapterGroupVO().getMessageType(),
+ encode, e.getCode(), e.getMessage(), errorResponseFormat);
+ response.getWriter().println(errorMsg);
+ } catch (Exception ex) {
+ // IGNORE
+ }
+ } catch (Exception e) {
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.error("HttpAdapterServiceBypass] " + adptGrpName + "-" + adptName + ">>" + e.getMessage(), e);
+ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ try {
+ response.getWriter().println(e.getMessage());
+ String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
+ throw new Exception(errCode);
+ } catch (Exception ex) {
+ // IGNORE
+ logger.warn("HttpAdapterServiceBypass] " + adptGrpName + "-" + adptName + ">>" + e.getMessage(), e);
+ }
+ }
+ }
+
+// private void validateServiceAndAdapter(String adptGrpName, String adptName, byte[] requestBytes, Properties prop)
+// throws JwtAuthException {
+// try {
+// String actionName = prop.getProperty(Processor.REQUEST_ACTION);
+// RequestAction action = ActionFactory.createAction(actionName);
+// action.setAdapterInfo(adptGrpName, adptName, prop);
+// String[] keys = action.perform(requestBytes);
+// String apiId = keys[0];
+//
+// // PathVariable 지원 추가
+// apiId = StandardMessageUtil.getMatchedKey(apiId, actionName);
+// if (apiId == null) {
+// throw new Exception("apiId");
+// }
+//
+//// STDMessageManager stdheaderManager = STDMessageManager.getInstance();
+//// STDMessage stdmessage = stdheaderManager.getSTDMessage(apiId);
+//// if (stdmessage == null) {
+//// throw new Exception("stdMsg");
+//// }
+//
+// long msgRcvTm = System.currentTimeMillis();
+// AdapterManager adapterManager = AdapterManager.getInstance();
+// AdapterGroupVO adptGrpVO = adapterManager.getAdapterGroupVO(adptGrpName);
+// ProcessVO processVO = setProcessVO(apiId, adptGrpVO.getOsidInstiNo(), msgRcvTm, adptGrpName, adptName);
+// ExtMessage extMessage = ExtMessageConverter.getExtMessageForNonStandard(requestBytes, requestBytes, processVO);
+//
+// EAIMessageManager eaiMsgManager = EAIMessageManager.getInstance();
+//// String eaiSvcCd = stdmessage.getEAITranName() + stdmessage.getSTDHeader().getMesgDvcd();
+// String eaiSvcCd = extMessage.getEAIServiceCode();
+// if (eaiSvcCd == null) {
+// eaiSvcCd = extMessage.getInterfaceId() + extMessage.getSendRecv() + extMessage.getDirection();
+// }
+// EAIMessage eaiMsg = eaiMsgManager.getEAIMessage(eaiSvcCd);
+// logger.warn("adptGrpName=[" + adptGrpName + "],eaiSvcCd=[" + eaiSvcCd + "],eaiMsg=[" + eaiMsg
+// + "],getSngSysItfTp=[" + "]");
+// if (eaiMsg == null) {
+// throw new Exception("eaiMsg");
+// }
+//
+// if (!StringUtils.equals(eaiMsg.getSngSysItfTp(), adptGrpName)) {
+// throw new Exception("adapter");
+// }
+// } catch (Exception e) {
+// String msg = String.format("The resource does not exist or does not have permissions(%s): %s",
+// e.getMessage(), prop.get(INBOUND_EXTURI));
+// throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL, msg);
+// }
+// }
+
+// private ProcessVO setProcessVO(String apiId, String osidInstiNo, long msgRcvTm, String adptGrpName,
+// String adptName) {
+// ProcessVO vo = new ProcessVO();
+// vo.setSelectedKey(apiId);
+// vo.setAdapterGroupName(adptGrpName);
+// vo.setAdapterName(adptName);
+// vo.setInAdapterOsidInstiNo(osidInstiNo);
+// vo.setErrTm(msgRcvTm);
+// return vo;
+// }
+
+ private String getRewritePath(String extUri, String basePath) {
+ return StringUtils.removeStart(extUri, StringUtils.removeEnd(basePath, "/"));
+ }
+
+ private Map assignPathVariables(HttpServletRequest request, String adptGrpName, String adptName,
+ Object requestBytes, Properties prop) {
+ Map variablesMap = null;
+ // QueryString 있을때는 체크(X)
+ if (StringUtils.isBlank(request.getQueryString())) {
+ try {
+ String actionName = prop.getProperty(Processor.REQUEST_ACTION);
+ RequestAction action = ActionFactory.createAction(actionName);
+ action.setAdapterInfo(adptGrpName, adptName, prop);
+ String[] keys = action.perform(requestBytes);
+ String requestPath = keys[0];
+
+ // PathVariable 지원 추가
+ String ruledPath = StandardMessageUtil.getMatchedKey(requestPath, actionName);
+ if (!StringUtils.equals(requestPath, ruledPath) && StringUtils.contains(ruledPath, "{")) {
+ variablesMap = new AntPathMatcher().extractUriTemplateVariables(ruledPath, requestPath);
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+
+ return variablesMap;
+ }
+
+ /**
+ * request header 를 Properties로 조립
+ *
+ * @param request
+ * @return
+ */
+ private Properties getHeaders(HttpServletRequest request) {
+ Properties prop = new Properties();
+
+ Enumeration headerNames = request.getHeaderNames();
+ while (headerNames.hasMoreElements()) {
+ String key = headerNames.nextElement();
+ String value = request.getHeader(key);
+ prop.setProperty(key, value);
+ }
+
+ return prop;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void assignResponseHeaders(HttpServletRequest request, HttpServletResponse response, Properties prop) {
+ Map outboundPropertyMap = (Map) prop.get(OUTBOUND_PROPERTY_MAP);
+ if (outboundPropertyMap == null) {
+ return;
+ }
+
+ Properties headerProp = (Properties) outboundPropertyMap.get(OUTBOUND_RESPONSE_HEADERS);
+ if (headerProp == null) {
+ return;
+ }
+
+ String httpStatus = "200";
+ for (Entry e : headerProp.entrySet()) {
+ String key = (String) e.getKey();
+ String value = (String) e.getValue();
+
+ if (StringUtils.equalsAnyIgnoreCase(key, HOP_BY_HOP_HEADERS)) {
+ continue;
+ }
+
+ if (StringUtils.equalsIgnoreCase(key, HttpHeaders.CONTENT_LENGTH)) {
+ if (logger.isDebug()) {
+ logger.debug("Response Content Lenght(Header)=" + value);
+ }
+ continue;
+ }
+
+ if (StringUtils.equalsAnyIgnoreCase(key, HttpHeaders.SET_COOKIE, HttpHeaders.SET_COOKIE2)) {
+ for (HttpCookie cookie : HttpCookie.parse(value)) {
+ Cookie servletCookie = createProxyCookie(request, cookie);
+ response.addCookie(servletCookie);
+ }
+ continue;
+ }
+
+ if (StringUtils.equalsIgnoreCase(key, HTTP_STATUS)) {
+ if (StringUtils.isNotBlank(value)) {
+ httpStatus = value;
+ continue;
+ }
+ }
+
+ if (StringUtils.equalsIgnoreCase(key, HttpHeaders.LOCATION)) {
+ if (!StringUtils.startsWith(httpStatus, "3")) {
+ httpStatus = "302";
+ }
+ }
+
+ response.addHeader(key, value);
+ }
+ response.setStatus(Integer.parseInt(httpStatus));
+ }
+
+ /**
+ * Creates a proxy cookie from the original cookie.
+ *
+ * @param servletRequest original request
+ * @param cookie original cookie
+ * @return proxy cookie
+ */
+ protected Cookie createProxyCookie(HttpServletRequest servletRequest, HttpCookie cookie) {
+ String proxyCookieName = getProxyCookieName(cookie);
+ Cookie servletCookie = new Cookie(proxyCookieName, cookie.getValue());
+ servletCookie.setPath(this.doPreserveCookiePath ? cookie.getPath() : // preserve original cookie path
+ buildProxyCookiePath(servletRequest) // set to the path of the proxy servlet
+ );
+ servletCookie.setComment(cookie.getComment());
+ servletCookie.setMaxAge((int) cookie.getMaxAge());
+ // don't set cookie domain
+ servletCookie.setSecure(servletRequest.isSecure() && cookie.getSecure());
+ servletCookie.setVersion(cookie.getVersion());
+ servletCookie.setHttpOnly(cookie.isHttpOnly());
+ return servletCookie;
+ }
+
+ /**
+ * Set cookie name prefixed with a proxy value so it won't collide with other
+ * cookies.
+ *
+ * @param cookie cookie to get proxy cookie name for
+ * @return non-conflicting proxy cookie name
+ */
+ protected String getProxyCookieName(HttpCookie cookie) {
+ return doPreserveCookies ? cookie.getName() : getCookieNamePrefix(cookie.getName()) + cookie.getName();
+ }
+
+ /**
+ * Create path for proxy cookie.
+ *
+ * @param servletRequest original request
+ * @return proxy cookie path
+ */
+ protected String buildProxyCookiePath(HttpServletRequest servletRequest) {
+ String path = servletRequest.getContextPath(); // path starts with / or is empty string
+ path += servletRequest.getServletPath(); // servlet path starts with / or is empty string
+ if (path.isEmpty()) {
+ path = "/";
+ }
+ return path;
+ }
+
+ /** The string prefixing rewritten cookies. */
+ protected String getCookieNamePrefix(String name) {
+ return "!Proxy!eLink";
+ }
+
+ /**
+ * 어댑터 명 이후를 가져온다.
+ *
+ * @param request
+ * @return
+ */
+ private String getExtUri(HttpServletRequest request) {
+ String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), "");
+ String uri = getExtUri(orgUri, 3);
+ if (uri != null && uri.trim().length() > 0) {
+ return "/" + uri;
+ } else {
+ return "";
+ }
+ }
+
+ private static String getExtUri(String url, int length) {
+ String[] urls = url.split("/");
+ List newUrls = new ArrayList<>();
+ Collections.addAll(newUrls, urls);
+ return StringUtils.join(newUrls.subList(length, urls.length).toArray(), "/");
+ }
+
+ public static void main(String[] args) throws Exception {
+ String orgUri = "/HTT/CbsInNetSys/abcd/123456";
+ String result = "";
+ result = getExtUri(orgUri, 3);
+ System.out.println(result);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceChannel.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceChannel.java
new file mode 100644
index 0000000..3365aea
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceChannel.java
@@ -0,0 +1,943 @@
+package com.eactive.eai.adapter.http.dynamic.impl;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.time.StopWatch;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.mina.common.ByteBuffer;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpMethodType;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.common.dao.DAOException;
+import com.eactive.eai.common.dao.DAOFactory;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.property.PropertyLoginKeys;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.session.ChannelSessionFacade;
+import com.eactive.eai.common.session.ChannelSessionFacade.LogoutType;
+import com.eactive.eai.common.session.SessionHistoryLogger;
+import com.eactive.eai.common.session.SessionManager;
+import com.eactive.eai.common.session.SessionVO;
+import com.eactive.eai.common.sessioninfo.SessionHistoryDTO;
+import com.eactive.eai.common.sessioninfo.SessionHistoryVO;
+import com.eactive.eai.common.util.ApplicationContextProvider;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.common.util.DatetimeUtil;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.UUIDGenerator;
+import com.eactive.eai.env.ElinkConfig;
+import com.eactive.eai.inbound.error.InboundErrorInfoDAO;
+import com.eactive.eai.inbound.error.InboundErrorInfoVO;
+import com.eactive.eai.message.StandardMessage;
+import com.eactive.eai.message.manager.StandardMessageManager;
+import com.eactive.eai.message.parser.StandardReader;
+import com.eactive.eai.message.service.InterfaceMapper;
+import com.ext.eai.common.stdmessage.STDMessageErrorKeys;
+import com.ext.eai.common.stdmessage.STDMessageKeys;
+
+public class HttpAdapterServiceChannel extends HttpAdapterServiceSupport {
+
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ private static String instid = null;
+ private static String serverName = null;
+ static {
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ instid = eaiServerManager.getInstId();
+ serverName = eaiServerManager.getLocalServerName();
+ }
+
+ /**
+ * 1. 기능 : Http Servlet service 구현 메소드
+ * 2. 처리 개요 : - 로컬 서비스 호출
+ * 3. 주의사항
+ *
+ * @param request Http Servlet Request
+ * @return response Http Servlet Response
+ * @exception Exception PARAMETER_MESSAGE가 null 이거나 로컬 서비스 호출 중 오류가 발생할 경우
+ **/
+ public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) {
+
+ try {
+
+ ChannelServiceDataBundle bundle = new ChannelServiceDataBundle(adptGrpName, adptName, request, response);
+
+ try {
+
+ /** SERVICE START **/
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ logger.info("시작 >> encode = [" + bundle.getEncode() + "] Method [" + request.getMethod() + "]");
+
+ response.addHeader("Access-Control-Allow-Origin", "*");
+ response.addHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
+ response.addHeader("Access-Control-Allow-Headers", "Origin,Accept,X-Requested-With,Access-Control-Request-Method,Access-Control-Request-Header,Authorization,Cookie,Content-Type,Content-Length");
+ response.addHeader("Access-Control-Expose-Headers", "Set-Cookie,X-Powered-By");
+ response.addHeader("Access-Control-Allow-Credentials", "true");
+ response.addHeader("Access-Control-Max-Age", "3600");
+
+ switch (HttpMethodType.getValue(request.getMethod())) {
+ case GET:
+ case DELETE:
+ case POST:
+ case PUT:
+ break;
+ default:
+ if (logger.isInfo()) {
+ logger.info("HttpAdapterServiceChannel] SET RESPONSE HEADER FOR ACAO Method[" + request.getMethod() + "] remoteAddress=" + request.getRemoteAddr());
+ }
+ return;
+ }
+
+ ChannelResponseDivider responseDivider = new ChannelResponseDivider(bundle);
+
+ /** Phase 1 **/
+ switch(responseDivider.dividePhase1()) {
+
+ case HttpPoll:
+ httpPollResponse(request, response, bundle);
+ return; // * return service
+
+ case DupLoginCheck:
+ dupLoginCheckResponse(request, response, bundle);
+ return; // * return service
+
+ case LoginValidation:
+ loginValidationResponse(request, response, bundle);
+ return; // * return service
+
+ case LoginUuidValidation:
+ loginUuidValidationResponse(request, response, bundle);
+ return; // * return service
+
+ default:
+ break; // go phase 2
+ }
+
+ stopWatch.stop();
+
+ if(logger.isDebug()){
+ String[] msgArgs = { adptGrpName, new String(bundle.getRequestBytes(), bundle.getEncode()) };
+ String resMsg = ExceptionUtil.make("RICEAIAHA005", msgArgs);
+ logger.debug("HttpAdapterServiceChannel] " + resMsg);
+ }
+
+ // 로컬 서비스 호출
+ logger.warn("HttpAdapterServiceChannel] REAL CALL HttpSession userId = " + bundle.getUserId() + ", message = " + new String(bundle.getRequestBytes(), bundle.getEncode()));
+ Object obj = service(adptGrpName, adptName, bundle.getRequestBytes(), new Properties(), request, response );
+ AdapterManager manager = AdapterManager.getInstance();
+ AdapterGroupVO group = manager.getAdapterGroupVO(adptGrpName);
+
+ byte[] result = null;
+
+ if (obj instanceof byte[]) {
+ result = (byte[])obj;
+ }else if (obj instanceof String){
+ result = ((String)obj).getBytes(StringUtils.defaultIfBlank(group.getMessageEncode(), Charset.defaultCharset().name()));
+ }
+
+ /** Phase 2 **/
+ switch(responseDivider.dividePhase2()) {
+
+ case Async:
+ asyncResponse(request, response, bundle, stopWatch, result);
+ break;
+
+ case LoginTransaction:
+ result = loginResponse(request, response, bundle, result);
+ break;
+
+ case LogoutTransaction:
+ result = logoutResponse(request, response, bundle, result);
+ break;
+
+ default:
+ break;
+
+ }
+
+ String responseData = new String(result, bundle.getEncode()); // UI와 통신시(UTF-8) 변환오류로 ENCODE 제거
+ logger.info("종료 >> encode = [" + bundle.getEncode() + "]");
+
+ if (bundle.getAddData().length() > 0) {
+ responseData = bundle.getAddData() + responseData;
+ }
+
+ response.setContentType("application/json"); // FIXME ContentType application/json으로 임시 셋팅 추후 어댑터 설정으로 변경 필요
+ response.setCharacterEncoding(bundle.getEncode()); // UI와 통신시(UTF-8) 변환오류로 ENCODE 제거
+ response.getWriter().print(responseData);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceChannel] SEND (" + adptGrpName + ") = [" + responseData + "]");
+ logger.debug("HttpAdapterServiceChannel] SEND (" + adptGrpName + ") = " + ((responseData == null) ? "" : CommonLib.getDumpMessage(responseData.getBytes(bundle.getEncode()))));
+ }
+
+ if (bundle.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName, "SEND " + "[" + responseData + "]" + ((responseData == null) ? "" : CommonLib.getDumpMessage(responseData.getBytes(bundle.getEncode()))));
+ }
+
+
+ } catch (Exception e) {
+ if (bundle.getTraceLevel() >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.error("HttpAdapterServiceChannel] " + adptGrpName + "-" + adptName + " guid=" + bundle.getGuid(), e);
+ response.setStatus(500);
+ try {
+ response.getWriter().println(e.getMessage());
+ String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
+ throw new Exception(errCode);
+ } catch (Exception ex) {
+ logger.warn("error", ex);
+ }
+ }
+
+
+ } catch (ServletException | IOException e) {
+ logger.error("HttpAdapterServiceChannel] " + adptGrpName + "-" + adptName, e);
+ response.setStatus(500);
+ try {
+ response.getWriter().println(e.getMessage());
+ String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
+ throw new Exception(errCode);
+ } catch (Exception ex) {
+ logger.warn("error", ex);
+ }
+ }
+
+ }
+
+ private void httpPollResponse(HttpServletRequest request, HttpServletResponse response, ChannelServiceDataBundle bundle) throws IOException {
+
+ String message = new String(bundle.getRequestBytes(), bundle.getEncode());
+
+ if (logger.isInfo()) {
+ logger.info("HttpAdapterServiceChannel] HTTPPOLL remoteAddress=" + request.getRemoteAddr() + " response=" + message);
+ }
+ String userId = message.substring(9, 9 + 9);
+ String uuid = message.substring(9 + 9, 58);
+
+ String responseMessage;
+
+ SessionVO sVo = SessionManager.getInstance().getHttpLogin(uuid);
+ String trimingId = StringUtils.trim(userId);
+
+ if (sVo == null) {
+ //ERROR
+ logger.warn("HttpAdapterServiceChannel] HTTPPOLL loginId=(" + trimingId + ") uuid[" + uuid + "] HTTPLOGIN not found");
+ responseMessage = "POLLERR@@" + userId + uuid;
+
+ } else {
+ //RESPONSE
+ PropManager pManager = PropManager.getInstance();
+ String cacheType = pManager.getProperty(SessionManager.SESSION_MANAGER_GROUPNAME,
+ SessionManager.SESSION_MANAGER_CACHETYPE, "EHCACHE");
+ logger.info("HttpAdapterServiceChannel] HTTPPOLL loginId=(" + trimingId + ") uuid[" + uuid + "] refresh HTTPLOGIN");
+
+ ChannelSessionFacade.getInstance().refreshHttpLoginCache(uuid, sVo);
+
+ responseMessage = "POLLRES@@" + userId + uuid;
+ }
+
+ logger.info("HttpAdapterServiceChannel] HTTPPOLL loginId=(" + trimingId + ") uuid[" + uuid + "] RESPONSE[" + responseMessage + "]");
+
+ response.setCharacterEncoding(bundle.getEncode());
+ response.getWriter().print(responseMessage);
+
+ }
+
+ private void loginValidationResponse(HttpServletRequest request, HttpServletResponse response, ChannelServiceDataBundle bundle) throws Exception {
+
+ Properties prop = PropManager.getInstance().getProperties(PropertyLoginKeys.LOGIN);
+
+ String CODE = prop.getProperty(PropertyLoginKeys.VALIDATION_LOGIN_CODE, STDMessageErrorKeys.NOT_LOGIN_ERROR_CODE_VALUE);
+ String MSG = prop.getProperty(PropertyLoginKeys.VALIDATION_LOGIN_MSG, STDMessageErrorKeys.NOT_LOGIN_ERROR_MSG_VALUE);
+
+ logger.error("HttpAdapterServiceChannel] NOTLOGIN OR EXPIRED SESSION userId[" + bundle.getUserId() + "] - RETURN ERROR.");
+
+ StandardMessage standardMessage = null;
+ StandardMessageManager standardManager = StandardMessageManager.getInstance();
+ StandardReader reader = null;
+ InterfaceMapper mapper = standardManager.getMapper();
+ AdapterGroupVO vo = AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName());
+ String messageType = vo.getMessageType();
+ String messageEncode = vo.getMessageEncode();
+ standardMessage = standardManager.getStandardMessage();
+ reader = standardManager.getReader(messageType);
+ reader.parse(standardMessage, bundle.getRequestBytes());
+ // 표준전문 파싱 후 어댑터의 charset을 설정한다.
+ standardMessage.setBizDataCharset(messageEncode);
+ standardManager.getMessageCoordinator().coordinateSetStandardMessageError(standardMessage, mapper, "RECEAIAHA020", null);
+ String responseData = standardMessage.getDataString(messageType, messageEncode);
+
+// ExtMessage extMessage = ExtMessageConverter.getExtMessageForStandard(bundle.getRequestBytes(), AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName()).getMessageType());
+// byte[] result = ExtMessageConverter.getDuplicateLoginResponseForStandard(extMessage, "", MSG, CODE, MSG);
+// String responseData = new String(result, bundle.getEncode());
+
+// response.setCharacterEncoding(bundle.getEncode());
+ response.setContentType("application/json");// FIXME ContentType application/json으로 임시 셋팅 추후 어댑터 설정으로 변경필요"
+ response.setCharacterEncoding(messageEncode);
+ response.getWriter().print(responseData);
+
+ //정의되지 않는 메시지에 로그추가
+ logUnknown(bundle,CODE,MSG);
+
+
+ }
+ private void loginUuidValidationResponse(HttpServletRequest request, HttpServletResponse response, ChannelServiceDataBundle bundle) throws Exception {
+
+ Properties prop = PropManager.getInstance().getProperties(PropertyLoginKeys.LOGIN);
+
+ String CODE = prop.getProperty(PropertyLoginKeys.VALIDATION_LOGIN_CODE, STDMessageErrorKeys.UUID_MISMATCH_ERROR_CODE_VALUE);
+ String MSG = prop.getProperty(PropertyLoginKeys.VALIDATION_LOGIN_MSG, STDMessageErrorKeys.UUID_MISMATCH_ERROR_MSG_VALUE);
+
+ logger.error("HttpAdapterServiceChannel] UUID mismatch userId[" + bundle.getUserId() + "] - RETURN ERROR.");
+ StandardMessage standardMessage = null;
+ StandardMessageManager standardManager = StandardMessageManager.getInstance();
+ StandardReader reader = null;
+ InterfaceMapper mapper = standardManager.getMapper();
+ AdapterGroupVO vo = AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName());
+ String messageType = vo.getMessageType();
+ String messageEncode = vo.getMessageEncode();
+ standardMessage = standardManager.getStandardMessage();
+ reader = standardManager.getReader(messageType);
+ reader.parse(standardMessage, bundle.getRequestBytes());
+ // 표준전문 파싱 후 어댑터의 charset을 설정한다.
+ standardMessage.setBizDataCharset(messageEncode);
+ standardManager.getMessageCoordinator().coordinateSetStandardMessageError(standardMessage, mapper, "RECEAIAHA022", null);
+ String responseData = standardMessage.getDataString(messageType, messageEncode);
+// ExtMessage extMessage = ExtMessageConverter.getExtMessageForStandard(bundle.getRequestBytes(), AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName()).getMessageType());
+// byte[] result = ExtMessageConverter.getDuplicateLoginResponseForStandard(extMessage, "", MSG, CODE, MSG);
+// String responseData = new String(result, bundle.getEncode());
+
+ response.setContentType("application/json");// FIXME ContentType application/json으로 임시 셋팅 추후 어댑터 설정으로 변경필요"
+ response.setCharacterEncoding(messageEncode);
+ response.getWriter().print(responseData);
+
+ //정의되지 않는 메시지에 로그추가
+ logUnknown(bundle,CODE,MSG);
+
+ }
+
+ //login validation 오류 로그 추가 2022-11-09
+ private void logUnknown(ChannelServiceDataBundle bundle,String errorCode,String errorMsg) throws Exception {
+ String uuid = instid + UUIDGenerator.getUUID();
+
+ InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO();
+ errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호
+ errorInfoVO.setAdptBwkGrpNm(bundle.getAdptGrpName()); // 어댑터업무그룹명
+ errorInfoVO.setEaiSvcCd("");
+ errorInfoVO.setErrCd(errorCode); // 에러코드
+ errorInfoVO.setErrTxt(errorMsg); // 에러내용
+ errorInfoVO.setErrTm(DatetimeUtil.getCurrentTimeMillis()); // 에러발생시각
+ errorInfoVO.setErrDstcd("IE");
+ errorInfoVO.setBzwkSvcKeyName("");
+ errorInfoVO.setBwkDataTxt(new String(bundle.getRequestBytes(), bundle.getEncode())); // 업무데이터내용
+ errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명
+ try {
+ InboundErrorInfoDAO dao = ApplicationContextProvider.getContext().getBean(InboundErrorInfoDAO.class);
+ dao.addInboundErrorInfo(errorInfoVO);
+ } catch(DAOException e) {
+ if (logger.isError()) logger.error("RequestProcessor] Unknown Message Logging Error", e);
+ }
+
+ if (logger.isError()) {
+ logger.error("======================================================================" );
+ logger.error(" HttpAdapterServiceChannel] GET LOGIN VALIDATION ERROR MESSAGE");
+ logger.error(" ADAPTER GROUP NAME [" + bundle.getAdptGrpName() + "]");
+ logger.error(" ADAPTER NAME [" + bundle.getAdptName() + "]");
+ logger.error(" USER_ID [" + bundle.getUserId() + "]");
+ logger.error("======================================================================" );
+ }
+ }
+
+ private void dupLoginCheckResponse(HttpServletRequest request, HttpServletResponse response, ChannelServiceDataBundle bundle) throws Exception {
+
+ Properties prop = PropManager.getInstance().getProperties(PropertyLoginKeys.LOGIN);
+
+ logger.error("HttpAdapterServiceChannel] LOGIN-DUPLICATED loginUserId= " + bundle.getUserId());
+
+ String DUPLICATE_LOGIN_CODE = prop.getProperty(PropertyLoginKeys.DUPLICATE_LOGIN_CODE, STDMessageErrorKeys.DUP_LOGIN_ERROR_CODE_VALUE);
+ String DUPLICATE_LOGIN_MSG = prop.getProperty(PropertyLoginKeys.DUPLICATE_LOGIN_MSG, STDMessageErrorKeys.DUP_LOGIN_ERROR_MSG_VALUE);
+ StandardMessage standardMessage = null;
+ StandardMessageManager standardManager = StandardMessageManager.getInstance();
+ StandardReader reader = null;
+ InterfaceMapper mapper = standardManager.getMapper();
+ AdapterGroupVO vo = AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName());
+ String messageType = vo.getMessageType();
+ String messageEncode = vo.getMessageEncode();
+ standardMessage = standardManager.getStandardMessage();
+ reader = standardManager.getReader(messageType);
+ reader.parse(standardMessage, bundle.getRequestBytes());
+ // 표준전문 파싱 후 어댑터의 charset을 설정한다.
+ standardMessage.setBizDataCharset(messageEncode);
+ standardManager.getMessageCoordinator().coordinateSetStandardMessageError(standardMessage, mapper,"RECEAIAHA021", null);
+ String responseData = standardMessage.getDataString(messageType, messageEncode);
+
+// response.setCharacterEncoding(bundle.getEncode());
+ response.getWriter().print(responseData);
+
+ String remoteIp = request.getHeader("X-Forwarded-For") != null ? request.getHeader("X-Forwarded-For") : request.getRemoteAddr();
+
+ SessionHistoryLogger.getInstance().log(
+ new SessionHistoryDTO(new String(bundle.getRequestBytes(), bundle.getEncode()), SessionHistoryVO.HISTORYDSTCD_DUPLOGIN, "E", null, remoteIp, true));
+
+ }
+
+ private void asyncResponse(HttpServletRequest request, HttpServletResponse response, ChannelServiceDataBundle bundle, StopWatch stopWatch, byte[] serviced) throws IOException {
+
+ if (stopWatch.getTime() > slowTranTime) {
+ if (logger.isWarn()) {
+ logger.warn("HttpAdapterServiceChannel] lazy async response time = " + stopWatch.toString() + ", message = " + new String(bundle.getRequestBytes(), bundle.getEncode()));
+ }
+ }
+
+ String responseData = serviced == null ? ElinkConfig.getAsyncDummyData("K") : new String(serviced, bundle.getEncode());
+
+ response.setCharacterEncoding(bundle.getEncode());
+ response.getWriter().print(responseData);
+
+ if (bundle.getTraceLevel() >= 3) {
+ HttpMemoryLogger.txlog(bundle.getAdptGrpName() + bundle.getAdptName(), "SEND " + "[" + responseData + "]" + ((responseData == null) ? "" : CommonLib.getDumpMessage(responseData.getBytes())));
+ }
+
+ }
+
+ private byte[] loginResponse(HttpServletRequest request, HttpServletResponse response, ChannelServiceDataBundle bundle, byte[] serviced) throws Exception {
+
+ String uuid = "UUID" + UUIDGenerator.getUUID();
+ // set uuid to STDMessage Header MCI_INTF_SESN_ID
+ /*
+ * 응답전문 변경 및 로그인 거래 일 경우에만 수행하므로 개발 용이성을 위해
+ * ExtMessageConverter.getExtMessageForStandard 코드를 유지
+ */
+// ExtMessage resExtMessage = ExtMessageConverter.getExtMessageForStandard(serviced, AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName()).getMessageType());
+
+ // 정상응답인지 확인 : RSPNS_RSLT_DVSN_CD = N
+// String respRsltDvsnCode = resExtMessage.getResponseType();
+ StandardMessage standardMessage = null;
+ StandardMessageManager standardManager = StandardMessageManager.getInstance();
+ StandardReader reader = null;
+ InterfaceMapper mapper = standardManager.getMapper();
+ AdapterGroupVO vo = AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName());
+ String messageType = vo.getMessageType();
+ String messageEncode = vo.getMessageEncode();
+ standardMessage = standardManager.getStandardMessage();
+ reader = standardManager.getReader(messageType);
+ reader.parse(standardMessage, serviced);
+ // 표준전문 파싱 후 어댑터의 charset을 설정한다.
+ standardMessage.setBizDataCharset(messageEncode);
+ String respRsltDvsnCode = mapper.getResponseType(standardMessage);
+ if (STDMessageKeys.RESPONSE_TYPE_CODE_N.equals(respRsltDvsnCode)) { // FIXME
+
+ // 2023. 12. 12. KAKAOBANK-CARD userId From Response Standard Header
+ bundle.setUserId(mapper.getUserId(standardMessage));
+
+ mapper.setSessionId(standardMessage, uuid);
+ mapper.setInstCode(standardMessage, EAIServerManager.getInstance().getLocalServerName());
+// resExtMessage.setSessionId(uuid);
+// STDMessage stdMsg = (STDMessage)resExtMessage.getStdMessage();
+// byte[] bizData = (byte[]) resExtMessage.getBizData()[0];
+// JSONObject resultJson = (JSONObject) JSONValue.parse(new String((byte[]) bizData, MessageType.UJSON_ENCODE));
+
+// serviced = ExtMessageConverter.toJsonBytes(resExtMessage, bundle.getEncode());
+ JSONObject resultJson = (JSONObject) JSONValue.parse(standardMessage.getBizData());
+ serviced = standardMessage.getDataBytes(messageType, messageEncode);
+ ChannelSessionFacade.getInstance().login(bundle.getUserId(), uuid, resultJson);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceChannel] loginId=(" + bundle.getUserId() + ") uuid[" + uuid + "]");
+ }
+
+ } else {
+ logger.warn("HttpAdapterServiceChannel] LOGIN Failed RSPNS_RSLT_DVSN_CD =" + respRsltDvsnCode);
+ }
+
+ String remoteIp = request.getHeader("X-Forwarded-For") != null ? request.getHeader("X-Forwarded-For") : request.getRemoteAddr();
+
+ SessionHistoryLogger.getInstance().log(
+ new SessionHistoryDTO(new String(bundle.getRequestBytes(), bundle.getEncode()), SessionHistoryVO.HISTORYDSTCD_LOGIN, respRsltDvsnCode, uuid, remoteIp, true));
+
+ return serviced;
+ }
+
+ private byte[] logoutResponse(HttpServletRequest request, HttpServletResponse response, ChannelServiceDataBundle bundle, byte[] serviced) throws Exception {
+
+// ExtMessage resExtMessage = ExtMessageConverter.getExtMessageForStandard(serviced, AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName()).getMessageType());
+ StandardMessage standardMessage = null;
+ StandardMessageManager standardManager = StandardMessageManager.getInstance();
+ StandardReader reader = null;
+ InterfaceMapper mapper = standardManager.getMapper();
+ AdapterGroupVO vo = AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName());
+ String messageType = vo.getMessageType();
+ String messageEncode = vo.getMessageEncode();
+ standardMessage = standardManager.getStandardMessage();
+ reader = standardManager.getReader(messageType);
+ reader.parse(standardMessage, serviced);
+ // 표준전문 파싱 후 어댑터의 charset을 설정한다.
+ standardMessage.setBizDataCharset(messageEncode);
+ String respRsltDvsnCode = mapper.getResponseType(standardMessage);
+
+ // 정상응답인지 확인 : RSPNS_RSLT_DVSN_CD = N
+// String respRsltDvsnCode = resExtMessage.getResponseType();
+ String uuid = "";
+ if (STDMessageKeys.RESPONSE_TYPE_CODE_N.contentEquals(respRsltDvsnCode)) {
+ SessionVO sessionVo = SessionManager.getInstance().getLogin(bundle.getUserId());
+ if (sessionVo == null) {
+ logger.warn("HttpAdapterServiceChannel] LOGOUT Login Session Not found userId =" + bundle.getUserId());
+ } else {
+ uuid = sessionVo.getUuid();
+ ChannelSessionFacade.getInstance().logout(sessionVo.getLoginUserId(), sessionVo.getUuid(), false, LogoutType.Logout);
+ }
+ } else {
+ logger.warn("HttpAdapterServiceChannel] LOGOUT Failed RSPNS_RSLT_DVSN_CD =" + respRsltDvsnCode);
+ }
+
+ SessionHistoryLogger.getInstance().log(
+ new SessionHistoryDTO(new String(bundle.getRequestBytes(), bundle.getEncode()), SessionHistoryVO.HISTORYDSTCD_LOGOUT, respRsltDvsnCode, uuid, null, true));
+
+ return serviced;
+ }
+
+}
+
+class ChannelServiceDataBundle {
+
+ private Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ private String adptGrpName;
+ private String adptName;
+
+ private int traceLevel = 0;
+
+ private String responseType;
+ private String urlDecodeYn;
+ private String encode;
+ private String requestBodyYn;
+ private String parameterName;
+ private String removeLength;
+ private String addData;
+
+ private byte[] requestBytes;
+ private int removeLen;
+
+ /** lazy setting **/
+ private String guid;
+ private String userId;
+
+ private String apiPath;
+ private String extUri;
+ private String standardApiPath;
+
+ public ChannelServiceDataBundle(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ this.adptGrpName = adptGrpName;
+ this.adptName = adptName;
+
+ AdapterVO adptVO = AdapterManager.getInstance().getAdapterVO(adptGrpName, adptName);
+ if (adptVO == null) {
+ throw new ServletException("Adapter not Found adptName=" + adptName);
+ }
+
+ Properties httpProp = AdapterPropManager.getInstance().getProperties(adptVO.getPropGroupName());
+
+ this.responseType = httpProp.getProperty(HttpAdapterServiceKey.RESPONSE_TYPE, "SYNC");
+ this.urlDecodeYn = httpProp.getProperty(HttpAdapterServiceKey.URL_DECODE_YN, "N");
+ this.encode = httpProp.getProperty(HttpAdapterServiceKey.ENCODE, "MS949");
+// this.requestBodyYn = httpProp.getProperty(HttpAdapterServiceKey.REQUEST_BODY_YN, "N");
+ this.requestBodyYn ="Y";
+ this.parameterName = httpProp.getProperty(HttpAdapterServiceKey.PARAMETER_NAME, HttpAdapterServiceKey.PARAMETER_MESSAGE);
+ this.removeLength = httpProp.getProperty(HttpAdapterServiceKey.REMOVE_LENGTH, "0");
+ this.addData = httpProp.getProperty(HttpAdapterServiceKey.ADD_DATA, "");
+ String traceLevelTemp = httpProp.getProperty(HttpAdapterServiceKey.TRACE_LEVEL, "0");
+ this.apiPath = httpProp.getProperty(HttpAdapterServiceKey.API_PATH, "");
+
+ if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)
+ || StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) {
+ // /api/v1/public/getUserInfo.svc
+ String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath());
+ this.extUri = extUrl;
+ } else {
+ this.extUri = getExtUri(request);
+ }
+
+ standardApiPath = extUri.replaceAll(apiPath, "");
+ if (!standardApiPath.startsWith("/")) {
+ standardApiPath = standardApiPath + "/";
+ }
+
+ try {
+ traceLevel = Integer.parseInt(traceLevelTemp);
+ } catch (Exception e) {
+ traceLevel = 0;
+ }
+ this.removeLen = 0;
+ try {
+ removeLen = Integer.parseInt(removeLength);
+ } catch (Exception e) {
+ removeLen = 0;
+ }
+
+ if ("Y".equals(requestBodyYn)) {
+ this.requestBytes = requestBytesSetting(request);
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName, "RECV " + "[" + new String(requestBytes, encode) + "]" + CommonLib.getDumpMessage(requestBytes));
+ }
+ } else {
+ String paramValue = request.getParameter(parameterName);
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName, "RECV " + "[" + paramValue + "]" + ((paramValue == null) ? "" : CommonLib.getDumpMessage(paramValue.getBytes())));
+ }
+ this.requestBytes = requestBytesFromParameterValue(paramValue, urlDecodeYn, encode);
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceChannel] RECV (" + adptGrpName + ") = [" + paramValue + "]");
+ logger.debug("HttpAdapterServiceChannel] RECV (" + adptGrpName + ") = " + ((paramValue == null) ? "" : CommonLib.getDumpMessage(paramValue.getBytes())));
+ }
+ }
+
+ if (removeLen > 0) {
+ byte[] cuttedBytes = new byte[requestBytes.length - removeLen];
+ System.arraycopy(requestBytes, removeLen, cuttedBytes, 0, cuttedBytes.length);
+ this.requestBytes = cuttedBytes;
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceChannel] RECV after remove (" + adptGrpName + ") = [" + new String(requestBytes, encode) + "]");
+ logger.debug("HttpAdapterServiceChannel] RECV after remove (" + adptGrpName + ") = " + CommonLib.getDumpMessage(requestBytes));
+ }
+ }
+
+ }
+
+ private byte[] requestBytesSetting(HttpServletRequest request) throws IOException {
+
+ byte[] result = null;
+
+ ServletInputStream sis = request.getInputStream();
+ ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true);
+ int i = 0;
+ byte[] cbuf = new byte[1024];
+ while ((i = sis.read(cbuf, 0, 1024)) != -1) {
+ if (i == 1024) {
+ bb.put(cbuf);
+ } else {
+ byte[] tail = new byte[i];
+ System.arraycopy(cbuf, 0, tail, 0, i);
+ bb.put(tail);
+ }
+ }
+ result = new byte[bb.position()];
+ bb.position(0);
+ bb.get(result);
+
+ return result;
+ }
+
+ private byte[] requestBytesFromParameterValue(String paramValue, String urlDecodeYn, String encode) throws ServletException, UnsupportedEncodingException {
+
+ if (paramValue == null)
+ throw new ServletException("RECEAIAHA002");
+
+ if ("Y".equals(urlDecodeYn)) {
+ paramValue = URLDecoder.decode(paramValue, encode);
+ }
+
+ return paramValue.getBytes(encode);
+ }
+
+ public String getAdptGrpName() {
+ return adptGrpName;
+ }
+
+ public String getAdptName() {
+ return adptName;
+ }
+
+ public int getTraceLevel() {
+ return traceLevel;
+ }
+
+ public String getResponseType() {
+ return responseType;
+ }
+
+ public String getUrlDecodeYn() {
+ return urlDecodeYn;
+ }
+
+ public String getEncode() {
+ return encode;
+ }
+
+ public String getRequestBodyYn() {
+ return requestBodyYn;
+ }
+
+ public String getParameterName() {
+ return parameterName;
+ }
+
+ public String getRemoveLength() {
+ return removeLength;
+ }
+
+ public String getAddData() {
+ return addData;
+ }
+
+ public byte[] getRequestBytes() {
+ return requestBytes;
+ }
+
+ public int getRemoveLen() {
+ return removeLen;
+ }
+
+ public String getGuid() {
+ return guid;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setGuid(String guid) {
+ this.guid = guid;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getApiPath() {
+ return apiPath;
+ }
+
+ public void setApiPath(String apiPath) {
+ this.apiPath = apiPath;
+ }
+
+ public String getExtUri() {
+ return extUri;
+ }
+
+ public void setExtUri(String extUri) {
+ this.extUri = extUri;
+ }
+
+ public String getStandardApiPath() {
+ return standardApiPath;
+ }
+
+ public void setStandardApiPath(String standardApiPath) {
+ this.standardApiPath = standardApiPath;
+ }
+ private String getExtUri(HttpServletRequest request) {
+ String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), "");
+ String uri = getExtUri(orgUri, 3);
+ if (uri != null && uri.trim().length() > 0) {
+ return "/" + uri;
+ } else {
+ return "";
+ }
+ }
+
+ private static String getExtUri(String url, int length) {
+ String[] urls = url.split("/");
+ List newUrls = new ArrayList<>();
+ Collections.addAll(newUrls, urls);
+ return StringUtils.join(newUrls.subList(length, urls.length).toArray(), "/");
+ }
+
+}
+
+class ChannelResponseDivider {
+
+ private Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ private ChannelServiceDataBundle bundle;
+
+ private boolean loginTransaction = false;
+ private boolean logoutTransaction = false;
+ private boolean skipTransaction = false;
+
+ public ChannelResponseDivider(ChannelServiceDataBundle bundle) {
+ this.bundle = bundle;
+ }
+
+ public enum ResponseType_Phase1 {
+ HttpPoll, DupLoginCheck, LoginValidation, LoginUuidValidation, Skip
+ }
+
+ public enum ResponseType_Phase2 {
+ Async, LoginTransaction, LogoutTransaction, Skip
+ }
+
+ public ResponseType_Phase1 dividePhase1() throws Exception {
+
+ if(bundle.getRequestBytes().length == 58) {
+ String message = new String(bundle.getRequestBytes(), bundle.getEncode());
+ if (message.startsWith("POLLREQ@@")) {
+ return ResponseType_Phase1.HttpPoll;
+ }
+ }
+
+ AdapterGroupVO agvo = AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName());
+ String LOGINSERVICEID = "";
+ String LOGOUTSERVICEID = "";
+ String SKIP_SERVICEID = "";
+
+ String userId = "";
+ String uuid = "";
+
+ if (MessageType.JSON.equals(agvo.getMessageType())) {
+
+ PropManager pManager = PropManager.getInstance();
+ Properties prop = pManager.getProperties(PropertyLoginKeys.LOGIN);
+ LOGINSERVICEID = prop.getProperty(PropertyLoginKeys.LOGIN_SERVICE_ID);
+ LOGOUTSERVICEID = prop.getProperty(PropertyLoginKeys.LOGOUT_SERVICE_ID);
+ SKIP_SERVICEID = prop.getProperty(PropertyLoginKeys.SKIP_SERVICE_ID, "");// 비밀번호 변경 등등
+
+ String requestStr = new String(bundle.getRequestBytes(), bundle.getEncode());
+ logger.debug("HttpAdapterServiceChannel] LOGIN_SERVICE_ID = " + LOGINSERVICEID);
+ logger.debug("HttpAdapterServiceChannel] LOGOUT_SERVICE_ID = " + LOGOUTSERVICEID);
+ logger.debug("HttpAdapterServiceChannel] SKIP_SERVICE_ID = " + SKIP_SERVICEID);
+ logger.debug("HttpAdapterServiceChannel] Request-JSON = " + requestStr);
+
+ /*
+ * 모든 거래가 서비스ID, 사용자ID를 가져오기 위해 표준전문 파싱을 하는것은 낭비라고 판단하여 JSON에서 직접 가져오도록 변경
+ */
+ // 표준전문 파싱으로 변경.
+ StandardMessage standardMessage = null;
+ StandardMessageManager standardManager = StandardMessageManager.getInstance();
+ StandardReader reader = null;
+ InterfaceMapper mapper = standardManager.getMapper();
+ AdapterGroupVO vo = AdapterManager.getInstance().getAdapterGroupVO(bundle.getAdptGrpName());
+ String messageType = vo.getMessageType();
+ String messageEncode = vo.getMessageEncode();
+ standardMessage = standardManager.getStandardMessage();
+ reader = standardManager.getReader(messageType);
+ reader.parse(standardMessage, bundle.getRequestBytes());
+ // 표준전문 파싱 후 어댑터의 charset을 설정한다.
+ standardMessage.setBizDataCharset(messageEncode);
+
+ String standardApiPath = bundle.getStandardApiPath();
+
+ String serviceId = "";
+
+ if (standardApiPath.length() > 1) {
+ serviceId = standardApiPath;
+ } else {
+ serviceId = mapper.getServiceId(standardMessage);
+ }
+
+ uuid = mapper.getSessionId(standardMessage);
+ userId = mapper.getUserId(standardMessage);
+ bundle.setGuid(mapper.getGuid(standardMessage));
+ bundle.setUserId(userId);
+
+ if (LOGINSERVICEID.equals(serviceId)) {
+
+ loginTransaction = true;
+// 2023.12.11 KAKAOBANK-CARD 중복 로그인 체크 안함
+// SessionVO sessionVo = SessionManager.getInstance().getLogin(userId);
+// if (sessionVo != null) {
+// String LOGIN_DUP_CHECK_YN = prop.getProperty(PropertyLoginKeys.LOGIN_DUP_CHECK_YN, "Y");
+// if ("Y".equals(LOGIN_DUP_CHECK_YN)) {
+// return ResponseType_Phase1.DupLoginCheck;
+// } else {
+// logger.error("HttpAdapterServiceChannel] LOGIN-DUPLICATED loginUserId= " + userId + " skip");
+// }
+// }
+
+ }
+
+ if (LOGOUTSERVICEID.equals(serviceId)) {
+ logoutTransaction = true;
+ }
+
+ //통합로그 비로그인 거래 처리(2022-08-12) AA요구사항
+ //대내 MCI 및 전사공통 선처리에서 사용자 ID가 가상 사용자( 'VRxxxxxxx') 인 경우 로그인 여부등 유효성 검증 SKIP(대내MCI/전사공통)
+ if (SKIP_SERVICEID.indexOf(serviceId) >= 0 /* || userId.startsWith("VR")*/) {
+ skipTransaction = true;
+ }
+ logger.debug("HttpAdapterServiceChannel] loginTransaction = " + loginTransaction);
+ logger.debug("HttpAdapterServiceChannel] logoutTransaction = " + logoutTransaction);
+ logger.debug("HttpAdapterServiceChannel] skipTransaction = " + skipTransaction);
+
+ }
+
+ if (!(loginTransaction || skipTransaction)) {
+
+ // FIXME : 로그인 여부를 체크할 것인가 ?
+ PropManager pManager = PropManager.getInstance();
+ Properties prop = pManager.getProperties(PropertyLoginKeys.LOGIN);
+ String LOGIN_VALIDATION_YN = prop.getProperty(PropertyLoginKeys.LOGIN_VALIDATION_YN, "N");// 로그인 validation
+ String UUID_VALIDATION_YN = prop.getProperty(PropertyLoginKeys.UUID_VALIDATION_YN, "N");// uuid validation
+
+ if ("Y".equals(LOGIN_VALIDATION_YN)) {
+ SessionVO sessionVo = SessionManager.getInstance().getLogin(userId);
+ if(sessionVo == null) {
+ return ResponseType_Phase1.LoginValidation;
+ }
+ }else if ("Y".equals(UUID_VALIDATION_YN)) {
+ //UUID validation 추가
+ SessionVO sessionVo = SessionManager.getInstance().getHttpLogin(uuid);
+ if (sessionVo == null || !userId.equals(sessionVo.getLoginUserId())) {
+ return ResponseType_Phase1.LoginUuidValidation;
+ }
+ } else {
+ logger.error("HttpAdapterServiceChannel] NOTLOGIN OR EXPIRED SESSION userId[" + userId + "] - continue.");
+ }
+
+ }
+
+ return ResponseType_Phase1.Skip;
+ }
+
+ public ResponseType_Phase2 dividePhase2() {
+
+ if (HttpAdapterServiceKey.RESPONSE_TYPE_ASYNC.equals(bundle.getResponseType())) {
+
+ return ResponseType_Phase2.Async;
+
+ } else {
+
+ if (bundle.getRequestBytes() != null) {
+ if (loginTransaction) {
+
+ return ResponseType_Phase2.LoginTransaction;
+
+ } else if (logoutTransaction) {
+
+ return ResponseType_Phase2.LogoutTransaction;
+ }
+ }
+
+ }
+
+ return ResponseType_Phase2.Skip;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServicePass.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServicePass.java
new file mode 100644
index 0000000..b6d1fb1
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServicePass.java
@@ -0,0 +1,153 @@
+package com.eactive.eai.adapter.http.dynamic.impl;
+
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+import org.apache.commons.httpclient.methods.PostMethod;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.Properties;
+
+public class HttpAdapterServicePass extends HttpAdapterServiceSupport {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ private static final int BUFFER_SIZE = 1024;
+ private static final String FROM = "From";
+ private static final String FILE_TYPE = "FileType";
+ private static final String FILE_NAME = "FileName";
+ private static final String USER_AGENT = "User-Agent";
+ private static final String USER_HEADER = "User-Header";
+ private static final String CONTENT_TYPE = "Content-Type";
+
+ public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) {
+
+ PropManager manager = PropManager.getInstance();
+
+ Properties prop = manager.getProperties("BYPASS_REU");
+ String url = prop.getProperty("URL", "http://192.168.12.224:8068/ForexWeb/ForexServiceServlet");
+ int connectionTimeout = 30000;
+ int timeout = 30000;
+
+ if (prop != null) {
+ try {
+ connectionTimeout = Integer.parseInt(prop.getProperty("CONNECTION_TIMEOUT", "30000"));
+ } catch (NumberFormatException e) {
+ connectionTimeout = 30000;
+ }
+ try {
+ timeout = Integer.parseInt(prop.getProperty("TIMEOUT", "30000"));
+ } catch (NumberFormatException e) {
+ timeout = 30000;
+ }
+ }
+
+ String from = request.getHeader(FROM);
+ String fileType = request.getHeader(FILE_TYPE);
+ String fileName = request.getHeader(FILE_NAME);
+ String userAgent = request.getHeader(USER_AGENT);// "Forex HTTP Connector"
+ String userHeader = request.getHeader(USER_HEADER);
+ String contentType = request.getHeader(CONTENT_TYPE);// "text/plain"
+ ByteArrayOutputStream outStream = null;
+ DataInputStream inStream = null;
+ byte[] data = null;
+
+ try {
+ int c = -1;
+ byte[] bytes = new byte[BUFFER_SIZE];
+ inStream = new DataInputStream(request.getInputStream());
+ outStream = new ByteArrayOutputStream();
+
+ while ((c = inStream.read(bytes, 0, bytes.length)) != -1) {
+ outStream.write(bytes, 0, c);
+ }
+ data = new byte[outStream.toByteArray().length];
+ data = outStream.toByteArray();
+ } catch (IOException e1) {
+ if (logger.isError())
+ logger.error("HttpPassAdapter] IOException ", e1);
+ } finally {
+ try {
+ if (inStream != null) {
+ inStream.close();
+ }
+ } catch (Exception e) {
+ logger.warn(e);
+ }
+ try {
+ if (outStream != null) {
+ outStream.close();
+ }
+ } catch (Exception e) {
+ logger.warn(e);
+ }
+ }
+
+ HttpClient httpClient = new HttpClient();
+
+ httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
+ httpClient.getHttpConnectionManager().getParams().setSoTimeout(timeout);
+
+ PostMethod post = new PostMethod(url);
+
+ post.setRequestHeader(FROM, from);
+ post.setRequestHeader(FILE_TYPE, fileType);
+ post.setRequestHeader(FILE_NAME, fileName);
+ post.setRequestHeader(USER_AGENT, userAgent);
+ post.setRequestHeader(USER_HEADER, userHeader);
+ post.setRequestHeader(CONTENT_TYPE, contentType);
+
+// post.setRequestBody(new ByteArrayInputStream(data));
+// if (data != null) {
+// post.setRequestContentLength(data.length);
+// }
+ ByteArrayRequestEntity entity = new ByteArrayRequestEntity(data);
+ post.setRequestEntity(entity);
+
+ int status = -1;
+
+ try {
+ status = httpClient.executeMethod(post);
+ } catch (SocketTimeoutException ste) {
+ if (logger.isError()) {
+ logger.error("HttpPassAdapter] SocketTimeoutException : " + ste.toString(), ste);
+ }
+ } catch (ConnectException ce) {
+ if (logger.isError()) {
+ logger.error("HttpPassAdapter] Connection Exception : " + ce.toString(), ce);
+ }
+ } catch (Exception e) {
+ if (logger.isError()) {
+ logger.error("HttpPassAdapter] Exception : " + e.toString(), e);
+ }
+ } finally {
+ post.releaseConnection();
+ if (status != HttpStatus.SC_OK) {
+ logger.error("Http error status=" + status);
+ }
+ }
+ response.setContentType("text/html");
+ PrintWriter writer = null;
+ try {
+ writer = response.getWriter();
+ writer.print(post.getResponseBodyAsString());
+ } catch (IOException e) {
+ if (logger.isError()) {
+ logger.error("HttpPassAdapter] IOException : " + e.toString(), e);
+ }
+ } finally {
+ try {
+ if (writer != null) {
+ writer.close();
+ }
+ } catch (Exception e) {
+ logger.warn(e);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceRest.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceRest.java
new file mode 100644
index 0000000..dfa8bd8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceRest.java
@@ -0,0 +1,783 @@
+package com.eactive.eai.adapter.http.dynamic.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URLDecoder;
+import java.util.*;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.common.TransactionContextKeys;
+import com.eactive.eai.common.util.HttpAdapterExtraLogUtil;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.apache.mina.common.ByteBuffer;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.util.AntPathMatcher;
+
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpMethodType;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.message.MessageType;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.MessageUtil;
+import com.eactive.eai.env.ElinkConfig;
+import com.eactive.eai.inbound.action.ActionFactory;
+import com.eactive.eai.inbound.action.RequestAction;
+import com.eactive.eai.inbound.processor.Processor;
+import com.eactive.eai.message.StandardMessageUtil;
+
+public class HttpAdapterServiceRest extends HttpAdapterServiceSupport {
+ public static final String HEADER_GROUP = "HEADER_GROUP";
+ // HEADER_GROUP JSON에 추가할 항목 정의, 없으면 전체 header 추가
+ public static final String HEADER_KEYS = "HEADER_KEYS";
+ public static final String HTTP_STATUS = "HTTP_STATUS";
+ public static final String PROPERTIES_NAME_HTTP_REQUEST_METHOD = "httpRequestMethod";
+
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ private String logPrefix = "HttpAdapterServiceRest] ";
+
+ private static final String JSON_CONTENT_TYPE = "application/json";
+ private static final String JSON_FIELD_NAME = "json-body";
+ private static final String FILE_GROUP_NAME = "image-file";
+ private static final String UPLOAD_ROOT_PATH = "UPLOAD_ROOT_PATH";
+
+ private String readMultipartBody(HttpServletRequest request) throws Exception {
+ String jsonString = null;
+ // Create a factory for disk-based file items
+ DiskFileItemFactory factory = new DiskFileItemFactory();
+
+ // Set the maximum size of the files to be uploaded
+ factory.setSizeThreshold(1024 * 1024);
+
+ // Set the temporary directory to store uploaded files
+ File tempDir = (File) request.getSession().getServletContext().getAttribute("javax.servlet.context.tempdir");
+ factory.setRepository(tempDir);
+
+ ServletFileUpload upload = new ServletFileUpload(factory);
+ Map fileMap = new HashMap<>();
+
+ InputStream fin = null;
+ try {
+ byte[] buffer = new byte[1024];
+ int read = 0;
+
+ List items = upload.parseRequest(request);
+ for (FileItem item : items) {
+ if (!item.isFormField()) {
+ // file
+ String fieldName = item.getFieldName();
+ String fileName = item.getName();
+ fin = item.getInputStream();
+ ByteArrayOutputStream fo = new ByteArrayOutputStream();
+ while ((read = fin.read(buffer)) > 0) {
+ fo.write(buffer, 0, read);
+ }
+ int fileSize = fo.size();
+ byte[] fileBytes = fo.toByteArray();
+ String fileContents = new String(fileBytes);
+ if (logger.isInfo()) {
+ logger.info("[FILE]-------------------------------------------------->");
+ logger.info("Field name = " + fieldName);
+ logger.info("File name = " + fileName + " contents length = " + fileSize);
+ logger.info("File Contents [" + fileContents + "]");
+ logger.info("[FILE]<--------------------------------------------------");
+ }
+ fileMap.put(fileName, fileContents);
+ fin.close();
+ } else {
+ // regular form field
+ String fieldName = item.getFieldName();
+ String fieldValue = item.getString();
+ if (logger.isInfo()) {
+ logger.info("[FIELD] " + fieldName + " [" + fieldValue + "]");
+ }
+ if (JSON_CONTENT_TYPE.equalsIgnoreCase(item.getContentType())
+ || JSON_FIELD_NAME.equals(fieldName)) {
+ jsonString = fieldValue;
+ }
+ }
+ }
+
+ if (logger.isInfo()) {
+ logger.info("Json body [" + jsonString + "]");
+ }
+
+ if (jsonString == null) {
+ jsonString = "{}";
+ } else {
+ // parsing json & add file contents
+ JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonString);
+ if (jsonObject == null) {
+ jsonString = "{}";
+ } else {
+ JSONObject fileGroup = new JSONObject();
+
+ for (Map.Entry entry : fileMap.entrySet()) {
+ fileGroup.put("fileName", entry.getKey());
+ fileGroup.put("fileContents", entry.getValue());
+ }
+ jsonObject.put(FILE_GROUP_NAME, fileGroup);
+ jsonString = jsonObject.toJSONString();
+ }
+ }
+
+ if (logger.isInfo()) {
+ logger.info("Json with file [" + jsonString + "]");
+ }
+ return jsonString;
+ } catch (Exception e) {
+ logger.error("Read multipart body error.", e);
+ throw e;
+ } finally {
+ if (fin != null) {
+ try {
+ fin.close();
+ } catch (Exception ex) {
+ // empty
+ }
+ }
+ }
+ }
+
+ private String checkRootPath(String path) {
+ if (StringUtils.isEmpty(path)) {
+ logger.info("upload dir not set(UPLOAD_ROOT_PATH), use system temp " + path);
+ return System.getProperty("java.io.tmpdir");
+ }
+ File file = new File(path);
+ if (!file.exists()) {
+ file.mkdirs();
+ }
+ return path;
+ }
+
+ private String uploadMultipartBody(HttpServletRequest request, String uploadRootPath) throws Exception {
+ String jsonString = null;
+ // Create a factory for disk-based file items
+ DiskFileItemFactory factory = new DiskFileItemFactory();
+
+ // Set the maximum size of the files to be uploaded
+ factory.setSizeThreshold(1024 * 1024);
+
+ // Set the temporary directory to store uploaded files
+ File tempDir = (File) request.getSession().getServletContext().getAttribute("javax.servlet.context.tempdir");
+ factory.setRepository(tempDir);
+
+ ServletFileUpload upload = new ServletFileUpload(factory);
+ try {
+ // if not exist, create folders
+ String uploadDir = checkRootPath(uploadRootPath);
+ List items = upload.parseRequest(request);
+ for (FileItem item : items) {
+ if (!item.isFormField()) {
+ // file
+ String fieldName = item.getFieldName();
+ String fileName = item.getName();
+ String uploadFilePath = uploadDir + File.separator + fileName;
+ File uploadFile = new File(uploadFilePath);
+ item.write(uploadFile);
+
+ if (logger.isInfo()) {
+ logger.info("[FILE]-------------------------------------------------->");
+ logger.info("Field name = " + fieldName);
+ logger.info("File name = " + fileName + " path = " + uploadFile.getAbsolutePath());
+ logger.info("[FILE]<--------------------------------------------------");
+ }
+ } else {
+ // regular form field
+ String fieldName = item.getFieldName();
+ String fieldValue = item.getString();
+ if (logger.isInfo()) {
+ logger.info("[FIELD] " + fieldName + " [" + fieldValue + "]");
+ }
+ if (JSON_CONTENT_TYPE.equalsIgnoreCase(item.getContentType())
+ || JSON_FIELD_NAME.equals(fieldName)) {
+ jsonString = fieldValue;
+ }
+ }
+ }
+
+ if (logger.isInfo()) {
+ logger.info("Json body [" + jsonString + "]");
+ }
+ return jsonString;
+ } catch (Exception e) {
+ logger.error("Read multipart body error.", e);
+ throw e;
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) {
+ int traceLevel = 0;
+
+ AdapterVO adptVO = null;
+ AdapterPropManager manager = null;
+
+ Properties httpProp = null;
+ String responseType = null;
+ String urlDecodeYn = null;
+ String encode = null;
+
+ String traceLevelTemp = null;
+ String relayRequestHeaderKeys = null;
+ String headerGroupName = null;
+
+ boolean isParameterType = false;
+ String message = null;
+
+ StopWatch stopWatch = null;
+ Properties prop = null;
+ String paramValue = null;
+ String adptMsgType = null;
+ String errorResponseFormat = null;
+ String uploadRootPath = null;
+ try {
+ AdapterManager adapterManager = AdapterManager.getInstance();
+ adptVO = adapterManager.getAdapterVO(adptGrpName, adptName);
+ if (adptVO == null) {
+ throw new Exception("Adapter not found error");
+ }
+
+ manager = AdapterPropManager.getInstance();
+
+ httpProp = manager.getProperties(adptVO.getPropGroupName());
+ responseType = httpProp.getProperty(RESPONSE_TYPE, "SYNC");
+ urlDecodeYn = httpProp.getProperty(URL_DECODE_YN, "N");
+ // encode = httpProp.getProperty(ENCODE, "UTF-8");
+ encode = StringUtils.defaultIfBlank(adapterManager.getAdapterGroupVO(adptGrpName).getMessageEncode(),
+ "UTF-8");
+ traceLevelTemp = httpProp.getProperty(TRACE_LEVEL, "0");
+ relayRequestHeaderKeys = httpProp.getProperty(HEADER_KEYS);
+ headerGroupName = httpProp.getProperty(HEADER_GROUP);
+ errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT);
+ uploadRootPath = httpProp.getProperty(UPLOAD_ROOT_PATH);
+ prop = new Properties();
+ prop.put(INBOUND_METHOD, request.getMethod());
+ prop.put(INBOUND_URI, request.getRequestURI());
+ prop.put(INBOUND_HEADER, getHeaders(request));
+ if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)
+ || StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) {
+ // /api/v1/public/getUserInfo.svc
+ String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath());
+ prop.put(INBOUND_EXTURI, extUrl);
+ } else {
+ prop.put(INBOUND_EXTURI, getExtUri(request));
+ }
+ prop.put(Processor.REQUEST_ACTION, adptVO.getAdapterGroupVO().getRefClass());
+ prop.put(API_PATH, httpProp.getProperty(API_PATH, ""));
+ prop.put(PRE_FILTERS, httpProp.getProperty(PRE_FILTERS, ""));
+ prop.put(POST_FILTERS, httpProp.getProperty(POST_FILTERS, ""));
+ prop.put(PROPERTIES_NAME_HTTP_REQUEST_METHOD, request.getMethod());
+ prop.put(ALLOW_IP, httpProp.getProperty(ALLOW_IP, ""));
+
+ isParameterType = false;
+ try {
+ traceLevel = Integer.parseInt(traceLevelTemp);
+ } catch (Exception e) {
+ traceLevel = 0;
+ }
+
+ stopWatch = new StopWatch();
+ stopWatch.start();
+
+ logger.debug("시작 >> encode = [" + encode + "]");
+
+ switch (HttpMethodType.getValue(request.getMethod())) {
+ case GET:
+ case DELETE:
+ isParameterType = true;
+ break;
+ case POST:
+ case PUT:
+ if (StringUtils.contains(request.getContentType(), "application/x-www-form-urlencoded")) {
+ isParameterType = true;
+ } else {
+ isParameterType = false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (isParameterType) {
+ paramValue = request.getQueryString();
+ if (paramValue == null)
+ paramValue = "";
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName,
+ "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(paramValue));
+ }
+
+ // json으로 변환
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ Map paramMap = assignParameterMap(request, adptGrpName, adptName, null, prop);
+ int i = 0;
+ for (Map.Entry entry : paramMap.entrySet()) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append("\"").append(entry.getKey()).append("\":");
+ String[] values = entry.getValue();
+ if (values.length > 1) {
+ // ["111", "222"]
+ sb.append("[");
+ for (int j = 0; j < values.length; j++) {
+ if (j > 0) {
+ sb.append(",");
+ }
+ sb.append("\"").append(JSONValue.escape(values[j])).append("\"");
+ }
+ sb.append("]");
+ } else {
+ sb.append("\"").append(JSONValue.escape(values[0])).append("\"");
+ }
+
+ i++;
+ }
+
+ sb.append("}");
+
+ paramValue = sb.toString();
+ } else {
+ if (ServletFileUpload.isMultipartContent(request)) {
+ // TODO : 아래의 로직은 업무에 맞게 수정이 필요함.
+ // 불필요할 경우 제거
+// if(StringUtils.isEmpty(uploadRootPath)) {
+// uploadRootPath = System.getProperty("java.io.tmpdir");
+// }
+
+ // 임시로직 : UPLOAD_ROOT_PATH 가 없는 경우에는 JSON에 추가
+ if (StringUtils.isEmpty(uploadRootPath)) {
+ paramValue = readMultipartBody(request);
+ } else {
+ paramValue = uploadMultipartBody(request, uploadRootPath);
+ }
+ // TEST : 테스트용 임시코드
+// response.setCharacterEncoding(encode);
+// response.getWriter().print(paramValue);
+// return;
+ } else {
+ ServletInputStream sis = request.getInputStream();
+ ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true);
+ int i = 0;
+ byte[] cbuf = new byte[1024];
+ while ((i = sis.read(cbuf, 0, 1024)) != -1) {
+ if (i == 1024) {
+ bb.put(cbuf);
+ } else {
+ byte[] tail = new byte[i];
+ System.arraycopy(cbuf, 0, tail, 0, i);
+ bb.put(tail);
+ }
+ }
+ byte[] data = new byte[bb.position()];
+ bb.position(0);
+ bb.get(data);
+ paramValue = new String(data, encode);
+
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName,
+ "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(paramValue));
+ }
+ }
+ }
+
+ if (paramValue == null) { // parameter가 없는 경우때문에 처리
+ paramValue = "";
+ }
+
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n"
+ + CommonLib.getDumpMessage(paramValue));
+ }
+
+ if ("Y".equals(urlDecodeYn) && isParameterType) {
+ message = URLDecoder.decode(paramValue);
+ } else {
+ message = paramValue;
+ }
+
+ if (logger.isDebug()) {
+ String[] msgArgs = new String[2];
+ msgArgs[0] = adptGrpName;
+ msgArgs[1] = message;
+ String resMsg = ExceptionUtil.make("RICEAIAHA005", msgArgs);
+ logger.debug(logPrefix + resMsg);
+ }
+
+ adptMsgType = adptVO.getAdapterGroupVO().getMessageType();
+ if (StringUtils.equals(adptMsgType, MessageType.JSON)) {
+ response.setContentType(JSON_CONTENT_TYPE+"; charset="+encode);
+ }
+
+ // HEADER_GROUP 셋팅
+ if (MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName)
+ && StringUtils.isNotBlank(relayRequestHeaderKeys)) {
+ JSONObject jsonMessage = (JSONObject) JSONValue.parse(message);
+ JSONObject headerJson = new JSONObject();
+ if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) {
+ for (Enumeration e = request.getHeaderNames(); e.hasMoreElements();) {
+ String key = e.nextElement();
+ headerJson.put(key, request.getHeader(key));
+ }
+ } else {
+ String[] relayKeyArr = org.springframework.util.StringUtils
+ .tokenizeToStringArray(relayRequestHeaderKeys, ",");
+
+ for (String key : relayKeyArr) {
+ String headerValue = request.getHeader(key);
+ if (StringUtils.isNotBlank(headerValue)) {
+ headerJson.put(key, headerValue);
+ }
+ }
+ }
+
+ if (headerJson.size() > 0) {
+ jsonMessage.put(headerGroupName, headerJson);
+ message = jsonMessage.toJSONString();
+ }
+ }
+
+ if (message == null) {
+ message = "";
+ }
+
+ // 로컬 서비스 호출 ,encoding 처리 추가
+ String result = (String) service(adptGrpName, adptName, message, prop, request, response);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceRest] result " + encode + " (" + adptGrpName + ") = [" + result + "]");
+ }
+
+ stopWatch.stop();
+
+ String responseData = "";
+ if (RESPONSE_TYPE_ASYNC.equals(responseType)) {
+ if (stopWatch.getTime() > slowTranTime && (logger.isInfo())) {
+ logger.info("HttpAdapterServiceRest] dummy response time = " + stopWatch.toString() + ", message = "
+ + message);
+
+ }
+ if (result == null) {
+ responseData = ElinkConfig.getAsyncDummyDataForAdapterGroup(adptGrpName);
+ } else {
+ responseData = result;
+ }
+ response.setCharacterEncoding(encode);
+ response.getWriter().print(responseData);
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName,
+ "SEND " + "[" + responseData + "]" + CommonLib.getDumpMessage(responseData));
+ }
+ } else {
+ responseData = result;
+ logger.info("종료 >> encode = [" + encode + "]");
+
+ JSONObject dataObject = null;
+ if (MessageType.JSON.equals(adptMsgType)) {
+ dataObject = (JSONObject) JSONValue.parse(responseData);
+ }
+
+ // HEADER_GROUP 하위 필드를 response Header에 세팅한다.
+ HashMap header = new HashMap<>();
+ boolean redirect = assignHttpHeaders(header, dataObject, headerGroupName);
+
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceRest] response header field (" + adptGrpName + ") = ["
+ + header.toString() + "]");
+ }
+
+ if (redirect) {
+ response.setStatus(302);
+ logger.debug("HttpAdapterServiceRest] set response status_code: 302");
+ } else {
+ String httpStatus = header.get(HTTP_STATUS);
+ if (httpStatus != null && !"".equals(httpStatus))
+ response.setStatus(Integer.parseInt(httpStatus));
+ header.remove(HTTP_STATUS);
+ }
+
+ // response header 셋팅
+ for (Map.Entry entry : header.entrySet()) {
+ response.setHeader(entry.getKey(), entry.getValue());
+ }
+
+ if (dataObject != null) {
+ responseData = dataObject.toJSONString();
+ }
+
+ // UI와 통신시(UTF-8) 변환오류로 ENCODE 제거
+ response.setCharacterEncoding(encode);
+ response.getWriter().print(responseData);
+ if (logger.isDebug()) {
+ logger.debug("HttpAdapterServiceRest] SEND (" + adptGrpName + ") = [" + responseData + "]");
+ logger.debug("HttpAdapterServiceRest] SEND (" + adptGrpName + ") = "
+ + CommonLib.getDumpMessage(responseData));
+ }
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.txlog(adptGrpName + adptName,
+ "SEND " + "[" + responseData + "]" + CommonLib.getDumpMessage(responseData));
+ }
+ }
+ } catch (HttpStatusException e) {
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.warn("HttpAdapter] " + adptGrpName + "-" + adptName + ">>" + e.getMessage());
+ response.setStatus(e.getStatus());
+ try {
+ String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(),
+ e.getMessage(), errorResponseFormat);
+ response.getWriter().println(errorMsg);
+ } catch (Exception ex) {
+ // IGNORE
+ }
+ } catch (JwtAuthException e) {
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.error(logPrefix + adptGrpName + "-" + adptName + ">>" + e.getMessage(), e);
+ response.setStatus(HttpStatus.UNAUTHORIZED.value());
+ try {
+ String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(),
+ e.getMessage(), errorResponseFormat);
+ response.getWriter().println(errorMsg);
+ } catch (Exception ex) {
+ // IGNORE
+ }
+ } catch (Exception e) {
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.error(logPrefix + adptGrpName + "-" + adptName + ">>" + e.getMessage(), e);
+ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ try {
+ response.getWriter().println(e.getMessage());
+ String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
+ throw new Exception(errCode);
+ } catch (Exception ex) {
+ // IGNORE
+ logger.warn(logPrefix + adptGrpName + "-" + adptName + ">>" + e.getMessage(), e);
+ }
+ } finally {
+ String uuid = prop.getProperty(TransactionContextKeys.TRANSACTION_UUID);
+ String url = prop.getProperty(HttpClientAdapterServiceKey.INBOUND_EXTURI);
+ String method = prop.getProperty(HttpClientAdapterServiceKey.INBOUND_METHOD);
+ String adapterGroupName = prop.getProperty(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME);
+ String adapterName = prop.getProperty(HttpClientAdapterServiceKey.ADAPTER_NAME);
+ int httpStatusCode = response.getStatus();
+ HttpAdapterExtraLogUtil.insertHttpAdapterExtraLog(uuid, 400, adapterGroupName, adapterName, new HashMap<>(), url, method, httpStatusCode);
+ }
+ }
+
+ private Map assignParameterMap(HttpServletRequest request, String adptGrpName, String adptName,
+ Object requestBytes, Properties prop) {
+ // PathVariable 체크
+ if (StringUtils.equalsAnyIgnoreCase(request.getMethod(), HttpMethod.GET.name(), HttpMethod.DELETE.name())
+ && StringUtils.isBlank(request.getQueryString())) {
+ try {
+ String actionName = prop.getProperty(Processor.REQUEST_ACTION);
+ RequestAction action = ActionFactory.createAction(actionName);
+ action.setAdapterInfo(adptGrpName, adptName, prop);
+ String[] keys = action.perform(requestBytes);
+ String requestPath = keys[0];
+
+ // PathVariable 지원 추가
+ String ruledPath = StandardMessageUtil.getMatchedKey(requestPath, actionName);
+ if (!StringUtils.equals(requestPath, ruledPath) && StringUtils.contains(ruledPath, "{")) {
+ Map paramMap = new AntPathMatcher().extractUriTemplateVariables(ruledPath,
+ requestPath);
+ if (paramMap != null && paramMap.size() > 0) {
+ Map returnMap = new HashMap<>();
+ for (String key : paramMap.keySet()) {
+ if (StringUtils.equalsIgnoreCase(key, "method")) {
+ continue;
+ }
+ returnMap.put(key, new String[] { paramMap.get(key) });
+ }
+
+ return returnMap;
+ }
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+
+ return request.getParameterMap();
+ }
+
+ private void validateServiceAndAdapter(String adptGrpName, String adptName, byte[] requestBytes, Properties prop)
+ throws JwtAuthException {
+// try {
+// String actionName = prop.getProperty(Processor.REQUEST_ACTION);
+// RequestAction action = ActionFactory.createAction(actionName);
+// action.setAdapterInfo(adptGrpName, adptName, prop);
+// String[] keys = action.perform(requestBytes);
+// String apiId = keys[0];
+//
+// // PathVariable 지원 추가
+// apiId = StandardMessageUtil.getMatchedKey(apiId, actionName);
+// if (apiId == null) {
+// throw new Exception("apiId");
+// }
+//
+//// STDMessageManager stdheaderManager = STDMessageManager.getInstance();
+//// STDMessage stdmessage = stdheaderManager.getSTDMessage(apiId);
+//// if (stdmessage == null) {
+//// throw new Exception("stdMsg");
+//// }
+//
+// long msgRcvTm = System.currentTimeMillis();
+// AdapterManager adapterManager = AdapterManager.getInstance();
+// AdapterGroupVO adptGrpVO = adapterManager.getAdapterGroupVO(adptGrpName);
+// ProcessVO processVO = setProcessVO(apiId, adptGrpVO.getOsidInstiNo(), msgRcvTm, adptGrpName, adptName);
+// ExtMessage extMessage = ExtMessageConverter.getExtMessageForNonStandard(requestBytes, requestBytes, processVO);
+//
+// EAIMessageManager eaiMsgManager = EAIMessageManager.getInstance();
+//// String eaiSvcCd = stdmessage.getEAITranName() + stdmessage.getSTDHeader().getMesgDvcd();
+// String eaiSvcCd = extMessage.getEAIServiceCode();
+// if (eaiSvcCd == null) {
+// eaiSvcCd = extMessage.getInterfaceId() + extMessage.getSendRecv() + extMessage.getDirection();
+// }
+// EAIMessage eaiMsg = eaiMsgManager.getEAIMessage(eaiSvcCd);
+// logger.warn("adptGrpName=[" + adptGrpName + "],eaiSvcCd=[" + eaiSvcCd + "],eaiMsg=[" + eaiMsg
+// + "],getSngSysItfTp=[" + "]");
+// if (eaiMsg == null) {
+// throw new Exception("eaiMsg");
+// }
+//
+// if (!StringUtils.equals(eaiMsg.getSngSysItfTp(), adptGrpName)) {
+// throw new Exception("adapter");
+// }
+// } catch (Exception e) {
+// String msg = String.format("The resource does not exist or does not have permissions(%s): %s",
+// e.getMessage(), prop.get(INBOUND_EXTURI));
+// throw new JwtAuthException(JwtAuthFilter.ERROR_AUTHORIZATION_FAIL, msg);
+// }
+ }
+
+// private ProcessVO setProcessVO(String apiId, String osidInstiNo, long msgRcvTm, String adptGrpName,
+// String adptName) {
+// ProcessVO vo = new ProcessVO();
+// vo.setSelectedKey(apiId);
+// vo.setAdapterGroupName(adptGrpName);
+// vo.setAdapterName(adptName);
+// vo.setInAdapterOsidInstiNo(osidInstiNo);
+// vo.setErrTm(msgRcvTm);
+// return vo;
+// }
+
+ /**
+ * request header 를 hashmap으로 조립
+ *
+ * @param request
+ * @return
+ */
+ private Properties getHeaders(HttpServletRequest request) {
+ Properties prop = new Properties();
+
+ Enumeration headerNames = request.getHeaderNames();
+ while (headerNames.hasMoreElements()) {
+ String key = headerNames.nextElement();
+ String value = request.getHeader(key);
+ prop.setProperty(key, value);
+ }
+
+ return prop;
+ }
+
+ /**
+ * adapter property의 HEADER_GROUP으로 정의된 (MFE_HEADER) 그룹의 하위 필드를 http Header에
+ * 세팅한다.
+ *
+ * @param header
+ * @param object
+ */
+ private boolean assignHttpHeaders(HashMap header, Object msg, String headerGroupName) {
+ boolean redirect = false;
+
+ if (msg == null || StringUtils.isBlank(headerGroupName)) {
+ return false;
+ }
+
+ if (msg instanceof JSONObject) {
+ JSONObject headerObject = (JSONObject) ((JSONObject) msg).get(headerGroupName);
+
+ if (headerObject == null) {
+ return false;
+ }
+
+ // List headerKeys = new ArrayList<>();
+ for (Object key : headerObject.keySet()) {
+
+ Object obj = headerObject.get(key);
+ if ((obj instanceof JSONObject) || (obj instanceof JSONArray)) {
+ continue;
+ }
+
+ header.put((String) key, (String) obj);
+
+ if (StringUtils.equalsIgnoreCase((String) key, "Location")) {
+ redirect = true;
+ }
+ }
+
+ ((JSONObject) msg).remove(headerGroupName);
+ }
+
+ return redirect;
+ }
+
+ /**
+ * 어댑터 명 이후의 URI값을 가져온다.
+ *
+ * @param request
+ * @return
+ */
+ private String getExtUri(HttpServletRequest request) {
+ String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), "");
+ String uri = getExtUri(orgUri, 3);
+ if (uri != null && uri.trim().length() > 0) {
+ return "/" + uri;
+ } else {
+ return "";
+ }
+ }
+
+ private static String getExtUri(String url, int length) {
+ String[] urls = url.split("/");
+ List newUrls = new ArrayList<>();
+ Collections.addAll(newUrls, urls);
+ return StringUtils.join(newUrls.subList(length, urls.length).toArray(), "/");
+ }
+
+// public static void main(String[] args) throws Exception {
+// String orgUri = "/HTT/CbsInNetSys/abcd/123456";
+// String result = "";
+// result = getExtUri(orgUri, 3);
+// System.out.println(result);
+// }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceStandard.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceStandard.java
new file mode 100644
index 0000000..fc2da76
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/impl/HttpAdapterServiceStandard.java
@@ -0,0 +1,306 @@
+package com.eactive.eai.adapter.http.dynamic.impl;
+
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.http.HttpStatusException;
+import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.MessageUtil;
+import com.eactive.eai.env.ElinkConfig;
+import com.eactive.eai.inbound.processor.Processor;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.StopWatch;
+import org.apache.mina.common.ByteBuffer;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+public class HttpAdapterServiceStandard extends HttpAdapterServiceSupport
+{
+ public static final String PROPERTIES_NAME_HTTP_REQUEST_METHOD = "httpRequestMethod";
+ /*
+ * Adapter Logger
+ */
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ /**
+ * 1. 기능 : Http Servlet service 구현 메소드
+ * 2. 처리 개요 :
+ * - 로컬 서비스 호출
+ * 3. 주의사항
+ *
+ * @param request Http Servlet Request
+ * @return response Http Servlet Response
+ * @exception Exception PARAMETER_MESSAGE가 null 이거나 로컬 서비스 호출 중 오류가 발생할 경우
+ **/
+ public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) {
+ int traceLevel = 0;
+ try {
+ AdapterManager adapterManager = AdapterManager.getInstance();
+ AdapterVO adptVO = adapterManager.getAdapterVO(adptGrpName,adptName);
+
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+
+ if(adptVO == null) {
+ throw new ServletException("Adapter not Found adptName="+adptName);
+ }
+
+ Properties httpProp = manager.getProperties(adptVO.getPropGroupName());
+ String responseType = httpProp.getProperty(RESPONSE_TYPE,"SYNC");
+ String urlDecodeYn = httpProp.getProperty(URL_DECODE_YN,"N");
+ String encode = StringUtils.defaultIfBlank(adapterManager.getAdapterGroupVO(adptGrpName).getMessageEncode(), "MS949");
+ String messageType = adapterManager.getAdapterGroupVO(adptGrpName).getMessageType();
+ String requestBodyYn = httpProp.getProperty(REQUEST_BODY_YN,"N");
+ String parameterName = httpProp.getProperty(PARAMETER_NAME,PARAMETER_MESSAGE);
+ String removeLength = httpProp.getProperty(REMOVE_LENGTH,"0");
+ String addData = httpProp.getProperty(ADD_DATA,"");
+ String traceLevelTemp = httpProp.getProperty(TRACE_LEVEL,"0");
+ try{
+ traceLevel = Integer.parseInt(traceLevelTemp);
+ }catch(Exception e){
+ traceLevel = 0;
+ }
+
+ String paramValue = null;
+
+ int removeLen = 0;
+ try{
+ removeLen = Integer.parseInt(removeLength);
+ }catch(Exception e){
+ removeLen = 0;
+ }
+
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ logger.info("시작 >> encode = [" + encode + "]");
+
+ byte[] requestBytes = null;
+
+ if ("Y".equals(requestBodyYn)){
+ ServletInputStream sis = request.getInputStream();
+ ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true);
+ int i=0;
+ byte[] cbuf = new byte[1024];
+ while( ( i = sis.read(cbuf, 0, 1024) ) != -1 ) {
+ if (i==1024){
+ bb.put(cbuf);
+ }else{
+ byte[] tail = new byte[i];
+ System.arraycopy(cbuf, 0, tail, 0, i);
+ bb.put(tail);
+ }
+ }
+ requestBytes = new byte[bb.position()];
+ bb.position(0);
+ bb.get(requestBytes);
+ if (traceLevel >= 3){
+ HttpMemoryLogger.txlog(adptGrpName+adptName, "RECV "+"["+new String(requestBytes, encode)+"]"+ CommonLib.getDumpMessage(requestBytes));
+ }
+ }else{
+ paramValue = request.getParameter(parameterName);
+ if (traceLevel >= 3){
+ HttpMemoryLogger.txlog(adptGrpName+adptName, "RECV "+"["+paramValue+"]"+
+ ((paramValue == null)?"":CommonLib.getDumpMessage(paramValue))
+ );
+ }
+
+ if(paramValue==null)
+ throw new ServletException("RECEAIAHA002");
+
+ if ("Y".equals(urlDecodeYn)){
+ paramValue = URLDecoder.decode(paramValue);
+ }
+
+ if (logger.isDebug()){
+ logger.debug("HttpAdapter] RECV ("+adptGrpName+") = [" + paramValue + "]");
+ logger.debug("HttpAdapter] RECV ("+adptGrpName+") = " +
+ ((paramValue == null)?"":CommonLib.getDumpMessage(paramValue))
+ );
+ }
+ requestBytes = paramValue.getBytes(encode);
+ }
+
+ if (removeLen > 0 ) {
+ byte[] cuttedBytes = new byte[requestBytes.length-removeLen];
+ System.arraycopy(requestBytes, removeLen, cuttedBytes, 0, cuttedBytes.length);
+ requestBytes = cuttedBytes;
+ if (logger.isDebug()){
+ logger.debug("HttpAdapter] RECV after remove ("+adptGrpName+") = [" + new String(requestBytes, encode) + "]");
+ logger.debug("HttpAdapter] RECV after remove ("+adptGrpName+") = " + CommonLib.getDumpMessage(requestBytes));
+ }
+ }
+
+ if(logger.isDebug()){
+ String[] msgArgs = new String[2];
+ msgArgs[0] = adptGrpName;
+ msgArgs[1] = new String(requestBytes, encode);
+ String resMsg = ExceptionUtil.make("RICEAIAHA005", msgArgs);
+ logger.debug("HttpAdapter] " + resMsg);
+ }
+
+ Properties prop = new Properties();
+ prop.put(INBOUND_METHOD, request.getMethod());
+ prop.put(INBOUND_URI, request.getRequestURI());
+ prop.put(INBOUND_HEADER, getHeaders(request));
+ if (StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_REST)
+ || StringUtils.equals(adptVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) {
+ // /api/v1/public/getUserInfo.svc
+ String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath());
+ prop.put(INBOUND_EXTURI, extUrl);
+ } else {
+ prop.put(INBOUND_EXTURI, getExtUri(request));
+ }
+ prop.put(Processor.REQUEST_ACTION, adptVO.getAdapterGroupVO().getRefClass());
+ prop.put(API_PATH, httpProp.getProperty(API_PATH, ""));
+ prop.put(PRE_FILTERS, httpProp.getProperty(PRE_FILTERS, ""));
+ prop.put(POST_FILTERS, httpProp.getProperty(POST_FILTERS, ""));
+ prop.put(PROPERTIES_NAME_HTTP_REQUEST_METHOD, request.getMethod());
+ prop.put(ALLOW_IP, httpProp.getProperty(ALLOW_IP, ""));
+
+ // 로컬 서비스 호출
+ Object result = null;
+ if (MessageUtil.isBytesMessage(messageType)) {
+ result = service(adptGrpName, adptName, requestBytes, prop, request, response);
+ } else {
+ result = service(adptGrpName, adptName, new String(requestBytes, encode), prop, request, response);
+ }
+
+ stopWatch.stop();
+
+ String responseData = "";
+ if (RESPONSE_TYPE_ASYNC.equals(responseType)){
+ if (stopWatch.getTime() > slowTranTime){
+ if (logger.isWarn()){
+ logger.warn("HttpAdapter] lazy async response time = " + stopWatch.toString() + ", message = "+new String(requestBytes, encode));
+ }
+ }
+
+ if (result == null) {
+ responseData = ElinkConfig.getAsyncDummyDataForAdapterGroup(adptGrpName);
+ } else if (result instanceof byte[]) {
+ responseData = new String((byte[]) result, encode);
+ } else if (result instanceof String) {
+ responseData = (String) result;
+ }
+
+ response.setCharacterEncoding(encode);
+ response.getWriter().print(responseData);
+ if (traceLevel >= 3){
+ HttpMemoryLogger.txlog(adptGrpName+adptName, "SEND "+"["+responseData+"]"+
+ ((responseData == null)?"":CommonLib.getDumpMessage(responseData))
+ );
+ }
+ } else {
+ if(requestBytes != null) {
+ if (result instanceof byte[]) {
+ responseData = new String((byte[]) result, encode);
+ } else if (result instanceof String) {
+ responseData = (String) result;
+ }
+
+ logger.info("종료 >> encode = [" + encode + "]");
+
+ if (addData.length() > 0){
+ responseData = addData + responseData;
+ }
+ // UI와 통신시(UTF-8) 변환오류로 ENCODE 제거
+ response.setContentType("text/plain");
+ response.setCharacterEncoding(encode);
+ response.getWriter().print(responseData);
+ if (logger.isDebug()){
+ logger.debug("HttpAdapter] SEND ("+adptGrpName+") = [" + responseData + "]");
+ logger.debug("HttpAdapter] SEND ("+adptGrpName+") = " +
+ ((responseData == null)?"":CommonLib.getDumpMessage(responseData))
+ );
+ }
+ if (traceLevel >= 3){
+ HttpMemoryLogger.txlog(adptGrpName+adptName, "SEND "+"["+responseData+"]"+
+ ((responseData == null)?"":CommonLib.getDumpMessage(responseData))
+ );
+ }
+ }
+ }
+ } catch (HttpStatusException e) {
+ if (traceLevel >= 3) {
+ HttpMemoryLogger.error(adptGrpName + adptName, e.toString(), e);
+ }
+ logger.warn("HttpAdapter] " + adptGrpName + "-" + adptName + ">>" + e.getMessage());
+ response.setStatus(e.getStatus());
+ try {
+ String errorMsg = String.format("(%d) %s", e.getStatus(), e.getMessage());
+ response.getWriter().println(errorMsg);
+ } catch (Exception ex) {
+ // IGNORE
+ }
+ } catch (Exception e) {
+ if (traceLevel >= 3){
+ HttpMemoryLogger.error(adptGrpName+adptName, e.toString(),e);
+ }
+ logger.error("HttpAdapter] "+adptGrpName+"-"+adptName, e);
+ response.setStatus(500);
+ try {
+ response.getWriter().println(e.getMessage());
+ String errCode = ExceptionUtil.getErrorCode(e, "RECEAIAHA003");
+ throw new Exception(errCode);
+ } catch (Exception ex) {
+ logger.warn("error", ex);
+ }
+ }
+ }
+
+ /**
+ * 어댑터 명 이후의 URI값을 가져온다.
+ *
+ * @param request
+ * @return
+ */
+ private String getExtUri(HttpServletRequest request) {
+ String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), "");
+ String uri = getExtUri(orgUri, 3);
+ if (uri != null && uri.trim().length() > 0) {
+ return "/" + uri;
+ } else {
+ return "";
+ }
+ }
+
+ private static String getExtUri(String url, int length) {
+ String[] urls = url.split("/");
+ List newUrls = new ArrayList<>();
+ Collections.addAll(newUrls, urls);
+ return StringUtils.join(newUrls.subList(length, urls.length).toArray(), "/");
+ }
+ /**
+ * request header 를 hashmap으로 조립
+ *
+ * @param request
+ * @return
+ */
+ private Properties getHeaders(HttpServletRequest request) {
+ Properties prop = new Properties();
+
+ Enumeration headerNames = request.getHeaderNames();
+ while (headerNames.hasMoreElements()) {
+ String key = headerNames.nextElement();
+ String value = request.getHeader(key);
+ prop.setProperty(key, value);
+ }
+
+ return prop;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/wrapper/KeepAliveFalseWrapper.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/wrapper/KeepAliveFalseWrapper.java
new file mode 100644
index 0000000..d0c8e57
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/wrapper/KeepAliveFalseWrapper.java
@@ -0,0 +1,20 @@
+package com.eactive.eai.adapter.http.dynamic.wrapper;
+
+import io.undertow.server.HandlerWrapper;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.Headers;
+
+public class KeepAliveFalseWrapper implements HandlerWrapper {
+ @Override
+ public HttpHandler wrap(HttpHandler handler) {
+ return new HttpHandler() {
+ @Override
+ public void handleRequest(HttpServerExchange exchange) throws Exception {
+ handler.handleRequest(exchange);
+ exchange.getResponseHeaders().put(Headers.CONNECTION, "close");
+ }
+ };
+ }
+}
+
diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/wrapper/KeepAliveTrueWrapper.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/wrapper/KeepAliveTrueWrapper.java
new file mode 100644
index 0000000..ae9e4fc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/wrapper/KeepAliveTrueWrapper.java
@@ -0,0 +1,69 @@
+package com.eactive.eai.adapter.http.dynamic.wrapper;
+
+import io.undertow.server.HandlerWrapper;
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.ServerConnection;
+import io.undertow.util.AttachmentKey;
+import io.undertow.util.Headers;
+
+public class KeepAliveTrueWrapper implements HandlerWrapper {
+ private final AttachmentKey MAX_COUNT = AttachmentKey.create(Integer.class);
+ private int keepAliveTimeout = 15;
+ private int maxRequestCount = -1; // 최대 요청 횟수 설정
+
+ public int getKeepAliveTimeout() {
+ return keepAliveTimeout;
+ }
+
+ public void setKeepAliveTimeout(int keepAliveTimeout) {
+ this.keepAliveTimeout = keepAliveTimeout;
+ }
+
+ public int getMaxRequestCount() {
+ return maxRequestCount;
+ }
+
+ public void setMaxRequestCount(int maxRequestCount) {
+ this.maxRequestCount = maxRequestCount;
+ }
+
+ @Override
+ public HttpHandler wrap(HttpHandler handler) {
+ return new HttpHandler() {
+ @Override
+ public void handleRequest(HttpServerExchange exchange) throws Exception {
+ // max requst count 가 제한이 없을경우
+ if (maxRequestCount == -1) {
+ handler.handleRequest(exchange);
+ exchange.getResponseHeaders().put(Headers.KEEP_ALIVE, "timeout=" + keepAliveTimeout);
+ return;
+ }
+
+ // 현재 연결의 요청 횟수 가져오기
+ ServerConnection con = exchange.getConnection();
+ int count = 0;
+ try {
+ count = con.getAttachment(MAX_COUNT);
+ } catch (Exception e) {
+
+ }
+ count++;
+
+ con.putAttachment(MAX_COUNT, count);
+ // 최대 요청 횟수를 초과한 경우 연결을 종료하고 로그를 출력
+ if (count > maxRequestCount) {
+ exchange.getConnection().close();
+ System.out.println("Connection closed due to exceeding max requests limit.");
+ return;
+ }
+ handler.handleRequest(exchange);
+ if (count > maxRequestCount - 1) {
+ exchange.getResponseHeaders().put(Headers.CONNECTION, "close");
+ }
+ exchange.getResponseHeaders().put(Headers.KEEP_ALIVE,
+ "timeout=" + keepAliveTimeout + ", max=" + (maxRequestCount - count));
+ }
+ };
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpHealthChecker.java b/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpHealthChecker.java
new file mode 100644
index 0000000..3877a1f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpHealthChecker.java
@@ -0,0 +1,76 @@
+package com.eactive.eai.adapter.http.healthcheck;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.common.util.Logger;
+
+public class HttpHealthChecker {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ private String healthCheckUrl;
+ private AdapterVO adapter;
+ int timeoutMillis = 2000;
+
+
+ public int getTimeoutMillis() {
+ return timeoutMillis;
+ }
+
+ public void setTimeoutMillis(int timeoutMillis) {
+ this.timeoutMillis = timeoutMillis;
+ }
+
+ public String getHealthCheckUrl() {
+ return healthCheckUrl;
+ }
+
+ public void setHealthCheckUrl(String healthCheckUrl) {
+ this.healthCheckUrl = healthCheckUrl;
+ }
+
+ public AdapterVO getAdapter() {
+ return adapter;
+ }
+
+ public void setAdapter(AdapterVO adapter) {
+ this.adapter = adapter;
+ }
+
+ public boolean isAlive() {
+ HttpURLConnection connection = null;
+ String debugPrefix = "HttpHealthChecker] " + adapter.getName() + " healthCheckUrl " + healthCheckUrl;
+ try {
+ if(logger.isInfo()) {
+ logger.info(debugPrefix);
+ }
+ URL url = new URL(healthCheckUrl);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(timeoutMillis); // Set connection timeout
+ connection.setReadTimeout(timeoutMillis); // Set read timeout
+
+ int responseCode = connection.getResponseCode();
+ boolean result = false;
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ result = true;
+ }
+
+ if(logger.isInfo()) {
+ logger.info(debugPrefix + " returned a response code: " + responseCode);
+ }
+ return result;
+ }
+ catch(Exception ex) {
+ logger.error(debugPrefix + " error", ex);
+ return false;
+ }
+ finally {
+ if(connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpTargetMonitor.java b/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpTargetMonitor.java
new file mode 100644
index 0000000..26ad337
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpTargetMonitor.java
@@ -0,0 +1,54 @@
+package com.eactive.eai.adapter.http.healthcheck;
+
+import java.util.Iterator;
+import java.util.TimerTask;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.common.util.Logger;
+
+public class HttpTargetMonitor extends TimerTask {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+ private HttpTargetMonitorManager manager;
+
+ public void setManager(HttpTargetMonitorManager manager) {
+ this.manager = manager;
+ }
+
+ public void run() {
+ logger.warn("HttpTargetMonitor] run");
+
+ if (this.manager == null || !this.manager.isStarted()) {
+ logger.warn("HttpTargetMonitorManager is stopped. stop HttpTargetMonitor.");
+ return;
+ }
+
+ Iterator adapterNames = manager.getAllAdapterNames();
+
+ ExecutorService executor = Executors.newFixedThreadPool(20);
+ try {
+ while (adapterNames.hasNext()) {
+ String name = adapterNames.next();
+ HttpHealthChecker checker = manager.getHttpHeacthChecker(name);
+ AdapterVO vo = checker.getAdapter();
+ if (checker == null || vo == null) {
+ logger.warn("Target HealthCheck remove - " + name);
+ manager.removeHttpHeacthChecker(name);
+ } else {
+ executor.submit(() -> {
+ try {
+ vo.setStatus(checker.isAlive());
+ } catch (Exception e) {
+ if (logger.isError()) {
+ logger.error("Target HealthCheck error", e);
+ }
+ }
+ });
+ }
+ }
+ } finally {
+ executor.shutdown();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpTargetMonitorManager.java b/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpTargetMonitorManager.java
new file mode 100644
index 0000000..b0120bd
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/healthcheck/HttpTargetMonitorManager.java
@@ -0,0 +1,239 @@
+package com.eactive.eai.adapter.http.healthcheck;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Timer;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.lifecycle.LifecycleSupport;
+import com.eactive.eai.common.property.PropManager;
+import com.eactive.eai.common.util.Logger;
+
+public class HttpTargetMonitorManager implements Lifecycle {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+
+ public static final String threadName = "HttpTargetMonitorManager";
+
+ public static final String PROP_GROUP = "HttpTargetMonitor";
+ public static final String CHECK_INTERVAL_SECS = "check.interval.secs";
+ private static final int CHECK_INTERVAL_MINSECS = 30;
+
+ private int checkIntervalSecs = 60;
+
+ private static HttpTargetMonitorManager manager = new HttpTargetMonitorManager();
+
+ private LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+ private boolean started;
+
+ private ConcurrentHashMap checkers = new ConcurrentHashMap<>();
+
+ private HttpTargetMonitor runner;
+
+ private Timer timer;
+
+ public static HttpTargetMonitorManager getInstance() {
+ return manager;
+ }
+
+ private void loadHttpAdapterList() {
+ AdapterManager adapterManager = AdapterManager.getInstance();
+
+ HashMap adapterGroups = adapterManager.getAllAdapterGroupVO();
+ for(AdapterGroupVO adapterGroup : adapterGroups.values()) {
+ if( adapterGroup.isUsedFlag()
+ && ( StringUtils.equals(Keys.ADAPTER_OUT, adapterGroup.getGubun()) )
+ && ( StringUtils.equals(Keys.TYPE_HTTP, adapterGroup.getType()) || StringUtils.equals(Keys.TYPE_REST, adapterGroup.getType()))
+ ) {
+ addAdapterGroup(adapterGroup);
+ }
+ }
+ }
+
+ public void addAdapterGroup(AdapterGroupVO adapterGroup) {
+ AdapterPropManager propManager = AdapterPropManager.getInstance();
+ Iterator adapters = adapterGroup.getAdapters();
+ while(adapters.hasNext()) {
+ AdapterVO adapter = adapters.next();
+ String healthCheckUrl = propManager.getProperty(adapter.getPropGroupName(), HttpClientAdapterServiceKey.HEALTHCHECK_URL);
+ String timeoutMs = propManager.getProperty(adapter.getPropGroupName(), HttpClientAdapterServiceKey.HEALTHCHECK_TIMEOUTMS);
+
+ if(StringUtils.isNotBlank(healthCheckUrl)) {
+ if(adapterGroup.isUsedFlag()) {
+ if(logger.isInfo()) {
+ logger.info(String.format("loadHttpAdapterList AdapterName=%s, healthCheckUrl=%s timeoutMs=%s", adapter.getName(), healthCheckUrl, timeoutMs));
+ }
+ addHttpHeacthChecker(healthCheckUrl, timeoutMs, adapter);
+ }
+ else {
+ if(logger.isInfo()) {
+ logger.info(String.format("removeHttpHeacthChecker AdapterName=%s, healthCheckUrl=%s timeoutMs=%s", adapter.getName(), healthCheckUrl, timeoutMs));
+ }
+ removeHttpHeacthChecker(adapter);
+ }
+ }
+ else {
+ if(logger.isInfo()) {
+ logger.info(String.format("removeHttpHeacthChecker AdapterName=%s, healthCheckUrl=%s timeoutMs=%s", adapter.getName(), healthCheckUrl, timeoutMs));
+ }
+ removeHttpHeacthChecker(adapter);
+ }
+ }
+ }
+
+ public void start() throws LifecycleException {
+ logger.error(threadName +"] is start");
+ if (started)
+ throw new LifecycleException("RECEAICTM001");
+
+ lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
+
+ loadHttpAdapterList();
+
+ PropManager pmanager = PropManager.getInstance();
+ // default 1 mins
+
+ try {
+ checkIntervalSecs = Integer.parseInt(pmanager.getProperty(PROP_GROUP, CHECK_INTERVAL_SECS));
+ } catch (NumberFormatException e) {
+ logger.warn( String.format("%s %s not number", PROP_GROUP, CHECK_INTERVAL_SECS), e);
+ }
+
+ if(checkIntervalSecs < CHECK_INTERVAL_MINSECS) {
+ logger.warn( String.format("%s %s too small, use default %s", CHECK_INTERVAL_SECS, checkIntervalSecs, CHECK_INTERVAL_MINSECS));
+ checkIntervalSecs = CHECK_INTERVAL_MINSECS;
+ }
+
+ this.runner = new HttpTargetMonitor();
+ this.runner.setManager(this);
+
+ this.timer = new Timer(threadName);
+
+ long period = (checkIntervalSecs * 1000);
+ this.timer.schedule(this.runner, period, period);
+
+ started = true;
+ lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
+ }
+
+ public void stop() throws LifecycleException {
+ if (!started)
+ throw new LifecycleException("RECEAICTM002");
+
+ lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
+
+ this.timer.cancel();
+ this.timer = null;
+ this.runner = null;
+
+ if (this.checkers != null) {
+ this.checkers.clear();
+ this.checkers = null;
+ }
+
+ started = false;
+ lifecycle.fireLifecycleEvent(STOPPED_EVENT, null);
+ }
+
+ public void addLifecycleListener(LifecycleListener listener) {
+ lifecycle.addLifecycleListener(listener);
+ }
+
+ public LifecycleListener[] findLifecycleListeners() {
+ return lifecycle.findLifecycleListeners();
+ }
+
+ public void removeLifecycleListener(LifecycleListener listener) {
+ lifecycle.removeLifecycleListener(listener);
+ }
+
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ public void addHttpHeacthChecker(String healthCheckUrl, String timeoutMsVal, AdapterVO vo) {
+ HttpHealthChecker checker = new HttpHealthChecker();
+ checker.setHealthCheckUrl(healthCheckUrl);
+
+ int timeoutMs = 2000;
+ if(StringUtils.isNoneBlank(timeoutMsVal)) {
+ try {
+ timeoutMs = Integer.parseInt(timeoutMsVal);
+ }
+ catch(NumberFormatException ne) {
+ timeoutMs = 2000;
+ }
+ }
+
+ if(checkIntervalSecs <= timeoutMs / 1000) {
+ logger.warn( String.format("%s timeoutMs %s too big, use default %s", vo.getName(), timeoutMs, (checkIntervalSecs-1) * 1000));
+ timeoutMs = (checkIntervalSecs-1) * 1000;
+ }
+
+ checker.setTimeoutMillis(timeoutMs);
+ checker.setAdapter(vo);
+ this.checkers.put(vo.getAdapterGroupName() + "-" + vo.getName(), checker);
+ }
+
+ public void removeHttpHeacthChecker(AdapterVO vo) {
+ this.checkers.remove(vo.getAdapterGroupName() + "-" + vo.getName());
+ }
+
+ public Iterator getAllAdapterNames() {
+ HashMap map = new HashMap<>(checkers);
+ return map.keySet().iterator();
+ }
+
+ public String[] getAllAdapterNamesWithGroupName(String adapterGroupName) {
+ HashMap map = new HashMap<>(checkers);
+ String namePrefix = adapterGroupName + "-";
+ Iterator it = map.keySet().iterator();
+ List list = new ArrayList<>();
+ while(it.hasNext()) {
+ String key = it.next();
+ if(key.startsWith(namePrefix)) {
+ list.add(key);
+ }
+ }
+ return list.toArray(new String[0]);
+ }
+
+ public HttpHealthChecker getHttpHeacthChecker(String adapterName) {
+ return this.checkers.get(adapterName);
+ }
+
+ public void removeHttpHeacthChecker(String adapterName) {
+ this.checkers.remove(adapterName);
+ }
+
+ public void removeHttpHeacthCheckerWithGroupName(String adapterGroupName) {
+ if(logger.isInfo()) {
+ logger.info("removeHttpHeacthCheckerWithGroupName - " +adapterGroupName);
+ }
+ String[] adatperNames = getAllAdapterNamesWithGroupName(adapterGroupName);
+ for(int i=0; i< adatperNames.length; i++) {
+ if(logger.isInfo()) {
+ logger.info("removeHttpHeacthCheckerWithGroupName remove - " +adatperNames[i]);
+ }
+ this.checkers.remove(adatperNames[i]);
+ }
+ }
+
+ public int getCheckerCount() {
+ return this.checkers.size();
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/secure/CustomHttpsSocketFactory.java b/src/main/java/com/eactive/eai/adapter/http/secure/CustomHttpsSocketFactory.java
new file mode 100644
index 0000000..6f156d8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/secure/CustomHttpsSocketFactory.java
@@ -0,0 +1,55 @@
+package com.eactive.eai.adapter.http.secure;
+
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+
+public class CustomHttpsSocketFactory implements SecureProtocolSocketFactory
+{
+
+ private final SecureProtocolSocketFactory base;
+
+ public CustomHttpsSocketFactory(ProtocolSocketFactory base)
+ {
+ if(base == null || !(base instanceof SecureProtocolSocketFactory)) throw new IllegalArgumentException();
+ this.base = (SecureProtocolSocketFactory) base;
+ }
+
+ private Socket acceptOnlyTLS12(Socket socket)
+ {
+ if(!(socket instanceof SSLSocket)) return socket;
+ SSLSocket sslSocket = (SSLSocket) socket;
+ sslSocket.setEnabledProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"});
+
+// for(int i=0; i< sslSocket.getEnabledProtocols().length; i++)
+// System.out.println("EnabledProtocols : " + i + " - " + sslSocket.getEnabledProtocols()[i]);
+
+ return sslSocket;
+ }
+
+ public Socket createSocket(String host, int port) throws IOException
+ {
+ return acceptOnlyTLS12(base.createSocket(host, port));
+ }
+
+ public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException
+ {
+ return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort));
+ }
+
+ public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException
+ {
+ return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort, params));
+ }
+
+ public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException
+ {
+ return acceptOnlyTLS12(base.createSocket(socket, host, port, autoClose));
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/secure/CustomSSLProtocolSocketFactory.java b/src/main/java/com/eactive/eai/adapter/http/secure/CustomSSLProtocolSocketFactory.java
new file mode 100644
index 0000000..547ec26
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/secure/CustomSSLProtocolSocketFactory.java
@@ -0,0 +1,58 @@
+package com.eactive.eai.adapter.http.secure;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+
+public class CustomSSLProtocolSocketFactory implements SecureProtocolSocketFactory {
+ private SSLContext sslContext;
+
+ public CustomSSLProtocolSocketFactory(SSLContext sslContext) {
+ this.sslContext = sslContext;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
+ return sslContext.getSocketFactory().createSocket(host, port);
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, java.net.InetAddress localAddress, int localPort) throws IOException, UnknownHostException {
+ return sslContext.getSocketFactory().createSocket(host, port, localAddress, localPort);
+ }
+
+ @Override
+ public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
+ return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localAddress, int localPort,
+ HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
+ if (params == null) {
+ throw new IllegalArgumentException("Parameters may not be null");
+ }
+ int timeout = params.getConnectionTimeout();
+ SocketFactory socketfactory = sslContext.getSocketFactory();
+ if (timeout == 0) {
+ return socketfactory.createSocket(host, port, localAddress, localPort);
+ } else {
+ Socket socket = socketfactory.createSocket();
+ SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
+ SocketAddress remoteaddr = new InetSocketAddress(host, port);
+ socket.bind(localaddr);
+ socket.connect(remoteaddr, timeout);
+ return socket;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/secure/EasySSLProtocolSocketFactory.java b/src/main/java/com/eactive/eai/adapter/http/secure/EasySSLProtocolSocketFactory.java
new file mode 100644
index 0000000..e87638d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/secure/EasySSLProtocolSocketFactory.java
@@ -0,0 +1,254 @@
+package com.eactive.eai.adapter.http.secure;
+
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.security.cert.X509Certificate;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.HttpClientError;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ *
+ * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
+ * that accept self-signed certificates.
+ *
+ *
+ * This socket factory SHOULD NOT be used for productive systems
+ * due to security reasons, unless it is a concious decision and
+ * you are perfectly aware of security implications of accepting
+ * self-signed certificates
+ *
+ *
+ *
+ * Example of using custom protocol socket factory for a specific host:
+ *
+ * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *
+ * URI uri = new URI("https://localhost/", true);
+ * // use relative url only
+ * GetMethod httpget = new GetMethod(uri.getPathQuery());
+ * HostConfiguration hc = new HostConfiguration();
+ * hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
+ * HttpClient client = new HttpClient();
+ * client.executeMethod(hc, httpget);
+ *
+ *
+ *
+ * Example of using custom protocol socket factory per default instead of the standard one:
+ *
+ * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ * Protocol.registerProtocol("https", easyhttps);
+ *
+ * HttpClient client = new HttpClient();
+ * GetMethod httpget = new GetMethod("https://localhost/");
+ * client.executeMethod(httpget);
+ *
+ *
+ *
+ * @author Oleg Kalnichevski
+ *
+ *
+ * DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ * The component is provided as a reference material, which may be inappropriate
+ * for use without additional customization.
+ *
+ */
+
+public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory {
+
+ /** Log object for this class. */
+ private static final Log LOG = LogFactory.getLog(EasySSLProtocolSocketFactory.class);
+
+ private SSLContext sslcontext = null;
+
+ /**
+ * Constructor for EasySSLProtocolSocketFactory.
+ */
+ public EasySSLProtocolSocketFactory() {
+ super();
+ }
+
+ private static SSLContext createEasySSLContext() {
+ try {
+ //---------------------------------------------
+ // 인증서 없이 하는 방법
+ //---------------------------------------------
+ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(X509Certificate[] certs,
+ String authType) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] certs,
+ String authType) {
+ }
+ } };
+ //---------------------------------------------
+ SSLContext context = SSLContext.getInstance("SSL");
+ context.init(
+ null,
+// new TrustManager[] {new EasyX509TrustManager(null)},
+ trustAllCerts,
+ null);
+ return context;
+ } catch (Exception e) {
+ LOG.error(e.getMessage(), e);
+ throw new HttpClientError(e.toString());
+ }
+ }
+
+ private SSLContext getSSLContext() {
+ if (this.sslcontext == null) {
+ this.sslcontext = createEasySSLContext();
+ }
+ return this.sslcontext;
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
+ */
+ public Socket createSocket(
+ String host,
+ int port,
+ InetAddress clientHost,
+ int clientPort)
+ throws IOException, UnknownHostException {
+
+ return getSSLContext().getSocketFactory().createSocket(
+ host,
+ port,
+ clientHost,
+ clientPort
+ );
+ }
+
+ /**
+ * Attempts to get a new socket connection to the given host within the given time limit.
+ *
+ * To circumvent the limitations of older JREs that do not support connect timeout a
+ * controller thread is executed. The controller thread attempts to create a new socket
+ * within the given limit of time. If socket constructor does not return until the
+ * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
+ *
+ *
+ * @param host the host name/IP
+ * @param port the port on the host
+ * @param clientHost the local host name/IP to bind the socket to
+ * @param clientPort the port on the local machine
+ * @param params {@link HttpConnectionParams Http connection parameters}
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ * @throws UnknownHostException if the IP address of the host cannot be
+ * determined
+ */
+ public Socket createSocket(
+ final String host,
+ final int port,
+ final InetAddress localAddress,
+ final int localPort,
+ final HttpConnectionParams params
+ ) throws IOException, UnknownHostException, ConnectTimeoutException {
+ if (params == null) {
+ throw new IllegalArgumentException("Parameters may not be null");
+ }
+ int timeout = params.getConnectionTimeout();
+ SocketFactory socketfactory = getSSLContext().getSocketFactory();
+ if (timeout == 0) {
+ return socketfactory.createSocket(host, port, localAddress, localPort);
+ } else {
+ Socket socket = socketfactory.createSocket();
+ SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
+ SocketAddress remoteaddr = new InetSocketAddress(host, port);
+ socket.bind(localaddr);
+ socket.connect(remoteaddr, timeout);
+ return socket;
+ }
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
+ */
+ public Socket createSocket(String host, int port)
+ throws IOException, UnknownHostException {
+ return getSSLContext().getSocketFactory().createSocket(
+ host,
+ port
+ );
+ }
+
+ /**
+ * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
+ */
+ public Socket createSocket(
+ Socket socket,
+ String host,
+ int port,
+ boolean autoClose)
+ throws IOException, UnknownHostException {
+ return getSSLContext().getSocketFactory().createSocket(
+ socket,
+ host,
+ port,
+ autoClose
+ );
+ }
+
+ public boolean equals(Object obj) {
+ return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class));
+ }
+
+ public int hashCode() {
+ return EasySSLProtocolSocketFactory.class.hashCode();
+ }
+
+}
+
diff --git a/src/main/java/com/eactive/eai/adapter/http/secure/EasyX509TrustManager.java b/src/main/java/com/eactive/eai/adapter/http/secure/EasyX509TrustManager.java
new file mode 100644
index 0000000..64f4431
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/secure/EasyX509TrustManager.java
@@ -0,0 +1,115 @@
+package com.eactive.eai.adapter.http.secure;
+
+/*
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ *
+ * EasyX509TrustManager unlike default {@link X509TrustManager} accepts
+ * self-signed certificates.
+ *
+ *
+ * This trust manager SHOULD NOT be used for productive systems
+ * due to security reasons, unless it is a concious decision and
+ * you are perfectly aware of security implications of accepting
+ * self-signed certificates
+ *
+ *
+ * @author Adrian Sutton
+ * @author Oleg Kalnichevski
+ *
+ *
+ * DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ * The component is provided as a reference material, which may be inappropriate
+ * for use without additional customization.
+ *
+ */
+
+public class EasyX509TrustManager implements X509TrustManager
+{
+ private X509TrustManager standardTrustManager = null;
+
+ /** Log object for this class. */
+ private static final Log LOG = LogFactory.getLog(EasyX509TrustManager.class);
+
+ /**
+ * Constructor for EasyX509TrustManager.
+ */
+ public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException {
+ super();
+ TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ factory.init(keystore);
+ TrustManager[] trustmanagers = factory.getTrustManagers();
+ if (trustmanagers.length == 0) {
+ throw new NoSuchAlgorithmException("no trust manager found");
+ }
+ this.standardTrustManager = (X509TrustManager)trustmanagers[0];
+ }
+
+ /**
+ * @see X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
+ */
+ public void checkClientTrusted(X509Certificate[] certificates,String authType) throws CertificateException {
+ standardTrustManager.checkClientTrusted(certificates,authType);
+ }
+
+ /**
+ * @see X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
+ */
+ public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException {
+ if ((certificates != null) && LOG.isDebugEnabled()) {
+ LOG.debug("Server certificate chain:");
+ for (int i = 0; i < certificates.length; i++) {
+ LOG.debug("X509Certificate[" + i + "]=" + certificates[i]);
+ }
+ }
+ if ((certificates != null) && (certificates.length == 1)) {
+ certificates[0].checkValidity();
+ } else {
+ standardTrustManager.checkServerTrusted(certificates,authType);
+ }
+ }
+
+ /**
+ * @see X509TrustManager#getAcceptedIssuers()
+ */
+ public X509Certificate[] getAcceptedIssuers() {
+ return this.standardTrustManager.getAcceptedIssuers();
+ }
+}
+
diff --git a/src/main/java/com/eactive/eai/adapter/http/secure/HttpClient5SSLContextFactory.java b/src/main/java/com/eactive/eai/adapter/http/secure/HttpClient5SSLContextFactory.java
new file mode 100644
index 0000000..edad554
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/secure/HttpClient5SSLContextFactory.java
@@ -0,0 +1,156 @@
+package com.eactive.eai.adapter.http.secure;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.Base64;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+
+import org.apache.commons.codec.binary.StringUtils;
+import org.apache.hc.core5.ssl.SSLContextBuilder;
+import org.apache.hc.core5.ssl.TrustStrategy;
+
+import com.eactive.eai.util.TestModeChecker;
+
+public class HttpClient5SSLContextFactory {
+
+ private static boolean testMode = TestModeChecker.isTestMode();
+
+ private HttpClient5SSLContextFactory() {
+
+ }
+
+ // not used (파일인증서 관리시 사용)
+ public static SSLContext createMTLSContextFromFile(String type, String keyStorePath, String keyStorePassword,
+ String trustStorePath, String trustStorePassword, boolean skipTrust, String[] tlsVersions,
+ String[] cipherSuites) throws SSLContextCreateException {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(type);
+ try (FileInputStream keyStoreInput = new FileInputStream(new File(keyStorePath))) {
+ keyStore.load(keyStoreInput, keyStorePassword.toCharArray());
+ }
+
+ SSLContextBuilder sslContextBuilder = null;
+ if (skipTrust) {
+ if (testMode) {
+ // 모든 인증서 신뢰 설정
+ TrustStrategy trustAllCertificates = new TrustStrategy() {
+ @Override
+ public boolean isTrusted(X509Certificate[] chain, String authType) {
+ return true;
+ }
+ };
+ sslContextBuilder = SSLContextBuilder.create()
+ .loadKeyMaterial(keyStore, keyStorePassword.toCharArray()) // 클라이언트 키스토어 로드
+ .loadTrustMaterial(null, trustAllCertificates); // 모든 인증서를 신뢰하도록 설정
+ } else {
+ // 기본 TrustStore를 사용하여 신뢰 설정
+ // java root CA를 사용함 (jvm 설정에 추가되어야 함 )
+ sslContextBuilder = SSLContextBuilder.create()
+ .loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
+ .loadTrustMaterial((TrustStrategy) null);
+ }
+ } else {
+ KeyStore trustStore = KeyStore.getInstance(type);
+ try (FileInputStream trustStoreInput = new FileInputStream(new File(trustStorePath))) {
+ trustStore.load(trustStoreInput, trustStorePassword.toCharArray());
+ }
+
+ sslContextBuilder = SSLContextBuilder.create().loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
+ .loadTrustMaterial(trustStore, (TrustStrategy) null);
+ }
+
+ SSLContext sslContext = sslContextBuilder.build();
+
+ SSLParameters sslParameters = sslContext.getDefaultSSLParameters();
+ if (tlsVersions != null) {
+ sslParameters.setProtocols(tlsVersions);
+ }
+ if (cipherSuites != null) {
+ sslParameters.setCipherSuites(cipherSuites);
+ }
+
+ return sslContext;
+ } catch (Exception e) {
+ String errorMessage = String.format("Failed to create SSLContext type(Algorithm): %s", type);
+ throw new SSLContextCreateException(errorMessage, e);
+ }
+ }
+
+ public static SSLContext createMTLSContextFromContent(String type, String keyStoreBase64Content,
+ String keyStorePassword, String trustStoreBase64Content, String trustStorePassword, boolean skipTrust,
+ String[] tlsVersions, String[] cipherSuites) throws SSLContextCreateException {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(type);
+ byte[] keyBytes = Base64.getDecoder().decode(keyStoreBase64Content);
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(keyBytes)) {
+ keyStore.load(bis, keyStorePassword.toCharArray());
+ }
+
+ SSLContextBuilder sslContextBuilder = null;
+ if (skipTrust) {
+ if (testMode) {
+ // 모든 인증서를 신뢰함
+ TrustStrategy trustAllCertificates = new TrustStrategy() {
+ @Override
+ public boolean isTrusted(X509Certificate[] chain, String authType) {
+ return true;
+ }
+ };
+ sslContextBuilder = SSLContextBuilder.create()
+ .loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
+ .loadTrustMaterial(null, trustAllCertificates);
+ } else {
+ // java root CA를 사용함 (jvm 설정에 추가되어야 함)
+ // java root CA 사용
+ sslContextBuilder = SSLContextBuilder.create()
+ .loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
+ .loadTrustMaterial((TrustStrategy) null);
+ }
+ } else {
+ KeyStore trustStore = KeyStore.getInstance(type);
+ byte[] trustBytes = Base64.getDecoder().decode(trustStoreBase64Content);
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(trustBytes)) {
+ trustStore.load(bis, trustStorePassword.toCharArray());
+ }
+
+ sslContextBuilder = SSLContextBuilder.create().loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
+ .loadTrustMaterial(trustStore, (TrustStrategy) null); // 신뢰할 모든 인증서
+ }
+
+ SSLContext sslContext = sslContextBuilder.build();
+
+ SSLParameters sslParameters = sslContext.getDefaultSSLParameters();
+ if (tlsVersions != null) {
+ sslParameters.setProtocols(tlsVersions);
+ }
+ if (cipherSuites != null) {
+ sslParameters.setCipherSuites(cipherSuites);
+ }
+
+ return sslContext;
+ } catch (Exception e) {
+ String errorMessage = String.format("Failed to create SSLContext type(Algorithm): %s", type);
+ throw new SSLContextCreateException(errorMessage, e);
+ }
+ }
+
+ public static SSLContext createMTLSContextForJKS(String keyStorePath, String keyStorePassword,
+ String trustStorePath, String trustStorePassword, String[] tlsVersions, String[] cipherSuites)
+ throws SSLContextCreateException {
+ return createMTLSContextFromFile("JKS", keyStorePath, keyStorePassword, trustStorePath, trustStorePassword,
+ false, tlsVersions, cipherSuites);
+ }
+
+ public static SSLContext createMTLSContextForP12(String keyStorePath, String keyStorePassword,
+ String trustStorePath, String trustStorePassword, String[] tlsVersions, String[] cipherSuites)
+ throws SSLContextCreateException {
+ return createMTLSContextFromFile("PKCS12", keyStorePath, keyStorePassword, trustStorePath, trustStorePassword,
+ false, tlsVersions, cipherSuites);
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/secure/SSLContextCreateException.java b/src/main/java/com/eactive/eai/adapter/http/secure/SSLContextCreateException.java
new file mode 100644
index 0000000..bd9c2e4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/secure/SSLContextCreateException.java
@@ -0,0 +1,14 @@
+package com.eactive.eai.adapter.http.secure;
+
+public class SSLContextCreateException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public SSLContextCreateException(String message) {
+ super(message);
+ }
+
+ public SSLContextCreateException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
+
diff --git a/src/main/java/com/eactive/eai/adapter/http/secure/SSLContextFactory.java b/src/main/java/com/eactive/eai/adapter/http/secure/SSLContextFactory.java
new file mode 100644
index 0000000..d85eee3
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/secure/SSLContextFactory.java
@@ -0,0 +1,170 @@
+package com.eactive.eai.adapter.http.secure;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.Base64;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.commons.codec.binary.StringUtils;
+
+import com.eactive.eai.util.TestModeChecker;
+
+public class SSLContextFactory {
+
+ private static boolean testMode = TestModeChecker.isTestMode();
+
+ private SSLContextFactory() {
+
+ }
+
+ // not used (파일인증서 관리시 사용)
+ public static SSLContext createMTLSContextFromFile(String type, String keyStorePath, String keyStorePassword,
+ String trustStorePath, String trustStorePassword, boolean skipTrust, String[] tlsVersions,
+ String[] cipherSuites) throws SSLContextCreateException {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(type);
+ try (FileInputStream keyStoreInput = new FileInputStream(new File(keyStorePath))) {
+ keyStore.load(keyStoreInput, keyStorePassword.toCharArray());
+ }
+
+ KeyStore trustStore = KeyStore.getInstance(type);
+ try (FileInputStream trustStoreInput = new FileInputStream(new File(trustStorePath))) {
+ trustStore.load(trustStoreInput, trustStorePassword.toCharArray());
+ }
+
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory
+ .getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(keyStore, trustStorePassword.toCharArray());
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ if (skipTrust) {
+ if (testMode) {
+ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {
+ }
+ } };
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, null);
+ } else {
+ // java root CA를 사용함 (jvm 설정에 추가되어야 함)
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory
+ .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init((KeyStore) null);
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ }
+ } else {
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory
+ .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(trustStore);
+
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ }
+
+ SSLParameters sslParameters = sslContext.getDefaultSSLParameters();
+ if (tlsVersions != null) {
+ sslParameters.setProtocols(tlsVersions);
+ }
+ if (cipherSuites != null) {
+ sslParameters.setCipherSuites(cipherSuites);
+ }
+
+ return sslContext;
+ } catch (Exception e) {
+ String errorMessage = String.format("Failed to create SSLContext type(Algorithm): %s", type);
+ throw new SSLContextCreateException(errorMessage, e);
+ }
+ }
+
+ public static SSLContext createMTLSContextFromContent(String type, String keyStoreBase64Content,
+ String keyStorePassword, String trustStoreBase64Content, String trustStorePassword, boolean skipTrust,
+ String[] tlsVersions, String[] cipherSuites) throws SSLContextCreateException {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(type);
+ byte[] keyBytes = Base64.getDecoder().decode(keyStoreBase64Content);
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(keyBytes)) {
+ keyStore.load(bis, keyStorePassword.toCharArray());
+ }
+
+ KeyStore trustStore = KeyStore.getInstance(type);
+ byte[] trustBytes = Base64.getDecoder().decode(trustStoreBase64Content);
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(trustBytes)) {
+ trustStore.load(bis, trustStorePassword.toCharArray());
+ }
+
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory
+ .getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ if (skipTrust) {
+ if (testMode) {
+ TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {
+ }
+ } };
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, null);
+ } else {
+ // java root CA를 사용함 (jvm 설정에 추가되어야 함)
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory
+ .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init((KeyStore) null);
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ }
+ } else {
+
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory
+ .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(trustStore);
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ }
+
+ SSLParameters sslParameters = sslContext.getDefaultSSLParameters();
+ if (tlsVersions != null) {
+ sslParameters.setProtocols(tlsVersions);
+ }
+ if (cipherSuites != null) {
+ sslParameters.setCipherSuites(cipherSuites);
+ }
+ return sslContext;
+ } catch (Exception e) {
+ String errorMessage = String.format("Failed to create SSLContext type(Algorithm): %s", type);
+ throw new SSLContextCreateException(errorMessage, e);
+ }
+ }
+
+ public static SSLContext createMTLSContextForJKS(String keyStorePath, String keyStorePassword,
+ String trustStorePath, String trustStorePassword, String[] tlsVersions, String[] cipherSuites)
+ throws SSLContextCreateException {
+ return createMTLSContextFromFile("JKS", keyStorePath, keyStorePassword, trustStorePath, trustStorePassword,
+ false, tlsVersions, cipherSuites);
+ }
+
+ public static SSLContext createMTLSContextForP12(String keyStorePath, String keyStorePassword,
+ String trustStorePath, String trustStorePassword, String[] tlsVersions, String[] cipherSuites)
+ throws SSLContextCreateException {
+ return createMTLSContextFromFile("PKCS12", keyStorePath, keyStorePassword, trustStorePath, trustStorePassword,
+ false, tlsVersions, cipherSuites);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/http/servlet/HttpAdapterLogServlet.java b/src/main/java/com/eactive/eai/adapter/http/servlet/HttpAdapterLogServlet.java
new file mode 100644
index 0000000..219d986
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/servlet/HttpAdapterLogServlet.java
@@ -0,0 +1,133 @@
+package com.eactive.eai.adapter.http.servlet;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.http.HttpMemoryLogger;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class HttpAdapterLogServlet extends HttpServlet {
+ final static SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+
+ String command = request.getContext();
+ if (command.lastIndexOf('/') == -1) {
+ command = "";
+ } else {
+ command = command.substring(command.indexOf('/')+1);
+ }
+
+ String result = "";
+
+ try {
+ if (command == null || "".equals(command) || "show".equals(command)) {
+ result = show(request.getParameter("adapter"));
+ } else if (command.startsWith("errorLog")) {
+ result = errorLog(request.getParameter("adapter"));
+ } else if (command.startsWith("txLog")) {
+ result = txLog(request.getParameter("adapter"));
+ } else {
+ response.setResponseCode(404);
+ return;
+ }
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ response.setContentType("text/html;charset=utf-8;");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+ }
+
+ final static String SCRIPT =
+ " \n";
+
+ public String show(String key) {
+ StringBuffer sb = new StringBuffer();
+ AdapterManager manager = AdapterManager.getInstance();
+ //List list = manager.getAllAdapterGroupNames();
+
+ HashMap hm = manager.getAllAdapterGroupVO();
+ List names = manager.getAllAdapterGroupNames();
+
+ sb.append(SCRIPT);
+ sb.append("http adapter log | keyword = " + key);
+ sb.append(" ");
+
+
+ for(String name : names){
+ AdapterGroupVO vo = hm.get(name);
+ if ("HTT".equals(vo.getType())){
+ if(name.indexOf(key) >=0){
+ sb.append("");
+ sb.append(String.format("ⓖ %-50s ", name)+"\n");
+ for(String adapter : vo.getAdapterNames()){
+ sb.append(String.format(" ⓐ %-50s ", adapter));
+ sb.append("txLog : "+HttpMemoryLogger.getTransactionCount(name+adapter)+" ");
+ sb.append("errorLog : "+HttpMemoryLogger.getErrorCount(name+adapter)+" ");
+ sb.append(" "+"\n");
+ }
+ sb.append(" "+"\n");
+
+ }
+ }
+
+ }
+
+ return sb.toString();
+ }
+ public String txLog(String name) {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append(SCRIPT);
+ sb.append("adapter ="+name+" ");
+ String[] logs = HttpMemoryLogger.getTransactions(name);
+ for (int i=logs.length-1; i>=0; i--) {
+ sb.append("");
+ sb.append("
");
+ sb.append(logs[i]);
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+
+ }
+ return sb.toString();
+ }
+ public String errorLog(String name) {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append(SCRIPT);
+ sb.append("adapter ="+name+" ");
+ String[] logs = HttpMemoryLogger.getErrors(name);
+ for (int i=logs.length-1; i>=0; i--) {
+ sb.append("");
+ sb.append("
");
+ sb.append(logs[i]);
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/http/util/HttpsGenerator.java b/src/main/java/com/eactive/eai/adapter/http/util/HttpsGenerator.java
new file mode 100644
index 0000000..ff7d6e8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/http/util/HttpsGenerator.java
@@ -0,0 +1,207 @@
+package com.eactive.eai.adapter.http.util;
+
+import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.httpclient.HostConfiguration;
+import org.apache.commons.httpclient.URI;
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.security.*;
+
+public class HttpsGenerator {
+
+ static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ // TODO 프라퍼티에서 관리하는걸로 수정 할것
+ private static final String PROP_KEYSTORE_PATH = "/certificate/keystore.p12";
+ private static final String PROP_KEYSTORE_PW = "elink-ssl";
+
+ public static HostConfiguration getHostConfiguration(String url) {
+
+ if(url.startsWith("https")){
+
+ URI uri;
+ try {
+ uri = new URI(url,true);
+ } catch (URIException e1) {
+ return null;
+ } catch (NullPointerException e1) {
+ return null;
+ }
+
+ Protocol httpsProtocol = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ HostConfiguration hc = new HostConfiguration();
+ try {
+ hc.setHost(uri.getHost(), uri.getPort(), httpsProtocol);
+ } catch (URIException e) {
+ return null;
+ }
+
+ return hc;
+
+ } else {
+ return null;
+ }
+ }
+
+ public static void setSSLTrust() {
+
+ Protocol httpsProtocol = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ Protocol.registerProtocol("https", httpsProtocol);
+ }
+
+ public static SSLContext createSSLContext(String keystoreFile, String keystorePass) {
+
+ SSLContext sslContext = null;
+ try {
+ sslContext = SSLContext.getInstance("TLS");
+ KeyManager[] keyManagers = createKeyManager(keystoreFile, keystorePass);
+
+ // Client Auth 지원하지 않음. - 추후 지원시 Comment 제거
+ // TrustManager[] trustManagers = createTrustManager(trustKey,trustPass);
+ TrustManager[] trustManagers = null;
+
+ if (null == keyManagers) return null;
+
+ sslContext.init(keyManagers, trustManagers, null);
+
+ } catch (NoSuchAlgorithmException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (KeyManagementException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+ }
+
+ return sslContext;
+ }
+
+ public static KeyManager[] createKeyManager(String keystoreFile, String password) {
+
+ KeyManager[] keyManagers = null;
+ File keyStoreFile = null;
+ if (StringUtils.isNotBlank(keystoreFile)) {
+ keyStoreFile = new File(keystoreFile);
+ } else {
+ Resource keystore = new ClassPathResource(PROP_KEYSTORE_PATH);
+ password = PROP_KEYSTORE_PW;
+ try {
+ keyStoreFile = keystore.getFile();
+ } catch (IOException e) {
+ logger.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ try {
+ FileInputStream keyStoreInputStream = new FileInputStream(keyStoreFile);
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ KeyStore keyStore = getKeyStore(keyStoreInputStream,password);
+
+ if (keyStore == null) return null;
+
+ keyManagerFactory.init(keyStore,password.toCharArray());
+ keyManagers = keyManagerFactory.getKeyManagers();
+
+ } catch (NoSuchAlgorithmException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (UnrecoverableKeyException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (KeyStoreException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (FileNotFoundException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+ }
+
+ return keyManagers;
+ }
+
+ public static TrustManager[] createTrustManager(String keystoreFile,String password) {
+
+ if (null == keystoreFile) return null;
+ TrustManager[] trustManager = null;
+
+ File keyStoreFile = new File(keystoreFile);
+
+ try {
+ FileInputStream keyStoreInputStream = new FileInputStream(keyStoreFile);
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ KeyStore trustStore = getKeyStore(keyStoreInputStream,password);
+
+ if (trustStore == null) return null;
+
+ trustManagerFactory.init(trustStore);
+ trustManager = trustManagerFactory.getTrustManagers();
+
+ } catch (NoSuchAlgorithmException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (KeyStoreException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (FileNotFoundException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+ }
+
+ return trustManager;
+ }
+
+ private static KeyStore getKeyStore(InputStream key, String password) {
+
+ KeyStore keyStore = null;
+
+ try {
+ keyStore = KeyStore.getInstance("JKS");
+ keyStore.load(key, password.toCharArray());
+
+ } catch (KeyStoreException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (NoSuchAlgorithmException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (IOException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+
+ } catch (java.security.cert.CertificateException e) {
+
+ logger.error(e.getMessage(), e);
+ return null;
+ }
+
+ return keyStore;
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/jtc/FmlTable.java b/src/main/java/com/eactive/eai/adapter/jtc/FmlTable.java
new file mode 100644
index 0000000..810d2d9
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/jtc/FmlTable.java
@@ -0,0 +1,2568 @@
+package com.eactive.eai.adapter.jtc;
+
+import tmax.jtc.util.TuxFieldTable;
+
+import java.util.Hashtable;
+
+
+/**
+* 1. 기능 : FML Field Table 정의 Class
+* 2. 처리 개요 :
+* * - FML 버퍼에 Field를 정의한 Class
+* 3. 주의사항
+*
+* @author :
+* @version : v 1.0.0
+* @see : 관련 기능을 참조
+* @since :
+* :
+*/
+public final class FmlTable
+ implements TuxFieldTable
+{
+ Hashtable nametofieldHashTable;
+ Hashtable fieldtonameHashTable;
+ /** number: 301 type: string */
+ public final static int STRING1 = 167772461;
+ /** number: 302 type: string */
+ public final static int STRING2 = 167772462;
+ /** number: 303 type: string */
+ public final static int STRING3 = 167772463;
+ /** number: 304 type: string */
+ public final static int STRING4 = 167772464;
+ /** number: 305 type: string */
+ public final static int STRING5 = 167772465;
+ /** number: 306 type: string */
+ public final static int STRING6 = 167772466;
+ /** number: 307 type: string */
+ public final static int STRING7 = 167772467;
+ /** number: 308 type: string */
+ public final static int STRING8 = 167772468;
+ /** number: 309 type: string */
+ public final static int STRING9 = 167772469;
+ /** number: 310 type: string */
+ public final static int STRING10 = 167772470;
+ /** number: 311 type: string */
+ public final static int STRING11 = 167772471;
+ /** number: 312 type: string */
+ public final static int STRING12 = 167772472;
+ /** number: 313 type: string */
+ public final static int STRING13 = 167772473;
+ /** number: 314 type: string */
+ public final static int STRING14 = 167772474;
+ /** number: 315 type: string */
+ public final static int STRING15 = 167772475;
+ /** number: 316 type: string */
+ public final static int STRING16 = 167772476;
+ /** number: 317 type: string */
+ public final static int STRING17 = 167772477;
+ /** number: 318 type: string */
+ public final static int STRING18 = 167772478;
+ /** number: 319 type: string */
+ public final static int STRING19 = 167772479;
+ /** number: 320 type: string */
+ public final static int STRING20 = 167772480;
+ /** number: 321 type: string */
+ public final static int STRING21 = 167772481;
+ /** number: 322 type: string */
+ public final static int STRING22 = 167772482;
+ /** number: 323 type: string */
+ public final static int STRING23 = 167772483;
+ /** number: 324 type: string */
+ public final static int STRING24 = 167772484;
+ /** number: 325 type: string */
+ public final static int STRING25 = 167772485;
+ /** number: 326 type: string */
+ public final static int STRING26 = 167772486;
+ /** number: 327 type: string */
+ public final static int STRING27 = 167772487;
+ /** number: 328 type: string */
+ public final static int STRING28 = 167772488;
+ /** number: 329 type: string */
+ public final static int STRING29 = 167772489;
+ /** number: 330 type: string */
+ public final static int STRING30 = 167772490;
+ /** number: 331 type: string */
+ public final static int STRING31 = 167772491;
+ /** number: 332 type: string */
+ public final static int STRING32 = 167772492;
+ /** number: 333 type: string */
+ public final static int STRING33 = 167772493;
+ /** number: 334 type: string */
+ public final static int STRING34 = 167772494;
+ /** number: 335 type: string */
+ public final static int STRING35 = 167772495;
+ /** number: 336 type: string */
+ public final static int STRING36 = 167772496;
+ /** number: 337 type: string */
+ public final static int STRING37 = 167772497;
+ /** number: 338 type: string */
+ public final static int STRING38 = 167772498;
+ /** number: 339 type: string */
+ public final static int STRING39 = 167772499;
+ /** number: 340 type: string */
+ public final static int STRING40 = 167772500;
+ /** number: 341 type: string */
+ public final static int STRING41 = 167772501;
+ /** number: 342 type: string */
+ public final static int STRING42 = 167772502;
+ /** number: 343 type: string */
+ public final static int STRING43 = 167772503;
+ /** number: 344 type: string */
+ public final static int STRING44 = 167772504;
+ /** number: 345 type: string */
+ public final static int STRING45 = 167772505;
+ /** number: 346 type: string */
+ public final static int STRING46 = 167772506;
+ /** number: 347 type: string */
+ public final static int STRING47 = 167772507;
+ /** number: 348 type: string */
+ public final static int STRING48 = 167772508;
+ /** number: 349 type: string */
+ public final static int STRING49 = 167772509;
+ /** number: 350 type: string */
+ public final static int STRING50 = 167772510;
+ /** number: 351 type: string */
+ public final static int STRING51 = 167772511;
+ /** number: 352 type: string */
+ public final static int STRING52 = 167772512;
+ /** number: 353 type: string */
+ public final static int STRING53 = 167772513;
+ /** number: 354 type: string */
+ public final static int STRING54 = 167772514;
+ /** number: 355 type: string */
+ public final static int STRING55 = 167772515;
+ /** number: 356 type: string */
+ public final static int STRING56 = 167772516;
+ /** number: 357 type: string */
+ public final static int STRING57 = 167772517;
+ /** number: 358 type: string */
+ public final static int STRING58 = 167772518;
+ /** number: 359 type: string */
+ public final static int STRING59 = 167772519;
+ /** number: 360 type: string */
+ public final static int STRING60 = 167772520;
+ /** number: 361 type: string */
+ public final static int STRING61 = 167772521;
+ /** number: 362 type: string */
+ public final static int STRING62 = 167772522;
+ /** number: 363 type: string */
+ public final static int STRING63 = 167772523;
+ /** number: 364 type: string */
+ public final static int STRING64 = 167772524;
+ /** number: 365 type: string */
+ public final static int STRING65 = 167772525;
+ /** number: 366 type: string */
+ public final static int STRING66 = 167772526;
+ /** number: 367 type: string */
+ public final static int STRING67 = 167772527;
+ /** number: 368 type: string */
+ public final static int STRING68 = 167772528;
+ /** number: 369 type: string */
+ public final static int STRING69 = 167772529;
+ /** number: 370 type: string */
+ public final static int STRING70 = 167772530;
+ /** number: 371 type: string */
+ public final static int STRING71 = 167772531;
+ /** number: 372 type: string */
+ public final static int STRING72 = 167772532;
+ /** number: 373 type: string */
+ public final static int STRING73 = 167772533;
+ /** number: 374 type: string */
+ public final static int STRING74 = 167772534;
+ /** number: 375 type: string */
+ public final static int STRING75 = 167772535;
+ /** number: 376 type: string */
+ public final static int STRING76 = 167772536;
+ /** number: 377 type: string */
+ public final static int STRING77 = 167772537;
+ /** number: 378 type: string */
+ public final static int STRING78 = 167772538;
+ /** number: 379 type: string */
+ public final static int STRING79 = 167772539;
+ /** number: 380 type: string */
+ public final static int STRING80 = 167772540;
+ /** number: 381 type: string */
+ public final static int STRING81 = 167772541;
+ /** number: 382 type: string */
+ public final static int STRING82 = 167772542;
+ /** number: 383 type: string */
+ public final static int STRING83 = 167772543;
+ /** number: 384 type: string */
+ public final static int STRING84 = 167772544;
+ /** number: 385 type: string */
+ public final static int STRING85 = 167772545;
+ /** number: 386 type: string */
+ public final static int STRING86 = 167772546;
+ /** number: 387 type: string */
+ public final static int STRING87 = 167772547;
+ /** number: 388 type: string */
+ public final static int STRING88 = 167772548;
+ /** number: 389 type: string */
+ public final static int STRING89 = 167772549;
+ /** number: 390 type: string */
+ public final static int STRING90 = 167772550;
+ /** number: 391 type: string */
+ public final static int STRING91 = 167772551;
+ /** number: 392 type: string */
+ public final static int STRING92 = 167772552;
+ /** number: 393 type: string */
+ public final static int STRING93 = 167772553;
+ /** number: 394 type: string */
+ public final static int STRING94 = 167772554;
+ /** number: 395 type: string */
+ public final static int STRING95 = 167772555;
+ /** number: 396 type: string */
+ public final static int STRING96 = 167772556;
+ /** number: 397 type: string */
+ public final static int STRING97 = 167772557;
+ /** number: 398 type: string */
+ public final static int STRING98 = 167772558;
+ /** number: 399 type: string */
+ public final static int STRING99 = 167772559;
+ /** number: 400 type: string */
+ public final static int STRING100 = 167772560;
+ /** number: 401 type: string */
+ public final static int STRING101 = 167772561;
+ /** number: 402 type: string */
+ public final static int STRING102 = 167772562;
+ /** number: 403 type: string */
+ public final static int STRING103 = 167772563;
+ /** number: 404 type: string */
+ public final static int STRING104 = 167772564;
+ /** number: 405 type: string */
+ public final static int STRING105 = 167772565;
+ /** number: 406 type: string */
+ public final static int STRING106 = 167772566;
+ /** number: 407 type: string */
+ public final static int STRING107 = 167772567;
+ /** number: 408 type: string */
+ public final static int STRING108 = 167772568;
+ /** number: 409 type: string */
+ public final static int STRING109 = 167772569;
+ /** number: 410 type: string */
+ public final static int STRING110 = 167772570;
+ /** number: 411 type: string */
+ public final static int STRING111 = 167772571;
+ /** number: 412 type: string */
+ public final static int STRING112 = 167772572;
+ /** number: 413 type: string */
+ public final static int STRING113 = 167772573;
+ /** number: 414 type: string */
+ public final static int STRING114 = 167772574;
+ /** number: 415 type: string */
+ public final static int STRING115 = 167772575;
+ /** number: 416 type: string */
+ public final static int STRING116 = 167772576;
+ /** number: 417 type: string */
+ public final static int STRING117 = 167772577;
+ /** number: 418 type: string */
+ public final static int STRING118 = 167772578;
+ /** number: 419 type: string */
+ public final static int STRING119 = 167772579;
+ /** number: 420 type: string */
+ public final static int STRING120 = 167772580;
+ /** number: 421 type: string */
+ public final static int STRING121 = 167772581;
+ /** number: 422 type: string */
+ public final static int STRING122 = 167772582;
+ /** number: 423 type: string */
+ public final static int STRING123 = 167772583;
+ /** number: 424 type: string */
+ public final static int STRING124 = 167772584;
+ /** number: 425 type: string */
+ public final static int STRING125 = 167772585;
+ /** number: 426 type: string */
+ public final static int STRING126 = 167772586;
+ /** number: 427 type: string */
+ public final static int STRING127 = 167772587;
+ /** number: 428 type: string */
+ public final static int STRING128 = 167772588;
+ /** number: 429 type: string */
+ public final static int STRING129 = 167772589;
+ /** number: 430 type: string */
+ public final static int STRING130 = 167772590;
+ /** number: 431 type: string */
+ public final static int STRING131 = 167772591;
+ /** number: 432 type: string */
+ public final static int STRING132 = 167772592;
+ /** number: 433 type: string */
+ public final static int STRING133 = 167772593;
+ /** number: 434 type: string */
+ public final static int STRING134 = 167772594;
+ /** number: 435 type: string */
+ public final static int STRING135 = 167772595;
+ /** number: 436 type: string */
+ public final static int STRING136 = 167772596;
+ /** number: 437 type: string */
+ public final static int STRING137 = 167772597;
+ /** number: 438 type: string */
+ public final static int STRING138 = 167772598;
+ /** number: 439 type: string */
+ public final static int STRING139 = 167772599;
+ /** number: 440 type: string */
+ public final static int STRING140 = 167772600;
+ /** number: 441 type: string */
+ public final static int STRING141 = 167772601;
+ /** number: 442 type: string */
+ public final static int STRING142 = 167772602;
+ /** number: 443 type: string */
+ public final static int STRING143 = 167772603;
+ /** number: 444 type: string */
+ public final static int STRING144 = 167772604;
+ /** number: 445 type: string */
+ public final static int STRING145 = 167772605;
+ /** number: 446 type: string */
+ public final static int STRING146 = 167772606;
+ /** number: 447 type: string */
+ public final static int STRING147 = 167772607;
+ /** number: 448 type: string */
+ public final static int STRING148 = 167772608;
+ /** number: 449 type: string */
+ public final static int STRING149 = 167772609;
+ /** number: 450 type: string */
+ public final static int STRING150 = 167772610;
+ /** number: 451 type: string */
+ public final static int STRING151 = 167772611;
+ /** number: 452 type: string */
+ public final static int STRING152 = 167772612;
+ /** number: 453 type: string */
+ public final static int STRING153 = 167772613;
+ /** number: 454 type: string */
+ public final static int STRING154 = 167772614;
+ /** number: 455 type: string */
+ public final static int STRING155 = 167772615;
+ /** number: 456 type: string */
+ public final static int STRING156 = 167772616;
+ /** number: 457 type: string */
+ public final static int STRING157 = 167772617;
+ /** number: 458 type: string */
+ public final static int STRING158 = 167772618;
+ /** number: 459 type: string */
+ public final static int STRING159 = 167772619;
+ /** number: 460 type: string */
+ public final static int STRING160 = 167772620;
+ /** number: 461 type: string */
+ public final static int STRING161 = 167772621;
+ /** number: 462 type: string */
+ public final static int STRING162 = 167772622;
+ /** number: 463 type: string */
+ public final static int STRING163 = 167772623;
+ /** number: 464 type: string */
+ public final static int STRING164 = 167772624;
+ /** number: 465 type: string */
+ public final static int STRING165 = 167772625;
+ /** number: 466 type: string */
+ public final static int STRING166 = 167772626;
+ /** number: 467 type: string */
+ public final static int STRING167 = 167772627;
+ /** number: 468 type: string */
+ public final static int STRING168 = 167772628;
+ /** number: 469 type: string */
+ public final static int STRING169 = 167772629;
+ /** number: 470 type: string */
+ public final static int STRING170 = 167772630;
+ /** number: 471 type: string */
+ public final static int STRING171 = 167772631;
+ /** number: 472 type: string */
+ public final static int STRING172 = 167772632;
+ /** number: 473 type: string */
+ public final static int STRING173 = 167772633;
+ /** number: 474 type: string */
+ public final static int STRING174 = 167772634;
+ /** number: 475 type: string */
+ public final static int STRING175 = 167772635;
+ /** number: 476 type: string */
+ public final static int STRING176 = 167772636;
+ /** number: 477 type: string */
+ public final static int STRING177 = 167772637;
+ /** number: 478 type: string */
+ public final static int STRING178 = 167772638;
+ /** number: 479 type: string */
+ public final static int STRING179 = 167772639;
+ /** number: 480 type: string */
+ public final static int STRING180 = 167772640;
+ /** number: 481 type: string */
+ public final static int STRING181 = 167772641;
+ /** number: 482 type: string */
+ public final static int STRING182 = 167772642;
+ /** number: 483 type: string */
+ public final static int STRING183 = 167772643;
+ /** number: 484 type: string */
+ public final static int STRING184 = 167772644;
+ /** number: 485 type: string */
+ public final static int STRING185 = 167772645;
+ /** number: 486 type: string */
+ public final static int STRING186 = 167772646;
+ /** number: 487 type: string */
+ public final static int STRING187 = 167772647;
+ /** number: 488 type: string */
+ public final static int STRING188 = 167772648;
+ /** number: 489 type: string */
+ public final static int STRING189 = 167772649;
+ /** number: 490 type: string */
+ public final static int STRING190 = 167772650;
+ /** number: 491 type: string */
+ public final static int STRING191 = 167772651;
+ /** number: 492 type: string */
+ public final static int STRING192 = 167772652;
+ /** number: 493 type: string */
+ public final static int STRING193 = 167772653;
+ /** number: 494 type: string */
+ public final static int STRING194 = 167772654;
+ /** number: 495 type: string */
+ public final static int STRING195 = 167772655;
+ /** number: 496 type: string */
+ public final static int STRING196 = 167772656;
+ /** number: 497 type: string */
+ public final static int STRING197 = 167772657;
+ /** number: 498 type: string */
+ public final static int STRING198 = 167772658;
+ /** number: 499 type: string */
+ public final static int STRING199 = 167772659;
+ /** number: 500 type: string */
+ public final static int STRING200 = 167772660;
+ /** number: 501 type: long */
+ public final static int LONG1 = 33554933;
+ /** number: 502 type: long */
+ public final static int LONG2 = 33554934;
+ /** number: 503 type: long */
+ public final static int LONG3 = 33554935;
+ /** number: 504 type: long */
+ public final static int LONG4 = 33554936;
+ /** number: 505 type: long */
+ public final static int LONG5 = 33554937;
+ /** number: 506 type: long */
+ public final static int LONG6 = 33554938;
+ /** number: 507 type: long */
+ public final static int LONG7 = 33554939;
+ /** number: 508 type: long */
+ public final static int LONG8 = 33554940;
+ /** number: 509 type: long */
+ public final static int LONG9 = 33554941;
+ /** number: 510 type: long */
+ public final static int LONG10 = 33554942;
+ /** number: 511 type: long */
+ public final static int LONG11 = 33554943;
+ /** number: 512 type: long */
+ public final static int LONG12 = 33554944;
+ /** number: 513 type: long */
+ public final static int LONG13 = 33554945;
+ /** number: 514 type: long */
+ public final static int LONG14 = 33554946;
+ /** number: 515 type: long */
+ public final static int LONG15 = 33554947;
+ /** number: 516 type: long */
+ public final static int LONG16 = 33554948;
+ /** number: 517 type: long */
+ public final static int LONG17 = 33554949;
+ /** number: 518 type: long */
+ public final static int LONG18 = 33554950;
+ /** number: 519 type: long */
+ public final static int LONG19 = 33554951;
+ /** number: 520 type: long */
+ public final static int LONG20 = 33554952;
+ /** number: 521 type: long */
+ public final static int LONG21 = 33554953;
+ /** number: 522 type: long */
+ public final static int LONG22 = 33554954;
+ /** number: 523 type: long */
+ public final static int LONG23 = 33554955;
+ /** number: 524 type: long */
+ public final static int LONG24 = 33554956;
+ /** number: 525 type: long */
+ public final static int LONG25 = 33554957;
+ /** number: 526 type: long */
+ public final static int LONG26 = 33554958;
+ /** number: 527 type: long */
+ public final static int LONG27 = 33554959;
+ /** number: 528 type: long */
+ public final static int LONG28 = 33554960;
+ /** number: 529 type: long */
+ public final static int LONG29 = 33554961;
+ /** number: 530 type: long */
+ public final static int LONG30 = 33554962;
+ /** number: 531 type: long */
+ public final static int LONG31 = 33554963;
+ /** number: 532 type: long */
+ public final static int LONG32 = 33554964;
+ /** number: 533 type: long */
+ public final static int LONG33 = 33554965;
+ /** number: 534 type: long */
+ public final static int LONG34 = 33554966;
+ /** number: 535 type: long */
+ public final static int LONG35 = 33554967;
+ /** number: 536 type: long */
+ public final static int LONG36 = 33554968;
+ /** number: 537 type: long */
+ public final static int LONG37 = 33554969;
+ /** number: 538 type: long */
+ public final static int LONG38 = 33554970;
+ /** number: 539 type: long */
+ public final static int LONG39 = 33554971;
+ /** number: 540 type: long */
+ public final static int LONG40 = 33554972;
+ /** number: 541 type: long */
+ public final static int LONG41 = 33554973;
+ /** number: 542 type: long */
+ public final static int LONG42 = 33554974;
+ /** number: 543 type: long */
+ public final static int LONG43 = 33554975;
+ /** number: 544 type: long */
+ public final static int LONG44 = 33554976;
+ /** number: 545 type: long */
+ public final static int LONG45 = 33554977;
+ /** number: 546 type: long */
+ public final static int LONG46 = 33554978;
+ /** number: 547 type: long */
+ public final static int LONG47 = 33554979;
+ /** number: 548 type: long */
+ public final static int LONG48 = 33554980;
+ /** number: 549 type: long */
+ public final static int LONG49 = 33554981;
+ /** number: 550 type: long */
+ public final static int LONG50 = 33554982;
+ /** number: 551 type: long */
+ public final static int LONG51 = 33554983;
+ /** number: 552 type: long */
+ public final static int LONG52 = 33554984;
+ /** number: 553 type: long */
+ public final static int LONG53 = 33554985;
+ /** number: 554 type: long */
+ public final static int LONG54 = 33554986;
+ /** number: 555 type: long */
+ public final static int LONG55 = 33554987;
+ /** number: 556 type: long */
+ public final static int LONG56 = 33554988;
+ /** number: 557 type: long */
+ public final static int LONG57 = 33554989;
+ /** number: 558 type: long */
+ public final static int LONG58 = 33554990;
+ /** number: 559 type: long */
+ public final static int LONG59 = 33554991;
+ /** number: 560 type: long */
+ public final static int LONG60 = 33554992;
+ /** number: 561 type: long */
+ public final static int LONG61 = 33554993;
+ /** number: 562 type: long */
+ public final static int LONG62 = 33554994;
+ /** number: 563 type: long */
+ public final static int LONG63 = 33554995;
+ /** number: 564 type: long */
+ public final static int LONG64 = 33554996;
+ /** number: 565 type: long */
+ public final static int LONG65 = 33554997;
+ /** number: 566 type: long */
+ public final static int LONG66 = 33554998;
+ /** number: 567 type: long */
+ public final static int LONG67 = 33554999;
+ /** number: 568 type: long */
+ public final static int LONG68 = 33555000;
+ /** number: 569 type: long */
+ public final static int LONG69 = 33555001;
+ /** number: 570 type: long */
+ public final static int LONG70 = 33555002;
+ /** number: 571 type: long */
+ public final static int LONG71 = 33555003;
+ /** number: 572 type: long */
+ public final static int LONG72 = 33555004;
+ /** number: 573 type: long */
+ public final static int LONG73 = 33555005;
+ /** number: 574 type: long */
+ public final static int LONG74 = 33555006;
+ /** number: 575 type: long */
+ public final static int LONG75 = 33555007;
+ /** number: 576 type: long */
+ public final static int LONG76 = 33555008;
+ /** number: 577 type: long */
+ public final static int LONG77 = 33555009;
+ /** number: 578 type: long */
+ public final static int LONG78 = 33555010;
+ /** number: 579 type: long */
+ public final static int LONG79 = 33555011;
+ /** number: 580 type: long */
+ public final static int LONG80 = 33555012;
+ /** number: 581 type: long */
+ public final static int LONG81 = 33555013;
+ /** number: 582 type: long */
+ public final static int LONG82 = 33555014;
+ /** number: 583 type: long */
+ public final static int LONG83 = 33555015;
+ /** number: 584 type: long */
+ public final static int LONG84 = 33555016;
+ /** number: 585 type: long */
+ public final static int LONG85 = 33555017;
+ /** number: 586 type: long */
+ public final static int LONG86 = 33555018;
+ /** number: 587 type: long */
+ public final static int LONG87 = 33555019;
+ /** number: 588 type: long */
+ public final static int LONG88 = 33555020;
+ /** number: 589 type: long */
+ public final static int LONG89 = 33555021;
+ /** number: 590 type: long */
+ public final static int LONG90 = 33555022;
+ /** number: 591 type: long */
+ public final static int LONG91 = 33555023;
+ /** number: 592 type: long */
+ public final static int LONG92 = 33555024;
+ /** number: 593 type: long */
+ public final static int LONG93 = 33555025;
+ /** number: 594 type: long */
+ public final static int LONG94 = 33555026;
+ /** number: 595 type: long */
+ public final static int LONG95 = 33555027;
+ /** number: 596 type: long */
+ public final static int LONG96 = 33555028;
+ /** number: 597 type: long */
+ public final static int LONG97 = 33555029;
+ /** number: 598 type: long */
+ public final static int LONG98 = 33555030;
+ /** number: 599 type: long */
+ public final static int LONG99 = 33555031;
+ /** number: 600 type: long */
+ public final static int LONG100 = 33555032;
+ /** number: 601 type: double */
+ public final static int DOUBLE1 = 134218329;
+ /** number: 602 type: double */
+ public final static int DOUBLE2 = 134218330;
+ /** number: 603 type: double */
+ public final static int DOUBLE3 = 134218331;
+ /** number: 604 type: double */
+ public final static int DOUBLE4 = 134218332;
+ /** number: 605 type: double */
+ public final static int DOUBLE5 = 134218333;
+ /** number: 606 type: double */
+ public final static int DOUBLE6 = 134218334;
+ /** number: 607 type: double */
+ public final static int DOUBLE7 = 134218335;
+ /** number: 608 type: double */
+ public final static int DOUBLE8 = 134218336;
+ /** number: 609 type: double */
+ public final static int DOUBLE9 = 134218337;
+ /** number: 610 type: double */
+ public final static int DOUBLE10 = 134218338;
+ /** number: 611 type: double */
+ public final static int DOUBLE11 = 134218339;
+ /** number: 612 type: double */
+ public final static int DOUBLE12 = 134218340;
+ /** number: 613 type: double */
+ public final static int DOUBLE13 = 134218341;
+ /** number: 614 type: double */
+ public final static int DOUBLE14 = 134218342;
+ /** number: 615 type: double */
+ public final static int DOUBLE15 = 134218343;
+ /** number: 616 type: double */
+ public final static int DOUBLE16 = 134218344;
+ /** number: 617 type: double */
+ public final static int DOUBLE17 = 134218345;
+ /** number: 618 type: double */
+ public final static int DOUBLE18 = 134218346;
+ /** number: 619 type: double */
+ public final static int DOUBLE19 = 134218347;
+ /** number: 620 type: double */
+ public final static int DOUBLE20 = 134218348;
+ /** number: 621 type: double */
+ public final static int DOUBLE21 = 134218349;
+ /** number: 622 type: double */
+ public final static int DOUBLE22 = 134218350;
+ /** number: 623 type: double */
+ public final static int DOUBLE23 = 134218351;
+ /** number: 624 type: double */
+ public final static int DOUBLE24 = 134218352;
+ /** number: 625 type: double */
+ public final static int DOUBLE25 = 134218353;
+ /** number: 626 type: double */
+ public final static int DOUBLE26 = 134218354;
+ /** number: 627 type: double */
+ public final static int DOUBLE27 = 134218355;
+ /** number: 628 type: double */
+ public final static int DOUBLE28 = 134218356;
+ /** number: 629 type: double */
+ public final static int DOUBLE29 = 134218357;
+ /** number: 630 type: double */
+ public final static int DOUBLE30 = 134218358;
+ /** number: 631 type: double */
+ public final static int DOUBLE31 = 134218359;
+ /** number: 632 type: double */
+ public final static int DOUBLE32 = 134218360;
+ /** number: 633 type: double */
+ public final static int DOUBLE33 = 134218361;
+ /** number: 634 type: double */
+ public final static int DOUBLE34 = 134218362;
+ /** number: 635 type: double */
+ public final static int DOUBLE35 = 134218363;
+ /** number: 636 type: double */
+ public final static int DOUBLE36 = 134218364;
+ /** number: 637 type: double */
+ public final static int DOUBLE37 = 134218365;
+ /** number: 638 type: double */
+ public final static int DOUBLE38 = 134218366;
+ /** number: 639 type: double */
+ public final static int DOUBLE39 = 134218367;
+ /** number: 640 type: double */
+ public final static int DOUBLE40 = 134218368;
+ /** number: 641 type: double */
+ public final static int DOUBLE41 = 134218369;
+ /** number: 642 type: double */
+ public final static int DOUBLE42 = 134218370;
+ /** number: 643 type: double */
+ public final static int DOUBLE43 = 134218371;
+ /** number: 644 type: double */
+ public final static int DOUBLE44 = 134218372;
+ /** number: 645 type: double */
+ public final static int DOUBLE45 = 134218373;
+ /** number: 646 type: double */
+ public final static int DOUBLE46 = 134218374;
+ /** number: 647 type: double */
+ public final static int DOUBLE47 = 134218375;
+ /** number: 648 type: double */
+ public final static int DOUBLE48 = 134218376;
+ /** number: 649 type: double */
+ public final static int DOUBLE49 = 134218377;
+ /** number: 650 type: double */
+ public final static int DOUBLE50 = 134218378;
+ /** number: 651 type: double */
+ public final static int DOUBLE51 = 134218379;
+ /** number: 652 type: double */
+ public final static int DOUBLE52 = 134218380;
+ /** number: 653 type: double */
+ public final static int DOUBLE53 = 134218381;
+ /** number: 654 type: double */
+ public final static int DOUBLE54 = 134218382;
+ /** number: 655 type: double */
+ public final static int DOUBLE55 = 134218383;
+ /** number: 656 type: double */
+ public final static int DOUBLE56 = 134218384;
+ /** number: 657 type: double */
+ public final static int DOUBLE57 = 134218385;
+ /** number: 658 type: double */
+ public final static int DOUBLE58 = 134218386;
+ /** number: 659 type: double */
+ public final static int DOUBLE59 = 134218387;
+ /** number: 660 type: double */
+ public final static int DOUBLE60 = 134218388;
+ /** number: 661 type: double */
+ public final static int DOUBLE61 = 134218389;
+ /** number: 662 type: double */
+ public final static int DOUBLE62 = 134218390;
+ /** number: 663 type: double */
+ public final static int DOUBLE63 = 134218391;
+ /** number: 664 type: double */
+ public final static int DOUBLE64 = 134218392;
+ /** number: 665 type: double */
+ public final static int DOUBLE65 = 134218393;
+ /** number: 666 type: double */
+ public final static int DOUBLE66 = 134218394;
+ /** number: 667 type: double */
+ public final static int DOUBLE67 = 134218395;
+ /** number: 668 type: double */
+ public final static int DOUBLE68 = 134218396;
+ /** number: 669 type: double */
+ public final static int DOUBLE69 = 134218397;
+ /** number: 670 type: double */
+ public final static int DOUBLE70 = 134218398;
+ /** number: 671 type: double */
+ public final static int DOUBLE71 = 134218399;
+ /** number: 672 type: double */
+ public final static int DOUBLE72 = 134218400;
+ /** number: 673 type: double */
+ public final static int DOUBLE73 = 134218401;
+ /** number: 674 type: double */
+ public final static int DOUBLE74 = 134218402;
+ /** number: 675 type: double */
+ public final static int DOUBLE75 = 134218403;
+ /** number: 676 type: double */
+ public final static int DOUBLE76 = 134218404;
+ /** number: 677 type: double */
+ public final static int DOUBLE77 = 134218405;
+ /** number: 678 type: double */
+ public final static int DOUBLE78 = 134218406;
+ /** number: 679 type: double */
+ public final static int DOUBLE79 = 134218407;
+ /** number: 680 type: double */
+ public final static int DOUBLE80 = 134218408;
+ /** number: 681 type: double */
+ public final static int DOUBLE81 = 134218409;
+ /** number: 682 type: double */
+ public final static int DOUBLE82 = 134218410;
+ /** number: 683 type: double */
+ public final static int DOUBLE83 = 134218411;
+ /** number: 684 type: double */
+ public final static int DOUBLE84 = 134218412;
+ /** number: 685 type: double */
+ public final static int DOUBLE85 = 134218413;
+ /** number: 686 type: double */
+ public final static int DOUBLE86 = 134218414;
+ /** number: 687 type: double */
+ public final static int DOUBLE87 = 134218415;
+ /** number: 688 type: double */
+ public final static int DOUBLE88 = 134218416;
+ /** number: 689 type: double */
+ public final static int DOUBLE89 = 134218417;
+ /** number: 690 type: double */
+ public final static int DOUBLE90 = 134218418;
+ /** number: 691 type: double */
+ public final static int DOUBLE91 = 134218419;
+ /** number: 692 type: double */
+ public final static int DOUBLE92 = 134218420;
+ /** number: 693 type: double */
+ public final static int DOUBLE93 = 134218421;
+ /** number: 694 type: double */
+ public final static int DOUBLE94 = 134218422;
+ /** number: 695 type: double */
+ public final static int DOUBLE95 = 134218423;
+ /** number: 696 type: double */
+ public final static int DOUBLE96 = 134218424;
+ /** number: 697 type: double */
+ public final static int DOUBLE97 = 134218425;
+ /** number: 698 type: double */
+ public final static int DOUBLE98 = 134218426;
+ /** number: 699 type: double */
+ public final static int DOUBLE99 = 134218427;
+ /** number: 700 type: double */
+ public final static int DOUBLE100 = 134218428;
+ /** number: 701 type: double */
+ public final static int DOUBLE101 = 134218429;
+ /** number: 702 type: double */
+ public final static int DOUBLE102 = 134218430;
+ /** number: 703 type: double */
+ public final static int DOUBLE103 = 134218431;
+ /** number: 704 type: double */
+ public final static int DOUBLE104 = 134218432;
+ /** number: 705 type: double */
+ public final static int DOUBLE105 = 134218433;
+ /** number: 706 type: double */
+ public final static int DOUBLE106 = 134218434;
+ /** number: 707 type: double */
+ public final static int DOUBLE107 = 134218435;
+ /** number: 708 type: double */
+ public final static int DOUBLE108 = 134218436;
+ /** number: 709 type: double */
+ public final static int DOUBLE109 = 134218437;
+ /** number: 710 type: double */
+ public final static int DOUBLE110 = 134218438;
+ /** number: 711 type: double */
+ public final static int DOUBLE111 = 134218439;
+ /** number: 712 type: double */
+ public final static int DOUBLE112 = 134218440;
+ /** number: 713 type: double */
+ public final static int DOUBLE113 = 134218441;
+ /** number: 714 type: double */
+ public final static int DOUBLE114 = 134218442;
+ /** number: 715 type: double */
+ public final static int DOUBLE115 = 134218443;
+ /** number: 716 type: double */
+ public final static int DOUBLE116 = 134218444;
+ /** number: 717 type: double */
+ public final static int DOUBLE117 = 134218445;
+ /** number: 718 type: double */
+ public final static int DOUBLE118 = 134218446;
+ /** number: 719 type: double */
+ public final static int DOUBLE119 = 134218447;
+ /** number: 720 type: double */
+ public final static int DOUBLE120 = 134218448;
+ /** number: 721 type: double */
+ public final static int DOUBLE121 = 134218449;
+ /** number: 722 type: double */
+ public final static int DOUBLE122 = 134218450;
+ /** number: 723 type: double */
+ public final static int DOUBLE123 = 134218451;
+ /** number: 724 type: double */
+ public final static int DOUBLE124 = 134218452;
+ /** number: 725 type: double */
+ public final static int DOUBLE125 = 134218453;
+ /** number: 726 type: double */
+ public final static int DOUBLE126 = 134218454;
+ /** number: 727 type: double */
+ public final static int DOUBLE127 = 134218455;
+ /** number: 728 type: double */
+ public final static int DOUBLE128 = 134218456;
+ /** number: 729 type: double */
+ public final static int DOUBLE129 = 134218457;
+ /** number: 730 type: double */
+ public final static int DOUBLE130 = 134218458;
+ /** number: 731 type: double */
+ public final static int DOUBLE131 = 134218459;
+ /** number: 732 type: double */
+ public final static int DOUBLE132 = 134218460;
+ /** number: 733 type: double */
+ public final static int DOUBLE133 = 134218461;
+ /** number: 734 type: double */
+ public final static int DOUBLE134 = 134218462;
+ /** number: 735 type: double */
+ public final static int DOUBLE135 = 134218463;
+ /** number: 736 type: double */
+ public final static int DOUBLE136 = 134218464;
+ /** number: 737 type: double */
+ public final static int DOUBLE137 = 134218465;
+ /** number: 738 type: double */
+ public final static int DOUBLE138 = 134218466;
+ /** number: 739 type: double */
+ public final static int DOUBLE139 = 134218467;
+ /** number: 740 type: double */
+ public final static int DOUBLE140 = 134218468;
+ /** number: 741 type: double */
+ public final static int DOUBLE141 = 134218469;
+ /** number: 742 type: double */
+ public final static int DOUBLE142 = 134218470;
+ /** number: 743 type: double */
+ public final static int DOUBLE143 = 134218471;
+ /** number: 744 type: double */
+ public final static int DOUBLE144 = 134218472;
+ /** number: 745 type: double */
+ public final static int DOUBLE145 = 134218473;
+ /** number: 746 type: double */
+ public final static int DOUBLE146 = 134218474;
+ /** number: 747 type: double */
+ public final static int DOUBLE147 = 134218475;
+ /** number: 748 type: double */
+ public final static int DOUBLE148 = 134218476;
+ /** number: 749 type: double */
+ public final static int DOUBLE149 = 134218477;
+ /** number: 750 type: double */
+ public final static int DOUBLE150 = 134218478;
+ /** number: 751 type: double */
+ public final static int DOUBLE151 = 134218479;
+ /** number: 752 type: double */
+ public final static int DOUBLE152 = 134218480;
+ /** number: 753 type: double */
+ public final static int DOUBLE153 = 134218481;
+ /** number: 754 type: double */
+ public final static int DOUBLE154 = 134218482;
+ /** number: 755 type: double */
+ public final static int DOUBLE155 = 134218483;
+ /** number: 756 type: double */
+ public final static int DOUBLE156 = 134218484;
+ /** number: 757 type: double */
+ public final static int DOUBLE157 = 134218485;
+ /** number: 758 type: double */
+ public final static int DOUBLE158 = 134218486;
+ /** number: 759 type: double */
+ public final static int DOUBLE159 = 134218487;
+ /** number: 760 type: double */
+ public final static int DOUBLE160 = 134218488;
+ /** number: 761 type: double */
+ public final static int DOUBLE161 = 134218489;
+ /** number: 762 type: double */
+ public final static int DOUBLE162 = 134218490;
+ /** number: 763 type: double */
+ public final static int DOUBLE163 = 134218491;
+ /** number: 764 type: double */
+ public final static int DOUBLE164 = 134218492;
+ /** number: 765 type: double */
+ public final static int DOUBLE165 = 134218493;
+ /** number: 766 type: double */
+ public final static int DOUBLE166 = 134218494;
+ /** number: 767 type: double */
+ public final static int DOUBLE167 = 134218495;
+ /** number: 768 type: double */
+ public final static int DOUBLE168 = 134218496;
+ /** number: 769 type: double */
+ public final static int DOUBLE169 = 134218497;
+ /** number: 770 type: double */
+ public final static int DOUBLE170 = 134218498;
+ /** number: 771 type: double */
+ public final static int DOUBLE171 = 134218499;
+ /** number: 772 type: double */
+ public final static int DOUBLE172 = 134218500;
+ /** number: 773 type: double */
+ public final static int DOUBLE173 = 134218501;
+ /** number: 774 type: double */
+ public final static int DOUBLE174 = 134218502;
+ /** number: 775 type: double */
+ public final static int DOUBLE175 = 134218503;
+ /** number: 776 type: double */
+ public final static int DOUBLE176 = 134218504;
+ /** number: 777 type: double */
+ public final static int DOUBLE177 = 134218505;
+ /** number: 778 type: double */
+ public final static int DOUBLE178 = 134218506;
+ /** number: 779 type: double */
+ public final static int DOUBLE179 = 134218507;
+ /** number: 780 type: double */
+ public final static int DOUBLE180 = 134218508;
+ /** number: 781 type: double */
+ public final static int DOUBLE181 = 134218509;
+ /** number: 782 type: double */
+ public final static int DOUBLE182 = 134218510;
+ /** number: 783 type: double */
+ public final static int DOUBLE183 = 134218511;
+ /** number: 784 type: double */
+ public final static int DOUBLE184 = 134218512;
+ /** number: 785 type: double */
+ public final static int DOUBLE185 = 134218513;
+ /** number: 786 type: double */
+ public final static int DOUBLE186 = 134218514;
+ /** number: 787 type: double */
+ public final static int DOUBLE187 = 134218515;
+ /** number: 788 type: double */
+ public final static int DOUBLE188 = 134218516;
+ /** number: 789 type: double */
+ public final static int DOUBLE189 = 134218517;
+ /** number: 790 type: double */
+ public final static int DOUBLE190 = 134218518;
+ /** number: 791 type: double */
+ public final static int DOUBLE191 = 134218519;
+ /** number: 792 type: double */
+ public final static int DOUBLE192 = 134218520;
+ /** number: 793 type: double */
+ public final static int DOUBLE193 = 134218521;
+ /** number: 794 type: double */
+ public final static int DOUBLE194 = 134218522;
+ /** number: 795 type: double */
+ public final static int DOUBLE195 = 134218523;
+ /** number: 796 type: double */
+ public final static int DOUBLE196 = 134218524;
+ /** number: 797 type: double */
+ public final static int DOUBLE197 = 134218525;
+ /** number: 798 type: double */
+ public final static int DOUBLE198 = 134218526;
+ /** number: 799 type: double */
+ public final static int DOUBLE199 = 134218527;
+ /** number: 800 type: double */
+ public final static int DOUBLE200 = 134218528;
+ /** number: 801 type: string */
+ public final static int SVCNAME = 167772961;
+ /** number: 802 type: string */
+ public final static int TPURCODE = 167772962;
+
+ public String getFieldName(int fldid)
+ {
+ if ( fieldtonameHashTable == null ) {
+ fieldtonameHashTable = new Hashtable();
+ fieldtonameHashTable.put(new Integer(STRING1), "STRING1");
+ fieldtonameHashTable.put(new Integer(STRING2), "STRING2");
+ fieldtonameHashTable.put(new Integer(STRING3), "STRING3");
+ fieldtonameHashTable.put(new Integer(STRING4), "STRING4");
+ fieldtonameHashTable.put(new Integer(STRING5), "STRING5");
+ fieldtonameHashTable.put(new Integer(STRING6), "STRING6");
+ fieldtonameHashTable.put(new Integer(STRING7), "STRING7");
+ fieldtonameHashTable.put(new Integer(STRING8), "STRING8");
+ fieldtonameHashTable.put(new Integer(STRING9), "STRING9");
+ fieldtonameHashTable.put(new Integer(STRING10), "STRING10");
+ fieldtonameHashTable.put(new Integer(STRING11), "STRING11");
+ fieldtonameHashTable.put(new Integer(STRING12), "STRING12");
+ fieldtonameHashTable.put(new Integer(STRING13), "STRING13");
+ fieldtonameHashTable.put(new Integer(STRING14), "STRING14");
+ fieldtonameHashTable.put(new Integer(STRING15), "STRING15");
+ fieldtonameHashTable.put(new Integer(STRING16), "STRING16");
+ fieldtonameHashTable.put(new Integer(STRING17), "STRING17");
+ fieldtonameHashTable.put(new Integer(STRING18), "STRING18");
+ fieldtonameHashTable.put(new Integer(STRING19), "STRING19");
+ fieldtonameHashTable.put(new Integer(STRING20), "STRING20");
+ fieldtonameHashTable.put(new Integer(STRING21), "STRING21");
+ fieldtonameHashTable.put(new Integer(STRING22), "STRING22");
+ fieldtonameHashTable.put(new Integer(STRING23), "STRING23");
+ fieldtonameHashTable.put(new Integer(STRING24), "STRING24");
+ fieldtonameHashTable.put(new Integer(STRING25), "STRING25");
+ fieldtonameHashTable.put(new Integer(STRING26), "STRING26");
+ fieldtonameHashTable.put(new Integer(STRING27), "STRING27");
+ fieldtonameHashTable.put(new Integer(STRING28), "STRING28");
+ fieldtonameHashTable.put(new Integer(STRING29), "STRING29");
+ fieldtonameHashTable.put(new Integer(STRING30), "STRING30");
+ fieldtonameHashTable.put(new Integer(STRING31), "STRING31");
+ fieldtonameHashTable.put(new Integer(STRING32), "STRING32");
+ fieldtonameHashTable.put(new Integer(STRING33), "STRING33");
+ fieldtonameHashTable.put(new Integer(STRING34), "STRING34");
+ fieldtonameHashTable.put(new Integer(STRING35), "STRING35");
+ fieldtonameHashTable.put(new Integer(STRING36), "STRING36");
+ fieldtonameHashTable.put(new Integer(STRING37), "STRING37");
+ fieldtonameHashTable.put(new Integer(STRING38), "STRING38");
+ fieldtonameHashTable.put(new Integer(STRING39), "STRING39");
+ fieldtonameHashTable.put(new Integer(STRING40), "STRING40");
+ fieldtonameHashTable.put(new Integer(STRING41), "STRING41");
+ fieldtonameHashTable.put(new Integer(STRING42), "STRING42");
+ fieldtonameHashTable.put(new Integer(STRING43), "STRING43");
+ fieldtonameHashTable.put(new Integer(STRING44), "STRING44");
+ fieldtonameHashTable.put(new Integer(STRING45), "STRING45");
+ fieldtonameHashTable.put(new Integer(STRING46), "STRING46");
+ fieldtonameHashTable.put(new Integer(STRING47), "STRING47");
+ fieldtonameHashTable.put(new Integer(STRING48), "STRING48");
+ fieldtonameHashTable.put(new Integer(STRING49), "STRING49");
+ fieldtonameHashTable.put(new Integer(STRING50), "STRING50");
+ fieldtonameHashTable.put(new Integer(STRING51), "STRING51");
+ fieldtonameHashTable.put(new Integer(STRING52), "STRING52");
+ fieldtonameHashTable.put(new Integer(STRING53), "STRING53");
+ fieldtonameHashTable.put(new Integer(STRING54), "STRING54");
+ fieldtonameHashTable.put(new Integer(STRING55), "STRING55");
+ fieldtonameHashTable.put(new Integer(STRING56), "STRING56");
+ fieldtonameHashTable.put(new Integer(STRING57), "STRING57");
+ fieldtonameHashTable.put(new Integer(STRING58), "STRING58");
+ fieldtonameHashTable.put(new Integer(STRING59), "STRING59");
+ fieldtonameHashTable.put(new Integer(STRING60), "STRING60");
+ fieldtonameHashTable.put(new Integer(STRING61), "STRING61");
+ fieldtonameHashTable.put(new Integer(STRING62), "STRING62");
+ fieldtonameHashTable.put(new Integer(STRING63), "STRING63");
+ fieldtonameHashTable.put(new Integer(STRING64), "STRING64");
+ fieldtonameHashTable.put(new Integer(STRING65), "STRING65");
+ fieldtonameHashTable.put(new Integer(STRING66), "STRING66");
+ fieldtonameHashTable.put(new Integer(STRING67), "STRING67");
+ fieldtonameHashTable.put(new Integer(STRING68), "STRING68");
+ fieldtonameHashTable.put(new Integer(STRING69), "STRING69");
+ fieldtonameHashTable.put(new Integer(STRING70), "STRING70");
+ fieldtonameHashTable.put(new Integer(STRING71), "STRING71");
+ fieldtonameHashTable.put(new Integer(STRING72), "STRING72");
+ fieldtonameHashTable.put(new Integer(STRING73), "STRING73");
+ fieldtonameHashTable.put(new Integer(STRING74), "STRING74");
+ fieldtonameHashTable.put(new Integer(STRING75), "STRING75");
+ fieldtonameHashTable.put(new Integer(STRING76), "STRING76");
+ fieldtonameHashTable.put(new Integer(STRING77), "STRING77");
+ fieldtonameHashTable.put(new Integer(STRING78), "STRING78");
+ fieldtonameHashTable.put(new Integer(STRING79), "STRING79");
+ fieldtonameHashTable.put(new Integer(STRING80), "STRING80");
+ fieldtonameHashTable.put(new Integer(STRING81), "STRING81");
+ fieldtonameHashTable.put(new Integer(STRING82), "STRING82");
+ fieldtonameHashTable.put(new Integer(STRING83), "STRING83");
+ fieldtonameHashTable.put(new Integer(STRING84), "STRING84");
+ fieldtonameHashTable.put(new Integer(STRING85), "STRING85");
+ fieldtonameHashTable.put(new Integer(STRING86), "STRING86");
+ fieldtonameHashTable.put(new Integer(STRING87), "STRING87");
+ fieldtonameHashTable.put(new Integer(STRING88), "STRING88");
+ fieldtonameHashTable.put(new Integer(STRING89), "STRING89");
+ fieldtonameHashTable.put(new Integer(STRING90), "STRING90");
+ fieldtonameHashTable.put(new Integer(STRING91), "STRING91");
+ fieldtonameHashTable.put(new Integer(STRING92), "STRING92");
+ fieldtonameHashTable.put(new Integer(STRING93), "STRING93");
+ fieldtonameHashTable.put(new Integer(STRING94), "STRING94");
+ fieldtonameHashTable.put(new Integer(STRING95), "STRING95");
+ fieldtonameHashTable.put(new Integer(STRING96), "STRING96");
+ fieldtonameHashTable.put(new Integer(STRING97), "STRING97");
+ fieldtonameHashTable.put(new Integer(STRING98), "STRING98");
+ fieldtonameHashTable.put(new Integer(STRING99), "STRING99");
+ fieldtonameHashTable.put(new Integer(STRING100), "STRING100");
+ fieldtonameHashTable.put(new Integer(STRING101), "STRING101");
+ fieldtonameHashTable.put(new Integer(STRING102), "STRING102");
+ fieldtonameHashTable.put(new Integer(STRING103), "STRING103");
+ fieldtonameHashTable.put(new Integer(STRING104), "STRING104");
+ fieldtonameHashTable.put(new Integer(STRING105), "STRING105");
+ fieldtonameHashTable.put(new Integer(STRING106), "STRING106");
+ fieldtonameHashTable.put(new Integer(STRING107), "STRING107");
+ fieldtonameHashTable.put(new Integer(STRING108), "STRING108");
+ fieldtonameHashTable.put(new Integer(STRING109), "STRING109");
+ fieldtonameHashTable.put(new Integer(STRING110), "STRING110");
+ fieldtonameHashTable.put(new Integer(STRING111), "STRING111");
+ fieldtonameHashTable.put(new Integer(STRING112), "STRING112");
+ fieldtonameHashTable.put(new Integer(STRING113), "STRING113");
+ fieldtonameHashTable.put(new Integer(STRING114), "STRING114");
+ fieldtonameHashTable.put(new Integer(STRING115), "STRING115");
+ fieldtonameHashTable.put(new Integer(STRING116), "STRING116");
+ fieldtonameHashTable.put(new Integer(STRING117), "STRING117");
+ fieldtonameHashTable.put(new Integer(STRING118), "STRING118");
+ fieldtonameHashTable.put(new Integer(STRING119), "STRING119");
+ fieldtonameHashTable.put(new Integer(STRING120), "STRING120");
+ fieldtonameHashTable.put(new Integer(STRING121), "STRING121");
+ fieldtonameHashTable.put(new Integer(STRING122), "STRING122");
+ fieldtonameHashTable.put(new Integer(STRING123), "STRING123");
+ fieldtonameHashTable.put(new Integer(STRING124), "STRING124");
+ fieldtonameHashTable.put(new Integer(STRING125), "STRING125");
+ fieldtonameHashTable.put(new Integer(STRING126), "STRING126");
+ fieldtonameHashTable.put(new Integer(STRING127), "STRING127");
+ fieldtonameHashTable.put(new Integer(STRING128), "STRING128");
+ fieldtonameHashTable.put(new Integer(STRING129), "STRING129");
+ fieldtonameHashTable.put(new Integer(STRING130), "STRING130");
+ fieldtonameHashTable.put(new Integer(STRING131), "STRING131");
+ fieldtonameHashTable.put(new Integer(STRING132), "STRING132");
+ fieldtonameHashTable.put(new Integer(STRING133), "STRING133");
+ fieldtonameHashTable.put(new Integer(STRING134), "STRING134");
+ fieldtonameHashTable.put(new Integer(STRING135), "STRING135");
+ fieldtonameHashTable.put(new Integer(STRING136), "STRING136");
+ fieldtonameHashTable.put(new Integer(STRING137), "STRING137");
+ fieldtonameHashTable.put(new Integer(STRING138), "STRING138");
+ fieldtonameHashTable.put(new Integer(STRING139), "STRING139");
+ fieldtonameHashTable.put(new Integer(STRING140), "STRING140");
+ fieldtonameHashTable.put(new Integer(STRING141), "STRING141");
+ fieldtonameHashTable.put(new Integer(STRING142), "STRING142");
+ fieldtonameHashTable.put(new Integer(STRING143), "STRING143");
+ fieldtonameHashTable.put(new Integer(STRING144), "STRING144");
+ fieldtonameHashTable.put(new Integer(STRING145), "STRING145");
+ fieldtonameHashTable.put(new Integer(STRING146), "STRING146");
+ fieldtonameHashTable.put(new Integer(STRING147), "STRING147");
+ fieldtonameHashTable.put(new Integer(STRING148), "STRING148");
+ fieldtonameHashTable.put(new Integer(STRING149), "STRING149");
+ fieldtonameHashTable.put(new Integer(STRING150), "STRING150");
+ fieldtonameHashTable.put(new Integer(STRING151), "STRING151");
+ fieldtonameHashTable.put(new Integer(STRING152), "STRING152");
+ fieldtonameHashTable.put(new Integer(STRING153), "STRING153");
+ fieldtonameHashTable.put(new Integer(STRING154), "STRING154");
+ fieldtonameHashTable.put(new Integer(STRING155), "STRING155");
+ fieldtonameHashTable.put(new Integer(STRING156), "STRING156");
+ fieldtonameHashTable.put(new Integer(STRING157), "STRING157");
+ fieldtonameHashTable.put(new Integer(STRING158), "STRING158");
+ fieldtonameHashTable.put(new Integer(STRING159), "STRING159");
+ fieldtonameHashTable.put(new Integer(STRING160), "STRING160");
+ fieldtonameHashTable.put(new Integer(STRING161), "STRING161");
+ fieldtonameHashTable.put(new Integer(STRING162), "STRING162");
+ fieldtonameHashTable.put(new Integer(STRING163), "STRING163");
+ fieldtonameHashTable.put(new Integer(STRING164), "STRING164");
+ fieldtonameHashTable.put(new Integer(STRING165), "STRING165");
+ fieldtonameHashTable.put(new Integer(STRING166), "STRING166");
+ fieldtonameHashTable.put(new Integer(STRING167), "STRING167");
+ fieldtonameHashTable.put(new Integer(STRING168), "STRING168");
+ fieldtonameHashTable.put(new Integer(STRING169), "STRING169");
+ fieldtonameHashTable.put(new Integer(STRING170), "STRING170");
+ fieldtonameHashTable.put(new Integer(STRING171), "STRING171");
+ fieldtonameHashTable.put(new Integer(STRING172), "STRING172");
+ fieldtonameHashTable.put(new Integer(STRING173), "STRING173");
+ fieldtonameHashTable.put(new Integer(STRING174), "STRING174");
+ fieldtonameHashTable.put(new Integer(STRING175), "STRING175");
+ fieldtonameHashTable.put(new Integer(STRING176), "STRING176");
+ fieldtonameHashTable.put(new Integer(STRING177), "STRING177");
+ fieldtonameHashTable.put(new Integer(STRING178), "STRING178");
+ fieldtonameHashTable.put(new Integer(STRING179), "STRING179");
+ fieldtonameHashTable.put(new Integer(STRING180), "STRING180");
+ fieldtonameHashTable.put(new Integer(STRING181), "STRING181");
+ fieldtonameHashTable.put(new Integer(STRING182), "STRING182");
+ fieldtonameHashTable.put(new Integer(STRING183), "STRING183");
+ fieldtonameHashTable.put(new Integer(STRING184), "STRING184");
+ fieldtonameHashTable.put(new Integer(STRING185), "STRING185");
+ fieldtonameHashTable.put(new Integer(STRING186), "STRING186");
+ fieldtonameHashTable.put(new Integer(STRING187), "STRING187");
+ fieldtonameHashTable.put(new Integer(STRING188), "STRING188");
+ fieldtonameHashTable.put(new Integer(STRING189), "STRING189");
+ fieldtonameHashTable.put(new Integer(STRING190), "STRING190");
+ fieldtonameHashTable.put(new Integer(STRING191), "STRING191");
+ fieldtonameHashTable.put(new Integer(STRING192), "STRING192");
+ fieldtonameHashTable.put(new Integer(STRING193), "STRING193");
+ fieldtonameHashTable.put(new Integer(STRING194), "STRING194");
+ fieldtonameHashTable.put(new Integer(STRING195), "STRING195");
+ fieldtonameHashTable.put(new Integer(STRING196), "STRING196");
+ fieldtonameHashTable.put(new Integer(STRING197), "STRING197");
+ fieldtonameHashTable.put(new Integer(STRING198), "STRING198");
+ fieldtonameHashTable.put(new Integer(STRING199), "STRING199");
+ fieldtonameHashTable.put(new Integer(STRING200), "STRING200");
+ fieldtonameHashTable.put(new Integer(LONG1), "LONG1");
+ fieldtonameHashTable.put(new Integer(LONG2), "LONG2");
+ fieldtonameHashTable.put(new Integer(LONG3), "LONG3");
+ fieldtonameHashTable.put(new Integer(LONG4), "LONG4");
+ fieldtonameHashTable.put(new Integer(LONG5), "LONG5");
+ fieldtonameHashTable.put(new Integer(LONG6), "LONG6");
+ fieldtonameHashTable.put(new Integer(LONG7), "LONG7");
+ fieldtonameHashTable.put(new Integer(LONG8), "LONG8");
+ fieldtonameHashTable.put(new Integer(LONG9), "LONG9");
+ fieldtonameHashTable.put(new Integer(LONG10), "LONG10");
+ fieldtonameHashTable.put(new Integer(LONG11), "LONG11");
+ fieldtonameHashTable.put(new Integer(LONG12), "LONG12");
+ fieldtonameHashTable.put(new Integer(LONG13), "LONG13");
+ fieldtonameHashTable.put(new Integer(LONG14), "LONG14");
+ fieldtonameHashTable.put(new Integer(LONG15), "LONG15");
+ fieldtonameHashTable.put(new Integer(LONG16), "LONG16");
+ fieldtonameHashTable.put(new Integer(LONG17), "LONG17");
+ fieldtonameHashTable.put(new Integer(LONG18), "LONG18");
+ fieldtonameHashTable.put(new Integer(LONG19), "LONG19");
+ fieldtonameHashTable.put(new Integer(LONG20), "LONG20");
+ fieldtonameHashTable.put(new Integer(LONG21), "LONG21");
+ fieldtonameHashTable.put(new Integer(LONG22), "LONG22");
+ fieldtonameHashTable.put(new Integer(LONG23), "LONG23");
+ fieldtonameHashTable.put(new Integer(LONG24), "LONG24");
+ fieldtonameHashTable.put(new Integer(LONG25), "LONG25");
+ fieldtonameHashTable.put(new Integer(LONG26), "LONG26");
+ fieldtonameHashTable.put(new Integer(LONG27), "LONG27");
+ fieldtonameHashTable.put(new Integer(LONG28), "LONG28");
+ fieldtonameHashTable.put(new Integer(LONG29), "LONG29");
+ fieldtonameHashTable.put(new Integer(LONG30), "LONG30");
+ fieldtonameHashTable.put(new Integer(LONG31), "LONG31");
+ fieldtonameHashTable.put(new Integer(LONG32), "LONG32");
+ fieldtonameHashTable.put(new Integer(LONG33), "LONG33");
+ fieldtonameHashTable.put(new Integer(LONG34), "LONG34");
+ fieldtonameHashTable.put(new Integer(LONG35), "LONG35");
+ fieldtonameHashTable.put(new Integer(LONG36), "LONG36");
+ fieldtonameHashTable.put(new Integer(LONG37), "LONG37");
+ fieldtonameHashTable.put(new Integer(LONG38), "LONG38");
+ fieldtonameHashTable.put(new Integer(LONG39), "LONG39");
+ fieldtonameHashTable.put(new Integer(LONG40), "LONG40");
+ fieldtonameHashTable.put(new Integer(LONG41), "LONG41");
+ fieldtonameHashTable.put(new Integer(LONG42), "LONG42");
+ fieldtonameHashTable.put(new Integer(LONG43), "LONG43");
+ fieldtonameHashTable.put(new Integer(LONG44), "LONG44");
+ fieldtonameHashTable.put(new Integer(LONG45), "LONG45");
+ fieldtonameHashTable.put(new Integer(LONG46), "LONG46");
+ fieldtonameHashTable.put(new Integer(LONG47), "LONG47");
+ fieldtonameHashTable.put(new Integer(LONG48), "LONG48");
+ fieldtonameHashTable.put(new Integer(LONG49), "LONG49");
+ fieldtonameHashTable.put(new Integer(LONG50), "LONG50");
+ fieldtonameHashTable.put(new Integer(LONG51), "LONG51");
+ fieldtonameHashTable.put(new Integer(LONG52), "LONG52");
+ fieldtonameHashTable.put(new Integer(LONG53), "LONG53");
+ fieldtonameHashTable.put(new Integer(LONG54), "LONG54");
+ fieldtonameHashTable.put(new Integer(LONG55), "LONG55");
+ fieldtonameHashTable.put(new Integer(LONG56), "LONG56");
+ fieldtonameHashTable.put(new Integer(LONG57), "LONG57");
+ fieldtonameHashTable.put(new Integer(LONG58), "LONG58");
+ fieldtonameHashTable.put(new Integer(LONG59), "LONG59");
+ fieldtonameHashTable.put(new Integer(LONG60), "LONG60");
+ fieldtonameHashTable.put(new Integer(LONG61), "LONG61");
+ fieldtonameHashTable.put(new Integer(LONG62), "LONG62");
+ fieldtonameHashTable.put(new Integer(LONG63), "LONG63");
+ fieldtonameHashTable.put(new Integer(LONG64), "LONG64");
+ fieldtonameHashTable.put(new Integer(LONG65), "LONG65");
+ fieldtonameHashTable.put(new Integer(LONG66), "LONG66");
+ fieldtonameHashTable.put(new Integer(LONG67), "LONG67");
+ fieldtonameHashTable.put(new Integer(LONG68), "LONG68");
+ fieldtonameHashTable.put(new Integer(LONG69), "LONG69");
+ fieldtonameHashTable.put(new Integer(LONG70), "LONG70");
+ fieldtonameHashTable.put(new Integer(LONG71), "LONG71");
+ fieldtonameHashTable.put(new Integer(LONG72), "LONG72");
+ fieldtonameHashTable.put(new Integer(LONG73), "LONG73");
+ fieldtonameHashTable.put(new Integer(LONG74), "LONG74");
+ fieldtonameHashTable.put(new Integer(LONG75), "LONG75");
+ fieldtonameHashTable.put(new Integer(LONG76), "LONG76");
+ fieldtonameHashTable.put(new Integer(LONG77), "LONG77");
+ fieldtonameHashTable.put(new Integer(LONG78), "LONG78");
+ fieldtonameHashTable.put(new Integer(LONG79), "LONG79");
+ fieldtonameHashTable.put(new Integer(LONG80), "LONG80");
+ fieldtonameHashTable.put(new Integer(LONG81), "LONG81");
+ fieldtonameHashTable.put(new Integer(LONG82), "LONG82");
+ fieldtonameHashTable.put(new Integer(LONG83), "LONG83");
+ fieldtonameHashTable.put(new Integer(LONG84), "LONG84");
+ fieldtonameHashTable.put(new Integer(LONG85), "LONG85");
+ fieldtonameHashTable.put(new Integer(LONG86), "LONG86");
+ fieldtonameHashTable.put(new Integer(LONG87), "LONG87");
+ fieldtonameHashTable.put(new Integer(LONG88), "LONG88");
+ fieldtonameHashTable.put(new Integer(LONG89), "LONG89");
+ fieldtonameHashTable.put(new Integer(LONG90), "LONG90");
+ fieldtonameHashTable.put(new Integer(LONG91), "LONG91");
+ fieldtonameHashTable.put(new Integer(LONG92), "LONG92");
+ fieldtonameHashTable.put(new Integer(LONG93), "LONG93");
+ fieldtonameHashTable.put(new Integer(LONG94), "LONG94");
+ fieldtonameHashTable.put(new Integer(LONG95), "LONG95");
+ fieldtonameHashTable.put(new Integer(LONG96), "LONG96");
+ fieldtonameHashTable.put(new Integer(LONG97), "LONG97");
+ fieldtonameHashTable.put(new Integer(LONG98), "LONG98");
+ fieldtonameHashTable.put(new Integer(LONG99), "LONG99");
+ fieldtonameHashTable.put(new Integer(LONG100), "LONG100");
+ fieldtonameHashTable.put(new Integer(DOUBLE1), "DOUBLE1");
+ fieldtonameHashTable.put(new Integer(DOUBLE2), "DOUBLE2");
+ fieldtonameHashTable.put(new Integer(DOUBLE3), "DOUBLE3");
+ fieldtonameHashTable.put(new Integer(DOUBLE4), "DOUBLE4");
+ fieldtonameHashTable.put(new Integer(DOUBLE5), "DOUBLE5");
+ fieldtonameHashTable.put(new Integer(DOUBLE6), "DOUBLE6");
+ fieldtonameHashTable.put(new Integer(DOUBLE7), "DOUBLE7");
+ fieldtonameHashTable.put(new Integer(DOUBLE8), "DOUBLE8");
+ fieldtonameHashTable.put(new Integer(DOUBLE9), "DOUBLE9");
+ fieldtonameHashTable.put(new Integer(DOUBLE10), "DOUBLE10");
+ fieldtonameHashTable.put(new Integer(DOUBLE11), "DOUBLE11");
+ fieldtonameHashTable.put(new Integer(DOUBLE12), "DOUBLE12");
+ fieldtonameHashTable.put(new Integer(DOUBLE13), "DOUBLE13");
+ fieldtonameHashTable.put(new Integer(DOUBLE14), "DOUBLE14");
+ fieldtonameHashTable.put(new Integer(DOUBLE15), "DOUBLE15");
+ fieldtonameHashTable.put(new Integer(DOUBLE16), "DOUBLE16");
+ fieldtonameHashTable.put(new Integer(DOUBLE17), "DOUBLE17");
+ fieldtonameHashTable.put(new Integer(DOUBLE18), "DOUBLE18");
+ fieldtonameHashTable.put(new Integer(DOUBLE19), "DOUBLE19");
+ fieldtonameHashTable.put(new Integer(DOUBLE20), "DOUBLE20");
+ fieldtonameHashTable.put(new Integer(DOUBLE21), "DOUBLE21");
+ fieldtonameHashTable.put(new Integer(DOUBLE22), "DOUBLE22");
+ fieldtonameHashTable.put(new Integer(DOUBLE23), "DOUBLE23");
+ fieldtonameHashTable.put(new Integer(DOUBLE24), "DOUBLE24");
+ fieldtonameHashTable.put(new Integer(DOUBLE25), "DOUBLE25");
+ fieldtonameHashTable.put(new Integer(DOUBLE26), "DOUBLE26");
+ fieldtonameHashTable.put(new Integer(DOUBLE27), "DOUBLE27");
+ fieldtonameHashTable.put(new Integer(DOUBLE28), "DOUBLE28");
+ fieldtonameHashTable.put(new Integer(DOUBLE29), "DOUBLE29");
+ fieldtonameHashTable.put(new Integer(DOUBLE30), "DOUBLE30");
+ fieldtonameHashTable.put(new Integer(DOUBLE31), "DOUBLE31");
+ fieldtonameHashTable.put(new Integer(DOUBLE32), "DOUBLE32");
+ fieldtonameHashTable.put(new Integer(DOUBLE33), "DOUBLE33");
+ fieldtonameHashTable.put(new Integer(DOUBLE34), "DOUBLE34");
+ fieldtonameHashTable.put(new Integer(DOUBLE35), "DOUBLE35");
+ fieldtonameHashTable.put(new Integer(DOUBLE36), "DOUBLE36");
+ fieldtonameHashTable.put(new Integer(DOUBLE37), "DOUBLE37");
+ fieldtonameHashTable.put(new Integer(DOUBLE38), "DOUBLE38");
+ fieldtonameHashTable.put(new Integer(DOUBLE39), "DOUBLE39");
+ fieldtonameHashTable.put(new Integer(DOUBLE40), "DOUBLE40");
+ fieldtonameHashTable.put(new Integer(DOUBLE41), "DOUBLE41");
+ fieldtonameHashTable.put(new Integer(DOUBLE42), "DOUBLE42");
+ fieldtonameHashTable.put(new Integer(DOUBLE43), "DOUBLE43");
+ fieldtonameHashTable.put(new Integer(DOUBLE44), "DOUBLE44");
+ fieldtonameHashTable.put(new Integer(DOUBLE45), "DOUBLE45");
+ fieldtonameHashTable.put(new Integer(DOUBLE46), "DOUBLE46");
+ fieldtonameHashTable.put(new Integer(DOUBLE47), "DOUBLE47");
+ fieldtonameHashTable.put(new Integer(DOUBLE48), "DOUBLE48");
+ fieldtonameHashTable.put(new Integer(DOUBLE49), "DOUBLE49");
+ fieldtonameHashTable.put(new Integer(DOUBLE50), "DOUBLE50");
+ fieldtonameHashTable.put(new Integer(DOUBLE51), "DOUBLE51");
+ fieldtonameHashTable.put(new Integer(DOUBLE52), "DOUBLE52");
+ fieldtonameHashTable.put(new Integer(DOUBLE53), "DOUBLE53");
+ fieldtonameHashTable.put(new Integer(DOUBLE54), "DOUBLE54");
+ fieldtonameHashTable.put(new Integer(DOUBLE55), "DOUBLE55");
+ fieldtonameHashTable.put(new Integer(DOUBLE56), "DOUBLE56");
+ fieldtonameHashTable.put(new Integer(DOUBLE57), "DOUBLE57");
+ fieldtonameHashTable.put(new Integer(DOUBLE58), "DOUBLE58");
+ fieldtonameHashTable.put(new Integer(DOUBLE59), "DOUBLE59");
+ fieldtonameHashTable.put(new Integer(DOUBLE60), "DOUBLE60");
+ fieldtonameHashTable.put(new Integer(DOUBLE61), "DOUBLE61");
+ fieldtonameHashTable.put(new Integer(DOUBLE62), "DOUBLE62");
+ fieldtonameHashTable.put(new Integer(DOUBLE63), "DOUBLE63");
+ fieldtonameHashTable.put(new Integer(DOUBLE64), "DOUBLE64");
+ fieldtonameHashTable.put(new Integer(DOUBLE65), "DOUBLE65");
+ fieldtonameHashTable.put(new Integer(DOUBLE66), "DOUBLE66");
+ fieldtonameHashTable.put(new Integer(DOUBLE67), "DOUBLE67");
+ fieldtonameHashTable.put(new Integer(DOUBLE68), "DOUBLE68");
+ fieldtonameHashTable.put(new Integer(DOUBLE69), "DOUBLE69");
+ fieldtonameHashTable.put(new Integer(DOUBLE70), "DOUBLE70");
+ fieldtonameHashTable.put(new Integer(DOUBLE71), "DOUBLE71");
+ fieldtonameHashTable.put(new Integer(DOUBLE72), "DOUBLE72");
+ fieldtonameHashTable.put(new Integer(DOUBLE73), "DOUBLE73");
+ fieldtonameHashTable.put(new Integer(DOUBLE74), "DOUBLE74");
+ fieldtonameHashTable.put(new Integer(DOUBLE75), "DOUBLE75");
+ fieldtonameHashTable.put(new Integer(DOUBLE76), "DOUBLE76");
+ fieldtonameHashTable.put(new Integer(DOUBLE77), "DOUBLE77");
+ fieldtonameHashTable.put(new Integer(DOUBLE78), "DOUBLE78");
+ fieldtonameHashTable.put(new Integer(DOUBLE79), "DOUBLE79");
+ fieldtonameHashTable.put(new Integer(DOUBLE80), "DOUBLE80");
+ fieldtonameHashTable.put(new Integer(DOUBLE81), "DOUBLE81");
+ fieldtonameHashTable.put(new Integer(DOUBLE82), "DOUBLE82");
+ fieldtonameHashTable.put(new Integer(DOUBLE83), "DOUBLE83");
+ fieldtonameHashTable.put(new Integer(DOUBLE84), "DOUBLE84");
+ fieldtonameHashTable.put(new Integer(DOUBLE85), "DOUBLE85");
+ fieldtonameHashTable.put(new Integer(DOUBLE86), "DOUBLE86");
+ fieldtonameHashTable.put(new Integer(DOUBLE87), "DOUBLE87");
+ fieldtonameHashTable.put(new Integer(DOUBLE88), "DOUBLE88");
+ fieldtonameHashTable.put(new Integer(DOUBLE89), "DOUBLE89");
+ fieldtonameHashTable.put(new Integer(DOUBLE90), "DOUBLE90");
+ fieldtonameHashTable.put(new Integer(DOUBLE91), "DOUBLE91");
+ fieldtonameHashTable.put(new Integer(DOUBLE92), "DOUBLE92");
+ fieldtonameHashTable.put(new Integer(DOUBLE93), "DOUBLE93");
+ fieldtonameHashTable.put(new Integer(DOUBLE94), "DOUBLE94");
+ fieldtonameHashTable.put(new Integer(DOUBLE95), "DOUBLE95");
+ fieldtonameHashTable.put(new Integer(DOUBLE96), "DOUBLE96");
+ fieldtonameHashTable.put(new Integer(DOUBLE97), "DOUBLE97");
+ fieldtonameHashTable.put(new Integer(DOUBLE98), "DOUBLE98");
+ fieldtonameHashTable.put(new Integer(DOUBLE99), "DOUBLE99");
+ fieldtonameHashTable.put(new Integer(DOUBLE100), "DOUBLE100");
+ fieldtonameHashTable.put(new Integer(DOUBLE101), "DOUBLE101");
+ fieldtonameHashTable.put(new Integer(DOUBLE102), "DOUBLE102");
+ fieldtonameHashTable.put(new Integer(DOUBLE103), "DOUBLE103");
+ fieldtonameHashTable.put(new Integer(DOUBLE104), "DOUBLE104");
+ fieldtonameHashTable.put(new Integer(DOUBLE105), "DOUBLE105");
+ fieldtonameHashTable.put(new Integer(DOUBLE106), "DOUBLE106");
+ fieldtonameHashTable.put(new Integer(DOUBLE107), "DOUBLE107");
+ fieldtonameHashTable.put(new Integer(DOUBLE108), "DOUBLE108");
+ fieldtonameHashTable.put(new Integer(DOUBLE109), "DOUBLE109");
+ fieldtonameHashTable.put(new Integer(DOUBLE110), "DOUBLE110");
+ fieldtonameHashTable.put(new Integer(DOUBLE111), "DOUBLE111");
+ fieldtonameHashTable.put(new Integer(DOUBLE112), "DOUBLE112");
+ fieldtonameHashTable.put(new Integer(DOUBLE113), "DOUBLE113");
+ fieldtonameHashTable.put(new Integer(DOUBLE114), "DOUBLE114");
+ fieldtonameHashTable.put(new Integer(DOUBLE115), "DOUBLE115");
+ fieldtonameHashTable.put(new Integer(DOUBLE116), "DOUBLE116");
+ fieldtonameHashTable.put(new Integer(DOUBLE117), "DOUBLE117");
+ fieldtonameHashTable.put(new Integer(DOUBLE118), "DOUBLE118");
+ fieldtonameHashTable.put(new Integer(DOUBLE119), "DOUBLE119");
+ fieldtonameHashTable.put(new Integer(DOUBLE120), "DOUBLE120");
+ fieldtonameHashTable.put(new Integer(DOUBLE121), "DOUBLE121");
+ fieldtonameHashTable.put(new Integer(DOUBLE122), "DOUBLE122");
+ fieldtonameHashTable.put(new Integer(DOUBLE123), "DOUBLE123");
+ fieldtonameHashTable.put(new Integer(DOUBLE124), "DOUBLE124");
+ fieldtonameHashTable.put(new Integer(DOUBLE125), "DOUBLE125");
+ fieldtonameHashTable.put(new Integer(DOUBLE126), "DOUBLE126");
+ fieldtonameHashTable.put(new Integer(DOUBLE127), "DOUBLE127");
+ fieldtonameHashTable.put(new Integer(DOUBLE128), "DOUBLE128");
+ fieldtonameHashTable.put(new Integer(DOUBLE129), "DOUBLE129");
+ fieldtonameHashTable.put(new Integer(DOUBLE130), "DOUBLE130");
+ fieldtonameHashTable.put(new Integer(DOUBLE131), "DOUBLE131");
+ fieldtonameHashTable.put(new Integer(DOUBLE132), "DOUBLE132");
+ fieldtonameHashTable.put(new Integer(DOUBLE133), "DOUBLE133");
+ fieldtonameHashTable.put(new Integer(DOUBLE134), "DOUBLE134");
+ fieldtonameHashTable.put(new Integer(DOUBLE135), "DOUBLE135");
+ fieldtonameHashTable.put(new Integer(DOUBLE136), "DOUBLE136");
+ fieldtonameHashTable.put(new Integer(DOUBLE137), "DOUBLE137");
+ fieldtonameHashTable.put(new Integer(DOUBLE138), "DOUBLE138");
+ fieldtonameHashTable.put(new Integer(DOUBLE139), "DOUBLE139");
+ fieldtonameHashTable.put(new Integer(DOUBLE140), "DOUBLE140");
+ fieldtonameHashTable.put(new Integer(DOUBLE141), "DOUBLE141");
+ fieldtonameHashTable.put(new Integer(DOUBLE142), "DOUBLE142");
+ fieldtonameHashTable.put(new Integer(DOUBLE143), "DOUBLE143");
+ fieldtonameHashTable.put(new Integer(DOUBLE144), "DOUBLE144");
+ fieldtonameHashTable.put(new Integer(DOUBLE145), "DOUBLE145");
+ fieldtonameHashTable.put(new Integer(DOUBLE146), "DOUBLE146");
+ fieldtonameHashTable.put(new Integer(DOUBLE147), "DOUBLE147");
+ fieldtonameHashTable.put(new Integer(DOUBLE148), "DOUBLE148");
+ fieldtonameHashTable.put(new Integer(DOUBLE149), "DOUBLE149");
+ fieldtonameHashTable.put(new Integer(DOUBLE150), "DOUBLE150");
+ fieldtonameHashTable.put(new Integer(DOUBLE151), "DOUBLE151");
+ fieldtonameHashTable.put(new Integer(DOUBLE152), "DOUBLE152");
+ fieldtonameHashTable.put(new Integer(DOUBLE153), "DOUBLE153");
+ fieldtonameHashTable.put(new Integer(DOUBLE154), "DOUBLE154");
+ fieldtonameHashTable.put(new Integer(DOUBLE155), "DOUBLE155");
+ fieldtonameHashTable.put(new Integer(DOUBLE156), "DOUBLE156");
+ fieldtonameHashTable.put(new Integer(DOUBLE157), "DOUBLE157");
+ fieldtonameHashTable.put(new Integer(DOUBLE158), "DOUBLE158");
+ fieldtonameHashTable.put(new Integer(DOUBLE159), "DOUBLE159");
+ fieldtonameHashTable.put(new Integer(DOUBLE160), "DOUBLE160");
+ fieldtonameHashTable.put(new Integer(DOUBLE161), "DOUBLE161");
+ fieldtonameHashTable.put(new Integer(DOUBLE162), "DOUBLE162");
+ fieldtonameHashTable.put(new Integer(DOUBLE163), "DOUBLE163");
+ fieldtonameHashTable.put(new Integer(DOUBLE164), "DOUBLE164");
+ fieldtonameHashTable.put(new Integer(DOUBLE165), "DOUBLE165");
+ fieldtonameHashTable.put(new Integer(DOUBLE166), "DOUBLE166");
+ fieldtonameHashTable.put(new Integer(DOUBLE167), "DOUBLE167");
+ fieldtonameHashTable.put(new Integer(DOUBLE168), "DOUBLE168");
+ fieldtonameHashTable.put(new Integer(DOUBLE169), "DOUBLE169");
+ fieldtonameHashTable.put(new Integer(DOUBLE170), "DOUBLE170");
+ fieldtonameHashTable.put(new Integer(DOUBLE171), "DOUBLE171");
+ fieldtonameHashTable.put(new Integer(DOUBLE172), "DOUBLE172");
+ fieldtonameHashTable.put(new Integer(DOUBLE173), "DOUBLE173");
+ fieldtonameHashTable.put(new Integer(DOUBLE174), "DOUBLE174");
+ fieldtonameHashTable.put(new Integer(DOUBLE175), "DOUBLE175");
+ fieldtonameHashTable.put(new Integer(DOUBLE176), "DOUBLE176");
+ fieldtonameHashTable.put(new Integer(DOUBLE177), "DOUBLE177");
+ fieldtonameHashTable.put(new Integer(DOUBLE178), "DOUBLE178");
+ fieldtonameHashTable.put(new Integer(DOUBLE179), "DOUBLE179");
+ fieldtonameHashTable.put(new Integer(DOUBLE180), "DOUBLE180");
+ fieldtonameHashTable.put(new Integer(DOUBLE181), "DOUBLE181");
+ fieldtonameHashTable.put(new Integer(DOUBLE182), "DOUBLE182");
+ fieldtonameHashTable.put(new Integer(DOUBLE183), "DOUBLE183");
+ fieldtonameHashTable.put(new Integer(DOUBLE184), "DOUBLE184");
+ fieldtonameHashTable.put(new Integer(DOUBLE185), "DOUBLE185");
+ fieldtonameHashTable.put(new Integer(DOUBLE186), "DOUBLE186");
+ fieldtonameHashTable.put(new Integer(DOUBLE187), "DOUBLE187");
+ fieldtonameHashTable.put(new Integer(DOUBLE188), "DOUBLE188");
+ fieldtonameHashTable.put(new Integer(DOUBLE189), "DOUBLE189");
+ fieldtonameHashTable.put(new Integer(DOUBLE190), "DOUBLE190");
+ fieldtonameHashTable.put(new Integer(DOUBLE191), "DOUBLE191");
+ fieldtonameHashTable.put(new Integer(DOUBLE192), "DOUBLE192");
+ fieldtonameHashTable.put(new Integer(DOUBLE193), "DOUBLE193");
+ fieldtonameHashTable.put(new Integer(DOUBLE194), "DOUBLE194");
+ fieldtonameHashTable.put(new Integer(DOUBLE195), "DOUBLE195");
+ fieldtonameHashTable.put(new Integer(DOUBLE196), "DOUBLE196");
+ fieldtonameHashTable.put(new Integer(DOUBLE197), "DOUBLE197");
+ fieldtonameHashTable.put(new Integer(DOUBLE198), "DOUBLE198");
+ fieldtonameHashTable.put(new Integer(DOUBLE199), "DOUBLE199");
+ fieldtonameHashTable.put(new Integer(DOUBLE200), "DOUBLE200");
+ fieldtonameHashTable.put(new Integer(SVCNAME), "SVCNAME");
+ fieldtonameHashTable.put(new Integer(TPURCODE), "TPURCODE");
+ }
+
+ return ((String)fieldtonameHashTable.get(new Integer(fldid)));
+ }
+
+ public int getFieldId(String name)
+ {
+ if ( nametofieldHashTable == null ) {
+ nametofieldHashTable = new Hashtable();
+ nametofieldHashTable.put("STRING1", new Integer(STRING1));
+ nametofieldHashTable.put("STRING2", new Integer(STRING2));
+ nametofieldHashTable.put("STRING3", new Integer(STRING3));
+ nametofieldHashTable.put("STRING4", new Integer(STRING4));
+ nametofieldHashTable.put("STRING5", new Integer(STRING5));
+ nametofieldHashTable.put("STRING6", new Integer(STRING6));
+ nametofieldHashTable.put("STRING7", new Integer(STRING7));
+ nametofieldHashTable.put("STRING8", new Integer(STRING8));
+ nametofieldHashTable.put("STRING9", new Integer(STRING9));
+ nametofieldHashTable.put("STRING10", new Integer(STRING10));
+ nametofieldHashTable.put("STRING11", new Integer(STRING11));
+ nametofieldHashTable.put("STRING12", new Integer(STRING12));
+ nametofieldHashTable.put("STRING13", new Integer(STRING13));
+ nametofieldHashTable.put("STRING14", new Integer(STRING14));
+ nametofieldHashTable.put("STRING15", new Integer(STRING15));
+ nametofieldHashTable.put("STRING16", new Integer(STRING16));
+ nametofieldHashTable.put("STRING17", new Integer(STRING17));
+ nametofieldHashTable.put("STRING18", new Integer(STRING18));
+ nametofieldHashTable.put("STRING19", new Integer(STRING19));
+ nametofieldHashTable.put("STRING20", new Integer(STRING20));
+ nametofieldHashTable.put("STRING21", new Integer(STRING21));
+ nametofieldHashTable.put("STRING22", new Integer(STRING22));
+ nametofieldHashTable.put("STRING23", new Integer(STRING23));
+ nametofieldHashTable.put("STRING24", new Integer(STRING24));
+ nametofieldHashTable.put("STRING25", new Integer(STRING25));
+ nametofieldHashTable.put("STRING26", new Integer(STRING26));
+ nametofieldHashTable.put("STRING27", new Integer(STRING27));
+ nametofieldHashTable.put("STRING28", new Integer(STRING28));
+ nametofieldHashTable.put("STRING29", new Integer(STRING29));
+ nametofieldHashTable.put("STRING30", new Integer(STRING30));
+ nametofieldHashTable.put("STRING31", new Integer(STRING31));
+ nametofieldHashTable.put("STRING32", new Integer(STRING32));
+ nametofieldHashTable.put("STRING33", new Integer(STRING33));
+ nametofieldHashTable.put("STRING34", new Integer(STRING34));
+ nametofieldHashTable.put("STRING35", new Integer(STRING35));
+ nametofieldHashTable.put("STRING36", new Integer(STRING36));
+ nametofieldHashTable.put("STRING37", new Integer(STRING37));
+ nametofieldHashTable.put("STRING38", new Integer(STRING38));
+ nametofieldHashTable.put("STRING39", new Integer(STRING39));
+ nametofieldHashTable.put("STRING40", new Integer(STRING40));
+ nametofieldHashTable.put("STRING41", new Integer(STRING41));
+ nametofieldHashTable.put("STRING42", new Integer(STRING42));
+ nametofieldHashTable.put("STRING43", new Integer(STRING43));
+ nametofieldHashTable.put("STRING44", new Integer(STRING44));
+ nametofieldHashTable.put("STRING45", new Integer(STRING45));
+ nametofieldHashTable.put("STRING46", new Integer(STRING46));
+ nametofieldHashTable.put("STRING47", new Integer(STRING47));
+ nametofieldHashTable.put("STRING48", new Integer(STRING48));
+ nametofieldHashTable.put("STRING49", new Integer(STRING49));
+ nametofieldHashTable.put("STRING50", new Integer(STRING50));
+ nametofieldHashTable.put("STRING51", new Integer(STRING51));
+ nametofieldHashTable.put("STRING52", new Integer(STRING52));
+ nametofieldHashTable.put("STRING53", new Integer(STRING53));
+ nametofieldHashTable.put("STRING54", new Integer(STRING54));
+ nametofieldHashTable.put("STRING55", new Integer(STRING55));
+ nametofieldHashTable.put("STRING56", new Integer(STRING56));
+ nametofieldHashTable.put("STRING57", new Integer(STRING57));
+ nametofieldHashTable.put("STRING58", new Integer(STRING58));
+ nametofieldHashTable.put("STRING59", new Integer(STRING59));
+ nametofieldHashTable.put("STRING60", new Integer(STRING60));
+ nametofieldHashTable.put("STRING61", new Integer(STRING61));
+ nametofieldHashTable.put("STRING62", new Integer(STRING62));
+ nametofieldHashTable.put("STRING63", new Integer(STRING63));
+ nametofieldHashTable.put("STRING64", new Integer(STRING64));
+ nametofieldHashTable.put("STRING65", new Integer(STRING65));
+ nametofieldHashTable.put("STRING66", new Integer(STRING66));
+ nametofieldHashTable.put("STRING67", new Integer(STRING67));
+ nametofieldHashTable.put("STRING68", new Integer(STRING68));
+ nametofieldHashTable.put("STRING69", new Integer(STRING69));
+ nametofieldHashTable.put("STRING70", new Integer(STRING70));
+ nametofieldHashTable.put("STRING71", new Integer(STRING71));
+ nametofieldHashTable.put("STRING72", new Integer(STRING72));
+ nametofieldHashTable.put("STRING73", new Integer(STRING73));
+ nametofieldHashTable.put("STRING74", new Integer(STRING74));
+ nametofieldHashTable.put("STRING75", new Integer(STRING75));
+ nametofieldHashTable.put("STRING76", new Integer(STRING76));
+ nametofieldHashTable.put("STRING77", new Integer(STRING77));
+ nametofieldHashTable.put("STRING78", new Integer(STRING78));
+ nametofieldHashTable.put("STRING79", new Integer(STRING79));
+ nametofieldHashTable.put("STRING80", new Integer(STRING80));
+ nametofieldHashTable.put("STRING81", new Integer(STRING81));
+ nametofieldHashTable.put("STRING82", new Integer(STRING82));
+ nametofieldHashTable.put("STRING83", new Integer(STRING83));
+ nametofieldHashTable.put("STRING84", new Integer(STRING84));
+ nametofieldHashTable.put("STRING85", new Integer(STRING85));
+ nametofieldHashTable.put("STRING86", new Integer(STRING86));
+ nametofieldHashTable.put("STRING87", new Integer(STRING87));
+ nametofieldHashTable.put("STRING88", new Integer(STRING88));
+ nametofieldHashTable.put("STRING89", new Integer(STRING89));
+ nametofieldHashTable.put("STRING90", new Integer(STRING90));
+ nametofieldHashTable.put("STRING91", new Integer(STRING91));
+ nametofieldHashTable.put("STRING92", new Integer(STRING92));
+ nametofieldHashTable.put("STRING93", new Integer(STRING93));
+ nametofieldHashTable.put("STRING94", new Integer(STRING94));
+ nametofieldHashTable.put("STRING95", new Integer(STRING95));
+ nametofieldHashTable.put("STRING96", new Integer(STRING96));
+ nametofieldHashTable.put("STRING97", new Integer(STRING97));
+ nametofieldHashTable.put("STRING98", new Integer(STRING98));
+ nametofieldHashTable.put("STRING99", new Integer(STRING99));
+ nametofieldHashTable.put("STRING100", new Integer(STRING100));
+ nametofieldHashTable.put("STRING101", new Integer(STRING101));
+ nametofieldHashTable.put("STRING102", new Integer(STRING102));
+ nametofieldHashTable.put("STRING103", new Integer(STRING103));
+ nametofieldHashTable.put("STRING104", new Integer(STRING104));
+ nametofieldHashTable.put("STRING105", new Integer(STRING105));
+ nametofieldHashTable.put("STRING106", new Integer(STRING106));
+ nametofieldHashTable.put("STRING107", new Integer(STRING107));
+ nametofieldHashTable.put("STRING108", new Integer(STRING108));
+ nametofieldHashTable.put("STRING109", new Integer(STRING109));
+ nametofieldHashTable.put("STRING110", new Integer(STRING110));
+ nametofieldHashTable.put("STRING111", new Integer(STRING111));
+ nametofieldHashTable.put("STRING112", new Integer(STRING112));
+ nametofieldHashTable.put("STRING113", new Integer(STRING113));
+ nametofieldHashTable.put("STRING114", new Integer(STRING114));
+ nametofieldHashTable.put("STRING115", new Integer(STRING115));
+ nametofieldHashTable.put("STRING116", new Integer(STRING116));
+ nametofieldHashTable.put("STRING117", new Integer(STRING117));
+ nametofieldHashTable.put("STRING118", new Integer(STRING118));
+ nametofieldHashTable.put("STRING119", new Integer(STRING119));
+ nametofieldHashTable.put("STRING120", new Integer(STRING120));
+ nametofieldHashTable.put("STRING121", new Integer(STRING121));
+ nametofieldHashTable.put("STRING122", new Integer(STRING122));
+ nametofieldHashTable.put("STRING123", new Integer(STRING123));
+ nametofieldHashTable.put("STRING124", new Integer(STRING124));
+ nametofieldHashTable.put("STRING125", new Integer(STRING125));
+ nametofieldHashTable.put("STRING126", new Integer(STRING126));
+ nametofieldHashTable.put("STRING127", new Integer(STRING127));
+ nametofieldHashTable.put("STRING128", new Integer(STRING128));
+ nametofieldHashTable.put("STRING129", new Integer(STRING129));
+ nametofieldHashTable.put("STRING130", new Integer(STRING130));
+ nametofieldHashTable.put("STRING131", new Integer(STRING131));
+ nametofieldHashTable.put("STRING132", new Integer(STRING132));
+ nametofieldHashTable.put("STRING133", new Integer(STRING133));
+ nametofieldHashTable.put("STRING134", new Integer(STRING134));
+ nametofieldHashTable.put("STRING135", new Integer(STRING135));
+ nametofieldHashTable.put("STRING136", new Integer(STRING136));
+ nametofieldHashTable.put("STRING137", new Integer(STRING137));
+ nametofieldHashTable.put("STRING138", new Integer(STRING138));
+ nametofieldHashTable.put("STRING139", new Integer(STRING139));
+ nametofieldHashTable.put("STRING140", new Integer(STRING140));
+ nametofieldHashTable.put("STRING141", new Integer(STRING141));
+ nametofieldHashTable.put("STRING142", new Integer(STRING142));
+ nametofieldHashTable.put("STRING143", new Integer(STRING143));
+ nametofieldHashTable.put("STRING144", new Integer(STRING144));
+ nametofieldHashTable.put("STRING145", new Integer(STRING145));
+ nametofieldHashTable.put("STRING146", new Integer(STRING146));
+ nametofieldHashTable.put("STRING147", new Integer(STRING147));
+ nametofieldHashTable.put("STRING148", new Integer(STRING148));
+ nametofieldHashTable.put("STRING149", new Integer(STRING149));
+ nametofieldHashTable.put("STRING150", new Integer(STRING150));
+ nametofieldHashTable.put("STRING151", new Integer(STRING151));
+ nametofieldHashTable.put("STRING152", new Integer(STRING152));
+ nametofieldHashTable.put("STRING153", new Integer(STRING153));
+ nametofieldHashTable.put("STRING154", new Integer(STRING154));
+ nametofieldHashTable.put("STRING155", new Integer(STRING155));
+ nametofieldHashTable.put("STRING156", new Integer(STRING156));
+ nametofieldHashTable.put("STRING157", new Integer(STRING157));
+ nametofieldHashTable.put("STRING158", new Integer(STRING158));
+ nametofieldHashTable.put("STRING159", new Integer(STRING159));
+ nametofieldHashTable.put("STRING160", new Integer(STRING160));
+ nametofieldHashTable.put("STRING161", new Integer(STRING161));
+ nametofieldHashTable.put("STRING162", new Integer(STRING162));
+ nametofieldHashTable.put("STRING163", new Integer(STRING163));
+ nametofieldHashTable.put("STRING164", new Integer(STRING164));
+ nametofieldHashTable.put("STRING165", new Integer(STRING165));
+ nametofieldHashTable.put("STRING166", new Integer(STRING166));
+ nametofieldHashTable.put("STRING167", new Integer(STRING167));
+ nametofieldHashTable.put("STRING168", new Integer(STRING168));
+ nametofieldHashTable.put("STRING169", new Integer(STRING169));
+ nametofieldHashTable.put("STRING170", new Integer(STRING170));
+ nametofieldHashTable.put("STRING171", new Integer(STRING171));
+ nametofieldHashTable.put("STRING172", new Integer(STRING172));
+ nametofieldHashTable.put("STRING173", new Integer(STRING173));
+ nametofieldHashTable.put("STRING174", new Integer(STRING174));
+ nametofieldHashTable.put("STRING175", new Integer(STRING175));
+ nametofieldHashTable.put("STRING176", new Integer(STRING176));
+ nametofieldHashTable.put("STRING177", new Integer(STRING177));
+ nametofieldHashTable.put("STRING178", new Integer(STRING178));
+ nametofieldHashTable.put("STRING179", new Integer(STRING179));
+ nametofieldHashTable.put("STRING180", new Integer(STRING180));
+ nametofieldHashTable.put("STRING181", new Integer(STRING181));
+ nametofieldHashTable.put("STRING182", new Integer(STRING182));
+ nametofieldHashTable.put("STRING183", new Integer(STRING183));
+ nametofieldHashTable.put("STRING184", new Integer(STRING184));
+ nametofieldHashTable.put("STRING185", new Integer(STRING185));
+ nametofieldHashTable.put("STRING186", new Integer(STRING186));
+ nametofieldHashTable.put("STRING187", new Integer(STRING187));
+ nametofieldHashTable.put("STRING188", new Integer(STRING188));
+ nametofieldHashTable.put("STRING189", new Integer(STRING189));
+ nametofieldHashTable.put("STRING190", new Integer(STRING190));
+ nametofieldHashTable.put("STRING191", new Integer(STRING191));
+ nametofieldHashTable.put("STRING192", new Integer(STRING192));
+ nametofieldHashTable.put("STRING193", new Integer(STRING193));
+ nametofieldHashTable.put("STRING194", new Integer(STRING194));
+ nametofieldHashTable.put("STRING195", new Integer(STRING195));
+ nametofieldHashTable.put("STRING196", new Integer(STRING196));
+ nametofieldHashTable.put("STRING197", new Integer(STRING197));
+ nametofieldHashTable.put("STRING198", new Integer(STRING198));
+ nametofieldHashTable.put("STRING199", new Integer(STRING199));
+ nametofieldHashTable.put("STRING200", new Integer(STRING200));
+ nametofieldHashTable.put("LONG1", new Integer(LONG1));
+ nametofieldHashTable.put("LONG2", new Integer(LONG2));
+ nametofieldHashTable.put("LONG3", new Integer(LONG3));
+ nametofieldHashTable.put("LONG4", new Integer(LONG4));
+ nametofieldHashTable.put("LONG5", new Integer(LONG5));
+ nametofieldHashTable.put("LONG6", new Integer(LONG6));
+ nametofieldHashTable.put("LONG7", new Integer(LONG7));
+ nametofieldHashTable.put("LONG8", new Integer(LONG8));
+ nametofieldHashTable.put("LONG9", new Integer(LONG9));
+ nametofieldHashTable.put("LONG10", new Integer(LONG10));
+ nametofieldHashTable.put("LONG11", new Integer(LONG11));
+ nametofieldHashTable.put("LONG12", new Integer(LONG12));
+ nametofieldHashTable.put("LONG13", new Integer(LONG13));
+ nametofieldHashTable.put("LONG14", new Integer(LONG14));
+ nametofieldHashTable.put("LONG15", new Integer(LONG15));
+ nametofieldHashTable.put("LONG16", new Integer(LONG16));
+ nametofieldHashTable.put("LONG17", new Integer(LONG17));
+ nametofieldHashTable.put("LONG18", new Integer(LONG18));
+ nametofieldHashTable.put("LONG19", new Integer(LONG19));
+ nametofieldHashTable.put("LONG20", new Integer(LONG20));
+ nametofieldHashTable.put("LONG21", new Integer(LONG21));
+ nametofieldHashTable.put("LONG22", new Integer(LONG22));
+ nametofieldHashTable.put("LONG23", new Integer(LONG23));
+ nametofieldHashTable.put("LONG24", new Integer(LONG24));
+ nametofieldHashTable.put("LONG25", new Integer(LONG25));
+ nametofieldHashTable.put("LONG26", new Integer(LONG26));
+ nametofieldHashTable.put("LONG27", new Integer(LONG27));
+ nametofieldHashTable.put("LONG28", new Integer(LONG28));
+ nametofieldHashTable.put("LONG29", new Integer(LONG29));
+ nametofieldHashTable.put("LONG30", new Integer(LONG30));
+ nametofieldHashTable.put("LONG31", new Integer(LONG31));
+ nametofieldHashTable.put("LONG32", new Integer(LONG32));
+ nametofieldHashTable.put("LONG33", new Integer(LONG33));
+ nametofieldHashTable.put("LONG34", new Integer(LONG34));
+ nametofieldHashTable.put("LONG35", new Integer(LONG35));
+ nametofieldHashTable.put("LONG36", new Integer(LONG36));
+ nametofieldHashTable.put("LONG37", new Integer(LONG37));
+ nametofieldHashTable.put("LONG38", new Integer(LONG38));
+ nametofieldHashTable.put("LONG39", new Integer(LONG39));
+ nametofieldHashTable.put("LONG40", new Integer(LONG40));
+ nametofieldHashTable.put("LONG41", new Integer(LONG41));
+ nametofieldHashTable.put("LONG42", new Integer(LONG42));
+ nametofieldHashTable.put("LONG43", new Integer(LONG43));
+ nametofieldHashTable.put("LONG44", new Integer(LONG44));
+ nametofieldHashTable.put("LONG45", new Integer(LONG45));
+ nametofieldHashTable.put("LONG46", new Integer(LONG46));
+ nametofieldHashTable.put("LONG47", new Integer(LONG47));
+ nametofieldHashTable.put("LONG48", new Integer(LONG48));
+ nametofieldHashTable.put("LONG49", new Integer(LONG49));
+ nametofieldHashTable.put("LONG50", new Integer(LONG50));
+ nametofieldHashTable.put("LONG51", new Integer(LONG51));
+ nametofieldHashTable.put("LONG52", new Integer(LONG52));
+ nametofieldHashTable.put("LONG53", new Integer(LONG53));
+ nametofieldHashTable.put("LONG54", new Integer(LONG54));
+ nametofieldHashTable.put("LONG55", new Integer(LONG55));
+ nametofieldHashTable.put("LONG56", new Integer(LONG56));
+ nametofieldHashTable.put("LONG57", new Integer(LONG57));
+ nametofieldHashTable.put("LONG58", new Integer(LONG58));
+ nametofieldHashTable.put("LONG59", new Integer(LONG59));
+ nametofieldHashTable.put("LONG60", new Integer(LONG60));
+ nametofieldHashTable.put("LONG61", new Integer(LONG61));
+ nametofieldHashTable.put("LONG62", new Integer(LONG62));
+ nametofieldHashTable.put("LONG63", new Integer(LONG63));
+ nametofieldHashTable.put("LONG64", new Integer(LONG64));
+ nametofieldHashTable.put("LONG65", new Integer(LONG65));
+ nametofieldHashTable.put("LONG66", new Integer(LONG66));
+ nametofieldHashTable.put("LONG67", new Integer(LONG67));
+ nametofieldHashTable.put("LONG68", new Integer(LONG68));
+ nametofieldHashTable.put("LONG69", new Integer(LONG69));
+ nametofieldHashTable.put("LONG70", new Integer(LONG70));
+ nametofieldHashTable.put("LONG71", new Integer(LONG71));
+ nametofieldHashTable.put("LONG72", new Integer(LONG72));
+ nametofieldHashTable.put("LONG73", new Integer(LONG73));
+ nametofieldHashTable.put("LONG74", new Integer(LONG74));
+ nametofieldHashTable.put("LONG75", new Integer(LONG75));
+ nametofieldHashTable.put("LONG76", new Integer(LONG76));
+ nametofieldHashTable.put("LONG77", new Integer(LONG77));
+ nametofieldHashTable.put("LONG78", new Integer(LONG78));
+ nametofieldHashTable.put("LONG79", new Integer(LONG79));
+ nametofieldHashTable.put("LONG80", new Integer(LONG80));
+ nametofieldHashTable.put("LONG81", new Integer(LONG81));
+ nametofieldHashTable.put("LONG82", new Integer(LONG82));
+ nametofieldHashTable.put("LONG83", new Integer(LONG83));
+ nametofieldHashTable.put("LONG84", new Integer(LONG84));
+ nametofieldHashTable.put("LONG85", new Integer(LONG85));
+ nametofieldHashTable.put("LONG86", new Integer(LONG86));
+ nametofieldHashTable.put("LONG87", new Integer(LONG87));
+ nametofieldHashTable.put("LONG88", new Integer(LONG88));
+ nametofieldHashTable.put("LONG89", new Integer(LONG89));
+ nametofieldHashTable.put("LONG90", new Integer(LONG90));
+ nametofieldHashTable.put("LONG91", new Integer(LONG91));
+ nametofieldHashTable.put("LONG92", new Integer(LONG92));
+ nametofieldHashTable.put("LONG93", new Integer(LONG93));
+ nametofieldHashTable.put("LONG94", new Integer(LONG94));
+ nametofieldHashTable.put("LONG95", new Integer(LONG95));
+ nametofieldHashTable.put("LONG96", new Integer(LONG96));
+ nametofieldHashTable.put("LONG97", new Integer(LONG97));
+ nametofieldHashTable.put("LONG98", new Integer(LONG98));
+ nametofieldHashTable.put("LONG99", new Integer(LONG99));
+ nametofieldHashTable.put("LONG100", new Integer(LONG100));
+ nametofieldHashTable.put("DOUBLE1", new Integer(DOUBLE1));
+ nametofieldHashTable.put("DOUBLE2", new Integer(DOUBLE2));
+ nametofieldHashTable.put("DOUBLE3", new Integer(DOUBLE3));
+ nametofieldHashTable.put("DOUBLE4", new Integer(DOUBLE4));
+ nametofieldHashTable.put("DOUBLE5", new Integer(DOUBLE5));
+ nametofieldHashTable.put("DOUBLE6", new Integer(DOUBLE6));
+ nametofieldHashTable.put("DOUBLE7", new Integer(DOUBLE7));
+ nametofieldHashTable.put("DOUBLE8", new Integer(DOUBLE8));
+ nametofieldHashTable.put("DOUBLE9", new Integer(DOUBLE9));
+ nametofieldHashTable.put("DOUBLE10", new Integer(DOUBLE10));
+ nametofieldHashTable.put("DOUBLE11", new Integer(DOUBLE11));
+ nametofieldHashTable.put("DOUBLE12", new Integer(DOUBLE12));
+ nametofieldHashTable.put("DOUBLE13", new Integer(DOUBLE13));
+ nametofieldHashTable.put("DOUBLE14", new Integer(DOUBLE14));
+ nametofieldHashTable.put("DOUBLE15", new Integer(DOUBLE15));
+ nametofieldHashTable.put("DOUBLE16", new Integer(DOUBLE16));
+ nametofieldHashTable.put("DOUBLE17", new Integer(DOUBLE17));
+ nametofieldHashTable.put("DOUBLE18", new Integer(DOUBLE18));
+ nametofieldHashTable.put("DOUBLE19", new Integer(DOUBLE19));
+ nametofieldHashTable.put("DOUBLE20", new Integer(DOUBLE20));
+ nametofieldHashTable.put("DOUBLE21", new Integer(DOUBLE21));
+ nametofieldHashTable.put("DOUBLE22", new Integer(DOUBLE22));
+ nametofieldHashTable.put("DOUBLE23", new Integer(DOUBLE23));
+ nametofieldHashTable.put("DOUBLE24", new Integer(DOUBLE24));
+ nametofieldHashTable.put("DOUBLE25", new Integer(DOUBLE25));
+ nametofieldHashTable.put("DOUBLE26", new Integer(DOUBLE26));
+ nametofieldHashTable.put("DOUBLE27", new Integer(DOUBLE27));
+ nametofieldHashTable.put("DOUBLE28", new Integer(DOUBLE28));
+ nametofieldHashTable.put("DOUBLE29", new Integer(DOUBLE29));
+ nametofieldHashTable.put("DOUBLE30", new Integer(DOUBLE30));
+ nametofieldHashTable.put("DOUBLE31", new Integer(DOUBLE31));
+ nametofieldHashTable.put("DOUBLE32", new Integer(DOUBLE32));
+ nametofieldHashTable.put("DOUBLE33", new Integer(DOUBLE33));
+ nametofieldHashTable.put("DOUBLE34", new Integer(DOUBLE34));
+ nametofieldHashTable.put("DOUBLE35", new Integer(DOUBLE35));
+ nametofieldHashTable.put("DOUBLE36", new Integer(DOUBLE36));
+ nametofieldHashTable.put("DOUBLE37", new Integer(DOUBLE37));
+ nametofieldHashTable.put("DOUBLE38", new Integer(DOUBLE38));
+ nametofieldHashTable.put("DOUBLE39", new Integer(DOUBLE39));
+ nametofieldHashTable.put("DOUBLE40", new Integer(DOUBLE40));
+ nametofieldHashTable.put("DOUBLE41", new Integer(DOUBLE41));
+ nametofieldHashTable.put("DOUBLE42", new Integer(DOUBLE42));
+ nametofieldHashTable.put("DOUBLE43", new Integer(DOUBLE43));
+ nametofieldHashTable.put("DOUBLE44", new Integer(DOUBLE44));
+ nametofieldHashTable.put("DOUBLE45", new Integer(DOUBLE45));
+ nametofieldHashTable.put("DOUBLE46", new Integer(DOUBLE46));
+ nametofieldHashTable.put("DOUBLE47", new Integer(DOUBLE47));
+ nametofieldHashTable.put("DOUBLE48", new Integer(DOUBLE48));
+ nametofieldHashTable.put("DOUBLE49", new Integer(DOUBLE49));
+ nametofieldHashTable.put("DOUBLE50", new Integer(DOUBLE50));
+ nametofieldHashTable.put("DOUBLE51", new Integer(DOUBLE51));
+ nametofieldHashTable.put("DOUBLE52", new Integer(DOUBLE52));
+ nametofieldHashTable.put("DOUBLE53", new Integer(DOUBLE53));
+ nametofieldHashTable.put("DOUBLE54", new Integer(DOUBLE54));
+ nametofieldHashTable.put("DOUBLE55", new Integer(DOUBLE55));
+ nametofieldHashTable.put("DOUBLE56", new Integer(DOUBLE56));
+ nametofieldHashTable.put("DOUBLE57", new Integer(DOUBLE57));
+ nametofieldHashTable.put("DOUBLE58", new Integer(DOUBLE58));
+ nametofieldHashTable.put("DOUBLE59", new Integer(DOUBLE59));
+ nametofieldHashTable.put("DOUBLE60", new Integer(DOUBLE60));
+ nametofieldHashTable.put("DOUBLE61", new Integer(DOUBLE61));
+ nametofieldHashTable.put("DOUBLE62", new Integer(DOUBLE62));
+ nametofieldHashTable.put("DOUBLE63", new Integer(DOUBLE63));
+ nametofieldHashTable.put("DOUBLE64", new Integer(DOUBLE64));
+ nametofieldHashTable.put("DOUBLE65", new Integer(DOUBLE65));
+ nametofieldHashTable.put("DOUBLE66", new Integer(DOUBLE66));
+ nametofieldHashTable.put("DOUBLE67", new Integer(DOUBLE67));
+ nametofieldHashTable.put("DOUBLE68", new Integer(DOUBLE68));
+ nametofieldHashTable.put("DOUBLE69", new Integer(DOUBLE69));
+ nametofieldHashTable.put("DOUBLE70", new Integer(DOUBLE70));
+ nametofieldHashTable.put("DOUBLE71", new Integer(DOUBLE71));
+ nametofieldHashTable.put("DOUBLE72", new Integer(DOUBLE72));
+ nametofieldHashTable.put("DOUBLE73", new Integer(DOUBLE73));
+ nametofieldHashTable.put("DOUBLE74", new Integer(DOUBLE74));
+ nametofieldHashTable.put("DOUBLE75", new Integer(DOUBLE75));
+ nametofieldHashTable.put("DOUBLE76", new Integer(DOUBLE76));
+ nametofieldHashTable.put("DOUBLE77", new Integer(DOUBLE77));
+ nametofieldHashTable.put("DOUBLE78", new Integer(DOUBLE78));
+ nametofieldHashTable.put("DOUBLE79", new Integer(DOUBLE79));
+ nametofieldHashTable.put("DOUBLE80", new Integer(DOUBLE80));
+ nametofieldHashTable.put("DOUBLE81", new Integer(DOUBLE81));
+ nametofieldHashTable.put("DOUBLE82", new Integer(DOUBLE82));
+ nametofieldHashTable.put("DOUBLE83", new Integer(DOUBLE83));
+ nametofieldHashTable.put("DOUBLE84", new Integer(DOUBLE84));
+ nametofieldHashTable.put("DOUBLE85", new Integer(DOUBLE85));
+ nametofieldHashTable.put("DOUBLE86", new Integer(DOUBLE86));
+ nametofieldHashTable.put("DOUBLE87", new Integer(DOUBLE87));
+ nametofieldHashTable.put("DOUBLE88", new Integer(DOUBLE88));
+ nametofieldHashTable.put("DOUBLE89", new Integer(DOUBLE89));
+ nametofieldHashTable.put("DOUBLE90", new Integer(DOUBLE90));
+ nametofieldHashTable.put("DOUBLE91", new Integer(DOUBLE91));
+ nametofieldHashTable.put("DOUBLE92", new Integer(DOUBLE92));
+ nametofieldHashTable.put("DOUBLE93", new Integer(DOUBLE93));
+ nametofieldHashTable.put("DOUBLE94", new Integer(DOUBLE94));
+ nametofieldHashTable.put("DOUBLE95", new Integer(DOUBLE95));
+ nametofieldHashTable.put("DOUBLE96", new Integer(DOUBLE96));
+ nametofieldHashTable.put("DOUBLE97", new Integer(DOUBLE97));
+ nametofieldHashTable.put("DOUBLE98", new Integer(DOUBLE98));
+ nametofieldHashTable.put("DOUBLE99", new Integer(DOUBLE99));
+ nametofieldHashTable.put("DOUBLE100", new Integer(DOUBLE100));
+ nametofieldHashTable.put("DOUBLE101", new Integer(DOUBLE101));
+ nametofieldHashTable.put("DOUBLE102", new Integer(DOUBLE102));
+ nametofieldHashTable.put("DOUBLE103", new Integer(DOUBLE103));
+ nametofieldHashTable.put("DOUBLE104", new Integer(DOUBLE104));
+ nametofieldHashTable.put("DOUBLE105", new Integer(DOUBLE105));
+ nametofieldHashTable.put("DOUBLE106", new Integer(DOUBLE106));
+ nametofieldHashTable.put("DOUBLE107", new Integer(DOUBLE107));
+ nametofieldHashTable.put("DOUBLE108", new Integer(DOUBLE108));
+ nametofieldHashTable.put("DOUBLE109", new Integer(DOUBLE109));
+ nametofieldHashTable.put("DOUBLE110", new Integer(DOUBLE110));
+ nametofieldHashTable.put("DOUBLE111", new Integer(DOUBLE111));
+ nametofieldHashTable.put("DOUBLE112", new Integer(DOUBLE112));
+ nametofieldHashTable.put("DOUBLE113", new Integer(DOUBLE113));
+ nametofieldHashTable.put("DOUBLE114", new Integer(DOUBLE114));
+ nametofieldHashTable.put("DOUBLE115", new Integer(DOUBLE115));
+ nametofieldHashTable.put("DOUBLE116", new Integer(DOUBLE116));
+ nametofieldHashTable.put("DOUBLE117", new Integer(DOUBLE117));
+ nametofieldHashTable.put("DOUBLE118", new Integer(DOUBLE118));
+ nametofieldHashTable.put("DOUBLE119", new Integer(DOUBLE119));
+ nametofieldHashTable.put("DOUBLE120", new Integer(DOUBLE120));
+ nametofieldHashTable.put("DOUBLE121", new Integer(DOUBLE121));
+ nametofieldHashTable.put("DOUBLE122", new Integer(DOUBLE122));
+ nametofieldHashTable.put("DOUBLE123", new Integer(DOUBLE123));
+ nametofieldHashTable.put("DOUBLE124", new Integer(DOUBLE124));
+ nametofieldHashTable.put("DOUBLE125", new Integer(DOUBLE125));
+ nametofieldHashTable.put("DOUBLE126", new Integer(DOUBLE126));
+ nametofieldHashTable.put("DOUBLE127", new Integer(DOUBLE127));
+ nametofieldHashTable.put("DOUBLE128", new Integer(DOUBLE128));
+ nametofieldHashTable.put("DOUBLE129", new Integer(DOUBLE129));
+ nametofieldHashTable.put("DOUBLE130", new Integer(DOUBLE130));
+ nametofieldHashTable.put("DOUBLE131", new Integer(DOUBLE131));
+ nametofieldHashTable.put("DOUBLE132", new Integer(DOUBLE132));
+ nametofieldHashTable.put("DOUBLE133", new Integer(DOUBLE133));
+ nametofieldHashTable.put("DOUBLE134", new Integer(DOUBLE134));
+ nametofieldHashTable.put("DOUBLE135", new Integer(DOUBLE135));
+ nametofieldHashTable.put("DOUBLE136", new Integer(DOUBLE136));
+ nametofieldHashTable.put("DOUBLE137", new Integer(DOUBLE137));
+ nametofieldHashTable.put("DOUBLE138", new Integer(DOUBLE138));
+ nametofieldHashTable.put("DOUBLE139", new Integer(DOUBLE139));
+ nametofieldHashTable.put("DOUBLE140", new Integer(DOUBLE140));
+ nametofieldHashTable.put("DOUBLE141", new Integer(DOUBLE141));
+ nametofieldHashTable.put("DOUBLE142", new Integer(DOUBLE142));
+ nametofieldHashTable.put("DOUBLE143", new Integer(DOUBLE143));
+ nametofieldHashTable.put("DOUBLE144", new Integer(DOUBLE144));
+ nametofieldHashTable.put("DOUBLE145", new Integer(DOUBLE145));
+ nametofieldHashTable.put("DOUBLE146", new Integer(DOUBLE146));
+ nametofieldHashTable.put("DOUBLE147", new Integer(DOUBLE147));
+ nametofieldHashTable.put("DOUBLE148", new Integer(DOUBLE148));
+ nametofieldHashTable.put("DOUBLE149", new Integer(DOUBLE149));
+ nametofieldHashTable.put("DOUBLE150", new Integer(DOUBLE150));
+ nametofieldHashTable.put("DOUBLE151", new Integer(DOUBLE151));
+ nametofieldHashTable.put("DOUBLE152", new Integer(DOUBLE152));
+ nametofieldHashTable.put("DOUBLE153", new Integer(DOUBLE153));
+ nametofieldHashTable.put("DOUBLE154", new Integer(DOUBLE154));
+ nametofieldHashTable.put("DOUBLE155", new Integer(DOUBLE155));
+ nametofieldHashTable.put("DOUBLE156", new Integer(DOUBLE156));
+ nametofieldHashTable.put("DOUBLE157", new Integer(DOUBLE157));
+ nametofieldHashTable.put("DOUBLE158", new Integer(DOUBLE158));
+ nametofieldHashTable.put("DOUBLE159", new Integer(DOUBLE159));
+ nametofieldHashTable.put("DOUBLE160", new Integer(DOUBLE160));
+ nametofieldHashTable.put("DOUBLE161", new Integer(DOUBLE161));
+ nametofieldHashTable.put("DOUBLE162", new Integer(DOUBLE162));
+ nametofieldHashTable.put("DOUBLE163", new Integer(DOUBLE163));
+ nametofieldHashTable.put("DOUBLE164", new Integer(DOUBLE164));
+ nametofieldHashTable.put("DOUBLE165", new Integer(DOUBLE165));
+ nametofieldHashTable.put("DOUBLE166", new Integer(DOUBLE166));
+ nametofieldHashTable.put("DOUBLE167", new Integer(DOUBLE167));
+ nametofieldHashTable.put("DOUBLE168", new Integer(DOUBLE168));
+ nametofieldHashTable.put("DOUBLE169", new Integer(DOUBLE169));
+ nametofieldHashTable.put("DOUBLE170", new Integer(DOUBLE170));
+ nametofieldHashTable.put("DOUBLE171", new Integer(DOUBLE171));
+ nametofieldHashTable.put("DOUBLE172", new Integer(DOUBLE172));
+ nametofieldHashTable.put("DOUBLE173", new Integer(DOUBLE173));
+ nametofieldHashTable.put("DOUBLE174", new Integer(DOUBLE174));
+ nametofieldHashTable.put("DOUBLE175", new Integer(DOUBLE175));
+ nametofieldHashTable.put("DOUBLE176", new Integer(DOUBLE176));
+ nametofieldHashTable.put("DOUBLE177", new Integer(DOUBLE177));
+ nametofieldHashTable.put("DOUBLE178", new Integer(DOUBLE178));
+ nametofieldHashTable.put("DOUBLE179", new Integer(DOUBLE179));
+ nametofieldHashTable.put("DOUBLE180", new Integer(DOUBLE180));
+ nametofieldHashTable.put("DOUBLE181", new Integer(DOUBLE181));
+ nametofieldHashTable.put("DOUBLE182", new Integer(DOUBLE182));
+ nametofieldHashTable.put("DOUBLE183", new Integer(DOUBLE183));
+ nametofieldHashTable.put("DOUBLE184", new Integer(DOUBLE184));
+ nametofieldHashTable.put("DOUBLE185", new Integer(DOUBLE185));
+ nametofieldHashTable.put("DOUBLE186", new Integer(DOUBLE186));
+ nametofieldHashTable.put("DOUBLE187", new Integer(DOUBLE187));
+ nametofieldHashTable.put("DOUBLE188", new Integer(DOUBLE188));
+ nametofieldHashTable.put("DOUBLE189", new Integer(DOUBLE189));
+ nametofieldHashTable.put("DOUBLE190", new Integer(DOUBLE190));
+ nametofieldHashTable.put("DOUBLE191", new Integer(DOUBLE191));
+ nametofieldHashTable.put("DOUBLE192", new Integer(DOUBLE192));
+ nametofieldHashTable.put("DOUBLE193", new Integer(DOUBLE193));
+ nametofieldHashTable.put("DOUBLE194", new Integer(DOUBLE194));
+ nametofieldHashTable.put("DOUBLE195", new Integer(DOUBLE195));
+ nametofieldHashTable.put("DOUBLE196", new Integer(DOUBLE196));
+ nametofieldHashTable.put("DOUBLE197", new Integer(DOUBLE197));
+ nametofieldHashTable.put("DOUBLE198", new Integer(DOUBLE198));
+ nametofieldHashTable.put("DOUBLE199", new Integer(DOUBLE199));
+ nametofieldHashTable.put("DOUBLE200", new Integer(DOUBLE200));
+ nametofieldHashTable.put("SVCNAME", new Integer(SVCNAME));
+ nametofieldHashTable.put("TPURCODE", new Integer(TPURCODE));
+ }
+
+ Integer fld = (Integer)nametofieldHashTable.get(name);
+ if (fld == null) {
+ return (-1);
+ } else {
+ return (fld.intValue());
+ }
+ }
+
+ public String[] getFldNames()
+ {
+ String retval[] = new String[502];
+ retval[0] = new String("STRING1");
+ retval[1] = new String("STRING2");
+ retval[2] = new String("STRING3");
+ retval[3] = new String("STRING4");
+ retval[4] = new String("STRING5");
+ retval[5] = new String("STRING6");
+ retval[6] = new String("STRING7");
+ retval[7] = new String("STRING8");
+ retval[8] = new String("STRING9");
+ retval[9] = new String("STRING10");
+ retval[10] = new String("STRING11");
+ retval[11] = new String("STRING12");
+ retval[12] = new String("STRING13");
+ retval[13] = new String("STRING14");
+ retval[14] = new String("STRING15");
+ retval[15] = new String("STRING16");
+ retval[16] = new String("STRING17");
+ retval[17] = new String("STRING18");
+ retval[18] = new String("STRING19");
+ retval[19] = new String("STRING20");
+ retval[20] = new String("STRING21");
+ retval[21] = new String("STRING22");
+ retval[22] = new String("STRING23");
+ retval[23] = new String("STRING24");
+ retval[24] = new String("STRING25");
+ retval[25] = new String("STRING26");
+ retval[26] = new String("STRING27");
+ retval[27] = new String("STRING28");
+ retval[28] = new String("STRING29");
+ retval[29] = new String("STRING30");
+ retval[30] = new String("STRING31");
+ retval[31] = new String("STRING32");
+ retval[32] = new String("STRING33");
+ retval[33] = new String("STRING34");
+ retval[34] = new String("STRING35");
+ retval[35] = new String("STRING36");
+ retval[36] = new String("STRING37");
+ retval[37] = new String("STRING38");
+ retval[38] = new String("STRING39");
+ retval[39] = new String("STRING40");
+ retval[40] = new String("STRING41");
+ retval[41] = new String("STRING42");
+ retval[42] = new String("STRING43");
+ retval[43] = new String("STRING44");
+ retval[44] = new String("STRING45");
+ retval[45] = new String("STRING46");
+ retval[46] = new String("STRING47");
+ retval[47] = new String("STRING48");
+ retval[48] = new String("STRING49");
+ retval[49] = new String("STRING50");
+ retval[50] = new String("STRING51");
+ retval[51] = new String("STRING52");
+ retval[52] = new String("STRING53");
+ retval[53] = new String("STRING54");
+ retval[54] = new String("STRING55");
+ retval[55] = new String("STRING56");
+ retval[56] = new String("STRING57");
+ retval[57] = new String("STRING58");
+ retval[58] = new String("STRING59");
+ retval[59] = new String("STRING60");
+ retval[60] = new String("STRING61");
+ retval[61] = new String("STRING62");
+ retval[62] = new String("STRING63");
+ retval[63] = new String("STRING64");
+ retval[64] = new String("STRING65");
+ retval[65] = new String("STRING66");
+ retval[66] = new String("STRING67");
+ retval[67] = new String("STRING68");
+ retval[68] = new String("STRING69");
+ retval[69] = new String("STRING70");
+ retval[70] = new String("STRING71");
+ retval[71] = new String("STRING72");
+ retval[72] = new String("STRING73");
+ retval[73] = new String("STRING74");
+ retval[74] = new String("STRING75");
+ retval[75] = new String("STRING76");
+ retval[76] = new String("STRING77");
+ retval[77] = new String("STRING78");
+ retval[78] = new String("STRING79");
+ retval[79] = new String("STRING80");
+ retval[80] = new String("STRING81");
+ retval[81] = new String("STRING82");
+ retval[82] = new String("STRING83");
+ retval[83] = new String("STRING84");
+ retval[84] = new String("STRING85");
+ retval[85] = new String("STRING86");
+ retval[86] = new String("STRING87");
+ retval[87] = new String("STRING88");
+ retval[88] = new String("STRING89");
+ retval[89] = new String("STRING90");
+ retval[90] = new String("STRING91");
+ retval[91] = new String("STRING92");
+ retval[92] = new String("STRING93");
+ retval[93] = new String("STRING94");
+ retval[94] = new String("STRING95");
+ retval[95] = new String("STRING96");
+ retval[96] = new String("STRING97");
+ retval[97] = new String("STRING98");
+ retval[98] = new String("STRING99");
+ retval[99] = new String("STRING100");
+ retval[100] = new String("STRING101");
+ retval[101] = new String("STRING102");
+ retval[102] = new String("STRING103");
+ retval[103] = new String("STRING104");
+ retval[104] = new String("STRING105");
+ retval[105] = new String("STRING106");
+ retval[106] = new String("STRING107");
+ retval[107] = new String("STRING108");
+ retval[108] = new String("STRING109");
+ retval[109] = new String("STRING110");
+ retval[110] = new String("STRING111");
+ retval[111] = new String("STRING112");
+ retval[112] = new String("STRING113");
+ retval[113] = new String("STRING114");
+ retval[114] = new String("STRING115");
+ retval[115] = new String("STRING116");
+ retval[116] = new String("STRING117");
+ retval[117] = new String("STRING118");
+ retval[118] = new String("STRING119");
+ retval[119] = new String("STRING120");
+ retval[120] = new String("STRING121");
+ retval[121] = new String("STRING122");
+ retval[122] = new String("STRING123");
+ retval[123] = new String("STRING124");
+ retval[124] = new String("STRING125");
+ retval[125] = new String("STRING126");
+ retval[126] = new String("STRING127");
+ retval[127] = new String("STRING128");
+ retval[128] = new String("STRING129");
+ retval[129] = new String("STRING130");
+ retval[130] = new String("STRING131");
+ retval[131] = new String("STRING132");
+ retval[132] = new String("STRING133");
+ retval[133] = new String("STRING134");
+ retval[134] = new String("STRING135");
+ retval[135] = new String("STRING136");
+ retval[136] = new String("STRING137");
+ retval[137] = new String("STRING138");
+ retval[138] = new String("STRING139");
+ retval[139] = new String("STRING140");
+ retval[140] = new String("STRING141");
+ retval[141] = new String("STRING142");
+ retval[142] = new String("STRING143");
+ retval[143] = new String("STRING144");
+ retval[144] = new String("STRING145");
+ retval[145] = new String("STRING146");
+ retval[146] = new String("STRING147");
+ retval[147] = new String("STRING148");
+ retval[148] = new String("STRING149");
+ retval[149] = new String("STRING150");
+ retval[150] = new String("STRING151");
+ retval[151] = new String("STRING152");
+ retval[152] = new String("STRING153");
+ retval[153] = new String("STRING154");
+ retval[154] = new String("STRING155");
+ retval[155] = new String("STRING156");
+ retval[156] = new String("STRING157");
+ retval[157] = new String("STRING158");
+ retval[158] = new String("STRING159");
+ retval[159] = new String("STRING160");
+ retval[160] = new String("STRING161");
+ retval[161] = new String("STRING162");
+ retval[162] = new String("STRING163");
+ retval[163] = new String("STRING164");
+ retval[164] = new String("STRING165");
+ retval[165] = new String("STRING166");
+ retval[166] = new String("STRING167");
+ retval[167] = new String("STRING168");
+ retval[168] = new String("STRING169");
+ retval[169] = new String("STRING170");
+ retval[170] = new String("STRING171");
+ retval[171] = new String("STRING172");
+ retval[172] = new String("STRING173");
+ retval[173] = new String("STRING174");
+ retval[174] = new String("STRING175");
+ retval[175] = new String("STRING176");
+ retval[176] = new String("STRING177");
+ retval[177] = new String("STRING178");
+ retval[178] = new String("STRING179");
+ retval[179] = new String("STRING180");
+ retval[180] = new String("STRING181");
+ retval[181] = new String("STRING182");
+ retval[182] = new String("STRING183");
+ retval[183] = new String("STRING184");
+ retval[184] = new String("STRING185");
+ retval[185] = new String("STRING186");
+ retval[186] = new String("STRING187");
+ retval[187] = new String("STRING188");
+ retval[188] = new String("STRING189");
+ retval[189] = new String("STRING190");
+ retval[190] = new String("STRING191");
+ retval[191] = new String("STRING192");
+ retval[192] = new String("STRING193");
+ retval[193] = new String("STRING194");
+ retval[194] = new String("STRING195");
+ retval[195] = new String("STRING196");
+ retval[196] = new String("STRING197");
+ retval[197] = new String("STRING198");
+ retval[198] = new String("STRING199");
+ retval[199] = new String("STRING200");
+ retval[200] = new String("LONG1");
+ retval[201] = new String("LONG2");
+ retval[202] = new String("LONG3");
+ retval[203] = new String("LONG4");
+ retval[204] = new String("LONG5");
+ retval[205] = new String("LONG6");
+ retval[206] = new String("LONG7");
+ retval[207] = new String("LONG8");
+ retval[208] = new String("LONG9");
+ retval[209] = new String("LONG10");
+ retval[210] = new String("LONG11");
+ retval[211] = new String("LONG12");
+ retval[212] = new String("LONG13");
+ retval[213] = new String("LONG14");
+ retval[214] = new String("LONG15");
+ retval[215] = new String("LONG16");
+ retval[216] = new String("LONG17");
+ retval[217] = new String("LONG18");
+ retval[218] = new String("LONG19");
+ retval[219] = new String("LONG20");
+ retval[220] = new String("LONG21");
+ retval[221] = new String("LONG22");
+ retval[222] = new String("LONG23");
+ retval[223] = new String("LONG24");
+ retval[224] = new String("LONG25");
+ retval[225] = new String("LONG26");
+ retval[226] = new String("LONG27");
+ retval[227] = new String("LONG28");
+ retval[228] = new String("LONG29");
+ retval[229] = new String("LONG30");
+ retval[230] = new String("LONG31");
+ retval[231] = new String("LONG32");
+ retval[232] = new String("LONG33");
+ retval[233] = new String("LONG34");
+ retval[234] = new String("LONG35");
+ retval[235] = new String("LONG36");
+ retval[236] = new String("LONG37");
+ retval[237] = new String("LONG38");
+ retval[238] = new String("LONG39");
+ retval[239] = new String("LONG40");
+ retval[240] = new String("LONG41");
+ retval[241] = new String("LONG42");
+ retval[242] = new String("LONG43");
+ retval[243] = new String("LONG44");
+ retval[244] = new String("LONG45");
+ retval[245] = new String("LONG46");
+ retval[246] = new String("LONG47");
+ retval[247] = new String("LONG48");
+ retval[248] = new String("LONG49");
+ retval[249] = new String("LONG50");
+ retval[250] = new String("LONG51");
+ retval[251] = new String("LONG52");
+ retval[252] = new String("LONG53");
+ retval[253] = new String("LONG54");
+ retval[254] = new String("LONG55");
+ retval[255] = new String("LONG56");
+ retval[256] = new String("LONG57");
+ retval[257] = new String("LONG58");
+ retval[258] = new String("LONG59");
+ retval[259] = new String("LONG60");
+ retval[260] = new String("LONG61");
+ retval[261] = new String("LONG62");
+ retval[262] = new String("LONG63");
+ retval[263] = new String("LONG64");
+ retval[264] = new String("LONG65");
+ retval[265] = new String("LONG66");
+ retval[266] = new String("LONG67");
+ retval[267] = new String("LONG68");
+ retval[268] = new String("LONG69");
+ retval[269] = new String("LONG70");
+ retval[270] = new String("LONG71");
+ retval[271] = new String("LONG72");
+ retval[272] = new String("LONG73");
+ retval[273] = new String("LONG74");
+ retval[274] = new String("LONG75");
+ retval[275] = new String("LONG76");
+ retval[276] = new String("LONG77");
+ retval[277] = new String("LONG78");
+ retval[278] = new String("LONG79");
+ retval[279] = new String("LONG80");
+ retval[280] = new String("LONG81");
+ retval[281] = new String("LONG82");
+ retval[282] = new String("LONG83");
+ retval[283] = new String("LONG84");
+ retval[284] = new String("LONG85");
+ retval[285] = new String("LONG86");
+ retval[286] = new String("LONG87");
+ retval[287] = new String("LONG88");
+ retval[288] = new String("LONG89");
+ retval[289] = new String("LONG90");
+ retval[290] = new String("LONG91");
+ retval[291] = new String("LONG92");
+ retval[292] = new String("LONG93");
+ retval[293] = new String("LONG94");
+ retval[294] = new String("LONG95");
+ retval[295] = new String("LONG96");
+ retval[296] = new String("LONG97");
+ retval[297] = new String("LONG98");
+ retval[298] = new String("LONG99");
+ retval[299] = new String("LONG100");
+ retval[300] = new String("DOUBLE1");
+ retval[301] = new String("DOUBLE2");
+ retval[302] = new String("DOUBLE3");
+ retval[303] = new String("DOUBLE4");
+ retval[304] = new String("DOUBLE5");
+ retval[305] = new String("DOUBLE6");
+ retval[306] = new String("DOUBLE7");
+ retval[307] = new String("DOUBLE8");
+ retval[308] = new String("DOUBLE9");
+ retval[309] = new String("DOUBLE10");
+ retval[310] = new String("DOUBLE11");
+ retval[311] = new String("DOUBLE12");
+ retval[312] = new String("DOUBLE13");
+ retval[313] = new String("DOUBLE14");
+ retval[314] = new String("DOUBLE15");
+ retval[315] = new String("DOUBLE16");
+ retval[316] = new String("DOUBLE17");
+ retval[317] = new String("DOUBLE18");
+ retval[318] = new String("DOUBLE19");
+ retval[319] = new String("DOUBLE20");
+ retval[320] = new String("DOUBLE21");
+ retval[321] = new String("DOUBLE22");
+ retval[322] = new String("DOUBLE23");
+ retval[323] = new String("DOUBLE24");
+ retval[324] = new String("DOUBLE25");
+ retval[325] = new String("DOUBLE26");
+ retval[326] = new String("DOUBLE27");
+ retval[327] = new String("DOUBLE28");
+ retval[328] = new String("DOUBLE29");
+ retval[329] = new String("DOUBLE30");
+ retval[330] = new String("DOUBLE31");
+ retval[331] = new String("DOUBLE32");
+ retval[332] = new String("DOUBLE33");
+ retval[333] = new String("DOUBLE34");
+ retval[334] = new String("DOUBLE35");
+ retval[335] = new String("DOUBLE36");
+ retval[336] = new String("DOUBLE37");
+ retval[337] = new String("DOUBLE38");
+ retval[338] = new String("DOUBLE39");
+ retval[339] = new String("DOUBLE40");
+ retval[340] = new String("DOUBLE41");
+ retval[341] = new String("DOUBLE42");
+ retval[342] = new String("DOUBLE43");
+ retval[343] = new String("DOUBLE44");
+ retval[344] = new String("DOUBLE45");
+ retval[345] = new String("DOUBLE46");
+ retval[346] = new String("DOUBLE47");
+ retval[347] = new String("DOUBLE48");
+ retval[348] = new String("DOUBLE49");
+ retval[349] = new String("DOUBLE50");
+ retval[350] = new String("DOUBLE51");
+ retval[351] = new String("DOUBLE52");
+ retval[352] = new String("DOUBLE53");
+ retval[353] = new String("DOUBLE54");
+ retval[354] = new String("DOUBLE55");
+ retval[355] = new String("DOUBLE56");
+ retval[356] = new String("DOUBLE57");
+ retval[357] = new String("DOUBLE58");
+ retval[358] = new String("DOUBLE59");
+ retval[359] = new String("DOUBLE60");
+ retval[360] = new String("DOUBLE61");
+ retval[361] = new String("DOUBLE62");
+ retval[362] = new String("DOUBLE63");
+ retval[363] = new String("DOUBLE64");
+ retval[364] = new String("DOUBLE65");
+ retval[365] = new String("DOUBLE66");
+ retval[366] = new String("DOUBLE67");
+ retval[367] = new String("DOUBLE68");
+ retval[368] = new String("DOUBLE69");
+ retval[369] = new String("DOUBLE70");
+ retval[370] = new String("DOUBLE71");
+ retval[371] = new String("DOUBLE72");
+ retval[372] = new String("DOUBLE73");
+ retval[373] = new String("DOUBLE74");
+ retval[374] = new String("DOUBLE75");
+ retval[375] = new String("DOUBLE76");
+ retval[376] = new String("DOUBLE77");
+ retval[377] = new String("DOUBLE78");
+ retval[378] = new String("DOUBLE79");
+ retval[379] = new String("DOUBLE80");
+ retval[380] = new String("DOUBLE81");
+ retval[381] = new String("DOUBLE82");
+ retval[382] = new String("DOUBLE83");
+ retval[383] = new String("DOUBLE84");
+ retval[384] = new String("DOUBLE85");
+ retval[385] = new String("DOUBLE86");
+ retval[386] = new String("DOUBLE87");
+ retval[387] = new String("DOUBLE88");
+ retval[388] = new String("DOUBLE89");
+ retval[389] = new String("DOUBLE90");
+ retval[390] = new String("DOUBLE91");
+ retval[391] = new String("DOUBLE92");
+ retval[392] = new String("DOUBLE93");
+ retval[393] = new String("DOUBLE94");
+ retval[394] = new String("DOUBLE95");
+ retval[395] = new String("DOUBLE96");
+ retval[396] = new String("DOUBLE97");
+ retval[397] = new String("DOUBLE98");
+ retval[398] = new String("DOUBLE99");
+ retval[399] = new String("DOUBLE100");
+ retval[400] = new String("DOUBLE101");
+ retval[401] = new String("DOUBLE102");
+ retval[402] = new String("DOUBLE103");
+ retval[403] = new String("DOUBLE104");
+ retval[404] = new String("DOUBLE105");
+ retval[405] = new String("DOUBLE106");
+ retval[406] = new String("DOUBLE107");
+ retval[407] = new String("DOUBLE108");
+ retval[408] = new String("DOUBLE109");
+ retval[409] = new String("DOUBLE110");
+ retval[410] = new String("DOUBLE111");
+ retval[411] = new String("DOUBLE112");
+ retval[412] = new String("DOUBLE113");
+ retval[413] = new String("DOUBLE114");
+ retval[414] = new String("DOUBLE115");
+ retval[415] = new String("DOUBLE116");
+ retval[416] = new String("DOUBLE117");
+ retval[417] = new String("DOUBLE118");
+ retval[418] = new String("DOUBLE119");
+ retval[419] = new String("DOUBLE120");
+ retval[420] = new String("DOUBLE121");
+ retval[421] = new String("DOUBLE122");
+ retval[422] = new String("DOUBLE123");
+ retval[423] = new String("DOUBLE124");
+ retval[424] = new String("DOUBLE125");
+ retval[425] = new String("DOUBLE126");
+ retval[426] = new String("DOUBLE127");
+ retval[427] = new String("DOUBLE128");
+ retval[428] = new String("DOUBLE129");
+ retval[429] = new String("DOUBLE130");
+ retval[430] = new String("DOUBLE131");
+ retval[431] = new String("DOUBLE132");
+ retval[432] = new String("DOUBLE133");
+ retval[433] = new String("DOUBLE134");
+ retval[434] = new String("DOUBLE135");
+ retval[435] = new String("DOUBLE136");
+ retval[436] = new String("DOUBLE137");
+ retval[437] = new String("DOUBLE138");
+ retval[438] = new String("DOUBLE139");
+ retval[439] = new String("DOUBLE140");
+ retval[440] = new String("DOUBLE141");
+ retval[441] = new String("DOUBLE142");
+ retval[442] = new String("DOUBLE143");
+ retval[443] = new String("DOUBLE144");
+ retval[444] = new String("DOUBLE145");
+ retval[445] = new String("DOUBLE146");
+ retval[446] = new String("DOUBLE147");
+ retval[447] = new String("DOUBLE148");
+ retval[448] = new String("DOUBLE149");
+ retval[449] = new String("DOUBLE150");
+ retval[450] = new String("DOUBLE151");
+ retval[451] = new String("DOUBLE152");
+ retval[452] = new String("DOUBLE153");
+ retval[453] = new String("DOUBLE154");
+ retval[454] = new String("DOUBLE155");
+ retval[455] = new String("DOUBLE156");
+ retval[456] = new String("DOUBLE157");
+ retval[457] = new String("DOUBLE158");
+ retval[458] = new String("DOUBLE159");
+ retval[459] = new String("DOUBLE160");
+ retval[460] = new String("DOUBLE161");
+ retval[461] = new String("DOUBLE162");
+ retval[462] = new String("DOUBLE163");
+ retval[463] = new String("DOUBLE164");
+ retval[464] = new String("DOUBLE165");
+ retval[465] = new String("DOUBLE166");
+ retval[466] = new String("DOUBLE167");
+ retval[467] = new String("DOUBLE168");
+ retval[468] = new String("DOUBLE169");
+ retval[469] = new String("DOUBLE170");
+ retval[470] = new String("DOUBLE171");
+ retval[471] = new String("DOUBLE172");
+ retval[472] = new String("DOUBLE173");
+ retval[473] = new String("DOUBLE174");
+ retval[474] = new String("DOUBLE175");
+ retval[475] = new String("DOUBLE176");
+ retval[476] = new String("DOUBLE177");
+ retval[477] = new String("DOUBLE178");
+ retval[478] = new String("DOUBLE179");
+ retval[479] = new String("DOUBLE180");
+ retval[480] = new String("DOUBLE181");
+ retval[481] = new String("DOUBLE182");
+ retval[482] = new String("DOUBLE183");
+ retval[483] = new String("DOUBLE184");
+ retval[484] = new String("DOUBLE185");
+ retval[485] = new String("DOUBLE186");
+ retval[486] = new String("DOUBLE187");
+ retval[487] = new String("DOUBLE188");
+ retval[488] = new String("DOUBLE189");
+ retval[489] = new String("DOUBLE190");
+ retval[490] = new String("DOUBLE191");
+ retval[491] = new String("DOUBLE192");
+ retval[492] = new String("DOUBLE193");
+ retval[493] = new String("DOUBLE194");
+ retval[494] = new String("DOUBLE195");
+ retval[495] = new String("DOUBLE196");
+ retval[496] = new String("DOUBLE197");
+ retval[497] = new String("DOUBLE198");
+ retval[498] = new String("DOUBLE199");
+ retval[499] = new String("DOUBLE200");
+ retval[500] = new String("SVCNAME");
+ retval[501] = new String("TPURCODE");
+ return retval;
+ }
+
+ public int getVersion() {
+ return 1;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/jtc/JtcBeanSample.java b/src/main/java/com/eactive/eai/adapter/jtc/JtcBeanSample.java
new file mode 100644
index 0000000..705afc9
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/jtc/JtcBeanSample.java
@@ -0,0 +1,84 @@
+package com.eactive.eai.adapter.jtc;
+
+import tmax.common.BufferAccess;
+import tmax.jtc.io.TuxCarrayBuffer;
+import tmax.jtc.io.TuxFieldBuffer;
+import tmax.jtc.io.TuxStringBuffer;
+import tmax.jtmax.JtmaxService;
+import tmax.webt.WebtException;
+import tmax.webt.WebtSystem;
+
+// TUXEDO -> JEUS
+//1.2.2. Bean 서비스 호출 설정
+// JTC 인바운드 통신을 통해 Bean 서비스를 호출하려면 다음과 같은 설정이 필요하다.
+//
+// webt.properties 설정 ($JEUS_HOME/lib/application)
+//JEUS SIDE
+//webt.properties
+//tux.beans.service.list = GSVC02
+//tux.beans.GSVC02.class = test.JtcBeanSample
+// Tuxedo 환경설정
+//TUX Side
+//*SERVICE
+//GSVC02
+// Tuxedo 도메인 환경설정
+//*DM_REMOTE_SERVICES
+//GSVC01
+// RNAME = "GSVC01"
+// RDOM = "TUXGW1"
+//
+//*DM_TDOMAIN
+//TUXGW1 NWADDR = "//192.168.37.100:9521"
+// JEUS와 Tuxedo 기동
+
+public class JtcBeanSample implements JtmaxService {
+
+ public void destroy() throws Exception {
+
+ }
+
+ public void initialize() throws Exception {
+
+ }
+
+ public BufferAccess service(BufferAccess tux) throws WebtException {
+ String bufferType = tux.getBufferTypeString();
+ if ("STRING".equals(bufferType)) {
+ TuxStringBuffer tuxbuf = (TuxStringBuffer) tux;
+ System.out.println("received string value : " + tuxbuf.getString());
+ TuxStringBuffer ret = new TuxStringBuffer(WebtSystem.getDefaultCharset());
+ ret.setString(tuxbuf.getString().toUpperCase());
+ return ret;
+ } else if ("CARRAY".equals(bufferType)) {
+ TuxCarrayBuffer tuxbuf = (TuxCarrayBuffer) tux;
+ String rcvstr = null;
+ try {
+ rcvstr = new String( tuxbuf.getBytes(), WebtSystem.getDefaultCharset());
+ }
+ catch(Exception ex) {
+ throw new WebtException(ex.getMessage());
+ }
+
+ String rtnstr = rcvstr.toUpperCase();
+ System.out.println("received string value : " + rcvstr);
+ System.out.println("return string value : " + rtnstr);
+ TuxCarrayBuffer ret = new TuxCarrayBuffer(WebtSystem.getDefaultCharset());
+ ret.setBytes(rtnstr.getBytes());;
+ return ret;
+ } else {
+ TuxFieldBuffer tuxbuf = (TuxFieldBuffer) tux;
+ // sample table = new sample();
+ // String rcvstr =
+ // tuxbuf.getField(table.fml_sec100).get().stringValue();
+
+ String rcvstr = tuxbuf.getField("SEC100").get().stringValue();
+ String rtnstr = rcvstr.toUpperCase();
+ System.out.println("received string value : " + rcvstr);
+ System.out.println("return string value : " + rtnstr);
+ TuxFieldBuffer ret = new TuxFieldBuffer(false); // FML 16임으로 false로
+ // ret.createField(sample.fml_sec2).add(rtnstr);
+ ret.createField("SEC2").add(rtnstr);
+ return ret;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/jtc/JtcClientAdapter.java b/src/main/java/com/eactive/eai/adapter/jtc/JtcClientAdapter.java
new file mode 100644
index 0000000..9f683e4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/jtc/JtcClientAdapter.java
@@ -0,0 +1,160 @@
+package com.eactive.eai.adapter.jtc;
+
+import com.eactive.eai.adapter.ElinkDefaultAdapter;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.common.util.CommonLib;
+import com.eactive.eai.common.util.Logger;
+import tmax.jtc.TuxService;
+import tmax.jtc.io.TuxBuffer;
+import tmax.jtc.io.TuxCallDescripter;
+import tmax.jtc.io.TuxFieldBuffer;
+
+import java.util.Properties;
+
+public class JtcClientAdapter extends ElinkDefaultAdapter {
+ private static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+
+ public static final String ADAPTER_GORUP_NAME="ADAPTER_GROUP_NAME";
+
+ public static final String DOMAIN_NAME = "domain.name";
+ public static final String SERVICE_NAME = "service.name";
+ public static final String BUFFER_TYPE = "buffer.type"; // CARRAY | STRING | FML | FML32
+ public static final String DEFAULT_BUFFER_TYPE = "CARRAY";
+ public static final String RESPONSE_TYPE = "response.type";
+
+
+ /**
+ * 1. 기능 : HttpClientAdapter default 생성자
+ * 2. 처리 개요 :
+ * - property 정보를 가져와 MultiThreadedHttpConnectionManager 속성 설정
+ * - HttpClient의 instance 생성
+ * 3. 주의사항
+ *
+ **/
+ public JtcClientAdapter() {
+ super();
+ }
+
+ /**
+ * 1. 기능 : 전문과 같은 Raw Data 통신에 사용
+ * 2. 처리 개요 :
+ * - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
+ * 3. 주의사항
+ *
+ * @param prop WebT Adapter properties 속성 정보
+ * @param message 송신 전문
+ * @return 반환 된 byte[] Object
+ * @exception Exception 수동 시스템 간 통신 중 발생
+ **/
+ // -Dwebt.properties=
+ public Object execute(Properties prop, Object message) throws Exception
+ {
+// String adapterGroupName = prop.getProperty(ADAPTER_GORUP_NAME);
+// String adapterName = prop.getProperty("adapterName");
+
+ byte[] data = null;
+ if(message instanceof byte[]) {
+ data = (byte[])message;
+ } else if( message instanceof String) {
+ data = ((String)message).getBytes();
+ } else {
+ throw new Exception("RECEAIAHA011");
+ }
+
+ String domainName = prop.getProperty(DOMAIN_NAME,"TDOM");
+ String serviceName = prop.getProperty(SERVICE_NAME,"SEAIRECV");
+ String bufferType = prop.getProperty(BUFFER_TYPE, DEFAULT_BUFFER_TYPE);
+ String responseType = prop.getProperty(RESPONSE_TYPE,"SYNC");
+
+ try{
+
+ TuxService service = new TuxService(domainName, serviceName);
+
+ if (logger.isDebug()){
+ logger.debug("JtcClientAdapter] ServiceName "+"["+serviceName+"]");
+ }
+
+
+ if (logger.isDebug()){
+ logger.debug("JtcClientAdapter] Send Data "+"["+new String(data)+"]");
+ logger.debug("JtcClientAdapter] Send Data dump "+CommonLib.getDumpMessage(data));
+
+ }
+
+ if (logger.isDebug()){
+ logger.debug("JtcClientAdapter] BUFFER_TYPE "+"["+bufferType+"]");
+ }
+ TuxBuffer sndbuf = null;
+ if(DEFAULT_BUFFER_TYPE.equals(bufferType)) {
+ sndbuf = service.createCarrayBuffer();
+ sndbuf.setBytes(data);
+ }
+ else if("STRING".equals(bufferType)) {
+ sndbuf = service.createStringBuffer();
+ sndbuf.setString(new String(data));
+ }
+ else if("FML".equals(bufferType)) {
+ // TODO : create table class
+ // JSON to FML conversion
+ // -> make Converter class (JSON -> FML)
+// sndbuf = service.createFieldBuffer(false, tuxFieldTable);
+ sndbuf = new TuxFieldBuffer(false);
+ sndbuf.createField("REQUEST").add(new String(data));
+ }
+ else if("FML32".equals(bufferType)) {
+ sndbuf = new TuxFieldBuffer(true);
+ sndbuf.createField("REQUEST").add(new String(data));
+ }
+ else {
+ throw new Exception("Invalid buffer.type ="+ bufferType);
+ }
+
+ if ("ASYN".equals(responseType)){
+
+ TuxCallDescripter d = service.tpacall(sndbuf);
+ data = null;
+ if (logger.isDebug()){
+ logger.debug("JtcClientAdapter] Recv Data Async "+"["+d.toString()+"]");
+ }
+ }else{
+ TuxBuffer rcvbuf = service.tpcall(sndbuf);
+
+ if(DEFAULT_BUFFER_TYPE.equals(bufferType)) {
+ byte[] response = rcvbuf.getBytes();
+ data = response;
+ }
+ else if("STRING".equals(bufferType)) {
+ String response = rcvbuf.getString();
+ data = response.getBytes();
+ }
+ else if("FML".equals(bufferType)) {
+ // TODO : FML to JSON conversion
+ String response =rcvbuf.getField("RESPONSE").get().stringValue();
+ data = response.getBytes();
+ }
+ else if("FML32".equals(bufferType)) {
+ String response =rcvbuf.getField("RESPONSE").get().stringValue();
+ data = response.getBytes();
+ }
+
+ if (logger.isDebug()){
+ logger.debug("JtcClientAdapter] Recv Data Sync "+"["+new String(data)+"]");
+ logger.debug("JtcClientAdapter] Recv Data dump "+CommonLib.getDumpMessage(data));
+ }
+ }
+ } catch (Exception e){
+ try {
+ String errorCode = "RECEAIOWT001";
+ String addMsg = ", "+e.getMessage()+",["+prop.getProperty(DOMAIN_NAME)+":"+prop.getProperty(SERVICE_NAME)+"]";
+ SMSLogger.loggingSMSWithCode(errorCode, addMsg);
+ } catch(Throwable t){
+ logger.error("[EAIDEBUG] SMS logging Error occured. but ignore this. - " + t.toString());
+ }
+ throw e;
+ }finally{
+
+ }
+
+ return data;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/jtc/JtcClientSample.java b/src/main/java/com/eactive/eai/adapter/jtc/JtcClientSample.java
new file mode 100644
index 0000000..dd90520
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/jtc/JtcClientSample.java
@@ -0,0 +1,100 @@
+package com.eactive.eai.adapter.jtc;
+
+import tmax.jtc.TuxService;
+import tmax.jtc.io.TuxBuffer;
+import tmax.webt.WebtException;
+
+// JEUS -> TUXEDO
+//11. JEUS lifecycle-invocation 등록하기
+//
+//JEUSMain.xml 파일
+//
+//
+//
+// tmax.jtc.external.TuxBootstrapper
+//
+//
+// init
+//
+// java.lang.String
+//
+//
+// /user/barami/jeus5/lib/application/jtc.properties
+//
+//BOOT
+//
+//
+//
+//
+//
+//
+//
+//12. jtc.properties 환경파일 설정으로 primary의 경우 barami 계정의 tuxedo이고 backup의 경우chnam 계정의 tuxedo이다.
+//
+//
+//log.level=debug
+//log.dir=/user/barami/jeus5/logs/
+//log.file=jtc1.log
+//log.bufsize=1024
+//
+//
+//tux.local.name=DM_M1_10
+//tux.remote.name.list=DM_A1_10,DM_A1_20
+//tux.default.remote=DM_A1_10
+//
+//
+//tux.buffer.size=1024
+//tux.default.timeout=60
+//tux.default.txtimeout=300
+//
+//
+//# Primary Tuxedo Server Setting
+//
+//
+//tux.DM_A1_10.addr=192.167.10.48
+//tux.DM_A1_10.port=20010
+//tux.DM_A1_10.interval=10
+//tux.DM_A1_10.backup=DM_A1_20
+//
+//
+//# Backup Tuxedo Server Setting
+//
+//
+//tux.DM_A1_20.addr=192.167.10.48
+//tux.DM_A1_20.port=20020
+//tux.DM_A1_20.interval=10
+
+
+public class JtcClientSample {
+
+ public static void main(String[] args) {
+ TuxService service = new TuxService("TUXDOM", "SAMPLE");
+// TuxCallDescripter cd = service.tpconnect(false);
+
+ try {
+// if(cd == null) {
+ System.out.println("tpconnect failed!");
+// }
+// else {
+
+// TuxBuffer sndbuf = service.createCarrayBuffer();
+// sndbuf.setBytes("test".getBytes());
+
+ TuxBuffer sndbuf = service.createStringBuffer();
+ sndbuf.setString("conversation service");
+
+ TuxBuffer rcvbuf = service.tpcall(sndbuf);
+ System.out.println(rcvbuf.getString());
+// }
+ }
+ catch (WebtException e) {
+ e.printStackTrace();
+ System.out.println("error Occurred");
+
+ }
+ finally {
+// service.tpdiscon(cd);
+ }
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/jtc/JtcServerAdapterBean.java b/src/main/java/com/eactive/eai/adapter/jtc/JtcServerAdapterBean.java
new file mode 100644
index 0000000..74ccd59
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/jtc/JtcServerAdapterBean.java
@@ -0,0 +1,113 @@
+package com.eactive.eai.adapter.jtc;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.RequestDispatcher;
+import com.eactive.eai.common.util.Logger;
+import tmax.common.BufferAccess;
+import tmax.jtc.io.TuxCarrayBuffer;
+import tmax.jtc.io.TuxFieldBuffer;
+import tmax.jtc.io.TuxStringBuffer;
+import tmax.jtmax.JtmaxService;
+import tmax.webt.WebtException;
+import tmax.webt.WebtSystem;
+
+import java.util.Properties;
+
+// TUXEDO -> JEUS
+//1.2.2. Bean 서비스 호출 설정
+// JTC 인바운드 통신을 통해 Bean 서비스를 호출하려면 다음과 같은 설정이 필요하다.
+//
+// webt.properties 설정 ($JEUS_HOME/lib/application)
+//JEUS SIDE
+//webt.properties
+//tux.beans.service.list = GSVC02
+//tux.beans.GSVC02.class = test.JtcBeanSample
+// Tuxedo 환경설정
+//TUX Side
+//*SERVICE
+//GSVC02
+// Tuxedo 도메인 환경설정
+//*DM_REMOTE_SERVICES
+//GSVC01
+// RNAME = "GSVC01"
+// RDOM = "TUXGW1"
+//
+//*DM_TDOMAIN
+//TUXGW1 NWADDR = "//192.168.37.100:9521"
+// JEUS와 Tuxedo 기동
+
+public class JtcServerAdapterBean implements JtmaxService {
+
+ public static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
+ private String adapterGroupName = "JTC_INBOUND";
+ private String adapterName = "JTC_INBOUND";
+
+ public void destroy() throws Exception {
+
+ }
+
+ public void initialize() throws Exception {
+
+ }
+
+ public BufferAccess service(BufferAccess tux) throws WebtException {
+ String bufferType = tux.getBufferTypeString();
+
+ AdapterPropManager pmanager = AdapterPropManager.getInstance();
+ Properties prop = pmanager.getProperties(adapterName);
+ try {
+ if ("STRING".equals(bufferType)) {
+ TuxStringBuffer tuxbuf = (TuxStringBuffer) tux;
+ System.out.println("received string value : " + tuxbuf.getString());
+ byte[] request = tuxbuf.getString().getBytes();
+ RequestDispatcher dispatcher = RequestDispatcher.getRequestDispatcher(adapterGroupName);
+ byte[] response = (byte[]) dispatcher.handle(adapterName, request, prop);
+
+ TuxStringBuffer ret = new TuxStringBuffer(WebtSystem.getDefaultCharset());
+ ret.setString(new String(response));
+ return ret;
+ } else if ("CARRAY".equals(bufferType)) {
+ TuxCarrayBuffer tuxbuf = (TuxCarrayBuffer) tux;
+ String rcvstr = null;
+ try {
+ rcvstr = new String( tuxbuf.getBytes(), WebtSystem.getDefaultCharset());
+ }
+ catch(Exception ex) {
+ throw new WebtException(ex.getMessage());
+ }
+
+ byte[] request = tuxbuf.getBytes();
+ RequestDispatcher dispatcher = RequestDispatcher.getRequestDispatcher(adapterGroupName);
+ byte[] response = (byte[]) dispatcher.handle(adapterName, request, prop);
+
+ TuxCarrayBuffer ret = new TuxCarrayBuffer(WebtSystem.getDefaultCharset());
+ ret.setBytes(response);;
+ return ret;
+ } else {
+ TuxFieldBuffer tuxbuf = (TuxFieldBuffer) tux;
+ // sample table = new sample();
+ // String rcvstr =
+ // tuxbuf.getField(table.fml_sec100).get().stringValue();
+
+// String rcvstr = tuxbuf.getField("SEC100").get().stringValue();
+// String rtnstr = rcvstr.toUpperCase();
+// System.out.println("received string value : " + rcvstr);
+// System.out.println("return string value : " + rtnstr);
+
+ byte[] request = tuxbuf.getBytes();
+ RequestDispatcher dispatcher = RequestDispatcher.getRequestDispatcher(adapterGroupName);
+ byte[] response = (byte[]) dispatcher.handle(adapterName, request, prop);
+
+
+ TuxFieldBuffer ret = new TuxFieldBuffer(false); // FML 16임으로 false로
+ // ret.createField(sample.fml_sec2).add(rtnstr);
+// ret.createField("SEC2").add(rtnstr);
+ return ret;
+ }
+ }
+ catch(Exception ex) {
+ logger.error("JtcServerAdapter] exception - ", ex);
+ throw new WebtException(ex.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/jtc/TestMsgListener.java b/src/main/java/com/eactive/eai/adapter/jtc/TestMsgListener.java
new file mode 100644
index 0000000..6ed12d0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/jtc/TestMsgListener.java
@@ -0,0 +1,48 @@
+package com.eactive.eai.adapter.jtc;
+
+import tmax.jtc.TuxAsyncMsgListener;
+import tmax.jtc.TuxAsyncService;
+import tmax.jtc.io.TuxBuffer;
+
+import javax.transaction.xa.Xid;
+
+
+// 비동기요청(JEUS->TUXEDO tpacall)에 대한 비동기 응답을 받을 경우 사용
+//TmaxXid xid = new TmaxXid(1,4,0);
+//TuxAsyncService service = new TuxAsyncService("TUXGW1","TUX_INSERT");
+//try {
+// service.getXAResource().start(xid, 0);
+//}
+//catch (XAException e) {
+//
+// e.printStackTrace();
+//}
+//TuxBuffer input = service.createStringBuffer();
+//input.setString("abc");
+//TuxAsyncMsgListener listener = new TestMsgListener(service, xid);
+//service.tpacall(input, null, listener );
+
+public class TestMsgListener implements TuxAsyncMsgListener {
+ TuxAsyncService service;
+ Xid xid;
+ public TestMsgListener(TuxAsyncService service, Xid xid) {
+ this.service = service;
+ this.xid = xid;
+ }
+
+ public void handleError(Exception e) {
+ System.out.println(e);
+ }
+
+ public void handleEvent(TuxBuffer rcvBuffer) {
+ System.out.println(Thread.currentThread().getName()
+ +" ] rcv " + rcvBuffer);
+ try {
+ // TODO : Call Internal service
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/jtc/TuxBufferConverter.java b/src/main/java/com/eactive/eai/adapter/jtc/TuxBufferConverter.java
new file mode 100644
index 0000000..bf8df2c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/jtc/TuxBufferConverter.java
@@ -0,0 +1,225 @@
+package com.eactive.eai.adapter.jtc;
+
+public class TuxBufferConverter {
+ private static boolean DEBUG = true;
+
+ //--------------------------------------------------------------------
+ // TODO : table class 로 변경해야 함.
+ //--------------------------------------------------------------------
+ // java -cp ..\webtJtc.jar tmax.webt.util.TuxFieldGen -32 com.eactive.eai.adapter.jtc FieldTable
+// private static ConcurrentHashMap keyMap = new ConcurrentHashMap();
+// private static ConcurrentHashMap nameMap = new ConcurrentHashMap();
+// static {
+// keyMap.put("STRING1", 167772461);
+// keyMap.put("STRING2", 167772462);
+// keyMap.put("LONG1", 33554933);
+//
+// nameMap.put(167772461, "STRING1");
+// nameMap.put(167772462, "STRING2");
+// nameMap.put(33554933, "LONG1");
+// }
+
+// private static FmlTable table = new FmlTable();
+//
+// public static int getFldKeyFromFieldName(String fieldName) {
+// int fldKey = -1;
+// try {
+//
+//// fldKey = keyMap.get(fieldName);
+// fldKey = table.getFieldId(fieldName);
+// }
+// catch(Exception e) {
+// printLog("Invalid Field Name - " + fieldName);
+// }
+// return fldKey;
+// }
+//
+// public static String getFieldNameFromFldKey(int fldKey) {
+// String fieldName = "UNKNOWN";
+// try {
+//// fieldName = nameMap.get(fldKey);
+//
+// fieldName = table.getFieldName(fldKey);
+// }
+// catch(Exception e) {
+// printLog("Invalid Field Key - " + fldKey);
+// }
+// return fieldName;
+// }
+// //--------------------------------------------------------------------
+//
+// private static void setDebug(boolean debug) {
+// DEBUG = debug;
+// }
+// private static void printLog(String message) {
+// if(DEBUG) {
+// System.out.println(message);
+// }
+// }
+//
+//
+// public static TuxFieldBuffer setJsonArrayToFml(TuxFieldBuffer tuxBuffer, String fieldName, JSONArray jsonFieldArray) {
+// for(int i=0; i fieldKeyMap = new HashMap();
+//
+// // TODO : convert TuxFieldBuffer to Json
+// TuxFieldTable table = tuxBuffer.getFieldTable();
+// Vector fNamesVt = tuxBuffer.getFieldKeyNames();
+// if(fNamesVt == null) {
+// Iterator it = tuxBuffer.getAllElementsIterator();
+// int pos = 0;
+//
+// JSONArray jsonFieldArray = null;
+//
+// while(it.hasNext()) {
+// WebtFieldElement fieldElement = (WebtFieldElement)it.next();
+// WebtField f = fieldElement.getField();
+// printLog("Field [" + (pos++) + "]-> " + f);
+//
+// int fieldType = f.getFieldType();
+//
+// printLog("FieldKey : " + f.getFieldKey());
+// printLog("FieldType : " + f.getFieldType());
+//
+//
+// if(fieldKeyMap.containsKey(f.getFieldKey())) {
+// printLog("SKIP FieldKey : " + f.getFieldKey());
+// continue;
+// }
+//
+// String fieldName = getFieldNameFromFldKey(f.getFieldKey());
+//
+// fieldKeyMap.put(f.getFieldKey(), fieldName);
+//
+//
+// Enumeration fe = f.getFieldEnumeration();
+//
+// StringBuffer buf = new StringBuffer();
+//
+// buf.append("data : ");
+// jsonFieldArray = (JSONArray)message.get(fieldName);
+//
+// if(jsonFieldArray == null) {
+// jsonFieldArray = new JSONArray();
+// }
+// while (fe.hasMoreElements()) {
+// WebtFieldElement e = (WebtFieldElement) fe.nextElement();
+//
+// if (e == null) {
+// buf.append("[]");
+// } else {
+// switch (fieldType) {
+// case 1 :
+//// printLog(" >> byteValue : " + e.byteValue());
+// buf.append("[").append(e.byteValue()).append("]");
+// jsonFieldArray.add(e.byteValue());
+// break;
+// case 2 :
+//// printLog(" >> WebtFieldElement : " + e.shortValue());
+// buf.append("[").append(e.shortValue()).append("]");
+// jsonFieldArray.add(e.shortValue());
+// break;
+// case 3 :
+// case 4 :
+//// printLog(" >> intValue : " + e.intValue());
+// buf.append("[").append(e.intValue()).append("]");
+// jsonFieldArray.add(e.intValue());
+// break;
+// case 5 :
+//// printLog(" >> floatValue : " + e.floatValue());
+// buf.append("[").append(e.floatValue()).append("]");
+// jsonFieldArray.add(e.floatValue());
+// break;
+// case 6 :
+//// printLog(" >> doubleValue : " + e.doubleValue());
+// buf.append("[").append(e.doubleValue()).append("]");
+// jsonFieldArray.add(e.doubleValue());
+// break;
+// case 7 :
+//// printLog(" >> stringValue : " + e.stringValue(f.getDefaultCharset()));
+// buf.append("[").append(e.stringValue(f.getDefaultCharset())).append("]");
+// jsonFieldArray.add(e.stringValue(f.getDefaultCharset()));
+// break;
+// case 8 :
+//// printLog(" >> bytesValue : " + e.bytesValue());
+// buf.append("[").append(e.bytesValue()).append("]");
+// jsonFieldArray.add(e.bytesValue());
+//
+// }
+// }
+// message.put(fieldName, jsonFieldArray);
+// }
+// printLog("data : " + buf.toString());
+//
+// }
+// }
+// else {
+// for(int i=0; i listenerMap = new ConcurrentHashMap<>();
+ static {
+ listenerMap.put("HTC-I", "com.eactive.eai.adapter.http.dynamic.HttpAdapterListener");
+ listenerMap.put("HTT-O", "com.eactive.eai.adapter.http.client.HttpClientAdapterListener");
+ listenerMap.put("RST-O", "com.eactive.eai.adapter.http.client.HttpClientAdapterListener");
+ listenerMap.put("NET-I", "com.eactive.eai.adapter.socket2.SocketAdapterListener");
+ listenerMap.put("NET-O", "com.eactive.eai.adapter.socket2.SocketAdapterListener");
+ listenerMap.put("WBT-I", "com.eactive.eai.adapter.webt.WebTAsyncServerAdapterListener");
+ listenerMap.put("WBT-O", "com.eactive.eai.adapter.webt.WebTClientAdapterListener");
+ listenerMap.put("AMQ-I", "com.eactive.eai.adapter.amq.AMQAdapterListener");
+ listenerMap.put("AMQ-O", "com.eactive.eai.adapter.amq.AMQAdapterListener");
+ listenerMap.put("DBQ-I", "com.eactive.eai.adapter.db.sql.DBInboudSqlAdapterListener");
+ listenerMap.put("WSK-I", "com.eactive.eai.adapter.websocket.WebSocketAdapterListener");
+ }
+
+ private ListenerUtil() {
+ super();
+ }
+
+ public static String getDefaultListenerClass(String adapterType, String ioType) {
+ String listenerClass = null;
+ String key = adapterType + "-" + ioType;
+ listenerClass = listenerMap.get(key);
+ return listenerClass;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/mapper/AdapterGroupMapper.java b/src/main/java/com/eactive/eai/adapter/mapper/AdapterGroupMapper.java
new file mode 100644
index 0000000..2f11861
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/mapper/AdapterGroupMapper.java
@@ -0,0 +1,43 @@
+package com.eactive.eai.adapter.mapper;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.data.entity.onl.adapter.AdapterGroup;
+import com.eactive.eai.data.mapper.BaseMapperConfig;
+import com.eactive.eai.data.mapper.GenericMapper;
+import com.eactive.eai.data.mapper.StringToBooleanMapper;
+import com.eactive.eai.data.mapper.StringTrimMapper;
+
+@Mapper(config = BaseMapperConfig.class)
+public interface AdapterGroupMapper extends GenericMapper {
+
+ @Mapping(source = "adptrbzwkgroupname", target = "name")
+ @Mapping(source = "adptrmsgptrncd", target = "adptrMsgPtrnCd")
+ @Mapping(source = "eaibzwkdstcd", target = "eaiBizCode")
+ @Mapping(source = "adptrcd", target = "type")
+ @Mapping(source = "adptrmsgdstcd", target = "messageType")
+ @Mapping(source = "adptriodstcd", target = "gubun")
+ @Mapping(source = "refclsname", target = "refClass")
+ @Mapping(source = "sndrcvhmslogyn", target = "srLogFlag", qualifiedBy = StringToBooleanMapper.class)
+ @Mapping(source = "adptruseyn", target = "usedFlag", qualifiedBy = StringToBooleanMapper.class)
+ @Mapping(source = "spcfcluuseyn", target = "spcfcLUUseYn", qualifiedBy = StringToBooleanMapper.class)
+ @Mapping(source = "adptrbzwkgroupdesc", target = "description", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "osidinstino", target = "osidInstiNo", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "kesauseyn", target = "kesaUseYn", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "testmasteryn", target = "testMasterYn", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "adptrnickname", target = "adptrNickName", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "companycodedata", target = "companyCodeData", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "adptrinsticode", target = "adptrInstiCode", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "bidinterface", target = "bidInterface", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "msgencode", target = "messageEncode", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "linkedAdapterGroup", target = "linkedAdapterGroup")
+ @Mapping(source = "sameSessionYn", target = "sameSessionYn")
+ @Mapping(source = "pairAdapterYn", target = "pairAdapterYn")
+ @Mapping(source = "clientId", target = "clientId")
+ AdapterGroupVO toVo(AdapterGroup entity);
+
+ @Mapping(target = "adapters", ignore = true)
+ AdapterGroup toEntity(AdapterGroupVO vo);
+}
diff --git a/src/main/java/com/eactive/eai/adapter/mapper/AdapterMapper.java b/src/main/java/com/eactive/eai/adapter/mapper/AdapterMapper.java
new file mode 100644
index 0000000..9c355af
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/mapper/AdapterMapper.java
@@ -0,0 +1,25 @@
+package com.eactive.eai.adapter.mapper;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.data.entity.onl.adapter.Adapter;
+import com.eactive.eai.data.mapper.BaseMapperConfig;
+import com.eactive.eai.data.mapper.GenericMapper;
+import com.eactive.eai.data.mapper.StringTrimMapper;
+
+@Mapper(config = BaseMapperConfig.class)
+public interface AdapterMapper extends GenericMapper {
+
+ @Mapping(source = "id.adptrbzwkgroupname", target = "adapterGroupName")
+ @Mapping(source = "id.adptrbzwkname", target = "name")
+ @Mapping(source = "eaisevrinstncname", target = "eaiSevrInstncName")
+ @Mapping(source = "lstnerclsname", target = "listenerClass", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "testclsname", target = "testCallClass", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "prptygroupname", target = "propGroupName", qualifiedBy = StringTrimMapper.class)
+ @Mapping(source = "adptrdesc", target = "description", qualifiedBy = StringTrimMapper.class)
+ @Override
+ AdapterVO toVo(Adapter entity);
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/sna/SNAAdapterManager.java b/src/main/java/com/eactive/eai/adapter/sna/SNAAdapterManager.java
new file mode 100644
index 0000000..146e89a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/sna/SNAAdapterManager.java
@@ -0,0 +1,188 @@
+package com.eactive.eai.adapter.sna;
+
+import com.eactive.eai.adapter.wca.exception.WCAException;
+import com.eactive.eai.adapter.wca.global.WCADefine;
+import com.eactive.eai.adapter.wca.util.RuntimeUtil;
+import com.eactive.eai.common.exception.ExceptionUtil;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.lifecycle.LifecycleSupport;
+import com.eactive.eai.common.util.Logger;
+
+/**
+* 1. 기능 : Softlink 및 SNAAdpaterManager(WCA) 관리
+* 2. 처리 개요 :
+* - start 할 경우
+* 1. Softman에게 명령어를 전송하여 Softlink 구동한다.
+* 2. SNAAdpaterManager(WCA) instance 생성한다.
+* (DB에서 SNA Adapter 정보를 메모리에 로딩 관리한다.)
+* - stop 할 경우
+* 1. Softman에게 명령어를 전송하여 Softlink 종료한다. -> 제거
+* 3. 주의사항
+* - EAI 로딩 우선순위가 AdapterManager 보다 먼저 로딩되어야 한다.
+*
+* @author :
+* @version : v 1.0.0
+* @see :
+* @since :
+*/
+public class SNAAdapterManager implements Lifecycle
+{
+ /**
+ * SNAAdapterManager Single Instance
+ */
+ private static SNAAdapterManager instance = new SNAAdapterManager();
+
+ /**
+ * LifeccyleSupport object
+ */
+ private LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+ /**
+ * 기동 여부
+ */
+ private boolean started;
+ /**
+ * SNAAdapter critical한 정보 로깅을 위한 logger
+ */
+ Logger adapter_logger = Logger.getLogger(WCADefine.ADAPTER_LOGGER_NAME);
+
+ /**
+ * softman 구동중
+ */
+ String SOFTMAN_RUNNING_MSG = "SoftMan is Already Running";
+
+ /**
+ * 1. 기능 : Default Constructor
+ * 2. 처리 개요 :
+ * 3. 주의사항
+ **/
+ private SNAAdapterManager() {
+ }
+
+ /**
+ * 1. 기능 : SNAAdapterManager Singleton Object를 반환하는 getter method
+ * 2. 처리 개요 : SNAAdapterManager Singleton Object를 반환한다.
+ * 3. 주의사항
+ *
+ * @return SNAAdapterManager Singleton object
+ **/
+ public static SNAAdapterManager getInstance() {
+ return instance;
+ }
+
+ /**
+ * 1. 기능 : Lifecycle의 start 메서드로 SNAAdapterManager 초기화하는 메서드
+ * 2. 처리 개요 :
+ * 3. 주의사항
+ *
+ * @exception LifecycleException 이미 시작되었을 경우(RECEAICBM201)
+ *
+ **/
+ public void start() throws LifecycleException {
+ if (started)
+ throw new LifecycleException("RECEAIASA001");
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
+
+ // Softlink 구동
+ try {
+ RuntimeUtil.getInstance().startSoftlink();
+ }catch(WCAException e){
+ String errMsg = e.toString();
+ // 이미 구동중일 경우
+ if (errMsg.indexOf(SOFTMAN_RUNNING_MSG) != -1){
+ if(adapter_logger.isInfo()){
+ adapter_logger.info(errMsg);
+ }
+ }
+ else
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIASA002"));
+ }
+ // SNAAdapter (WCA) Manager instance 생성
+// SNAAdapterManager smanager = SNAAdapterManager.getInstance();
+
+ started = true;
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
+ }
+
+ /**
+ * 1. 기능 : Lifecycle의 stop 메서드로 SNAAdapterManager를 종료하는 메서드
+ * 2. 처리 개요 :
+ * 3. 주의사항
+ *
+ * @exception LifecycleException 이미 종료된 경우 발생(RECEAICBM203)
+ **/
+ public void stop() throws LifecycleException {
+ // Validate and update our current component state
+ if (!started)
+ throw new LifecycleException("RECEAIASA003");
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
+
+ // Softlink 종료 --> 제거
+ /*
+ try {
+ RuntimeUtil.getInstance().stopSoftlink();
+ }catch(WCAException e){
+ throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIASA004"));
+ }
+ */
+ started = false;
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
+ }
+
+ /**
+ * 1. 기능 : LifecycleListener를 등록하는 메서드
+ * 2. 처리 개요 : LifecycleListener를 등록한다.
+ * 3. 주의사항
+ *
+ * @param listener LifecycleEvent를 수신한 LifecycleListener
+ **/
+ public void addLifecycleListener(LifecycleListener listener)
+ {
+ lifecycle.addLifecycleListener(listener);
+ }
+
+ /**
+ * 1. 기능 : 등록된 LifecycleListener 리스트를 반환하는 메서드
+ * 2. 처리 개요 : 등록된 LifecycleListener 리스트를 반환하다.
+ * 3. 주의사항
+ *
+ * @return 등록된 LifecycleListener 리스트
+ **/
+ public LifecycleListener[] findLifecycleListeners()
+ {
+ return lifecycle.findLifecycleListeners();
+ }
+
+
+ /**
+ * 1. 기능 : 등록된 LifecycleListener를 삭제하는 메서드
+ * 2. 처리 개요 : 파라미터의 LifecycleListener를 삭제한다.
+ * 3. 주의사항
+ *
+ * @param listener 삭제할 LifecycleListener
+ **/
+ public void removeLifecycleListener(LifecycleListener listener)
+ {
+ lifecycle.removeLifecycleListener(listener);
+ }
+
+ /**
+ * 1. 기능 : SNAAdapterManager를 초기화 여부를 반환하는 getter 메서드
+ * 2. 처리 개요 : SNAAdapterManager를 초기화 여부를 반환한다.
+ * 3. 주의사항
+ *
+ * @return 초기화 여부
+ **/
+ public boolean isStarted() {
+ return this.started;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/EAIConnectException.java b/src/main/java/com/eactive/eai/adapter/socket2/EAIConnectException.java
new file mode 100644
index 0000000..0fb57d2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/EAIConnectException.java
@@ -0,0 +1,14 @@
+package com.eactive.eai.adapter.socket2;
+
+import com.eactive.eai.adapter.EAIException;
+
+public class EAIConnectException extends EAIException {
+
+ public EAIConnectException(String msg) {
+ super(msg);
+ }
+
+ public EAIConnectException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/EAINoAvailableConnectionException.java b/src/main/java/com/eactive/eai/adapter/socket2/EAINoAvailableConnectionException.java
new file mode 100644
index 0000000..16e0139
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/EAINoAvailableConnectionException.java
@@ -0,0 +1,14 @@
+package com.eactive.eai.adapter.socket2;
+
+import com.eactive.eai.adapter.EAIException;
+
+public class EAINoAvailableConnectionException extends EAIException {
+
+ public EAINoAvailableConnectionException(String msg) {
+ super(msg);
+ }
+
+ public EAINoAvailableConnectionException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/EAITimeoutException.java b/src/main/java/com/eactive/eai/adapter/socket2/EAITimeoutException.java
new file mode 100644
index 0000000..39e365e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/EAITimeoutException.java
@@ -0,0 +1,14 @@
+package com.eactive.eai.adapter.socket2;
+
+import com.eactive.eai.adapter.EAIException;
+
+public class EAITimeoutException extends EAIException {
+
+ public EAITimeoutException(String msg) {
+ super(msg);
+ }
+
+ public EAITimeoutException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/SingleSessionManager.java b/src/main/java/com/eactive/eai/adapter/socket2/SingleSessionManager.java
new file mode 100644
index 0000000..a93952e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/SingleSessionManager.java
@@ -0,0 +1,74 @@
+package com.eactive.eai.adapter.socket2;
+
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.session.SessionManager;
+import com.eactive.eai.common.session.SessionVO;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class SingleSessionManager {
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+ private static SingleSessionManager instance ;
+
+ private ConcurrentHashMap sessionMap ;
+
+ private SingleSessionManager() {
+ this.sessionMap = new ConcurrentHashMap<>();
+ }
+
+ public static SingleSessionManager getInstance(){
+ if (instance == null){
+ instance = new SingleSessionManager();
+ }
+ return instance;
+ }
+ public ConcurrentMap getSessionList(){
+ return sessionMap;
+ }
+
+ public synchronized void sessionOpen(String adapterGroupName, IoSession session) throws Exception {
+ logger.warn("SingleSessionManager ] sessionOpen - [" + adapterGroupName + "," + session + "]");
+ sessionMap.put(adapterGroupName, session);
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ String loginInstId = eaiServerManager.getLocalServerName();
+
+ SessionVO psessionVo = SessionManager.getInstance().getConnectionInfo(adapterGroupName);
+ if(psessionVo != null) {
+ throw new Exception("Connection already exist in other Server - " + psessionVo.getLoginInstId());
+ }
+
+ SessionVO sessionVo = new SessionVO();
+ sessionVo.setLoginUserId(adapterGroupName);
+ sessionVo.setLoginInstId(loginInstId);
+ SessionManager.getInstance().putConnectionInfo(adapterGroupName, sessionVo);
+ }
+
+ public synchronized void sessionClose(String adapterGroupName, IoSession session){
+ try{
+ logger.warn("SingleSessionManager ] closeSession - [" + adapterGroupName + "," + session + "]");
+ if(adapterGroupName != null) {
+ sessionMap.remove(adapterGroupName);
+ }
+
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ String loginInstId = eaiServerManager.getLocalServerName();
+
+ SessionVO sessionVo = SessionManager.getInstance().getConnectionInfo(adapterGroupName);
+
+ if(loginInstId != null && sessionVo != null && loginInstId.equals(sessionVo.getLoginInstId())) {
+ SessionManager.getInstance().removeConnectionInfo(adapterGroupName);
+ }
+ }catch(Exception e){
+ logger.error("SingleSessionManager ] Error Occured in Closing session - " + session,e );
+ }
+ }
+
+ public synchronized IoSession getSession(String adapterGroupName){
+ IoSession session = sessionMap.get(adapterGroupName);
+ logger.warn("SingleSessionManager ] getSession - [" + adapterGroupName + "," + session + "]");
+ return session;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/SocketAdapterFacade.java b/src/main/java/com/eactive/eai/adapter/socket2/SocketAdapterFacade.java
new file mode 100644
index 0000000..6246a44
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/SocketAdapterFacade.java
@@ -0,0 +1,116 @@
+package com.eactive.eai.adapter.socket2;
+
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.mina.common.IoSession;
+
+import com.eactive.eai.adapter.ElinkDefaultAdapter;
+import com.eactive.eai.adapter.Keys;
+import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.inbound.processor.GWSessionManager;
+
+/**
+* 1. 기능 : Outbound Socket Adapter를 Access하기 위한 Java Class로 SocketControl에서 사용함.
+* 2. 처리 개요 :
+* * - OutboundControl Object를 통해 Outbound Socket을 통해 수동시스템과 Socket인터페이스를 위한
+* SocketAdapter Class
+* 3. 주의사항
+* - Outbound Process에서 Outbound Socket의 Adapter Group Name에 대한 Property를 지정해야한다.
+* @author :
+* @version : v 1.0.0
+* @see : 관련 기능을 참조
+* @since :
+*/
+public class SocketAdapterFacade extends ElinkDefaultAdapter
+{
+ static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
+ static SocketAdapterFacade socketAdapter = new SocketAdapterFacade();
+
+ private SocketAdapterFacade() {
+ }
+
+ public static SocketAdapterFacade getInstance()
+ {
+ return socketAdapter;
+ }
+
+ /**
+ * 1. 기능 : SocketAdapter의 실행 Method
+ * 2. 처리 개요 :
+ * - OutboundControl Object를 생성 후 요청된 메시지를 Assign한 후 CallService를 통해
+ * 해당 Outbound Adapter Group의 Socket Connection을 얻은 후 메시지 송수신에 따른 결과를
+ * 리턴한다.
+ * 3. 주의사항
+ *
+ * @param prop WLI OutboundAdapter의 Property정보, SocketAdapter의 경우 ADAPTER_GROUP_NAME
+ * Property Key에 Adapter Group Name을 지정한다.
+ * @param message Outbound process에서 요청하는 메시지 Object로 byte[] 속성의 메시지여야한다.
+ * @return 결과메시지 Object로 SYNC 유형의 경우 byte[] 메시지가 리턴된다.
+ * @exception Exception
+ **/
+ @Override
+ public Object execute(Properties prop, Object message, Properties tempProp) throws Exception {
+ String adapterGroupName = tempProp.getProperty(Keys.OUT_ADAPTER_GROUP_NAME);
+ String adapterName = tempProp.getProperty(Keys.OUT_ADAPTER_NAME);
+ if (logger.isDebug())
+ logger.debug("[SocketAdapterFacade] | Outbound Adapter Group is " + adapterGroupName);
+
+ byte[] request = null;
+ if ( message instanceof byte[]) {
+ request = (byte[]) message;
+ } else {
+ throw new Exception(adapterGroupName + " | [SocketAdapterFacade] cannot send object type : " + message.getClass().getName());
+ }
+
+ ISocketAdapter adapter = null;
+
+ if(adapterGroupName != null) adapter = SocketAdapterManager.getInstance().getOutboundSocketAdapter(adapterGroupName, adapterName);
+
+ if (adapter == null)
+ throw new Exception(adapterGroupName + " | [SocketAdapterFacade] 수동 어댑터 정보 없음 adapterGroupName="+adapterGroupName +", adapterName="+adapterName);
+
+ byte[] response = null;
+ if (adapter.getContext().isSync()){
+ /**
+ * adapter.getContext().getTimeout() 는 초단위
+ * Process.INTERFACE_TIME_OUT 는 ms 단위
+ * 초단위로 바꾸는 작업필요
+ * TODO 전체적인 타임아웃값 확인필요
+ */
+ int responseTimeout = 0;
+ String interfaceTimeout = tempProp.getProperty("INTERFACE_TIME_OUT");
+ if (interfaceTimeout == null || NumberUtils.toInt(interfaceTimeout) == 0){
+ responseTimeout = adapter.getContext().getTimeout();
+ }else{
+ try{
+ responseTimeout = Integer.parseInt(interfaceTimeout) / 1000;//ms 단위이기 때문에
+ }catch(Exception e){
+ responseTimeout = adapter.getContext().getTimeout();
+ }
+ }
+ if (responseTimeout == adapter.getContext().getTimeout()){
+ response = (byte[]) adapter.sendMessage(request );
+ }else{
+ response = (byte[]) adapter.sendMessage(request, responseTimeout );
+ }
+ }else{
+ String sessionId = tempProp.getProperty(HttpClientAdapterServiceKey.TRANSACTION_ID);
+ logger.debug("[SocketAdapterFacade] | sessionId: {}", sessionId);
+ if (StringUtils.isNotBlank(sessionId)) {
+ IoSession session = GWSessionManager.getInstance().getSession(sessionId);
+ response = (byte[]) adapter.sendMessage(session, request);
+ GWSessionManager.getInstance().sessionOut(sessionId);
+ } else {
+ response = (byte[]) adapter.sendMessage(request);
+ }
+ }
+
+
+ return response;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/SocketAdapterListener.java b/src/main/java/com/eactive/eai/adapter/socket2/SocketAdapterListener.java
new file mode 100644
index 0000000..3829dd3
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/SocketAdapterListener.java
@@ -0,0 +1,69 @@
+package com.eactive.eai.adapter.socket2;
+
+import com.eactive.eai.adapter.listener.AdapterException;
+import com.eactive.eai.adapter.listener.AdapterListenerSupport;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+
+/**
+ * 1. 기능 : Socket Adapter의 기동/중지를 위한 Adapter Listener로 FrameWork에서
+ * SocketAdapter를 중지/기동하기 위한 Socket Adapter Listener이다. 2. 처리 개요 : -
+ * SocketAdapterManager Instance를 얻은 후 해당 Adapter에 대한 Stop/Start 기능을 수행한다. 3.
+ * 주의사항
+ *
+ * @param
+ * @return
+ * @exception
+ */
+public class SocketAdapterListener extends AdapterListenerSupport {
+ static final Logger errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ @Override
+ public void start() throws AdapterException {
+// SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ try {
+ if (info == null)
+ throw new Exception("SocketAdapterListener | AdapterVO가 NULL입니다.");
+
+ ISocketAdapter adapter = SocketAdapterFactory.createSocketAdapter(info);
+
+ adapter.getContext().setAdapterVO(info);
+ if (adapter.getContext().isPermanent()) {
+ adapter.setAdapterStatus(false);
+ } else {
+ adapter.setAdapterStatus(true);
+ }
+
+ adapter.start(); //.join();
+ } catch (Exception e) {
+ String errorMessage = info==null? "":info.getName() + " | SocketAdapterListener | cannot start : " + e.getMessage();
+ logger.error(errorMessage, e);
+ throw new AdapterException(errorMessage);
+ }
+ }
+
+ @Override
+ public void stop() throws AdapterException {
+
+ SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ try {
+ if (info == null)
+ throw new Exception("SocketAdapterListener | AdapterVO가 NULL입니다.");
+
+ ISocketAdapter adapter = manager.getSocketAdapter(info.getAdapterGroupName(), info.getName());
+ if (adapter == null)
+ throw new Exception(info.getName() + " | [SocketAdapterListener] AdapterVO가 NULL입니다.");
+
+ adapter.setAdapterStatus(false);
+
+ adapter.stop().join();
+ } catch (Exception e) {
+ String errorMessage = info==null? "":info.getName() + " | SocketAdapterListener | cannot stop : " + e.getMessage();
+ logger.error(errorMessage, e);
+ throw new AdapterException(errorMessage);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/dump/DumpServer.java b/src/main/java/com/eactive/eai/adapter/socket2/app/dump/DumpServer.java
new file mode 100644
index 0000000..707db00
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/dump/DumpServer.java
@@ -0,0 +1,65 @@
+package com.eactive.eai.adapter.socket2.app.dump;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+public class DumpServer {
+ static public void main(String[] args) throws Exception {
+ if (args.length != 1) {
+ System.out.println("Usage : dump ");
+ return;
+ }
+ int port = Integer.parseInt(args[0]);
+
+ SocketAdapterContext context = new SocketAdapterContext();
+ context.setAdapterGroupName("DumpServerAdapterGroup");
+ context.setAdapterName("DumpServerAdapter");
+ context.setBoundUsage("INBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName("localhost");
+ context.setPortNumber(port);
+ context.setResponseType("ASYN");
+ context.setTimeout(10);
+ context.setMaxConnection(10);
+ context.setTraceLevel(context.TRACE_LEVEL_DEBUG);
+ context.setPermanent("N");
+
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setLlFieldType("NONE");
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ // do nothing
+ return request;
+ }
+ });
+
+ ISocketAdapter adapter = SocketAdapterFactory.createSocketAdapter(context);
+ adapter.start().join();
+
+
+ /**
+ * process command
+ */
+ processCommand();
+ }
+
+ private static void processCommand() {
+ while(true) {
+ try {
+ System.out.print("> ");
+ String cmd = (new java.io.BufferedReader(new java.io.InputStreamReader(System.in))).readLine();
+ if ("".equals(cmd)) {
+ System.out.println(SocketAdapterManager.getInstance());
+ } else if ("exit".equals(cmd)) {
+ System.exit(1);
+ }
+ } catch(Exception e) {
+ System.out.println(e.toString());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/echo/EchoServer.java b/src/main/java/com/eactive/eai/adapter/socket2/app/echo/EchoServer.java
new file mode 100644
index 0000000..7f7d510
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/echo/EchoServer.java
@@ -0,0 +1,58 @@
+package com.eactive.eai.adapter.socket2.app.echo;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+public class EchoServer {
+ static public void main(String[] args) throws Exception {
+ /**
+ * Xecure Server - [1] BASIC
+ */
+ SocketAdapterContext context = new SocketAdapterContext();
+ context.setProtocol("XECURE");
+ context.setAdapterGroupName("XecureServerAdapterGroup");
+ context.setAdapterName("XecureBasicServerAdapter");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName("localhost");
+ context.setPortNumber(9901);
+ context.setResponseType("SYNC");
+ context.setTimeout(10);
+ context.setMaxConnection(10);
+ context.setTraceLevel(context.TRACE_LEVEL_DEBUG);
+ context.setPermanent("N");
+
+ context.setXecureType("BASIC");
+ //context.setXecureTmode("10");
+ //context.setXecureEncodeMode("BASE64");
+ //context.setXecurePassword("qwer1234");
+ context.setXecureConfigPath("modules/xecure/windows/conf/xc_conf.txt");
+
+ ISocketAdapter adapter = SocketAdapterFactory.createSocketAdapter(context);
+ adapter.start().join();
+
+
+ /**
+ * process command
+ */
+ processCommand();
+ }
+
+ private static void processCommand() {
+ while(true) {
+ try {
+ System.out.print("> ");
+ String cmd = (new java.io.BufferedReader(new java.io.InputStreamReader(System.in))).readLine();
+ if ("".equals(cmd)) {
+ System.out.println(SocketAdapterManager.getInstance());
+ } else if ("exit".equals(cmd)) {
+ System.exit(1);
+ }
+ } catch(Exception e) {
+ System.out.println("processCommand errpr "+ e.toString());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/muxer/Muxer.java b/src/main/java/com/eactive/eai/adapter/socket2/app/muxer/Muxer.java
new file mode 100644
index 0000000..d69560e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/muxer/Muxer.java
@@ -0,0 +1,86 @@
+package com.eactive.eai.adapter.socket2.app.muxer;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+public class Muxer {
+ static public void startup(String inboundHostname, int inboundPort, String outboundHostname, int outboundPort) throws Exception {
+ /**
+ * Outbound Client
+ */
+ SocketAdapterContext context = new SocketAdapterContext();
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setAdapterGroupName("MuxerGroup");
+ context.setAdapterName("OutboundAdapter");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("CLIENT");
+ context.setHostName(outboundHostname);
+ context.setPortNumber(outboundPort);
+ context.setResponseType("SYNC");
+ context.setMaxConnection(1);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_TRACE);
+
+ ISocketAdapter outboundClient = SocketAdapterFactory.createSocketAdapter(context);
+ outboundClient.start().join();
+
+ /**
+ * Inbound Server
+ */
+ context = new SocketAdapterContext();
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setAdapterGroupName("MuxerGroup");
+ context.setAdapterName("InboundAdapter");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName(inboundHostname);
+ context.setPortNumber(inboundPort);
+ context.setResponseType("SYNC");
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_TRACE);
+ context.setRequestProcessor(new MuxerRequestProcessor(outboundClient));
+
+ ISocketAdapter inboundServer = SocketAdapterFactory.createSocketAdapter(context);
+ inboundServer.start().join();
+
+ }
+
+ public synchronized byte[] handle(byte[] message) {
+ System.out.println("##############################################################");
+ System.out.println("CiscoListener | message received : " + new String(message));
+ System.out.println("##############################################################");
+ return message;
+ }
+
+ static public void main(String[] args) throws Exception {
+ if (args.length != 3) {
+ System.out.println("java " + Muxer.class.getName() + " ");
+ return;
+ }
+
+ int inboundPort = Integer.parseInt(args[0]);
+ String outboundHostname = args[1];
+ int outboundPort = Integer.parseInt(args[2]);
+
+ startup("*", inboundPort, outboundHostname, outboundPort);
+ }
+}
+
+class MuxerRequestProcessor implements IRequestProcessor {
+ ISocketAdapter outboundAdapter;
+
+ public MuxerRequestProcessor(ISocketAdapter outboundAdapter) {
+ this.outboundAdapter = outboundAdapter;
+ }
+
+ public synchronized byte[] handle(byte[] message) throws EAIException {
+ System.out.println("##############################################################");
+ System.out.println("MuxerRequestProcessor | message received : " + new String(message));
+ System.out.println("##############################################################");
+
+ return (byte[]) outboundAdapter.sendMessage(message);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/proxy/ProxyServer.java b/src/main/java/com/eactive/eai/adapter/socket2/app/proxy/ProxyServer.java
new file mode 100644
index 0000000..38f238a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/proxy/ProxyServer.java
@@ -0,0 +1,47 @@
+package com.eactive.eai.adapter.socket2.app.proxy;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+public class ProxyServer {
+ static public void startup(String proxyHostname, int proxyPort, String remoteHostname, int remotePort) throws Exception {
+
+ /**
+ * Proxy Server
+ */
+ SocketAdapterContext context = new SocketAdapterContext();
+ context.setProtocol("PROXY");
+ context.setAdapterGroupName("AdminAdapterGroup");
+ context.setAdapterName("ProxyAdapter");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName(proxyHostname);
+ context.setPortNumber(proxyPort);
+ context.setLocalHostName(remoteHostname);
+ context.setLocalPortNumber(remotePort);
+ context.setAckSupport("N");
+ context.setPermanent("Y");
+ context.setResponseType("SYNC");
+ context.setTimeout(60);
+ context.setScript("proxy.groovy");
+ context.setTraceLevel(context.TRACE_LEVEL_TRACE);
+
+ //SocketAdapter adapter = new AdminServer(context);
+ ISocketAdapter adapter = SocketAdapterFactory.createSocketAdapter(context);
+ adapter.start().join();
+ }
+
+ static public void main(String[] args) throws Exception {
+ if (args.length != 3) {
+ System.out.println("java " + ProxyServer.class.getName() + " ");
+ return;
+ }
+
+ int proxyPort = Integer.parseInt(args[0]);
+ String remoteHostname = args[1];
+ int remotePort = Integer.parseInt(args[2]);
+
+ startup("*", proxyPort, remoteHostname, remotePort);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/tester/AsyncSimulator.java b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/AsyncSimulator.java
new file mode 100644
index 0000000..217723b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/AsyncSimulator.java
@@ -0,0 +1,543 @@
+package com.eactive.eai.adapter.socket2.app.tester;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+public class AsyncSimulator {
+ String hostname;
+ String rHostname;
+ int rPort;
+ int mThread;
+
+ final ISocketAdapter httpAdapter;
+// final ISocketAdapter adapter11;
+
+ final ISocketAdapter adapter21;
+ final ISocketAdapter adapter22;
+ final ISocketAdapter adapter23;
+ final ISocketAdapter adapter24;
+ final ISocketAdapter adapter25;
+ final ISocketAdapter adapter26;
+
+ final ISocketAdapter adapter31;
+ final ISocketAdapter adapter32;
+ final ISocketAdapter adapter33;
+ final ISocketAdapter adapter34;
+ final ISocketAdapter adapter35;
+ final ISocketAdapter adapter36;
+
+ final ISocketAdapter adapter41;
+ final ISocketAdapter adapter42;
+ final ISocketAdapter adapter43;
+ final ISocketAdapter adapter44;
+ final ISocketAdapter adapter45;
+ final ISocketAdapter adapter46;
+
+ public AsyncSimulator(String hostname, String rHostname, int rPort, int mThread) throws Exception {
+ this.hostname = hostname;
+ this.rHostname = rHostname;
+ this.rPort = rPort;
+ this.mThread = mThread;
+
+ SocketAdapterContext context = null;
+
+ /**
+ * Http Server
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AdminAdapterGroup");
+ context.setAdapterName("HttpAdapter");
+ context.setProtocol("HTTP");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName("*");
+ context.setPortNumber(8282);
+ context.setAckSupport("N");
+ context.setPermanent("N");
+ context.setResponseType("SYNC");
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ context.setAclList("172.26.128.*,127.0.0.1");
+ httpAdapter = SocketAdapterFactory.createSocketAdapter(context);
+ httpAdapter.start();
+
+ /**
+ * Inbound RECEIVER(SERVER) - 응답 수신
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-RECV_41");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(44041);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+ adapter41 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter41.start();
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-RECV_42");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(44042);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+ adapter42 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter42.start();
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-RECV_43");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(44043);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+ adapter43 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter43.start();
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-RECV_44");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(44044);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+ adapter44 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter44.start();
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-RECV_45");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(44045);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+ adapter45 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter45.start();
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-RECV_46");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(44046);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+ adapter46 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter46.start();
+
+ /**
+ * Outbound SENDER(CLIENT) - 응답 요청
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-SEND_31");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(rHostname);
+ context.setPortNumber(rPort + 1);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(mThread);
+ context.setMaxThread(mThread);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter31 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter31.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter41.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-SEND_32");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(rHostname);
+ context.setPortNumber(rPort + 2);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(mThread);
+ context.setMaxThread(mThread);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter32 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter32.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter42.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-SEND_33");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(rHostname);
+ context.setPortNumber(rPort + 3);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(mThread);
+ context.setMaxThread(mThread);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter33 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter33.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter43.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-SEND_34");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(rHostname);
+ context.setPortNumber(rPort + 4);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(mThread);
+ context.setMaxThread(mThread);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter34 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter34.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter44.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-SEND_35");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(rHostname);
+ context.setPortNumber(rPort + 5);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(mThread);
+ context.setMaxThread(mThread);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter35 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter35.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter45.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("RES-SEND_36");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(rHostname);
+ context.setPortNumber(rPort + 6);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(mThread);
+ context.setMaxThread(mThread);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter36 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter36.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter46.sendMessage(request);
+ return request;
+ }
+ });
+
+ /**
+ * Outbound RECEIVER(SERVER) - 요청 수신
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("REQ-RECV_21");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(42001);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter21 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter21.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter31.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("REQ-RECV_22");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(42002);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter22 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter22.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter32.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("REQ-RECV_23");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(42003);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter23 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter23.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter33.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("REQ-RECV_24");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(42004);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter24 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter24.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter34.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("REQ-RECV_25");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(42005);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter25 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter25.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter35.sendMessage(request);
+ return request;
+ }
+ });
+
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+ context.setAdapterName("REQ-RECV_26");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setHostName(hostname);
+ context.setPortNumber(42006);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(100);
+ context.setMaxThread(100);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter26 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter26.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ adapter36.sendMessage(request);
+ return request;
+ }
+ });
+
+ /**
+ * Inbound SENDER(CLIENT) - 요청 송신
+ */
+// context = new SocketAdapterContext();
+// context.setAdapterGroupName("AsyncSimulatorAdapterGroup");
+// context.setAdapterName("Inbound-SEND");
+// context.setProtocol("FIXED_LENGTH_HEADER");
+// context.setSocketType("CLIENT");
+// context.setHostName(hostname);
+// context.setPortNumber(42001);
+// context.setLlFieldType("CHAR");
+// context.setLlFieldLength(4);
+// context.setResponseType("ASYN");
+// context.setMaxConnection(100);
+// context.setMaxThread(100);
+// context.setTimeout(60);
+// context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+// adapter11 = SocketAdapterFactory.createSocketAdapter(context);
+// adapter11.start().join();
+ }
+
+ static public void main(String[] args) throws Exception {
+
+ //String hostname = "localhost";
+ String hostname = args[0];
+ String rHostname = args[1];
+ int rPort = Integer.parseInt(args[2]);
+ int mThread = Integer.parseInt(args[3]);
+ new AsyncSimulator(hostname, rHostname, rPort, mThread);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/tester/EchoSimulator.java b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/EchoSimulator.java
new file mode 100644
index 0000000..4805195
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/EchoSimulator.java
@@ -0,0 +1,173 @@
+package com.eactive.eai.adapter.socket2.app.tester;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+public class EchoSimulator {
+
+ final ISocketAdapter httpAdapter;
+// final ISocketAdapter adapter11;
+ final ISocketAdapter adapter21;
+// final ISocketAdapter adapter31;
+ final ISocketAdapter adapter41;
+
+ public EchoSimulator(int echoPort, int destPort, int maxConn, String script, int adminPort, String llfieldinclude, String lloffsetexclude, String llInclude) throws Exception {
+
+ SocketAdapterContext context = null;
+
+ /**
+ * Http Server
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AdminAdapterGroup");
+ context.setAdapterName("HttpAdapter");
+ context.setProtocol("HTTP");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName("*");
+ context.setPortNumber(adminPort);
+ context.setAckSupport("N");
+ context.setPermanent("N");
+ context.setResponseType("SYNC");
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+// context.setAclList("172.26.128.*,127.0.0.1");
+ httpAdapter = SocketAdapterFactory.createSocketAdapter(context);
+ httpAdapter.start();
+
+ /**
+ * Inbound RECEIVER(SERVER) - 응답 수신[400]
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("EchoSimulatorAdapterGroup");
+ context.setAdapterName("DestinationAsS");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ //context.setBoundUsage("INBOUND");
+ //context.setHostName(hostname);
+ context.setPortNumber(destPort);//64001);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setLlFieldInclude(llfieldinclude);
+ context.setLlOffsetExclude(lloffsetexclude);
+ context.setLlInclude(llInclude);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(maxConn);//30);
+ context.setMaxThread(maxConn);//30);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter41 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter41.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+
+ /**
+ * Outbound SENDER(CLIENT) - 응답 요청[300]
+ */
+// context = new SocketAdapterContext();
+// context.setAdapterGroupName("EchoSimulatorAdapterGroup");
+// context.setAdapterName("RES-SEND_31");
+// context.setProtocol("FIXED_LENGTH_HEADER");
+// context.setSocketType("CLIENT");
+// context.setHostName(rHost);
+// context.setPortNumber(rPort);
+// //context.setLlFieldType("BIN");
+// //context.setLlFieldLength(2);
+// context.setResponseType("ASYN");
+// context.setMaxConnection(30);
+// context.setMaxThread(30);
+// context.setTimeout(60);
+//// context.setScript("sync-perm.groovy");
+// context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+// adapter31 = SocketAdapterFactory.createSocketAdapter(context);
+// adapter31.start();
+
+// context.setRequestProcessor(new IRequestProcessor() {
+// public byte[] handle(byte[] request) throws Exception {
+//// adapter41.sendMessage(request);
+// System.out.println(new String(request));
+// request[request.length-1] = (byte) '-';
+// return request;
+// }
+// });
+
+
+ /**
+ * Outbound RECEIVER(SERVER) - 요청 수신[200]
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("EchoSimulatorAdapterGroup");
+ context.setAdapterName("EchoAsS");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setBoundUsage("IOBOUND");
+ //context.setHostName(hostname);
+ context.setPortNumber(echoPort);//62001);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setLlFieldOffset(0);
+ context.setLlFieldInclude(llfieldinclude);
+ context.setLlOffsetExclude(lloffsetexclude);
+ context.setLlInclude(llInclude);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(maxConn);//30);
+ context.setMaxThread(maxConn);//30);
+ context.setTimeout(60);
+ context.setScript(script);//"asyn-perm.groovy");
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ adapter21 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter21.start();
+
+// context.setRequestProcessor(new IRequestProcessor() {
+// public byte[] handle(byte[] request) throws Exception {
+// adapter31.sendMessage(request);
+// return request;
+// }
+// });
+
+
+ /**
+ * Inbound SENDER(CLIENT) - 요청 송신[100]
+ */
+// context = new SocketAdapterContext();
+// context.setAdapterGroupName("EchoSimulatorAdapterGroup");
+// context.setAdapterName("Inbound-SEND");
+// context.setProtocol("FIXED_LENGTH_HEADER");
+// context.setSocketType("CLIENT");
+// context.setHostName(hostname);
+// context.setPortNumber(61001);
+// context.setLlFieldType("BIN");
+// context.setLlFieldLength(2);
+// context.setResponseType("ASYN");
+// context.setMaxConnection(30);
+// context.setMaxThread(30);
+// context.setTimeout(60);
+// context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+// adapter11 = SocketAdapterFactory.createSocketAdapter(context);
+// adapter11.start().join();
+ }
+
+ static public void main(String[] args) throws Exception {
+
+ // echoPort, destPort, maxConn, script, adminPort, llfieldinclude, lloffsetexclude, llinclude
+// String eaiHost = args[0];
+// int eaiPort = Integer.parseInt(args[1]);
+ int echoPort = Integer.parseInt(args[0]);
+ int destPort = Integer.parseInt(args[1]);
+ int maxConn = Integer.parseInt(args[2]);
+ String script = args[3];
+ int adminPort = Integer.parseInt(args[4]);
+ String llfieldinclude = args[5];
+ String lloffsetexclude = args[6];
+ String llInclude = args[7];
+ new EchoSimulator(echoPort, destPort, maxConn, script, adminPort, llfieldinclude, lloffsetexclude, llInclude);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/tester/LoadRunner.java b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/LoadRunner.java
new file mode 100644
index 0000000..4d2ca64
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/LoadRunner.java
@@ -0,0 +1,382 @@
+package com.eactive.eai.adapter.socket2.app.tester;
+
+
+import com.eactive.eai.adapter.socket2.common.StopWatch;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.UUIDGenerator;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+
+public class LoadRunner {
+ String hostname;
+ String message;
+
+ final ISocketAdapter httpAdapter;
+ final ISocketAdapter adapter1;
+ final ISocketAdapter adapter2;
+ final ISocketAdapter adapter3;
+ final ISocketAdapter adapter4;
+
+ int threadCount = 1;
+ int loopCount = 1;
+ long thinkTime = 0L;
+ CountDownLatch latch;
+
+
+ public LoadRunner(String hostname, String filename) throws Exception {
+ this.hostname = hostname;
+ this.message = readFile(filename);
+
+ SocketAdapterContext context = null;
+
+ /**
+ * Http Server
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AdminAdapterGroup");
+ context.setAdapterName("HttpAdapter");
+ context.setProtocol("HTTP");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName("*");
+ context.setPortNumber(8282);
+ context.setAckSupport("N");
+ context.setPermanent("N");
+ context.setResponseType("SYNC");
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ context.setAclList("172.26.127.*,127.0.0.1");
+ httpAdapter = SocketAdapterFactory.createSocketAdapter(context);
+ httpAdapter.start();
+
+ /**
+ * port:10004
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10004");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10004);
+
+ //context.setLocalHostName("172.26.127.106");
+ //context.setLocalPortNumber(12929);
+
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ //System.out.println("[" + TimeUtil.formatDate(System.currentTimeMillis()) + "] " + new String(request));
+ System.out.print(".");
+ latch.countDown();
+ return request;
+ }
+ });
+
+ adapter4 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter4.start();
+
+ /**
+ * port:10003
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10003");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10003);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+ adapter3 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter3.start();
+
+ /**
+ * port:10002
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10002");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10002);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+ adapter2 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter2.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ //System.out.print("2");
+ adapter3.sendMessage(request);
+ //System.out.print("3");
+ return request;
+ }
+ });
+
+ /**
+ * port:10001
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10001");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10001);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+ adapter1 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter1.start().join();
+ }
+
+ public void start() throws Exception {
+ /**
+ * latch
+ */
+ latch = new CountDownLatch(threadCount * loopCount);
+
+ /**
+ * executor
+ */
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ final CountDownLatch startLatch = new CountDownLatch(1);
+ final CountDownLatch stopLatch = new CountDownLatch(threadCount);
+
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ for (int i = 0; i < threadCount; i++) {
+ executor.execute(new Runnable() {
+ public void run() {
+ try {
+ startLatch.await();
+ for (int j=0; j ");
+ String line = (new BufferedReader(new java.io.InputStreamReader(System.in))).readLine();
+
+ if (line == null) {
+ break;
+ } else if ("".equals(line.trim())) {
+ } else if ("help".equals(line.trim())) {
+ System.out.println("===============================================================");
+ System.out.println("LoadRunner v1.0 (http port = 8282)");
+ System.out.println("===============================================================");
+ System.out.println(" help : help");
+ System.out.println(" start : start [thread count] [loop count] [think time]");
+ System.out.println(" exit : exit");
+ System.out.println("");
+ } else if (line.trim().startsWith("start")) {
+ String[] tokens = line.trim().split("[ ]+");
+ if (tokens.length > 1)
+ threadCount = Integer.parseInt(tokens[1]);
+ if (tokens.length > 2)
+ loopCount = Integer.parseInt(tokens[2]);
+ if (tokens.length > 3)
+ thinkTime = Long.parseLong(tokens[3]);
+ start();
+ } else if ("exit".equals(line.trim())) {
+ System.exit(1);
+ } else {
+ System.out.println("Unknow command. type help.");
+ }
+ } catch(Exception e) {
+ System.out.println("Error " + e.toString());
+ }
+ }
+ }
+
+
+ private String readFile(String filename) throws FileNotFoundException, IOException {
+ String line = "";
+ ByteMessage data = new ByteMessage();
+ BufferedReader br = new BufferedReader(new FileReader(filename));
+
+ try {
+ while ((line = br.readLine()) != null) {
+ while(line.indexOf("0x") != -1) {
+ data.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ data.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ data.append(line);
+ }
+ return data.getString();
+ }
+ catch(Exception e) {
+ throw e;
+ }
+ finally {
+ try {
+ if(br != null) br.close();
+ }
+ catch(Exception ee) {
+ System.out.println("close error");
+ }
+ }
+
+
+ }
+
+ static public void main(String[] args) throws Exception {
+// /**
+// * server - port:10004
+// */
+// SocketAdapterContext context = new SocketAdapterContext();
+// context.setAdapterGroupName("FixedLengthHeaderAdapterServerGroup");
+// context.setAdapterName("Bin2ServerAdapter-10004");
+// context.setProtocol("FIXED_LENGTH_HEADER");
+// context.setSocketType("SERVER");
+// context.setHostName("*");
+// context.setPortNumber(10004);
+// context.setResponseType("ASYN");
+// context.setMaxConnection(10);
+// context.setMaxThread(100);
+// context.setTimeout(10);
+// context.setTraceLevel(context.TRACE_LEVEL_INFO);
+// final ISocketAdapter adapter4 = SocketAdapterFactory.createSocketAdapter(context);
+// adapter4.start();
+//
+//
+// /**
+// * server - port:10001
+// */
+// context = new SocketAdapterContext();
+// context.setAdapterGroupName("FixedLengthHeaderAdapterServerGroup");
+// context.setAdapterName("Bin2ServerAdapter-10001");
+// context.setProtocol("FIXED_LENGTH_HEADER");
+// context.setSocketType("SERVER");
+// context.setHostName("*");
+// context.setPortNumber(10001);
+// context.setResponseType("ASYN");
+// context.setMaxConnection(10);
+// context.setMaxThread(100);
+// context.setTimeout(10);
+// context.setTraceLevel(context.TRACE_LEVEL_INFO);
+//
+// context.setRequestProcessor(new IRequestProcessor() {
+// public byte[] handle(final byte[] request) throws Exception {
+//// ExecutorService executor = new ThreadPoolExecutor(16, 16, 60, TimeUnit.SECONDS, new LinkedBlockingQueue());
+//// executor.execute(new Runnable() {
+//// public void run() {
+//// try {
+// adapter4.sendMessage(request);
+//// } catch(Exception e) {
+//// e.printStackTrace();
+//// }
+//// }
+//// });
+// return request;
+// }
+// });
+//
+// final ISocketAdapter adapter1 = SocketAdapterFactory.createSocketAdapter(context);
+// adapter1.start();
+
+ //----------------------------------------------------------------------
+ if (System.getProperty("inst.Name") == null)
+ System.setProperty("inst.Name", System.getProperty("test"));
+
+ String hostname = "localhost";
+ String filename = "";
+
+ if (args.length == 2) {
+ hostname = args[0];
+ System.out.println("remote host : " + hostname);
+ filename = args[1];
+ } else {
+ System.out.println("Usage : loadrunner [ip] [file]");
+ return;
+ }
+
+ LoadRunner loadRunner = new LoadRunner(hostname, filename);
+ loadRunner.processCommand();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/tester/LoadRunner2.java b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/LoadRunner2.java
new file mode 100644
index 0000000..2248622
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/LoadRunner2.java
@@ -0,0 +1,384 @@
+package com.eactive.eai.adapter.socket2.app.tester;
+
+
+import com.eactive.eai.adapter.socket2.common.StopWatch;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.UUIDGenerator;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+
+public class LoadRunner2 {
+ String hostname;
+ String message;
+
+ final ISocketAdapter httpAdapter;
+ final ISocketAdapter adapter1;
+ final ISocketAdapter adapter2;
+ final ISocketAdapter adapter3;
+ final ISocketAdapter adapter4;
+
+ int threadCount = 1;
+ int loopCount = 1;
+ long thinkTime = 0L;
+ CountDownLatch latch;
+
+
+ public LoadRunner2(String hostname, String filename) throws Exception {
+ this.hostname = hostname;
+ this.message = readFile(filename);
+
+ SocketAdapterContext context = null;
+
+ /**
+ * Http Server
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AdminAdapterGroup");
+ context.setAdapterName("HttpAdapter");
+ context.setProtocol("HTTP");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName("*");
+ context.setPortNumber(8282);
+ context.setAckSupport("N");
+ context.setPermanent("N");
+ context.setResponseType("SYNC");
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_DEFAULT);
+ context.setAclList("172.26.127.*,127.0.0.1");
+ httpAdapter = SocketAdapterFactory.createSocketAdapter(context);
+ httpAdapter.start();
+
+ /**
+ * port:10006
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10006");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10006);
+
+ //context.setLocalHostName("172.26.127.106");
+ //context.setLocalPortNumber(12929);
+
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ //System.out.println("[" + TimeUtil.formatDate(System.currentTimeMillis()) + "] " + new String(request));
+ System.out.print(".");
+ latch.countDown();
+ return request;
+ }
+ });
+
+ adapter4 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter4.start();
+
+ /**
+ * port:10003
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10003");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10003);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+ adapter3 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter3.start();
+
+ /**
+ * port:10005
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10005");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10005);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+ adapter2 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter2.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+ //System.out.print("2");
+ adapter3.sendMessage(request);
+ //System.out.print("3");
+ return request;
+ }
+ });
+
+ /**
+ * port:10001
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("FixedLengthHeaderAdapterGroup");
+ context.setAdapterName("Bin2ClientAdapter-10001");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("CLIENT");
+ context.setHostName(hostname);
+ context.setPortNumber(10001);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(10);
+ context.setMaxThread(100);
+ context.setTimeout(10);
+ context.setTraceLevel(context.TRACE_LEVEL_INFO);
+ adapter1 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter1.start().join();
+ }
+
+ public void start() throws Exception {
+ /**
+ * latch
+ */
+ latch = new CountDownLatch(threadCount * loopCount);
+
+ /**
+ * executor
+ */
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ final CountDownLatch startLatch = new CountDownLatch(1);
+ final CountDownLatch stopLatch = new CountDownLatch(threadCount);
+
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+
+ for (int i = 0; i < threadCount; i++) {
+ executor.execute(new Runnable() {
+ public void run() {
+ try {
+ startLatch.await();
+ for (int j=0; j ");
+ String line = (new BufferedReader(new java.io.InputStreamReader(System.in))).readLine();
+
+ if (line == null) {
+ break;
+ } else if ("".equals(line.trim())) {
+ } else if ("help".equals(line.trim())) {
+ System.out.println("===============================================================");
+ System.out.println("LoadRunner v1.0 (http port = 8282)");
+ System.out.println("===============================================================");
+ System.out.println(" help : help");
+ System.out.println(" start : start [thread count] [loop count] [think time]");
+ System.out.println(" exit : exit");
+ System.out.println("");
+ } else if (line.trim().startsWith("start")) {
+ String[] tokens = line.trim().split("[ ]+");
+ if (tokens.length > 1)
+ threadCount = Integer.parseInt(tokens[1]);
+ if (tokens.length > 2)
+ loopCount = Integer.parseInt(tokens[2]);
+ if (tokens.length > 3)
+ thinkTime = Long.parseLong(tokens[3]);
+ start();
+ } else if ("exit".equals(line.trim())) {
+ System.exit(1);
+ } else {
+ System.out.println("Unknow command. type help.");
+ }
+ } catch(Exception e) {
+// e.printStackTrace();
+ System.out.println("Exception");
+ }
+ }
+ }
+
+
+ private String readFile(String filename) throws FileNotFoundException, IOException {
+ BufferedReader br = new BufferedReader(new FileReader(filename));
+ String line = "";
+
+ ByteMessage data = new ByteMessage();
+ try {
+ while ((line = br.readLine()) != null) {
+ while(line.indexOf("0x") != -1) {
+ data.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ data.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ data.append(line);
+ }
+ }
+ catch(Exception e) {
+ System.out.println(e.toString());
+ }
+ finally {
+ try {
+ br.close();
+ }
+ catch(Exception e) {
+ System.out.println(e.toString());
+ }
+ }
+
+ return data.getString();
+ }
+
+ static public void main(String[] args) throws Exception {
+// /**
+// * server - port:10004
+// */
+// SocketAdapterContext context = new SocketAdapterContext();
+// context.setAdapterGroupName("FixedLengthHeaderAdapterServerGroup");
+// context.setAdapterName("Bin2ServerAdapter-10004");
+// context.setProtocol("FIXED_LENGTH_HEADER");
+// context.setSocketType("SERVER");
+// context.setHostName("*");
+// context.setPortNumber(10004);
+// context.setResponseType("ASYN");
+// context.setMaxConnection(10);
+// context.setMaxThread(100);
+// context.setTimeout(10);
+// context.setTraceLevel(context.TRACE_LEVEL_INFO);
+// final ISocketAdapter adapter4 = SocketAdapterFactory.createSocketAdapter(context);
+// adapter4.start();
+//
+//
+// /**
+// * server - port:10001
+// */
+// context = new SocketAdapterContext();
+// context.setAdapterGroupName("FixedLengthHeaderAdapterServerGroup");
+// context.setAdapterName("Bin2ServerAdapter-10001");
+// context.setProtocol("FIXED_LENGTH_HEADER");
+// context.setSocketType("SERVER");
+// context.setHostName("*");
+// context.setPortNumber(10001);
+// context.setResponseType("ASYN");
+// context.setMaxConnection(10);
+// context.setMaxThread(100);
+// context.setTimeout(10);
+// context.setTraceLevel(context.TRACE_LEVEL_INFO);
+//
+// context.setRequestProcessor(new IRequestProcessor() {
+// public byte[] handle(final byte[] request) throws Exception {
+//// ExecutorService executor = new ThreadPoolExecutor(16, 16, 60, TimeUnit.SECONDS, new LinkedBlockingQueue());
+//// executor.execute(new Runnable() {
+//// public void run() {
+//// try {
+// adapter4.sendMessage(request);
+//// } catch(Exception e) {
+//// e.printStackTrace();
+//// }
+//// }
+//// });
+// return request;
+// }
+// });
+//
+// final ISocketAdapter adapter1 = SocketAdapterFactory.createSocketAdapter(context);
+// adapter1.start();
+
+ //----------------------------------------------------------------------
+ if (System.getProperty("inst.Name") == null)
+ System.setProperty("inst.Name", System.getProperty("test"));
+
+ String hostname = "localhost";
+ String filename = "";
+
+ if (args.length == 2) {
+ hostname = args[0];
+ System.out.println("remote host : " + hostname);
+ filename = args[1];
+ } else {
+ System.out.println("Usage : loadrunner [ip] [file]");
+ return;
+ }
+
+ LoadRunner2 loadRunner = new LoadRunner2(hostname, filename);
+ loadRunner.processCommand();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/tester/Xecure2Simulator.java b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/Xecure2Simulator.java
new file mode 100644
index 0000000..45b6111
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/tester/Xecure2Simulator.java
@@ -0,0 +1,104 @@
+package com.eactive.eai.adapter.socket2.app.tester;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+public class Xecure2Simulator {
+
+ final ISocketAdapter httpAdapter;
+ final ISocketAdapter adapter21;
+ final ISocketAdapter adapter41;
+
+ public Xecure2Simulator(int echoPort, int destPort, int maxConn, String script, int adminPort) throws Exception {
+
+ SocketAdapterContext context = null;
+
+ /**
+ * Http Server
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("AdminAdapterGroup");
+ context.setAdapterName("HttpAdapter");
+ context.setProtocol("HTTP");
+ context.setBoundUsage("IOBOUND");
+ context.setSocketType("SERVER");
+ context.setHostName("*");
+ context.setPortNumber(adminPort);
+ context.setAckSupport("N");
+ context.setPermanent("N");
+ context.setResponseType("SYNC");
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_TRACE);
+ context.setAclList("172.26.128.*,127.0.0.1");
+ httpAdapter = SocketAdapterFactory.createSocketAdapter(context);
+ httpAdapter.start();
+
+ /**
+ * Inbound RECEIVER(SERVER) - 응답 수신[400]
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("EchoSimulatorAdapterGroup");
+ context.setAdapterName("DestinationAsS");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ //context.setBoundUsage("INBOUND");
+ //context.setHostName(hostname);
+ context.setPortNumber(destPort);//64001);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setResponseType("ASYN");
+ context.setMaxConnection(maxConn);//30);
+ context.setMaxThread(maxConn);//30);
+ context.setTimeout(60);
+ context.setTraceLevel(context.TRACE_LEVEL_TRACE);
+ adapter41 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter41.start();
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.print(".");
+ return request;
+ }
+ });
+
+ /**
+ * Outbound RECEIVER(SERVER) - 요청 수신[200]
+ */
+ context = new SocketAdapterContext();
+ context.setAdapterGroupName("EchoSimulatorAdapterGroup");
+ context.setAdapterName("EchoAsS");
+// context.setProtocol("XECURE2");
+ context.setProtocol("FIXED_LENGTH_HEADER");
+ context.setSocketType("SERVER");
+ context.setBoundUsage("IOBOUND");
+ //context.setHostName(hostname);
+ context.setPortNumber(echoPort);//62001);
+ context.setLlFieldType("CHAR");
+ context.setLlFieldLength(4);
+ context.setLlFieldOffset(0);
+ context.setLlFieldInclude("Y");
+ context.setLlInclude("Y");
+ context.setResponseType("ASYN");
+ context.setMaxConnection(maxConn);//30);
+ context.setMaxThread(maxConn);//30);
+ context.setTimeout(60);
+ context.setScript(script);//"asyn-perm.groovy");
+ context.setTraceLevel(context.TRACE_LEVEL_TRACE);
+ adapter21 = SocketAdapterFactory.createSocketAdapter(context);
+ adapter21.start();
+
+ }
+
+ static public void main(String[] args) throws Exception {
+
+ // eaiHost, eaiPort, echoPort, destPort, maxConn, script
+ int echoPort = Integer.parseInt(args[0]);
+ int destPort = Integer.parseInt(args[1]);
+ int maxConn = Integer.parseInt(args[2]);
+ String script = args[3];
+ int adminPort = Integer.parseInt(args[4]);
+ new Xecure2Simulator(echoPort, destPort, maxConn, script, adminPort);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/app/udpquote/UdpQuote.java b/src/main/java/com/eactive/eai/adapter/socket2/app/udpquote/UdpQuote.java
new file mode 100644
index 0000000..2507dc0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/app/udpquote/UdpQuote.java
@@ -0,0 +1,46 @@
+package com.eactive.eai.adapter.socket2.app.udpquote;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterFactory;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+
+
+public class UdpQuote {
+ static public void main(String[] args) throws Exception {
+ SocketAdapterContext context = new SocketAdapterContext();
+ context.setAdapterGroupName("UdpServerAdapterGroup");
+ context.setAdapterName("UdpServerAdapter");
+ context.setBoundUsage("INBOUND");
+ context.setResponseType("ASYN");
+
+// context.setSocketType("CLIENT");
+// context.setHostName("121.189.63.31");
+// context.setPortNumber(61868); //45517);
+// context.setLocalHostName("10.80.1.181");
+// context.setLocalPortNumber(45517);
+
+ context.setSocketType("SERVER");
+ context.setHostName("*");
+ context.setPortNumber(45517);
+
+ context.setProtocol("UDP_FIXED_LENGTH_PAYLOAD");
+ context.setSendPayloadLength(63);
+ context.setRecvPayloadLength(63);
+
+ context.setTimeout(60);
+ context.setMaxConnection(10);
+ context.setTraceLevel(context.TRACE_LEVEL_DEBUG);
+
+ context.setRequestProcessor(new IRequestProcessor() {
+ public byte[] handle(byte[] request) throws Exception {
+// System.out.println("[" + TimeUtil.formatDate(System.currentTimeMillis()) +
+// "] '" + new String(request) + "'");
+ return request;
+ }
+ });
+
+ ISocketAdapter client = SocketAdapterFactory.createSocketAdapter(context);
+ client.start().join();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/CircularQueue.java b/src/main/java/com/eactive/eai/adapter/socket2/common/CircularQueue.java
new file mode 100644
index 0000000..5889d64
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/CircularQueue.java
@@ -0,0 +1,111 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.collections.buffer.CircularFifoBuffer;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class CircularQueue extends CircularFifoBuffer {
+ static final Logger logger = SocketLoggerManager.getInstance().getLogger();
+
+ static final long AGE = 1000L * 60 * 60 * 24; // 1 day
+ static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("MM-dd HH:mm:ss");
+ private String logPrefix = "CircularQueue | ";
+
+ public CircularQueue(int maxSize) {
+ super(maxSize);
+ }
+
+ @Override
+ public synchronized boolean add(Object o) {
+ try {
+ return super.add(o);
+ } catch(Exception e) {
+ super.clear();
+ logger.warn(logPrefix + e.getMessage());
+ return true;
+ }
+ }
+
+ public synchronized void addRecord(String recordData) {
+ try {
+ super.add(new Tuple(System.currentTimeMillis(), recordData));
+ } catch(Exception e) {
+ super.clear();
+ logger.warn(logPrefix + e.getMessage());
+ }
+ }
+
+ public synchronized int getRecordCount() {
+ clearOldRecords();
+ return size();
+ }
+
+ public synchronized String[]getRecords() {
+ clearOldRecords();
+
+ Object[] elements = toArray();
+ String[] errors = new String[elements.length];
+ for (int i=0; i AGE) {
+ this.remove(tuple);
+ }
+ }
+ } catch(Exception e) {
+ super.clear();
+ logger.warn(logPrefix + e.getMessage());
+ }
+ }
+
+ public static class Tuple {
+ long time;
+ String message;
+
+ public Tuple(long time, String message) {
+ this.time = time;
+ this.message = message;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("CircularQueue max:" + maxSize() + " size:" + size() + "\n");
+ sb.append("---------------------------------------------------------------------------------------------------------------------\n");
+ Object[] elements = toArray();
+ for (int i=elements.length-1; i>=0; i--) {
+ if (elements[i] == null)
+ continue;
+ sb.append(((String) elements[i]) + "\n");
+ }
+ sb.append("---------------------------------------------------------------------------------------------------------------------\n");
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/CommonLib.java b/src/main/java/com/eactive/eai/adapter/socket2/common/CommonLib.java
new file mode 100644
index 0000000..bc729bb
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/CommonLib.java
@@ -0,0 +1,366 @@
+/*
+ * Created on 2005. 2. 26.
+ */
+package com.eactive.eai.adapter.socket2.common;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+/**
+ * 1. 기능 : SocketAdapter에서 사용되는 공통기능 제공
+ * 2. 처리 개요 :
+ * -
+ * 3. 주의사항
+ *
+ * @param
+ * @return
+ * @exception
+ **/
+import java.text.DecimalFormat;
+
+import org.apache.mina.common.ByteBuffer;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.common.errorcode.ErrorCodeHandler;
+
+/**
+ * @author janet
+ * 송수신 메시지 SPEC.
+ * llzz + syncFlag + user data(전문포맷전체를 사용자 DATA로 본다.)
+ * - llzz(2BYTE/4BYTE) UNSIGNED INTEGER로 처리한다. -- ConfigurationContext에 저장
+ * default는 4byte로 한다.
+ * - syncFlag - 'S' - R/R, 'A' - ASYNC, 'K' - ACK ONLY(이 경우, SEVER의 ACK를 받는다.
+ * - llzz+K[ACK|NACK]
+ * - user data,...
+ */
+public class CommonLib {
+
+ public static final char SPACE = ' ';
+
+ public static final char ZERO = '0';
+
+ public static final String EMPTY_STRING = "";
+
+ public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ public static final int NEGOTIATING_PROTOCOL = 1;
+
+ public static final int PROCESSING_PROTOCOL = 2;
+
+ public static final byte[] SYNC_PROTOCOL_MESSAGE = "SYNC".getBytes();
+
+ public static final byte[] ASYNC_PROTOCOL_MESSAGE = "ASYN".getBytes();
+
+ public static final byte[] NACK_MESSAGE = "NACK PROTOCOL VIOLATION".getBytes();
+
+ public static final byte[] ACK_MESSAGE = "ACK".getBytes();
+
+ private static final char[] HEX_CHAR_ARRAY = { '0', '1', '2', '3', '4',
+ '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ private CommonLib() {
+
+ }
+
+ /**
+ * BYTE ARRAY값을 HEXA STRING으로 변환하여 String을 리턴한다.
+ * @param abyte
+ * @return
+ */
+ public static String byte2Hex(byte[] abyte) {
+ StringBuilder buf = new StringBuilder();
+ int len = abyte.length;
+
+ int high = 0;
+ int low = 0;
+ for (int i = 0; i < len; i++) {
+ high = ((abyte[i] & 0xf0) >> 4);
+ low = (abyte[i] & 0x0f);
+ buf.append(HEX_CHAR_ARRAY[high]);
+ buf.append(HEX_CHAR_ARRAY[low]);
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * HEXA String값을 BYTE ARRAY로 변환한다.
+ * @param s
+ * @return
+ */
+ public static byte[] hex2Bytes(String s) {
+ byte[] abyte = new byte[s.length() / 2];
+ for (int j = 0; j < abyte.length; j++)
+ abyte[j] = (byte) Integer.parseInt(s.substring(2 * j, 2 * j + 2), 16);
+ return abyte;
+ }
+
+ /**
+ * 주어진 String값을 주어진 길이많큼 Padding/Trim한다.
+ * @param svalue - 입력스트링
+ * @param isRightJustify - true이면 RIGHT JUSTIFY, false이면 LEFT JUSTIFY
+ * @param padding - Padding 문자
+ * @param length - 리턴할 스트링의 바이트수
+ * @return 포맷팅된 String결과
+ */
+ public static String stringFormat(String svalue, boolean isRightJustify, char padding, int length) {
+ if ( svalue == null ) return svalue;
+
+ StringBuilder mpad = new StringBuilder();
+ StringBuilder fmtStr = new StringBuilder();
+
+ String tvalue = svalue;
+ int pLength = 0;
+
+ pLength = length - svalue.getBytes().length;
+
+ if (pLength == 0)
+ return svalue;
+ else if ( pLength < 0) {
+ byte[] abytes = null;
+ if (isRightJustify) {
+ abytes = (new String( svalue.getBytes(), -(pLength), length)).getBytes();
+ } else {
+ abytes = (new String( svalue.getBytes(), 0, length)).getBytes();
+ }
+
+ if ( abytes.length == length ) {
+ return new String( abytes );
+ } else {
+ tvalue = new String( abytes );
+ pLength = length - tvalue.length();
+ }
+ }
+
+ for(int i =0; i < pLength ; i++) {
+ mpad.append( padding );
+ }
+
+ if ( isRightJustify ) {
+ return fmtStr.append(mpad).append(tvalue).toString();
+ } else {
+ return fmtStr.append(tvalue).append(mpad).toString();
+ }
+ }
+
+ public static java.lang.String getFormatString(long value, int length)
+ {
+ DecimalFormat df = new DecimalFormat("000000000000000000");
+ String fs = df.format( value );
+ return fs.substring(fs.length() - length);
+ }
+
+ public static java.lang.String getFormatString(int value, int length)
+ {
+ DecimalFormat df = new DecimalFormat("000000000000000000");
+ String fs = df.format((long)value);
+ return fs.substring(fs.length() - length);
+ }
+
+ /**
+ * 메시지 비교
+ */
+ public static boolean compare(byte[] source, byte[] target) {
+ if ( source.length != target.length ) return false;
+
+ for ( int i=0; i < source.length; i++ ) {
+ if ( source[i] != target[i] ) return false;
+ }
+ return true;
+ }
+
+ /**
+ * 송수신전문에 대한 DUMP를 프린트할 수 있는 포맷으로 변환하여 String Array로 리턴한다.
+ * @param bytes
+ * @return
+ */
+ public static String[] makeDumpFormat(byte[] bytes) {
+ return makeDumpFormat(bytes, Charset.defaultCharset().toString());
+ }
+ public static String[] makeDumpFormat(byte[] bytes, String encode) {
+ if (bytes == null || bytes.length == 0)
+ return CommonLib.EMPTY_STRING_ARRAY;
+
+ String[] dumps = new String[bytes.length / 16 + ((bytes.length % 16) == 0 ? 4 : 5)];
+ dumps[0] = " +----------------------------------------------------------------------+";
+ dumps[1] = " | Offset | 0 1 2 3 4 5 6 7 8 9 A B C D E F | U S E R D A T A |";
+ dumps[2] = " |----------+----------------------------------------+------------------|";
+ dumps[dumps.length - 1] = " +----------------------------------------------------------------------+";
+
+ int len = 0;
+ final byte PERIOD = 0x2E;
+ char aChar ;
+ boolean isDBCS = false;
+ boolean isHalfDBCS = false;
+
+
+ for (int i = 3; i < dumps.length - 1; i++) {
+ len = ( ((bytes.length - (i - 2) * 16) >= 0) ? 16 : (bytes.length - (i - 3)*16) );
+ byte[] buf = new byte[len];
+ System.arraycopy( bytes, (i-3)*16, buf, 0, len );
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(" | ").append( stringFormat( Integer.toHexString((i-3)*16).toUpperCase(), true, ZERO, 8) ).append(" | ");
+
+ String hexStr = byte2Hex( buf );
+ StringBuilder fmtStr = new StringBuilder();
+
+ int k = hexStr.length()/8 + ((hexStr.length() % 8) == 0 ? 0 : 1);
+ for (int j=0; j < k ; j++) {
+ int l = ((hexStr.length() - (j+1)*8 ) >= 0 ? 8 : (hexStr.length() - j*8 ));
+ fmtStr.append( hexStr.substring(j*8, j*8 + l ) ).append(" ");
+ }
+
+ sb.append( stringFormat(fmtStr.toString(), false, SPACE, 39) ).append("| ");
+
+ k = 0;
+ // 한글 및 특수문자가 깨지게 표시되는 것 을 방지한다.
+ for ( int j=0; j < len; j++) {
+ if ( buf[j] >> 7 == 0 ) {
+ // Single Byte Character
+ if ( isDBCS ) {
+ isDBCS = false;
+ if ( k != 0 && ((k % 2) == 1 )) {
+ buf[j - 1] = PERIOD;
+ }
+ }
+ aChar = (char)buf[j];
+ if ( Character.isWhitespace( aChar ) || Character.isISOControl( aChar ) || buf[j] == 0 ) {
+ buf[j] = PERIOD;
+ }
+ continue;
+ }
+ // Double Bytes Character.
+ if ( !isDBCS ) isDBCS = true;
+ if ( j == 0 && isHalfDBCS ) {
+ buf[j] = PERIOD;
+ isDBCS = false;
+ continue;
+ }
+ // To check the DBCS pairwise
+ k++;
+ }
+ if ( isDBCS && ((k%2)==1) ) {
+ buf[ len -1 ] = PERIOD;
+ isHalfDBCS = true;
+ } else {
+ isHalfDBCS = false;
+ }
+ try {
+ dumps[i] = sb.append(stringFormat(new String(buf, encode), false, SPACE, 16)).append(" |").toString();
+ } catch (UnsupportedEncodingException e) {
+ dumps[i] = sb.append(stringFormat(new String(buf), false, SPACE, 16)).append(" |").toString();
+ }
+ }
+ return dumps;
+
+ }
+ public static String hexDump(byte[] message) {
+ return hexDump(message, true, Charset.defaultCharset().toString());
+ }
+
+ public static String hexDump(byte[] message, boolean printBytesInf) {
+ return hexDump(message, printBytesInf, Charset.defaultCharset().toString());
+ }
+ public static String hexDump(byte[] message, boolean printBytesInfo, SocketAdapterContext context) {
+ if (context != null && context.getAdapterVO() != null && context.getAdapterVO().getAdapterGroupVO() != null && context.getAdapterVO().getAdapterGroupVO().getMessageEncode() != null) {
+ return hexDump(message, printBytesInfo, context.getAdapterVO().getAdapterGroupVO().getMessageEncode());
+ }else {
+ return hexDump(message, printBytesInfo, Charset.defaultCharset().toString());
+ }
+ }
+ public static String hexDump(byte[] message, boolean printBytesInfo, String encode) {
+ String[] dumpMsg = makeDumpFormat(message, encode);
+ StringBuilder dump = new StringBuilder();
+ if (printBytesInfo) {
+ dump.append("byte[size=" + message.length + "]");
+ }
+ dump.append("\n");
+ for(int i=0; i < dumpMsg.length; i++) {
+ dump.append(dumpMsg[i]);
+ if (i < dumpMsg.length-1)
+ dump.append("\n");
+ }
+
+ return dump.toString();
+ }
+
+
+
+ /**
+ * ByteBuffer -> hexDump
+ */
+ public static String hexDump(ByteBuffer buffer) {
+ return hexDump(buffer, Charset.defaultCharset().toString());
+ }
+ public static String hexDump(ByteBuffer buffer, SocketAdapterContext context) {
+ if (context != null && context.getAdapterVO() != null && context.getAdapterVO().getAdapterGroupVO() != null && context.getAdapterVO().getAdapterGroupVO().getMessageEncode() != null) {
+ return hexDump(buffer, context.getAdapterVO().getAdapterGroupVO().getMessageEncode());
+ }else {
+ return hexDump(buffer, Charset.defaultCharset().toString());
+ }
+ }
+ public static String hexDump(ByteBuffer buffer, String encode) {
+ int mark = buffer.position();
+ byte[] bytes = new byte[buffer.remaining()];
+ buffer.get(bytes);
+ buffer.position(mark);
+ StringBuilder sb = new StringBuilder();
+ sb.append("ByteBuffer[pos=" + mark);
+ sb.append(", lim=" + buffer.limit());
+ sb.append(" ,cap=" + buffer.capacity() + "]");
+ sb.append(hexDump(bytes, false, encode));
+ return sb.toString();
+ }
+
+ public static String hexDumpRead(ByteBuffer buffer) {
+ return hexDumpRead(buffer, Charset.defaultCharset().toString());
+ }
+ public static String hexDumpRead(ByteBuffer buffer, SocketAdapterContext context) {
+ if (context != null && context.getAdapterVO() != null && context.getAdapterVO().getAdapterGroupVO() != null && context.getAdapterVO().getAdapterGroupVO().getMessageEncode() != null) {
+ return hexDumpRead(buffer, context.getAdapterVO().getAdapterGroupVO().getMessageEncode());
+ }else {
+ return hexDumpRead(buffer, Charset.defaultCharset().toString());
+ }
+ }
+ public static String hexDumpRead(ByteBuffer buffer, String encode) {
+ StringBuilder sb = new StringBuilder();
+ if (buffer.isDirect()) {
+ sb.append("DirectBuffer");
+ } else {
+ sb.append("HeapBuffer");
+ }
+ sb.append("[pos=");
+ sb.append(buffer.position());
+ sb.append(" lim=");
+ sb.append(buffer.limit());
+ sb.append(" cap=");
+ sb.append(buffer.capacity());
+ sb.append("] - ");
+ int mark = buffer.position();
+ int limit = buffer.limit();
+ byte[] bytes = new byte[mark];
+ buffer.position(0).limit(mark);
+ buffer.get(bytes);
+ buffer.position(mark);
+ buffer.limit(limit);
+ sb.append(hexDump(bytes, true, encode));
+ return sb.toString();
+ }
+ public static String getMessage(String msgCode, String[] params) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[").append(msgCode).append("] ").append( ErrorCodeHandler.getMessage( msgCode, params ) );
+ return sb.toString();
+ }
+
+ public static String getMessage(String msgCode) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[").append(msgCode).append("] ").append( ErrorCodeHandler.getMessage( msgCode ) );
+ return sb.toString();
+ }
+
+ public static String getDebugMessage(String msgCode, String[] params) {
+ StringBuilder sb = new StringBuilder();
+ sb.append( ErrorCodeHandler.getMessage( msgCode, params ) );
+ return ErrorCodeHandler.getMessage( msgCode, params );
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/Env.java b/src/main/java/com/eactive/eai/adapter/socket2/common/Env.java
new file mode 100644
index 0000000..d5a41c8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/Env.java
@@ -0,0 +1,35 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import com.eactive.eai.common.server.Keys;
+
+public class Env {
+ static final boolean IS_WINDOWS = System.getProperty("os.name", "Windows").startsWith("Windows");
+ static final boolean IS_ECHO = System.getProperty("echo") != null;
+ static final boolean IS_TEST = System.getProperty("test") != null;
+ static final boolean IS_STANDALONE = System.getProperty(Keys.SERVER_KEY) == null;
+ static final boolean IS_SMS_ENABLED = System.getProperty("sms.logging", "true").equalsIgnoreCase("true");
+
+ private Env() {
+
+ }
+
+ public static boolean isWindows() {
+ return IS_WINDOWS;
+ }
+
+ public static boolean isEcho() {
+ return IS_ECHO;
+ }
+
+ public static boolean isTest() {
+ return IS_TEST;
+ }
+
+ public static boolean isStandalone() {
+ return IS_STANDALONE;
+ }
+
+ public static boolean isSmsEnabled() {
+ return IS_SMS_ENABLED;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/ExceptionStackTrace.java b/src/main/java/com/eactive/eai/adapter/socket2/common/ExceptionStackTrace.java
new file mode 100644
index 0000000..a38fc06
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/ExceptionStackTrace.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.common;
+
+public class ExceptionStackTrace {
+ private ExceptionStackTrace() {
+
+ }
+ public static String dump(Throwable t) {
+ return ThreadDumpUtil.getStackTrace(t);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/ExecutionContext.java b/src/main/java/com/eactive/eai/adapter/socket2/common/ExecutionContext.java
new file mode 100644
index 0000000..a097627
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/ExecutionContext.java
@@ -0,0 +1,46 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import java.util.Hashtable;
+
+
+public class ExecutionContext extends ThreadLocal {
+ static ExecutionContext instance = new ExecutionContext();
+
+ public static ExecutionContext getInstance() {
+ return instance;
+ }
+
+ private ExecutionContext() {
+ super();
+ }
+
+ protected Object initialValue() {
+ return new Hashtable();
+ }
+
+ public void set(String key, Object value) {
+ ((Hashtable) super.get()).put(key, value);
+ }
+
+ public Object get(String key) {
+ return ((Hashtable) super.get()).get(key);
+ }
+
+ public void remove(String key) {
+ ((Hashtable) super.get()).remove(key);
+ }
+
+ public void set(Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object get() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
+
+
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/ExpiringMap.java b/src/main/java/com/eactive/eai/adapter/socket2/common/ExpiringMap.java
new file mode 100644
index 0000000..f1cc512
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/ExpiringMap.java
@@ -0,0 +1,636 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * A map with expiration.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+public class ExpiringMap implements Map {
+
+ /** The Constant DEFAULT_TIME_TO_LIVE. */
+ public static final int DEFAULT_TIME_TO_LIVE = 60;
+
+ /** The Constant DEFAULT_EXPIRATION_INTERVAL. */
+ public static final int DEFAULT_EXPIRATION_INTERVAL = 1;
+
+ /** The Constant DEFAULT_EXPIRATION_INTERVAL. */
+ public static final String DEFAULT_NAME = "DEFAULT";
+
+
+ /** The expirer count. */
+ private static volatile int expirerCount = 1;
+
+ private String name =null;
+
+ /** The delegate. */
+ private final ConcurrentHashMap delegate;
+
+ /** The expirer. */
+ private final Expirer expirer;
+
+ /**
+ * Instantiates a new expiring map.
+ */
+ public ExpiringMap() {
+ this(DEFAULT_NAME,DEFAULT_TIME_TO_LIVE, DEFAULT_EXPIRATION_INTERVAL);
+ }
+ /**
+ * Instantiates a new expiring map.
+ *
+ * @param timeToLive the time to live
+ */
+ public ExpiringMap(int timeToLive) {
+ this(DEFAULT_NAME,timeToLive, DEFAULT_EXPIRATION_INTERVAL);
+ }
+ /**
+ * Instantiates a new expiring map.
+ *
+ * @param timeToLive the time to live
+ */
+ public ExpiringMap(String name,int timeToLive) {
+ this(name,timeToLive, DEFAULT_EXPIRATION_INTERVAL);
+ }
+ /**
+ * Instantiates a new expiring map.
+ *
+ * @param timeToLive the time to live
+ * @param expirationInterval the expiration interval
+ */
+ public ExpiringMap(int timeToLive, int expirationInterval) {
+ this(DEFAULT_NAME,new ConcurrentHashMap(),
+ timeToLive,
+ expirationInterval);
+ }
+ /**
+ * Instantiates a new expiring map.
+ *
+ * @param timeToLive the time to live
+ * @param expirationInterval the expiration interval
+ */
+ public ExpiringMap(String name,int timeToLive, int expirationInterval) {
+ this(name,new ConcurrentHashMap(),
+ timeToLive,
+ expirationInterval);
+ }
+
+ /**
+ * Instantiates a new expiring map.
+ *
+ * @param delegate the delegate
+ * @param expirationListeners the expiration listeners
+ * @param timeToLive the time to live
+ * @param expirationInterval the expiration interval
+ */
+ private ExpiringMap(String name,ConcurrentHashMap delegate,
+ int timeToLive, int expirationInterval) {
+ this.name = name;
+ this.delegate = delegate;
+
+ this.expirer = new Expirer();
+ expirer.setExpirationInterval(expirationInterval);
+ expirer.setTimeToLive(timeToLive);
+ expirer.startExpiring();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#put(java.lang.Object, java.lang.Object)
+ */
+ public V put(K key, V value) {
+ ExpiringObject answer = delegate.put(key, new ExpiringObject(key,
+ value, System.currentTimeMillis()));
+ if (answer == null) {
+ return null;
+ }
+
+ return answer.getValue();
+ }
+
+ /**
+ * Put.
+ *
+ * @param key the key
+ * @param value the value
+ * @param timeToLive the time to live
+ *
+ * @return the v
+ */
+ public V put(K key, V value, int timeToLive) {
+ ExpiringObject answer = delegate.put(key, new ExpiringObject(key,
+ value, System.currentTimeMillis(), timeToLive));
+ if (answer == null) {
+ return null;
+ }
+
+ return answer.getValue();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#get(java.lang.Object)
+ */
+ public V get(Object key) {
+ ExpiringObject object = delegate.get(key);
+ if (object != null) {
+ return object.getValue();
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#remove(java.lang.Object)
+ */
+ public V remove(Object key) {
+ ExpiringObject answer = delegate.remove(key);
+ if (answer == null) {
+ return null;
+ }
+
+ return answer.getValue();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#containsKey(java.lang.Object)
+ */
+ public boolean containsKey(Object key) {
+ return delegate.containsKey(key);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#containsValue(java.lang.Object)
+ */
+ public boolean containsValue(Object value) {
+ return delegate.containsValue(value);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#size()
+ */
+ public int size() {
+ return delegate.size();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#isEmpty()
+ */
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#clear()
+ */
+ public void clear() {
+ delegate.clear();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#keySet()
+ */
+ public Set keySet() {
+ return delegate.keySet();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return delegate.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ public void putAll(Map extends K, ? extends V> inMap) {
+ for (Entry extends K, ? extends V> e : inMap.entrySet()) {
+ this.put(e.getKey(), e.getValue());
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#values()
+ */
+ public Collection values() {
+ throw new UnsupportedOperationException();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Map#entrySet()
+ */
+ public Set> entrySet() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gets the expirer.
+ *
+ * @return the expirer
+ */
+ public Expirer getExpirer() {
+ return expirer;
+ }
+
+ /**
+ * Gets the expiration interval.
+ *
+ * @return the expiration interval
+ */
+ public int getExpirationInterval() {
+ return expirer.getExpirationInterval();
+ }
+
+ /**
+ * Gets the time to live.
+ *
+ * @return the time to live
+ */
+ public int getTimeToLive() {
+ return expirer.getTimeToLive();
+ }
+
+ /**
+ * Sets the expiration interval.
+ *
+ * @param expirationInterval the new expiration interval
+ */
+ public void setExpirationInterval(int expirationInterval) {
+ expirer.setExpirationInterval(expirationInterval);
+ }
+
+ /**
+ * Sets the time to live.
+ *
+ * @param timeToLive the new time to live
+ */
+ public void setTimeToLive(int timeToLive) {
+ expirer.setTimeToLive(timeToLive);
+ }
+
+ /**
+ * The Class ExpiringObject.
+ *
+ * 1. Function :
+ * 2. Summary :
+ * 3. Notification :
+ *
+ *
+ * @author : $Author: $
+ * @version : $Revision: 1.4 $
+ */
+ private class ExpiringObject {
+
+ /** The key. */
+ private K key;
+
+ /** The value. */
+ private V value;
+
+ /** The access time. */
+ private long accessTime;
+
+ /** The time to live millis. */
+ private long timeToLiveMillis;
+
+ /**
+ * Instantiates a new expiring object.
+ *
+ * @param key the key
+ * @param value the value
+ * @param accessTime the access time
+ */
+ ExpiringObject(K key, V value, long accessTime) {
+ this(key, value, accessTime, 0);
+ }
+
+ /**
+ * Instantiates a new expiring object.
+ *
+ * @param key the key
+ * @param value the value
+ * @param accessTime the access time
+ * @param timeToLiveMillis the time to live millis
+ */
+ ExpiringObject(K key, V value, long accessTime, int timeToLiveMillis) {
+
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "An expiring object cannot be null.");
+ }
+
+ this.key = key;
+ this.value = value;
+ this.accessTime = accessTime;
+ this.timeToLiveMillis = timeToLiveMillis * 1000;
+ }
+
+ /**
+ * Gets the time to live millis.
+ *
+ * @return the time to live millis
+ */
+ public long getTimeToLiveMillis() {
+ return timeToLiveMillis;
+ }
+
+ /**
+ * Sets the time to live millis.
+ *
+ * @param timeToLiveMillis the new time to live millis
+ */
+ public void setTimeToLiveMillis(long timeToLiveMillis) {
+ this.timeToLiveMillis = timeToLiveMillis;
+ }
+
+ /**
+ * Gets the access time.
+ *
+ * @return the access time
+ */
+ public long getAccessTime() {
+ return accessTime;
+ }
+
+ /**
+ * Sets the access time.
+ *
+ * @param lastAccessTime the new access time
+ */
+ public void setAccessTime(long lastAccessTime) {
+ this.accessTime = lastAccessTime;
+ }
+
+ /**
+ * Gets the key.
+ *
+ * @return the key
+ */
+ public K getKey() {
+ return key;
+ }
+
+ /**
+ * Gets the value.
+ *
+ * @return the value
+ */
+ public V getValue() {
+ return value;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return value.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+ }
+
+ /**
+ * The Class Expirer.
+ *
+ * 1. Function :
+ * 2. Summary :
+ * 3. Notification :
+ *
+ *
+ * @author : $Author:
+ * @version : $Revision: 1.4 $
+ */
+ public class Expirer implements Runnable {
+
+ /** The state lock. */
+ private ReadWriteLock stateLock = new ReentrantReadWriteLock();
+
+ /** The time to live millis. */
+ private long timeToLiveMillis;
+
+ /** The expiration interval millis. */
+ private long expirationIntervalMillis;
+
+ /** The running. */
+ private boolean running = false;
+
+ /** The expirer thread. */
+ private final Thread expirerThread;
+
+ /**
+ * Instantiates a new expirer.
+ */
+ public Expirer() {
+ expirerThread = new Thread(this, "ExpiringMapExpirer-"+name+"-"
+ + (expirerCount++));
+ expirerThread.setDaemon(true);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ while (running) {
+ processExpires();
+
+ try {
+ Thread.sleep(expirationIntervalMillis);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ /**
+ * Process expires.
+ * expire : timeNow >= expireTime
+ * expireTime = accessTime + timeToLive
+ */
+ private void processExpires() {
+ long timeNow = System.currentTimeMillis();
+
+ long timeToLiveMillis = 0;
+
+ for (ExpiringObject o : delegate.values()) {
+
+ if (o.getTimeToLiveMillis() > 0) {
+ timeToLiveMillis = o.getTimeToLiveMillis();
+ } else {
+ timeToLiveMillis = this.timeToLiveMillis;
+ }
+
+ if (timeToLiveMillis <= 0)
+ continue;
+
+ long expireTime = o.getAccessTime() + timeToLiveMillis;
+
+ if (timeNow >= expireTime) {
+ delegate.remove(o.getKey());
+ }
+ }
+ }
+
+ /**
+ * Start expiring.
+ */
+ public void startExpiring() {
+ stateLock.writeLock().lock();
+
+ try {
+ if (!running) {
+ running = true;
+ expirerThread.start();
+ }
+ } finally {
+ stateLock.writeLock().unlock();
+ }
+ }
+
+ /**
+ * Start expiring if not started.
+ */
+ public void startExpiringIfNotStarted() {
+ stateLock.readLock().lock();
+ try {
+ if (running) {
+ return;
+ }
+ } finally {
+ stateLock.readLock().unlock();
+ }
+
+ stateLock.writeLock().lock();
+ try {
+ if (!running) {
+ running = true;
+ expirerThread.start();
+ }
+ } finally {
+ stateLock.writeLock().unlock();
+ }
+ }
+
+ /**
+ * Stop expiring.
+ */
+ public void stopExpiring() {
+ stateLock.writeLock().lock();
+
+ try {
+ if (running) {
+ running = false;
+ expirerThread.interrupt();
+ }
+ } finally {
+ stateLock.writeLock().unlock();
+ }
+ }
+
+ /**
+ * Checks if is running.
+ *
+ * @return true, if is running
+ */
+ public boolean isRunning() {
+ stateLock.readLock().lock();
+
+ try {
+ return running;
+ } finally {
+ stateLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Gets the time to live.
+ *
+ * @return the time to live
+ */
+ public int getTimeToLive() {
+ stateLock.readLock().lock();
+
+ try {
+ return (int) timeToLiveMillis / 1000;
+ } finally {
+ stateLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Sets the time to live.
+ *
+ * @param timeToLive the new time to live
+ */
+ public void setTimeToLive(long timeToLive) {
+ stateLock.writeLock().lock();
+
+ try {
+ this.timeToLiveMillis = timeToLive * 1000;
+ } finally {
+ stateLock.writeLock().unlock();
+ }
+ }
+
+ /**
+ * Gets the expiration interval.
+ *
+ * @return the expiration interval
+ */
+ public int getExpirationInterval() {
+ stateLock.readLock().lock();
+
+ try {
+ return (int) expirationIntervalMillis / 1000;
+ } finally {
+ stateLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Sets the expiration interval.
+ *
+ * @param expirationInterval the new expiration interval
+ */
+ public void setExpirationInterval(long expirationInterval) {
+ stateLock.writeLock().lock();
+
+ try {
+ this.expirationIntervalMillis = expirationInterval * 1000;
+ } finally {
+ stateLock.writeLock().unlock();
+ }
+ }
+ }
+ public static void main (String[] args) throws Exception{
+ ExpiringMap m = new ExpiringMap(1);
+ String key ="aaaaaaa";
+ m.put(key,key);
+ System.out.println(m.get(key));
+ Thread.sleep(1 * 1000L);
+ System.out.println(m.get(key));
+ Thread.sleep(1 * 1000L);
+ System.out.println(m.get(key));
+ Thread.sleep(1 * 1000L);
+ System.out.println(m.get(key));
+ Thread.sleep(1 * 1000L);
+ System.out.println(m.get(key));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/FileUtil.java b/src/main/java/com/eactive/eai/adapter/socket2/common/FileUtil.java
new file mode 100644
index 0000000..0d359c1
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/FileUtil.java
@@ -0,0 +1,34 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+
+public class FileUtil {
+ private FileUtil() {
+
+ }
+ public static byte[] readFile(String filename) throws IOException {
+
+ try (
+ BufferedReader br = new BufferedReader(new FileReader(filename));
+ ) {
+ String line = "";
+ ByteMessage m = new ByteMessage();
+ while ((line = br.readLine()) != null) {
+ while(line.indexOf("0x") != -1) {
+ m.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ m.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ m.append(line);
+ }
+ return m.getBytes();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/FutureMap.java b/src/main/java/com/eactive/eai/adapter/socket2/common/FutureMap.java
new file mode 100644
index 0000000..5bdd83d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/FutureMap.java
@@ -0,0 +1,21 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class FutureMap {
+ Map map;
+
+ public FutureMap() {
+ map = Collections.synchronizedMap(new HashMap());
+ }
+
+ public void put(String key, SimpleFuture future) {
+ map.put(key, future);
+ }
+
+ public SimpleFuture get(String key) {
+ return map.remove(key);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/HexUtil.java b/src/main/java/com/eactive/eai/adapter/socket2/common/HexUtil.java
new file mode 100644
index 0000000..2b79d07
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/HexUtil.java
@@ -0,0 +1,23 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+
+
+public class HexUtil {
+ private HexUtil() {
+
+ }
+ public static byte[] string2Hex(String line) {
+
+ ByteMessage m = new ByteMessage();
+
+ while(line.indexOf("0x") != -1) {
+ m.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ m.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ m.append(line);
+ return m.getBytes();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/SMSLogger.java b/src/main/java/com/eactive/eai/adapter/socket2/common/SMSLogger.java
new file mode 100644
index 0000000..7344898
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/SMSLogger.java
@@ -0,0 +1,28 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import com.eactive.eai.common.util.SMSLogUtil;
+import com.eactive.eai.common.util.StringUtil;
+
+public class SMSLogger {
+ private SMSLogger() {
+
+ }
+ public static void loggingSMS(String svcName, String logMsg) {
+ if(Env.isSmsEnabled()) {
+ SMSLogUtil.loggingSMS(svcName, logMsg);
+ }
+ }
+
+ public static void loggingSMSWithCode(String svcName, String code) {
+ if(Env.isSmsEnabled()) {
+ SMSLogUtil.loggingSMSWithCode(svcName, code);
+ }
+ }
+
+ public static void loggingSMS4Soc(String adptName, String adptDesc, String code) {
+ if(Env.isSmsEnabled()) {
+ String svcName = StringUtil.chunkString(adptDesc, 12) + "|" + adptName;
+ SMSLogUtil.loggingSMSWithCode(svcName, code);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/SimpleFuture.java b/src/main/java/com/eactive/eai/adapter/socket2/common/SimpleFuture.java
new file mode 100644
index 0000000..04994c0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/SimpleFuture.java
@@ -0,0 +1,44 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import com.eactive.eai.adapter.socket2.EAITimeoutException;
+
+public class SimpleFuture {
+ private Object result;
+ private boolean ready = false;
+
+ public synchronized void init() {
+ ready = false;
+ }
+
+ public synchronized void set(Object result) {
+ this.result = result;
+ this.ready = true;
+ notifyAll();
+ }
+
+ public synchronized Object join() {
+ //return join(60000L); // 60 seconds
+
+ while (!ready) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ return result;
+ }
+
+ public synchronized Object join(long timeout) throws EAITimeoutException {
+ while (!ready) {
+ try {
+ wait(timeout);
+ } catch (InterruptedException e) {
+ break;
+ }
+ if (!ready)
+ throw new EAITimeoutException("timeout error (" + timeout + "ms)");
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/SocketAdapterException.java b/src/main/java/com/eactive/eai/adapter/socket2/common/SocketAdapterException.java
new file mode 100644
index 0000000..c7cf110
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/SocketAdapterException.java
@@ -0,0 +1,114 @@
+/*
+ * Created on 2005. 2. 26.
+ *
+ */
+package com.eactive.eai.adapter.socket2.common;
+
+import com.eactive.eai.adapter.EAIException;
+
+/**
+ * @author janet
+ *
+ */
+public class SocketAdapterException extends EAIException {
+
+ public static final int UNEXPECTED_TERMINATION = 1;
+
+ public static final int REMOTE_HOST_DISCONNECTED = 2;
+
+ public static final int INTERNAL_ERROR = 5;
+
+ public static final int CHANNEL_FAILURE = 6;
+
+ public static final int CANCELLED_CONNECTION = 8;
+
+ public static final int CONNECT_FAILED = 10;
+
+ public static final int CONNECTION_CLOSED = 12;
+
+ public static final int AGENT_ERROR = 13;
+
+ public static final int SESSION_STREAM_ERROR = 15;
+
+ int reason;
+
+ Throwable cause;
+
+ /**
+ * Create an exception with the given description and reason.
+ * @param msg
+ * @param reason
+ */
+
+ public SocketAdapterException(String msg, int reason) {
+ this(msg, reason, null);
+ }
+
+ /**
+ * Create an exception with the given cause and reason.
+ * @param reason
+ * @param cause
+ */
+ public SocketAdapterException(int reason, Throwable cause) {
+ this(null, reason, cause);
+ }
+
+ /**
+ * Create an exception with the given description and cause. The reason given
+ * will be INTERNAL_ERROR.
+ *
+ * @param msg
+ * @param cause
+ */
+ public SocketAdapterException(String msg, Throwable cause) {
+ this(msg, INTERNAL_ERROR, cause);
+ }
+
+ /**
+ *
+ * @param msg
+ */
+ public SocketAdapterException(String msg) {
+ this(msg, INTERNAL_ERROR, null);
+ }
+
+ /**
+ * Create an exception by providing the cause of the error. This constructor
+ * sets the reason to INTERNAL_ERROR.
+ * @param cause
+ */
+ public SocketAdapterException(Throwable cause) {
+ this("An unexpected exception was caught: " + cause.getMessage(), cause);
+ }
+
+ /**
+ * Create an exception with the given description cause, reason.
+ * @param msg
+ * @param reason
+ * @param cause
+ */
+ public SocketAdapterException(String msg, int reason, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ this.reason = reason;
+ }
+
+ /**
+ * Get the reason for the exception
+ * @return
+ */
+ public int getReason() {
+ return reason;
+ }
+
+ /**
+ * If an INTERNAL_ERROR reason is given this method MAY return the cause of
+ * the error.
+ * @return
+ */
+ @Override
+ public synchronized Throwable getCause() {
+ return cause;
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/StopWatch.java b/src/main/java/com/eactive/eai/adapter/socket2/common/StopWatch.java
new file mode 100644
index 0000000..1fb8aec
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/StopWatch.java
@@ -0,0 +1,73 @@
+package com.eactive.eai.adapter.socket2.common;
+
+
+public class StopWatch {
+ private long startTime = -1;
+ private long stopTime = -1;
+ private final int HIM = 60 * 60 * 1000;
+ private final int MIM = 60 * 1000;
+
+ public StopWatch() {
+ super();
+ }
+
+ public void start() {
+ this.startTime = System.currentTimeMillis();
+ }
+
+ public void stop() {
+ this.stopTime = System.currentTimeMillis();
+ }
+
+ public void reset() {
+ this.startTime = -1;
+ this.stopTime = -1;
+ }
+
+ public long getTime() {
+ if (stopTime == -1) {
+ return (System.currentTimeMillis() - this.startTime);
+ } else {
+ return (this.stopTime - this.startTime);
+ }
+ }
+
+ public String toString() {
+ return getTimeString();
+ }
+
+ protected String getTimeString() {
+ int hours;
+ int minutes;
+ int seconds;
+ int milliseconds;
+ long time = getTime();
+ hours = (int) (time / HIM);
+ time = time - (hours * HIM);
+ minutes = (int) (time / MIM);
+ time = time - (minutes * MIM);
+ seconds = (int) (time / 1000);
+ time = time - (seconds * 1000);
+ milliseconds = (int) time;
+
+ return hours + "h:" + minutes + "m:" + seconds + "s:" + milliseconds + "ms";
+ }
+
+// public static void main(String args[]) throws Exception {
+// test();
+//}
+
+// private static void test() throws Exception {
+// StopWatch stopWatch = new StopWatch();
+// stopWatch.start();
+//
+// try {
+// Thread.currentThread().sleep(1500);
+// } catch (InterruptedException ie) {
+// System.out.println("error");
+// }
+//
+// stopWatch.stop();
+// System.out.println(stopWatch);
+// }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/common/ThreadDumpUtil.java b/src/main/java/com/eactive/eai/adapter/socket2/common/ThreadDumpUtil.java
new file mode 100644
index 0000000..8662de3
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/common/ThreadDumpUtil.java
@@ -0,0 +1,142 @@
+package com.eactive.eai.adapter.socket2.common;
+
+import java.util.Arrays;
+import java.util.Hashtable;
+
+
+public class ThreadDumpUtil {
+ public String threadDump() throws Exception {
+// //name = "ExecuteThread: '"+name+"' for queue: 'weblogic.kernel.Default'";
+// ThreadGroup it = Thread.currentThread().getThreadGroup();
+//
+// out.println("[group] " + it.getName() + "
");
+//
+// Thread[] threads = new Thread[it.activeCount()] ;
+// out.println("active count : "+it.activeCount() + "
");
+// it.enumerate(threads);
+// out.println("
");
+// for(int i=0;i");
+// out.println(getStackTrace(threads[i]));
+// out.println("");
+// }
+// }
+// out.println("
");
+ return null;
+ }
+
+ static private String getStackTrace(Thread thread) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("■ " + thread.getName() + " ");
+ sb.append("prio=" + thread.getPriority() + " ");
+ sb.append(thread.isDaemon() ? "daemon " : " ");
+
+ StackTraceElement stack[] = thread.getStackTrace();
+
+ if (stack==null || stack.length<1)
+ return sb.toString();
+
+ if (stack[0].getMethodName().equals("wait"))
+ sb.append("wait \n");
+ else if (stack[0].getMethodName().equals("sleep"))
+ sb.append("sleep \n");
+ else
+ sb.append(stack[0].getMethodName() + " \n");
+
+ for (int i=0; i at ");
+ else
+ sb.append(" at ");
+ sb.append(className + "." + methodName);
+ sb.append("(" + filename + ":" + (isNativeMethod ? "native" : String.valueOf(line)) + ")");
+ if (!className.startsWith("java") && !className.startsWith("org.") && !className.startsWith("sun.") && !className.startsWith("com.sun."))
+ sb.append("-");
+ sb.append("\n");
+ }
+
+// if (stack[0].getMethodName().equals("wait"))
+// return "" + sb.toString() + " ";
+// else if (stack[0].getMethodName().equals("sleep"))
+// return "" + sb.toString() + " ";
+// else
+ return sb.toString();
+ }
+
+ static public String dump() {
+ Hashtable hash = new Hashtable();
+
+ StringBuffer sb = new StringBuffer();
+ ThreadGroup it = Thread.currentThread().getThreadGroup();
+ //sb.append("[group] " + it.getName() + "\n");
+ Thread[] threads = new Thread[it.activeCount()] ;
+ sb.append("active thread count : " + it.activeCount() + "\n");
+ it.enumerate(threads);
+
+ //----------------------------------------------------------------------
+ ///*
+ String[] threadNames = new String[threads.length];
+ for (int i=0; i Integer.parseInt(props[2])) return false;
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/config/Constants.java b/src/main/java/com/eactive/eai/adapter/socket2/config/Constants.java
new file mode 100644
index 0000000..2d96fed
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/config/Constants.java
@@ -0,0 +1,210 @@
+/*
+ * Created on 2005. 7. 10.
+ *
+ */
+package com.eactive.eai.adapter.socket2.config;
+
+/**
+* 1. 기능 : Socket Adapter의 구성정보를 지정하기 위한 property의 KEY값을 나타낸다.
+* 2. 처리 개요 :
+* -
+* 3. 주의사항
+*
+* @param
+* @return
+* @exception
+**/
+public interface Constants {
+
+ //public static final String ADAPTER_NAME = "adapter.name";
+
+ /**
+ * Socket Adapter의 Adapter Group명을 나타낸는 KEY값
+ */
+ public static final String ADAPTER_GROUP_NAME = "adapter.group.name";
+
+
+ /**
+ * protocol [FIXED_LENGTH_HEADER|CISCO|XECURE|CERT|ADMIN|HTTP]
+ */
+ public static final String PROTOCOL = "protocol";
+
+
+ /**
+ * Socket Adapter가 INBOUND/OUTBOUND/IOBOUND용인지 나타내기위한 KEY값
+ */
+ public static final String BOUND_USAGE = "bound.usage";
+
+ /**
+ * Socket Adapter의 SOCKET유형이 [SERVER|CLIENT]에 구분을 나타
+ */
+ public static final String SOCKET_TYPE = "socket.type";
+ public static final String PERMANENT = "permanent";
+ public static final String BLOCKING = "blocking";
+ public static final String POLLING_TYPE = "polling.type";
+ public static final String HOST_NAME = "host.name";
+ public static final String HOST_NAME_DR = "host.name.dr";
+ public static final String PORT_NUMBER = "port.number";
+ public static final String PORT_NUMBER_DR = "port.number.dr";
+ public static final String LOCAL_HOST_NAME = "local.host.name";
+ public static final String LOCAL_PORT_NUMBER = "local.port.number";
+ public static final String CONN_LIMIT_PER_IP = "connection.limit.per.ip";
+ public static final String MAX_CONNECTION = "max.connection";
+ public static final String MAX_THREAD = "max.thread";
+ public static final String TIMEOUT = "timeout";
+ public static final String IDLE_TIMEOUT = "idle.timeout";
+ public static final String RESPONSE_TYPE = "response.type";
+ public static final String SOCKET_REUSE = "socket.reuse";
+
+ public static final String LL_FIELD_TYPE = "ll.field.type"; // [BIN|CHAR|CISCO]
+ public static final String LL_FIELD_LENGTH = "ll.field.length";
+ public static final String LL_FIELD_OFFSET = "ll.field.offset";
+ public static final String LL_FIELD_INCLUDE = "ll.field.include";
+ public static final String LL_OFFSET_EXCLUDE = "ll.offset.exclude";
+ public static final String LL_INCLUDE = "ll.include";
+
+ public static final String LL_LENGTH_ADJUST = "ll.length.adjust";
+
+ public static final String SEND_HEADER_LENGTH = "send.header.length"; // 2012.10.30 Kwon Se Hwan
+ public static final String RECV_HEADER_LENGTH = "recv.header.length"; // 2012.10.30 Kwon Se Hwan
+
+ public static final String SEND_PAYLOAD_LENGTH = "send.payload.length";
+ public static final String RECV_PAYLOAD_LENGTH = "recv.payload.length";
+
+ public static final String ACK_SUPPORT = "ack.support";
+ public static final String VALIDATION_RULE = "validation.rule";
+ public static final String DATACONTROL_RULE = "datacontrol.rule";
+ public static final String ACL_LIST = "acl.list";
+ public static final String WORK_CLASS_CODE = "business.work.class.code";
+ public static final String TRACE_LEVEL = "trace.level";
+ public static final String DESCRIPTION = "description";
+
+ public static final String POLLING_USE = "polling.use";
+ public static final String POLLING_ROLE = "polling.role";
+ public static final String POLLING_ONEWAY = "polling.oneway";
+ public static final String POLLING_TIMEOUT = "polling.timeout";
+ public static final String POLLING_REQUEST = "polling.request";
+ public static final String POLLING_REQUEST_PATTERN = "polling.request.pattern";
+ public static final String POLLING_REPLACEMENT = "polling.replacement";
+ public static final String POLLING_RESPONSE_PATTERN = "polling.response.pattern";
+
+ public static final String INIT_MSG_USE = "init.msg.use";
+ public static final String INIT_MSG_ROLE = "init.msg.role";
+ public static final String INIT_MSG_REQUEST = "init.msg.request";
+ public static final String INIT_MSG_REQUEST_PATTERN = "init.msg.request.pattern";
+ public static final String INIT_MSG_REPLACEMENT = "init.msg.replacement";
+ public static final String INIT_MSG_RESPONSE_PATTERN = "init.msg.response.pattern";
+
+ public static final String SSL_USE = "ssl.use";
+ public static final String SSL_CERT_STORE = "ssl.cert.store";
+ public static final String SSL_CERT_PASSWORD = "ssl.cert.password";
+
+ public static final String DES_USE = "des.use";
+
+ public static final String SEED_USE = "seed.use";
+
+ /**
+ * inisafe
+ */
+ public static final String INISAFE_CONFIG_PATH = "inisafe.config.path";
+ public static final String INISAFE_RELATED_ADAPTER_GROUPS = "inisafe.related.adapter.groups";
+ public static final String INISAFE_START_MESSAGE = "inisafe.start.message";
+ public static final String INISAFE_STOP_MESSAGE = "inisafe.stop.message";
+
+ /**
+ * inisafe_payload 20100515 JGY
+ */
+ public static final String INISAFE_ID_PASSWORD = "inisafe.id.password";
+
+ /**
+ * SMS running time
+ */
+ public static final String SMS_RUNNING_TIME = "sms.running.time";
+
+
+ /**
+ * xecure
+ */
+ public static final String XECURE_TYPE = "xecure.type";
+ public static final String XECURE_CONFIG_PATH = "xecure.config.path";
+ public static final String XECURE_REMOTE_CERT = "xecure.remote.cert";
+
+ /**
+ * xecure2
+ */
+ public static final String XECURE2_CONFIG_PATH = "xecure2.config.path";
+ public static final String XECURE2_SM_IP = "xecure2.sm.ip";
+ public static final String XECURE2_SM_PORT = "xecure2.sm.port";
+
+
+ /**
+ * xecure3 20100901 JGY
+ */
+ public static final String XECURE3_CERT_STORE = "xecure3.cert.store";
+ public static final String XECURE3_SERVER_CERT = "xecure3.server.cert";
+ public static final String XECURE3_CLIENT_CERT = "xecure3.client.cert";
+ public static final String XECURE3_CERT_KEY = "xecure3.cert.key";
+ public static final String XECURE3_CERT_PASSWORD = "xecure3.cert.password";
+
+ /**
+ * xecure3 20210929 epb
+ */
+ public static final String XC3EPB_PASSWORD = "xc3epb.password";
+ public static final String XC3EPB_CONFIG_PATH = "xc3epb.config.path";
+
+ /**
+ * envelop
+ */
+ public static final String ENVELOP_SIGNCERT_PATH = "envelop.signcert.path";
+ public static final String ENVELOP_SIGNKEY_PATH = "envelop.signkey.path";
+ public static final String ENVELOP_PASSWORD = "envelop.password";
+
+ /**
+ * tcseed 20101213 JGY
+ */
+ public static final String TCSEED_KEY_STORE = "tcseed.key.store";
+
+ /**
+ * login client
+ */
+ public static final String LOGIN_SEND = "login.send";
+ public static final String LOGIN_RECV = "login.recv";
+ public static final String BIND_TYPE = "bind.type";
+ public static final String LL_FIELD_LENGTH_ALPHA = "ll.field.length.alpha";
+
+ /**
+ * inicis pg
+ */
+ public static final String INICIS_KEY_PATH = "inicis.key.path";
+ public static final String INICIS_KEY_PASS = "inicis.key.pass";
+
+ /**
+ * delimiter
+ */
+ public static final String DELIMITER = "delimiter";
+ /**
+ * append protocol
+ */
+ public static final String APPEND_HEAD = "append.head";
+ public static final String APPEND_TAIL = "append.tail";
+
+ /**
+ * block ip list
+ */
+ public static final String BLOCK_IP_LIST = "block.ip.list";
+
+ /**
+ * l4 skip ip list
+ */
+ public static final String L4_SKIP_IP_LIST = "l4.skip.ip.list";
+
+ public static final String IS_SINGLE_SESSION = "is.single.session";
+ public static final String SINGLE_PRIMARY_INST = "single.primary.inst";
+
+
+ public static final String DYNAMIC_OFFSET_PATTERN = "dynamic.offset.pattern";
+ public static final String DATA_ADD_RULE = "data.add.rule";
+ public static final String DATA_REMOVE_RULE = "data.remove.rule";
+
+ public static final String KEEP_ALIVE = "keep.alive";
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/config/MonitoringUtil.java b/src/main/java/com/eactive/eai/adapter/socket2/config/MonitoringUtil.java
new file mode 100644
index 0000000..611961e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/config/MonitoringUtil.java
@@ -0,0 +1,300 @@
+package com.eactive.eai.adapter.socket2.config;
+
+import com.eactive.eai.adapter.AdapterGroupVO;
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class MonitoringUtil {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+ private MonitoringUtil() {
+
+ }
+
+ public static String[][] adapterStatus(String adapterGroupName) throws Exception {
+ Vector list = new Vector<>();
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) manager.getSocketAdapterGroups();
+ AdapterManager gmanager = AdapterManager.getInstance();
+
+ if (existsAdapterGroup(adapterGroupName)) {
+ AdapterGroupVO gvo = gmanager.getAdapterGroupVO(adapterGroupName);
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+ for (Enumeration ee = adapters.elements(); ee.hasMoreElements();) {
+ String[] info = new String[12];
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ info[0] = adapterGroupName;
+ info[1] = adapter.getContext().getAdapterName();
+ info[2] = adapter.getContext().getDescription();
+ info[3] = adapter.getContext().getBoundUsage();
+ info[4] = String.valueOf(getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
+ info[5] = ""; // gvo.getRealTimeGroupName();
+ info[6] = "1"; // gvo.isRealTimeBzwkFlag() ? "1" : "0";
+ info[7] = adapter.getState().toString();
+ info[8] = gvo.getKesaUseYn();
+ info[9] = gvo.getTestMasterYn();
+ info[10] = gvo.getAdptrNickName();
+ info[11] = gvo.getCompanyCodeData();
+ list.add(info);
+ }
+ }
+
+ String[][] adapters = new String[list.size()][5];
+ for (int i = 0; i < list.size(); i++) {
+ adapters[i] = list.get(i);
+ }
+ return adapters;
+ }
+
+ public static String[][] adapterList1() throws Exception {
+ Vector list = new Vector<>();
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) manager.getSocketAdapterGroups();
+ AdapterManager gmanager = AdapterManager.getInstance();
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ if (!existsAdapterGroup(adapterGroupName)) {
+ continue;
+ }
+ AdapterGroupVO gvo = gmanager.getAdapterGroupVO(adapterGroupName);
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+ for (Enumeration ee = adapters.elements(); ee.hasMoreElements();) {
+ String[] info = new String[12];
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ info[0] = adapterGroupName;
+ info[1] = adapter.getContext().getAdapterName();
+ info[2] = adapter.getContext().getDescription();
+ info[3] = adapter.getContext().getBoundUsage();
+ info[4] = String.valueOf(getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
+ info[5] = ""; // gvo.getRealTimeGroupName();
+ info[6] = "1"; // gvo.isRealTimeBzwkFlag() ? "1" : "0";
+ info[7] = adapter.getState().toString();
+ info[8] = gvo.getKesaUseYn();
+ info[9] = gvo.getTestMasterYn();
+ info[10] = gvo.getAdptrNickName();
+ info[11] = gvo.getCompanyCodeData();
+ list.add(info);
+ }
+ }
+
+ String[][] adapters = new String[list.size()][5];
+ for (int i = 0; i < list.size(); i++) {
+ adapters[i] = list.get(i);
+ }
+ return adapters;
+ }
+
+ public static String[][] adapterList2() throws Exception {
+ Vector list = new Vector();
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) manager.getSocketAdapterGroups();
+// AdapterManager gmanager = AdapterManager.getInstance();
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ if (!existsAdapterGroup(adapterGroupName)) {
+ continue;
+ }
+// AdapterGroupVO gvo = gmanager.getAdapterGroupVO(adapterGroupName);
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+ for (Enumeration ee = adapters.elements(); ee.hasMoreElements();) {
+ String[] info = new String[11];
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ info[0] = adapterGroupName;
+ info[1] = adapter.getContext().getAdapterName();
+ info[2] = adapter.getContext().getDescription();
+ info[3] = String.valueOf(adapter.getContext().getMaxConnection());
+ info[4] = String.valueOf(adapter.getSessionPool().peekSize());
+ info[5] = String.valueOf(adapter.getMessageSend());
+ info[6] = String.valueOf(adapter.getMessageRecv());
+ info[7] = String.valueOf(adapter.getRecentErrorCount());
+ info[8] = String.valueOf(getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
+ info[9] = ""; // gvo.getRealTimeGroupName();
+ info[10] = "1"; // gvo.isRealTimeBzwkFlag() ? "1" : "0";
+ list.add(info);
+ }
+ }
+
+ String[][] adapters = new String[list.size()][7];
+ for (int i = 0; i < list.size(); i++) {
+ adapters[i] = list.get(i);
+ }
+ return adapters;
+ }
+
+ public static String[][] adapterInstList() throws Exception {
+ Vector list = new Vector();
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) manager.getSocketAdapterGroups();
+// AdapterManager gmanager = AdapterManager.getInstance();
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ if (!existsAdapterGroup(adapterGroupName)) {
+ continue;
+ }
+// AdapterGroupVO gvo = gmanager.getAdapterGroupVO(adapterGroupName);
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+ for (Enumeration ee = adapters.elements(); ee.hasMoreElements();) {
+ String[] info = new String[6];
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ info[0] = adapterGroupName;
+ info[1] = adapter.getContext().getAdapterName();
+ info[2] = adapter.getContext().getDescription();
+ info[3] = String.valueOf(adapter.getMessageSend());
+ info[4] = String.valueOf(adapter.getMessageRecv());
+ info[5] = String.valueOf(adapter.getRecentErrorCount());
+ list.add(info);
+ }
+ }
+
+ String[][] adapters = new String[list.size()][6];
+ for (int i = 0; i < list.size(); i++) {
+ adapters[i] = list.get(i);
+ }
+ return adapters;
+ }
+
+ public static String[][] adapterTraceLevel() throws Exception {
+ Vector list = new Vector();
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) manager.getSocketAdapterGroups();
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ if (!existsAdapterGroup(adapterGroupName)) {
+ continue;
+ }
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+ for (Enumeration ee = adapters.elements(); ee.hasMoreElements();) {
+ String[] info = new String[5];
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ info[0] = adapterGroupName;
+ info[1] = adapter.getContext().getAdapterName();
+ info[2] = adapter.getContext().getDescription();
+ info[3] = String.valueOf(getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
+ info[4] = String.valueOf(adapter.getContext().getTraceLevel());
+ list.add(info);
+ }
+ }
+
+ String[][] adapters = new String[list.size()][4];
+ for (int i = 0; i < list.size(); i++) {
+ adapters[i] = list.get(i);
+ }
+ return adapters;
+ }
+
+ public static String[] adapterError(String adapterGroupName, String adapterName) throws Exception {
+// StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterGroupName + "." + adapterName);
+ if (adapter == null)
+ return new String[0];
+
+ return adapter.getRecentErrors();
+ }
+
+ public static String[][] sessionList(String adapterGroupName) throws Exception {
+ Vector list = new Vector();
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) manager.getSocketAdapterGroups();
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+
+ if (adapters == null || !existsAdapterGroup(adapterGroupName)) {
+ return new String[0][14];
+ }
+
+ for (Enumeration ee = adapters.elements(); ee.hasMoreElements();) {
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ for (Iterator iter = adapter.getSessionPool().iterator(); iter.hasNext();) {
+ String[] info = new String[14];
+ IoSession session = (IoSession) iter.next();
+ info[0] = adapterGroupName;
+ info[1] = adapter.getContext().getAdapterName();
+ info[2] = adapter.getContext().getDescription();
+ info[3] = adapter.getContext().getBwkClsCd();
+ info[4] = adapter.getContext().getBoundUsage();
+ info[5] = adapter.getContext().getSocketType();
+ info[6] = adapter.getContext().getAckSupport();
+ info[7] = session.getLocalAddress().toString();
+ info[8] = session.getRemoteAddress().toString();
+ info[9] = String.valueOf(session.getWrittenMessages());
+ info[10] = String.valueOf(session.getReadMessages());
+ info[11] = getDateTime(session.getCreationTime());
+ info[12] = getDateTime(session.getLastIoTime());
+ info[13] = session.toString();
+ list.add(info);
+ }
+ }
+
+ String[][] sessions = new String[list.size()][13];
+ for (int i = 0; i < list.size(); i++) {
+ sessions[i] = list.get(i);
+ }
+ return sessions;
+ }
+
+ public static void adapterStart(String adapterGroupName, String adapterName) throws Exception {
+ SocketAdapterManager.getInstance().start(adapterGroupName, adapterName);
+ }
+
+ public static void adapterStop(String adapterGroupName, String adapterName) throws Exception {
+ SocketAdapterManager.getInstance().stop(adapterGroupName, adapterName);
+ }
+
+ public static void adapterChangeTraceLevel(String adapterGroupName, String adapterName, int traceLevel)
+ throws Exception {
+ ISocketAdapter adapter = SocketAdapterManager.getInstance().getSocketAdapter(adapterGroupName, adapterName);
+ if (adapter != null)
+ adapter.getContext().setTraceLevel(traceLevel);
+ }
+
+// public static void sessionClose(String adapterGroupName, String adapterName, String remoteAddress, String localAddress) throws Exception {
+// ISocketAdapter adapter = SocketAdapterManager.getInstance().getSocketAdapter(adapterGroupName, adapterName);
+// IoSession session = adapter.getSessionPool().find(remoteAddress, localAddress);
+// if (session != null)
+// session.close();
+// }
+
+ public static void sessionClose(String adapterGroupName, String sessionName) throws Exception {
+// Vector list = new Vector();
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) manager.getSocketAdapterGroups();
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+
+ for (Enumeration ee = adapters.elements(); ee.hasMoreElements();) {
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ for (Iterator iter = adapter.getSessionPool().iterator(); iter.hasNext();) {
+ IoSession session = (IoSession) iter.next();
+ if (sessionName.equals(session.toString())) {
+ session.close();
+ return;
+ }
+ }
+ }
+ }
+
+ private static boolean getAdapterStatus(String adapterGroupName, String adapterName) {
+ AdapterManager manager = AdapterManager.getInstance();
+ AdapterVO vo = manager.getAdapterVO(adapterGroupName, adapterName);
+ if (vo != null)
+ return vo.isStatus();
+ return false;
+ }
+
+ private static boolean existsAdapterGroup(String adapterGroupName) {
+ AdapterManager manager = AdapterManager.getInstance();
+ AdapterGroupVO gvo = manager.getAdapterGroupVO(adapterGroupName);
+ if (gvo != null)
+ return true;
+ return false;
+ }
+
+ private static String getDateTime(long time) {
+ Instant instant = Instant.ofEpochMilli(time);
+ ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
+ return dateFormat.format(zdt);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterContext.java b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterContext.java
new file mode 100644
index 0000000..245e677
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterContext.java
@@ -0,0 +1,1329 @@
+package com.eactive.eai.adapter.socket2.config;
+
+import java.io.Serializable;
+import java.util.Properties;
+import java.util.concurrent.Semaphore;
+
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.socket2.protocol.IRequestProcessor;
+
+
+/**
+* 1. 기능 : SocketAdapter의 구성정보 및 속성을 나타내는 Object Class
+* 2. 처리 개요 :
+* - 구성정보의 DEFAULT값을 갖고 있으며, 각 속성에 대한 getter/setter 기능을 제공한다.
+* 3. 주의사항
+* - 해당 Property의 기본속성값을 확인하여, 해당 Property의 속성지정을 생략시 어떤 값을 갖는지 확인하여야한다.
+**/
+
+public class SocketAdapterContext implements Serializable {
+ public static final String INBOUND_SOCKET = "INBOUND";
+ public static final String OUTBOUND_SOCKET = "OUTBOUND";
+ public static final String IOBOUND_SOCKET = "IOBOUND";
+
+ public static final String SERVER_SOCKET = "SERVER";
+ public static final String CLIENT_SOCKET = "CLIENT";
+ public static final String ADMIN_SOCKET = "ADMIN";
+
+ public static final String SYNC_MODE = "SYNC";
+ public static final String ASYNC_MODE = "ASYN";
+
+// public static final String ACKON_MODE = "AKON";
+
+ public static final String TRUE_FLAG = "Y";
+ public static final String FALSE_FLAG = "N";
+
+ /**
+ * trace level
+ */
+ public static final int TRACE_LEVEL_DEFAULT = 0; // WARNING, ERROR, FATAL인 경우 에러로깅
+ public static final int TRACE_LEVEL_INFO = 1; // INFO 수준의 LOGGING을 수행한다.
+ public static final int TRACE_LEVEL_DEBUG = 2; // DEBUG 수준의 송수신전문 및 에러 메인처리내용의 모든수준의 로깅을 수행한다.
+ public static final int TRACE_LEVEL_TRACE = 3; // TRACE 수준의 송수신전문 및 에러 메인처리내용의 모든수준의 로깅을 수행한다.
+
+ /**
+ * xecure type
+ */
+ public static final String XECURE_TYPE_BASIC = "BASIC";
+ public static final String XECURE_TYPE_FIXED = "FIXED";
+ public static final String XECURE_TYPE_WELCOME = "WELCOME";
+ public static final String XECURE_TYPE_ENVELOPE = "ENVELOPE"; // 전자봉투
+ public static final String XECURE_TYPE_FIXEDHEADER = "FIXEDHEADER";
+
+ /**
+ * Configuration properties
+ */
+ private String adapterGroupName = "AdapterGroup"; // SOCKET ADADAPTER GROUP NAME
+ private String adapterName = "Adapter"; // SOCKET ADAPTER 구성 이름
+
+ private String protocol = "FIXED_LENGTH_HEADER"; //FIXED_LENGTH_HEADER | CISCO | ADMIN | XECURE | CERT | HTTP
+ private String permanent = "Y"; // Permanent or Non-Permanent
+
+ private String boundUsage = IOBOUND_SOCKET; // INBOUND | OUTBOUND | IOBOUND
+ private String socketType = CLIENT_SOCKET; // SERVER | CLIENT
+
+
+ private String hostName = "localhost"; // BIND할 서버의 호스트명 또는 IP ADDRESS
+ private int portNumber = 0; // BIND할 서버의 PORT NUMBER
+
+ private String localHostName = ""; // Client Socket Type에 한하여 설정
+ private int localPortNumber = 0; // Client Socket Type으로 원격서버와 연결시 BIND할localPortNumber
+
+ private int connLimitPerIp = 0; // SERVER TYPE SOCKET의 경우 REMOTE의 특정 IP별 CONNECTION 수를 제한시키는 것
+ private int maxConnection = 0; // 원격시스템과 Socket Connection 최대허용 수
+ // Server Socket의 경우 - Server Listening port로 접속허용할 최대 수
+ // Client Socket의 경우 - Remote Host의 지정 포트로 연결할 최대 Connection 수
+ private Semaphore maxConnSemaphore = null;
+ private boolean bCloseExistingConnection = false; // maxConnection < 0 일 경우 이전 'YOUNG' connection을 끊고 새로운 connection을 맺는다.
+ // negative(-) 옵션을 준 상태에서 세션이 Full 상태 일때, 가장 오래 된 세션을 끊고 새로운 세션을 연결한다.
+ private boolean bCloseExistingConnectionPerIpLimit = false; // maxConnectionPerIp < 0 일 경우 이전 'OLDEST' connection을 끊고 새로운 connection을 맺는다.
+
+ private int maxThread = 10; // INBOUND의 경우한하여 의미가 있음.
+// private int maxThread = 1; // Worker Thread default 1로 조정, 2009.10.16
+ // Socket Adapter의 N개의 Connection에 대해 session을 연결할 최대 수 (실행 Thread Pool의 Session수)
+
+ private int timeout = 60; // Socket Read Timeout & Transaction Timeout 값 설정 (단위 : 초)
+
+ private int idleTimeout = 0; // 초단위
+
+ private String responseType = SYNC_MODE; // SYNC_MODE, ASYNC_MODE
+ private String socketReuse = TRUE_FLAG; // "Y" - Socket Connection reuse
+
+ /**
+ * client & non-perm & fixed_length_header & sync
+ * 일 경우 서버에서 응답을 주고 connection 을 끊는 경우 처리를 위하여
+ * 예) 데이콤
+ */
+ private String blocking = "N";
+
+ /**
+ * ll
+ */
+ private String llFieldType = "BIN"; // BIN(Binary), CHAR(Numeric Character), CISCO
+ private int llFieldLength = 2; // LL필드길이 2-unsigned short, 4 ~ 8 Numeric Char
+ private int llFieldOffset = 0; // LL 필드가 중간에 있을 경우 offset
+ private String llFieldInclude = FALSE_FLAG; // LL 필드 length 가 (header=ll) 을 포함하는가?
+ private String llOffsetExclude = FALSE_FLAG; // Offset을 포함하여 LL Length를 계산할 것인가?
+ private String llInclude = FALSE_FLAG; // LL 필드를 포함하여 F/W 에 던질 것인가?
+
+ private int llLenAdjust = 0; // 한은맘 헤더 길이 평문테스트 용
+
+ /**
+ * payload length
+ */
+ private int sendPayloadLength = 0;
+ private int recvPayloadLength = 0;
+
+ /**
+ * variable header length
+ */
+ private int sendHeaderLength = 0;
+ private int recvHeaderLength = 0;
+
+
+
+ private String ackSupport = FALSE_FLAG; // ACK송수신 여부 -- Client Type의 Socket에 적용되며, 서버는 Protocol에 의해 작동판단...
+ private String bwkClsCd = ""; // 업무구분코드
+
+ private String validationRule = "";
+
+ /**
+ * dataControlRule 금결원
+ */
+ private String dataControlRule = "";
+
+ private int traceLevel = TRACE_LEVEL_DEFAULT; // 추적관리 수준 - 0, 1, 2
+ private String description = ""; // Socket Adapter Configuration에 대한 용도설명
+
+ /**
+ * acl
+ */
+ private String aclList = "";
+
+ /**
+ * script (groovy | response message)
+ */
+ private String script = "";
+
+ /**
+ * polling
+ */
+ private String pollingUse = "N";
+ private String pollingRole = ""; // SENDER|RECEIVER
+ private String pollingOneway = "N"; // Y|N
+ private int pollingTimeout = 600;
+ private String pollingRequest = "HDRREQPOLL%d{MMddHHmmss}";
+ private String pollingRequestPattern = "(HDR)?(REQPOLL)([0-9]{10})";
+ private String pollingReplacement = "$1RESPOLL$3";
+ private String pollingResponsePattern = "(HDR)?(RESPOLL)([0-9]{10})";
+
+ /**
+ * init Message
+ */
+ private String initMsgUse = "N";
+ private String initMsgRole = ""; // SENDER|RECEIVER
+ private String initMsgRequest = "INITREQMSG%d{MMddHHmmss}";
+ private String initMsgRequestPattern = "(INIT)?(REQMSG)([0-9]{10})";
+ private String initMsgReplacement = "$1RESMSG$3";
+ private String initMsgResponsePattern = "(INIT)?(RESMSG)([0-9]{10})";
+
+ /**
+ * Security - SSL
+ */
+ private String sslUse = "N";
+ private String sslCertStore = ""; // SSL용 보안 인증서, TCSEED용 Key저장소
+ private String sslCertPassword = ""; // SSL용 인증서 암호
+
+ /**
+ * inisafe
+ */
+ private String inisafeConfigPath = "";
+ private String inisafeRelatedAdapterGroups = "";
+ private String inisafeStartMessage = "STARTED";
+ private String inisafeStopMessage = "STOPPED";
+
+ /**
+ * inisafe_payload
+ */
+ private String inisafeIdPassword = ""; // 은행코드(3) + ID(8) + Password(20)
+
+ /**
+ * SMS
+ */
+ private String smsRunningTime = "";
+
+ /**
+ * XC (XecureConnect)
+ */
+ private String xecureType = ""; // XC 보안 모듈 타입 (TYPEA, TYPEB, ..)
+ private String xecureConfigPath = ""; // XecureConnect 설정에 필요한 정보 (인증서정보, 세팅사항 등..)
+ private String xecurePassword = ""; // 개인키 추출을 위한 비밀번호 문자열
+ private String xecureRemoteCert = ""; // 전자봉투 방식 - remote cert file
+
+ /**
+ * Xecure2 Connect[Session Manager]
+ */
+ private String xecure2ConfigPath = ""; // example : "/fshome/greai/eaiadm/softforum/xc20/conf/cert.txt";
+ private String xecure2SmIp = "127.0.0.1";
+ private int xecure2SmPort = 9300;
+
+ /**
+ * Xecure3 Connect
+ */
+ private String xecure3CertStore = "/fshome/greai/eaiadm/softforum/xc30/certstore";
+ private String xecure3ServerCert = "/fshome/greai/eaiadm/softforum/xc30/cert/kb/SignCert.der";
+ private String xecure3CertKey = "/fshome/greai/eaiadm/softforum/xc30/cert/kb/signPri.key";
+ private String xecure3ClientCert = "/fshome/greai/eaiadm/softforum/xc30/cert/army/SignCert.der";
+ private String xecure3CertPassword = "qwer1234";
+
+ /**
+ * Xecure3 epb
+ */
+ private String xc3epbPassword = ""; // 개인키 추출을 위한 비밀번호 문자열
+ private String xc3epbConfigPath = ""; // XecureConnect3 설정에 필요한 정보 (인증서정보, 세팅사항 등..)
+
+ /**
+ * ENVELOP Connect[Session Manager]
+ */
+ private String envelopSigncertPath = ""; // example : "/fshome/greai/eaiadm/softforum/xc20/conf/signCert.der"
+ private String envelopSignkeyPath = ""; // example : "/fshome/greai/eaiadm/softforum/xc20/conf/signPri.key"
+ private String envelopPassword = ""; // example : "qwer1234";
+
+ /**
+ * login client
+ */
+ private String loginSend = "";
+ private String loginRecv = "";
+ private String bindType = "";
+ private int llFieldLengthAlpha = 0;
+
+ /**
+ * Security - TCSEED
+ */
+ private String tcseedKeyStore = ""; // TCSEED용 Key저장소
+
+ /**
+ * inisis
+ */
+ private String inicisKeyPath ="";
+ private String inicisKeyPass ="";
+
+ /**
+ * append protocol
+ */
+ private String appendHead ="";
+ private String appendTail ="";
+
+ /**
+ * block ip list
+ */
+ private String blockIpList ="";
+
+ /**
+ * l4 skip ip list
+ */
+ private String l4SkipIpList ="";
+ /**
+ * delimiter
+ */
+ private String delimiter ="";
+
+ /**
+ * IS_SINGLE_SESSION
+ */
+ private String singleSession = "N"; // Y : 기관 허용세션이 1인 경우
+
+ // 기관 허용세션이 1이면서 Active/Active 인스던스 2개 운영시 Primary 인스던스명 - 싱글어댑터 속성
+ private String primaryInstId = "";
+
+
+ private String dynamicOffsetPattern = "";
+ private String dataAddRule = "";
+ private String dataRemoveRule = "";
+
+ /**
+ * SO_KEEPALIVE
+ */
+ private String keepAlive = "N"; // Y : TCP KeepAlive option
+
+
+ /**
+ *
+ */
+ private AdapterVO adapterVO = null;
+ private IRequestProcessor requestProcessor = null;
+ private boolean started = true;
+
+
+
+ public SocketAdapterContext() {
+ }
+
+ public SocketAdapterContext(Properties prop) {
+ this.adapterGroupName = prop.getProperty("ADAPTER_GROUP_NAME", "").trim();
+ this.adapterName = prop.getProperty("ADAPTER_NAME", "").trim();
+ this.hostName = prop.getProperty("HOST_NAME", "").trim();
+ this.portNumber = Integer.parseInt(prop.getProperty("PORT_NUMBER", "").trim());
+ this.traceLevel = Integer.parseInt(prop.getProperty("TRACE_LEVEL", "2").trim());
+
+ this.socketType = prop.getProperty("SOCKET_TYPE", CLIENT_SOCKET).trim();
+ this.boundUsage = prop.getProperty("BOUND_USAGE", OUTBOUND_SOCKET).trim();
+ this.ackSupport = prop.getProperty("ACK_SUPPORT", FALSE_FLAG).trim();
+ this.protocol = prop.getProperty("PROTOCOL", "FIXED_LENGTH_HEADER").trim();
+ this.llFieldType = prop.getProperty("LL_FIELD_TYPE", "BIN").trim();
+ this.llFieldLength = Integer.parseInt(prop.getProperty("LL_FIELD_LENGTH", "2").trim());
+ this.llFieldOffset = Integer.parseInt(prop.getProperty("LL_FIELD_OFFSET", "0").trim());
+ this.llFieldInclude = prop.getProperty("LL_FIELD_INCLUDE", "N").trim();
+ this.llOffsetExclude = prop.getProperty("LL_OFFSET_EXCLUDE", "N").trim();
+ this.llInclude = prop.getProperty("LL_INCLUDE", "N").trim();
+ this.responseType = prop.getProperty("RESPONSE_TYPE", "SYNC").trim();
+ this.timeout = Integer.parseInt(prop.getProperty("TIMEOUT", "60").trim());
+ this.maxConnection = Integer.parseInt(prop.getProperty("MAX_CONNECTION", "1").trim());
+ this.maxConnSemaphore = new Semaphore(this.maxConnection > 0 ? this.maxConnection : -this.maxConnection);
+ this.permanent = prop.getProperty("PERMANENT", "Y").trim();
+ this.aclList = prop.getProperty("ACL_LSIT", "").trim();
+
+ this.recvHeaderLength = Integer.parseInt(prop.getProperty("RECV_HEADER_LENGTH", "0").trim());
+ this.sendHeaderLength = Integer.parseInt(prop.getProperty("SEND_HEADER_LENGTH", "0").trim());
+
+ this.smsRunningTime = prop.getProperty("SMS_RUNNING_TIME", "").trim();
+
+ this.pollingUse = prop.getProperty("POLLING_USE", "N").trim();
+
+ this.initMsgUse = prop.getProperty("INIT_MSG_USE", "N").trim();
+
+ this.singleSession = prop.getProperty("IS_SINGLE_SESSION", "N").trim();
+
+ this.keepAlive = prop.getProperty("KEEP_ALIVE", "N").trim();
+
+ }
+
+ public String getAdapterGroupName() {
+ return adapterGroupName;
+ }
+
+ public void setAdapterGroupName(String adapterGroupName) {
+ this.adapterGroupName = adapterGroupName;
+ }
+
+ public String getAdapterName() {
+ return adapterName;
+ }
+
+ public void setAdapterName(String adapterName) {
+ this.adapterName = adapterName;
+ }
+
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public String getProtocol() {
+ return this.protocol;
+ }
+
+ public int getConnLimitPerIp() {
+ return connLimitPerIp;
+ }
+
+ public void setConnLimitPerIp(int connLimitPerIp) {
+ if (connLimitPerIp < 0) {
+ setCloseExistingConnectionPerIpLimit(true);
+ this.connLimitPerIp = -connLimitPerIp;
+ } else {
+ this.connLimitPerIp = connLimitPerIp;
+ }
+ }
+
+ public boolean getCloseExistingConnectionPerIpLimit() {
+ return this.bCloseExistingConnectionPerIpLimit;
+ }
+
+ public void setCloseExistingConnectionPerIpLimit(boolean bCloseExistingConnectionPerIpLimit) {
+ this.bCloseExistingConnectionPerIpLimit = bCloseExistingConnectionPerIpLimit;
+ }
+
+ public String getBwkClsCd() {
+ return bwkClsCd;
+ }
+
+ public void setBwkClsCd(String bizCode) {
+ this.bwkClsCd = bizCode;
+ }
+
+ public String getAckSupport() {
+ return ackSupport;
+ }
+
+ public void setAckSupport(String ackSupport) {
+ this.ackSupport = ackSupport;
+ }
+
+ public String getBoundUsage() {
+ return boundUsage;
+ }
+
+ public void setBoundUsage(String boundUsage) {
+ this.boundUsage = boundUsage;
+ }
+
+ public void setPermanent(String permanent) {
+ this.permanent = permanent;
+ }
+
+ public String getPermanent() {
+ return permanent;
+ }
+
+ public boolean isPermanent() {
+ return "Y".equals(permanent);
+ }
+
+ public void setPollingUse(String pollingUse) {
+ this.pollingUse = pollingUse;
+ }
+
+ public String getPollingUse() {
+ return pollingUse;
+ }
+
+ public boolean isPollingUse() {
+ return "Y".equals(pollingUse);
+ }
+
+ public void setPollingRole(String pollingRole) {
+ this.pollingRole = pollingRole;
+ }
+
+ public String getPollingRole() {
+ return pollingRole;
+ }
+
+ public boolean isPollingSender() {
+ if ("".equals(pollingRole)) {
+ return isClient();
+ } else {
+ return "SENDER".equals(pollingRole);
+ }
+ }
+
+ public boolean isPollingReceiver() {
+ return !isPollingSender();
+ }
+
+ public String getPollingOneway() {
+ return pollingOneway;
+ }
+
+ public void setPollingOneway(String oneway) {
+ this.pollingOneway = oneway;
+ }
+
+ public boolean isPollingOneway() {
+ return "Y".equals(pollingOneway);
+ }
+
+ public void setPollingTimeout(int pollingTimeout) {
+ this.pollingTimeout = pollingTimeout;
+ }
+
+ public int getPollingTimeout() {
+ return pollingTimeout;
+ }
+
+
+ public void setPollingRequest(String pollingRequest) {
+ this.pollingRequest = pollingRequest;
+ }
+
+ public String getPollingRequest() {
+ return pollingRequest;
+ }
+
+ public void setPollingRequestPattern(String pollingRequestPattern) {
+ this.pollingRequestPattern = pollingRequestPattern;
+ }
+
+ public String getPollingRequestPattern() {
+ return pollingRequestPattern;
+ }
+
+ public void setPollingResponsePattern(String pollingResponsePattern) {
+ this.pollingResponsePattern = pollingResponsePattern;
+ }
+
+ public String getPollingResponsePattern() {
+ return pollingResponsePattern;
+ }
+
+ public void setPollingReplacement(String pollingReplacement) {
+ this.pollingReplacement = pollingReplacement;
+ }
+
+ public String getPollingReplacement() {
+ return pollingReplacement;
+ }
+
+//KSH
+ public void setInitMsgUse(String initMsgUse) {
+ this.initMsgUse = initMsgUse;
+ }
+
+ public String getInitMsgUse() {
+ return initMsgUse;
+ }
+
+ public boolean isInitMsgUse() {
+ return "Y".equals(initMsgUse);
+ }
+
+ public void setInitMsgRole(String initMsgRole) {
+ this.initMsgRole = initMsgRole;
+ }
+
+ public String getInitMsgRole() {
+ return initMsgRole;
+ }
+
+ public boolean isInitMsgSender() {
+ if ("".equals(initMsgRole)) {
+ return isClient();
+ } else {
+ return "SENDER".equals(initMsgRole);
+ }
+ }
+
+ public boolean isInitMsgReceiver() {
+ return !isInitMsgSender();
+ }
+
+ public void setInitMsgRequest(String initMsgRequest) {
+ this.initMsgRequest = initMsgRequest;
+ }
+
+ public String getInitMsgRequest() {
+ return initMsgRequest;
+ }
+
+ public void setInitMsgRequestPattern(String initMsgRequestPattern) {
+ this.initMsgRequestPattern = initMsgRequestPattern;
+ }
+
+ public String getInitMsgRequestPattern() {
+ return initMsgRequestPattern;
+ }
+
+ public void setInitMsgResponsePattern(String initMsgResponsePattern) {
+ this.initMsgResponsePattern = initMsgResponsePattern;
+ }
+
+ public String getInitMsgResponsePattern() {
+ return initMsgResponsePattern;
+ }
+
+ public void setInitMsgReplacement(String initMsgReplacement) {
+ this.initMsgReplacement = initMsgReplacement;
+ }
+
+ public String getInitMsgReplacement() {
+ return initMsgReplacement;
+ }
+
+//-----------------------------
+
+ public String getValidationRule() {
+ return validationRule;
+ }
+
+ public void setValidationRule(String validationRule) {
+ this.validationRule = validationRule;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getAclList() {
+ return aclList;
+ }
+
+ public void setAclList(String aclList) {
+ this.aclList = aclList;
+ }
+
+ public String getScript() {
+ return script;
+ }
+
+ public void setScript(String script) {
+ this.script = script;
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
+ }
+
+ /**
+ * ll field
+ */
+ public String getLlFieldType() {
+ return llFieldType;
+ }
+
+ public void setLlFieldType(String llFieldType) {
+ this.llFieldType = llFieldType;
+ }
+
+ public int getLlFieldOffset() {
+ return llFieldOffset;
+ }
+
+ public void setLlFieldOffset(int llFieldOffset) {
+ this.llFieldOffset = llFieldOffset;
+ }
+
+
+ public int getLlLenAdjust() {
+ return llLenAdjust;
+ }
+
+ public void setLlLenAdjust(int llLenAdjust) {
+ this.llLenAdjust = llLenAdjust;
+ }
+
+ public int getLlFieldLength() {
+ return llFieldLength;
+ }
+
+ public void setLlFieldLength(int llFieldLength) {
+ this.llFieldLength = llFieldLength;
+ }
+
+ public String getLlFieldInclude() {
+ return llFieldInclude;
+ }
+
+ public void setLlFieldInclude(String llFieldInclude) {
+ this.llFieldInclude = llFieldInclude;
+ }
+
+ public String getLlOffsetExclude() {
+ return llOffsetExclude;
+ }
+
+ public void setLlOffsetExclude(String llOffsetExclude) {
+ this.llOffsetExclude = llOffsetExclude;
+ }
+
+ public String getLlInclude() {
+ return llInclude;
+ }
+
+ public void setLlInclude(String llInclude) {
+ this.llInclude = llInclude;
+ }
+
+ /**
+ * payload length
+ */
+ public int getSendPayloadLength() {
+ return sendPayloadLength;
+ }
+
+ public void setSendPayloadLength(int sendPayloadLength) {
+ this.sendPayloadLength = sendPayloadLength;
+ }
+
+ public int getRecvPayloadLength() {
+ return recvPayloadLength;
+ }
+
+ public void setRecvPayloadLength(int recvPayloadLength) {
+ this.recvPayloadLength = recvPayloadLength;
+ }
+
+ /**
+ * ssl
+ */
+ public String getSslUse() {
+ return sslUse;
+ }
+
+ public void setSslUse(String sslUse) {
+ this.sslUse = sslUse;
+ }
+
+ public String getSslCertStore() {
+ return sslCertStore;
+ }
+
+ public void setSslCertStore(String sslCertStore) {
+ this.sslCertStore = sslCertStore;
+ }
+
+ public String getSslCertPassword() {
+ return sslCertPassword;
+ }
+
+ public void setSslCertPassword(String sslCertPassword) {
+ this.sslCertPassword = sslCertPassword;
+ }
+
+ public String getLocalHostName() {
+ return localHostName;
+ }
+
+ public void setLocalHostName(String localHostName) {
+ this.localHostName = localHostName;
+ }
+
+ public int getLocalPortNumber() {
+ return localPortNumber;
+ }
+
+ public void setLocalPortNumber(int localPortNumber) {
+ this.localPortNumber = localPortNumber;
+ }
+
+ public int getMaxConnection() {
+ return maxConnection;
+ }
+
+ public void setMaxConnection(int maxConnection) {
+ if (maxConnection < 0) {
+ setCloseExistingConnection(true);
+ this.maxConnection = -maxConnection;
+ } else {
+ this.maxConnection = maxConnection;
+ }
+
+ this.maxConnSemaphore = new Semaphore(this.maxConnection);
+ }
+
+ public boolean getCloseExistingConnection() {
+ return this.bCloseExistingConnection;
+ }
+
+ public void setCloseExistingConnection(boolean bCloseExistingConnection) {
+ this.bCloseExistingConnection = bCloseExistingConnection;
+ }
+
+ public Semaphore getMaxConnSemaphore() {
+ return maxConnSemaphore;
+ }
+
+ public int getMaxThread() {
+ return maxThread;
+ }
+
+ public void setMaxThread(int maxThread) {
+ this.maxThread = maxThread;
+ }
+
+ public int getPortNumber() {
+ return portNumber;
+ }
+
+ public void setPortNumber(int portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public int getIdleTimeout() {
+ return idleTimeout;
+ }
+
+ public void setIdleTimeout(int idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ }
+
+ public boolean isAckProtocol() {
+ return this.ackSupport.equals(TRUE_FLAG);
+ }
+
+ public void setResponseType(String responseType) {
+ this.responseType = responseType;
+ }
+
+ public String getResponseType() {
+ return responseType;
+ }
+
+ public boolean isSync() {
+ return this.responseType.equals(SYNC_MODE);
+ }
+
+ public void setSocketReuse(String socketReuse) {
+ this.socketReuse = socketReuse;
+ }
+
+ public String getSocketReuse() {
+ return socketReuse;
+ }
+
+ public boolean isSocketReuse() {
+ return socketReuse.equals(TRUE_FLAG);
+ }
+
+ public String getSocketType() {
+ return socketType;
+ }
+
+ public void setSocketType(String socketType) {
+ this.socketType = socketType;
+ }
+
+ public boolean isClient() {
+ return CLIENT_SOCKET.equals(socketType);
+ }
+
+ public boolean isServer() {
+ return SERVER_SOCKET.equals(socketType);
+ }
+
+ public String getBlocking() {
+ return blocking;
+ }
+
+ public void setBlocking(String blocking) {
+ this.blocking = blocking;
+ }
+
+ public boolean isBlocking() {
+ return "Y".equals(blocking);
+ }
+
+ public int getTraceLevel() {
+ return traceLevel;
+ }
+
+ public void setTraceLevel(int traceLevel) {
+ this.traceLevel = traceLevel;
+ }
+
+ /**
+ * inisafe protocol related
+ */
+ public String getInisafeConfigPath() {
+ return inisafeConfigPath;
+ }
+
+ public void setInisafeConfigPath(String inisafeConfigPath) {
+ this.inisafeConfigPath = inisafeConfigPath;
+ }
+
+ public String getInisafeRelatedAdapterGroups() {
+ return inisafeRelatedAdapterGroups;
+ }
+
+ public void setInisafeRelatedAdapterGroups(String inisafeRelatedAdapterGroups) {
+ this.inisafeRelatedAdapterGroups = inisafeRelatedAdapterGroups;
+ }
+
+ public String getInisafeStartMessage() {
+ return inisafeStartMessage;
+ }
+
+ public void setInisafeStartMessage(String inisafeStartMessage) {
+ this.inisafeStartMessage = inisafeStartMessage;
+ }
+
+ public String getInisafeStopMessage() {
+ return inisafeStopMessage;
+ }
+
+ public void setInisafeStopMessage(String inisafeStopMessage) {
+ this.inisafeStopMessage = inisafeStopMessage;
+ }
+
+ public IRequestProcessor getRequestProcessor() {
+ return requestProcessor;
+ }
+
+ public void setRequestProcessor(IRequestProcessor requestProcessor) {
+ this.requestProcessor = requestProcessor;
+ }
+
+ public void setAdapterVO(AdapterVO adapterVO) {
+ this.adapterVO = adapterVO;
+ }
+
+ public AdapterVO getAdapterVO() {
+ return adapterVO;
+ }
+
+ public void setStarted(boolean on) {
+ this.started = on;
+ }
+
+ public boolean isStarted() {
+ return this.started;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append( this.adapterName ).append( " [Adapter의 등록정보입니다. : " );
+ sb.append("adapter.group.name=").append( this.adapterGroupName );
+ sb.append(", bound.usage=").append( this.boundUsage );
+ sb.append(", socket.type=").append( this.socketType );
+ sb.append(", host.name=").append( this.hostName );
+ sb.append(", port.number=").append( this.portNumber);
+ sb.append(", local.host.name=").append( this.localHostName );
+ sb.append(", local.port.number=").append( this.localPortNumber );
+ if ( this.connLimitPerIp > 0 ) {
+ sb.append(", connection.limit.per.ip=").append( this.connLimitPerIp );
+ } else {
+ sb.append(", connection.limit.per.ip=0(UNLIMITED)" );
+ }
+
+ if ( this.maxConnection > 0 ) {
+ sb.append(", max.connection=").append( this.maxConnection );
+ } else {
+ sb.append(", max.connection=0 (UNLIMITED)" );
+ }
+
+ sb.append(", max.thread=").append( this.maxThread );
+ sb.append(", timeout=").append( this.timeout );
+ sb.append(", response.type=").append( this.responseType );
+ sb.append(", socket.reuse=").append( this.socketReuse );
+ sb.append(", ll.field.type=").append( this.llFieldType );
+ sb.append(", ll.field.offset=").append( this.llFieldOffset );
+ sb.append(", ll.field.length=").append( this.llFieldLength );
+ sb.append(", ll.field.include=").append( this.llFieldInclude );
+ sb.append(", ll.include=").append( this.llInclude );
+ sb.append(", variable.head.length=").append( this.sendHeaderLength );
+ sb.append(", payload.length=").append( this.sendPayloadLength );
+ sb.append(", ack.support=").append( this.ackSupport );
+ sb.append(", business.work.class.code=").append( this.bwkClsCd );
+
+ sb.append(", trace.level=");
+ if ( this.traceLevel == 2 ) {
+ sb.append( this.traceLevel ).append("(DEBUG)");
+ } else if ( this.traceLevel == 1 ) {
+ sb.append( this.traceLevel ).append("(INFO)");
+ } else {
+ sb.append( this.traceLevel ).append("(ERROR)");
+ }
+
+ sb.append(", description=").append(this.description);
+
+ if ("XECURE".equals(this.protocol)) {
+ sb.append(", xecure.type=").append(this.xecureType);
+ //sb.append(", xecure.tmode=").append(this.xecureTmode);
+ //sb.append(", xecure.encode.mode=").append(this.xecureEncodeMode);
+ sb.append(", xecure.config.path=").append(this.xecureConfigPath);
+ sb.append(", xecure.password=").append(this.xecurePassword);
+ }
+
+ if ("XECURE2".equals(this.protocol)) {
+ sb.append(", xecure2.config.path=").append(this.xecure2ConfigPath);
+ sb.append(", xecure2.sm.ip=").append(this.xecure2SmIp);
+ sb.append(", xecure2.sm.port=").append( String.valueOf(this.xecure2SmPort) );
+ }
+
+ sb.append("]");
+
+ return sb.toString();
+ }
+
+ /**
+ * SMS
+ */
+ public String getSmsRunningTime() {
+ return smsRunningTime;
+ }
+
+ public void setSmsRunningTime(String smsRunningTime) {
+ this.smsRunningTime = smsRunningTime;
+ }
+
+ /**
+ * xecure protocol related
+ */
+ public String getXecureType() {
+ return xecureType;
+ }
+
+ public void setXecureType(String xecureType) {
+ this.xecureType = xecureType;
+ }
+
+ public String getXecureConfigPath() {
+ return xecureConfigPath;
+ }
+
+ public void setXecureConfigPath(String xecureConfigPath) {
+ this.xecureConfigPath = xecureConfigPath;
+ }
+
+ public String getXecureRemoteCert() {
+ return xecureRemoteCert;
+ }
+
+ public void setXecureRemoteCert(String xecureRemoteCert) {
+ this.xecureRemoteCert = xecureRemoteCert;
+ }
+
+ /**
+ * xecure2 protocol related
+ */
+ public String getXecure2ConfigPath() {
+ return xecure2ConfigPath;
+ }
+
+ public void setXecure2ConfigPath(String xecure2ConfigPath) {
+ this.xecure2ConfigPath = xecure2ConfigPath;
+ }
+
+ public String getXecure2SmIp() {
+ return xecure2SmIp;
+ }
+
+ public void setXecure2SmIp(String xecure2SmIp) {
+ this.xecure2SmIp = xecure2SmIp;
+ }
+
+ public int getXecure2SmPort() {
+ return xecure2SmPort;
+ }
+
+ public void setXecure2SmPort(int xecure2SmPort) {
+ this.xecure2SmPort = xecure2SmPort;
+ }
+
+ /**
+ * xecure2 Envelop protocol related
+ */
+ public String getEnvelopPassword() {
+ return envelopPassword;
+ }
+
+ public void setEnvelopPassword(String envelopPassword) {
+ this.envelopPassword = envelopPassword;
+ }
+
+ public String getEnvelopSigncertPath() {
+ return envelopSigncertPath;
+ }
+
+ public void setEnvelopSigncertPath(String envelopSigncertPath) {
+ this.envelopSigncertPath = envelopSigncertPath;
+ }
+
+ public String getEnvelopSignkeyPath() {
+ return envelopSignkeyPath;
+ }
+
+ public void setEnvelopSignkeyPath(String envelopSignkeyPath) {
+ this.envelopSignkeyPath = envelopSignkeyPath;
+ }
+
+ /**
+ * xecure3 protocol related 20100901 JGY
+ */
+ public String getXecure3CertStore() {
+ return xecure3CertStore;
+ }
+
+ public void setXecure3CertStore(String xecure3CertStore) {
+ this.xecure3CertStore = xecure3CertStore;
+ }
+
+ public String getXecure3ServerCert() {
+ return xecure3ServerCert;
+ }
+
+ public void setXecure3ServerCert(String xecure3ServerCert) {
+ this.xecure3ServerCert = xecure3ServerCert;
+ }
+
+ public String getXecure3ClientCert() {
+ return xecure3ClientCert;
+ }
+
+ public void setXecure3ClientCert(String xecure3ClientCert) {
+ this.xecure3ClientCert = xecure3ClientCert;
+ }
+
+ public String getXecure3CertKey() {
+ return xecure3CertKey;
+ }
+
+ public void setXecure3CertKey(String xecure3CertKey) {
+ this.xecure3CertKey = xecure3CertKey;
+ }
+
+ public String getXecure3CertPassword() {
+ return xecure3CertPassword;
+ }
+
+ public void setXecure3CertPassword(String xecure3CertPassword) {
+ this.xecure3CertPassword = xecure3CertPassword;
+ }
+ /**
+ * xecureconnect3 epb
+ */
+ public String getXc3epbPassword() {
+ return xc3epbPassword;
+ }
+
+ public void setXc3epbPassword(String xc3epbPassword) {
+ this.xc3epbPassword = xc3epbPassword;
+ }
+
+ public String getXc3epbConfigPath() {
+ return xc3epbConfigPath;
+ }
+
+ public void setXc3epbConfigPath(String xc3epbConfigPath) {
+ this.xc3epbConfigPath = xc3epbConfigPath;
+ }
+
+ /**
+ * inisafe_payload protocol related 20100515 JGY
+ */
+ public String getInisafeIdPassword() {
+ return inisafeIdPassword;
+ }
+
+ public void setInisafeIdPassword(String inisafeIdPassword) {
+ this.inisafeIdPassword = inisafeIdPassword;
+ }
+
+ /**
+ * TCSEED protocol related 20101213 JGY
+ */
+ public String getTcseedKeyStore() {
+ return tcseedKeyStore;
+ }
+
+ public void setTcseedKeyStore(String tcseedKeyStore) {
+ this.tcseedKeyStore = tcseedKeyStore;
+ }
+
+ /**
+ * variable header protocol related 20121030 KwonSeHwan
+ */
+
+ public int getRecvHeaderLength() {
+ return recvHeaderLength;
+ }
+
+ public void setRecvHeaderLength(int recvHeaderLength) {
+ this.recvHeaderLength = recvHeaderLength;
+ }
+
+ public int getSendHeaderLength() {
+ return sendHeaderLength;
+ }
+
+ public void setSendHeaderLength(int sendHeaderLength) {
+ this.sendHeaderLength = sendHeaderLength;
+ }
+
+ public String getSingleSession() {
+ return singleSession;
+ }
+
+ public void setSingleSession(String singleSession) {
+ this.singleSession = singleSession;
+ }
+
+ public String getBlockIpList() {
+ return blockIpList;
+ }
+
+ public void setBlockIpList(String blockIpList) {
+ this.blockIpList = blockIpList;
+ }
+
+ public String getL4SkipIpList() {
+ return l4SkipIpList;
+ }
+
+ public void setL4SkipIpList(String l4SkipIpList) {
+ this.l4SkipIpList = l4SkipIpList;
+ }
+
+ public String getDelimiter() {
+ return delimiter;
+ }
+
+ public void setDelimiter(String delimiter) {
+ this.delimiter = delimiter;
+ }
+
+ public String getLoginSend() {
+ return loginSend;
+ }
+
+ public void setLoginSend(String loginSend) {
+ this.loginSend = loginSend;
+ }
+
+ public String getLoginRecv() {
+ return loginRecv;
+ }
+
+ public void setLoginRecv(String loginRecv) {
+ this.loginRecv = loginRecv;
+ }
+
+ public String getBindType() {
+ return bindType;
+ }
+
+ public void setBindType(String bindType) {
+ this.bindType = bindType;
+ }
+
+ public int getLlFieldLengthAlpha() {
+ return llFieldLengthAlpha;
+ }
+
+ public void setLlFieldLengthAlpha(int llFieldLengthAlpha) {
+ this.llFieldLengthAlpha = llFieldLengthAlpha;
+ }
+
+ public String getInicisKeyPath() {
+ return inicisKeyPath;
+ }
+
+ public void setInicisKeyPath(String inicisKeyPath) {
+ this.inicisKeyPath = inicisKeyPath;
+ }
+
+ public String getInicisKeyPass() {
+ return inicisKeyPass;
+ }
+
+ public void setInicisKeyPass(String inicisKeyPass) {
+ this.inicisKeyPass = inicisKeyPass;
+ }
+
+ public String getAppendHead() {
+ return appendHead;
+ }
+
+ public void setAppendHead(String appendHead) {
+ this.appendHead = appendHead;
+ }
+
+ public String getAppendTail() {
+ return appendTail;
+ }
+
+ public void setAppendTail(String appendTail) {
+ this.appendTail = appendTail;
+ }
+
+ public String getDataControlRule() {
+ return dataControlRule;
+ }
+
+ public void setDataControlRule(String dataControlRule) {
+ this.dataControlRule = dataControlRule;
+ }
+
+ // for 싱글어댑터
+ public String getPrimaryInstId() {
+ return primaryInstId;
+ }
+
+ // for 싱글어댑터
+ public void setPrimaryInstId(String primaryInstId) {
+ this.primaryInstId = primaryInstId;
+ }
+
+ public String getDynamicOffsetPattern() {
+ return dynamicOffsetPattern;
+ }
+
+ public void setDynamicOffsetPattern(String dynamicOffsetPattern) {
+ this.dynamicOffsetPattern = dynamicOffsetPattern;
+ }
+
+ public String getDataAddRule() {
+ return dataAddRule;
+ }
+
+ public void setDataAddRule(String dataAddRule) {
+ this.dataAddRule = dataAddRule;
+ }
+
+ public String getDataRemoveRule() {
+ return dataRemoveRule;
+ }
+
+ public void setDataRemoveRule(String dataRemoveRule) {
+ this.dataRemoveRule = dataRemoveRule;
+ }
+
+ public void setKeepAlive(String keepAlive) {
+ this.keepAlive = keepAlive;
+ }
+
+ public String getKeepAlive() {
+ return keepAlive;
+ }
+
+ public boolean isKeepAlive() {
+ return "Y".equals(keepAlive);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterFactory.java
new file mode 100644
index 0000000..d09855f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterFactory.java
@@ -0,0 +1,1305 @@
+package com.eactive.eai.adapter.socket2.config;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.admin.AdminServer;
+import com.eactive.eai.adapter.socket2.protocol.append.AppendClient;
+import com.eactive.eai.adapter.socket2.protocol.append.AppendServer;
+import com.eactive.eai.adapter.socket2.protocol.cert.CertClient;
+import com.eactive.eai.adapter.socket2.protocol.cert.CertServer;
+import com.eactive.eai.adapter.socket2.protocol.cisco.CiscoClient;
+import com.eactive.eai.adapter.socket2.protocol.cisco.CiscoServer;
+import com.eactive.eai.adapter.socket2.protocol.delimiter.DelimiterClient;
+import com.eactive.eai.adapter.socket2.protocol.delimiter.DelimiterServer;
+import com.eactive.eai.adapter.socket2.protocol.dynamicoffset.DynamicOffsetClient;
+import com.eactive.eai.adapter.socket2.protocol.dynamicoffset.DynamicOffsetServer;
+import com.eactive.eai.adapter.socket2.protocol.echo.EchoClient;
+import com.eactive.eai.adapter.socket2.protocol.echo.EchoServer;
+import com.eactive.eai.adapter.socket2.protocol.envelop.EnvelopClient;
+import com.eactive.eai.adapter.socket2.protocol.envelop.EnvelopServer;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.FixedHeaderClient;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.FixedHeaderServer;
+import com.eactive.eai.adapter.socket2.protocol.fixedpayload.FixedPayloadClient;
+import com.eactive.eai.adapter.socket2.protocol.fixedpayload.FixedPayloadServer;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServer;
+import com.eactive.eai.adapter.socket2.protocol.inicis.InicisClient;
+import com.eactive.eai.adapter.socket2.protocol.inicis.InicisServer;
+import com.eactive.eai.adapter.socket2.protocol.inisafe.InisafeClient;
+import com.eactive.eai.adapter.socket2.protocol.inisafe.InisafeServer;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.Inisafe2020Client;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.Inisafe2020Server;
+import com.eactive.eai.adapter.socket2.protocol.inisafenatn.InisafeNatnPayloadClient;
+import com.eactive.eai.adapter.socket2.protocol.inisafenatn.InisafeNatnPayloadServer;
+import com.eactive.eai.adapter.socket2.protocol.inisafepayload.InisafePayloadClient;
+import com.eactive.eai.adapter.socket2.protocol.inisafepayload.InisafePayloadServer;
+import com.eactive.eai.adapter.socket2.protocol.law.LawClient;
+import com.eactive.eai.adapter.socket2.protocol.law.LawServer;
+import com.eactive.eai.adapter.socket2.protocol.login.BindClient;
+import com.eactive.eai.adapter.socket2.protocol.login.LazyClient;
+import com.eactive.eai.adapter.socket2.protocol.login.LoginClient;
+import com.eactive.eai.adapter.socket2.protocol.proxy.ProxyServer;
+import com.eactive.eai.adapter.socket2.protocol.tcseed.TcseedClient;
+import com.eactive.eai.adapter.socket2.protocol.tcseed.TcseedServer;
+import com.eactive.eai.adapter.socket2.protocol.udp.UdpClient;
+import com.eactive.eai.adapter.socket2.protocol.udp.UdpServer;
+import com.eactive.eai.adapter.socket2.protocol.variableheader.VariableHeaderClient;
+import com.eactive.eai.adapter.socket2.protocol.variableheader.VariableHeaderServer;
+import com.eactive.eai.adapter.socket2.protocol.xc3epb.Xc3EpbClient;
+import com.eactive.eai.adapter.socket2.protocol.xc3epb.Xc3EpbServer;
+import com.eactive.eai.adapter.socket2.protocol.xecure.XecureClient;
+import com.eactive.eai.adapter.socket2.protocol.xecure.XecureServer;
+import com.eactive.eai.adapter.socket2.protocol.xecure2.Xecure2Client;
+import com.eactive.eai.adapter.socket2.protocol.xecure2.Xecure2Server;
+import com.eactive.eai.adapter.socket2.protocol.xecure3.Xecure3Client;
+import com.eactive.eai.adapter.socket2.protocol.xecure3.Xecure3Server;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.NullControl;
+
+import java.util.Properties;
+
+public class SocketAdapterFactory {
+ private static Logger logger = SocketLoggerManager.getInstance().getLogger();
+// private static Logger errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ private enum SocketType {
+ SERVER, CLIENT, ADMIN, UNKNOWN;
+
+ public static SocketType getValue(String value) {
+ try {
+ return valueOf(value.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+ }
+
+ private enum Protocol {
+ ADMIN,
+ CERT,
+ CISCO,
+ ECHO,
+ EGSEED,
+ ENVELOP,
+ FIXED_LENGTH_HEADER,
+ FIXED_LENGTH_PAYLOAD,
+ VARIABLE_LENGTH_HEADER,
+ INISAFE,
+ INISAFE_2020,
+ INISAFE_NATN,
+ INISAFE_PAYLOAD,
+ HTTP,
+ PROXY,
+ TCSEED,
+ UDP_FIXED_LENGTH_HEADER,
+ UDP_FIXED_LENGTH_PAYLOAD,
+ XECURE,
+ XECURE2,
+ XECURE3,
+ LOGIN,
+ LAZY,
+ BIND,
+ LAW,
+ DELIMITER,
+ INICIS,
+ APPEND,
+ XC3EPB,
+ DYNAMIC_OFFSET,
+ UNKNOWN;
+
+ public static Protocol getValue(String value) {
+ try {
+ return valueOf(value.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+ }
+
+// private static boolean isDrMode = false;
+// static {
+// if("Y".equals(System.getProperty(Keys.DR_MODE, "N").toUpperCase())) {
+// isDrMode = true;
+// }
+// }
+
+ public SocketAdapterFactory() {
+ super();
+ }
+
+ public static ISocketAdapter createSocketAdapter(SocketAdapterContext context) throws EAIException {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | create socket adapter ... ");
+ }
+
+ try {
+// String adapterGroupName = context.getAdapterGroupName();
+// String adapterName = context.getAdapterName();
+
+ ISocketAdapter adapter = null;
+
+ switch(SocketType.getValue(context.getSocketType())) {
+ case ADMIN:
+ if(Protocol.getValue(context.getProtocol()) == Protocol.ADMIN) {
+ context.setSocketType("SERVER");
+ }
+ else {
+ throw new EAIException("unknown ADMIN protocol : " + context.getProtocol());
+ }
+ break;
+ case SERVER:
+ switch(Protocol.getValue(context.getProtocol())) {
+ case ADMIN:
+ adapter = new AdminServer(context);
+ break;
+ case CERT:
+ adapter = new CertServer(context);
+ break;
+ case CISCO:
+ if (Env.isWindows()) { // for test
+ adapter = new CiscoServer(context);
+ break;
+ } else {
+ throw new EAIException(context.getAdapterName() + " | 'CISCO' Protocol does not support 'SERVER' socket type.");
+ }
+ case ECHO:
+ adapter = new EchoServer(context);
+ break;
+ case ENVELOP: // 20100423 JGY
+ adapter = new EnvelopServer(context);
+ break;
+ case FIXED_LENGTH_HEADER:
+ adapter = new FixedHeaderServer(context);
+ break;
+ case FIXED_LENGTH_PAYLOAD:
+ adapter = new FixedPayloadServer(context);
+ break;
+ case VARIABLE_LENGTH_HEADER: //20121030 KWON SE HWAN
+ adapter = new VariableHeaderServer(context);
+ break;
+ case INISAFE: // 한국은행 신한은망
+ adapter = new InisafeServer(context);
+ break;
+ case INISAFE_2020: // 한국은행 신한은망 NEW Version
+ adapter = new Inisafe2020Server(context);
+ break;
+ case INISAFE_NATN: // 한국은행 국고망
+ adapter = new InisafeNatnPayloadServer(context);
+ break;
+ case INISAFE_PAYLOAD: // 20100510 JGY // 정책금융공사
+ adapter = new InisafePayloadServer(context);
+ break;
+ case HTTP:
+ adapter = new HttpServer(context);
+ break;
+ case PROXY:
+ adapter = new ProxyServer(context);
+ break;
+ case TCSEED: // 20101213 JGY
+ adapter = new TcseedServer(context);
+ break;
+ case UDP_FIXED_LENGTH_HEADER:
+ case UDP_FIXED_LENGTH_PAYLOAD:
+ adapter = new UdpServer(context);
+ break;
+ case XECURE:
+ adapter = new XecureServer(context);
+ break;
+ case XECURE2:
+ adapter = new Xecure2Server(context);
+ break;
+ case XECURE3: // 20100901 JGY
+ adapter = new Xecure3Server(context);
+ break;
+ case LAW:
+ adapter = new LawServer(context);
+ break;
+ case DELIMITER:
+ adapter = new DelimiterServer(context);
+ break;
+ case INICIS:
+ adapter = new InicisServer(context);
+ break;
+ case APPEND:
+ adapter = new AppendServer(context);
+ break;
+ case XC3EPB:
+ adapter = new Xc3EpbServer(context);
+ break;
+ case DYNAMIC_OFFSET:
+ adapter = new DynamicOffsetServer(context);
+ break;
+ case UNKNOWN:
+ default:
+ throw new EAIException("unknown protocol : " + context.getProtocol());
+ }
+ break;
+ case CLIENT:
+ switch(Protocol.getValue(context.getProtocol())) {
+ case ADMIN:
+ case CERT:
+ if (Env.isWindows()) { // for test
+ adapter = new CertClient(context);
+ break;
+ } else {
+ throw new EAIException(context.getAdapterName() + " | 'CERT' Protocol does not support 'CLIENT' socket type.");
+ }
+ case CISCO:
+ adapter = new CiscoClient(context);
+ break;
+ case ECHO:
+ adapter = new EchoClient(context);
+ break;
+ case ENVELOP:
+ adapter = new EnvelopClient(context);
+ break;
+ case FIXED_LENGTH_HEADER:
+ adapter = new FixedHeaderClient(context);
+ break;
+ case FIXED_LENGTH_PAYLOAD:
+ adapter = new FixedPayloadClient(context);
+ break;
+ case VARIABLE_LENGTH_HEADER:
+ adapter = new VariableHeaderClient(context);
+ break;
+ case INISAFE: // 한국은행 신한은망
+ adapter = new InisafeClient(context);
+ break;
+ case INISAFE_2020: // 한국은행 신한은망 New Version
+ adapter = new Inisafe2020Client(context);
+ break;
+ case INISAFE_NATN: // 한국은행 국고망
+ adapter = new InisafeNatnPayloadClient(context);
+ break;
+ case INISAFE_PAYLOAD: // 정책금융공사
+ adapter = new InisafePayloadClient(context);
+ break;
+ case HTTP:
+ case PROXY:
+ throw new EAIException(context.getAdapterName() + " | '" + context.getProtocol() + "' Protocol does not support 'CLIENT' socket type.");
+ case TCSEED:
+ adapter = new TcseedClient(context);
+ break;
+ case UDP_FIXED_LENGTH_HEADER:
+ case UDP_FIXED_LENGTH_PAYLOAD:
+ adapter = new UdpClient(context);
+ break;
+ case XECURE:
+ adapter = new XecureClient(context);
+ break;
+ case XECURE2:
+ adapter = new Xecure2Client(context);
+ break;
+ case XECURE3:
+ adapter = new Xecure3Client(context);
+ break;
+ case LOGIN:
+ adapter = new LoginClient(context);
+ break;
+ case LAZY:
+ adapter = new LazyClient(context);
+ break;
+ case BIND:
+ adapter = new BindClient(context);
+ break;
+ case LAW:
+ adapter = new LawClient(context);
+ break;
+ case DELIMITER:
+ adapter = new DelimiterClient(context);
+ break;
+ case INICIS:
+ adapter = new InicisClient(context);
+ break;
+ case APPEND:
+ adapter = new AppendClient(context);
+ break;
+ case XC3EPB:
+ adapter = new Xc3EpbClient(context);
+ break;
+ case DYNAMIC_OFFSET:
+ adapter = new DynamicOffsetClient(context);
+ break;
+ case UNKNOWN:
+ default:
+ throw new EAIException("unknown protocol : " + context.getProtocol());
+ }
+ break;
+ case UNKNOWN:
+ default:
+ throw new EAIException("unknown socket type : " + context.getSocketType());
+ }
+
+ SocketAdapterManager.getInstance().addAdapter(adapter);
+
+ return adapter;
+ } catch (EAIException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new EAIException(e);
+ }
+ }
+
+ // START A SOCKET ADAPTER CONFIGURATION
+ public static ISocketAdapter createSocketAdapter(AdapterVO config) throws Exception {
+ return createSocketAdapter(createContext(config));
+ }
+
+ public static SocketAdapterContext createContext(AdapterVO config) throws Exception {
+ SocketAdapterContext context = new SocketAdapterContext();
+ context.setAdapterGroupName(config.getAdapterGroupName());
+ context.setAdapterName(config.getName());
+
+ //PropManager manager = PropManager.getInstance();
+ AdapterPropManager manager = AdapterPropManager.getInstance();
+ Properties prop = manager.getProperties(config.getPropGroupName());
+// String errMsg = null;
+
+ /**
+ * protocol
+ */
+ if (!"".equals(prop.getProperty(Constants.PROTOCOL, "").trim())) {
+ context.setProtocol(prop.getProperty(Constants.PROTOCOL, context.getProtocol()).trim());
+ if (!context.getProtocol().matches("(FIXED_LENGTH_HEADER|FIXED_LENGTH_PAYLOAD|VARIABLE_LENGTH_HEADER|CISCO|CERT|INISAFE|INISAFE_2020|INISAFE_NATN|INISAFE_PAYLOAD|EGSEED|TCSEED|ADMIN|HTTP|OBJECT|UDP_FIXED_LENGTH_HEADER|UDP_FIXED_LENGTH_PAYLOAD|XECURE|XECURE2|XECURE3|ENVELOP|LOGIN|LAZY|BIND|APPEND|DELIMITER|INICIS|XC3EPB|DYNAMIC_OFFSET|)")) {
+ throw new Exception(context.getAdapterName() + " | protocol must be one of (FIXED_LENGTH_HEADER|FIXED_LENGTH_PAYLOAD|VARIABLE_LENGTH_HEADER|CISCO|CERT|INISAFE|INISAFE_2020|INISAFE_NATN|INISAFE_PAYLOAD|EGSEED|TCSEED|ADMIN|HTTP|OBJECT|UDP_FIXED_LENGTH_HEADER|UDP_FIXED_LENGTH_PAYLOAD|XECURE|XECURE2|XECURE3|ENVELOP|LOGIN|LAZY|BIND|APPEND|DELIMITER|INICIS|XC3EPB|DYNAMIC_OFFSET|), but - '" + context.getProtocol() + "'");
+ }
+ } else {
+ // for backward compatibility
+ if ("CISCO".equals(prop.getProperty(Constants.LL_FIELD_TYPE))) {
+ context.setProtocol("CISCO");
+ }
+ logger.warn(context.getAdapterName() + " | 'protocol' is not specified. use default : " + context.getProtocol());
+ }
+
+ /**
+ * adapter.group.name
+ */
+ if (prop.getProperty(Constants.ADAPTER_GROUP_NAME) == null) {
+ throw new Exception(context.getAdapterName() + " | adapter group name is null");
+ }
+
+ /**
+ * bound.usage
+ */
+ if (!"".equals(prop.getProperty(Constants.BOUND_USAGE, "").trim())) {
+ context.setBoundUsage(prop.getProperty(Constants.BOUND_USAGE, context.getBoundUsage()).trim());
+ if ("INBOUND,OUTBOUND,IOBOUND".indexOf(context.getBoundUsage()) < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.BOUND_USAGE + " must be one of [INBOUND|OUTBOUND|IOBOUND], but - '" + context.getBoundUsage() + "'");
+ }
+ }
+
+ /**
+ * socket.type
+ */
+ if (!"".equals(prop.getProperty(Constants.SOCKET_TYPE, "").trim())) {
+ if ("ADMIN".equals(context.getSocketType()))
+ context.setSocketType("SERVER");
+
+ context.setSocketType(prop.getProperty(Constants.SOCKET_TYPE, context.getSocketType()).trim());
+ if ("SERVER,CLIENT".indexOf(context.getSocketType()) < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.SOCKET_TYPE + " must be one of [SERVER|CLIENT], but - '" + context.getSocketType() + "'");
+ }
+ }
+
+ /**
+ * permanent
+ */
+ if (!"".equals(prop.getProperty(Constants.PERMANENT, "").trim())) {
+ context.setPermanent(prop.getProperty(Constants.PERMANENT, context.getPermanent()).trim());
+ if (context.getPermanent() == null || !context.getPermanent().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.PERMANENT + " must be one of [Y|N], but - '" + context.getPermanent() + "'");
+ }
+ }
+
+ /**
+ * blocking
+ */
+ if (!"".equals(prop.getProperty(Constants.BLOCKING, "").trim())) {
+ context.setBlocking(prop.getProperty(Constants.BLOCKING, context.getBlocking()).trim());
+ if (context.getBlocking() == null || !context.getBlocking().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.BLOCKING + " must be one of [Y|N], but - '" + context.getBlocking() + "'");
+ }
+ }
+
+ /**
+ * host.name | port.number
+ */
+ context.setHostName(prop.getProperty(Constants.HOST_NAME, context.getHostName()).trim());
+
+ context.setPortNumber(Integer.parseInt(prop.getProperty(Constants.PORT_NUMBER, Integer
+ .toString(context.getPortNumber())).trim()));
+
+ /**
+ * local.host.name | local.port.number (CLIENT type || PROXY protocol)
+ */
+ if (context.getSocketType().equals(SocketAdapterContext.CLIENT_SOCKET)) {
+ if (!"".equals(prop.getProperty(Constants.LOCAL_PORT_NUMBER, "").trim())) {
+ try {
+ context.setLocalPortNumber(Integer.parseInt(prop.getProperty(Constants.LOCAL_PORT_NUMBER, Integer.toString(context.getLocalPortNumber())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LOCAL_PORT_NUMBER + " | " + e.getMessage());
+ }
+ }
+
+ if (!"".equals(prop.getProperty(Constants.LOCAL_HOST_NAME, "").trim())) {
+ context.setLocalHostName(prop.getProperty(Constants.LOCAL_HOST_NAME, context.getLocalHostName()).trim());
+ }
+ }
+
+ /**
+ * max.connection
+ */
+ if (!"".equals(prop.getProperty(Constants.MAX_CONNECTION, "").trim())) {
+ try {
+ context.setMaxConnection(Integer.parseInt(prop.getProperty(Constants.MAX_CONNECTION, Integer.toString(context.getMaxConnection())).trim()));
+ if (context.getSocketType().equals(SocketAdapterContext.CLIENT_SOCKET) && context.getMaxConnection() < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.MAX_CONNECTION + "(" + context.getMaxConnection() + ") < 0");
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.MAX_CONNECTION + " | " + e.getMessage());
+ }
+ } else {
+ if (context.isServer()) {
+ context.setMaxConnection(0);
+ }
+ }
+
+ /**
+ * connection.limit.per.ip
+ */
+ if (!"".equals(prop.getProperty(Constants.CONN_LIMIT_PER_IP, "").trim())) {
+ try {
+ context.setConnLimitPerIp(Integer.parseInt(prop.getProperty(Constants.CONN_LIMIT_PER_IP, Integer.toString(context.getConnLimitPerIp())).trim()));
+ if (context.getConnLimitPerIp() < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.CONN_LIMIT_PER_IP + " must be > 0, but - '" + context.getConnLimitPerIp() + "'");
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.CONN_LIMIT_PER_IP + " | " + e.getMessage());
+ }
+ }
+
+ /**
+ * max.thread
+ */
+ if (!"".equals(prop.getProperty(Constants.MAX_THREAD, "").trim())) {
+ try {
+ context.setMaxThread(Integer.parseInt(prop.getProperty(Constants.MAX_THREAD, Integer.toString(context.getMaxThread())).trim()));
+ if (context.getMaxThread() < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.MAX_THREAD + " must be > 0, but - '" + context.getMaxThread() + "'");
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.MAX_THREAD + " | " + e.getMessage());
+ }
+ // for backward compatibility - old socket
+ } else if (!"".equals(prop.getProperty("max.session", "").trim())) {
+ logger.warn(context.getAdapterName() + " | old socket property | change property name 'max.session' -> '" + Constants.MAX_THREAD + "'");
+ try {
+ context.setMaxThread(Integer.parseInt(prop.getProperty("max.session", Integer.toString(context.getMaxThread())).trim()));
+ if (context.getMaxThread() < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.MAX_THREAD + " must be > 0, but - '" + context.getMaxThread() + "'");
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.MAX_THREAD + " | " + e.getMessage());
+ }
+ }
+
+ /**
+ * timeout
+ */
+ if (!"".equals(prop.getProperty(Constants.TIMEOUT, "").trim())) {
+ try {
+ context.setTimeout(Integer.parseInt(prop.getProperty(Constants.TIMEOUT, Integer.toString(context.getTimeout())).trim()));
+ if (context.getTimeout() < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.TIMEOUT + " must be > 0, but - '" + context.getTimeout() + "'");
+ }
+
+ if (context.getTimeout() > 600) {
+ logger.warn(context.getAdapterName() + " | timeout is to big '" + context.getTimeout() + "' -> timeout is reset to 600 (sec)");
+ context.setTimeout(600);
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.TIMEOUT + " | " + e.getMessage());
+ }
+ }
+
+
+ /**
+ * idle timeout
+ */
+ if (!"".equals(prop.getProperty(Constants.IDLE_TIMEOUT, "").trim())) {
+ try {
+ context.setIdleTimeout(Integer.parseInt(prop.getProperty(Constants.IDLE_TIMEOUT, Integer.toString(context.getIdleTimeout())).trim()));
+ // idle.timeout 을 설정하지 않을 경우, 0으로 처리되므로 동일하게 체크하도록 수정함
+ // 다만, L4에 의해 비정상 종료되는 경우가 발생할 수 있으므로 유의해서 사용해야 함
+ if (context.getIdleTimeout() == 0) {
+ logger.warn(context.getAdapterName() + " | idle.timeout =" + context.getIdleTimeout() + ", session will not close");
+ }
+ else {
+ if (context.getIdleTimeout() < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.IDLE_TIMEOUT + " must be > 0, but - '" + context.getIdleTimeout() + "'");
+ }
+
+ if (context.getIdleTimeout() <= context.getTimeout()) {
+ throw new Exception(context.getAdapterName() + " | idle.timeout (" + context.getIdleTimeout() + " sec) must be greater than timeout(" + context.getTimeout() + " sec)");
+ }
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.IDLE_TIMEOUT + " | " + e.getMessage());
+ }
+ }
+
+ /**
+ * response.type
+ */
+ if (!"".equals(prop.getProperty(Constants.RESPONSE_TYPE, "").trim())) {
+ context.setResponseType(prop.getProperty(Constants.RESPONSE_TYPE, context.getResponseType()).trim());
+ if ("SYNC,ASYN".indexOf(context.getResponseType()) < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.RESPONSE_TYPE + " must be one of (SYNC|ASYN), but - '" + context.getResponseType() + "'");
+ }
+ }
+
+ /**
+ * socket.reuse
+ */
+ if (!"".equals(prop.getProperty(Constants.SOCKET_REUSE, "").trim())) {
+ context.setSocketReuse(prop.getProperty(Constants.SOCKET_REUSE, context.getSocketReuse()).trim());
+ if ("Y,N".indexOf(context.getSocketReuse()) < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.SOCKET_REUSE + " must be one of [Y|N], but - '" + context.getSocketReuse() + "'");
+ }
+ }
+
+ /**
+ * ack.support
+ */
+ if (!"".equals(prop.getProperty(Constants.ACK_SUPPORT, "").trim())) {
+ context.setAckSupport(prop.getProperty(Constants.ACK_SUPPORT, context.getAckSupport()).trim());
+ if ("Y,N".indexOf(context.getAckSupport()) < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.ACK_SUPPORT + " must be one of [Y|N], but - '" + context.getAckSupport() + "'");
+ }
+ }
+
+ /**
+ * acl
+ */
+ if (!"".equals(prop.getProperty(Constants.ACL_LIST, "").trim())) {
+ context.setAclList(prop.getProperty(Constants.ACL_LIST , context.getAclList()).trim());
+ }
+
+ /**
+ * validation.rule
+ */
+ if (!"".equals(prop.getProperty(Constants.VALIDATION_RULE, "").trim())) {
+ context.setValidationRule(prop.getProperty(Constants.VALIDATION_RULE, context.getValidationRule()).trim());
+ }
+
+ /**
+ * datacontrol.rule
+ */
+ if (!"".equals(prop.getProperty(Constants.DATACONTROL_RULE, ""))) {
+ context.setDataControlRule(prop.getProperty(Constants.DATACONTROL_RULE, context.getDataControlRule()));
+ }
+
+ /**
+ * business.work.class.code
+ */
+ context.setBwkClsCd(prop.getProperty(Constants.WORK_CLASS_CODE, context.getBwkClsCd()).trim());
+
+ /**
+ * trace.level
+ */
+ if (!"".equals(prop.getProperty(Constants.TRACE_LEVEL, "").trim())) {
+ try {
+ context.setTraceLevel(Integer.parseInt(prop.getProperty(Constants.TRACE_LEVEL, Integer
+ .toString(context.getTraceLevel())).trim()));
+ if ("0,1,2,3".indexOf(Integer.toString(context.getTraceLevel())) < 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.TRACE_LEVEL + " must be one of [0|1|2|3], but - '" + context.getTraceLevel() + "'");
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.TRACE_LEVEL + " | " + e.getMessage());
+ }
+ }
+
+ /**
+ * description
+ */
+ context.setDescription(prop.getProperty(Constants.DESCRIPTION, context.getDescription()).trim());
+
+
+ /**
+ * polling
+ * - polling.use : Y|N
+ * - polling.role : SEDNER|RECEIVER
+ * - polling.oneway : Y|N
+ * - polling.timeout : SENDER (default:client)
+ * - polling.request : SENDER (default:client)
+ * - polling.response.pattern : SENDER (default:client)
+ * - polling.request.pattern : RECEIVER (default:server)
+ * - polling.replacement : RECEIVER (default:server)
+ */
+
+ /**
+ * polling.use
+ */
+ if (!"".equals(prop.getProperty(Constants.POLLING_USE, "").trim())) {
+ context.setPollingUse(prop.getProperty(Constants.POLLING_USE, context.getPollingUse()).trim());
+ if (!context.getPollingUse().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.POLLING_USE + " must be one of [Y|N], but - '" + context.getPollingUse() + "'");
+ }
+ }
+
+ if (context.isPollingUse()) {
+ /**
+ * polling.role
+ */
+ // JGY 20100510
+ String pollingRole = prop.getProperty(Constants.POLLING_ROLE, "").trim();
+ if ("".equals(pollingRole)) {
+ if (context.isClient()) {
+ context.setPollingRole("SENDER");
+ } else {
+ context.setPollingRole("RECEIVER");
+ }
+ } else {
+// if (!context.getPollingRole().matches("(SENDER|RECEIVER)")) {
+ if (!pollingRole.matches("(SENDER|RECEIVER)")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.POLLING_ROLE + " must be one of (SENDER|RECEIVER), but -> '" + pollingRole + "'");
+ }
+ context.setPollingRole(prop.getProperty(Constants.POLLING_ROLE, context.getPollingRole()).trim());
+ }
+
+ /**
+ * polling.oneway
+ */
+ if (!"".equals(prop.getProperty(Constants.POLLING_ONEWAY, "").trim())) {
+ context.setPollingOneway(prop.getProperty(Constants.POLLING_ONEWAY, context.getPollingOneway()).trim());
+ }
+
+ /**
+ * polling.timeout
+ */
+ if (!"".equals(prop.getProperty(Constants.POLLING_TIMEOUT, "").trim())) {
+ try {
+ context.setPollingTimeout(Integer.parseInt(prop.getProperty(Constants.POLLING_TIMEOUT, Integer.toString(context.getPollingTimeout())).trim()));
+ if (context.getPollingTimeout() <= 0) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.POLLING_TIMEOUT + " must be > 0, but - '" + context.getPollingTimeout() + "'");
+ }
+ if (context.getPollingTimeout() <= context.getTimeout()) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.POLLING_TIMEOUT + " must be > timeout(" + context.getTimeout() + ")");
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.POLLING_TIMEOUT + " | " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * polling.request
+ */
+ if (!"".equals( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_REQUEST, ""))) ) {
+ context.setPollingRequest( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_REQUEST, context.getPollingRequest())) );
+ }
+
+ /**
+ * polling.request.pattern
+ */
+ if (!"".equals( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_REQUEST_PATTERN, ""))) ) {
+ context.setPollingRequestPattern( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_REQUEST_PATTERN, context.getPollingRequestPattern())) );
+ }
+
+ /**
+ * polling.replacement
+ */
+ if (!"".equals( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_REPLACEMENT, ""))) ) {
+ context.setPollingReplacement ( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_REPLACEMENT, context.getPollingReplacement())) );
+ }
+
+ /**
+ * polling.response.pattern
+ */
+ if (!"".equals( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_RESPONSE_PATTERN, ""))) ) {
+ context.setPollingResponsePattern( NullControl.trimSpace2(prop.getProperty(Constants.POLLING_RESPONSE_PATTERN, context.getPollingResponsePattern())) );
+ }
+ }
+
+
+ /**KSH
+ * init.msg.use
+ */
+ if (!"".equals(prop.getProperty(Constants.INIT_MSG_USE, "").trim())) {
+ context.setInitMsgUse(prop.getProperty(Constants.INIT_MSG_USE, context.getInitMsgUse()).trim());
+ if (!context.getInitMsgUse().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.INIT_MSG_USE + " must be one of [Y|N], but - '" + context.getInitMsgUse() + "'");
+ }
+ }
+
+ if (context.isInitMsgUse()) {
+ /**
+ * init.msg.role
+ */
+ // KSH
+ String initMsgRole = prop.getProperty(Constants.INIT_MSG_ROLE, "").trim();
+ if ("".equals(initMsgRole)) {
+ if (context.isClient()) {
+ context.setInitMsgRole("SENDER");
+ } else {
+ context.setInitMsgRole("RECEIVER");
+ }
+ } else {
+ if (!initMsgRole.matches("(SENDER|RECEIVER)")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.INIT_MSG_ROLE + " must be one of (SENDER|RECEIVER), but -> '" + initMsgRole + "'");
+ }
+ context.setInitMsgRole(prop.getProperty(Constants.INIT_MSG_ROLE, context.getInitMsgRole()).trim());
+ }
+
+ /**
+ * init.msg.request
+ */
+ if (!"".equals(prop.getProperty(Constants.INIT_MSG_REQUEST, "").trim())) {
+ context.setInitMsgRequest(prop.getProperty(Constants.INIT_MSG_REQUEST, context.getInitMsgRequest()).trim());
+ }
+
+ /**
+ * init.msg.request.pattern
+ */
+ if (!"".equals(prop.getProperty(Constants.INIT_MSG_REQUEST_PATTERN, "").trim())) {
+ context.setInitMsgRequestPattern(prop.getProperty(Constants.INIT_MSG_REQUEST_PATTERN, context.getInitMsgRequestPattern()).trim());
+ }
+
+ /**
+ * init.msg.replacement
+ */
+ if (!"".equals(prop.getProperty(Constants.INIT_MSG_REPLACEMENT, "").trim())) {
+ context.setInitMsgReplacement(prop.getProperty(Constants.INIT_MSG_REPLACEMENT, context.getInitMsgReplacement()).trim());
+ }
+
+ /**
+ * init.msg.response.pattern
+ */
+ if (!"".equals(prop.getProperty(Constants.INIT_MSG_RESPONSE_PATTERN, "").trim())) {
+ context.setInitMsgResponsePattern(prop.getProperty(Constants.INIT_MSG_RESPONSE_PATTERN, context.getInitMsgResponsePattern()).trim());
+ }
+ }
+
+
+ /**
+ * FIXED_LENGTH_HEADER, UDP_FIXED_LENGTH_HEADER, XECURE, XECURE2, XECURE3, EGSEED, ENVELOP protocol only
+ * VARIABLE_LENGTH_HEADER add 2012.10.30 Kwon Se Hwan
+ * - ll.field.type
+ * - ll.field.offset
+ * - ll.field.length
+ * - ll.field.include
+ * - ll.include
+ */
+ if ("FIXED_LENGTH_HEADER".equals(context.getProtocol())
+ || "VARIABLE_LENGTH_HEADER".equals(context.getProtocol())
+ || "UDP_FIXED_LENGTH_HEADER".equals(context.getProtocol())
+ || "EGSEED".equals(context.getProtocol())
+ || "TCSEED".equals(context.getProtocol())
+ || "ENVELOP".equals(context.getProtocol())
+ || "XECURE".equals(context.getProtocol())
+ || "XECURE2".equals(context.getProtocol())
+ || "XECURE3".equals(context.getProtocol())
+ || "LOGIN".equals(context.getProtocol())
+ || "LAZY".equals(context.getProtocol())
+ || "BIND".equals(context.getProtocol())
+ || "APPEND".equals(context.getProtocol())
+ || "INICIS".equals(context.getProtocol())
+ || "XC3EPB".equals(context.getProtocol())
+ || "DYNAMIC_OFFSET".equals(context.getProtocol())
+ ) {
+
+ if (!"".equals(prop.getProperty(Constants.LL_FIELD_TYPE, "").trim())) {
+ context.setLlFieldType(prop.getProperty(Constants.LL_FIELD_TYPE, context.getLlFieldType()).trim());
+ if (!context.getLlFieldType().matches("(BIN|CHAR|NONE)")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_FIELD_TYPE + " must be one of (BIN|CHAR|NONE), but - '" + context.getLlFieldType() + "'");
+ }
+ } else if ("XECURE".equals(context.getProtocol())) {
+ context.setLlFieldType("CHAR");
+ }
+
+ /**
+ * ll.field.offset
+ */
+ if (!"".equals(prop.getProperty(Constants.LL_FIELD_OFFSET, "").trim())) {
+ try {
+ context.setLlFieldOffset(Integer.parseInt(prop.getProperty(Constants.LL_FIELD_OFFSET,
+ Integer.toString(context.getLlFieldOffset())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_FIELD_OFFSET + " | " + e.getMessage());
+ }
+ } else if ("XECURE".equals(context.getProtocol())) {
+ context.setLlFieldOffset(0);
+ }
+
+ /**
+ * ll.field.length
+ */
+ if (!"".equals(prop.getProperty(Constants.LL_LENGTH_ADJUST, "").trim())) {
+ try {
+ context.setLlLenAdjust(Integer.parseInt(prop.getProperty(Constants.LL_LENGTH_ADJUST,
+ Integer.toString(context.getLlFieldLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_LENGTH_ADJUST + " | " + e.getMessage());
+ }
+ }
+
+ /**
+ * ll.field.length
+ */
+ if (!"".equals(prop.getProperty(Constants.LL_FIELD_LENGTH, "").trim())) {
+ try {
+ context.setLlFieldLength(Integer.parseInt(prop.getProperty(Constants.LL_FIELD_LENGTH,
+ Integer.toString(context.getLlFieldLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_FIELD_LENGTH + " | " + e.getMessage());
+ }
+ } else if ("XECURE".equals(context.getProtocol())) {
+ context.setLlFieldLength(7);
+ }
+
+ /**
+ * ll.field.include
+ */
+ if (!"".equals(prop.getProperty(Constants.LL_FIELD_INCLUDE, "").trim())) {
+ context.setLlFieldInclude(prop.getProperty(Constants.LL_FIELD_INCLUDE,
+ context.getLlFieldInclude()).trim());
+ if (!context.getLlFieldInclude().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_FIELD_INCLUDE + " must be one of [Y|N], but - '" + context.getLlFieldInclude() + "'");
+ }
+ } else if ("XECURE".equals(context.getProtocol())) {
+ context.setLlFieldInclude("N");
+ }
+
+ /**
+ * ll.offset.exclude
+ */
+ if (!"".equals(prop.getProperty(Constants.LL_OFFSET_EXCLUDE, "").trim())) {
+ context.setLlOffsetExclude(prop.getProperty(Constants.LL_OFFSET_EXCLUDE,
+ context.getLlOffsetExclude()).trim());
+ if (!context.getLlOffsetExclude().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_OFFSET_EXCLUDE + " must be one of [Y|N], but - '" + context.getLlOffsetExclude() + "'");
+ }
+ } else if ("XECURE".equals(context.getProtocol())) {
+ context.setLlOffsetExclude("N");
+ }
+
+ /**
+ * ll.include
+ */
+ if (!"".equals(prop.getProperty(Constants.LL_INCLUDE, "").trim())) {
+ context.setLlInclude(prop.getProperty(Constants.LL_INCLUDE,
+ context.getLlInclude()).trim());
+ if (!context.getLlFieldInclude().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_INCLUDE + " must be one of [Y|N], but - '" + context.getLlInclude() + "'");
+ }
+ } else if ("XECURE".equals(context.getProtocol())) {
+ context.setLlInclude("Y");
+ }
+
+
+ /**
+ * recv.header.length 2012.10.30 Kwon Se Hwan
+ */
+ if (!"".equals(prop.getProperty(Constants.RECV_HEADER_LENGTH, "").trim())) {
+ try {
+ context.setRecvHeaderLength(Integer.parseInt(prop.getProperty(Constants.RECV_HEADER_LENGTH,
+ Integer.toString(context.getRecvHeaderLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.RECV_HEADER_LENGTH + " | " + e.getMessage());
+ }
+ }
+
+ /**
+ * send.header.length 2012.10.30 Kwon Se Hwan
+ */
+ if (!"".equals(prop.getProperty(Constants.SEND_HEADER_LENGTH, "").trim())) {
+ try {
+ context.setSendHeaderLength(Integer.parseInt(prop.getProperty(Constants.SEND_HEADER_LENGTH,
+ Integer.toString(context.getSendHeaderLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.SEND_HEADER_LENGTH + " | " + e.getMessage());
+ }
+ }
+
+ }
+
+
+ /**
+ * FIXED_LENGTH_PAYLOAD, UDP_FIXED_LENGTH_PAYLOAD, INISAFE_PAYLOAD protocol only
+ * - send.payload.length
+ * - recv.payload.length
+ */
+ if ("FIXED_LENGTH_PAYLOAD".equals(context.getProtocol())
+ || "INISAFE_PAYLOAD".equals(context.getProtocol()) // 20100510 JGY
+ || "UDP_FIXED_LENGTH_PAYLOAD".equals(context.getProtocol())) {
+ /**
+ * send.payload.length
+ */
+ if (!"".equals(prop.getProperty(Constants.SEND_PAYLOAD_LENGTH, "").trim())) {
+ try {
+ context.setSendPayloadLength(Integer.parseInt(prop.getProperty(Constants.SEND_PAYLOAD_LENGTH,
+ Integer.toString(context.getSendPayloadLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.SEND_PAYLOAD_LENGTH + " | " + e.getMessage());
+ }
+ }
+ /**
+ * recv.payload.length
+ */
+ if (!"".equals(prop.getProperty(Constants.RECV_PAYLOAD_LENGTH, "").trim())) {
+ try {
+ context.setRecvPayloadLength(Integer.parseInt(prop.getProperty(Constants.RECV_PAYLOAD_LENGTH,
+ Integer.toString(context.getRecvPayloadLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.RECV_PAYLOAD_LENGTH + " | " + e.getMessage());
+ }
+ }
+ }
+
+
+ /**
+ * SSL
+ * - ssl.use
+ * - ssl.cert.store
+ * - ssl.cert.password
+ */
+ if (!"".equals(prop.getProperty(Constants.SSL_USE, "").trim())) {
+ context.setSslUse(prop.getProperty(Constants.SSL_USE, context.getSslUse()).trim());
+ /*
+ if (!context.getSslUse().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.SSL_USE + " must be one of [Y|N], but - '" + context.getSslUse() + "'");
+ }
+ */
+
+ context.setSslCertStore(prop.getProperty(Constants.SSL_CERT_STORE, context.getSslCertStore()).trim());
+
+ context.setSslCertPassword(prop.getProperty(Constants.SSL_CERT_PASSWORD, context.getSslCertPassword()).trim());
+ }
+
+ /**
+ * INISAFE, INISAFE_NATN protocol only
+ */
+ if ( "INISAFE".equals(context.getProtocol()) || "INISAFE_2020".equals(context.getProtocol())) {
+ context.setInisafeConfigPath(prop.getProperty(Constants.INISAFE_CONFIG_PATH,
+ context.getInisafeConfigPath()).trim());
+
+ context.setInisafeRelatedAdapterGroups(prop.getProperty(Constants.INISAFE_RELATED_ADAPTER_GROUPS,
+ context.getInisafeRelatedAdapterGroups()).trim());
+
+ if (!"".equals(prop.getProperty(Constants.INISAFE_START_MESSAGE, "").trim())) {
+ context.setInisafeStartMessage(prop.getProperty(Constants.INISAFE_START_MESSAGE,
+ context.getInisafeStartMessage()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.INISAFE_STOP_MESSAGE, "").trim())) {
+ context.setInisafeStopMessage(prop.getProperty(Constants.INISAFE_STOP_MESSAGE,
+ context.getInisafeStopMessage()).trim());
+ }
+ }
+ else if ( "INISAFE_NATN".equals(context.getProtocol()) ) {
+ context.setInisafeConfigPath(prop.getProperty(Constants.INISAFE_CONFIG_PATH,
+ context.getInisafeConfigPath()).trim());
+
+ context.setInisafeRelatedAdapterGroups(prop.getProperty(Constants.INISAFE_RELATED_ADAPTER_GROUPS,
+ context.getInisafeRelatedAdapterGroups()).trim());
+
+ if (!"".equals(prop.getProperty(Constants.INISAFE_START_MESSAGE, "").trim())) {
+ context.setInisafeStartMessage(prop.getProperty(Constants.INISAFE_START_MESSAGE,
+ context.getInisafeStartMessage()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.INISAFE_STOP_MESSAGE, "").trim())) {
+ context.setInisafeStopMessage(prop.getProperty(Constants.INISAFE_STOP_MESSAGE,
+ context.getInisafeStopMessage()).trim());
+ }
+
+ /**
+ * send.payload.length
+ */
+ if (!"".equals(prop.getProperty(Constants.SEND_PAYLOAD_LENGTH, "").trim())) {
+ try {
+ context.setSendPayloadLength(Integer.parseInt(prop.getProperty(Constants.SEND_PAYLOAD_LENGTH,
+ Integer.toString(context.getSendPayloadLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.SEND_PAYLOAD_LENGTH + " | " + e.getMessage());
+ }
+ }
+ else {
+ context.setSendPayloadLength(460);
+ }
+ /**
+ * recv.payload.length
+ */
+ if (!"".equals(prop.getProperty(Constants.RECV_PAYLOAD_LENGTH, "").trim())) {
+ try {
+ context.setRecvPayloadLength(Integer.parseInt(prop.getProperty(Constants.RECV_PAYLOAD_LENGTH,
+ Integer.toString(context.getRecvPayloadLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.RECV_PAYLOAD_LENGTH + " | " + e.getMessage());
+ }
+ }
+ else {
+ context.setRecvPayloadLength(460);
+ }
+
+ /**
+ * ll.field.length
+ */
+ if (!"".equals(prop.getProperty(Constants.LL_FIELD_LENGTH, "").trim())) {
+ try {
+ context.setLlFieldLength(Integer.parseInt(prop.getProperty(Constants.LL_FIELD_LENGTH,
+ Integer.toString(context.getLlFieldLength())).trim()));
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.LL_FIELD_LENGTH + " | " + e.getMessage());
+ }
+ } else {
+ context.setLlFieldLength(0);
+ }
+ }
+
+ /**
+ * INISAFE_PAYLOAD protocol only - 20100510 JGY
+ */
+ if ("INISAFE_PAYLOAD".equals(context.getProtocol())) {
+ context.setInisafeConfigPath(prop.getProperty(Constants.INISAFE_CONFIG_PATH,
+ context.getInisafeConfigPath()).trim());
+
+ context.setInisafeIdPassword(prop.getProperty(Constants.INISAFE_ID_PASSWORD,
+ context.getInisafeIdPassword()).trim());
+ }
+
+ /**
+ * sms.running.time
+ */
+ if (!"".equals(prop.getProperty(Constants.SMS_RUNNING_TIME, "").trim())) {
+ context.setSmsRunningTime(prop.getProperty(Constants.SMS_RUNNING_TIME , context.getSmsRunningTime()).trim());
+ }
+
+ /**
+ * XECURE protocol only
+ * - xecure.type
+ * - xecure.config.path
+ * - xecure.remote.cert
+ */
+
+ if ("XECURE".equals(context.getProtocol())) {
+ context.setXecureType(prop.getProperty(Constants.XECURE_TYPE, context.getXecureType()));
+ if (!context.getXecureType().matches("(BASIC|FIXED|WELCOME|ENVELOPE|FIXEDHEADER)")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.XECURE_TYPE + " must be one of (BASIC|FIXED|WELCOME|ENVELOPE|FIXEDHEADER), but - '" + context.getXecureType() + "'");
+ }
+
+ context.setXecureConfigPath(prop.getProperty(Constants.XECURE_CONFIG_PATH,
+ context.getXecureConfigPath()).trim());
+
+ context.setXecureRemoteCert(prop.getProperty(Constants.XECURE_REMOTE_CERT,
+ context.getXecureRemoteCert()).trim());
+ }
+
+ /**
+ * XECURE2 protocole only
+ * - xecure2.config.path
+ * - xecure2.sm.ip
+ * - xecure2.sm.port
+ */
+ if ("XECURE2".equals(context.getProtocol())) {
+ if (!"".equals(prop.getProperty(Constants.XECURE2_CONFIG_PATH, "").trim())) {
+ context.setXecure2ConfigPath(prop.getProperty(Constants.XECURE2_CONFIG_PATH,
+ context.getXecure2ConfigPath()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.XECURE2_SM_IP, "").trim())) {
+ context.setXecure2SmIp(prop.getProperty(Constants.XECURE2_SM_IP,
+ context.getXecure2SmIp()).trim());
+ }
+
+ try {
+ if (!"".equals(prop.getProperty(Constants.XECURE2_SM_PORT, "").trim())) {
+ context.setXecure2SmPort(Integer.parseInt(prop.getProperty(Constants.XECURE2_SM_PORT,
+ Integer.toString(context.getXecure2SmPort())).trim()));
+ }
+ } catch (NumberFormatException e) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.XECURE2_SM_PORT + " | " + e.getMessage());
+ }
+
+ // use CISCO interface only
+ if (!"".equals(prop.getProperty(Constants.XECURE_TYPE, "").trim())) {
+ context.setXecureType(prop.getProperty(Constants.XECURE_TYPE, context.getXecureType()));
+ }
+ }
+
+ /**
+ * XECURE3 protocol only
+ * - xecure3.type
+ * - xecure3.config.path
+ * - xecure3.remote.cert
+ */
+
+ if ("XECURE3".equals(context.getProtocol())) {
+ context.setXecureType(prop.getProperty(Constants.XECURE_TYPE, context.getXecureType()));
+ if (!context.getXecureType().matches("(ENVELOPE)")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.XECURE_TYPE + " must be one of (ENVELOPE), but - '" + context.getXecureType() + "'");
+ }
+
+ if (!"".equals(prop.getProperty(Constants.XECURE3_CERT_STORE, "").trim())) {
+ context.setXecure3CertStore(prop.getProperty(Constants.XECURE3_CERT_STORE,
+ context.getXecure3CertStore()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.XECURE3_SERVER_CERT, "").trim())) {
+ context.setXecure3ServerCert(prop.getProperty(Constants.XECURE3_SERVER_CERT,
+ context.getXecure3ServerCert()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.XECURE3_CLIENT_CERT, "").trim())) {
+ context.setXecure3ClientCert(prop.getProperty(Constants.XECURE3_CLIENT_CERT,
+ context.getXecure3ClientCert()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.XECURE3_CERT_KEY, "").trim())) {
+ context.setXecure3CertKey(prop.getProperty(Constants.XECURE3_CERT_KEY,
+ context.getXecure3CertKey()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.XECURE3_CERT_PASSWORD, "").trim())) {
+ context.setXecure3CertPassword(prop.getProperty(Constants.XECURE3_CERT_PASSWORD,
+ context.getXecure3CertPassword()).trim());
+ }
+ }
+ /**
+ * XC3EPB protocol only
+ * - xc3epb.password
+ * - xc3epb.config.path
+ */
+
+ if ("XC3EPB".equals(context.getProtocol())) {
+
+ if (!"".equals(prop.getProperty(Constants.XC3EPB_PASSWORD, "").trim())) {
+ context.setXc3epbPassword(prop.getProperty(Constants.XC3EPB_PASSWORD,
+ context.getXc3epbPassword()).trim());
+ }
+ if (!"".equals(prop.getProperty(Constants.XC3EPB_CONFIG_PATH, "").trim())) {
+ context.setXc3epbConfigPath(prop.getProperty(Constants.XC3EPB_CONFIG_PATH,
+ context.getXc3epbConfigPath()).trim());
+ }
+ }
+
+ // 20100423 JGY
+ if ("ENVELOP".equals(context.getProtocol())) {
+ if (!"".equals(prop.getProperty(Constants.ENVELOP_SIGNCERT_PATH, "").trim())) {
+ context.setEnvelopSigncertPath(prop.getProperty(Constants.ENVELOP_SIGNCERT_PATH,
+ context.getEnvelopSigncertPath()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.ENVELOP_SIGNKEY_PATH, "").trim())) {
+ context.setEnvelopSignkeyPath(prop.getProperty(Constants.ENVELOP_SIGNKEY_PATH,
+ context.getEnvelopSignkeyPath()).trim());
+ }
+
+ if (!"".equals(prop.getProperty(Constants.ENVELOP_PASSWORD, "").trim())) {
+ context.setEnvelopPassword(prop.getProperty(Constants.ENVELOP_PASSWORD,
+ context.getEnvelopPassword()).trim());
+ }
+ }
+
+ /**
+ * TCSEED protocol only - 20101213 JGY
+ */
+ if ("TCSEED".equals(context.getProtocol())) {
+ context.setTcseedKeyStore(prop.getProperty(Constants.TCSEED_KEY_STORE,
+ context.getTcseedKeyStore()).trim());
+
+ }
+ /**
+ * INICIS protocol only
+ */
+
+ if ("INICIS".equals(context.getProtocol())) {
+ context.setInicisKeyPath(prop.getProperty(Constants.INICIS_KEY_PATH,
+ context.getInicisKeyPath()));
+ context.setInicisKeyPass(prop.getProperty(Constants.INICIS_KEY_PASS,
+ context.getInicisKeyPass()));
+ }
+ /**
+ * DELIMITER protocol only
+ */
+
+ if ("DELIMITER".equals(context.getProtocol())) {
+ context.setDelimiter(prop.getProperty(Constants.DELIMITER,
+ context.getDelimiter()));
+ }
+
+ if (( "LOGIN".equals(context.getProtocol())
+ ||"BIND".equals(context.getProtocol())
+ ||"LAZY".equals(context.getProtocol()) )
+ && context.isClient()) {
+ context.setLoginSend(prop.getProperty(Constants.LOGIN_SEND,
+ context.getLoginSend()));
+ context.setLoginRecv(prop.getProperty(Constants.LOGIN_RECV,
+ context.getLoginRecv()));
+ context.setLlFieldLengthAlpha(Integer.parseInt(prop.getProperty(Constants.LL_FIELD_LENGTH_ALPHA,
+ Integer.toString(context.getLlFieldLengthAlpha()))));
+ }
+ if ("BIND".equals(context.getProtocol()) && context.isClient()) {
+ context.setBindType(prop.getProperty(Constants.BIND_TYPE,
+ context.getBindType()));
+ }
+ if ("APPEND".equals(context.getProtocol())){
+ context.setAppendHead(prop.getProperty(Constants.APPEND_HEAD,
+ context.getAppendHead()));
+ context.setAppendTail(prop.getProperty(Constants.APPEND_TAIL,
+ context.getAppendTail()));
+ }
+
+ /**
+ * block.ip.list
+ */
+ if (!"".equals(prop.getProperty(Constants.BLOCK_IP_LIST,"")) && context.isServer()) {
+ context.setBlockIpList(prop.getProperty(Constants.BLOCK_IP_LIST,""));
+ }
+ /**
+ * l4.skip.ip.list
+ */
+ if (!"".equals(prop.getProperty(Constants.L4_SKIP_IP_LIST,"")) && context.isServer()) {
+ context.setL4SkipIpList(prop.getProperty(Constants.L4_SKIP_IP_LIST,""));
+ }
+
+ /**
+ * SingleSession
+ */
+ if (!"".equals(prop.getProperty(Constants.IS_SINGLE_SESSION, ""))) {
+ context.setSingleSession(prop.getProperty(Constants.IS_SINGLE_SESSION, context.getSingleSession()));
+ if (context.getSingleSession() == null || !context.getSingleSession().matches("[Y|N]")) {
+ throw new Exception(context.getAdapterName() + " | " + Constants.IS_SINGLE_SESSION + " must be one of [Y|N], but - '" + context.getSingleSession() + "'");
+ }
+ }
+
+ /**
+ * SingleSession Primary
+ */
+ if(!"".equals(prop.getProperty(Constants.SINGLE_PRIMARY_INST, ""))) {
+ context.setPrimaryInstId( prop.getProperty(Constants.SINGLE_PRIMARY_INST, context.getPrimaryInstId()));
+ }
+ if ("DYNAMIC_OFFSET".equals(context.getProtocol())){
+ if(!"".equals(prop.getProperty(Constants.DYNAMIC_OFFSET_PATTERN, ""))) {
+ context.setDynamicOffsetPattern( prop.getProperty(Constants.DYNAMIC_OFFSET_PATTERN, context.getDynamicOffsetPattern()));
+ }
+ if(!"".equals(prop.getProperty(Constants.DATA_ADD_RULE, ""))) {
+ context.setDataAddRule( prop.getProperty(Constants.DATA_ADD_RULE, context.getDataAddRule()));
+ }
+ if(!"".equals(prop.getProperty(Constants.DATA_REMOVE_RULE, ""))) {
+ context.setDataRemoveRule( prop.getProperty(Constants.DATA_REMOVE_RULE, context.getDataRemoveRule()));
+ }
+ context.setLlInclude("Y");
+ }
+
+ /**
+ * keep.alive
+ */
+ if (!"".equals(prop.getProperty(Constants.KEEP_ALIVE,"N"))) {
+ context.setKeepAlive(prop.getProperty(Constants.KEEP_ALIVE,"N"));
+ }
+
+ return context;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterManager.java b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterManager.java
new file mode 100644
index 0000000..ef1b7fa
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketAdapterManager.java
@@ -0,0 +1,485 @@
+/*
+ * Created on 2005. 2. 26.
+ */
+package com.eactive.eai.adapter.socket2.config;
+
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.lifecycle.Lifecycle;
+import com.eactive.eai.common.lifecycle.LifecycleException;
+import com.eactive.eai.common.lifecycle.LifecycleListener;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ *
+ */
+public class SocketAdapterManager implements Lifecycle {
+ private Logger logger = SocketLoggerManager.getInstance().getLogger();
+ private Logger errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ public static final long CONNECTION_CHECK_CYCLE = 60 * 1000L; // every 60 sec.
+ public static final long RECOVERY_CHECK_CYCLE = 10 * 1000L; // every 20 sec.
+ // 10분간 미상용시 Connection Close; 0으로 설정시 강제적으로 미사용 소켓을 CLOSE하지 않음....
+ public static final long UNUSED_CONNECTION_TIMEOUT = 0L; // 10 * 60 * 1000L;
+
+ private static final SocketAdapterManager instance = new SocketAdapterManager();
+ private SocketAdapterFactory socketAdapterFactory;
+
+ private ConcurrentHashMap> adapterGroups;
+ Random random = new Random();
+
+ private boolean started;
+
+ public static SocketAdapterManager getInstance() {
+ return instance;
+ }
+
+ private SocketAdapterManager() {
+ adapterGroups = new ConcurrentHashMap<>();
+
+ socketAdapterFactory = new SocketAdapterFactory();
+ started = false;
+ logger.debug(socketAdapterFactory.toString() +" started = " + started);
+ }
+
+
+ public boolean isStarted() {
+ // 자동 생성된 메소드 스텁
+ return false;
+ }
+
+ public void start() throws LifecycleException {
+ // 자동 생성된 메소드 스텁
+
+ }
+
+ public void stop() {
+ for (Enumeration> e = adapterGroups.elements(); e.hasMoreElements(); ) {
+ ConcurrentHashMap group = e.nextElement();
+ for (Enumeration ee = group.elements(); ee.hasMoreElements(); ) {
+ ISocketAdapter adapter = ee.nextElement();
+ try {
+ SimpleFuture future = adapter.stop();
+ future.join();
+ } catch(Exception ex) {
+ logger.error(adapter.getContext().getAdapterName() + " | " + ex.getMessage(), ex);
+ errLogger.error(adapter.getContext().getAdapterName() + " | " + ex.getMessage(), ex);
+ }
+ }
+ }
+ }
+
+ public ConcurrentMap> getSocketAdapterGroups() {
+ return adapterGroups;
+ }
+
+ public ISocketAdapter[] getSocketAdapters(String adapterGroupName) {
+ ConcurrentHashMap adapters0 = adapterGroups.get(adapterGroupName);
+ if (adapters0 == null)
+ return null;
+ ISocketAdapter[] adapters = new ISocketAdapter[adapters0.size()];
+ int i = 0;
+ for (Enumeration e = adapters0.elements(); e.hasMoreElements(); ) {
+ adapters[i++] = e.nextElement();
+ }
+ return adapters;
+ }
+
+ public ISocketAdapter getSocketAdapter(String adapterGroupName, String adapterName) {
+ ConcurrentHashMap adapters = adapterGroups.get(adapterGroupName);
+ if (adapters == null)
+ return null;
+
+ if (adapterName != null) {
+ return adapters.get(adapterName);
+ } else {
+ return adapters.elements().nextElement();
+ }
+ }
+
+ public ISocketAdapter getOutboundSocketAdapter(String adapterGroupName, String adapterName) {
+ ConcurrentHashMap adapters = adapterGroups.get(adapterGroupName);
+ if (adapters == null)
+ return null;
+
+ if (adapterName != null) {
+ return adapters.get(adapterName);
+ } else {
+ // select random
+ Vector started = new Vector<>();
+ for (Iterator iter = adapters.values().iterator(); iter.hasNext();) {
+ ISocketAdapter adapter = iter.next();
+ if (adapter.getState() == ISocketAdapter.State.STARTED
+ && !"INBOUND".equals(adapter.getContext().getBoundUsage())
+ && ("N".equals(adapter.getContext().getPermanent()) || adapter.getSessionPool().size() > 0)
+ ) // concern Non-Permanent pool size 0
+ started.add(adapter);
+ }
+ Object[] array = started.toArray();
+ if (array == null || array.length <= 0) {
+ return null;
+ }
+ else if(array.length > 1) {
+ int index = random.nextInt(array.length);
+ return (ISocketAdapter) array[index];
+ }
+ else {
+ return (ISocketAdapter) array[0];
+ }
+ }
+ }
+
+ public ISocketAdapter getSocketAdapter(String adapterFullName) {
+ String adapterGroupName = adapterFullName;
+ String adapterName = null;
+ if (adapterFullName.indexOf('.') != -1) {
+ adapterGroupName = adapterFullName.substring(0, adapterFullName.indexOf('.'));
+ adapterName = adapterFullName.substring(adapterFullName.indexOf('.')+1);
+ }
+
+ ConcurrentHashMap adapters = adapterGroups.get(adapterGroupName);
+ if (adapters == null)
+ return null;
+
+ if (adapterName != null) {
+ return adapters.get(adapterName);
+ } else {
+ // select random
+ Vector started = new Vector<>();
+ for (Iterator iter = adapters.values().iterator(); iter.hasNext();) {
+ ISocketAdapter adapter = iter.next();
+ if (adapter.getState() == ISocketAdapter.State.STARTED
+ && adapter.getSessionPool().size() > 0) {
+ started.add(adapter);
+ }
+ }
+ Object[] array = started.toArray();
+ if (array == null || array.length <= 0) {
+ return null;
+ }
+ else if(array.length > 1) {
+ int index = random.nextInt(array.length);
+ return (ISocketAdapter) array[index];
+ }
+ else {
+ return (ISocketAdapter) array[0];
+ }
+ }
+ }
+
+ /**
+ * get adapter context
+ */
+ public SocketAdapterContext getContext(String adapterName) {
+ ISocketAdapter adapter = getSocketAdapter(adapterName);
+ if (adapter != null)
+ return adapter.getContext();
+ return null;
+ }
+
+ /**
+ * Adapter Name별 Socket Adapter starting...
+ */
+ public String start(String adapterGroupName, String adapterName) {
+ ISocketAdapter adapter = getSocketAdapter(adapterGroupName, adapterName);
+ if (adapter == null)
+ return adapterGroupName + "." + adapterName + " | SocketAdapter Manager - cannot start - socket adapter does not exists.";
+
+ try {
+ adapter.start().join(60000L);
+ } catch(Exception e) {
+ return ExceptionStackTrace.dump(e);
+ }
+
+ return adapterGroupName + "." + adapterName + " | SocketAdapterManager - adapter started";
+ }
+
+
+ public String stop(String adapterGroupName, String adapterName) {
+// StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = getSocketAdapter(adapterGroupName, adapterName);
+ if (adapter == null)
+ return adapterGroupName + "." + adapterName + " | SocketAdapterManager - socket adapter does not exists.";
+
+ try {
+ adapter.stop().join();
+ } catch(Exception e) {
+ return ExceptionStackTrace.dump(e);
+ }
+
+ return adapterGroupName + "." + adapterName + " | SocketAdapterManager - adapter stopped";
+ }
+
+
+ public void stop(AdapterVO vo) throws Exception {
+ stop(vo.getAdapterGroupName(), vo.getName());
+ }
+
+ public void addAdapter(ISocketAdapter adapter) throws Exception {
+ ConcurrentHashMap adapters = adapterGroups.get(adapter.getContext().getAdapterGroupName());
+ if (adapters == null) {
+ adapterGroups.put(adapter.getContext().getAdapterGroupName(), new ConcurrentHashMap());
+ } else {
+ if (adapters.get(adapter.getContext().getAdapterName()) != null) {
+ logger.warn(adapter.getContext().getAdapterName() + " | SocketAdapterManager - socket adapter already exist -> replace [" + adapter.getContext().getAdapterGroupName() + ", " + adapter.getContext().getAdapterName() + "]");
+ try {
+ ((ISocketAdapter) adapters.get(adapter.getContext().getAdapterName())).stop().join();
+ } catch(Exception e) {
+ logger.warn(adapter.getContext().getAdapterName() + " | old adapter stop error.", e);
+ //adapter.addRecentError(adapter.getContext().getAdapterName() + " | old adapter stop error.", e);
+ } finally {
+ // sleep 1 second to avoid BindException
+ try {
+ Thread.sleep(1000L);
+ } catch(Exception e) {
+ logger.warn(adapter.getContext().getAdapterName() + " | sleep error.", e);
+ }
+ }
+ //throw new Exception(adapter.getContext().getAdapterName() + " | SocketAdapterManager | start error : Socket adapter aready exist [" + adapter.getContext().getAdapterGroupName() + ", " + adapter.getContext().getAdapterName() + "]");
+ }
+ }
+ adapterGroups.get(adapter.getContext().getAdapterGroupName()).put(adapter.getContext().getAdapterName(), adapter);
+ }
+
+
+ public synchronized String disconnect(String remoteIP, String remotePort) {
+ return null;
+ }
+
+ public String toString() {
+ return toString(false);
+ }
+
+ public String toString(boolean verbose) {
+ StringBuilder sb = new StringBuilder();
+ //sb.append("SocketAdater Info (AdpaterGroup > Adapter > Session)\n");
+ sb.append("---------------------------------------------------------------------------------------------------------------------\n");
+
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = e.nextElement();
+ ConcurrentHashMap adapters = adapterGroups.get(adapterGroupName);
+ sb.append("ⓖ AdapterGroup : " + adapterGroupName);
+ //sb.append(", " + adapterGroups);
+ sb.append("\n");
+ for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
+ ISocketAdapter adapter = ee.nextElement();
+ sb.append(" ⓐ Adapter : ");
+ sb.append(adapter.getContext().getAdapterName());
+ sb.append(", " + adapter.getState().name());
+ sb.append(", " + adapter.getContext().getProtocol());
+ sb.append(", " + adapter.getContext().getBoundUsage());
+ sb.append("-" + adapter.getContext().getSocketType());
+ if (adapter.getContext().isClient()) {
+ sb.append(" (" + adapter.getContext().getLocalHostName() + ":" + adapter.getContext().getLocalPortNumber());
+ sb.append("->");
+ sb.append("/" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber() + ")");
+ } else {
+ sb.append(" (" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber());
+ sb.append("<-)");
+ }
+ if(adapter.getContext().isSync()) {
+ sb.append(", SYNC");
+ } else {
+ sb.append(", ASYN");
+ }
+ if ("Y".equals(adapter.getContext().getAckSupport())) {
+ sb.append(", ACK");
+ } else {
+ sb.append(", NO_ACK");
+ }
+ if(adapter.getContext().isPermanent()) {
+ sb.append(", PERMANENT");
+ } else {
+ sb.append(", NON_PERM");
+ }
+ sb.append(", " + adapter.getContext().getMaxConnection());
+ sb.append(", " + adapter.getContext().getMaxThread());
+
+ if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "ADMIN".equals(adapter.getContext().getProtocol())) {
+ sb.append(", " + adapter.getContext().getLlFieldType());
+ sb.append(":" + adapter.getContext().getLlFieldOffset());
+ sb.append(":" + adapter.getContext().getLlFieldLength());
+ sb.append(":" + adapter.getContext().getLlFieldInclude());
+ sb.append(":" + adapter.getContext().getLlInclude());
+ }
+
+ if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "ADMIN".equals(adapter.getContext().getProtocol())) {
+ sb.append(", " + adapter.getContext().getLlFieldType());
+ sb.append(":" + adapter.getContext().getLlFieldOffset());
+ sb.append(":" + adapter.getContext().getLlFieldLength());
+ sb.append(":" + adapter.getContext().getLlFieldInclude());
+ sb.append(":" + adapter.getContext().getLlInclude());
+ sb.append(":" + adapter.getContext().getRecvHeaderLength());
+ sb.append(":" + adapter.getContext().getSendHeaderLength());
+ }
+
+
+ if (adapter.getContext().isClient() &&adapter.getContext().isPollingUse()) {
+ sb.append(" (");
+ sb.append("POLLING, ");
+ sb.append(", " + adapter.getContext().getPollingTimeout());
+ sb.append(", " + adapter.getContext().getPollingRequest());
+ sb.append(")");
+ }
+
+ //KSH
+ if (adapter.getContext().isClient() &&adapter.getContext().isInitMsgUse()) {
+ sb.append(" (");
+ sb.append("INIT_MSG, ");
+ sb.append(", " + adapter.getContext().getInitMsgRequest());
+ sb.append(")");
+ }
+
+ sb.append(", pool:" + adapter.getSessionPool().remaining() + "/" + adapter.getSessionPool().peekSize());
+ sb.append(", recv:" + adapter.getMessageRecv());
+ sb.append(", send:" + adapter.getMessageSend());
+ sb.append(", error:" + adapter.getRecentErrorCount());
+
+ if ("XECURE".equals(adapter.getContext().getProtocol())) {
+ sb.append(", (");
+ sb.append(adapter.getContext().getXecureType());
+ //sb.append(", " + adapter.getContext().getXecureTmode());
+ //sb.append(", " + adapter.getContext().getXecureEncodeMode());
+ //sb.append(", " + adapter.getContext().getXecurePassword());
+ sb.append(", " + adapter.getContext().getXecureConfigPath());
+ sb.append(", " + adapter.getContext().getXecureRemoteCert());
+ sb.append(")");
+ }
+
+// if (verbose && false) {
+// sb.append(", " + adapter.getContext().getDescription());
+// }
+
+ sb.append("\n");
+// if (verbose && false) {
+// sb.append(adapter.getContext() + "\n");
+// }
+ for (Iterator iii = adapter.getSessionPool().iterator() ; iii.hasNext(); ) {
+ IoSession session = iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");
+ //sb.append(" [" + session.getTrafficMask() + "]");
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", " + TimeUtil.formatDate(session.getCreationTime()));
+ //sb.append(" start:" + DatetimeUtil.getCurrentDateDash(session.getCreationTime())
+ sb.append(", recv:" + session.getReadMessages());
+ //sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ //sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+
+ if (adapter.getSessionPool().checkedOut() > 0) {
+ sb.append(" -----------------------------------------------------------------------------------------------\n");
+ }
+
+ for (Iterator iii = adapter.getSessionPool().checkedOutIterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");
+ //sb.append(" [" + session.getTrafficMask() + "]");
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", " + TimeUtil.formatDate(session.getCreationTime()));
+ //sb.append(" start:" + DatetimeUtil.getCurrentDateDash(session.getCreationTime())
+ sb.append(", recv:" + session.getReadMessages());
+ //sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ //sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ }
+ }
+ sb.append("---------------------------------------------------------------------------------------------------------------------\n");
+ //sb.append(queue.toString());
+ return sb.toString();
+ }
+
+ public void addLifecycleListener(LifecycleListener listener) {
+ if(logger.isDebug()) logger.debug("addLifecycleListener : " + listener);
+ }
+
+ public LifecycleListener[] findLifecycleListeners() {
+ return new LifecycleListener[0];
+ }
+
+ public void removeLifecycleListener(LifecycleListener listener) {
+ if(logger.isDebug()) logger.debug("removeLifecycleListener : " + listener);
+ }
+
+ public List searchAdapterGroupName(String searchType,String searchValue){
+ List adapterGroupNames = new ArrayList<>();
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = e.nextElement();
+ ConcurrentHashMap adapters = adapterGroups.get(adapterGroupName);
+
+ for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
+ ISocketAdapter adapter = ee.nextElement();
+
+ String value = null;
+ if ("PROTOCOL".equals(searchType)){
+ value = adapter.getContext().getProtocol();
+ }else if ("PORTNUMBER".equals(searchType)){
+ value = String.valueOf(adapter.getContext().getPortNumber());
+ }else if ("HOSTNAME".equals(searchType)){
+ value = adapter.getContext().getHostName();
+ }
+
+ if (value != null && value.equals(searchValue)){
+ adapterGroupNames.add(adapterGroupName);
+ break;
+ }
+ }
+ }
+
+ return adapterGroupNames;
+ }
+ /**
+ * 일자전환 관련
+ * - ATM socket 어댑터를 끊기 위해서 생성
+ *
+ */
+ public void sessionCloseAll(String adapterGroupName){
+ ConcurrentHashMap adapters0 = adapterGroups.get(adapterGroupName);
+ if (adapters0 == null)
+ return ;
+ int i = 0;
+ for (Enumeration e = adapters0.elements(); e.hasMoreElements(); ) {
+ ISocketAdapter socket = e.nextElement();
+ socket.getSessionPool().shutdown();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/config/SocketLogger.java b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketLogger.java
new file mode 100644
index 0000000..e1918db
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketLogger.java
@@ -0,0 +1,12 @@
+package com.eactive.eai.adapter.socket2.config;
+//package com.eactive.eai.adapter.socket2.config;
+//
+//import com.eactive.eai.common.util.Logger;
+//
+//public class SocketLogger {
+//
+// public static final int DEFAULT = 0; // WARNING, ERROR, FATAL인 경우 에러로깅
+// public static final int INFO = 1; // INFO 수준의 LOGGING을 수행한다.
+// public static final int DEBUG = 2; // DEBUG 수준의 송수신전문 및 에러 메인처리내용의 모든수준의 로깅을 수행한다.
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/config/SocketLoggerManager.java b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketLoggerManager.java
new file mode 100644
index 0000000..777c718
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/config/SocketLoggerManager.java
@@ -0,0 +1,134 @@
+/*
+ * Created on 2005. 2. 26.
+ */
+package com.eactive.eai.adapter.socket2.config;
+
+import com.eactive.eai.adapter.AdapterPropManager;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.util.Logger;
+
+import java.util.HashMap;
+import java.util.Properties;
+
+
+/**
+ * @author janet
+ */
+public class SocketLoggerManager {
+ private static SocketLoggerManager instance = new SocketLoggerManager();
+
+ private HashMap pool = new HashMap() ; // KEY - adapterGroupName, VALUE - logger
+ private String eaiServer;
+ public static String DEFAULT_LOGGER_NAME = "NET";
+ public static String ERROR_LOGGER_NAME = "ERRORNET";
+
+ public SocketLoggerManager() {
+ eaiServer = EAIServerManager.getInstance().getLocalServerName();
+ if (eaiServer == null)
+ eaiServer = "";
+ }
+
+ public static SocketLoggerManager getInstance() {
+ return instance;
+ }
+
+ public void stop() {
+ this.removeAll();
+ }
+
+ public void removeAll() {
+ pool.clear();
+ }
+
+ // Socket Adapter Group Name별 Logger생성 및 관리...
+ public void start(String adapterGroupName) {
+ this.addLogger(adapterGroupName);
+ }
+
+ public synchronized void addLogger(String adapterGroupName) {
+ String loggerName = this.getLoggerName( adapterGroupName );
+ Object o = pool.get( loggerName );
+ if ( o == null ) {
+ synchronized ( pool ) {
+ o = pool.get( loggerName );
+ if ( o == null ) {
+ Logger logger = Logger.getLogger( loggerName );
+// boolean isNull = (logger == null );
+ pool.put( loggerName, logger );
+ }
+ }
+ }
+ }
+
+ private String getLoggerName(String adapterGroupName) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("FileLogger{").append( adapterGroupName ).append("}_").append( this.eaiServer );
+
+ return sb.toString();
+ }
+
+ private String getLoggerBase(String adapterGroupName) {
+ StringBuffer strBuff = new StringBuffer();
+ strBuff.append("FileLogger{").append( adapterGroupName ).append("}");
+
+ return strBuff.toString();
+ }
+
+ public void removeLogger(String adapterGroupName) {
+ pool.remove( this.getLoggerName( adapterGroupName ));
+ }
+
+ public void stop(String adapterGroupName) {
+ // adapterGroupName의 session stop & clear
+ this.removeLogger( adapterGroupName );
+ }
+
+ public Logger getLogger( String adapterGroupName ) {
+ return getLoggerGroup( adapterGroupName );
+ }
+
+ public Logger getErrLogger() {
+ return getLoggerGroup( ERROR_LOGGER_NAME );
+ }
+
+ public Logger getLoggerGroup( String adapterGroupName ) {
+
+ Logger logger = (Logger) pool.get( this.getLoggerName( adapterGroupName ) );
+ if ( logger == null ) {
+ if ( DEFAULT_LOGGER_NAME.equals( adapterGroupName ) ) {
+ this.addLogger( adapterGroupName );
+ logger = (Logger) pool.get( this.getLoggerName( adapterGroupName ) );
+ } else {
+ //PropManager pmanager = PropManager.getInstance();
+ AdapterPropManager pmanager = AdapterPropManager.getInstance();
+ Properties loggerInfo= null;
+
+ try {
+ loggerInfo = pmanager.getProperties( getLoggerBase(adapterGroupName) );
+ } catch(Exception e) {
+ loggerInfo = null;
+ }
+
+ if ( loggerInfo == null ) {
+ logger = getLogger();
+ } else {
+ this.addLogger( adapterGroupName );
+ logger = (Logger) pool.get( this.getLoggerName( adapterGroupName ) );
+ }
+ }
+ }
+ return logger;
+ }
+
+ public Logger getLogger() {
+ //return Logger.getLogger( Logger.LOGGER_ADAPTER );
+ Logger logger = (Logger) pool.get( this.getLoggerName( this.DEFAULT_LOGGER_NAME ) );
+ if ( logger == null ) {
+ this.addLogger( DEFAULT_LOGGER_NAME );
+ logger = (Logger) pool.get( this.getLoggerName( DEFAULT_LOGGER_NAME ) );
+ }
+
+ return logger;
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/AclFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/AclFilter.java
new file mode 100644
index 0000000..57f7df0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/AclFilter.java
@@ -0,0 +1,83 @@
+package com.eactive.eai.adapter.socket2.filter.acl;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.util.IpUtil;
+
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class AclFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ private final Set aclList = new HashSet();
+
+ public AclFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ String[] allowList = context.getAclList().split(",");
+ for (int i=0; i= context.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | AclFilter | deny connection - [" + session.toString() + "]");
+ }
+
+ session.close();
+ }
+
+ private boolean isAllowed(IoSession session) {
+ SocketAddress remoteAddress = session.getRemoteAddress();
+
+ if (remoteAddress instanceof InetSocketAddress) {
+ byte[] remoteAddr = ((InetSocketAddress) remoteAddress).getAddress().getAddress();
+ String remoteIp = "";
+ for (int i=0; i 0) {
+ remoteIp += ".";
+ }
+ remoteIp += remoteAddr[i]&0xFF;
+ }
+ return IpUtil.isMatchIp(String.join(",", aclList), remoteIp);
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/BlockIpFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/BlockIpFilter.java
new file mode 100644
index 0000000..65cb0d0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/BlockIpFilter.java
@@ -0,0 +1,82 @@
+package com.eactive.eai.adapter.socket2.filter.acl;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.util.IpUtil;
+
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class BlockIpFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ private final Set blockIpList = new HashSet();
+
+ public BlockIpFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ String[] blockList = context.getBlockIpList().split(",");
+ for (int i=0; i= context.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | BlockIpFilter | "+context.getBlockIpList()+" | deny connection - [" + session.toString() + "]");
+ }
+ session.close();
+ }
+
+ private boolean isBlocked(IoSession session) {
+ SocketAddress remoteAddress = session.getRemoteAddress();
+
+ if (remoteAddress instanceof InetSocketAddress) {
+ byte[] remoteAddr = ((InetSocketAddress) remoteAddress).getAddress().getAddress();
+ String remoteIp = "";
+ for (int i=0; i 0) {
+ remoteIp += ".";
+ }
+ remoteIp += remoteAddr[i]&0xFF;
+ }
+ return IpUtil.isMatchIp(String.join(",", blockIpList), remoteIp);
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/L4SkipIpFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/L4SkipIpFilter.java
new file mode 100644
index 0000000..be9526b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/acl/L4SkipIpFilter.java
@@ -0,0 +1,93 @@
+package com.eactive.eai.adapter.socket2.filter.acl;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class L4SkipIpFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ private final Set l4SkipIpList = new HashSet();
+
+ public L4SkipIpFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ String[] l4SkipList = context.getL4SkipIpList().split(",");
+ for (int i=0; i= context.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | L4SkipFilter | "+context.getL4SkipIpList()+" | deny connection - [" + session.toString() + "]");
+ }
+// session.close();
+ }
+
+ private boolean isSkiped(IoSession session) {
+ SocketAddress remoteAddress = session.getRemoteAddress();
+
+ if (remoteAddress instanceof InetSocketAddress) {
+ for (String allow : l4SkipIpList) {
+ byte[] remoteAddr = ((InetSocketAddress) remoteAddress).getAddress().getAddress();
+ String remoteIp = "";
+ for (int i=0; i 0) {
+ remoteIp += ".";
+ }
+ remoteIp += remoteAddr[i]&0xFF;
+ }
+
+ if (allow.indexOf('*') == -1) {
+ if (allow.equals(remoteIp)) {
+ return true;
+ }
+ } else {
+ String allowRegexp = allow.replaceAll("\\*", "[0-9]+");
+ Matcher matcher = Pattern.compile(allowRegexp, Pattern.CASE_INSENSITIVE).matcher(remoteIp);
+ if (matcher.matches()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/datacontrol/DataControlFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/datacontrol/DataControlFilter.java
new file mode 100644
index 0000000..d16d06d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/datacontrol/DataControlFilter.java
@@ -0,0 +1,117 @@
+package com.eactive.eai.adapter.socket2.filter.datacontrol;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.StringUtil;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class DataControlFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ public DataControlFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ ByteMessage mm = null ;
+
+ /**
+ * datacontrol.rule
+ */
+ if (!"".equals(context.getDataControlRule())) {
+ Matcher matcher = Pattern.compile("\\[([ ]*[0-9]+)[ ]*,([ ]*[0-9]+)[ ]*\\][ ]*=[ ]*(.+)").matcher(context.getDataControlRule().trim());
+ if (matcher.find()) {
+ int offset = Integer.parseInt(matcher.group(1).trim());
+ int length = Integer.parseInt(matcher.group(2).trim());
+ String re = matcher.group(3).trim();
+
+
+ mm = (new ByteMessage())
+ .append(m.getBytes(0, offset))
+ .append(m.getBytes(offset + length));
+
+
+ } else {
+ throw new Exception(context.getAdapterName() + " | datacontrol.rule format is invalid : " + context.getDataControlRule());
+ }
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.messageReceived(session, mm);
+ }
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+ ByteMessage m = null;
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteBuffer) {
+ m = new ByteMessage((ByteBuffer) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ ByteMessage mm = null ;
+
+ /**
+ * datacontrol.rule
+ */
+ if (!"".equals(context.getDataControlRule())) {
+ Matcher matcher = Pattern.compile("\\[([ ]*[0-9]+)[ ]*,([ ]*[0-9]+)[ ]*\\][ ]*=[ ]*(.+)").matcher(context.getDataControlRule().trim());
+ if (matcher.find()) {
+ int offset = Integer.parseInt(matcher.group(1).trim());
+ int length = Integer.parseInt(matcher.group(2).trim());
+ String re = matcher.group(3).trim();
+ if (re != null && length != re.length()){
+ re = StringUtil.stringFormat(re, false, ' ', length);
+ }
+ if (re != null){
+ byte[] org = m.getBytes(offset,length);
+
+ if (re.equals(new String(org))){
+ //TODO JUN 같은 값이면 추가 안하는 걸로 했는데 바꿔야 할듯
+ mm = m;
+ }else{
+ mm = (new ByteMessage())
+ .append(m.getBytes(0, offset))
+ .append(re.getBytes())
+ .append(m.getBytes(offset));
+ }
+ }
+ } else {
+ throw new Exception(context.getAdapterName() + " | datacontrol.rule format is invalid : " + context.getDataControlRule());
+ }
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.filterWrite(session, new WriteRequest(mm, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/BlockingThreadPoolExecutor.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/BlockingThreadPoolExecutor.java
new file mode 100644
index 0000000..4c9af64
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/BlockingThreadPoolExecutor.java
@@ -0,0 +1,36 @@
+package com.eactive.eai.adapter.socket2.filter.executor;
+
+import java.util.concurrent.*;
+
+
+
+public class BlockingThreadPoolExecutor extends ThreadPoolExecutor {
+ private Semaphore semaphore;
+
+ public BlockingThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
+ TimeUnit unit, BlockingQueue workQueue) {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
+ this.semaphore = new Semaphore(maximumPoolSize);
+ }
+
+ @Override
+ public void execute(final Runnable task) {
+ try {
+ semaphore.acquire();
+ super.execute(new Runnable() {
+ public void run() {
+ try {
+ task.run();
+ } finally {
+ semaphore.release();
+ }
+ }
+ });
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } catch(RejectedExecutionException e) {
+ semaphore.release();
+ throw e;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/BoundedExecutorFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/BoundedExecutorFilter.java
new file mode 100644
index 0000000..a244b76
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/BoundedExecutorFilter.java
@@ -0,0 +1,318 @@
+package com.eactive.eai.adapter.socket2.filter.executor;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.ByteBufferUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+
+public class BoundedExecutorFilter extends IoFilterAdapter {
+ private final Logger logger ;
+ private final Executor executor;
+ private final Semaphore semaphore;
+ private ISocketAdapter adapter;
+ private SocketAdapterContext context;
+
+
+ // ----------------------------------------------------------------------
+ // added by bmchae
+ // ----------------------------------------------------------------------
+ public BoundedExecutorFilter(ISocketAdapter adapter, Executor executor) {
+ this.executor = executor;
+
+ //-------------------------------------------------------
+ // 2009.05.12
+ // Connect retry Error
+ // Outbound의 MaxThread 는 10으로 고정되고
+ // connection이 20일 경우
+ // 상대편의 Socket Server 가 재기동 되었을 경우
+ // retry 수행시
+ // this.semaphore 가 20 이 되므로 문제가 발생함
+ //-------------------------------------------------------
+// this.semaphore = new Semaphore(adapter.getContext().getMaxThread() + 10);
+ if(adapter.getContext().getMaxThread() > adapter.getContext().getMaxConnection()) {
+ this.semaphore = new Semaphore(adapter.getContext().getMaxThread() + 10);
+ }
+ else {
+ this.semaphore = new Semaphore(adapter.getContext().getMaxConnection() + 10);
+ }
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ }
+
+ /**
+ * Returns the underlying {@link Executor} instance this filter uses.
+ */
+ public Executor getExecutor() {
+ return executor;
+ }
+
+ private void fireEvent(NextFilter nextFilter, IoSession session, EventType type, Object data) {
+ Event event = new Event(type, nextFilter, data);
+ final SessionBuffer sessionBuffer = SessionBuffer.getSessionBuffer(session);
+
+ synchronized (sessionBuffer.eventQueue) {
+ sessionBuffer.eventQueue.add(event);
+ }
+
+ if (sessionBuffer.processingCompleted) {
+ sessionBuffer.processingCompleted = false;
+ if (logger.isDebugEnabled()) {
+ logger.debug("Launching thread for " + session.getRemoteAddress());
+ }
+
+ if (Thread.currentThread().getName().contains("IoProcessor")||Thread.currentThread().getName().contains("DatagramAcceptor")) {
+ try {
+ if (semaphore.tryAcquire(context.getTimeout(), TimeUnit.SECONDS)) {
+ executor.execute(new Runnable() {
+ public void run() {
+ try {
+ (new ProcessEventsRunnable(context, sessionBuffer)).run();
+ } finally {
+ semaphore.release();
+ }
+ }
+ });
+ } else {
+ throw new RuntimeException("timeout (" + context.getTimeout() + ") occurred when allocate thread");
+ }
+ } catch(InterruptedException e) {
+ throw new RuntimeException("thread interrupted when acquire semaphore", e);
+ } catch(RejectedExecutionException e) {
+ semaphore.release();
+ throw new RuntimeException("cannot allocate thread -> increase thread pool size (max.threads)", e);
+ }
+ } else {
+ (new ProcessEventsRunnable(context, sessionBuffer)).run();
+ }
+ } else { //if (type==EventType.CLOSED || type==EventType.EXCEPTION) {
+ //--------------------------------------------------------------
+ // added by bmchae
+ // client && sync && non-permanent 일 경우 CLOSED/EXCEPTION event 무시
+ //--------------------------------------------------------------
+ if (context.isClient()
+ && context.isSync()
+ && !context.isPermanent()
+ //&& context.isBlocking()
+ && (type.equals(EventType.CLOSED)
+ || (type.equals(EventType.EXCEPTION) && data instanceof java.io.IOException))) {
+ return;
+ }
+
+ if (Thread.currentThread().getName().contains("IoProcessor")||Thread.currentThread().getName().contains("DatagramAcceptor")) {
+ try {
+ if (semaphore.tryAcquire(context.getTimeout(), TimeUnit.SECONDS)) {
+ executor.execute(new Runnable() {
+ public void run() {
+ try {
+ (new ProcessEventsRunnable(context, sessionBuffer)).run();
+ } finally {
+ semaphore.release();
+ }
+ }
+ });
+ } else {
+ throw new RuntimeException("timeout (" + context.getTimeout() + ") occurred when allocate thread");
+ }
+ } catch(InterruptedException e) {
+ throw new RuntimeException("thread interrupted when acquire semaphore", e);
+ } catch(RejectedExecutionException e) {
+ semaphore.release();
+ throw new RuntimeException("cannot allocate thread -> increase thread pool size (max.threads)", e);
+ }
+ } else {
+ (new ProcessEventsRunnable(context, sessionBuffer)).run();
+ }
+ }
+ }
+
+ private static class SessionBuffer {
+ private static final String KEY = SessionBuffer.class.getName() + ".KEY";
+
+ private static SessionBuffer getSessionBuffer(IoSession session) {
+ synchronized (session) {
+ SessionBuffer sessionBuffer = (SessionBuffer) session.getAttribute(KEY);
+ if (sessionBuffer == null) {
+ sessionBuffer = new SessionBuffer(session);
+ session.setAttribute(KEY, sessionBuffer);
+ }
+ return sessionBuffer;
+ }
+ }
+
+ private final IoSession session;
+
+ private final List eventQueue = new ArrayList();
+
+ private boolean processingCompleted = true;
+
+ private SessionBuffer(IoSession session) {
+ this.session = session;
+ }
+ }
+
+ protected static class EventType {
+ public static final EventType OPENED = new EventType("OPENED");
+ public static final EventType CLOSED = new EventType("CLOSED");
+ public static final EventType READ = new EventType("READ");
+ public static final EventType WRITTEN = new EventType("WRITTEN");
+ public static final EventType RECEIVED = new EventType("RECEIVED");
+ public static final EventType SENT = new EventType("SENT");
+ public static final EventType IDLE = new EventType("IDLE");
+ public static final EventType EXCEPTION = new EventType("EXCEPTION");
+
+ private final String value;
+
+ private EventType(String value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return value;
+ }
+ }
+
+ protected static class Event {
+ private final EventType type;
+
+ private final NextFilter nextFilter;
+
+ private final Object data;
+
+ Event(EventType type, NextFilter nextFilter, Object data) {
+ this.type = type;
+ this.nextFilter = nextFilter;
+ this.data = data;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public NextFilter getNextFilter() {
+ return nextFilter;
+ }
+
+ public EventType getType() {
+ return type;
+ }
+ }
+
+ public void sessionCreated(NextFilter nextFilter, IoSession session) {
+ nextFilter.sessionCreated(session);
+ }
+
+ public void sessionOpened(NextFilter nextFilter, IoSession session) {
+ fireEvent(nextFilter, session, EventType.OPENED, null);
+ }
+
+ public void sessionClosed(NextFilter nextFilter, IoSession session) {
+ fireEvent(nextFilter, session, EventType.CLOSED, null);
+ }
+
+ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) {
+ fireEvent(nextFilter, session, EventType.IDLE, status);
+ }
+
+ public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) {
+ fireEvent(nextFilter, session, EventType.EXCEPTION, cause);
+ }
+
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
+ ByteBufferUtil.acquireIfPossible(message);
+ fireEvent(nextFilter, session, EventType.RECEIVED, message);
+ }
+
+ public void messageSent(NextFilter nextFilter, IoSession session, Object message) {
+ ByteBufferUtil.acquireIfPossible(message);
+ fireEvent(nextFilter, session, EventType.SENT, message);
+ }
+
+ protected void processEvent(NextFilter nextFilter, IoSession session, EventType type,
+ Object data) {
+ //----------------------------------------------------------------------
+ // added by bmchae
+ //----------------------------------------------------------------------
+ adapter.getThreadMap().put(Thread.currentThread().getName(), Thread.currentThread());
+ try {
+ if (type.equals(EventType.RECEIVED)) {
+ nextFilter.messageReceived(session, data);
+ ByteBufferUtil.releaseIfPossible(data);
+ } else if (type.equals(EventType.SENT)) {
+ nextFilter.messageSent(session, data);
+ ByteBufferUtil.releaseIfPossible(data);
+ } else if (type.equals(EventType.EXCEPTION)) {
+ nextFilter.exceptionCaught(session, (Throwable) data);
+ } else if (type.equals(EventType.IDLE)) {
+ nextFilter.sessionIdle(session, (IdleStatus) data);
+ } else if (type.equals(EventType.OPENED)) {
+ nextFilter.sessionOpened(session);
+ } else if (type.equals(EventType.CLOSED)) {
+ nextFilter.sessionClosed(session);
+ }
+ } finally {
+ adapter.getThreadMap().remove(Thread.currentThread().getName());
+ }
+ }
+
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) {
+ nextFilter.filterWrite(session, writeRequest);
+ }
+
+ public void filterClose(NextFilter nextFilter, IoSession session) throws Exception {
+ nextFilter.filterClose(session);
+ }
+
+ private class ProcessEventsRunnable implements Runnable {
+ private final SessionBuffer sessionBuffer;
+ private SocketAdapterContext context;
+
+ ProcessEventsRunnable(SocketAdapterContext context, SessionBuffer sessionBuffer) {
+ this.context = context;
+ this.sessionBuffer = sessionBuffer;
+ }
+
+ public void run() {
+ //------------------------------------------------------------------
+ // added by bmchae
+ //------------------------------------------------------------------
+ if (Thread.currentThread().getName().startsWith("pool-") && context != null) {
+ Thread.currentThread().setName(context.getAdapterName() + "-" + Thread.currentThread().getName());
+ }
+
+ while (!Thread.currentThread().isInterrupted()) {
+ Event event;
+
+ synchronized (sessionBuffer.eventQueue) {
+ if (sessionBuffer.eventQueue.isEmpty()) {
+ sessionBuffer.processingCompleted = true;
+ break;
+ }
+
+ event = (Event) sessionBuffer.eventQueue.remove(0);
+ }
+
+ processEvent(event.getNextFilter(), sessionBuffer.session, event.getType(), event
+ .getData());
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Exiting since queue is empty for "
+ + sessionBuffer.session.getRemoteAddress());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/ExecutorFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/ExecutorFilter.java
new file mode 100644
index 0000000..a8829bc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/executor/ExecutorFilter.java
@@ -0,0 +1,299 @@
+package com.eactive.eai.adapter.socket2.filter.executor;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.ByteBufferUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+
+public class ExecutorFilter extends IoFilterAdapter {
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+ private final Executor executor;
+ private ISocketAdapter adapter;
+ private SocketAdapterContext context;
+
+ /**
+ * Creates a new instace with the default thread pool implementation (
+ *
+ * new ThreadPoolExecutor(16, 16, 60, TimeUnit.SECONDS, new LinkedBlockingQueue() )
+ * ).
+ */
+ /*
+ public ExecutorFilter() {
+ this(new ThreadPoolExecutor(16, 16, 60, TimeUnit.SECONDS, new LinkedBlockingQueue()));
+ }
+ */
+
+ /**
+ * Creates a new instance with the specified executor .
+ */
+ /*
+ public ExecutorFilter(Executor executor) {
+ if (executor == null) {
+ throw new NullPointerException("executor");
+ }
+
+ this.executor = executor;
+ }
+ */
+
+ /**
+ * Creates a new instance with the specified executor .
+ */
+ // ----------------------------------------------------------------------
+ // added by bmchae
+ // ----------------------------------------------------------------------
+ public ExecutorFilter(ISocketAdapter adapter, Executor executor) {
+ this.executor = executor;
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+ }
+
+ /**
+ * Returns the underlying {@link Executor} instance this filter uses.
+ */
+ public Executor getExecutor() {
+ return executor;
+ }
+
+ private void fireEvent(NextFilter nextFilter, IoSession session, EventType type, Object data) {
+ Event event = new Event(type, nextFilter, data);
+ SessionBuffer buf = SessionBuffer.getSessionBuffer(session);
+
+ synchronized (buf.eventQueue) {
+ buf.eventQueue.add(event);
+ if (buf.processingCompleted) {
+ buf.processingCompleted = false;
+ if (logger.isDebugEnabled()) {
+ logger.debug("Launching thread for " + session.getRemoteAddress());
+ }
+
+ try {
+ executor.execute(new ProcessEventsRunnable(context, buf));
+ } catch(RejectedExecutionException e) {
+ throw new RuntimeException("cannot allocate thread -> increase thread pool size (max.threads)", e);
+ }
+ } else { //if (type==EventType.CLOSED || type==EventType.EXCEPTION) {
+ //--------------------------------------------------------------
+ // added by bmchae
+ //--------------------------------------------------------------
+ //--------------------------------------------------------------
+ // client && sync && non-permanent 일 경우 CLOSED/EXCEPTION event 무시
+ //--------------------------------------------------------------
+
+// StringBuffer sb = new StringBuffer();
+// sb.append("EventQueue=[");
+// for (Iterator iter = buf.eventQueue.iterator(); iter.hasNext();) {
+// Event ev = (Event) iter.next();
+// sb.append(ev.getType().toString() + ",");
+// }
+// sb.append("]");
+// adapter.addRecentError(context.getAdapterName() + " | " +sb.toString());
+// logger.info(context.getAdapterName() + " | " +sb.toString());
+// System.out.println("######################### " + type + " | " + data);
+
+ if (context.isClient()
+ && context.isSync()
+ && !context.isPermanent()
+ //&& context.isBlocking()
+ && (type.equals(EventType.CLOSED)
+ || (type.equals(EventType.EXCEPTION) && data instanceof java.io.IOException))) {
+ return;
+ }
+
+ try {
+ executor.execute(new ProcessEventsRunnable(context, buf));
+ } catch(RejectedExecutionException e) {
+ throw new RuntimeException("cannot allocate thread -> increase thread pool size (max.threads)", e);
+ }
+ }
+ }
+ }
+
+ private static class SessionBuffer {
+ private static final String KEY = SessionBuffer.class.getName() + ".KEY";
+
+ private static SessionBuffer getSessionBuffer(IoSession session) {
+ synchronized (session) {
+ SessionBuffer buf = (SessionBuffer) session.getAttribute(KEY);
+ if (buf == null) {
+ buf = new SessionBuffer(session);
+ session.setAttribute(KEY, buf);
+ }
+ return buf;
+ }
+ }
+
+ private final IoSession session;
+
+ private final List eventQueue = new ArrayList();
+
+ private boolean processingCompleted = true;
+
+ private SessionBuffer(IoSession session) {
+ this.session = session;
+ }
+ }
+
+ protected static class EventType {
+ public static final EventType OPENED = new EventType("OPENED");
+ public static final EventType CLOSED = new EventType("CLOSED");
+ public static final EventType READ = new EventType("READ");
+ public static final EventType WRITTEN = new EventType("WRITTEN");
+ public static final EventType RECEIVED = new EventType("RECEIVED");
+ public static final EventType SENT = new EventType("SENT");
+ public static final EventType IDLE = new EventType("IDLE");
+ public static final EventType EXCEPTION = new EventType("EXCEPTION");
+
+ private final String value;
+
+ private EventType(String value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return value;
+ }
+ }
+
+ protected static class Event {
+ private final EventType type;
+
+ private final NextFilter nextFilter;
+
+ private final Object data;
+
+ Event(EventType type, NextFilter nextFilter, Object data) {
+ this.type = type;
+ this.nextFilter = nextFilter;
+ this.data = data;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public NextFilter getNextFilter() {
+ return nextFilter;
+ }
+
+ public EventType getType() {
+ return type;
+ }
+ }
+
+ public void sessionCreated(NextFilter nextFilter, IoSession session) {
+ nextFilter.sessionCreated(session);
+ }
+
+ public void sessionOpened(NextFilter nextFilter, IoSession session) {
+ fireEvent(nextFilter, session, EventType.OPENED, null);
+ }
+
+ public void sessionClosed(NextFilter nextFilter, IoSession session) {
+ fireEvent(nextFilter, session, EventType.CLOSED, null);
+ }
+
+ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) {
+ fireEvent(nextFilter, session, EventType.IDLE, status);
+ }
+
+ public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) {
+ fireEvent(nextFilter, session, EventType.EXCEPTION, cause);
+ }
+
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
+ ByteBufferUtil.acquireIfPossible(message);
+ fireEvent(nextFilter, session, EventType.RECEIVED, message);
+ }
+
+ public void messageSent(NextFilter nextFilter, IoSession session, Object message) {
+ ByteBufferUtil.acquireIfPossible(message);
+ fireEvent(nextFilter, session, EventType.SENT, message);
+ }
+
+ protected void processEvent(NextFilter nextFilter, IoSession session, EventType type,
+ Object data) {
+ //----------------------------------------------------------------------
+ // added by bmchae
+ //----------------------------------------------------------------------
+ adapter.getThreadMap().put(Thread.currentThread().getName(), Thread.currentThread());
+ try {
+ if (type.equals(EventType.RECEIVED)) {
+ nextFilter.messageReceived(session, data);
+ ByteBufferUtil.releaseIfPossible(data);
+ } else if (type.equals(EventType.SENT)) {
+ nextFilter.messageSent(session, data);
+ ByteBufferUtil.releaseIfPossible(data);
+ } else if (type.equals(EventType.EXCEPTION)) {
+ nextFilter.exceptionCaught(session, (Throwable) data);
+ } else if (type.equals(EventType.IDLE)) {
+ nextFilter.sessionIdle(session, (IdleStatus) data);
+ } else if (type.equals(EventType.OPENED)) {
+ nextFilter.sessionOpened(session);
+ } else if (type.equals(EventType.CLOSED)) {
+ nextFilter.sessionClosed(session);
+ }
+ } finally {
+ adapter.getThreadMap().remove(Thread.currentThread().getName());
+ }
+ }
+
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) {
+ nextFilter.filterWrite(session, writeRequest);
+ }
+
+ public void filterClose(NextFilter nextFilter, IoSession session) throws Exception {
+ nextFilter.filterClose(session);
+ }
+
+ private class ProcessEventsRunnable implements Runnable {
+ private final SessionBuffer buffer;
+ private SocketAdapterContext context;
+
+ ProcessEventsRunnable(SocketAdapterContext context, SessionBuffer buffer) {
+ this.context = context;
+ this.buffer = buffer;
+ }
+
+ public void run() {
+ //------------------------------------------------------------------
+ // added by bmchae
+ //------------------------------------------------------------------
+ if (Thread.currentThread().getName().startsWith("pool-") && context != null) {
+ Thread.currentThread().setName(
+ context.getAdapterName() + "-" + Thread.currentThread().getName());
+ }
+
+ while (true) {
+ Event event;
+
+ synchronized (buffer.eventQueue) {
+ if (buffer.eventQueue.isEmpty()) {
+ buffer.processingCompleted = true;
+ break;
+ }
+
+ event = (Event) buffer.eventQueue.remove(0);
+ }
+
+ processEvent(event.getNextFilter(), buffer.session, event.getType(), event
+ .getData());
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Exiting since queue is empty for "
+ + buffer.session.getRemoteAddress());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/flowcontrol/FlowControlFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/flowcontrol/FlowControlFilter.java
new file mode 100644
index 0000000..e7b1490
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/flowcontrol/FlowControlFilter.java
@@ -0,0 +1,18 @@
+package com.eactive.eai.adapter.socket2.filter.flowcontrol;
+
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+
+/**
+ * TODO : snmp 와 연동...
+ */
+public class FlowControlFilter extends IoFilterAdapter {
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ // Some logic here...
+ nextFilter.messageReceived(session, message);
+ // Some other logic here...
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/flowcontrol/ReadThrottleFilterBuilder.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/flowcontrol/ReadThrottleFilterBuilder.java
new file mode 100644
index 0000000..d0df5c7
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/flowcontrol/ReadThrottleFilterBuilder.java
@@ -0,0 +1,119 @@
+package com.eactive.eai.adapter.socket2.filter.flowcontrol;
+
+import com.eactive.eai.adapter.socket2.filter.executor.BoundedExecutorFilter;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import org.apache.mina.common.DefaultIoFilterChainBuilder;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoFilterChain.Entry;
+import org.apache.mina.common.IoSession;
+
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * IoFilterChain chain = config.getFilterChain();
+ * ReadThrottleFilterBuilder filter = new ReadThrottleFilterBuilder();
+ * filter.attach(chain);
+ */
+
+public class ReadThrottleFilterBuilder {
+ public static final String COUNTER = ReadThrottleFilterBuilder.class.getName() + ".counter";
+
+ public static final String SUSPENDED_READS = ReadThrottleFilterBuilder.class.getName() + ".suspendedReads";
+
+ private volatile int maximumConnectionBufferSize = 100; // 1024 * 1024; // 1mb
+
+ public void setMaximumConnectionBufferSize(int maximumConnectionBufferSize) {
+ this.maximumConnectionBufferSize = maximumConnectionBufferSize;
+ }
+
+ public void attach(IoFilterChain chain) {
+ String name = getThreadPoolFilterEntryName(chain.getAll());
+
+ chain.addBefore(name, getClass().getName() + ".add", new Add());
+ chain.addAfter(name, getClass().getName() + ".release", new Release());
+ }
+
+ public void attach(DefaultIoFilterChainBuilder builder) {
+ String name = getThreadPoolFilterEntryName(builder.getAll());
+
+ builder.addBefore(name, getClass().getName() + ".add", new Add());
+ builder.addAfter(name, getClass().getName() + ".release", new Release());
+ }
+
+ private String getThreadPoolFilterEntryName(List entries) {
+ Iterator i = entries.iterator();
+
+ while (i.hasNext()) {
+ Entry entry = i.next();
+
+ if (entry.getFilter().getClass().isAssignableFrom(BoundedExecutorFilter.class)) {
+ return entry.getName();
+ }
+ }
+
+ throw new IllegalStateException("Chain does not contain a ExecutorFilter");
+ }
+
+ private void add(IoSession session, int size) {
+ synchronized (session) {
+ int counter = getCounter(session);
+ counter = counter + size;
+ session.setAttribute(COUNTER, new Integer(counter));
+
+ if (counter >= maximumConnectionBufferSize && session.getTrafficMask().isReadable()) {
+//System.out.println("----- session -> suspendRead() : ");
+ session.suspendRead();
+ session.setAttribute(SUSPENDED_READS);
+ }
+ }
+ }
+
+ private void release(IoSession session, int size) {
+ synchronized (session) {
+ int counter = Math.max(0, getCounter(session) - size);
+ session.setAttribute(COUNTER, new Integer(counter));
+
+ if (counter < maximumConnectionBufferSize && isSuspendedReads(session)) {
+//System.out.println("+++++ session -> resumeRead() : ");
+ session.resumeRead();
+ session.removeAttribute(SUSPENDED_READS);
+ }
+
+ }
+ }
+
+ private boolean isSuspendedReads(IoSession session) {
+ Boolean flag = (Boolean) session.getAttribute(SUSPENDED_READS);
+ return null != flag && flag.booleanValue();
+ }
+
+ private int getCounter(IoSession session) {
+ Integer i = (Integer) session.getAttribute(COUNTER);
+ return null == i ? 0 : i.intValue();
+ }
+
+ private class Add extends IoFilterAdapter {
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message)
+ throws Exception {
+ if (message instanceof ByteMessage) {
+ add(session, ((ByteMessage) message).size());
+ }
+
+ nextFilter.messageReceived(session, message);
+ }
+ }
+
+ private class Release extends IoFilterAdapter {
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message)
+ throws Exception {
+ if (message instanceof ByteMessage) {
+ release(session, ((ByteMessage) message).size());
+ }
+
+ nextFilter.messageReceived(session, message);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/initmsgshake/InitMsgFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/initmsgshake/InitMsgFilter.java
new file mode 100644
index 0000000..b2d9485
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/initmsgshake/InitMsgFilter.java
@@ -0,0 +1,167 @@
+package com.eactive.eai.adapter.socket2.filter.initmsgshake;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.concurrent.ExecutorService;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class InitMsgFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ private static final String FILTER_STATE_KEY = InitMsgFilter.class.getName() + ".STATE";
+ private static class FilterState {
+ SimpleFuture initMsgResponseFuture = new SimpleFuture();
+ }
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+ protected ExecutorService executor;
+ private static String endHandshake="N";
+
+ public InitMsgFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+ nextFilter.sessionCreated(session);
+ }
+
+ @Override
+ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState != null && filterState.initMsgResponseFuture != null) {
+ filterState.initMsgResponseFuture.set(new Exception("session closed by peer"));
+ }
+ endHandshake="N";
+ nextFilter.sessionClosed(session);
+ }
+
+ @Override
+ public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState != null && filterState.initMsgResponseFuture != null) {
+ filterState.initMsgResponseFuture.set(cause);
+ }
+ endHandshake="N";
+ nextFilter.exceptionCaught(session, cause);
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ if (context.isInitMsgSender() && context.isPermanent() && context.isInitMsgUse()){
+ sendInitMsgRequest(session);
+ }
+ endHandshake="N";
+ nextFilter.sessionOpened(session);
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+// FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (endHandshake.equals("N") ){
+ endHandshake = "Y";
+ } else {
+ nextFilter.messageReceived(session, message);
+ }
+ }
+
+ private void sendInitMsgRequest(IoSession session) {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ final byte[] initMsgRequest = getInitMsgRequestFormatted();
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentSend(session, "InitMsgFilter | session idle -> initMsg request - "
+ + CommonLib.hexDump(initMsgRequest, true, context));
+ logger.debug(context.getAdapterName() + " | InitMsgFilter | session idle -> initMsg request - "
+ + CommonLib.hexDump(initMsgRequest, true, context));
+ }
+ IoSession sess = adapter.getSessionPool().acquire(session);
+ try {
+ if (filterState.initMsgResponseFuture == null) {
+ filterState.initMsgResponseFuture = new SimpleFuture();
+ }
+ final IoSession s = session;
+// final FilterState hState = filterState;
+ if (Thread.currentThread().getName().startsWith("pool-")) {
+ Thread.currentThread().setName(context.getAdapterName() + "-InitMsgFilter-" + Thread.currentThread().getName());
+ }
+ internalSendMessage(s, initMsgRequest);
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | InitMsgFilter | error when send INIT_MSG request - " + e.getMessage(), e);
+ logger.warn(context.getAdapterName() + " | InitMsgFilter | error when send INIT_MSG request - " + e.getMessage());
+ } finally {
+ if (sess != null) {
+ adapter.getSessionPool().release(sess);
+ }
+ }
+ }
+
+ protected void internalSendMessage(IoSession session, Object message) throws Exception {
+ ByteMessage m = null;
+
+ if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else {
+ throw new Exception("Unknown data format");
+ }
+// WriteFuture future = session.write(message);
+ session.write(message);
+ }
+
+ protected byte[] getInitMsgRequestFormatted() {
+ String message = context.getInitMsgRequest();
+ //Polling ·ÎÁ÷ ¼öÁ¤ 2017.05 KSH
+ String str[] = message.split("%d");
+ String endMsg = "";
+ for(int i=0; i= context.TRACE_LEVEL_TRACE && !"HTTP".equals(context.getProtocol())) {
+ logger.debug(context.getAdapterName() + " | ConnectionLimitFilter | session created : " + session);
+ }
+ */
+ //Session 오픈 이전에 message를 수신하지 않도록 한다.
+ session.suspendRead();
+
+ SessionPool sessionPool = adapter.getSessionPool();
+
+ /**
+ * max connection 제한
+ */
+ synchronized(this) {
+ if (context.getMaxConnection() > 0) {
+ /**
+ * TODO : 아래 원인을 다시 한번 체크해 볼 것
+ * clear invalid ('CLOSING') connections - avoid bug
+ */
+ for (Iterator iter = sessionPool.iterator(); iter.hasNext(); ) {
+ IoSession s = (IoSession) iter.next();
+ if (s != null && s.isClosing()) {
+ s.close();
+ sessionPool.remove(s);
+ }
+ }
+
+ /**
+ * curr connections >= max.connection 이라면, 아래 2가지 중 한 작업
+ */
+ if (sessionPool.size() >= context.getMaxConnection()) {
+ /**
+ * [1] close existing 'YOUNGEST' connections
+ */
+ if (context.getCloseExistingConnection()) {
+ if (sessionPool.size() > 0) {
+ IoSession victim = sessionPool.acquireYoungest();
+
+ if (victim != null) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(context.getAdapterName() + " | ConnectionLimitFilter | ");
+ sb.append("max connection(" + context.getMaxConnection() + ") exceeded ");
+ sb.append("-> remove 'YOUNGEST' victim connection in pool - [" + victim.toString() + "]");
+ sb.append(", put new connection in pool - [" + session + "]");
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_INFO) {
+ logger.info(sb.toString());
+ }
+
+ adapter.addRecentErrorOnly(sb.toString() + "\n" + dumpSessionPool());
+
+ victim.close();
+ sessionPool.remove(victim);
+ } else {
+ sessionPool.shutdown();
+ }
+ }
+ /**
+ * [2] close new connections
+ */
+ } else {
+ StringBuffer sb = new StringBuffer();
+ sb.append(context.getAdapterName() + " | ConnectionLimitFilter | ");
+ sb.append("max connection(" + sessionPool.size() + "/" + context.getMaxConnection() + ") exceeded ");
+ sb.append("-> close 'new' session - [" + session.toString() + "]");
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_INFO) {
+ logger.info(sb.toString());
+ }
+
+ adapter.addRecentErrorOnly(sb.toString() + "\n" + dumpSessionPool());
+
+ sessionPool.remove(session);
+ session.close();
+
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * remote ip 당 connection 갯수 제한 (SERVER only)
+ */
+ synchronized (this) {
+ if (context.isServer() && context.getConnLimitPerIp() > 0) {
+ String remoteIp = ((InetSocketAddress) session.getRemoteAddress()).getHostName();
+ Integer remotePort = ((InetSocketAddress) session.getRemoteAddress()).getPort();
+
+ if (ipLimitTable.get(remoteIp) == null) {
+ ipLimitTable.put(remoteIp, new ConcurrentHashMap());
+ }
+
+ /**
+ * TODO : 아래 원인을 다시 한번 체크해 볼 것
+ * clear invalid ('CLOSING') connections - avoid bug
+ */
+ ConcurrentHashMap map = (ConcurrentHashMap) ipLimitTable.get(remoteIp);
+ for (Iterator iter = map.values().iterator(); iter.hasNext(); ) {
+ IoSession s = (IoSession) iter.next();
+ if (s != null && s.isClosing()) {
+ s.close();
+ map.remove(((InetSocketAddress) s.getRemoteAddress()).getPort());
+ }
+ }
+
+ if (((ConcurrentHashMap) ipLimitTable.get(remoteIp)).size() < context.getConnLimitPerIp()) {
+ ((ConcurrentHashMap) ipLimitTable.get(remoteIp)).put(remotePort, session);
+ } else {
+ /**
+ * [1] close existing 'OLDEST' connections
+ * 2009.09.10 권세환대리 요청
+ * negative(-) 옵션을 준 상태에서 세션이 Full 상태 일때, 가장 오래 된 세션을 끊고 새로운 세션을 연결한다.
+ */
+ if (context.getCloseExistingConnectionPerIpLimit()) {
+ if (sessionPool.size() > 0) {
+ IoSession victim = sessionPool.acquire();
+
+ if (victim != null) {
+ Integer victimPort = ((InetSocketAddress) victim.getRemoteAddress()).getPort();
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(context.getAdapterName() + " | ConnectionLimitFilter | ");
+ sb.append("connection.limit.per.ip(" + context.getConnLimitPerIp() + ") exceeded ");
+ sb.append("-> remove 'OLDEST' victim connection in pool - [" + victim.toString() + "]");
+ sb.append(", put new connection in pool - [" + session + "]");
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_INFO) {
+ logger.info(sb.toString());
+ }
+
+ adapter.addRecentErrorOnly(sb.toString() + "\n" + dumpSessionPool());
+
+ victim.close();
+ sessionPool.remove(victim);
+
+ ((ConcurrentHashMap) ipLimitTable.get(remoteIp)).remove(victimPort);
+ ((ConcurrentHashMap) ipLimitTable.get(remoteIp)).put(remotePort, session);
+ } else {
+ sessionPool.shutdown();
+ }
+ }
+ }
+ /**
+ * [2] close new connections
+ */
+ else {
+ StringBuffer sb = new StringBuffer();
+ sb.append(context.getAdapterName() + " | ConnectionLimitFilter | ");
+ sb.append("session created. : but connection.limit.per.ip(" + context.getConnLimitPerIp() + ") exceeded ");
+ sb.append("-> close 'new' session. (" + session + ")");
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_INFO) {
+ logger.info(sb.toString());
+ }
+
+ adapter.addRecentErrorOnly(sb.toString() + "\n" +
+ dumpSessionPool() +
+ dumpIpLimitTable());
+
+ sessionPool.remove(session);
+ session.close();
+
+ return;
+ }
+ }
+ }
+ }
+
+ //Connection Limit 를 체크한후 Message 를 Read 한다.
+ session.resumeRead();
+
+ nextFilter.sessionOpened(session);
+ }
+
+
+ @Override
+ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
+ /*
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE && !"HTTP".equals(context.getProtocol())) {
+ logger.debug(context.getAdapterName() + " | ConnectionLimitFilter | session closed : " + session);
+ }
+ */
+
+ /**
+ * remote ip 당 connection 갯수 제한 (SERVER only)
+ */
+ synchronized (this) {
+ if (context.isServer() && context.getConnLimitPerIp() > 0) {
+ String remoteIp = ((InetSocketAddress) session.getRemoteAddress()).getHostName();
+ Integer remotePort = ((InetSocketAddress) session.getRemoteAddress()).getPort();
+
+ if (ipLimitTable.get(remoteIp) == null) {
+ ipLimitTable.put(remoteIp, new ConcurrentHashMap());
+ }
+
+ ((ConcurrentHashMap) ipLimitTable.get(remoteIp)).remove(remotePort);
+ }
+ }
+
+ nextFilter.sessionClosed(session);
+ }
+
+
+ private String dumpSessionPool() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("SessionPool Dump : ");
+ sb.append("\n");
+ for (Iterator i = adapter.getSessionPool().iterator() ; i.hasNext(); ) {
+ IoSession session = (IoSession) i.next();
+ sb.append(" " + sessionInfo(session) + "\n");
+ }
+ sb.append(" ");
+
+ sb.append("");
+ for (Iterator i = adapter.getSessionPool().checkedOutIterator() ; i.hasNext(); ) {
+ IoSession session = (IoSession) i.next();
+ sb.append(" " + sessionInfo(session) + "\n");
+ }
+ sb.append(" ");
+
+ return sb.toString();
+ }
+
+
+ private String dumpIpLimitTable() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("IpLimitTable Dump : ");
+ sb.append("\n");
+ for (Iterator iter = ipLimitTable.keySet().iterator() ; iter.hasNext(); ) {
+ String ip = iter.next();
+ ConcurrentHashMap map = (ConcurrentHashMap) ipLimitTable.get(ip);
+ sb.append(String.format(" * %s (%d)\n", ip, map.size()));
+ for (Iterator iter2 = map.values().iterator() ; iter2.hasNext(); ) {
+ IoSession session = (IoSession) iter2.next();
+ sb.append(" " + sessionInfo(session) + "\n");
+ }
+ }
+ sb.append(" ");
+ return sb.toString();
+ }
+
+
+ private String sessionInfo(IoSession session) {
+ StringBuffer sb = new StringBuffer();
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");;
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()));
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/polling/HexPollingFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/polling/HexPollingFilter.java
new file mode 100644
index 0000000..8e83c53
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/polling/HexPollingFilter.java
@@ -0,0 +1,295 @@
+package com.eactive.eai.adapter.socket2.filter.polling;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.concurrent.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class HexPollingFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ private static final String FILTER_STATE_KEY = HexPollingFilter.class.getName() + ".STATE";
+
+ private static class FilterState {
+ SimpleFuture pollingResponseFuture = new SimpleFuture();
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+ protected ExecutorService executor;
+
+
+ public HexPollingFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+ this.executor = Executors.newCachedThreadPool();
+ ((ThreadPoolExecutor) this.executor).setKeepAliveTime(1L, TimeUnit.SECONDS);
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ //SimpleFuture handshakeFuture = new SimpleFuture();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ nextFilter.sessionCreated(session);
+ }
+
+
+ @Override
+ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState != null && filterState.pollingResponseFuture != null) {
+ filterState.pollingResponseFuture.set(new Exception("session closed by peer"));
+ }
+
+ nextFilter.sessionClosed(session);
+ }
+
+
+ @Override
+ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
+ if (context.isPollingSender() && context.isPermanent() && context.isPollingUse()
+ && System.currentTimeMillis()-session.getLastIoTime() > (context.getTimeout() + 1) * 1000L
+ && System.currentTimeMillis()-session.getLastIoTime() < (context.getPollingTimeout() + 10) * 1000L) {
+ sendPollingRequest(session);
+ } else {
+ nextFilter.sessionIdle(session, status);
+ }
+ }
+
+
+ @Override
+ public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState != null && filterState.pollingResponseFuture != null) {
+ filterState.pollingResponseFuture.set(cause);
+ }
+ nextFilter.exceptionCaught(session, cause);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ ByteMessage m = (ByteMessage) message;
+
+ if (recvPolling(session, m, filterState)) {
+ if (filterState.pollingResponseFuture == null) {
+ filterState.pollingResponseFuture = new SimpleFuture();
+ }
+ filterState.pollingResponseFuture.set(m);
+ } else {
+ nextFilter.messageReceived(session, message);
+ }
+ }
+
+
+ private void sendPollingRequest(IoSession session) {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ /**
+ * send polling request
+ */
+ final byte[] pollingRequest = getPollingRequestFormatted();
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentSend(session, "HexPollingFilter | session idle -> polling request - "
+ + CommonLib.hexDump(pollingRequest, true, context));
+ logger.debug(context.getAdapterName() + " | HexPollingFilter | session idle -> polling request - "
+ + CommonLib.hexDump(pollingRequest, true, context));
+ }
+
+ IoSession sess = adapter.getSessionPool().acquire(session);
+
+ try {
+ if (filterState.pollingResponseFuture == null) {
+ filterState.pollingResponseFuture = new SimpleFuture();
+ }
+
+ final IoSession s = sess;
+ final FilterState hState = filterState;
+
+ FutureTask futureTask = new FutureTask(new Callable() {
+ public byte[] call() {
+ if (Thread.currentThread().getName().startsWith("pool-")) {
+ Thread.currentThread().setName(context.getAdapterName() + "-HexPollingFilter-" + Thread.currentThread().getName());
+ }
+
+ try {
+ internalSendMessage(s, pollingRequest);
+
+ /**
+ * oneway 이면 기다리지 않는다.
+ */
+ if (adapter.getContext().isPollingOneway()) {
+ return null;
+ }
+
+ if (hState.pollingResponseFuture != null) {
+ Object result = hState.pollingResponseFuture.join(context.getTimeout() * 1000L);
+ if (result instanceof ByteMessage) {
+ return ((ByteMessage) result).getBytes();
+ } else {
+ throw new Exception("error when wait polling response", (Throwable) result);
+ }
+ } else {
+ throw new Exception("future result(poll message response) is null");
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | " + e.getMessage(), e);
+ logger.warn(context.getAdapterName() + " | " + e.getMessage());
+ return null;
+ }
+ }
+ });
+
+ executor.execute(futureTask);
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | HexPollingFilter | error when send POLLING request - " + e.getMessage(), e);
+ logger.warn(context.getAdapterName() + " | HexPollingFilter | error when send POLLING request - " + e.getMessage());
+ } finally {
+ if (sess != null) {
+ adapter.getSessionPool().release(sess);
+ }
+ }
+ }
+
+
+ private boolean recvPolling(IoSession session, ByteMessage m, FilterState filterState) throws Exception {
+ ByteMessage om = m;
+
+ if ("Y".equals(context.getLlInclude())) {
+ m = (new ByteMessage())
+ .append(m.getBytes(0, context.getLlFieldOffset()))
+ .append(m.getBytes(context.getLlFieldOffset() + context.getLlFieldLength()));
+ }
+
+ if (context.isPollingReceiver() && m.getString().matches(getHexToStr(context.getPollingRequestPattern()))) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "HexPollingFilter | polling request - " + om.hexDump());
+ logger.debug(context.getAdapterName() + " | HexPollingFilter | polling request - " + om.hexDump());
+ }
+
+ /**
+ * oneway 일 경우, polling 응답을 보내지 않는다
+ */
+ if (context.isPollingOneway()) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "HexPollingFilter | oneway polling - skip sending polling response");
+ logger.debug(context.getAdapterName() + " | HexPollingFilter | oneway polling - skip sending polling response");
+ }
+ return true;
+ }
+
+ try {
+ byte[] response = m.getString().replaceAll(getHexToStr(context.getPollingRequestPattern()),
+ getHexToStr(context.getPollingReplacement())).getBytes();
+
+ if ("Y".equals(context.getLlInclude())) {
+ byte[] ll = new byte[context.getLlFieldLength()];
+ ByteMessage rm = new ByteMessage(response);
+ ByteMessage mm = (new ByteMessage())
+ .append(rm.getBytes(0, context.getLlFieldOffset()))
+ .append(ll)
+ .append(rm.getBytes(context.getLlFieldOffset()));
+ response = mm.getBytes();
+ }
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentSend(session, "HexPollingFilter | polling response - " + CommonLib.hexDump(response, true, context));
+ logger.debug(context.getAdapterName() + " | HexPollingFilter | polling response - " + CommonLib.hexDump(response, true, context));
+ }
+
+ internalSendMessage(session, response);
+ } catch (Exception e) {
+ throw e;
+ }
+
+ return true;
+ } else if (context.isPollingSender() && m.getString().matches(getHexToStr(context.getPollingResponsePattern()))) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "HexPollingFilter | polling response - " + om.hexDump());
+ logger.debug(context.getAdapterName() + " | HexPollingFilter | polling response - " + om.hexDump());
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+
+ protected void internalSendMessage(IoSession session, Object message) throws Exception {
+ ByteMessage m = null;
+
+ if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else {
+ throw new Exception("Unknown data format");
+ }
+// WriteFuture future = session.write(message);
+ session.write(message);
+ //future.join(context.getTimeout() * 1000L);
+
+ }
+
+
+ protected byte[] getPollingRequestFormatted() {
+ String message = getHexToStr(context.getPollingRequest());
+ Matcher matcher = Pattern.compile("%d\\{([a-zA-Z \\-]+)\\}").matcher(getHexToStr(context.getPollingRequest()));
+ if (matcher.find()) {
+ String datePattern = matcher.group(1);
+ DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(datePattern);
+ message = getHexToStr(context.getPollingRequest()).replaceAll("%d\\{([a-zA-Z \\-]+)\\}", dateFormat.format(ZonedDateTime.now()));
+ }
+
+ if ("Y".equals(context.getLlInclude())) {
+ byte[] ll = new byte[context.getLlFieldLength()];
+ ByteMessage mm = (new ByteMessage())
+ .append(message.substring(0, context.getLlFieldOffset()))
+ .append(ll)
+ .append(message.substring(context.getLlFieldOffset()));
+ return mm.getBytes();
+ } else {
+ return message.getBytes();
+ }
+ }
+ protected String getHexToStr(String str){
+ ByteMessage data = new ByteMessage();
+ while(str.indexOf("0x") != -1) {
+ data.append(str.substring(0, str.indexOf("0x")));
+ String hex = str.substring(str.indexOf("0x"), str.indexOf("0x")+4);
+ data.append((byte) Integer.parseInt(hex.substring(2), 16));
+ str = str.substring(str.indexOf("0x")+4);
+ }
+ data.append(str);
+ return data.getString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/polling/KFTCPollingFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/polling/KFTCPollingFilter.java
new file mode 100644
index 0000000..e0284ee
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/polling/KFTCPollingFilter.java
@@ -0,0 +1,322 @@
+package com.eactive.eai.adapter.socket2.filter.polling;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.concurrent.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class KFTCPollingFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ private static final String FILTER_STATE_KEY = KFTCPollingFilter.class.getName() + ".STATE";
+ private static final int offset =0; //context.getLlFieldOffset() 을 offset 으로 변경
+ private static class FilterState {
+ SimpleFuture pollingResponseFuture = new SimpleFuture();
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+ protected ExecutorService executor;
+
+
+ public KFTCPollingFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+ this.executor = Executors.newCachedThreadPool();
+ ((ThreadPoolExecutor) this.executor).setKeepAliveTime(1L, TimeUnit.SECONDS);
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ //SimpleFuture handshakeFuture = new SimpleFuture();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ nextFilter.sessionCreated(session);
+ }
+
+
+ @Override
+ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState != null && filterState.pollingResponseFuture != null) {
+ filterState.pollingResponseFuture.set(new Exception("session closed by peer"));
+ }
+
+ nextFilter.sessionClosed(session);
+ }
+
+
+ @Override
+ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
+ int responseTimeout = 0;
+
+ if (session.containsAttribute("responseTimeout")){
+ responseTimeout = (Integer)session.getAttribute("responseTimeout");
+ }
+// if (context.isPollingSender() && context.isPermanent() && context.isPollingUse()
+// && System.currentTimeMillis()-session.getLastIoTime() > (context.getTimeout() + 1) * 1000L
+// && System.currentTimeMillis()-session.getLastIoTime() < (context.getPollingTimeout() + 10) * 1000L) {
+// sendPollingRequest(session);
+// } else {
+// nextFilter.sessionIdle(session, status);
+// }
+ if (responseTimeout > 0){
+ nextFilter.sessionIdle(session, status);
+ }else{//원래로직
+ if (context.isPollingSender() && context.isPermanent() && context.isPollingUse()
+ && System.currentTimeMillis()-session.getLastIoTime() > (context.getTimeout() + 1) * 1000L
+ && System.currentTimeMillis()-session.getLastIoTime() < (context.getPollingTimeout() + 10) * 1000L) {
+ sendPollingRequest(session);
+ } else {
+ nextFilter.sessionIdle(session, status);
+ }
+ }
+
+ }
+
+
+ @Override
+ public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState != null && filterState.pollingResponseFuture != null) {
+ filterState.pollingResponseFuture.set(cause);
+ }
+ nextFilter.exceptionCaught(session, cause);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ ByteMessage m = (ByteMessage) message;
+
+ if (recvPolling(session, m, filterState)) {
+ if (filterState.pollingResponseFuture == null) {
+ filterState.pollingResponseFuture = new SimpleFuture();
+ }
+ filterState.pollingResponseFuture.set(m);
+ } else {
+ nextFilter.messageReceived(session, message);
+ }
+ }
+
+
+ private void sendPollingRequest(IoSession session) {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ /**
+ * send polling request
+ */
+ final byte[] pollingRequest = getPollingRequestFormatted();
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentSend(session, "KFTCPollingFilter | session idle -> polling request - "
+ + CommonLib.hexDump(pollingRequest, true, context));
+ logger.debug(context.getAdapterName() + " | KFTCPollingFilter | session idle -> polling request - "
+ + CommonLib.hexDump(pollingRequest, true, context));
+ }
+
+ IoSession sess = adapter.getSessionPool().acquire(session);
+
+ try {
+ if (filterState.pollingResponseFuture == null) {
+ filterState.pollingResponseFuture = new SimpleFuture();
+ }
+
+ final IoSession s = sess;
+ final FilterState hState = filterState;
+
+ FutureTask futureTask = new FutureTask(new Callable() {
+ public byte[] call() {
+ if (Thread.currentThread().getName().startsWith("pool-")) {
+ Thread.currentThread().setName(context.getAdapterName() + "-KFTCPollingFilter-" + Thread.currentThread().getName());
+ }
+
+ try {
+ internalSendMessage(s, pollingRequest);
+
+ /**
+ * oneway 이면 기다리지 않는다.
+ */
+ if (adapter.getContext().isPollingOneway()) {
+ return null;
+ }
+
+ if (hState.pollingResponseFuture != null) {
+ Object result = hState.pollingResponseFuture.join(context.getTimeout() * 1000L);
+ if (result instanceof ByteMessage) {
+ return ((ByteMessage) result).getBytes();
+ } else {
+ throw new Exception("error when wait polling response", (Throwable) result);
+ }
+ } else {
+ throw new Exception("future result(poll message response) is null");
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | " + e.getMessage(), e);
+ logger.warn(context.getAdapterName() + " | " + e.getMessage());
+ return null;
+ }
+ }
+ });
+
+ executor.execute(futureTask);
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | KFTCPollingFilter | error when send POLLING request - " + e.getMessage(), e);
+ logger.warn(context.getAdapterName() + " | KFTCPollingFilter | error when send POLLING request - " + e.getMessage());
+ } finally {
+ if (sess != null) {
+ adapter.getSessionPool().release(sess);
+ }
+ }
+ }
+
+
+ private boolean recvPolling(IoSession session, ByteMessage m, FilterState filterState) throws Exception {
+ ByteMessage om = m;
+
+ if ("Y".equals(context.getLlInclude())) {
+ m = (new ByteMessage())
+ .append(m.getBytes(0, offset))
+ .append(m.getBytes(offset + context.getLlFieldLength()));
+ }
+
+ if (context.isPollingReceiver() && m.getString().matches(context.getPollingRequestPattern())) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "KFTCPollingFilter | polling request - " + om.hexDump());
+ logger.debug(context.getAdapterName() + " | KFTCPollingFilter | polling request - " + om.hexDump());
+ }
+
+ /**
+ * oneway 일 경우, polling 응답을 보내지 않는다
+ */
+ if (context.isPollingOneway()) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "KFTCPollingFilter | oneway polling - skip sending polling response");
+ logger.debug(context.getAdapterName() + " | KFTCPollingFilter | oneway polling - skip sending polling response");
+ }
+ return true;
+ }
+
+ try {
+ byte[] response = m.getString().replaceAll(context.getPollingRequestPattern(),
+ context.getPollingReplacement()).getBytes();
+
+ if ("Y".equals(context.getLlInclude())) {
+ byte[] ll = new byte[context.getLlFieldLength()];
+ ll = padding(ll,(byte)0x30);
+ ByteMessage rm = new ByteMessage(response);
+ ByteMessage mm = (new ByteMessage())
+ .append(rm.getBytes(0, offset))
+ .append(ll)
+ .append(rm.getBytes(offset));
+ response = mm.getBytes();
+ }
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentSend(session, "KFTCPollingFilter | polling response - " + CommonLib.hexDump(response, true, context));
+ logger.debug(context.getAdapterName() + " | KFTCPollingFilter | polling response - " + CommonLib.hexDump(response, true, context));
+ }
+
+ internalSendMessage(session, response);
+ } catch (Exception e) {
+ throw e;
+ }
+
+ return true;
+ } else if (context.isPollingSender() && m.getString().matches(context.getPollingResponsePattern())) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "KFTCPollingFilter | polling response - " + om.hexDump());
+ logger.debug(context.getAdapterName() + " | KFTCPollingFilter | polling response - " + om.hexDump());
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+
+ protected void internalSendMessage(IoSession session, Object message) throws Exception {
+ ByteMessage m = null;
+
+ if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+// WriteFuture future = session.write(message);
+ session.write(message);
+ //future.join(context.getTimeout() * 1000L);
+ }
+
+
+ protected byte[] getPollingRequestFormatted() {
+ String message = context.getPollingRequest();
+ //Polling 로직 수정 2017.05 KSH
+ String str[] = message.split("%d");
+ String endMsg = "";
+ for(int i=0; i (context.getTimeout() + 1) * 1000L
+// && System.currentTimeMillis()-session.getLastIoTime() < (context.getPollingTimeout() + 10) * 1000L) {
+// sendPollingRequest(session);
+// } else {
+// nextFilter.sessionIdle(session, status);
+// }
+ if (responseTimeout > 0){
+ nextFilter.sessionIdle(session, status);
+ }else{//원래로직
+ if (context.isPollingSender() && context.isPermanent() && context.isPollingUse()
+ && System.currentTimeMillis()-session.getLastIoTime() > (context.getTimeout() + 1) * 1000L
+ && System.currentTimeMillis()-session.getLastIoTime() < (context.getPollingTimeout() + 10) * 1000L) {
+ sendPollingRequest(session);
+ } else {
+ nextFilter.sessionIdle(session, status);
+ }
+ }
+
+ }
+
+
+ @Override
+ public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState != null && filterState.pollingResponseFuture != null) {
+ filterState.pollingResponseFuture.set(cause);
+ }
+ nextFilter.exceptionCaught(session, cause);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ ByteMessage m = (ByteMessage) message;
+
+ if (recvPolling(session, m, filterState)) {
+ if (filterState.pollingResponseFuture == null) {
+ filterState.pollingResponseFuture = new SimpleFuture();
+ }
+ filterState.pollingResponseFuture.set(m);
+ } else {
+ nextFilter.messageReceived(session, message);
+ }
+ }
+
+
+ private void sendPollingRequest(IoSession session) {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ /**
+ * send polling request
+ */
+ final byte[] pollingRequest = getPollingRequestFormatted();
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentSend(session, "PollingFilter | session idle -> polling request - "
+ + CommonLib.hexDump(pollingRequest, true, context));
+ logger.debug(context.getAdapterName() + " | PollingFilter | session idle -> polling request - "
+ + CommonLib.hexDump(pollingRequest, true, context));
+ }
+
+ IoSession sess = adapter.getSessionPool().acquire(session);
+
+ try {
+ if (filterState.pollingResponseFuture == null) {
+ filterState.pollingResponseFuture = new SimpleFuture();
+ }
+
+ final IoSession s = sess;
+ final FilterState hState = filterState;
+
+ FutureTask futureTask = new FutureTask(new Callable() {
+ public byte[] call() {
+ if (Thread.currentThread().getName().startsWith("pool-")) {
+ Thread.currentThread().setName(context.getAdapterName() + "-PollingFilter-" + Thread.currentThread().getName());
+ }
+
+ try {
+ internalSendMessage(s, pollingRequest);
+
+ /**
+ * oneway 이면 기다리지 않는다.
+ */
+ if (adapter.getContext().isPollingOneway()) {
+ return null;
+ }
+
+ if (hState.pollingResponseFuture != null) {
+ Object result = hState.pollingResponseFuture.join(context.getTimeout() * 1000L);
+ if (result instanceof ByteMessage) {
+ return ((ByteMessage) result).getBytes();
+ } else {
+ throw new Exception("error when wait polling response", (Throwable) result);
+ }
+ } else {
+ throw new Exception("future result(poll message response) is null");
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | " + e.getMessage(), e);
+ logger.warn(context.getAdapterName() + " | " + e.getMessage());
+ return null;
+ }
+ }
+ });
+
+ executor.execute(futureTask);
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | PollingFilter | error when send POLLING request - " + e.getMessage(), e);
+ logger.warn(context.getAdapterName() + " | PollingFilter | error when send POLLING request - " + e.getMessage());
+ } finally {
+ if (sess != null) {
+ adapter.getSessionPool().release(sess);
+ }
+ }
+ }
+
+
+ private boolean recvPolling(IoSession session, ByteMessage m, FilterState filterState) throws Exception {
+ ByteMessage om = m;
+
+ if ("Y".equals(context.getLlInclude())) {
+ m = (new ByteMessage())
+ .append(m.getBytes(0, context.getLlFieldOffset()))
+ .append(m.getBytes(context.getLlFieldOffset() + context.getLlFieldLength()));
+ }
+
+ if (context.isPollingReceiver() && m.getString().matches(context.getPollingRequestPattern())) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "PollingFilter | polling request - " + om.hexDump());
+ logger.debug(context.getAdapterName() + " | PollingFilter | polling request - " + om.hexDump());
+ }
+
+ /**
+ * oneway 일 경우, polling 응답을 보내지 않는다
+ */
+ if (context.isPollingOneway()) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "PollingFilter | oneway polling - skip sending polling response");
+ logger.debug(context.getAdapterName() + " | PollingFilter | oneway polling - skip sending polling response");
+ }
+ return true;
+ }
+
+ try {
+ byte[] response = m.getString().replaceAll(context.getPollingRequestPattern(),
+ context.getPollingReplacement()).getBytes();
+
+ if ("Y".equals(context.getLlInclude())) {
+ byte[] ll = new byte[context.getLlFieldLength()];
+ ByteMessage rm = new ByteMessage(response);
+ ByteMessage mm = (new ByteMessage())
+ .append(rm.getBytes(0, context.getLlFieldOffset()))
+ .append(ll)
+ .append(rm.getBytes(context.getLlFieldOffset()));
+ response = mm.getBytes();
+ }
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentSend(session, "PollingFilter | polling response - " + CommonLib.hexDump(response, true, context));
+ logger.debug(context.getAdapterName() + " | PollingFilter | polling response - " + CommonLib.hexDump(response, true, context));
+ }
+
+ internalSendMessage(session, response);
+ } catch (Exception e) {
+ throw e;
+ }
+
+ return true;
+ } else if (context.isPollingSender() && m.getString().matches(context.getPollingResponsePattern())) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, "PollingFilter | polling response - " + om.hexDump());
+ logger.debug(context.getAdapterName() + " | PollingFilter | polling response - " + om.hexDump());
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+
+ protected void internalSendMessage(IoSession session, Object message) throws Exception {
+ ByteMessage m = null;
+
+ if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+// WriteFuture future = session.write(message);
+ session.write(message);
+ //future.join(context.getTimeout() * 1000L);
+ }
+
+
+ protected byte[] getPollingRequestFormatted() {
+ String message = context.getPollingRequest();
+ //Polling 로직 수정 2017.05 KSH
+ String str[] = message.split("%d");
+ String endMsg = "";
+ for(int i=0; i= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | create SSLContext - " + (isServer ? "SERVER" : "CLIENT"));
+ }
+
+ SSLContext sslContext = null;
+ if (isServer) {
+ if (serverSslContext == null) {
+ synchronized (SSLContextFactory.class) {
+ if (serverSslContext == null) {
+ try {
+ serverSslContext = createServerSSLContext(context);
+ } catch (Exception ioe) {
+ throw new GeneralSecurityException("Can't create Server SSLContext:" + ioe);
+ }
+ }
+ }
+ }
+ sslContext = serverSslContext;
+ } else {
+ if (clientSslContext == null) {
+ synchronized (SSLContextFactory.class) {
+ if (clientSslContext == null) {
+ clientSslContext = createClientSSLContext(context);
+ }
+ }
+ }
+ sslContext = clientSslContext;
+ }
+ return sslContext;
+ }
+
+
+ private static SSLContext createServerSSLContext(SocketAdapterContext context) throws GeneralSecurityException, IOException {
+ // Create keystore
+ KeyStore ks = KeyStore.getInstance("JKS");
+ InputStream in = null;
+ try {
+ in = SSLContextFactory.class.getResourceAsStream(context.getSslCertStore());
+ if (in == null) {
+ throw new GeneralSecurityException("ssl cert store does not exist - " + context.getSslCertStore());
+ }
+ ks.load(in, context.getSslCertPassword().toCharArray());
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+
+ // Set up key manager factory to use our key store
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
+ kmf.init(ks, context.getSslCertPassword().toCharArray());
+
+ // Initialize the SSLContext to work with our key managers.
+ SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
+ sslContext.init(kmf.getKeyManagers(), TrustManagerFactory.X509_MANAGERS, null);
+
+ return sslContext;
+ }
+
+
+ private static SSLContext createClientSSLContext(SocketAdapterContext context) throws GeneralSecurityException {
+ SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
+ sslContext.init(null, TrustManagerFactory.X509_MANAGERS, null);
+ //SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket();
+ //sslSocket.startHandshake();
+ return sslContext;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/SSLServerSocketFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/SSLServerSocketFactory.java
new file mode 100644
index 0000000..e03d1af
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/SSLServerSocketFactory.java
@@ -0,0 +1,68 @@
+package com.eactive.eai.adapter.socket2.filter.ssl;
+//package com.eactive.eai.adapter.socket2.protocol.ssl;
+//
+//import java.io.IOException;
+//import java.net.InetAddress;
+//import java.net.ServerSocket;
+//import java.security.GeneralSecurityException;
+//
+//import javax.net.ServerSocketFactory;
+//
+//import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+//import com.eactive.eai.common.util.Logger;
+//
+//
+//public class SSLServerSocketFactory extends javax.net.ServerSocketFactory {
+// static final protected Logger logger = SocketLoggerManager.getInstance().getLogger();
+// static final protected Logger errLogger = SocketLoggerManager.getInstance().getErrLogger();
+//
+// private static boolean sslEnabled = false;
+// private static javax.net.ServerSocketFactory sslFactory = null;
+// private static ServerSocketFactory factory = null;
+//
+// public SSLServerSocketFactory() {
+// super();
+// }
+//
+// public ServerSocket createServerSocket(int port) throws IOException {
+// return new ServerSocket(port);
+// }
+//
+// public ServerSocket createServerSocket(int port, int backlog) throws IOException {
+// return new ServerSocket(port, backlog);
+// }
+//
+// public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress)
+// throws IOException {
+// return new ServerSocket(port, backlog, ifAddress);
+// }
+//
+// public static javax.net.ServerSocketFactory getServerSocketFactory() throws IOException {
+// if (isSslEnabled()) {
+// if (sslFactory == null) {
+// try {
+// sslFactory = SSLContextFactory.createSSLContext(true).getServerSocketFactory();
+// } catch (GeneralSecurityException e) {
+// IOException ioe = new IOException("could not create SSL socket");
+// ioe.initCause(e);
+// throw ioe;
+// }
+// }
+// return sslFactory;
+// } else {
+// if (factory == null) {
+// factory = new SSLServerSocketFactory();
+// }
+// return factory;
+// }
+//
+// }
+//
+// public static boolean isSslEnabled() {
+// return sslEnabled;
+// }
+//
+// public static void setSslEnabled(boolean newSslEnabled) {
+// sslEnabled = newSslEnabled;
+// }
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/SSLSocketFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/SSLSocketFactory.java
new file mode 100644
index 0000000..20bd147
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/SSLSocketFactory.java
@@ -0,0 +1,88 @@
+package com.eactive.eai.adapter.socket2.filter.ssl;
+//package com.eactive.eai.adapter.socket2.protocol.ssl;
+//
+//import java.io.IOException;
+//import java.net.InetAddress;
+//import java.net.Socket;
+//import java.net.UnknownHostException;
+//import java.security.GeneralSecurityException;
+//
+//import javax.net.SocketFactory;
+//
+//import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+//import com.eactive.eai.common.util.Logger;
+//
+//
+//public class SSLSocketFactory extends SocketFactory {
+// static final protected Logger logger = SocketLoggerManager.getInstance().getLogger();
+// static final protected Logger errLogger = SocketLoggerManager.getInstance().getErrLogger();
+//
+// private static boolean sslEnabled = false;
+// private static javax.net.ssl.SSLSocketFactory sslFactory = null;
+// private static javax.net.SocketFactory factory = null;
+//
+// public SSLSocketFactory() {
+// super();
+// }
+//
+// public Socket createSocket(String arg1, int arg2) throws IOException, UnknownHostException {
+// if (isSslEnabled()) {
+// return getSSLFactory().createSocket(arg1, arg2);
+// } else {
+// return new Socket(arg1, arg2);
+// }
+// }
+//
+// public Socket createSocket(String arg1, int arg2, InetAddress arg3, int arg4) throws IOException, UnknownHostException {
+// if (isSslEnabled()) {
+// return getSSLFactory().createSocket(arg1, arg2, arg3, arg4);
+// } else {
+// return new Socket(arg1, arg2, arg3, arg4);
+// }
+// }
+//
+// public Socket createSocket(InetAddress arg1, int arg2) throws IOException {
+// if (isSslEnabled()) {
+// return getSSLFactory().createSocket(arg1, arg2);
+// } else {
+// return new Socket(arg1, arg2);
+// }
+// }
+//
+// public Socket createSocket(InetAddress arg1, int arg2, InetAddress arg3, int arg4) throws IOException {
+// System.out.println("-SSLSocketFactory.createSocket()");
+//
+// if (isSslEnabled()) {
+// return getSSLFactory().createSocket(arg1, arg2, arg3, arg4);
+// } else {
+// return new Socket(arg1, arg2, arg3, arg4);
+// }
+// }
+//
+// public static javax.net.SocketFactory getSocketFactory() {
+// if (factory == null) {
+// factory = new SSLSocketFactory();
+// }
+// return factory;
+// }
+//
+// private javax.net.ssl.SSLSocketFactory getSSLFactory() throws IOException {
+// if (sslFactory == null) {
+// try {
+// sslFactory = SSLContextFactory.createSSLContext(false).getSocketFactory();
+// } catch (GeneralSecurityException e) {
+// throw new RuntimeException("could not create SSL socket", e);
+// }
+// }
+// return sslFactory;
+// }
+//
+// public static boolean isSslEnabled() {
+// return sslEnabled;
+// }
+//
+// public static void setSslEnabled(boolean newSslEnabled) {
+// sslEnabled = newSslEnabled;
+// }
+//
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/TrustManagerFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/TrustManagerFactory.java
new file mode 100644
index 0000000..5398dbf
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/TrustManagerFactory.java
@@ -0,0 +1,48 @@
+package com.eactive.eai.adapter.socket2.filter.ssl;
+
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactorySpi;
+import javax.net.ssl.X509TrustManager;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+
+
+class TrustManagerFactory extends TrustManagerFactorySpi {
+
+ static final X509TrustManager X509 = new X509TrustManager() {
+ public void checkClientTrusted(X509Certificate[] x509Certificates,
+ String s) throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] x509Certificates,
+ String s) throws CertificateException {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ };
+
+ static final TrustManager[] X509_MANAGERS = new TrustManager[] { X509 };
+
+ public TrustManagerFactory() {
+ }
+
+ protected TrustManager[] engineGetTrustManagers() {
+ return X509_MANAGERS;
+ }
+
+ protected void engineInit(KeyStore keystore) throws KeyStoreException {
+ // noop
+ }
+
+ protected void engineInit(ManagerFactoryParameters managerFactoryParameters)
+ throws InvalidAlgorithmParameterException {
+ // noop
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/bogus.cert b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/bogus.cert
new file mode 100644
index 0000000..d34502d
Binary files /dev/null and b/src/main/java/com/eactive/eai/adapter/socket2/filter/ssl/bogus.cert differ
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/filter/validation/ValidationFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/filter/validation/ValidationFilter.java
new file mode 100644
index 0000000..c3c6963
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/filter/validation/ValidationFilter.java
@@ -0,0 +1,63 @@
+package com.eactive.eai.adapter.socket2.filter.validation;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class ValidationFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ public ValidationFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ /*
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | ValidationFilter | messageReceived()");
+ }
+ */
+
+ ByteMessage m = (ByteMessage) message;
+
+ /**
+ * validation.rule
+ */
+ if (!"".equals(context.getValidationRule())) {
+ Matcher matcher = Pattern.compile("\\[([ ]*[0-9]+)[ ]*,([ ]*[0-9]+)[ ]*\\][ ]*=[ ]*(.+)").matcher(context.getValidationRule().trim());
+ if (matcher.find()) {
+ int offset = Integer.parseInt(matcher.group(1).trim());
+ int length = Integer.parseInt(matcher.group(2).trim());
+ String re = matcher.group(3).trim();
+
+ if (!new String(m.getBytes(offset, length)).matches(re)) {
+ throw new Exception(context.getAdapterName() + " | data is invalid - validation.rule : " + context.getValidationRule() + " " + m.hexDump());
+ }
+ } else {
+ throw new Exception(context.getAdapterName() + " | validation.rule format is invalid : " + context.getValidationRule());
+ }
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.messageReceived(session, message);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/ByteMessage.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/ByteMessage.java
new file mode 100644
index 0000000..a20964c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/ByteMessage.java
@@ -0,0 +1,143 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import org.apache.mina.common.ByteBuffer;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+
+public class ByteMessage {
+ protected byte[] value;
+
+ public ByteMessage() {
+ this.value = new byte[0];
+ }
+
+ public ByteMessage(byte[] value) {
+ this.value = value;
+ }
+
+ public ByteMessage(String value) {
+ this.value = value.getBytes();
+ }
+
+ public ByteMessage(ByteBuffer buffer) {
+ this.setByteBuffer(buffer);
+ }
+
+ public byte getByte(int offset) {
+ return this.value[offset];
+ }
+
+ public byte[] getBytes() {
+ return value;
+ }
+
+ public byte[] getBytes(int offset, int length) throws EAIException {
+ if (size() - offset - length < 0) {
+ throw new EAIException("ByteMessage | cannot make negative array size bytes"
+ + "| size=" + size() + ", offset=" + offset + ", length=" + length + " - " + CommonLib.hexDump(this.value));
+ }
+
+ byte[] bytes = new byte[length];
+ System.arraycopy(value, offset, bytes, 0, length);
+ return bytes;
+ }
+
+ public byte[] getBytes(int offset) {
+ if (size() - offset < 0) {
+ throw new RuntimeException("ByteMessage | cannot make negative array size bytes"
+ + "| size=" + size() + ", offset=" + offset + " - " + CommonLib.hexDump(this.value));
+ }
+
+ byte[] bytes = new byte[size()-offset];
+ System.arraycopy(value, offset, bytes, 0, size()-offset);
+ return bytes;
+ }
+
+ public ByteMessage exclude(int offset, int length) throws EAIException {
+ byte[] messageWithoutLl = new byte[size() - length];
+ System.arraycopy(getBytes(0, offset), 0, messageWithoutLl, 0, offset);
+ System.arraycopy(getBytes(offset + length), 0, messageWithoutLl, offset+length, size()-length-offset);
+ return new ByteMessage(messageWithoutLl);
+ }
+
+ public ByteMessage append(byte b) {
+ byte[] sum = new byte[size() + 1];
+ System.arraycopy(this.value, 0, sum, 0, size());
+ sum[size()] = b;
+ this.value = sum;
+ return this;
+ }
+
+ public ByteMessage append(byte[] bytes) {
+ byte[] sum = new byte[size() + bytes.length];
+ System.arraycopy(this.value, 0, sum, 0, size());
+ System.arraycopy(bytes, 0, sum, size(), bytes.length);
+ this.value = sum;
+ return this;
+ }
+
+ public ByteMessage append(String str) {
+ return append(str.getBytes());
+ }
+
+ public ByteMessage padding(int length, byte b) throws EAIException {
+ if (length >= size()) {
+ byte[] sum = new byte[length];
+ System.arraycopy(this.value, 0, sum, 0, size());
+ for (int i=0; i retryThreads;
+ protected SessionPool sessionPool;
+
+ protected long messageSend = 0;
+ protected long messageRecv = 0;
+ private boolean isXCInclude = false;//XecuserConnect 모듈 유무 판단.
+
+ protected ProtocolHandler(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ this.sessionPool = new SessionPool(adapter, context);
+ //XecuserConnect 모듈 유무 판단.
+ try {
+ Class clazz = Class.forName("com.sf.xc3.XCException");
+ isXCInclude = true;
+ logger.warn("XCException include");
+ } catch (Throwable e) {
+ logger.error("XCException not include");
+ }
+ }
+
+ public void start() throws Exception {
+ this.retryThreads = new ArrayList<>();
+ }
+
+ public void stop() throws Exception {
+ for (Iterator iter = (new ArrayList(retryThreads)).iterator(); iter.hasNext(); ) {
+ try {
+ iter.next().interrupt();
+ } catch(ConcurrentModificationException e) {
+ logger.debug("stop ConcurrentModificationException");
+ }
+ }
+ }
+
+ @Override
+ public void sessionCreated(IoSession session) throws Exception {
+ super.sessionCreated(session);
+
+ synchronized(lockObj) {
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+ if (handlerState == null) {
+ handlerState = new HandlerState();
+ session.setAttribute(HANDLER_STATE_KEY, handlerState);
+ setSessionState(session, handlerState.state.toString());
+
+ SimpleFuture handshakeFuture = new SimpleFuture();
+ session.setAttribute(HANDSHAKE_FUTURE, handshakeFuture);
+ }
+ }
+ }
+
+ @Override
+ public void sessionOpened(IoSession session) throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE && !"HTTP".equals(context.getProtocol())) {
+ logger.debug(context.getAdapterName() + " | session opened : " + session);
+ }
+
+ // DEFAULT : false
+ if(session.getTransportType() == TransportType.SOCKET
+ && context.isKeepAlive()) {
+ ((SocketSessionConfig)session.getConfig()).setKeepAlive(true);
+ }
+
+ if (context.isPollingUse() && context.isPollingSender() && context.isPermanent()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ session.setWriteTimeout(context.getTimeout());
+
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+ if (handlerState == null) {
+ handlerState = new HandlerState();
+ handlerState.state = State.STATE_MESSAGE_WAIT_REQUEST;
+ session.setAttribute(HANDLER_STATE_KEY, handlerState);
+ }
+
+ synchronized(lockObj) {
+ sessionPool.release(session);
+
+ if (!context.isPermanent()) {
+ SimpleFuture handshakeFuture = (SimpleFuture) session.getAttribute(HANDSHAKE_FUTURE);
+ if (handshakeFuture != null) {
+ handshakeFuture.set(Boolean.TRUE);
+ }
+ }
+
+ adapter.setAdapterStatus(true);
+ }
+ if("Y".equals(context.getSingleSession())){
+ logger.debug(context.getAdapterName() + " | session opened : SingleSession - " + session);
+ SingleSessionManager.getInstance().sessionOpen(context.getAdapterGroupName(), session);
+ }
+ }
+
+ @Override
+ public void sessionIdle(IoSession session, IdleStatus status) {
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("idle:" + TimeUtil.elapsedTime(session.getLastIoTime()));
+ if (System.currentTimeMillis()-session.getLastIoTime() < (context.getTimeout() + 1) * 1000L) {
+ sb.append(", timeout:" + context.getTimeout());
+ sb.append(", protocol:" + context.getProtocol());
+ if (handlerState != null) {
+ sb.append(", state:" + handlerState.state.toString());
+ }
+ sb.append("/" + session.getAttribute(SESSION_STATE));
+ sb.append("/" + session.getAttribute(CODEC_STATE));
+ sb.append(", " + session.getAttribute(CODEC_STATE_BUFFER));
+
+ logger.error(context.getAdapterName() + " | transaction timeout -> disconnecting (" + session + ") " + sb.toString());
+ adapter.addRecentError(context.getAdapterName() + " | transaction timeout -> disconnecting (" + session + ") " + sb.toString());
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA005");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA005");
+ } else {
+ /**
+ * idle.timeout이 0 이면 connection을 끊지 않는다.
+ */
+ if (context.getIdleTimeout() == 0) {
+ return;
+ }
+
+ adapter.addRecentErrorOnly(context.getAdapterName() + " | session idle -> disconnecting (" + session + ") " + sb.toString());
+ logger.info(context.getAdapterName() + " | session idle -> disconnecting (" + session + ") " + sb.toString());
+ }
+
+ // disconnect an idle client
+ sessionPool.remove(session);
+ session.close();
+ }
+
+ @Override
+ public void sessionClosed(IoSession session) throws Exception {
+ try {
+ /**
+ * logging
+ */
+ if (context.isPermanent() && context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ /**
+ * ignore L4 connection close event
+ */
+ if (session.getWrittenMessages()==0 && session.getReadMessages()==0
+ && System.currentTimeMillis() - session.getCreationTime() < 1000) {
+ // ignore - skip logging
+ } else {
+ adapter.addRecentError(context.getAdapterName() + " | session closed (" + session + ")");
+ }
+ }
+
+ if (context.isPermanent() && context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE && !"HTTP".equals(context.getProtocol())) {
+ logger.debug(context.getAdapterName() + " | session closed (" + session + ")" + "");
+ }
+
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+ if (handlerState != null
+ && handlerState.responseFuture != null
+ && (context.isServer() || context.isPermanent())) {
+ handlerState.responseFuture.set(new Exception("session closed by peer (" + session + ")"));
+ }
+
+ ConnectFuture connectFuture = (ConnectFuture) session.getAttribute("connectFuture");
+ if (connectFuture != null) {
+ connectFuture.setException(new Exception("inbound session is closed by peer (" + session + ")"));
+ }
+
+ if (!context.isPermanent()) {
+ return;
+ }
+
+ if (adapter.getState() == ISocketAdapter.State.STOPPING || adapter.getState() == ISocketAdapter.State.STOPPED) {
+ return;
+ }
+ } finally {
+ try {
+ if("Y".equals(context.getSingleSession())){
+ SingleSessionManager.getInstance().sessionClose(context.getAdapterGroupName(), session);
+ }
+
+ sessionPool.remove(session);
+ session.close();
+
+ if (sessionPool.size() <= 0 && context.isPermanent()) {
+ adapter.setAdapterStatus(false);
+ }
+ } catch(Exception e) {
+ logger.error(context.getAdapterName() + " | " + e.getMessage(), e);
+ }
+ }
+
+ if (adapter instanceof SocketAdapterClient
+ && context.isPermanent()
+ && adapter.getState() == ISocketAdapter.State.STARTED
+ && adapter.getSessionPool().size() < adapter.getContext().getMaxConnection()
+ && !("INISAFE".equals(context.getProtocol())
+ || "INISAFE_2020".equals(context.getProtocol())
+ || "INISAFE_NATN".equals(context.getProtocol())
+ )) {
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | session closed -> try to connect after 10 seconds ...");
+ }
+
+ while (!Thread.currentThread().isInterrupted()) {
+ if (adapter.getState() != ISocketAdapter.State.STARTED) {
+ break;
+ }
+
+ // 싱글어댑터 - Start ---------------------------------------------------------------------------------------------------------------------
+ boolean retry = true;
+
+ // 싱글어댑터 session 종료 시 재연결 처리
+ if (context.getSingleSession().equals("Y")) {
+ String primaryInst = context.getPrimaryInstId();
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ String localServerName = eaiServerManager.getLocalServerName();
+ String adapterGroupName = context.getAdapterGroupName();
+
+ if (localServerName.equals(primaryInst)) { // CASE : Primary 서버
+ SessionVO sessionVO = SessionManager.getInstance().getConnectionStatus(adapterGroupName);
+
+ if(sessionVO != null) { // Secondary 서버가 연결하고 있음
+ retry = false;
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + "| SingleSession Validation Exist [" +sessionVO.getLoginInstId()+"]");
+ }
+
+ } else { // Secondary 서버가 연결하지 않고 있으므로 연결 시도함.
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + "| SingleSession Validation Connection empty -> retry to connect after 10 secs");
+ }
+ }
+ } else { // CASE : Secondary 서버
+ boolean isAlive = HealthCheckManager.getInstance().getServerStatus(primaryInst); // Primay서버 상태 확인
+
+ if (isAlive) { // Primary 서버 살아있으면 재연결 시도 안함
+ retry = false;
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG)
+ logger.debug(context.getAdapterName() + "| SingleSession Validation Exist [" +primaryInst+"]");
+ } else {
+ SessionManager.getInstance().removeConnectionInfo(adapterGroupName);
+ }
+ }
+
+ }
+
+ if(!retry) {
+ try {
+ Thread.sleep(10 * 1000L);
+ } catch (InterruptedException e) {
+ logger.error(context.getAdapterName() + " | " + e.getMessage(), e);
+ }
+ continue;
+ }
+ // 싱글어댑터 - End ---------------------------------------------------------------------------------------------------------------------
+ /**
+ * FDS - connectOne 시도 후, 바로 connection이 끊어지는 경우
+ * ExecutorFilter에서 Thread 생성이 계속 늘어나는 현상을 방지
+ * connection retry thread 개수를 max.connection 개수에 맞춘다.
+ */
+ synchronized(retryThreads) {
+ if (sessionPool.size() + retryThreads.size() >= context.getMaxConnection()) {
+ break;
+ }
+ retryThreads.add(Thread.currentThread());
+ }
+
+ try {
+ try {
+ Thread.sleep(10000L);
+ } catch(InterruptedException ee) {
+ break;
+ } catch(Exception ee) {
+ logger.error(context.getAdapterName() + " | " + ee.getMessage(), ee);
+ }
+
+// if (adapter.getState() != ISocketAdapter.State.STARTED) {
+// break;
+// }
+
+ try {
+ if (adapter.connectOne() != null) {
+ break;
+ }
+ } catch(Throwable t) {
+ logger.debug(context.getAdapterName() + " | session closed -> fail to reconnect -> retry after 10 seconds. caused by " + t.toString());
+ }
+ } finally {
+ synchronized(retryThreads) {
+ retryThreads.remove(Thread.currentThread());
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void exceptionCaught(IoSession session, Throwable cause) {
+ if (cause instanceof IOException) {
+ logger.warn(context.getAdapterName() + " | " + cause.getMessage() + " (" + session + ")");
+ String cMsg = cause.getMessage();
+ if( (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) && context.isPermanent()
+ && (cMsg != null && cMsg.indexOf("reset by peer") != -1) ) {
+ adapter.addRecentError(context.getAdapterName() + " | " + cMsg + " (" + session + ")", cause);
+ }
+
+ } else if (isXCInclude && cause instanceof com.sf.xc3.XCException) {
+ logger.warn(context.getAdapterName() + " | session exception caught (" + session + ") - " + cause.getMessage());
+ } else {
+ String errorMsg = context.getAdapterName() + " | session exception caught (" + session + ")";
+ logger.error(errorMsg, cause);
+ adapter.addRecentError(errorMsg, cause);
+ errLogger.error(errorMsg, cause);
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA001");
+ }
+
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+ if (handlerState != null && handlerState.responseFuture != null
+ && cause instanceof IOException
+ && (context.isServer() || context.isPermanent())) {
+ handlerState.responseFuture.set(cause);
+ }
+
+ // close the connection on exceptional situation
+ // TODO : 위의 sessionClosed() 메쏘드가 불려져서 pool에서 제거되는지 확인
+ sessionPool.remove(session);
+ session.close();
+ }
+
+ public SocketAdapterContext getContext() {
+ return context;
+ }
+
+ public SessionPool getSessionPool() {
+ return sessionPool;
+ }
+
+ /**
+ * message received
+ */
+ @Override
+ public void messageReceived(final IoSession session, Object message) throws Exception {
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG && !"HTTP".equals(context.getProtocol())) {
+ logger.debug(context.getAdapterName() + " (" + session + ") | " + message);
+ }
+
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+ if (handlerState == null) {
+ handlerState = new HandlerState();
+ handlerState.state = State.STATE_MESSAGE_WAIT_REQUEST;
+ session.setAttribute(HANDLER_STATE_KEY, handlerState);
+ }
+
+ incMessageRecv();
+
+ ByteMessage m = (ByteMessage) message;
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ adapter.addRecentRecv(session, CommonLib.hexDump(m.getBytes(), true, context));
+ }
+
+ switch (handlerState.state) {
+ case STATE_MESSAGE_WAIT_RESPONSE:
+ if (handlerState.responseFuture != null) {
+ handlerState.responseFuture.set(m);
+ }
+ if (context.isPermanent() && (!session.isConnected() || session.isClosing())) {
+ throw new IOException("session is not connected (" + session + ")");
+ }
+ break;
+
+ case STATE_MESSAGE_WAIT_REQUEST:
+ try {
+ sessionPool.acquire(session);
+
+ byte[] r = null;
+ if (message instanceof ByteMessage) {
+ r = ((ByteMessage) message).getBytes();
+ } else {
+ throw new Exception("unknown message type : " + message.getClass().getName());
+ }
+
+ if ("OUTBOUND".equals(context.getBoundUsage())) {
+ throw new Exception("'OUTBOUND" + (context.isSync() ? "" : ", ASYN") + "' adapter cannot process request : " + CommonLib.hexDump(r, true, context));
+ }
+
+ final byte[] request = r;
+ @SuppressWarnings("unchecked")
+ final FutureTask futureTask = new FutureTask(new Callable() {
+ ExecutionContext executionContext = ExecutionContext.getInstance();
+
+ public byte[] call() throws Exception {
+ try {
+ if (Thread.currentThread().getName().startsWith("pool-")) {
+ Thread.currentThread().setName(context.getAdapterName() + "-Worker-" + Thread.currentThread().getName());
+ }
+ executionContext.set("session", session);
+ return processRequest(session, request);
+ } finally {
+ executionContext.remove("session");
+ }
+ }
+ });
+
+ try {
+ futureTask.run();
+ } catch(Exception e) {
+ throw new RuntimeException("error when process request", e);
+ }
+
+ if (context.isPermanent() && (!session.isConnected() || session.isClosing())) {
+ throw new IOException("session is not connected (" + session + ")");
+ }
+
+ /**
+ * if SYNC -> send result to sender
+ */
+ if (context.isSync()) {
+ try {
+ byte[] response = (byte[]) futureTask.get(context.getTimeout(), TimeUnit.SECONDS);
+
+ if (response == null) {
+ throw new EAIException("cannot send NULL response message (framework returned) - check if target adapter is ASYNC");
+ } else if (response.length == 0) {
+ throw new EAIException("cannot send ZERO-size response message (framework returned) - check if target adapter is ASYNC");
+ } else {
+ try {
+ internalSendMessage(session, new ByteMessage(response));
+ } catch(Exception e) {
+ throw new EAIException("(SYNC) cannot send response message", e);
+ }
+ }
+ } catch (ExecutionException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof Exception)
+ throw (Exception) cause;
+ else
+ throw new Exception(cause.getMessage());
+ } catch (InterruptedException e) {
+ throw new TimeoutException("(future) cannot recv message. timeout=" + context.getTimeout());
+ } catch(TimeoutException e) {
+ throw new TimeoutException("(future) cannot send message. timeout=" + context.getTimeout());
+ }
+ }
+ } finally {
+ try {
+ releaseSession(session);
+ } catch(Exception e) {
+ logger.warn("releaseSession error", e);
+ }
+ }
+
+ break;
+ }
+ }
+
+ protected byte[] processRequest(IoSession session, byte[] request) throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | (before) process request : " + CommonLib.hexDump(request, true, context));
+ }
+
+ try {
+ Properties prop = new Properties();
+ byte[] response = null;
+
+ //for GW
+ AdapterManager adapterManager = AdapterManager.getInstance();
+ AdapterGroupVO adptGrpVO = adapterManager.getAdapterGroupVO(context.getAdapterGroupName());
+
+// if (context.getBoundUsage().equals(context.IOBOUND_SOCKET)) {
+ if (StringUtils.isNotBlank(adptGrpVO.getSameSessionYn()) && "1".equals(adptGrpVO.getSameSessionYn())
+ && context.getBoundUsage().equals(context.IOBOUND_SOCKET)) {
+ String sessionId = String.valueOf(session.hashCode());
+ prop.setProperty("SESSION_ID", sessionId);
+ GWSessionManager.getInstance().sessionIn(sessionId, session);
+ }
+
+ if (context.getRequestProcessor() != null) {
+ response = context.getRequestProcessor().handle(request);
+ } else if (!"".equals(context.getScript().trim())) {
+ String filename = context.getScript();
+ if (filename.endsWith(".groovy")) {
+ Groovy groovy = new Groovy(filename,
+ context.getAdapterGroupName() + "." + context.getAdapterName());
+ response = groovy.run(request);
+ } else {
+ response = FileUtil.readFile(filename);
+ }
+ } else if (Env.isEcho() || context.getDescription().startsWith("ECHO")) {
+ response = request;
+ } else if (!Env.isStandalone()) {
+
+ String encode = null;
+ try {
+ RequestDispatcher dispatcher = RequestDispatcher
+ .getRequestDispatcher(context.getAdapterGroupName());
+ Object responseObject = dispatcher.handle(context.getAdapterName(), request, prop);
+ if (responseObject == null) {
+ response = null;
+ } else if (responseObject instanceof byte[]) {
+ response = (byte[]) responseObject;
+ } else if (responseObject instanceof String) {
+ // TODO : 정상작동여부를 확인해야 함.
+ encode = prop.getProperty(com.eactive.eai.adapter.Keys.CHARSET_KEY_IN, "euc-kr");
+ response = ((String) responseObject).getBytes(encode);
+ } else {
+ throw new Exception("RECEAIAHA001");
+ }
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | (after) process request : "
+ + CommonLib.hexDump(response, true, context));
+ }
+
+ return response;
+ } catch (Throwable t) {
+ logger.error(t);
+ byte[] errorResponse = ("[RECEAIONA001] " + context.getAdapterName()
+ + " | cannot process request - " + t.getMessage()).getBytes(encode);
+ internalSendMessage(session, new ByteMessage(errorResponse));
+ throw t;
+ }
+ } else {
+ throw new Exception("no rule to handle request");
+ }
+
+ return response;
+ } catch (Throwable t) {
+ logger.error(context.getAdapterName() + " | cannot process request " + CommonLib.hexDump(request, true, context), t);
+ adapter.addRecentError(context.getAdapterName() + " | cannot process request " + CommonLib.hexDump(request, true, context), t);
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA010");
+
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+ if (handlerState != null && handlerState.responseFuture != null) {
+ handlerState.responseFuture.set(t);
+ }
+ throw new EAIException(t);
+ }
+ }
+
+ protected void internalSendMessage(IoSession session, Object message) throws Exception {
+ if(!session.isConnected()) {
+ throw new EAIException("cannot send message - session is not connected (" + session + ")");
+ }
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | " + getHexDump(message));
+ adapter.addRecentSend(session, getHexDump(message));
+ }
+
+ WriteFuture future = session.write(message);
+ if (adapter instanceof TcpAdapterClient || adapter instanceof TcpAdapterServer) {
+ future.join(context.getTimeout() * 1000L);
+ }
+
+ incMessageSend();
+ }
+
+ public Object sendMessage(IoSession reservedSession, Object message) throws EAIException {
+ return sendMessage(reservedSession, message, context.getTimeout());
+ }
+ public Object sendMessage(IoSession reservedSession, Object message, int responseTimeout) throws EAIException {
+ switch(adapter.getState()) {
+ case STARTING:
+ case STARTED:
+ break;
+ default:
+ adapter.addRecentError(context.getAdapterName() + " | cannot send message. adapter state is " + adapter.getState().name());
+ throw new EAIException(context.getAdapterName() + " | cannot send message. adapter state is " + adapter.getState().name());
+ }
+
+ IoSession session = null;
+
+ try {
+ if (reservedSession == null) {
+ session = acquireSession();
+ } else {
+ session = reservedSession;
+ }
+
+ HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+ handlerState.responseFuture = new SimpleFuture();
+ if (context.isSync()) {
+ handlerState.state = State.STATE_MESSAGE_WAIT_RESPONSE;
+ }
+
+ internalSendMessage(session, message);
+
+ if(!session.isConnected() && (context.isServer() || context.isPermanent())) {
+ String logMessage = context.getDescription() + "(" + context.getAdapterName() + ") | (server||permanent) SEND 후, 세션 연결 끊김 (" + session + ")";
+ logger.error(logMessage);
+ throw new EAIException(logMessage);
+ }
+
+ if (context.isSync()) {
+ try {
+ session.setAttribute("responseTimeout",responseTimeout);
+ session.setIdleTime(IdleStatus.BOTH_IDLE, responseTimeout);
+
+ Object result = handlerState.responseFuture.join(responseTimeout * 1000L);
+ session.removeAttribute("responseTimeout");
+
+ if (result instanceof TimeoutException) {
+ throw new EAITimeoutException("timeout(" + responseTimeout + "), cannot receive result message");
+ } else if (result instanceof Throwable) {
+ throw new EAIException("send/recv(SYNC) faild - " + ((Exception) result).getMessage(), (Throwable) result);
+ } else {
+ ByteMessage m = (ByteMessage) result;
+ if (m.size() >= 7 && new String(m.getBytes(0,7)).startsWith("[RECEAI"))
+ throw new EAIException(m.getString());
+ return m.getBytes();
+ }
+ } finally {
+ handlerState.state = State.STATE_MESSAGE_WAIT_REQUEST;
+ }
+ } else {
+ return null;
+ }
+ } catch(EAITimeoutException e) {
+ sessionPool.remove(session);
+ if(session != null) session.close();
+ String errorMessage = context.getAdapterName() + " | send(/recv) EAITimeoutException - " + e.getMessage();
+ adapter.addRecentError(errorMessage, e);
+ throw new EAITimeoutException(errorMessage, e);
+ } catch(EAIException e) {
+ sessionPool.remove(session);
+ if(session != null) session.close();
+ String errorMessage = context.getAdapterName() + " | send(/recv) EAIException - " + e.getMessage();
+ adapter.addRecentError(errorMessage, e);
+ throw new EAIException(errorMessage, e);
+ } catch(TimeoutException e) {
+ sessionPool.remove(session);
+ if(session != null) session.close();
+ String errorMessage = context.getAdapterName() + " | send(/recv) TimeoutException - " + e.getMessage();
+ adapter.addRecentError(errorMessage, e);
+ throw new EAITimeoutException(errorMessage, e);
+ } catch(Throwable e) {
+ sessionPool.remove(session);
+ if(session != null) session.close();
+ String errorMessage = context.getAdapterName() + " | send(/recv) Throwable - " + e.getMessage();
+ adapter.addRecentError(errorMessage, e);
+ throw new EAIException(errorMessage, e);
+ } finally {
+ if (reservedSession == null) {
+ releaseSession(session);
+ }
+ }
+ }
+
+
+ public IoSession acquireSession() throws EAIException {
+ IoSession session = null;
+
+ if (context.isClient() && !context.isPermanent()) {
+ session = adapter.connectOne();
+
+ if (session == null) {
+ String errorMsg = context.getAdapterName()
+ + " | cannot connect -> " + context.getHostName() + "/" + context.getPortNumber();
+ logger.error(errorMsg);
+ adapter.addRecentError(errorMsg);
+ if (TimeUtil.isSMSRunningTime(context.getSmsRunningTime()))
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA014");
+ throw new EAIConnectException(errorMsg);
+ }
+
+ SimpleFuture handshakeFuture = (SimpleFuture) session.getAttribute(HANDSHAKE_FUTURE);
+ if (handshakeFuture != null) {
+ try {
+ Object result = handshakeFuture.join(context.getTimeout() * 1000L);
+ if (result instanceof Exception) {
+ throw new EAIConnectException(context.getAdapterName() + " | cannot connect error", (Exception) result);
+ }
+ } catch(EAITimeoutException e) {
+ throw new EAIConnectException(context.getAdapterName() + " | handshake faild due to timeout", e);
+ }
+ }
+ } else {
+ /**
+ * client && pool size = 0 일 경우, 10ms만 기다린다.
+ */
+ long timeout = context.getTimeout() * 1000L;
+ if (adapter.getState()==ISocketAdapter.State.STARTED && sessionPool.size()<1) {
+ timeout = 10L;
+ }
+
+ session = sessionPool.acquire(timeout);
+
+ if (session == null) {
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA015");
+ throw new EAINoAvailableConnectionException("cannot get session(=connection) from SessionPool[size=" + sessionPool.size() + ", remaining=" + sessionPool.remaining() + "]");
+ }
+ }
+
+ return session;
+ }
+
+ public void releaseSession(IoSession session) {
+ if (session == null) {
+ return;
+ }
+
+ if (context.isClient() && !context.isPermanent()) {
+ sessionPool.remove(session);
+ session.close();
+ } else {
+ if (session.isClosing()) {
+ sessionPool.remove(session);
+ } else {
+ sessionPool.release(session);
+ }
+ }
+ }
+
+ public Object sendBatch(Object message) throws Exception {
+ return null;
+ /*
+ if (context.getSocketListener() != null) {
+ return ((SocketListener) context.getSocketListener()).messageReceived(request);
+ }
+ */
+ }
+
+ public long getMessageSend() {
+ return messageSend;
+ }
+
+ public long getMessageRecv() {
+ return messageRecv;
+ }
+
+ public synchronized void incMessageSend() {
+ messageSend++;
+ }
+
+ public synchronized void incMessageRecv() {
+ messageRecv++;
+ }
+
+ public void clearStats() {
+ messageSend = 0;
+ messageRecv = 0;
+ }
+
+ protected String getSessionState(IoSession session) {
+ return (String) session.getAttribute(SESSION_STATE);
+ }
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+
+ protected String getHexDump(Object message) {
+ if (message == null) {
+ return "";
+ } else if (message instanceof byte[]) {
+ message = new ByteMessage((byte[]) message);
+ return ((ByteMessage) message).hexDump();
+ } else if (message instanceof String) {
+ message = new ByteMessage((String) message);
+ return ((ByteMessage) message).hexDump();
+ } else {
+ return message.toString();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/SessionPool.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SessionPool.java
new file mode 100644
index 0000000..fb07d8b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SessionPool.java
@@ -0,0 +1,250 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+
+import java.net.InetSocketAddress;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+
+public class SessionPool {
+ private Logger logger = SocketLoggerManager.getInstance().getLogger();
+
+ private ISocketAdapter adapter;
+ private SocketAdapterContext context;
+ private List pool;
+ private List checkedOut;
+
+ public SessionPool(ISocketAdapter adapter, SocketAdapterContext context) {
+ this.adapter = adapter;
+ this.context = context;
+ this.pool = new CopyOnWriteArrayList<>();
+ this.checkedOut = new CopyOnWriteArrayList<>();
+ }
+
+ public synchronized IoSession acquire(IoSession session) {
+ if (pool.remove(session)) {
+ if (!checkedOut.contains(session)) {
+ checkedOut.add(session);
+ }
+ return session;
+ }
+
+ return null;
+ }
+
+ public synchronized IoSession acquire() {
+ return acquire(context.getTimeout() * 1000L, true);
+ }
+
+ public synchronized IoSession acquireYoungest() {
+ return acquire(context.getTimeout() * 1000L, false);
+ }
+
+ public synchronized IoSession acquire(long timeout) {
+ return acquire(timeout, true);
+ }
+
+ private synchronized IoSession acquire(long timeout, boolean pickOld) {
+ long startTime = System.currentTimeMillis();
+ IoSession session;
+
+ while ((session = internalAcquire(timeout, pickOld)) == null) {
+ try {
+ /**
+ * timeout의 1/10 만큼만 기다린다.
+ */
+ wait(timeout/10L);
+ } catch (InterruptedException e) {
+ break;
+ }
+
+ if ((System.currentTimeMillis() - startTime) >= timeout) {
+ // Timeout has expired
+ break;
+ }
+ }
+
+
+ if (session != null) {
+ checkedOut.add(session);
+ }
+
+ return session;
+ }
+
+ private IoSession internalAcquire(long timeout, boolean pickOld) {
+ IoSession session = null;
+
+ if (!pool.isEmpty()) {
+ // pick the first Connection in the vector to get round-robin usage
+ if (pickOld) {
+ session = pool.remove(0);
+ } else {
+ session = pool.remove(pool.size()-1);
+ }
+
+ try {
+ // ##
+ if (session == null || !session.isConnected()) {
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | remove bad connection from IoSessionPool.");
+ }
+
+ // Try again recursively
+ session = acquire(timeout, pickOld);
+ }
+ } catch (Exception e) {
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | remove bad connection from IoSessionPool.");
+ }
+
+ // Try again recursively
+ session = acquire(timeout, pickOld);
+ }
+ }
+
+ return session;
+ }
+
+ public synchronized void release(IoSession session) {
+ if ((session != null) && session.isConnected()) {
+ if (pool.contains(session)) {
+ //throw new RuntimeException(context.getAdapterName() + " | cannot put session into session pool. session already exists in pool (" + session + ")");
+ return;
+ }
+ pool.add(session);
+ checkedOut.remove(session);
+ notifyAll();
+ }
+ }
+
+ public void remove(IoSession session) {
+ pool.remove(session);
+ checkedOut.remove(session);
+ }
+ public void remove(int localPort, int remotePort){
+ for (Iterator iii = pool.iterator() ; iii.hasNext(); ) {
+ IoSession session = iii.next();
+
+ if(session == null) return;
+
+ InetSocketAddress local =(InetSocketAddress)session.getLocalAddress();
+ InetSocketAddress remote =(InetSocketAddress)session.getRemoteAddress();
+
+ if (remote != null && local.getPort() == localPort && remote.getPort() == remotePort ){
+ pool.remove(session);
+ try{
+ session.close();
+ }catch(Exception e){
+ logger.error(e);
+ }
+ break;
+ }
+ }
+
+ }
+ public void sessionValidate(){
+ for (Iterator iii = pool.iterator() ; iii.hasNext(); ) {
+ IoSession session = iii.next();
+ if (session!=null && !session.isConnected()){
+ pool.remove(session);
+ try{
+ session.close();
+ }catch(Exception e){
+ logger.error(e);
+ }
+ }
+ }
+
+ }
+
+ public synchronized int size() {
+ return checkedOut.size() + pool.size();
+ }
+
+ public int peekSize() {
+ return checkedOut.size() + pool.size();
+ }
+
+ public int checkedOut() {
+ return checkedOut.size();
+ }
+
+ public int remaining() {
+ return pool.size();
+ }
+
+ public Iterator iterator() {
+ return pool.iterator();
+ }
+
+ public Iterator checkedOutIterator() {
+ return checkedOut.iterator();
+ }
+
+ public void shutdown() {
+ int count = 0;
+ while (size() > 0 && count++ < 10) {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | session pool shutdown - try count : " + count);
+ }
+
+ for(IoSession session : checkedOut) {
+ try {
+ if (session != null) {
+ if (session.isConnected() && !session.isClosing()) {
+ session.close().join();
+ }
+ checkedOut.remove(session);
+ }
+ } catch(Exception e) {
+ checkedOut.remove(session);
+ logger.error(context.getAdapterName() + " | " + e.getMessage(), e);
+ adapter.addRecentError(context.getAdapterName() + " | " + ExceptionStackTrace.dump(e));
+ }
+ }
+
+ IoSession session = null;
+ while (pool.size() > 0) {
+ try {
+ session = acquire(1000L, true);
+ if (session != null) {
+ if (session.isConnected() && !session.isClosing()) {
+ session.close().join();
+ }
+ pool.remove(session);
+ }
+ } catch(Exception e) {
+ pool.remove(session);
+ logger.error(context.getAdapterName() + " | " + e.getMessage(), e);
+ adapter.addRecentError(context.getAdapterName() + " | " + ExceptionStackTrace.dump(e));
+ }
+ }
+
+ try {
+ Thread.sleep(100L);
+ } catch(Exception e) {
+ logger.error(context.getAdapterName() + " | session pool sleep error.", e);
+ }
+ }
+
+ if (count >= 100) {
+ logger.error(context.getAdapterName() + " | session pool shutdown failed - garbage connection left");
+ adapter.addRecentError(context.getAdapterName() + " | session pool shutdown failed - garbage connection left");
+ }
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[SessionPool of " + context.getAdapterName());
+ sb.append(" | pool:" + pool.size());
+ sb.append(" | checkedout:" + checkedOut.size() + "]");
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapter.java
new file mode 100644
index 0000000..91543cc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapter.java
@@ -0,0 +1,250 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.mina.common.IoSession;
+
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.EAIConnectException;
+import com.eactive.eai.adapter.socket2.common.CircularQueue;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.common.util.Logger;
+
+import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
+import edu.emory.mathcs.backport.java.util.concurrent.Executors;
+import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor;
+import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
+
+public abstract class SocketAdapter implements ISocketAdapter {
+ static final int MAX_LOG_MESSAGE_SIZE = 100000;
+
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ protected State state = State.STOPPED;
+
+ protected SocketAdapterContext context;
+ protected ProtocolHandler handler;
+ protected ExecutorService executor;
+ protected Hashtable threadMap = new Hashtable<>();
+
+ protected static CircularQueue globalErrorQueue = new CircularQueue(10);
+ protected CircularQueue recentErrorQueue = new CircularQueue(10);
+ protected CircularQueue recentSendRecvQueue = new CircularQueue(10);
+
+ protected Date uptime;
+
+ protected void startExecutor() {
+ this.executor = Executors.newCachedThreadPool();
+ ((ThreadPoolExecutor) this.executor).setKeepAliveTime(1L, TimeUnit.SECONDS);
+ }
+
+ protected SocketAdapter(SocketAdapterContext context) {
+ this.context = context;
+ startExecutor();
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+
+ this.uptime = new Date();
+ }
+
+ public SocketAdapterContext getContext() {
+ return context;
+ }
+
+ public void setTraceLevel(int traceLevel) {
+ context.setTraceLevel(traceLevel);
+ }
+
+ public boolean connect() throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ public IoSession connectOne() throws EAIConnectException {
+ throw new UnsupportedOperationException();
+ }
+
+ public SessionPool getSessionPool() {
+ return handler.getSessionPool();
+ }
+
+ public Map getThreadMap() {
+ return threadMap;
+ }
+
+ public long getMessageSend() {
+ return handler.getMessageSend();
+ }
+
+ public long getMessageRecv() {
+ return handler.getMessageRecv();
+ }
+
+ public void incMessageSend() {
+ handler.incMessageSend();
+ }
+
+ public void incMessageRecv() {
+ handler.incMessageRecv();
+ }
+
+ public State getState() {
+ return this.state;
+ }
+
+ public void setState(State state) {
+ this.state = state;
+ }
+
+ public int getRecentErrorCount() {
+ return recentErrorQueue.getRecordCount();
+ }
+
+ public String[] getRecentErrors() {
+ return recentErrorQueue.getRecords();
+ }
+
+ public static String[] getGlobalErrors() {
+ return globalErrorQueue.getRecords();
+ }
+
+ public void addRecentError(String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE/10)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE/10);
+ recentErrorQueue.addRecord(message);
+ globalErrorQueue.addRecord(message);
+ }
+
+ public void addRecentError(String message, Throwable t) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE/10)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE/10);
+ recentErrorQueue.addRecord(message + "\n" + ExceptionStackTrace.dump(t));
+ globalErrorQueue.addRecord(message + "\n" + ExceptionStackTrace.dump(t));
+ }
+
+ public void addRecentErrorOnly(String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE/10)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE/10);
+ recentErrorQueue.addRecord(message);
+ //globalErrorQueue.addRecord(message);
+ }
+
+ public void addRecentErrorOnly(String message, Throwable t) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE/10)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE/10);
+ recentErrorQueue.addRecord(message + "\n" + ExceptionStackTrace.dump(t));
+ //globalErrorQueue.addRecord(message + "\n" + ExceptionStackTrace.dump(t));
+ }
+
+ public void addRecentLog(String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+ recentSendRecvQueue.addRecord(message);
+ }
+
+ public void addRecentSend(IoSession session, String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+ recentSendRecvQueue.addRecord(" " + (session==null ? "" : "(" + session + ") - ") + message);
+ }
+
+ public void addRecentRecv(IoSession session, String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+ recentSendRecvQueue.addRecord(" " + (session==null ? "" : "(" + session + ") - ") + message);
+ }
+
+ public void addRecentSendTrace(IoSession session, String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+ recentSendRecvQueue.addRecord(" " + (session==null ? "" : "(" + session + ") - ") + message + " ");
+ }
+
+ public void addRecentRecvTrace(IoSession session, String message) {
+ if (message == null)
+ return;
+ if (message.length() > MAX_LOG_MESSAGE_SIZE)
+ message = message.substring(0, MAX_LOG_MESSAGE_SIZE);
+ recentSendRecvQueue.addRecord(" " + (session==null ? "" : "(" + session + ") - ") + message + " ");
+ }
+
+ public String[] getRecentSendRecv() {
+ return recentSendRecvQueue.getRecords();
+ }
+
+ public void clearStat() {
+ recentErrorQueue.clear();
+ recentSendRecvQueue.clear();
+ handler.clearStats();
+ }
+
+ public void resumeRead() {
+ }
+
+ public void resumeWrite() {
+ }
+
+ public void suspendRead() {
+ }
+
+ public void suspendWrite() {
+ }
+
+ public Object sendMessage(Object message) throws EAIException {
+ return handler.sendMessage(null, message);
+ }
+
+ public Object sendMessage(Object message, int responseTimeout) throws EAIException {
+ return handler.sendMessage(null, message, responseTimeout);
+ }
+
+ public Object sendMessage(IoSession reservedSession, Object message) throws EAIException {
+ return handler.sendMessage(reservedSession, message);
+ }
+
+ public IoSession acquireSession() throws Exception {
+ return handler.acquireSession();
+ }
+
+ public void releaseSession(IoSession session) {
+ handler.releaseSession(session);
+ }
+
+ public void setAdapterStatus(boolean status) {
+ AdapterVO vo = getContext().getAdapterVO();
+ if (vo != null) {
+ vo.setStatus(status);
+ }
+ }
+
+ public Date getUptime() {
+ return uptime;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(context.getAdapterName() + " | sessionPool size : " + handler.getSessionPool().size());
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapterClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapterClient.java
new file mode 100644
index 0000000..2bb4eb9
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapterClient.java
@@ -0,0 +1,413 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.TimeoutException;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.ThreadModel;
+import org.apache.mina.common.support.BaseIoConnector;
+import org.apache.mina.common.support.BaseIoConnectorConfig;
+import org.apache.mina.filter.SSLFilter;
+import org.apache.mina.util.NewThreadExecutor;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.EAIConnectException;
+import com.eactive.eai.adapter.socket2.common.ExecutionContext;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.filter.datacontrol.DataControlFilter;
+import com.eactive.eai.adapter.socket2.filter.executor.BoundedExecutorFilter;
+import com.eactive.eai.adapter.socket2.filter.initmsgshake.InitMsgFilter;
+import com.eactive.eai.adapter.socket2.filter.polling.PollingFilter;
+import com.eactive.eai.adapter.socket2.filter.ssl.SSLContextFactory;
+import com.eactive.eai.adapter.socket2.filter.validation.ValidationFilter;
+import com.eactive.eai.common.server.EAIServerManager;
+import com.eactive.eai.common.session.SessionManager;
+import com.eactive.eai.common.session.SessionVO;
+import com.eactive.eai.util.HealthCheckManager;
+
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor;
+
+
+public abstract class SocketAdapterClient extends SocketAdapter {
+ protected Executor ioProcessExecutor;
+ protected BaseIoConnector connector;
+ protected BaseIoConnectorConfig config;
+ private Thread launcher = null;
+
+ protected SocketAdapterClient(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ if (context.getMaxConnection() == 0) {
+ context.setMaxConnection(1);
+ }
+
+ /**
+ * Configure the service.
+ */
+ config = createConnectorConfig();
+
+ config.setConnectTimeout(context.getTimeout());
+ config.setThreadModel(ThreadModel.MANUAL);
+
+ /**
+ * filters
+ */
+ config.getFilterChain().addFirst("threadPool", new BoundedExecutorFilter(this, executor));
+ //config.getFilterChain().addLast("logger", new LoggingFilter());
+
+ if ("Y".equals(context.getSslUse())) {
+ SSLContext sslContext = SSLContextFactory.createSSLContext(context);
+ SSLFilter sslFilter = new SSLFilter(sslContext);
+ sslFilter.setUseClientMode(true);
+ config.getFilterChain().addLast("ssl", sslFilter);
+ }
+
+ //KSH
+ if (context.isInitMsgUse()) {
+ config.getFilterChain().addLast("initMsg", new InitMsgFilter(this));
+ }
+
+ if (context.isPollingUse()) {
+ config.getFilterChain().addLast("polling", new PollingFilter(this));
+ }
+
+
+ if (!"".equals(context.getValidationRule().trim())) {
+ config.getFilterChain().addLast("validation", new ValidationFilter(this));
+ }
+ if (!"".equals(context.getDataControlRule().trim())) {
+ config.getFilterChain().addLast("datacontrol", new DataControlFilter(this));
+ }
+ }
+
+ public SimpleFuture start() throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | start client socket adapter.");
+ }
+
+ switch(getState()) {
+ case STARTED:
+ throw new Exception(context.getAdapterName() + " | socket adapter already started. - " + getState().name());
+ case STARTING:
+ throw new Exception(context.getAdapterName() + " | socket adapter already starting... - " + getState().name());
+ case STOPPING:
+ throw new Exception(context.getAdapterName() + " | socket adapter shutdown progressing. - " + getState().name());
+ default:
+ break;
+ }
+
+ /**
+ * start protocol handler
+ */
+ handler.start();
+
+ /**
+ * io process executor
+ */
+ ioProcessExecutor = new NewThreadExecutor();
+
+ /**
+ * determine ioProcessor count
+ */
+ int ioProcessorCount1 = 1 + Runtime.getRuntime().availableProcessors();
+ int ioProcessorCount2 = 1 + (context.getMaxThread() / 10);
+ int ioProcessorCount = ioProcessorCount1 < ioProcessorCount2 ? ioProcessorCount1 : ioProcessorCount2;
+
+ /**
+ * create connector
+ */
+ connector = createConnector(ioProcessorCount, ioProcessExecutor);
+
+ setState(State.STARTING);
+
+ final SimpleFuture future = new SimpleFuture();
+// final ISocketAdapter adapter = this;
+
+ if (!context.isPermanent()) {
+ setAdapterStatus(true);
+ setState(State.STARTED);
+ future.set(Boolean.TRUE);
+ return future;
+ }
+
+ Runnable runnable = new Runnable() {
+ public void run() {
+ boolean retry = true;
+ while(true) {
+ try {
+ if(getState() == State.STARTED
+ || getState() == State.STOPPING
+ || getState() == State.STOPPED) {
+ logger.warn("Exit Launcher - " + context.getAdapterName() + "-Terminator");
+ return;
+ }
+
+ retry = true;
+ if(context.getSingleSession().equals("Y")) {
+ String adapterGroupoName = context.getAdapterGroupName();
+ SessionVO sessionVo = SessionManager.getInstance().getConnectionStatus(adapterGroupoName);
+
+ // 싱글어댑터 - Start ---------------------------------------------------------------------------------------------------------------------
+ String primaryInst = context.getPrimaryInstId();
+ EAIServerManager eaiServerManager = EAIServerManager.getInstance();
+ String localServerName = eaiServerManager.getLocalServerName();
+
+ if ( localServerName.equals(primaryInst)) { // CASE : Primary 서버
+ SessionVO sessionVO = SessionManager.getInstance().getConnectionStatus(adapterGroupoName);
+
+ if (sessionVO != null) {
+ if(localServerName.equals(sessionVO.getLoginInstId())) {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + "| SingleSession Validation, local server exist [" +sessionVO.getLoginInstId()+"], remove cache -> retry to connect after 10 secs");
+ }
+ SessionManager.getInstance().removeConnectionInfo(adapterGroupoName);
+ }
+ else {// Secondary 서버가 연결하고 있음
+ retry = false;
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + "| SingleSession Validation, Secondary server exist [" +sessionVO.getLoginInstId()+"]");
+ }
+ }
+ } else {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + "| SingleSession Validation, Connection empty -> retry to connect after 10 secs");
+ }
+
+ }
+ } else { // CASE : Secondary 서버
+ boolean isAlive = HealthCheckManager.getInstance().getServerStatus(primaryInst);
+
+ if (isAlive) { // Primary 서버 살아있으면 재연결 시도 안함
+ retry = false;
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG)
+ logger.debug(context.getAdapterName() + "| SingleSession Validation, Primary server exist [" +primaryInst+"]");
+ } else {
+ SessionManager.getInstance().removeConnectionInfo(adapterGroupoName);
+ }
+
+ SessionVO svo = SessionManager.getInstance().getConnectionInfo(adapterGroupoName);
+
+ if (svo != null) {
+ String connectedInst = svo.getLoginInstId();
+ if(connectedInst.equals(localServerName))
+ SessionManager.getInstance().removeConnectionInfo(adapterGroupoName);
+ }
+ }
+ // 싱글어댑터 - End ---------------------------------------------------------------------------------------------------------------------
+
+
+ if(sessionVo != null) {
+ retry = false;
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | SingleSession Validation Exist ["+sessionVo.getLoginInstId() +"] -> retry to connect after 10 seconds...");
+ }
+ }
+ else {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | SingleSession Validation Connection Empty -> retry to connect after 10 seconds...");
+ }
+ }
+ }
+
+ if(retry) {
+ boolean result = connect();
+
+ if (result && getSessionPool().size() > 0) {
+ setAdapterStatus(true);
+ context.setStarted(true);
+ setState(State.STARTED);
+ future.set(Boolean.TRUE);
+ break;
+ } else {
+ setAdapterStatus(false);
+ context.setStarted(false);
+ future.set(Boolean.FALSE);
+ getSessionPool().shutdown();
+ }
+ }
+ } catch(Throwable t) {
+ setAdapterStatus(false);
+ context.setStarted(false);
+ future.set(t);
+ getSessionPool().shutdown();
+ }
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG
+ && retry && logger.isDebug()) {
+ logger.debug(context.getAdapterName() + " | failed to connect -> retry to connect after 10 seconds...");
+ }
+
+ try {
+ Thread.sleep(10000L);
+ } catch(InterruptedException e) {
+ if(logger.isDebug()) {
+ logger.debug(context.getAdapterName() + " sleep error - " + e.getMessage());
+ }
+ }
+ }
+ }
+ };
+ //executor.execute(runnable);
+ launcher = new Thread(runnable);
+ launcher.setName(context.getAdapterName() + "-Launcher");
+ launcher.start();
+
+ return future;
+ }
+
+ public SimpleFuture stop() throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | stop client socket adapter.");
+ }
+
+ switch(getState()) {
+ case STOPPING:
+ case STOPPED:
+ logger.warn(context.getAdapterName() + " | socket adapter already " + getState().name());
+ final SimpleFuture future = new SimpleFuture();
+ future.set(Boolean.TRUE);
+ return future;
+ default:
+ break;
+ }
+
+ return doStop();
+ }
+
+ public SimpleFuture stopForcely() throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | stop client socket adapter forcely.");
+ }
+ return doStop();
+ }
+
+ private SimpleFuture doStop() throws Exception {
+ setState(State.STOPPING);
+ context.setStarted(false);
+
+ final SimpleFuture future = new SimpleFuture();
+
+ Runnable runnable = new Runnable() {
+ public void run() {
+ try {
+ handler.stop();
+ getSessionPool().shutdown();
+ setAdapterStatus(false);
+ setState(State.STOPPED);
+// List list = ioProcessExecutor.shutdownNow();
+// for (Iterator iter = list.iterator(); iter.hasNext(); ) {
+// ((Thread) iter.next()).interrupt();
+// }
+ future.set(Boolean.TRUE);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | socket adapter stopped.");
+ }
+ } catch(Exception e) {
+ logger.error(context.getAdapterName() + " | socket adapter stop process failed.", e);
+ addRecentError(context.getAdapterName() + " | socket adapter stop process failed.", e);
+ future.set(e);
+ }
+ }
+ };
+ //executor.execute(runnable);
+ Thread t = new Thread(runnable);
+ t.setName(context.getAdapterName() + "-Terminator");
+ t.start();
+
+ return future;
+ }
+
+ @Override
+ public boolean connect() throws Exception {
+ for (int i = 0; i < context.getMaxConnection(); i++) {
+ IoSession session = connectOne();
+ if (session == null) {
+ setState(State.STOPPED);
+ context.setStarted(false);
+ throw new Exception(context.getAdapterName() + " | failed to establish connection ... ");
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public IoSession connectOne() throws EAIConnectException {
+ InetSocketAddress remoteAddress = new InetSocketAddress(context.getHostName(), context.getPortNumber());
+ InetSocketAddress localAddress = null;
+
+ if (context.getLocalPortNumber() > 0 || context.getLocalHostName().trim().length() > 0) {
+ localAddress = new InetSocketAddress(context.getLocalHostName(), context.getLocalPortNumber());
+ }
+
+ IoSession session = null;
+
+ try {
+ ConnectFuture future = connector.connect(
+ remoteAddress,
+ localAddress,
+ handler,
+ config);
+
+ /**
+ * inbound connection 이 끊어졌을 경우,
+ * outbound connection 시도 작업을 중단한다.
+ */
+ ExecutionContext executionContext = ExecutionContext.getInstance();
+ IoSession sess = (IoSession) executionContext.get("session");
+ if (sess != null) {
+ sess.setAttribute("connectFuture", future);
+ }
+
+ boolean success = future.join(context.getTimeout() * 1000L);
+ if (success) {
+ session = future.getSession();
+ if(!session.isConnected()) {
+ throw new EAIException("session closed by peer (" + session + ")");
+ }
+ return session;
+ } else {
+ throw new TimeoutException("connect timeout '" + context.getTimeout() + "' sec");
+ }
+ } catch (Exception e) {
+ if (session != null && session.isConnected()) {
+ try {
+ getSessionPool().remove(session);
+ session.close().join();
+ } catch(Exception ee) {
+ logger.warn(context.getAdapterName() +" session close error");
+ }
+ }
+ String errorMessage = context.getAdapterName()
+ + " | cannot connect - " + context.getHostName() + "/" + context.getPortNumber();
+ logger.error(errorMessage, e);
+
+ if (getState() != State.STARTING) {
+ addRecentError(errorMessage, e);
+ } else {
+ addRecentErrorOnly(errorMessage, e);
+ }
+
+ try {
+ if (TimeUtil.isSMSRunningTime(context.getSmsRunningTime()))
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA014");
+ } catch(Throwable t) {
+ logger.debug("[EAIDEBUG] SMS logging Error occured. but ignore this. - " + t.toString());
+ }
+
+ context.setStarted(false);
+
+ throw new EAIConnectException("cannot connect - " + context.getHostName() + "/" + context.getPortNumber(), e);
+ }
+ }
+
+ abstract protected BaseIoConnectorConfig createConnectorConfig();
+ abstract protected BaseIoConnector createConnector(int ioProcessorCount, Executor ioProcessExecutor);
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapterServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapterServer.java
new file mode 100644
index 0000000..33054fc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/SocketAdapterServer.java
@@ -0,0 +1,224 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.filter.acl.AclFilter;
+import com.eactive.eai.adapter.socket2.filter.acl.BlockIpFilter;
+import com.eactive.eai.adapter.socket2.filter.acl.L4SkipIpFilter;
+import com.eactive.eai.adapter.socket2.filter.datacontrol.DataControlFilter;
+import com.eactive.eai.adapter.socket2.filter.executor.BoundedExecutorFilter;
+import com.eactive.eai.adapter.socket2.filter.initmsgshake.InitMsgFilter;
+import com.eactive.eai.adapter.socket2.filter.limit.ConnectionLimitFilter;
+import com.eactive.eai.adapter.socket2.filter.polling.PollingFilter;
+import com.eactive.eai.adapter.socket2.filter.ssl.SSLContextFactory;
+import com.eactive.eai.adapter.socket2.filter.validation.ValidationFilter;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
+import edu.emory.mathcs.backport.java.util.concurrent.Executors;
+import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor;
+
+import org.apache.mina.common.ThreadModel;
+import org.apache.mina.common.support.BaseIoAcceptor;
+import org.apache.mina.common.support.BaseIoAcceptorConfig;
+import org.apache.mina.filter.SSLFilter;
+
+import javax.net.ssl.SSLContext;
+import java.net.InetSocketAddress;
+import java.util.Iterator;
+import java.util.List;
+
+
+public abstract class SocketAdapterServer extends SocketAdapter {
+ protected ExecutorService ioProcessExecutor;
+ protected BaseIoAcceptor acceptor;
+ protected BaseIoAcceptorConfig config;
+
+ protected SocketAdapterServer(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ config = createAcceptorConfig();
+
+ config.setThreadModel(ThreadModel.MANUAL);
+
+ /**
+ * filters
+ */
+ config.getFilterChain().addFirst("threadPool", new BoundedExecutorFilter(this, executor));
+ //config.getFilterChain().addLast("logger", new LoggingFilter());
+
+ if (!"".equals(context.getL4SkipIpList().trim())) {
+ config.getFilterChain().addLast("l4SkipIp", new L4SkipIpFilter(this));
+ }
+ if (!"".equals(context.getBlockIpList().trim())) {
+ config.getFilterChain().addLast("blockIp", new BlockIpFilter(this));
+ }
+ // polling response 후 LIMIT Filter에 걸리는 경우가 있어 ACL, LIMIT Filter를 앞에 둠
+ if (!"".equals(context.getAclList().trim())) {
+ config.getFilterChain().addLast("acl", new AclFilter(this));
+ }
+
+ if (context.getMaxConnection() > 0 || context.getConnLimitPerIp() > 0) {
+ config.getFilterChain().addLast("limit", new ConnectionLimitFilter(this));
+ }
+
+ if ("Y".equals(context.getSslUse())) {
+ SSLContext sslContext = SSLContextFactory.createSSLContext(context);
+ SSLFilter sslFilter = new SSLFilter(sslContext);
+ config.getFilterChain().addLast("ssl", sslFilter);
+ }
+
+ if (context.isInitMsgUse()) {
+ config.getFilterChain().addLast("initMsg", new InitMsgFilter(this));
+ }
+
+ if (context.isPollingUse()) {
+ config.getFilterChain().addLast("polling", new PollingFilter(this));
+ }
+
+ if (!"".equals(context.getValidationRule().trim())) {
+ config.getFilterChain().addLast("validation", new ValidationFilter(this));
+ }
+ if (!"".equals(context.getDataControlRule().trim())) {
+ config.getFilterChain().addLast("datacontrol", new DataControlFilter(this));
+ }
+ }
+
+ public SimpleFuture start() throws Exception {
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | start server socket adapter.");
+ }
+
+ switch(getState()) {
+ case STARTED:
+ throw new Exception(context.getAdapterName() + " | socket adapter already started - " + getState().name());
+ case STARTING:
+ throw new Exception(context.getAdapterName() + " | socket adapter booting process already started - " + getState().name());
+ case STOPPING:
+ throw new Exception(context.getAdapterName() + " | socket adapter shutdown progressing - " + getState().name());
+ default:
+ break;
+ }
+
+ /**
+ * start protocol handler
+ */
+ handler.start();
+
+ /**
+ * ioProcessorExecutor
+ */
+ ioProcessExecutor = Executors.newCachedThreadPool();
+
+ /**
+ * determine ioProcessor count
+ */
+ int ioProcessorCount1 = 1 + Runtime.getRuntime().availableProcessors();
+ int ioProcessorCount2 = 1 + (context.getMaxThread() / 10);
+ int ioProcessorCount = ioProcessorCount1 < ioProcessorCount2 ? ioProcessorCount1 : ioProcessorCount2;
+
+ /**
+ * create acceptor
+ */
+ acceptor = createAcceptor(ioProcessorCount, ioProcessExecutor);
+
+ setState(State.STARTING);
+ SimpleFuture future = new SimpleFuture();
+
+ /**
+ * bind
+ */
+ try {
+ acceptor.bind(new InetSocketAddress(context.getPortNumber()), handler, config);
+ if (!context.isPermanent()) {
+ setAdapterStatus(true);
+ }
+ setState(State.STARTED);
+ context.setStarted(true);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | socket adapter listening on port " + context.getPortNumber());
+ }
+
+ future.set(Boolean.TRUE);
+
+ return future;
+ } catch(Exception e) {
+ logger.error(context.getAdapterName() + " | " + e.getMessage(), e);
+ addRecentError(context.getAdapterName() + " | " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA013");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA013");
+ setAdapterStatus(false);
+ context.setStarted(false);
+ setState(State.STOPPED);
+ future.set(Boolean.FALSE);
+ return future;
+ }
+ }
+
+ public SimpleFuture stop() throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | stop server socket adapter.");
+ }
+
+ switch(getState()) {
+ case STOPPING:
+ case STOPPED:
+ throw new Exception(context.getAdapterName() + " | socket adapter already " + getState().name());
+ default:
+ break;
+ }
+
+ return doStop();
+ }
+
+ public SimpleFuture stopForcely() throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | stop server socket adapter forcely.");
+ }
+
+ return doStop();
+ }
+
+ private SimpleFuture doStop() throws Exception {
+ setState(State.STOPPING);
+ context.setStarted(false);
+
+ final SimpleFuture future = new SimpleFuture();
+
+ Runnable runnable = new Runnable() {
+ public void run() {
+ try {
+ acceptor.unbindAll();
+ handler.stop();
+ getSessionPool().shutdown();
+ setAdapterStatus(false);
+ setState(State.STOPPED);
+ List list = ioProcessExecutor.shutdownNow();
+ for (Iterator iter = list.iterator(); iter.hasNext(); ) {
+ ((Thread) iter.next()).interrupt();
+ }
+ future.set(Boolean.TRUE);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | socket adapter stopped.");
+ }
+ } catch(Exception e) {
+ logger.error(context.getAdapterName() + " | socket adapter stop process failed.", e);
+ addRecentError(context.getAdapterName() + " | socket adapter stop process failed.", e);
+ future.set(e);
+ }
+ }
+ };
+
+ //executor.execute(runnable);
+ Thread t = new Thread(runnable);
+ t.setName(context.getAdapterName() + "-Terminator");
+ t.start();
+
+ return future;
+ }
+
+ protected abstract BaseIoAcceptorConfig createAcceptorConfig();
+ protected abstract BaseIoAcceptor createAcceptor(int ioProcessorCount, Executor ioProcessExecutor);
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/TcpAdapterClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/TcpAdapterClient.java
new file mode 100644
index 0000000..2df8cb5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/TcpAdapterClient.java
@@ -0,0 +1,25 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.support.BaseIoConnector;
+import org.apache.mina.common.support.BaseIoConnectorConfig;
+import org.apache.mina.transport.socket.nio.SocketConnector;
+import org.apache.mina.transport.socket.nio.SocketConnectorConfig;
+
+
+public abstract class TcpAdapterClient extends SocketAdapterClient {
+ protected TcpAdapterClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ }
+
+ protected BaseIoConnectorConfig createConnectorConfig() {
+ return new SocketConnectorConfig();
+ }
+
+ protected BaseIoConnector createConnector(int ioProcessorCount, Executor ioProcessExecutor) {
+ SocketConnector connector = new SocketConnector(ioProcessorCount, ioProcessExecutor, this);
+ connector.setWorkerTimeout(1);
+ return connector;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/TcpAdapterServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/TcpAdapterServer.java
new file mode 100644
index 0000000..c56be74
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/TcpAdapterServer.java
@@ -0,0 +1,30 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.support.BaseIoAcceptor;
+import org.apache.mina.common.support.BaseIoAcceptorConfig;
+import org.apache.mina.transport.socket.nio.SocketAcceptor;
+import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
+
+
+abstract public class TcpAdapterServer extends SocketAdapterServer {
+ public TcpAdapterServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ }
+
+ protected BaseIoAcceptorConfig createAcceptorConfig() {
+ SocketAcceptorConfig config = new SocketAcceptorConfig();
+
+ //config.getSessionConfig().setSoLinger(0);
+
+ // to reuse TIME_WAIT state port
+ config.setReuseAddress("Y".equals(context.getSocketReuse()) ? true : false);
+
+ return config;
+ }
+
+ protected BaseIoAcceptor createAcceptor(int ioProcessorCount, Executor ioProcessExecutor) {
+ return new SocketAcceptor(ioProcessorCount, ioProcessExecutor, this);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/UdpAdapterClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/UdpAdapterClient.java
new file mode 100644
index 0000000..6e4645f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/UdpAdapterClient.java
@@ -0,0 +1,28 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.support.BaseIoConnector;
+import org.apache.mina.common.support.BaseIoConnectorConfig;
+import org.apache.mina.transport.socket.nio.DatagramConnector;
+import org.apache.mina.transport.socket.nio.DatagramConnectorConfig;
+import org.apache.mina.transport.socket.nio.support.DatagramConnectorDelegate;
+
+
+public abstract class UdpAdapterClient extends SocketAdapterClient {
+ protected UdpAdapterClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ }
+
+ protected BaseIoConnectorConfig createConnectorConfig() {
+ DatagramConnectorConfig config = new DatagramConnectorConfig();
+ //config.setSessionRecycler(new ExpiringSessionRecycler(24 * 60 * 60));
+ return config;
+ }
+
+ protected BaseIoConnector createConnector(int ioProcessorCount, Executor ioProcessExecutor) {
+ DatagramConnector dc = new DatagramConnector();
+ DatagramConnectorDelegate connector = new DatagramConnectorDelegate(dc, ioProcessExecutor, this);
+ return connector;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/UdpAdapterServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/UdpAdapterServer.java
new file mode 100644
index 0000000..bf1932a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/UdpAdapterServer.java
@@ -0,0 +1,29 @@
+package com.eactive.eai.adapter.socket2.protocol;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.support.BaseIoAcceptor;
+import org.apache.mina.common.support.BaseIoAcceptorConfig;
+import org.apache.mina.transport.socket.nio.DatagramAcceptor;
+import org.apache.mina.transport.socket.nio.DatagramAcceptorConfig;
+import org.apache.mina.transport.socket.nio.support.DatagramAcceptorDelegate;
+
+
+public abstract class UdpAdapterServer extends SocketAdapterServer {
+ protected UdpAdapterServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ }
+
+ protected BaseIoAcceptorConfig createAcceptorConfig() {
+ DatagramAcceptorConfig config = new DatagramAcceptorConfig();
+ config.setDisconnectOnUnbind(true);
+ //config.setSessionRecycler(new ExpiringSessionRecycler(24 * 60 * 60 ));
+ return config;
+ }
+
+ protected BaseIoAcceptor createAcceptor(int ioProcessorCount, Executor ioProcessExecutor) {
+ DatagramAcceptor da = new DatagramAcceptor();
+ DatagramAcceptorDelegate acceptor = new DatagramAcceptorDelegate(da, ioProcessExecutor, this);
+ return acceptor;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/adapter_properties.txt b/src/main/java/com/eactive/eai/adapter/socket2/protocol/adapter_properties.txt
new file mode 100644
index 0000000..7b26e4b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/adapter_properties.txt
@@ -0,0 +1,140 @@
+ basic
+ fixed
+ welcome
+ envelope
++--------------------------------------------------------------------------------------------------------------------------------------------+
+|protocol |HTTP |FIXED_H_L|UDP_F_H_L|FIXED_P_L|UDP_F_P_L|CISCO |XECURE |INISAFE |CERT |EGSEED |XECURE2 |
+|--------------------------------------------------------------------------------------------------------------------------------------------|
+|protocol |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|permanent |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|blocking | |0 |0 | | | | | | | | |
+|adapter.group.name |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|adapter.name |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|bound.usage |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|host.name |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|port.number |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|(c)local.host.name |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|(c)local.port.number |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|socket.type |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|ack.support | |0 | | | | | | | | | |
+|response.type |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|business.work.class.code |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|(s)connection.limit.per.ip |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|(s)acl.list |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|max.connection |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|max.thread |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|(s)socket.reuse |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|timeout |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|idle.timeout |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|validation.rule |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|trace.level |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|description |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|(c)sms.running.time |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+|----------------------------------------------------------------------------------------------------------------------------------|---------|
+|polling.use | |0 | | | | | | | | | |
+|polling.role | |0 | | | | | | | | | |
+|polling.oneway | |0 | | | | | | | | | |
+|(S)polling.timeout | |0 | | | | | | | | | |
+|(S)polling.request | |0 | | | | | | | | | |
+|(R)polling.request.pattern | |0 | | | | | | | | | |
+|(R)polling.replacement | |0 | | | | | | | | | |
+|(S)polling.response.pattern | |0 | | | | | | | | | |
+|----------------------------------------------------------------------------------------------------------------------------------|---------|
+|ll.field.type | |0 |0 | | | |0 | | |0 |0 |
+|ll.field.length | |0 |0 | | | |0 | | |0 |0 |
+|ll.field.offset | |0 |0 | | | |0 | | |0 |0 |
+|ll.field.include | |0 |0 | | | |0 | | |0 |0 |
+|ll.offset.exclude | |0 |0 | | | |0 | | |0 |0 |
+|ll.include | |0 |0 | | | |0 | | |0 |0 |
+|----------------------------------------------------------------------------------------------------------------------------------|---------|
+|send.payload.length | | | |0 |0 | | | | | | |
+|recv.payload.length | | | |0 |0 | | | | | | |
+|----------------------------------------------------------------------------------------------------------------------------------|---------|
+|xecure.type | | | | | | |0 | | | | |
+|xecure.config.path | | | | | | |0 | | | | |
+|(cfg)xecure.local.cert | | | | | | |0 | | | | |
+|(cfg)xecure.local.key | | | | | | |0 | | | | |
+|(cfg)xecure.local.password | | | | | | |0 | | | | |
+|xecure.remote.cert | | | | | | |0 | | | | |
+|----------------------------------------------------------------------------------------------------------------------------------|---------|
+|inisafe.config.path | | | | | | | |0 | | | |
+|inisafe.related.adapter.groups| | | | | | | |0 | | | |
+|inisafe.start.message | | | | | | | |0 | | | |
+|inisafe.stop.message | | | | | | | |0 | | | |
+|----------------------------------------------------------------------------------------------------------------------------------|---------|
+|ssl.use | | | | | | | | | | | |
+|ssl.cert.store | | | | | | | | | | | |
+|ssl.cert.password | | | | | | | | | | | |
++----------------------------------------------------------------------------------------------------------------------------------+---------+
+|(cfg)xecure2.config.path | | | | | | | | | | |0 |
+|xecure2.sm.ip | | | | | | | | | | |0 |
+|xecure2.sm.port | | | | | | | | | | |0 |
++----------------------------------------------------------------------------------------------------------------------------------+---------+
+ (c)client (s)server (cfg)config file (S) sender (R) receiver
+
+
+
+
+
++--------------------------------------------------------------------------------------------------------------+
+|protocol | 접속 통신규약을 정하는 항목 |
+|permanent | 거래시 마다 접속을 유지할지 끊을지 판단하는 항목 |
+|blocking | 소켓 접속시 Blocking 모드로 할지 Non-Blocking모드를 할지 판단하는 항목 |
+| | |
+|adapter.group.name | 아답터의 그룹명 |
+|bound.usage | 나가는 거래인지 들어오는거래인지 판단하는 항목 |
+|host.name | 바인딩 되는 아이피 |
+|port.number | 바인딩 되는 포트 |
+|local.host.name | 로컬에 바인딩 되는 아이피 |
+|local.port.number | 로컬에 바인딩 되는 포트 |
+|socket.type | 서버인지 클라이언트인지 판단하는 항목 |
+|ack.support | 응답을 받을지 판단하는 항목 |
+|response.type | 응답방법(동기/비동기) |
+|business.work.class.code | 업무를 구분하기위한 코드 |
+|connection.limit.per.ip | 아이피당 접속을 제한하는 항목 |
+|max.connection | 최대 접속 갯수를 제한하는 항목 |
+|max.thread | 거래 처리시 최대 쓰레드 갯수를 제한하는 항목 |
+|socket.reuse | 서버 소켓일경우 이전 소켓을 무시하고 재사용하는 항목 |
+|timeout | 거래시 데이타가 안들어올경우 타임아웃 항목 |
+|idle.timeout | 접속후 데이타를 안보내거나 안받을 경우 타이아웃 항목 |
+|validation.rule | 거래가 들어올경우 룰에 안맞는건 error처리 |
+|trace.level | 거래로그 레벨 |
+|description | 설명 |
+|sms.running.time | sms 발송시간, value = [BUSINESS_DAY | ALL_WEEK],%d{HHmmss},%d{HHmmss} |
+|--------------------------------------------------------------------------------------------------------------|
+|polling.use | 폴링 사용유무 |
+|polling.timeout | 폴링 타임아웃 |
+|polling.request | 폴링 요청 |
+|polling.request.pattern | 폴링 요청 패턴 |
+|polling.replacement | 폴링 요청을 응답으로 바꾸는 패턴 |
+|polling.response.pattern | 폴링 응답 패턴 |
+|--------------------------------------------------------------------------------------------------------------|
+|ll.field.type | LL 필드의 Type(CHAR/BIN) |
+|ll.field.length | LL 필드의 길이 |
+|ll.field.offset | LL 필드의 시작위치 |
+|ll.field.include | LL 필드 포함 길이여부 |
+|ll.offset.exclude | LL 필드의 시작위치 포함여부 |
+|ll.include | LL 필드를 포함에서 넘길지 여부 |
+|--------------------------------------------------------------------------------------------------------------|
+|payload.length | 거래시 특정 길이로 LL을 셋팅하고 송수신 |
+|--------------------------------------------------------------------------------------------------------------|
+|xecure.type | Xecure Connect Type(WELCOME/ENVELOPE/BASIC) |
+|xecure.config.path | Xecure Connect 환경파일 위치 |
+|(cfg)xecure.local.cert | Xecure Connect 인증서 파일명 |
+|(cfg)xecure.local.key | Xecure Connect 키 파일명 |
+|(cfg)xecure.local.password | Xecure Connect 패스워드 |
+|xecure.remote.cert | Xecure Connect 원격지 인증서 파일명 |
+|--------------------------------------------------------------------------------------------------------------|
+|inisafe.config.path | INI Safe 환경파일 위치 |
+|inisafe.related.adapter.groups| INI Safe와 관련된 아답터 그룹 (신한은망용) |
+|inisafe.start.message | INI Safe와 관련된 아답터 시작 메시지 (신한은망용) |
+|inisafe.stop.message | INI Safe와 관련되 아답터 종료 메시지 (신한은망용) |
+|--------------------------------------------------------------------------------------------------------------|
+|ssl.use | SSL 사용여부 |
+|ssl.cert.store | SSL 인증서 |
+|ssl.cert.password | SSL 패스워드 |
+|--------------------------------------------------------------------------------------------------------------|
+|(cfg)xecure2.config.path | Xecure Connect Session Manager Type Protocol config file path |
+|xecure2.sm.ip | Session Manager Listen IP |
+|xecure2.sm.port | Session Manager Listen PORT |
++--------------------------------------------------------------------------------------------------------------+
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/AdminHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/AdminHandler.java
new file mode 100644
index 0000000..16ed82f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/AdminHandler.java
@@ -0,0 +1,368 @@
+package com.eactive.eai.adapter.socket2.protocol.admin;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.Options;
+import org.apache.mina.common.IoSession;
+
+import java.util.Enumeration;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class AdminHandler extends ProtocolHandler {
+// private static final String HANDLER_STATE_KEY = AdminHandler.class.getName() + ".STATE";
+ SocketAdapterManager manager = SocketAdapterManager.getInstance();
+
+ private enum State {
+ STATE_HANDSHAKE,
+ STATE_MESSAGE;
+ }
+
+ private static class HandlerState {
+ State state = State.STATE_HANDSHAKE;
+ }
+
+ AdminParser parser;
+
+
+ public AdminHandler(ISocketAdapter adapter) {
+ super(adapter);
+
+ this.parser = new AdminParser();
+ }
+
+// private void initState(IoSession session) {
+// HandlerState handlerState = (HandlerState) session.getAttribute(HANDLER_STATE_KEY);
+//
+// if (handlerState == null) {
+// handlerState = new HandlerState();
+// // NO_ACK Protocol
+// if ("N".equals(context.getAckSupport())) {
+// handlerState.state = State.STATE_MESSAGE;
+// setSessionState(session, handlerState.state.toString());
+//
+// if (context.isPermanent()) {
+// sessionPool.release(session);
+// } else {
+// SimpleFuture handshakeFuture = (SimpleFuture) session.getAttribute(HANDSHAKE_FUTURE);
+// handshakeFuture.set(Boolean.TRUE);
+// }
+// adapter.setAdapterStatus(true);
+// }
+// session.setAttribute(HANDLER_STATE_KEY, handlerState);
+// }
+// }
+
+
+ @Override
+ protected byte[] processRequest(IoSession session, byte[] request) {
+ String result = processCommand(new String(request));
+ if(result == null) {
+ return "".getBytes();
+ }
+ else {
+ return result.getBytes();
+ }
+ }
+
+ private enum Command {
+ HELP, // help
+ CC, CD, // change context
+ LIST, LS, // list status
+ START, // start
+ STOP, // stop
+ //GET, // get
+ SET, // set
+ DISCONNECT, // distconnect
+ QUIT, EXIT, BYE, // quit
+ UNKNOWN;
+
+ public static Command getValue(String value) {
+ try {
+ return valueOf(value.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+ }
+
+ private enum Option {
+ CONNECTION,
+ SESSION,
+ TRACE,
+ CONFIG,
+ UNKNOWN;
+
+ public static Option getValue(String value) {
+ try {
+ return valueOf(value.toUpperCase());
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+ }
+
+ public String processCommand(String command) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | execute command : " + command);
+ }
+
+ //String commands = "stop,start,get,set,disconnect";
+ //String options = "connection,session,trace,config";
+ //String inCmd = command;
+
+ if (command == null || command.equals("")) {
+ return "";
+ }
+
+ // Parse the program arguments
+ CommandLine line = null;
+ try {
+ line = parser.parse(command);
+ } catch(Exception e) {
+ logger.error(context.getAdapterName() + " | " + e.getMessage(), e);
+ adapter.addRecentError(context.getAdapterName() + " | " + e.getMessage(), e);
+ return "[AdminHandler] " + e.getMessage();
+ }
+
+ // Set the appropriate variables based on supplied options
+ boolean verbose = false;
+ boolean help = false;
+
+ if (line.hasOption('h')) {
+ help = true;
+ }
+
+ if (line.hasOption('v')) {
+ verbose = true;
+ }
+
+ String[] args = line.getArgs();
+ String arg0 = args[0].toLowerCase();
+
+ switch (Command.getValue(arg0)) {
+ case HELP:
+ return help();
+
+ case CD:
+ case CC:
+ return cc(args);
+
+ case LS:
+ case LIST:
+ return ls(args, verbose);
+
+ case START:
+ return start(args);
+
+ case STOP:
+ return stop(args);
+
+ case DISCONNECT:
+ return disconnect(args, command);
+
+// case GET:
+// if (args.length < 3) {
+// return "args.length < 3";
+// }
+//
+// switch (Option.getValue(args[1].toLowerCase())) {
+// case CONNECTION:
+// if (args[2].equalsIgnoreCase("all")) {
+// return manager.getConnectionInfo(null);
+// } else if (args[2].equalsIgnoreCase("summary")) {
+// return manager.getConnectionSummary();
+// } else {
+// return manager.getConnectionInfo(args[2]);
+// }
+// case CONFIG:
+// SocketAdapterContext ctx = manager.getContext(args[2]);
+// if (ctx == null) {
+// return CommonLib.getMessage("cannot get context");
+// } else {
+// return manager.getContext(args[2]).toString();
+// }
+// case SESSION:
+// if (args[2].equalsIgnoreCase("all")) {
+// return manager.getSessionInfo(null);
+// } else {
+// return manager.getSessionInfo(args[2]);
+// }
+// case UNKNOWN:
+// default:
+// return "Invalid Option : " + command;
+// }
+//
+ case SET:
+ if (args.length < 4) {
+ return CommonLib.getMessage("args.length < 4");
+ }
+
+ // Connections
+ int newCount = 0;
+ try {
+ newCount = Integer.parseInt(args[3]);
+ } catch (Exception e) {
+ return e.getMessage();
+ }
+
+ switch (Option.getValue(args[1].toLowerCase())) {
+// case CONNECTION:
+// return manager.adjustConnection(args[2], newCount);
+// case SESSION:
+// try {
+// return manager.adjustThread(args[2], newCount);
+// } catch (Exception e) {
+// return e.getMessage();
+// }
+ case TRACE:
+ SocketAdapterContext ctx = manager.getContext(args[2]);
+ if (newCount < 0 || newCount > 2) {
+ return "count is invalid";
+ }
+ if (ctx == null) {
+ return "context is null";
+ }
+ ctx.setTraceLevel(newCount);
+ String newLevel = "";
+
+ switch(newCount) {
+ case 0:
+ newLevel = "0(ERROR)";
+ break;
+ case 1:
+ newLevel = "1(INFO)";
+ break;
+ default:
+ newLevel = "2(DEBUG)";
+ }
+
+ return "change trace level to " + newLevel;
+ case UNKNOWN:
+ default:
+ return "Invalid Option : " + command;
+ }
+
+ case QUIT:
+ case EXIT:
+ case BYE:
+ return "EXIT";
+ case UNKNOWN:
+ default:
+ return " Unknown Command : " + command + ". Type 'help'";
+ }
+ }
+
+ private String help() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n help\n");
+ sb.append(" -------------------------------------------------------------------\n");
+ sb.append(" help - 도움말\n");
+ sb.append(" list|ls|stat|st| - List properties, Status\n");
+ sb.append(" cd|cc [AdapterGroup].[Adapter] - Change Context\n");
+ sb.append(" start - Start socket adapter\n");
+ sb.append(" stop - Stop socket adapter\n");
+ sb.append(" disconnect - Disconnect session\n");
+ sb.append(" set - Modify socket adapter property\n");
+ return sb.toString();
+ }
+
+ private String cc(String[] args) {
+ if (args.length < 2) {
+ return " usage : cc|cd [adapter group].[adapter]";
+ }
+
+ ISocketAdapter adapter = manager.getSocketAdapter(args[1]);
+ if (adapter != null)
+ return args[1];
+ else
+ return " ERROR - context (adapter group, adapter) does not exist : " + args[1];
+ }
+
+ private String ls(String[] args, boolean verbose) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n");
+ sb.append(String.format(" %-30s %-10s %-10s %10s %10s %10s %10s\n",
+ "adapter",
+ "protocol",
+ "state",
+ "pool",
+ "recv",
+ "send",
+ "error"));
+ sb.append(" -----------------------------------------------------------------------------------------------------------\n");
+ String prev = "";
+
+ ConcurrentHashMap> adapterGroups = (ConcurrentHashMap)manager.getSocketAdapterGroups();
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ ConcurrentHashMap adapters = adapterGroups.get(adapterGroupName);
+ //sb.append(adapterGroupName + "\n");
+ for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
+ ISocketAdapter adapter = ee.nextElement();
+ if (!prev.equals(adapterGroupName)) {
+ sb.append(String.format(" %-31s %s\n",
+ adapterGroupName,
+ "---------------------------------------------------------------------------"));
+ }
+ sb.append(String.format(" .%-30s %-10s %-10s %10d %10d %10d %10d\n",
+ adapter.getContext().getAdapterName(),
+ adapter.getContext().getProtocol().length() > 5 ? adapter.getContext().getProtocol().substring(0,5) : adapter.getContext().getProtocol(),
+ adapter.getState().name(),
+ adapter.getSessionPool().peekSize(),
+ adapter.getMessageRecv(),
+ adapter.getMessageSend(),
+ adapter.getRecentErrorCount()));
+ prev = adapterGroupName;
+ }
+ }
+
+ return sb.toString();
+ }
+
+ private String start(String[] args) {
+ if (args.length < 3) {
+ return " usage : start [adapter group] [adapter]";
+ }
+
+ return manager.start(args[1], args[2]);
+ }
+
+ private String stop(String[] args) {
+ if (args.length < 3) {
+ return " usage : stop [adapter group] [adapter]";
+ }
+
+ manager.stop();
+ return "stopped";
+ }
+
+ private String disconnect(String[] args, String command) {
+ if (args.length < 3) {
+ return "args.length < 3";
+ }
+ return manager.disconnect(args[1].toLowerCase(), args[2]);
+ }
+}
+
+class AdminParser {
+ CommandLineParser parser;
+ Options options;
+
+ public AdminParser() {
+ parser = new BasicParser();
+ options = new Options();
+ options.addOption("h", "help", false, "Print this usage information");
+ options.addOption("v", "verbose", false, "Print out VERBOSE information");
+ //options.addOption("f", "file", true, "File to save program output to");
+ }
+
+ public CommandLine parse(String cmd) throws Exception {
+ return parser.parse(options, cmd.split("\\s"));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/AdminServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/AdminServer.java
new file mode 100644
index 0000000..52f6b7a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/AdminServer.java
@@ -0,0 +1,27 @@
+package com.eactive.eai.adapter.socket2.protocol.admin;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.FixedHeaderCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class AdminServer extends TcpAdapterServer {
+ public AdminServer(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ context.setLlFieldType("BIN");
+ context.setLlFieldOffset(0);
+ context.setLlFieldLength(2);
+ context.setLlFieldInclude("N");
+ context.setLlInclude("N");
+
+ this.handler = new AdminHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedHeaderCodecFactory(this)));
+ }
+
+ public Object sendMessage(Object message) throws EAIException {
+ throw new EAIException("[Admin Server] not supported function");
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetAdminHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetAdminHandler.java
new file mode 100644
index 0000000..590feb2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetAdminHandler.java
@@ -0,0 +1,34 @@
+package com.eactive.eai.adapter.socket2.protocol.admin;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import org.apache.mina.common.IoSession;
+
+public class TelnetAdminHandler extends ProtocolHandler {
+ public TelnetAdminHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void sessionOpened(IoSession session) {
+ session.write("WELCOME");
+ session.write("cmd> " + (byte) 0xF8);
+ }
+
+ @Override
+ public void messageReceived(IoSession session, Object message) throws Exception {
+ String msg = message.toString().trim();
+ System.out.println(" " + msg);
+
+ if ("quit".equals(msg) || "exit".equals(msg)) {
+ session.write("bye......");
+ sessionPool.remove(session);
+ session.close();
+ return;
+ }
+
+ session.write(msg);
+ session.write("\r\ncmd> ");
+ session.write((byte) 0x22);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetAdminServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetAdminServer.java
new file mode 100644
index 0000000..df0216e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetAdminServer.java
@@ -0,0 +1,23 @@
+package com.eactive.eai.adapter.socket2.protocol.admin;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+
+import java.nio.charset.Charset;
+
+
+public class TelnetAdminServer extends TcpAdapterServer {
+ public TelnetAdminServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new TelnetAdminHandler(this);
+
+ SocketSessionConfig sessionConfig = (SocketSessionConfig) config.getSessionConfig();
+ sessionConfig.setTcpNoDelay(true);
+ sessionConfig.setKeepAlive(true);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetTextLineCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetTextLineCodecFactory.java
new file mode 100644
index 0000000..8ba76be
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/admin/TelnetTextLineCodecFactory.java
@@ -0,0 +1,89 @@
+package com.eactive.eai.adapter.socket2.protocol.admin;
+
+import org.apache.mina.common.BufferDataException;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.textline.LineDelimiter;
+import org.apache.mina.filter.codec.textline.TextLineDecoder;
+import org.apache.mina.filter.codec.textline.TextLineEncoder;
+
+import java.nio.charset.Charset;
+
+public class TelnetTextLineCodecFactory implements ProtocolCodecFactory {
+ private final TextLineEncoder encoder;
+
+ private final TextLineDecoder decoder;
+
+ /**
+ * Creates a new instance with the current default {@link Charset}.
+ */
+ public TelnetTextLineCodecFactory() {
+ this(Charset.defaultCharset());
+ }
+
+ /**
+ * Creates a new instance with the specified {@link Charset}.
+ */
+ public TelnetTextLineCodecFactory(Charset charset) {
+ encoder = new TextLineEncoder(charset, LineDelimiter.UNIX);
+ decoder = new TextLineDecoder(charset, LineDelimiter.AUTO);
+ }
+
+ public ProtocolEncoder getEncoder() {
+ return encoder;
+ }
+
+ public ProtocolDecoder getDecoder() {
+ return decoder;
+ }
+
+ /**
+ * Returns the allowed maximum size of the encoded line.
+ * If the size of the encoded line exceeds this value, the encoder
+ * will throw a {@link IllegalArgumentException}. The default value
+ * is {@link Integer#MAX_VALUE}.
+ *
+ * This method does the same job with {@link TextLineEncoder#getMaxLineLength()}.
+ */
+ public int getEncoderMaxLineLength() {
+ return encoder.getMaxLineLength();
+ }
+
+ /**
+ * Sets the allowed maximum size of the encoded line.
+ * If the size of the encoded line exceeds this value, the encoder
+ * will throw a {@link IllegalArgumentException}. The default value
+ * is {@link Integer#MAX_VALUE}.
+ *
+ * This method does the same job with {@link TextLineEncoder#setMaxLineLength(int)}.
+ */
+ public void setEncoderMaxLineLength(int maxLineLength) {
+ encoder.setMaxLineLength(maxLineLength);
+ }
+
+ /**
+ * Returns the allowed maximum size of the line to be decoded.
+ * If the size of the line to be decoded exceeds this value, the
+ * decoder will throw a {@link BufferDataException}. The default
+ * value is 1024 (1KB).
+ *
+ * This method does the same job with {@link TextLineDecoder#getMaxLineLength()}.
+ */
+ public int getDecoderMaxLineLength() {
+ return decoder.getMaxLineLength();
+ }
+
+ /**
+ * Sets the allowed maximum size of the line to be decoded.
+ * If the size of the line to be decoded exceeds this value, the
+ * decoder will throw a {@link BufferDataException}. The default
+ * value is 1024 (1KB).
+ *
+ * This method does the same job with {@link TextLineDecoder#setMaxLineLength(int)}.
+ */
+ public void setDecoderMaxLineLength(int maxLineLength) {
+ decoder.setMaxLineLength(maxLineLength);
+ }
+}
+
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendClient.java
new file mode 100644
index 0000000..ab21a9b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendClient.java
@@ -0,0 +1,18 @@
+package com.eactive.eai.adapter.socket2.protocol.append;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.append.codec.AppendCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class AppendClient extends TcpAdapterClient {
+
+ public AppendClient(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ this.handler = new AppendHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new AppendCodecFactory(this)));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendHandler.java
new file mode 100644
index 0000000..c595d39
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.protocol.append;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class AppendHandler extends ProtocolHandler {
+ public AppendHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendServer.java
new file mode 100644
index 0000000..da8f3d5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/AppendServer.java
@@ -0,0 +1,18 @@
+package com.eactive.eai.adapter.socket2.protocol.append;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.append.codec.AppendCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class AppendServer extends TcpAdapterServer {
+
+ public AppendServer(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ this.handler = new AppendHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new AppendCodecFactory(this)));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendCodecFactory.java
new file mode 100644
index 0000000..cca6009
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendCodecFactory.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.append.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class AppendCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+ public AppendCodecFactory(ISocketAdapter adapter) {
+ encoder = new AppendEncoder(adapter);
+ decoder = new AppendDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendDecoder.java
new file mode 100644
index 0000000..f6ec9e2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendDecoder.java
@@ -0,0 +1,310 @@
+package com.eactive.eai.adapter.socket2.protocol.append.codec;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+
+public class AppendDecoder extends ProtocolDecoderAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ private static final String errorCode = "RECEAINNA008";
+
+ public static final int MAX_PAYLOAD_SIZE = 25 * 1024 * 1024; // 25MB
+
+ private static final String DECODER_STATE_KEY = AppendDecoder.class.getName() + ".STATE";
+
+ private enum State {
+ STATE_HEADER_READ, STATE_PAYLOAD_READ;
+ }
+
+ private static class CodecState {
+ State state = State.STATE_HEADER_READ;
+ ByteBuffer buffer = ByteBuffer.allocate(0).setAutoExpand(true);
+ int payloadSize;
+ }
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public AppendDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @SuppressWarnings("static-access")
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+
+
+ if (codecState == null) {
+ String line = context.getAppendHead();
+ ByteMessage head = new ByteMessage();
+ while(line.indexOf("0x") != -1) {
+ head.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ head.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ head.append(line);
+
+ line = context.getAppendTail();
+
+ ByteMessage tail = new ByteMessage();
+ while(line.indexOf("0x") != -1) {
+ tail.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ tail.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ tail.append(line);
+ session.setAttribute("head",head);
+ session.setAttribute("tail",tail);
+
+ codecState = new CodecState();
+ codecState.buffer.limit(context.getLlFieldOffset() + context.getLlFieldLength() + head.size() );
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+ ByteMessage head = (ByteMessage)session.getAttribute("head");
+ ByteMessage tail = (ByteMessage)session.getAttribute("tail");
+ if (head == null) head = new ByteMessage();
+ if (tail == null) tail = new ByteMessage();
+
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("FixedHeaderDecoder");
+ if (codecState.state == State.STATE_PAYLOAD_READ) {
+ sb.append("(" + codecState.payloadSize + ")");
+ }
+ sb.append(" | decode : " + CommonLib.hexDump(in, context));
+ logger.debug(sb.toString());
+ adapter.addRecentRecvTrace(session, sb.toString());
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+ /**
+ * payload size < 0 인 경우
+ */
+ if (codecState.payloadSize < 0) {
+ throw new EAIException(errorCode, context.getAdapterName() +
+ " (" + context.getLlFieldType() + "," + context.getLlFieldOffset() + "," + context.getLlFieldLength() +
+ ") | when read header, ll length field is invalid | " + CommonLib.hexDump(codecState.buffer, context));
+ /**
+ * payload size == 0 인 경우
+ */
+ } else if (codecState.payloadSize == 0) {
+ if (context.isSync()) {
+ throw new Exception(" payload size 0 (ping). 'SYNC' response type socket does not support ping(size 0) message.");
+ }
+
+ //codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_INFO ) {
+ logger.info(context.getAdapterName() + " | payload size 0 (ping) -> ignore. - " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "payload size 0 (ping) -> ignore. - " + CommonLib.hexDump(in, context));
+ }
+
+ /**
+ * header 값을 읽은 후 buffer의 position을 이동해 준다.
+ * 이 작업을 안해주면 무한루프에 빠질 수 있다.
+ * 예) 법원 공탁금 (_LAW_IN_SOC_AsS{...})
+ */
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength());
+
+ if (context.isPollingUse() && context.isPollingSender() && context.isPermanent()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ }else{
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ break;
+ }
+ /**
+ * ll.include = 'Y' - LL을 포함해서 넘긴다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ try {
+ codecState.buffer.position(context.getLlFieldOffset() + context.getLlFieldLength()+ head.size())
+ .limit(codecState.payloadSize + context.getLlFieldLength()+ head.size() +tail.size());
+ } catch(IllegalArgumentException e) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(context.getAdapterName() + " | error when handling buffer | ");
+ sb.append("offset=" + context.getLlFieldOffset() + context.getLlFieldLength());
+ sb.append(", limit=" + codecState.payloadSize + context.getLlFieldLength());
+ logger.error(sb.toString());
+ errLogger.error(sb.toString());
+ adapter.addRecentError(sb.toString());
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA007");
+ throw e;
+ }
+ /**
+ * ll.include = 'N' - LL을 제외하고 넘긴다.
+ */
+ } else {
+ try {
+ codecState.buffer.position(context.getLlFieldOffset()).limit(codecState.payloadSize);
+ } catch(IllegalArgumentException e) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(context.getAdapterName() + " | error when handling buffer | ");
+ sb.append("offset=" + context.getLlFieldOffset());
+ sb.append(", limit=" + codecState.payloadSize);
+ logger.error(sb.toString());
+ errLogger.error(sb.toString());
+ adapter.addRecentError(sb.toString());
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA007");
+ throw e;
+ }
+ }
+
+ /**
+ * offset + ll 을 읽었고, 더 이상 읽을 것(payload)이 없는 경우
+ * - ll.length value = ll.offset + ll.field.length
+ */
+ if (codecState.buffer.position() == codecState.buffer.limit()) {
+ byte[] bytes = new byte[codecState.buffer.limit()-head.size()-tail.size()];
+ byte[] tails = new byte[tail.size()];
+ codecState.buffer.position(head.size());
+ codecState.buffer.get(bytes);
+ codecState.buffer.get(tails);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength() + head.size());
+
+ if (context.isPollingUse() && context.isPollingSender() && context.isPermanent()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ }else{
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+
+ break;
+ }
+
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()-head.size()-tail.size()];
+ byte[] tails = new byte[tail.size()];
+ codecState.buffer.position(head.size());
+ codecState.buffer.get(bytes);
+ codecState.buffer.get(tails);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength() + head.size());
+
+ //by short11
+ //polling.role 이 Server 가 sender일 경우 오류가 있었음
+ if (context.isPollingUse() && context.isPollingSender() && context.isPermanent()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ }else{
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+
+ break;
+ default :
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ ByteMessage head = (ByteMessage)session.getAttribute("head");
+// ByteMessage tail = (ByteMessage)session.getAttribute("tail");
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ if ("BIN".equals(context.getLlFieldType())) {
+ codecState.payloadSize = 0;
+ for (int i=0; i MAX_PAYLOAD_SIZE) {
+ throw new Exception("max payload size(" + MAX_PAYLOAD_SIZE + ") exceeded : " +
+ codecState.payloadSize + " | " +
+ CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ /**
+ * ll.field.include = 'Y' - 헤더 길이를 빼 준다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ codecState.payloadSize = codecState.payloadSize - context.getLlFieldLength();
+ }
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 더해서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+ codecState.payloadSize = codecState.payloadSize + context.getLlFieldOffset();
+ }
+
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendEncoder.java
new file mode 100644
index 0000000..0b770a8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/append/codec/AppendEncoder.java
@@ -0,0 +1,155 @@
+package com.eactive.eai.adapter.socket2.protocol.append.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class AppendEncoder implements ProtocolEncoder {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public AppendEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+ /**
+ * head size 및 value
+ */
+
+ String line = context.getAppendHead();
+ ByteMessage head = new ByteMessage();
+ while(line.indexOf("0x") != -1) {
+ head.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ head.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ head.append(line);
+
+ /**
+ * tail size 및 value
+ */
+ line = context.getAppendTail();
+
+ ByteMessage tail = new ByteMessage();
+ while(line.indexOf("0x") != -1) {
+ tail.append(line.substring(0, line.indexOf("0x")));
+ String hex = line.substring(line.indexOf("0x"), line.indexOf("0x")+4);
+ tail.append((byte) Integer.parseInt(hex.substring(2), 16));
+ line = line.substring(line.indexOf("0x")+4);
+ }
+ tail.append(line);
+
+
+
+ /**
+ * ll.include = 'Y' - 통째로 보낸다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ ByteBuffer buffer = ByteBuffer.allocate(m.size() - context.getLlFieldLength());
+ buffer.put(m.getBytes(0, context.getLlFieldOffset()));
+ buffer.put(m.getBytes(context.getLlFieldOffset() + context.getLlFieldLength()));
+ buffer.flip();
+ m.setByteBuffer(buffer);
+ }
+
+ int length = m.size();
+ ByteBuffer buffer = ByteBuffer.allocate(context.getLlFieldLength() + length + head.size()+ tail.size()).limit(context.getLlFieldLength() + length+ head.size()+ tail.size());
+
+ /**
+ * ll.field.include = 'Y' - header 길이 포함하여 ll 을 계산한다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ length = length + context.getLlFieldLength();
+ }
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 빼서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+ length = length - context.getLlFieldOffset();
+ }
+
+ /**
+ * [1] head 추가
+ */
+
+ buffer.put(head.getBytes());
+ /**
+ * [2] before-payload
+ */
+ buffer.put(m.getBytes(0, context.getLlFieldOffset()));
+
+ /**
+ * [3] write header
+ */
+ if ("BIN".equals(context.getLlFieldType())) {
+ int tmpLength = length;
+ byte[] header = new byte[context.getLlFieldLength()];
+ for (int i = context.getLlFieldLength()-1; i>=0; i--) {
+ header[i] = (byte) (tmpLength % 256);
+ tmpLength = tmpLength / 256;
+ }
+ buffer.put(header);
+ } else { // "CHAR"
+ String lenStr = CommonLib.getFormatString(length, context.getLlFieldLength());
+ buffer.put(lenStr.getBytes());
+ }
+ /**
+ * [4] after-payload
+ */
+ buffer.put(m.getBytes(context.getLlFieldOffset(), m.getBytes().length - context.getLlFieldOffset()));
+
+
+ /**
+ * [5]tail 추가
+ */
+ buffer.put(tail.getBytes());
+
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | FixedHeaderEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "FixedHeaderEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ out.flush();
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ // empty
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertClient.java
new file mode 100644
index 0000000..548bfaf
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertClient.java
@@ -0,0 +1,19 @@
+package com.eactive.eai.adapter.socket2.protocol.cert;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.cert.codec.CertCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.cert.handshake.CertClientFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class CertClient extends TcpAdapterClient {
+
+ public CertClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new CertHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new CertCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "cert", new CertClientFilter(this));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertHandler.java
new file mode 100644
index 0000000..09d350b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.protocol.cert;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class CertHandler extends ProtocolHandler {
+ public CertHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertServer.java
new file mode 100644
index 0000000..464066f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/CertServer.java
@@ -0,0 +1,17 @@
+package com.eactive.eai.adapter.socket2.protocol.cert;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.cert.codec.CertCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.cert.handshake.CertServerFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class CertServer extends TcpAdapterServer {
+ public CertServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new CertHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new CertCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "cert", new CertServerFilter(this));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertCodecFactory.java
new file mode 100644
index 0000000..3f19d96
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertCodecFactory.java
@@ -0,0 +1,25 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class CertCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+
+ public CertCodecFactory(ISocketAdapter adapter) {
+ encoder = new CertEncoder(adapter);
+ decoder = new CertDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertConstants.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertConstants.java
new file mode 100644
index 0000000..6f904e4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertConstants.java
@@ -0,0 +1,8 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.codec;
+
+public class CertConstants {
+ public static final String CODEC_KEY = "UNRELAIBLE_CODEC_KEY";
+ private CertConstants() {
+
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertDecoder.java
new file mode 100644
index 0000000..fc1b193
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertDecoder.java
@@ -0,0 +1,147 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.codec;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.adapter.socket2.protocol.cert.message.CertMessage;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+
+public class CertDecoder extends ProtocolDecoderAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ private enum State {
+ STATE_LL_READ,
+ STATE_PAYLOAD_READ
+ }
+
+ public static class CodecState {
+ State state = State.STATE_LL_READ;
+ ByteBuffer buffer = ByteBuffer.allocate(0).setAutoExpand(true);
+ int payloadSize;
+ }
+
+ public CertDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out)
+ throws Exception {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertDecoder | decode : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "CertDecoder | decode : " + CommonLib.hexDump(in, context));
+ }
+
+ CodecState codecState = (CodecState) session.getAttribute(CertConstants.CODEC_KEY);
+
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(CertMessage.LL_LENGTH);
+ session.setAttribute(CertConstants.CODEC_KEY, codecState);
+ }
+
+ while (in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_LL_READ:
+ if (readHeader(codecState, in)) {
+ codecState.buffer.position(CertMessage.LL_LENGTH).limit(CertMessage.LL_LENGTH + codecState.payloadSize);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.get(bytes);
+
+ CertMessage message = new CertMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(CertMessage.LL_LENGTH);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_LL_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ default :
+ }
+ }
+ }
+
+ private boolean readHeader(CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | read header : " + CommonLib.hexDump(in));
+ }
+ */
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while (codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ codecState.buffer.flip();
+
+ try {
+ byte[] header = new byte[CertMessage.LL_LENGTH];
+ codecState.buffer.get(header);
+ codecState.payloadSize = Integer.parseInt(new String(header));
+ } catch (NumberFormatException e) {
+ throw new EAIException("RECEAINNA008", context.getAdapterName() + " | when read header, number format is invalid - " + e.getMessage() + " | " + CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ return true;
+ }
+
+ private boolean readPayload(CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | read payload : " + CommonLib.hexDump(in));
+ }
+ */
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while (codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ codecState.buffer.flip();
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertEncoder.java
new file mode 100644
index 0000000..49b819e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/codec/CertEncoder.java
@@ -0,0 +1,95 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.cert.codec.CertDecoder.CodecState;
+import com.eactive.eai.adapter.socket2.protocol.cert.message.CertMessage;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class CertEncoder implements ProtocolEncoder {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public CertEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ /*
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | decode : " + message);
+ }
+ */
+
+ CodecState codecState = (CodecState) session.getAttribute(CertConstants.CODEC_KEY);
+
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(CertMessage.LL_LENGTH);
+ session.setAttribute(CertConstants.CODEC_KEY, codecState);
+ }
+
+ CertMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof CertMessage) {
+ m = (CertMessage) message;
+ } else if (message instanceof ByteMessage) {
+ m = new CertMessage(((ByteMessage) message).getBytes());
+ } else if (message instanceof String) {
+ m = new CertMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new CertMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ ByteBuffer buffer = ByteBuffer.allocate(CertMessage.COMMON_HEADER_LENGTH + CertMessage.INDIVIDUAL_HEADER_LENGTH + m.getBytes().length);
+ //buf.setAutoExpand(true); // Enable auto-expand for easier encoding
+
+ // write header
+// String ll = CommonLib.getFormatString(m.getBytes().length, CertMessage.LL_LENGTH);
+// buffer.put(ll.getBytes()); // tatal message length
+ // tatal message length - left padding '0'
+ //buffer.put(StringUtils.leftPad(String.valueOf(m.getValue().length + Constants.HEADER_LENGTH + Constants.TAIL_LENGTH), 7, '0').getBytes());
+
+ // 암호화 타입 (0:plain 1:DES 2:Plll Connect)
+ //buffer.put(codecState.securityType);
+ // 판매점 아이디 (16 Byte 고정으로 앞 또는 뒤를 공백문자로 채운다)
+ //buffer.put(StringUtils.leftPad("1111", 16, ' ').getBytes());
+
+ // write header
+ buffer.put(m.getHeader());
+
+ //write payload
+ buffer.put(m.getBytes());
+
+ int mark = buffer.position();
+ buffer.position(0);
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | CertEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "CertEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ // empty
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertClientFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertClientFilter.java
new file mode 100644
index 0000000..63984ef
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertClientFilter.java
@@ -0,0 +1,75 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.cert.message.CertMessage;
+import org.apache.mina.common.IoSession;
+
+
+public class CertClientFilter extends CertFilter {
+ public CertClientFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+// FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ CertMessage mm = new CertMessage();
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertClientFilter | challenge : " + mm.hexDump());
+ }
+// IoFuture future = session.write(mm.getBytes());
+ session.write(mm.getBytes());
+ //future.join(context.getTimeout() * 1000L);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ ByteMessage m = (ByteMessage) message;
+
+ switch (filterState.state) {
+ case STATE_CHALLENGE:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertClientFilter | challenge : " + m.hexDump());
+ }
+ CertMessage mm = new CertMessage();
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertClientFilter | auth : " + mm.hexDump());
+ }
+// IoFuture future = session.write(mm.getBytes());
+ session.write(mm.getBytes());
+ //future.join(context.getTimeout() * 1000L);
+
+ filterState.state = State.STATE_AUTH;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_AUTH:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertClientFilter | auth : " + m.hexDump());
+ }
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ break;
+
+ case STATE_MESSAGE:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | CertClientFilter | : " + m.hexDump());
+ }
+ nextFilter.messageReceived(session, message);
+ break;
+
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + m);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertFilter.java
new file mode 100644
index 0000000..3ecce80
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertFilter.java
@@ -0,0 +1,65 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+
+
+public abstract class CertFilter extends IoFilterAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ public static final String FILTER_STATE_KEY = CertFilter.class.getName() + ".STATE";
+ public static final String SESSION_STATE = "SESSION_STATE";
+
+ public enum State {
+ STATE_CHALLENGE,
+ STATE_AUTH,
+ STATE_MESSAGE;
+ }
+
+ public static class FilterState {
+ public State state = State.STATE_CHALLENGE;
+ byte[] key; // token?
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ protected CertFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
+ if (parent.contains(CertFilter.class)) {
+ throw new IllegalStateException("A filter chain cannot contain more than one CertFilter.");
+ }
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ }
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertServerFilter.java
new file mode 100644
index 0000000..d854037
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/handshake/CertServerFilter.java
@@ -0,0 +1,63 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.cert.message.CertMessage;
+import org.apache.mina.common.IoFuture;
+import org.apache.mina.common.IoSession;
+
+
+public class CertServerFilter extends CertFilter {
+ public CertServerFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ CertMessage m = (CertMessage) message;
+
+ switch (filterState.state) {
+ case STATE_CHALLENGE:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertServerFilter | challenge : " + m.hexDump());
+ }
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertServerFilter | challenge : " + m.hexDump());
+ }
+ IoFuture future = session.write(m.getBytes());
+ //future.join(context.getTimeout() * 1000L);
+
+ filterState.state = State.STATE_AUTH;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_AUTH:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertServerFilter | auth : " + m.hexDump());
+ }
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | CertServerFilter | auth : " + m.hexDump());
+ }
+ future = session.write(m.getBytes()); //filterState.key);
+ //future.join(context.getTimeout() * 1000L);
+
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ break;
+
+ case STATE_MESSAGE:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | CertServerFilter | : " + m.hexDump());
+ }
+
+ nextFilter.messageReceived(session, message);
+ break;
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/message/CertMessage.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/message/CertMessage.java
new file mode 100644
index 0000000..7736f42
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cert/message/CertMessage.java
@@ -0,0 +1,49 @@
+package com.eactive.eai.adapter.socket2.protocol.cert.message;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+
+public class CertMessage extends ByteMessage {
+ public static final int LL_LENGTH = 9;
+ public static final int COMMON_HEADER_LENGTH = 223;
+ public static final int INDIVIDUAL_HEADER_LENGTH = 235;
+
+ byte[] header;
+
+ public CertMessage() {
+ this(new byte[0]);
+ }
+
+ public CertMessage(String body) {
+ this(body.getBytes());
+ }
+
+ public CertMessage(byte[] body) {
+ this(new byte[COMMON_HEADER_LENGTH + INDIVIDUAL_HEADER_LENGTH], body);
+ }
+
+ public CertMessage(byte[] header, byte[] body) {
+ this.header = header;
+ this.value = body;
+ String ll = CommonLib.getFormatString(COMMON_HEADER_LENGTH - LL_LENGTH + INDIVIDUAL_HEADER_LENGTH + body.length, LL_LENGTH);
+ System.arraycopy(ll.getBytes(), 0, header, 0, LL_LENGTH);
+ }
+
+ public byte[] getHeader() {
+ return header;
+ }
+
+ @Override
+ public String hexDump() {
+ return CommonLib.hexDump(value);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("CertMessage - [");
+ sb.append(new String(value));
+ sb.append("]");
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoClient.java
new file mode 100644
index 0000000..d66f170
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoClient.java
@@ -0,0 +1,44 @@
+package com.eactive.eai.adapter.socket2.protocol.cisco;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.cisco.codec.CiscoCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+public class CiscoClient extends TcpAdapterClient {
+
+ public CiscoClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new CiscoHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new CiscoCodecFactory(this)));
+
+ /**
+ * TODO : snmp 와 연동하여 아래 작업 할 것 flow control filter
+ */
+ //config.getFilterChain().addLast("flowControl", new FlowControlFilter());
+
+ /*
+ ReadThrottleFilterBuilder filter = new ReadThrottleFilterBuilder();
+ filter.attach(config.getFilterChain());
+ */
+
+
+ /**
+ * flow control filter (apache mina version 1.9.x)
+ */
+ /*
+ * config.getFilterChain().addLast("executor", new ExecutorFilter(executor));
+ * ReadThrottleFilterBuilder flowControlFilter = new ReadThrottleFilterBuilder();
+ * flowControlFilter.setMaximumConnectionBufferSize(1024*1024); // 1MB
+ * flowControlFilter.attach(config.getFilterChain());
+ */
+
+ /**
+ * flow control filter (apache mina version 2.x)
+ */
+ /*
+ * config.getFilterChain().addLast("flowControl", new ReadThrottleFilter());
+ * config.getFilterChain().addLast("flowControl", new WriteThrottleFilter());
+ */
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoHandler.java
new file mode 100644
index 0000000..2400124
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoHandler.java
@@ -0,0 +1,11 @@
+package com.eactive.eai.adapter.socket2.protocol.cisco;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class CiscoHandler extends ProtocolHandler {
+
+ public CiscoHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoServer.java
new file mode 100644
index 0000000..71cec81
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/CiscoServer.java
@@ -0,0 +1,44 @@
+package com.eactive.eai.adapter.socket2.protocol.cisco;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.cisco.codec.CiscoCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class CiscoServer extends TcpAdapterServer {
+ public CiscoServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new CiscoHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new CiscoCodecFactory(this)));
+
+ /**
+ * TODO : snmp 와 연동하여 아래 작업 할 것 flow control filter
+ */
+ //config.getFilterChain().addLast("flowControl", new FlowControlFilter());
+
+ /*
+ ReadThrottleFilterBuilder filter = new ReadThrottleFilterBuilder();
+ filter.attach(config.getFilterChain());
+ */
+
+
+ /**
+ * flow control filter (apache mina version 1.9.x)
+ */
+ /*
+ * config.getFilterChain().addLast("executor", new ExecutorFilter(executor));
+ * ReadThrottleFilterBuilder flowControlFilter = new ReadThrottleFilterBuilder();
+ * flowControlFilter.setMaximumConnectionBufferSize(1024*1024); // 1MB
+ * flowControlFilter.attach(config.getFilterChain());
+ */
+
+ /**
+ * flow control filter (apache mina version 2.x)
+ */
+ /*
+ * config.getFilterChain().addLast("flowControl", new ReadThrottleFilter());
+ * config.getFilterChain().addLast("flowControl", new WriteThrottleFilter());
+ */
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoCodecFactory.java
new file mode 100644
index 0000000..f39b807
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoCodecFactory.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.cisco.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class CiscoCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+ public CiscoCodecFactory(ISocketAdapter adapter) {
+ encoder = new CiscoEncoder(adapter);
+ decoder = new CiscoDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoConstants.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoConstants.java
new file mode 100644
index 0000000..bedcec6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoConstants.java
@@ -0,0 +1,9 @@
+package com.eactive.eai.adapter.socket2.protocol.cisco.codec;
+
+public class CiscoConstants {
+ public static final int CISCO_PACKET_SIZE = 1024;
+ //public static final long RECONNECT_INTERVAL = 1000;
+ private CiscoConstants() {
+
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoDecoder.java
new file mode 100644
index 0000000..1b529fc
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoDecoder.java
@@ -0,0 +1,154 @@
+package com.eactive.eai.adapter.socket2.protocol.cisco.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+public class CiscoDecoder extends ProtocolDecoderAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ private static final String DECODER_STATE_KEY = CiscoDecoder.class.getName() + ".STATE";
+
+ private enum State {
+ STATE_HEADER_READ,
+ STATE_PAYLOAD_READ;
+ }
+
+ private static class CodecState {
+ State state = State.STATE_HEADER_READ;
+ ByteBuffer partBuffer = ByteBuffer.allocate(CiscoConstants.CISCO_PACKET_SIZE);
+ ByteBuffer wholeBuffer = ByteBuffer.allocate(CiscoConstants.CISCO_PACKET_SIZE).setAutoExpand(true);
+ int payloadSize;
+ boolean last;
+ }
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public CiscoDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out)
+ throws Exception {
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | CiscoDecoder | decode : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "CiscoDecoder | decode : " + CommonLib.hexDump(in, context));
+ }
+
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.partBuffer.limit(6);
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch(codecState.state) {
+ case STATE_HEADER_READ :
+ // try to read first image
+ if (readHeader(session, codecState, in)) {
+ codecState.partBuffer.position(0).limit(codecState.payloadSize);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ :
+ if (readPayload(session, codecState, in)) {
+ codecState.wholeBuffer.put(codecState.partBuffer);
+ if (codecState.last) {
+ byte[] bytes = new byte[codecState.wholeBuffer.position()];
+ codecState.wholeBuffer.position(0);
+ codecState.wholeBuffer.get(bytes);
+ ByteMessage m = new ByteMessage(bytes);
+ out.write(m);
+
+ codecState.wholeBuffer.position(0).limit(6);
+ codecState.last = false;
+ }
+ codecState.partBuffer.position(0).limit(6);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ }
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | read header : " + CommonLib.hexDump(in));
+ }
+ */
+
+ if (codecState.partBuffer.remaining() > in.remaining()) {
+ codecState.partBuffer.put(in);
+ return false;
+ }
+
+ while(codecState.partBuffer.hasRemaining()) {
+ codecState.partBuffer.put(in.get());
+ }
+
+ if ((codecState.partBuffer.get(0) & 0xD7) == 0
+ || codecState.partBuffer.get(1) != 0x4A
+ || codecState.partBuffer.get(5) != 0x00) {
+ throw new Exception(context.getAdapterName() + " | magic number is wrong.");
+ }
+
+ codecState.payloadSize = ((int) ((codecState.partBuffer.get(2)) & 0xFF) * 256)
+ + ((int) ((codecState.partBuffer.get(3)) & 0xFF));
+ codecState.last = codecState.partBuffer.get(4) == 0x00;
+
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | read payload : " + CommonLib.hexDump(in));
+ }
+ */
+
+ if (codecState.partBuffer.remaining() > in.remaining()) {
+ codecState.partBuffer.put(in);
+ return false;
+ }
+
+ while(codecState.partBuffer.hasRemaining()) {
+ codecState.partBuffer.put(in.get());
+ }
+
+ codecState.partBuffer.flip();
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoEncoder.java
new file mode 100644
index 0000000..a7240a8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/cisco/codec/CiscoEncoder.java
@@ -0,0 +1,91 @@
+package com.eactive.eai.adapter.socket2.protocol.cisco.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class CiscoEncoder implements ProtocolEncoder {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public CiscoEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out)
+ throws Exception {
+
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ ByteBuffer buffer = ByteBuffer.allocate(6);
+ buffer.setAutoExpand(true); // Enable auto-expand for easier encoding
+
+ int toSendLen = 0;
+ int sentLen = 0;
+
+ while (true) {
+ if (m.getBytes().length - sentLen <= CiscoConstants.CISCO_PACKET_SIZE) {
+ toSendLen = m.getBytes().length - sentLen;
+ } else {
+ toSendLen = CiscoConstants.CISCO_PACKET_SIZE;
+ }
+
+ buffer.put((byte) 0xD7);
+ buffer.put((byte) 0x4A);
+ buffer.put((byte) (toSendLen/256));
+ buffer.put((byte) (toSendLen%256));
+ buffer.put((byte) (sentLen + toSendLen >= m.getBytes().length ? 0x00 : 0x01));
+ buffer.put((byte) 0x00);
+
+ byte[] payload = new byte[toSendLen];
+ System.arraycopy(m.getBytes(), sentLen, payload, 0, toSendLen);
+ buffer.put(payload);
+
+ sentLen += toSendLen;
+
+ if( sentLen >= m.getBytes().length) {
+ break;
+ }
+ //continue;
+ }
+
+ int mark = buffer.position();
+ buffer.position(0);
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | CiscoEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "CiscoEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+
+ buffer.flip();
+ out.write(buffer);
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterClient.java
new file mode 100644
index 0000000..ca68c61
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterClient.java
@@ -0,0 +1,15 @@
+package com.eactive.eai.adapter.socket2.protocol.delimiter;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.delimiter.codec.DelimiterCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class DelimiterClient extends TcpAdapterClient {
+ public DelimiterClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new DelimiterHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new DelimiterCodecFactory(this)));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterHandler.java
new file mode 100644
index 0000000..54b277a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.protocol.delimiter;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class DelimiterHandler extends ProtocolHandler {
+ public DelimiterHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterServer.java
new file mode 100644
index 0000000..0424f93
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/DelimiterServer.java
@@ -0,0 +1,16 @@
+package com.eactive.eai.adapter.socket2.protocol.delimiter;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.delimiter.codec.DelimiterCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class DelimiterServer extends TcpAdapterServer {
+ public DelimiterServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new DelimiterHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new DelimiterCodecFactory(this)));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterCodecFactory.java
new file mode 100644
index 0000000..86a51f4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterCodecFactory.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.delimiter.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class DelimiterCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+ public DelimiterCodecFactory(ISocketAdapter adapter) {
+ encoder = new DelimiterEncoder(adapter);
+ decoder = new DelimiterDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterDecoder.java
new file mode 100644
index 0000000..51cf432
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterDecoder.java
@@ -0,0 +1,174 @@
+package com.eactive.eai.adapter.socket2.protocol.delimiter.codec;
+
+
+import java.util.Arrays;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.HexUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+
+public class DelimiterDecoder extends ProtocolDecoderAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ public static final int MAX_PAYLOAD_SIZE = 25 * 1024 * 1024; // 25MB
+
+ private static final String DECODER_STATE_KEY = DelimiterDecoder.class.getName() + ".STATE";
+
+ private enum State {
+ STATE_HEADER_READ, STATE_PAYLOAD_READ;
+ }
+
+ private static class CodecState {
+ State state = State.STATE_HEADER_READ;
+ ByteBuffer buffer = ByteBuffer.allocate(0).setAutoExpand(true);
+ int payloadSize;
+ }
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public DelimiterDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @SuppressWarnings("static-access")
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ byte[] delimiter = HexUtil.string2Hex(context.getDelimiter());
+ codecState.buffer.limit(delimiter.length);
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("DelimiterDecoder");
+ if (codecState.state == State.STATE_PAYLOAD_READ) {
+ sb.append("(" + codecState.payloadSize + ")");
+ }
+ sb.append(" | decode : " + CommonLib.hexDump(in, context));
+ logger.debug(sb.toString());
+ adapter.addRecentRecvTrace(session, sb.toString());
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+ /**
+ * payload size < 0 인 경우
+ */
+ if (codecState.payloadSize < 0) {
+ throw new EAIException("RECEAINNA008", context.getAdapterName() +
+ " (" + context.getLlFieldType() + "," + context.getLlFieldOffset() + "," + context.getLlFieldLength() +
+ ") | when read header, ll length field is invalid | " + CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0);
+ codecState.buffer.get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+ byte[] delimiter = HexUtil.string2Hex(context.getDelimiter());
+
+ codecState.buffer.position(0).limit(delimiter.length);
+
+ //by short11
+ //polling.role 이 Server 가 sender일 경우 오류가 있었음
+ if (context.isPollingUse() && context.isPollingSender() && context.isPermanent()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ }else{
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ default :
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ codecState.payloadSize = 0;
+
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ byte[] delimiter = HexUtil.string2Hex(context.getDelimiter());
+
+ if (delimiter.length >1 ){
+ ByteMessage dst = new ByteMessage();
+ int position = codecState.buffer.position();
+ for(int i=delimiter.length-1;i >0;i--){
+ dst.append(codecState.buffer.position(position-i).get());
+ }
+ while(in.hasRemaining()){
+ byte b = in.get();
+ dst.append(b);
+ if (Arrays.equals(dst.getBytes(), delimiter)){
+ codecState.buffer.put(b);
+ int lposition = codecState.buffer.position();
+ codecState.buffer.limit(lposition - delimiter.length);
+ return true;
+ }else{
+ codecState.buffer.put(b);
+ }
+ dst =dst.exclude(0, 1);
+ }
+ }else{
+ while(in.hasRemaining()){
+ byte b = in.get();
+ if (b == delimiter[0]){
+ return true;
+ }else{
+ codecState.buffer.put(b);
+ }
+ }
+ }
+ return false;
+
+ }
+
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterEncoder.java
new file mode 100644
index 0000000..1492703
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/delimiter/codec/DelimiterEncoder.java
@@ -0,0 +1,69 @@
+package com.eactive.eai.adapter.socket2.protocol.delimiter.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.HexUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class DelimiterEncoder implements ProtocolEncoder {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public DelimiterEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+ byte[] delimiter = HexUtil.string2Hex(context.getDelimiter());
+ int length = m.size();
+ ByteBuffer buffer = ByteBuffer.allocate( length + delimiter.length ).limit( length + delimiter.length );
+ buffer.put(m.getBytes());
+ buffer.put(delimiter);
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | DelimiterEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "DelimiterEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ out.flush();
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ }
+
+
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesClientFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesClientFilter.java
new file mode 100644
index 0000000..e19e3b6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesClientFilter.java
@@ -0,0 +1,66 @@
+package com.eactive.eai.adapter.socket2.protocol.des.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+import javax.crypto.spec.SecretKeySpec;
+
+
+public class DesClientFilter extends DesFilter {
+ public DesClientFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ // empty
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = (ByteMessage) message;
+
+ switch (filterState.state) {
+ case STATE_HANDSHAKE:
+ /**
+ * read secret key
+ */
+ /*
+ ByteArrayInputStream bis = new ByteArrayInputStream(m.getBytes());
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ filterState.secretKey = (SecretKey) ois.readObject();
+ ois.close();
+ */
+ filterState.secretKey = new SecretKeySpec(m.getBytes(), "DES");
+
+ /**
+ * change state
+ */
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+ nextFilter.sessionOpened(session);
+ break;
+
+ case STATE_MESSAGE:
+ DesCodec des = new DesCodec(filterState.secretKey);
+ byte[] decrypted = des.decrypt(m.getBytes());
+ m = new ByteMessage(decrypted);
+
+ ///*
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | DesClientFilter | after decrypt : " + m.hexDump());
+ }
+ //*/
+
+ nextFilter.messageReceived(session, m);
+ break;
+
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + m);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesCodec.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesCodec.java
new file mode 100644
index 0000000..0a05b72
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesCodec.java
@@ -0,0 +1,64 @@
+package com.eactive.eai.adapter.socket2.protocol.des.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.common.util.Logger;
+
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.SecretKey;
+
+public class DesCodec {
+ Cipher ecipher;
+ Cipher dcipher;
+ private Logger logger = SocketLoggerManager.getInstance().getLogger();
+ private static final String DES_CIPER = "DES";
+ public DesCodec(SecretKey key) {
+ try {
+ ecipher = Cipher.getInstance(DES_CIPER);
+ dcipher = Cipher.getInstance(DES_CIPER);
+ ecipher.init(Cipher.ENCRYPT_MODE, key);
+ dcipher.init(Cipher.DECRYPT_MODE, key);
+ } catch (javax.crypto.NoSuchPaddingException e) {
+ logger.info("NoSuchPaddingException"+ e.toString());
+ } catch (java.security.NoSuchAlgorithmException e) {
+ logger.info("NoSuchAlgorithmException"+ e.toString());
+ } catch (java.security.InvalidKeyException e) {
+ logger.info("InvalidKeyException"+ e.toString());
+ }
+ }
+
+ public byte[] encrypt(byte[] utf8) {
+ try {
+ // Encode the string into bytes using utf-8
+ //byte[] utf8 = str.getBytes("UTF8");
+ // Encrypt
+// byte[] enc = ecipher.doFinal(utf8);
+ // Encode bytes to base64 to get a string
+ //return new sun.misc.BASE64Encoder().encode(enc);
+ return ecipher.doFinal(utf8);
+ } catch (javax.crypto.BadPaddingException e) {
+ logger.info("BadPaddingException - "+ e.toString());
+ } catch (IllegalBlockSizeException e) {
+ logger.info("IllegalBlockSizeException - "+ e.toString());
+ }
+ return null;
+ }
+
+ public byte[] decrypt(byte[] dec) {
+ try {
+ // Decode base64 to get bytes
+ //byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
+
+ // Decrypt
+// byte[] utf8 = dcipher.doFinal(dec);
+ // Decode using utf-8
+// return new String(utf8, "UTF8");
+ return dcipher.doFinal(dec);
+ } catch (javax.crypto.BadPaddingException e) {
+ logger.info("BadPaddingException - "+ e.toString());
+ } catch (IllegalBlockSizeException e) {
+ logger.info("IllegalBlockSizeException - "+ e.toString());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesFilter.java
new file mode 100644
index 0000000..89226c6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesFilter.java
@@ -0,0 +1,108 @@
+package com.eactive.eai.adapter.socket2.protocol.des.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+
+import javax.crypto.SecretKey;
+
+
+public abstract class DesFilter extends IoFilterAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ private static final String NEXT_FILTER = DesFilter.class.getName() + ".NextFilter";
+ protected static final String FILTER_STATE_KEY = DesFilter.class.getName() + ".STATE";
+ protected static final String SESSION_STATE = "SESSION_STATE";
+
+ protected enum State {
+ STATE_HANDSHAKE,
+ STATE_MESSAGE;
+ }
+
+ protected static class FilterState {
+ public State state = State.STATE_HANDSHAKE;
+ public SecretKey secretKey = null;
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ protected DesFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
+ if (parent.contains(DesFilter.class)) {
+ throw new IllegalStateException("A filter chain cannot contain more than one DesFilter.");
+ }
+
+ IoSession session = parent.getSession();
+ session.setAttribute(NEXT_FILTER, nextFilter);
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ nextFilter.sessionCreated(session);
+ }
+
+
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = null;
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ if (filterState.state == State.STATE_MESSAGE) {
+ ///*
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | DesFilter | filterWrite() " + m.hexDump());
+ }
+ //*/
+
+ //key = KeyGenerator.getInstance("DES").generateKey();
+ DesCodec des = new DesCodec(filterState.secretKey);
+ byte[] encrypted = des.encrypt(m.getBytes());
+ m = new ByteMessage(encrypted);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | DesFilter | filterWrite() - after encrypt - " + m.hexDump());
+ }
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesServerFilter.java
new file mode 100644
index 0000000..2c27a61
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/des/handshake/DesServerFilter.java
@@ -0,0 +1,70 @@
+package com.eactive.eai.adapter.socket2.protocol.des.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+import javax.crypto.KeyGenerator;
+
+
+public class DesServerFilter extends DesFilter {
+ public DesServerFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ /**
+ * create secret key
+ */
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ filterState.secretKey = KeyGenerator.getInstance("DES").generateKey();
+
+ /**
+ * send secret key
+ */
+ /*
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(filterState.secretKey);
+ oos.close();
+ WriteFuture future = session.write(new ByteMessage(bos.toByteArray()));
+ //future.join(context.getTimeout() * 60L);
+ */
+ byte[] keyBytes = filterState.secretKey.getEncoded();
+// WriteFuture future = session.write(new ByteMessage(keyBytes));
+ session.write(new ByteMessage(keyBytes));
+ /**
+ * change state
+ */
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ /**
+ * next filter
+ */
+ nextFilter.sessionOpened(session);
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | DesServerFilter | messageReceived() " + m.hexDump());
+ }
+
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ DesCodec des = new DesCodec(filterState.secretKey);
+ byte[] decrypted = des.decrypt(m.getBytes());
+ m = new ByteMessage(decrypted);
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | DesServerFilter | messageReceived() - after decrypt - " + m.hexDump());
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.messageReceived(session, m);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetClient.java
new file mode 100644
index 0000000..15e229f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetClient.java
@@ -0,0 +1,39 @@
+package com.eactive.eai.adapter.socket2.protocol.dynamicoffset;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.filter.polling.KFTCPollingFilter;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.dynamicoffset.codec.DynamicOffsetCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.ack.AckClientFilter;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.ChunkCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class DynamicOffsetClient extends TcpAdapterClient {
+ public DynamicOffsetClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new DynamicOffsetHandler(this);
+
+ if ("NONE".equals(context.getLlFieldType())) {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new ChunkCodecFactory(this)));
+ } else {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new DynamicOffsetCodecFactory(this)));
+ }
+
+ if ("Y".equals(context.getAckSupport())) {
+ config.getFilterChain().addAfter("codec", "ack", new AckClientFilter(this));
+ }
+
+ if (context.isPollingUse()) {
+ config.getFilterChain().addAfter("polling", "kftcPolling", new KFTCPollingFilter(this));
+ config.getFilterChain().remove("polling");
+ }
+
+ }
+
+ @Override
+ public Object sendMessage(Object message) throws EAIException {
+ return super.sendMessage(message);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetHandler.java
new file mode 100644
index 0000000..b8e2455
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.protocol.dynamicoffset;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class DynamicOffsetHandler extends ProtocolHandler {
+ public DynamicOffsetHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetServer.java
new file mode 100644
index 0000000..736c7c2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/DynamicOffsetServer.java
@@ -0,0 +1,32 @@
+package com.eactive.eai.adapter.socket2.protocol.dynamicoffset;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.filter.polling.KFTCPollingFilter;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.dynamicoffset.codec.DynamicOffsetCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.ack.AckServerFilter;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.ChunkCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class DynamicOffsetServer extends TcpAdapterServer {
+ public DynamicOffsetServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new DynamicOffsetHandler(this);
+
+ if ("NONE".equals(context.getLlFieldType())) {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new ChunkCodecFactory(this)));
+ } else {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new DynamicOffsetCodecFactory(this)));
+ }
+
+ if ("Y".equals(context.getAckSupport())) {
+ config.getFilterChain().addAfter("codec", "ack", new AckServerFilter(this));
+ }
+ if (context.isPollingUse()) {
+ config.getFilterChain().addAfter("polling", "kftcPolling", new KFTCPollingFilter(this));
+ config.getFilterChain().remove("polling");
+ }
+
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetCodecFactory.java
new file mode 100644
index 0000000..9fba649
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetCodecFactory.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.dynamicoffset.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class DynamicOffsetCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+ public DynamicOffsetCodecFactory(ISocketAdapter adapter) {
+ encoder = new DynamicOffsetEncoder(adapter);
+ decoder = new DynamicOffsetDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetDecoder.java
new file mode 100644
index 0000000..4711962
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetDecoder.java
@@ -0,0 +1,355 @@
+package com.eactive.eai.adapter.socket2.protocol.dynamicoffset.codec;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.util.ByteCharSequence;
+
+public class DynamicOffsetDecoder extends ProtocolDecoderAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ int hdrLength = 0;//패턴때문에 보정필요
+ public static final int MAX_PAYLOAD_SIZE = 25 * 1024 * 1024; // 25MB
+
+ private static final String ERROR_CODE = "RECEAINNA008";
+
+ private static final String DECODER_STATE_KEY = DynamicOffsetDecoder.class.getName() + ".STATE";
+
+ private enum State {
+ STATE_HEADER_READ, STATE_PAYLOAD_READ;
+ }
+
+ private static class CodecState {
+ State state = State.STATE_HEADER_READ;
+ ByteBuffer buffer = ByteBuffer.allocate(0).setAutoExpand(true);
+ int payloadSize;
+ int offsetSize;
+ }
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public DynamicOffsetDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @SuppressWarnings("static-access")
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(context.getLlFieldOffset() + context.getLlFieldLength() + hdrLength);
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("DynamicOffsetDecoder");
+ //sb.append(codecState.state);
+ if (codecState.state == State.STATE_PAYLOAD_READ) {
+ sb.append("(" + codecState.payloadSize + ")");
+ }
+ sb.append(" | decode : " + CommonLib.hexDump(in, context));
+ logger.debug(sb.toString());
+ adapter.addRecentRecvTrace(session, sb.toString());
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+
+ /**
+ * payload size < 0 인 경우
+ */
+ if (codecState.payloadSize < 0) {
+ throw new EAIException(ERROR_CODE, context.getAdapterName() +
+// " (" + context.getLlFieldType() + "," + context.getLlFieldOffset() + "," + context.getLlFieldLength() +
+ " (" + context.getLlFieldType() + "," + codecState.offsetSize + "," + context.getLlFieldLength() +
+ ") | when read header, ll length field is invalid | " + CommonLib.hexDump(codecState.buffer, context));
+ /**
+ * payload size == 0 인 경우
+ */
+ } else if (codecState.payloadSize == 0) {
+ if (context.isSync()) {
+ throw new Exception(" payload size 0 (ping). 'SYNC' response type socket does not support ping(size 0) message.");
+ }
+
+ //codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_INFO ) {
+ logger.info(context.getAdapterName() + " | payload size 0 (ping) -> ignore. - " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "payload size 0 (ping) -> ignore. - " + CommonLib.hexDump(in, context));
+ }
+
+ /**
+ * header 값을 읽은 후 buffer의 position을 이동해 준다.
+ * 이 작업을 안해주면 무한루프에 빠질 수 있다.
+ * 예) 법원 공탁금 (_LAW_IN_SOC_AsS{...})
+ */
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength());//초기화
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ break;
+ }
+
+ /**
+ * ll.include = 'Y' - LL을 포함해서 넘긴다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ try {
+ codecState.buffer.position(context.getLlFieldOffset() + context.getLlFieldLength())
+ .limit(codecState.payloadSize + context.getLlFieldLength());
+// if (codecState.offsetSize == context.getLlFieldOffset()){ //일반전문
+// codecState.buffer.position(codecState.offsetSize + context.getLlFieldLength() )
+// .limit(codecState.payloadSize + context.getLlFieldLength());
+// }else{//폴링전문
+// codecState.buffer.position(codecState.offsetSize +context.getLlFieldOffset() + context.getLlFieldLength() )
+// .limit(codecState.payloadSize + context.getLlFieldLength());
+// }
+ } catch(IllegalArgumentException e) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(context.getAdapterName() + " | error when handling buffer | ");
+// sb.append("offset=" + context.getLlFieldOffset() + context.getLlFieldLength());
+ sb.append("offset=" + codecState.offsetSize + context.getLlFieldLength());
+ sb.append(", limit=" + codecState.payloadSize + context.getLlFieldLength());
+ logger.error(sb.toString());
+ errLogger.error(sb.toString());
+ adapter.addRecentError(sb.toString());
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA007");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA007");
+ throw e;
+ }
+ /**
+ * ll.include = 'N' - LL을 제외하고 넘긴다.
+ */
+ } else {
+ try {
+ codecState.buffer.position(context.getLlFieldOffset()).limit(codecState.payloadSize);
+// if (codecState.offsetSize == context.getLlFieldOffset()){ //일반전문
+// codecState.buffer.position(codecState.offsetSize).limit(codecState.payloadSize);
+// }else{
+// codecState.buffer.position(codecState.offsetSize + context.getLlFieldOffset()).limit(codecState.payloadSize);
+// }
+ } catch(IllegalArgumentException e) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(context.getAdapterName() + " | error when handling buffer | ");
+// sb.append("offset=" + context.getLlFieldOffset());
+ sb.append("offset=" + codecState.offsetSize);
+ sb.append(", limit=" + codecState.payloadSize);
+ logger.error(sb.toString());
+ errLogger.error(sb.toString());
+ adapter.addRecentError(sb.toString());
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA007");
+ throw e;
+ }
+ }
+
+ /**
+ * offset + ll 을 읽었고, 더 이상 읽을 것(payload)이 없는 경우
+ * - ll.length value = ll.offset + ll.field.length
+ */
+ if (codecState.buffer.position() == codecState.buffer.limit()) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0);
+ codecState.buffer.get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength());//초기화
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ break;
+ }
+
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0);
+ codecState.buffer.get(bytes);
+// ByteMessage message = new ByteMessage(bytes);
+ ByteMessage message = null;
+ if (codecState.offsetSize == context.getLlFieldOffset()){
+ message = removeData(new ByteMessage(bytes));
+ }else{
+ message = new ByteMessage(bytes);
+ }
+
+ out.write(message);
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength());//limit 초기화
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+
+ break;
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | read header : " + in);
+ }
+ */
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+ //offsetSize 를 가져온다.
+ codecState.offsetSize = getPatternOffset(codecState);
+ if ("CHAR".equals(context.getLlFieldType())) {
+ codecState.buffer.flip();
+ try {
+ byte[] header = new byte[context.getLlFieldLength()];
+ for (int i=0; i MAX_PAYLOAD_SIZE) {
+ throw new Exception("max payload size(" + MAX_PAYLOAD_SIZE + ") exceeded : " +
+ codecState.payloadSize + " | " +
+ CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ /**
+ * ll.field.include = 'Y' - 헤더 길이를 빼 준다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ codecState.payloadSize = codecState.payloadSize - context.getLlFieldLength();
+ }
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 더해서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+// codecState.payloadSize = codecState.payloadSize + context.getLlFieldOffset();
+ codecState.payloadSize = codecState.payloadSize + codecState.offsetSize;
+ }
+
+ /**
+ * ll.length.adjust = 200 - 공통부 header 길이를 더한다. (한은망 평문 테스트용)
+ */
+ if (context.getLlLenAdjust() != 0) {
+ codecState.payloadSize = codecState.payloadSize + context.getLlLenAdjust();
+ }
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | read payload : " + in);
+ }
+ */
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ return true;
+ }
+ private int getPatternOffset(CodecState codecState){
+ int offset = 0;
+
+ byte[] data = new byte[codecState.buffer.limit()];
+ codecState.buffer.flip();
+ codecState.buffer.get(data);
+
+ String dynamicOffsetPattern = context.getDynamicOffsetPattern().trim();
+ Matcher matcher = Pattern.compile(dynamicOffsetPattern).matcher(new ByteCharSequence(data));
+ if(matcher.find()){
+ offset = matcher.start();
+ }else{
+ offset = context.getLlFieldOffset();
+ }
+ return offset;
+ }
+ private ByteMessage removeData(ByteMessage m) throws Exception{
+ ByteMessage mm = null ;
+
+ /**
+ * removedata.rule
+ */
+ if (!"".equals(context.getDataRemoveRule())) {
+ Matcher matcher = Pattern.compile("\\[([ ]*[0-9]+)[ ]*,([ ]*[0-9]+)[ ]*\\][ ]*").matcher(context.getDataRemoveRule().trim());
+
+ if (matcher.find()) {
+ int offset = Integer.parseInt(matcher.group(1).trim());
+ int length = Integer.parseInt(matcher.group(2).trim());
+ mm = (new ByteMessage())
+ .append(m.getBytes(0, offset))
+ .append(m.getBytes(offset + length));
+ }
+ else {
+ throw new Exception(context.getAdapterName() + " | data.remove.rule format is invalid : " + context.getDataRemoveRule());
+ }
+ }
+ return mm;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetEncoder.java
new file mode 100644
index 0000000..d687926
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/dynamicoffset/codec/DynamicOffsetEncoder.java
@@ -0,0 +1,175 @@
+package com.eactive.eai.adapter.socket2.protocol.dynamicoffset.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import com.eactive.eai.common.util.StringUtil;
+import com.eactive.eai.util.ByteCharSequence;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DynamicOffsetEncoder implements ProtocolEncoder {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public DynamicOffsetEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ int offset = getPatternOffset(m.getBytes());
+ if (offset == context.getLlFieldOffset()){
+ m = addData(m);
+ }
+
+ if(m == null) {
+ throw new Exception("ByteMessage cannot NULL.");
+ }
+ /**
+ * ll.include = 'Y' - 통째로 보낸다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ ByteBuffer buffer = ByteBuffer.allocate(m.size() - context.getLlFieldLength());
+// buffer.put(m.getBytes(0, context.getLlFieldOffset()));
+// buffer.put(m.getBytes(context.getLlFieldOffset() + context.getLlFieldLength()));
+ buffer.put(m.getBytes(0, offset));
+ buffer.put(m.getBytes(offset + context.getLlFieldLength()));
+ buffer.flip();
+ m.setByteBuffer(buffer);
+ }
+
+ int length = m.size();
+ ByteBuffer buffer = ByteBuffer.allocate(context.getLlFieldLength() + length).limit(context.getLlFieldLength() + length);
+
+ /**
+ * ll.field.include = 'Y' - header 길이 포함하여 ll 을 계산한다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ length = length + context.getLlFieldLength();
+ }
+
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 빼서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+// length = length - context.getLlFieldOffset();
+ length = length - offset;
+ }
+
+ /**
+ * ll.length.adjust = 200 - 공통부 header 길이를 더한다. (한은망 평문 테스트용)
+ */
+ if (context.getLlLenAdjust() != 0) {
+ length = length + context.getLlLenAdjust();
+ }
+
+
+ /**
+ * [1] before-payload
+ */
+// buffer.put(m.getBytes(0, context.getLlFieldOffset()));
+ buffer.put(m.getBytes(0, offset));
+
+ /**
+ * [2] write header
+ */
+ if ("CHAR".equals(context.getLlFieldType())) {
+ String lenStr = CommonLib.getFormatString(length, context.getLlFieldLength());
+ buffer.put(lenStr.getBytes());
+ }
+
+ /**
+ * [3] after-payload
+ */
+// buffer.put(m.getBytes(context.getLlFieldOffset(), m.getBytes().length - context.getLlFieldOffset()));
+ buffer.put(m.getBytes(offset, m.getBytes().length - offset));
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | FixedHeaderEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "FixedHeaderEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ out.flush();
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ // empty
+ }
+ private int getPatternOffset(byte[] data){
+ int offset = 0;
+
+ String dynamicOffsetPattern = context.getDynamicOffsetPattern().trim();
+ Matcher matcher = Pattern.compile(dynamicOffsetPattern).matcher(new ByteCharSequence(data));
+ if(matcher.find()){
+ offset = matcher.start();
+ }else{
+ offset = context.getLlFieldOffset();
+ }
+ return offset;
+ }
+ private ByteMessage addData(ByteMessage m) throws Exception{
+ ByteMessage mm = null ;
+
+ /**
+ * adddata.rule
+ */
+ if (!"".equals(context.getDataAddRule())) {
+ Matcher matcher = Pattern.compile("\\[([ ]*[0-9]+)[ ]*,([ ]*[0-9]+)[ ]*\\][ ]*=[ ]*(.+)").matcher(context.getDataAddRule().trim());
+ if (matcher.find()) {
+ int offset = Integer.parseInt(matcher.group(1).trim());
+ int length = Integer.parseInt(matcher.group(2).trim());
+ String re = matcher.group(3).trim();
+ if (re != null && length != re.length()){
+ re = StringUtil.stringFormat(re, false, ' ', length);
+ }
+ if (re != null){
+ mm = (new ByteMessage())
+ .append(m.getBytes(0, offset))
+ .append(re.getBytes())
+ .append(m.getBytes(offset));
+
+ }
+ } else {
+ throw new Exception(context.getAdapterName() + " | data.add.rule format is invalid : " + context.getDataAddRule());
+ }
+ }
+ return mm;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoClient.java
new file mode 100644
index 0000000..50c681a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoClient.java
@@ -0,0 +1,12 @@
+package com.eactive.eai.adapter.socket2.protocol.echo;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+
+
+public class EchoClient extends TcpAdapterClient {
+ public EchoClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new EchoProtocolHandler(this);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoProtocolHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoProtocolHandler.java
new file mode 100644
index 0000000..2ef423f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoProtocolHandler.java
@@ -0,0 +1,63 @@
+package com.eactive.eai.adapter.socket2.protocol.echo;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+
+
+public class EchoProtocolHandler extends ProtocolHandler {
+ public EchoProtocolHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void messageReceived(IoSession session, Object message) throws Exception {
+ if (!(message instanceof ByteBuffer)) {
+ return;
+ }
+
+ ByteBuffer rb = (ByteBuffer) message;
+
+ synchronized(this) {
+ messageRecv++;
+ }
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | : " + CommonLib.hexDump(rb, context));
+ }
+
+ if (!context.isSync()) {
+ return;
+ }
+
+ ByteBuffer wb = ByteBuffer.allocate(rb.remaining());
+ wb.put(rb);
+ wb.flip();
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | : " + CommonLib.hexDump(wb, context));
+ }
+
+ session.write(wb).join();
+
+ synchronized(this) {
+ messageSend++;
+ }
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ if (message instanceof byte[]) {
+ logger.debug(context.getAdapterName() + " | " + CommonLib.hexDump((byte[]) message, true, context));
+ adapter.addRecentSend(session, CommonLib.hexDump((byte[]) message, true, context ));
+ } else if (message instanceof String) {
+ logger.debug(context.getAdapterName() + " | " + CommonLib.hexDump(((String) message).getBytes(), true, context));
+ adapter.addRecentSend(session, message.toString());
+ } else {
+ logger.debug(context.getAdapterName() + " | " + message);
+ adapter.addRecentSend(session, message.toString());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoServer.java
new file mode 100644
index 0000000..6b41f2c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/echo/EchoServer.java
@@ -0,0 +1,12 @@
+package com.eactive.eai.adapter.socket2.protocol.echo;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+
+public class EchoServer extends TcpAdapterServer {
+
+ public EchoServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new EchoProtocolHandler(this);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopClient.java
new file mode 100644
index 0000000..e2d1e07
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopClient.java
@@ -0,0 +1,18 @@
+package com.eactive.eai.adapter.socket2.protocol.envelop;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.envelop.handshake.EnvelopClientFilter;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.FixedHeaderCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+public class EnvelopClient extends TcpAdapterClient {
+
+ public EnvelopClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new EnvelopHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedHeaderCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "envelop-client", new EnvelopClientFilter(this));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopHandler.java
new file mode 100644
index 0000000..ba5739e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.protocol.envelop;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class EnvelopHandler extends ProtocolHandler {
+ public EnvelopHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopServer.java
new file mode 100644
index 0000000..1fa8bb0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/EnvelopServer.java
@@ -0,0 +1,18 @@
+package com.eactive.eai.adapter.socket2.protocol.envelop;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.envelop.handshake.EnvelopServerFilter;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.FixedHeaderCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+public class EnvelopServer extends TcpAdapterServer {
+ public EnvelopServer(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ this.handler = new EnvelopHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedHeaderCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "ENVELOP.SERVER", new EnvelopServerFilter(this));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopClientFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopClientFilter.java
new file mode 100644
index 0000000..68ddd1e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopClientFilter.java
@@ -0,0 +1,171 @@
+package com.eactive.eai.adapter.socket2.protocol.envelop.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import com.sf.xc.XCException;
+import com.sf.xc.XCUtil;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+
+
+public class EnvelopClientFilter extends IoFilterAdapter {
+
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ private static final String NEXT_FILTER = EnvelopClientFilter.class.getName() + ".NextFilter";
+ protected static final String FILTER_STATE_KEY = EnvelopClientFilter.class.getName() + ".STATE";
+ protected static final String SESSION_STATE = "SESSION_STATE";
+
+ protected enum State {
+ STATE_HANDSHAKE,
+ STATE_MESSAGE;
+ }
+
+ protected static class FilterState {
+ public State state = State.STATE_MESSAGE; //State.STATE_HANDSHAKE;
+ public byte[] userKey = new byte[16];
+ public int[] roundKey = new int[32];
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ public EnvelopClientFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
+ if (parent.contains(EnvelopClientFilter.class)) {
+ throw new IllegalStateException("A filter chain cannot contain more than one DesFilter.");
+ }
+
+ IoSession session = parent.getSession();
+ session.setAttribute(NEXT_FILTER, nextFilter);
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ nextFilter.sessionCreated(session);
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ try {
+ /**
+ * EnvelopClient init
+ */
+ try {
+ byte[] cert = XCUtil.readFile("modules/envelop/cert/signCert.der");
+// XCE2EClient client = new XCE2EClient(cert);
+
+// session.setAttribute("ENVELOP.CLIENT", client);
+ } catch(Exception e) {
+ logger.warn("ENVELOP.CLIENT set error", e);
+ }
+
+ nextFilter.sessionOpened(session);
+
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | Envelop init error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | Envelop init error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | Envelop init error - " + e.getMessage(), e);
+
+ try {
+ adapter.getSessionPool().remove(session);
+ session.close();
+ } catch(Exception ignor) {
+ logger.warn("session.close error", e);
+ }
+
+ throw new Exception(context.getAdapterName() + " | Envelop init error - " + e.getMessage());
+ }
+ }
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = (ByteMessage) message;
+
+ switch (filterState.state) {
+ case STATE_MESSAGE:
+ /**
+ * decrypt
+ */
+// byte[] decrypted = EnvelopCodec.e2eClientDecrypt(m.getBytes(), session);
+// if (decrypted == null || decrypted.length == 0) {
+// throw new Exception("received message is invalid - check if message is encrypted : " + m.hexDump());
+// }
+// m.setBytes(decrypted);
+
+ /**
+ * next filter
+ */
+ nextFilter.messageReceived(session, m);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + m.hexDump());
+ }
+ }
+
+ @SuppressWarnings("static-access")
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = null;
+
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | EnvelopFilter | " + filterState.state.toString() + " | " + m.hexDump());
+ }
+
+ try {
+
+// m = EnvelopCodec.e2eClientEncrypt(m.getBytes(), session);
+
+ } catch(Exception xce) {
+ adapter.addRecentError(context.getAdapterName() + " | envelop error - " + xce.getMessage(), xce);
+ logger.error(context.getAdapterName() + " | envelop error - " + xce.getMessage(), xce);
+ errLogger.error(context.getAdapterName() + " | envelop error - " + xce.getMessage(), xce);
+ throw new XCException(context.getAdapterName() + " | envelop error - " + xce.getMessage());
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopCodec.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopCodec.java
new file mode 100644
index 0000000..5c8eab3
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopCodec.java
@@ -0,0 +1,32 @@
+package com.eactive.eai.adapter.socket2.protocol.envelop.handshake;//package com.eactive.eai.adapter.socket2.protocol.envelop.handshake;
+//
+//import org.apache.mina.common.IoSession;
+//
+//import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+//import com.sf.xc.XCE2EClient;
+//import com.sf.xc.XCE2EServer;
+//
+//public class EnvelopCodec {
+// public static ByteMessage e2eServerEncrypt(byte[] bytes, IoSession session) throws Exception {
+//
+// XCE2EServer server = (XCE2EServer) session.getAttribute("ENVELOP.SERVER");
+// return (new ByteMessage(server.encryptServer(bytes)));
+// }
+//
+// public static byte[] e2eServerDecrypt(byte[] bytes, IoSession session) throws Exception {
+//
+// XCE2EServer server = (XCE2EServer) session.getAttribute("ENVELOP.SERVER");
+// return (server.decryptServer(bytes));
+// }
+// public static ByteMessage e2eClientEncrypt(byte[] bytes, IoSession session) throws Exception {
+//
+// XCE2EClient client = (XCE2EClient) session.getAttribute("ENVELOP.CLIENT");
+// return (new ByteMessage(client.encryptClient(bytes)));
+// }
+//
+// public static byte[] e2eClientDecrypt(byte[] bytes, IoSession session) throws Exception {
+//
+// XCE2EClient client = (XCE2EClient) session.getAttribute("ENVELOP.CLIENT");
+// return (client.decryptClient(bytes));
+// }
+//}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopServerFilter.java
new file mode 100644
index 0000000..88d6cda
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/envelop/handshake/EnvelopServerFilter.java
@@ -0,0 +1,192 @@
+package com.eactive.eai.adapter.socket2.protocol.envelop.handshake;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import com.sf.xc.XCException;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+
+
+public class EnvelopServerFilter extends IoFilterAdapter {
+
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ private static final String NEXT_FILTER = EnvelopServerFilter.class.getName() + ".NextFilter";
+ protected static final String FILTER_STATE_KEY = EnvelopServerFilter.class.getName() + ".STATE";
+ protected static final String SESSION_STATE = "SESSION_STATE";
+
+ protected enum State {
+ STATE_HANDSHAKE,
+ STATE_MESSAGE;
+ }
+
+ protected static class FilterState {
+ public State state = State.STATE_MESSAGE; //State.STATE_HANDSHAKE;
+ public byte[] userKey = new byte[16];
+ public int[] roundKey = new int[32];
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ public EnvelopServerFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
+ if (parent.contains(EnvelopServerFilter.class)) {
+ throw new IllegalStateException("A filter chain cannot contain more than one DesFilter.");
+ }
+
+ IoSession session = parent.getSession();
+ session.setAttribute(NEXT_FILTER, nextFilter);
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ nextFilter.sessionCreated(session);
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ try {
+ /**
+ * EnvelopServer init
+ */
+// XCE2EServer server = new XCE2EServer(context.getEnvelopSigncertPath(),context.getEnvelopSignkeyPath(),context.getEnvelopPassword());
+//
+// session.setAttribute("ENVELOP.SERVER", server);
+//
+// nextFilter.sessionOpened(session);
+
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | Envelop init error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | Envelop init error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | Envelop init error - " + e.getMessage(), e);
+
+ try {
+ adapter.getSessionPool().remove(session);
+ session.close();
+ } catch(Exception ignor) {
+ logger.warn(context.getAdapterName() + " session close errir ", e);
+ }
+
+ throw new Exception(context.getAdapterName() + " | Envelop init error - " + e.getMessage());
+ }
+ }
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = (ByteMessage) message;
+
+ switch (filterState.state) {
+ case STATE_MESSAGE:
+ /**
+ * decrypt
+ */
+// byte[] decrypted = EnvelopCodec.e2eServerDecrypt(m.getBytes(), session);
+// if (decrypted == null || decrypted.length == 0) {
+// throw new Exception("received message is invalid - check if message is encrypted : " + m.hexDump());
+// }
+// m.setBytes(decrypted);
+
+ /**
+ * next filter
+ */
+ nextFilter.messageReceived(session, m);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + m.hexDump());
+ }
+ }
+
+ @SuppressWarnings("static-access")
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = null;
+
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | EnvelopFilter | " + filterState.state.toString() + " | " + m.hexDump());
+ }
+
+ try {
+ /**
+ * check polling message - skip polling
+ */
+ if (!context.isPollingUse() || !isPollingPattern(m)) {
+
+ filterState.state = State.STATE_MESSAGE;
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+
+ /**
+ * encrypt
+ */
+// m = EnvelopCodec.e2eServerEncrypt(m.getBytes(), session);
+
+ }
+
+ } catch(Exception xce) {
+ adapter.addRecentError(context.getAdapterName() + " | envelop error - " + xce.getMessage(), xce);
+ logger.error(context.getAdapterName() + " | envelop error - " + xce.getMessage(), xce);
+ errLogger.error(context.getAdapterName() + " | envelop error - " + xce.getMessage(), xce);
+ throw new XCException(context.getAdapterName() + " | envelop error - " + xce.getMessage());
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+
+ private boolean isPollingPattern(ByteMessage m) throws EAIException {
+ ByteMessage bm = m;
+ if ("Y".equals(context.getLlInclude())) {
+ bm = (new ByteMessage())
+ .append(m.getBytes(0, context.getLlFieldOffset()))
+ .append(m.getBytes(context.getLlFieldOffset() + context.getLlFieldLength()));
+ }
+
+ if ((context.isPollingReceiver() && bm.getString().matches(context.getPollingResponsePattern()))
+ || (context.isPollingSender() && bm.getString().matches(context.getPollingRequestPattern())))
+ return true;
+
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderBlockingHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderBlockingHandler.java
new file mode 100644
index 0000000..2897a51
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderBlockingHandler.java
@@ -0,0 +1,256 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.SocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.FixedHeaderDecoder;
+import com.eactive.eai.common.util.Logger;
+
+import java.io.*;
+import java.net.Socket;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class FixedHeaderBlockingHandler {
+ @SuppressWarnings("static-access")
+ static public byte[] sendMessage(SocketAdapter adapter, Object request) throws Exception {
+ SocketAdapterContext context = adapter.getContext();
+ Logger logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+
+ byte[] m = null;
+ if (request instanceof byte[]) {
+ m = (byte[]) request;
+ } else if (request instanceof String) {
+ m = ((String) request).getBytes();
+ }
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | " + CommonLib.hexDump(m, true, context));
+ adapter.addRecentSend(null, CommonLib.hexDump(m, true, context));
+ }
+
+ Socket socket = null;
+ InputStream is = null;
+ OutputStream os = null;
+
+ // System.out.println(Thread.currentThread().getName() +
+ // " ### before get | semaphore + " +
+ // context.getMaxConnSemaphore().availablePermits());
+ boolean success = context.getMaxConnSemaphore().tryAcquire(context.getTimeout(),
+ TimeUnit.SECONDS);
+ if (!success) {
+ throw new TimeoutException("connot get max conn semaphore - "
+ + context.getMaxConnection());
+ }
+
+ try {
+ socket = new Socket(context.getHostName(), context.getPortNumber());
+ socket.setSoTimeout(context.getTimeout() * 1000);
+ is = new BufferedInputStream(socket.getInputStream());
+ os = new BufferedOutputStream(socket.getOutputStream());
+ os.write(encode(context, m));
+ os.flush();
+ adapter.incMessageSend();
+
+ byte[] response = decode(context, m, socket, is);
+ adapter.incMessageRecv();
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | " + CommonLib.hexDump(response, true, context));
+ adapter.addRecentRecv(null, CommonLib.hexDump(response, true, context));
+ }
+
+ return response;
+ } finally {
+ if (is != null)
+ try {
+ is.close();
+ } catch (Exception e) {
+ }
+ if (os != null)
+ try {
+ os.close();
+ } catch (Exception e) {
+ }
+ if (socket != null)
+ try {
+ socket.close();
+ } catch (Exception e) {
+ }
+ context.getMaxConnSemaphore().release();
+ // System.out.println(Thread.currentThread().getName() +
+ // " ### after release | semaphore - " +
+ // context.getMaxConnSemaphore().availablePermits());
+ }
+ }
+
+ @SuppressWarnings("static-access")
+ static private byte[] encode(SocketAdapterContext context, byte[] request) throws Exception {
+ Logger logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+
+ ByteMessage m = new ByteMessage(request);
+ ByteMessage result = new ByteMessage();
+
+ /**
+ * ll.include = 'Y' - 통째로 보낸다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ ByteMessage temp = new ByteMessage();
+ temp.append(m.getBytes(0, context.getLlFieldOffset()));
+ temp.append(m.getBytes(context.getLlFieldOffset() + context.getLlFieldLength()));
+ m = temp;
+ }
+
+ int length = m.size();
+
+ /**
+ * ll.field.include = 'Y' - header 길이 포함하여 ll 을 계산한다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ length = length + context.getLlFieldLength();
+ }
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 빼서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+ length = length - context.getLlFieldOffset();
+ }
+
+ /**
+ * [1] before-payload
+ */
+ result.append(m.getBytes(0, context.getLlFieldOffset()));
+
+ /**
+ * [2] write header
+ */
+ byte[] header = null;
+ if ("BIN".equals(context.getLlFieldType())) {
+ int tmpLength = length;
+ header = new byte[context.getLlFieldLength()];
+ for (int i = context.getLlFieldLength() - 1; i >= 0; i--) {
+ header[i] = (byte) (tmpLength % 256);
+ tmpLength = tmpLength / 256;
+ }
+ } else { // "CHAR"
+ String lenStr = CommonLib.getFormatString(length, context.getLlFieldLength());
+ header = lenStr.getBytes();
+ }
+ result.append(header);
+
+ /**
+ * [3] after-payload
+ */
+ result.append(m.getBytes(context.getLlFieldOffset(), m.getBytes().length
+ - context.getLlFieldOffset()));
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | FixedHeaderEncoder(Blocking) | encode : "
+ + result.hexDump());
+ }
+ return result.getBytes();
+ }
+
+ @SuppressWarnings("static-access")
+ static private byte[] decode(SocketAdapterContext context, byte[] request, Socket socket,
+ InputStream is) throws Exception {
+ Logger logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+
+ ByteMessage result = new ByteMessage();
+
+ byte[] offsetPlusHeader = new byte[context.getLlFieldOffset() + context.getLlFieldLength()];
+ int read = is.read(offsetPlusHeader);
+ if (read == -1) {
+ throw new IOException("socket is closed by peer - "
+ + socket.getLocalAddress().getHostName() + ":" + socket.getLocalPort() + "->"
+ + context.getHostName() + ":" + socket.getPort());
+ }
+
+ int payloadSize = 0;
+ if ("BIN".equals(context.getLlFieldType())) {
+ for (int i = 0; i < context.getLlFieldLength(); i++) {
+ payloadSize += ((int) offsetPlusHeader[context.getLlFieldOffset() + i] & 0xFF)
+ * Math.pow(256, context.getLlFieldLength() - i - 1);
+ }
+ } else {
+ try {
+ byte[] header = new byte[context.getLlFieldLength()];
+ for (int i = 0; i < context.getLlFieldLength(); i++) {
+ header[i] = offsetPlusHeader[context.getLlFieldOffset() + i];
+ }
+ payloadSize = Integer.parseInt(new String(header));
+ } catch (NumberFormatException e) {
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA008");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA008");
+ throw new EAIException("RECEAINNA008", context.getAdapterName() + " ("
+ + context.getLlFieldType() + "," + context.getLlFieldOffset() + ","
+ + context.getLlFieldLength()
+ + ") | when read header, number format is invalid - " + e.getMessage()
+ + " | " + CommonLib.hexDump(offsetPlusHeader, true, context));
+ }
+ }
+
+ if (payloadSize > FixedHeaderDecoder.MAX_PAYLOAD_SIZE) {
+ throw new Exception("max payload size(" + FixedHeaderDecoder.MAX_PAYLOAD_SIZE
+ + ") exceeded : " + payloadSize);
+ }
+
+ /**
+ * ll.field.include = 'Y' - 헤더 길이를 빼 준다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ payloadSize = payloadSize - context.getLlFieldLength(); // -
+ // context.
+ // getLlFieldOffset
+ // ();
+ }
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 더해서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+ payloadSize = payloadSize + context.getLlFieldOffset();
+ }
+
+ /**
+ * ll.field.include = 'Y' - 헤더 길이를 빼 준다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ result.append(offsetPlusHeader);
+ } else {
+ result.append((new ByteMessage(offsetPlusHeader)).getBytes(0, context
+ .getLlFieldOffset()));
+ }
+
+ byte[] remaining = readPayload(is, payloadSize - context.getLlFieldOffset());
+ result.append(remaining);
+
+ ByteMessage full = (new ByteMessage(offsetPlusHeader)).append(remaining);
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | FixedHeaderDecoder(Blocking) | decode : "
+ + full.hexDump());
+ }
+
+ return result.getBytes();
+ }
+
+ private static byte[] readPayload(InputStream in, int total) throws Exception {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ int amt = 0;
+ byte[] buf = new byte[2048];
+ while (amt < total) {
+ int n = in.read(buf, 0, total-amt<2048 ? total-amt : 2048);
+ if (n == -1) {
+ break;
+ }
+ amt += n;
+ bos.write(buf, 0, n);
+ }
+ bos.flush();
+ return bos.toByteArray();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderClient.java
new file mode 100644
index 0000000..5160bb2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderClient.java
@@ -0,0 +1,43 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.ack.AckClientFilter;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.ChunkCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.FixedHeaderCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class FixedHeaderClient extends TcpAdapterClient {
+ public FixedHeaderClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new FixedHeaderHandler(this);
+
+ if ("NONE".equals(context.getLlFieldType())) {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new ChunkCodecFactory(this)));
+ } else {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedHeaderCodecFactory(this)));
+ }
+
+ if ("Y".equals(context.getAckSupport())) {
+ config.getFilterChain().addAfter("codec", "ack", new AckClientFilter(this));
+ }
+ }
+
+ public Object sendMessage(Object message) throws EAIException {
+ if (context.isClient()
+ && "FIXED_LENGTH_HEADER".equals(context.getProtocol())
+ && context.isSync()
+ && !context.isPermanent()
+ && context.isBlocking()) {
+ try {
+ return FixedHeaderBlockingHandler.sendMessage(this, message);
+ } catch(Exception e) {
+ throw new EAIException(e);
+ }
+ } else {
+ return super.sendMessage(message);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderHandler.java
new file mode 100644
index 0000000..45b96cd
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class FixedHeaderHandler extends ProtocolHandler {
+ public FixedHeaderHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderServer.java
new file mode 100644
index 0000000..e4aa47e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/FixedHeaderServer.java
@@ -0,0 +1,26 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.ack.AckServerFilter;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.ChunkCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.FixedHeaderCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class FixedHeaderServer extends TcpAdapterServer {
+ public FixedHeaderServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new FixedHeaderHandler(this);
+
+ if ("NONE".equals(context.getLlFieldType())) {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new ChunkCodecFactory(this)));
+ } else {
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedHeaderCodecFactory(this)));
+ }
+
+ if ("Y".equals(context.getAckSupport())) {
+ config.getFilterChain().addAfter("codec", "ack", new AckServerFilter(this));
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckClientFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckClientFilter.java
new file mode 100644
index 0000000..ff29588
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckClientFilter.java
@@ -0,0 +1,81 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.ack;
+
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+
+public class AckClientFilter extends AckFilter {
+ public AckClientFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+// WriteFuture future = session.write(new ByteMessage(context.getResponseType()));
+ session.write(new ByteMessage(context.getResponseType()));
+ //future.join(context.getTimeout() * 1000L);
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | AckClientFilter | " + context.getResponseType());
+ }
+
+ filterState.state = State.STATE_HANDSHAKE_CLIENT_WAIT_HELLO_ACK;
+ setSessionState(session, filterState.state.toString());
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ ByteMessage m = (ByteMessage) message;
+
+ switch (filterState.state) {
+ case STATE_HANDSHAKE_CLIENT_WAIT_HELLO_ACK:
+ if (!"ACK".equals(m.getString())) {
+ throw new Exception("expected 'ACK' when handshaking, but received : " + m.getString());
+ }
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | AckClientFilter | HELLO ACK : " + m.hexDump());
+ }
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ break;
+
+ case STATE_WAIT_ACK:
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | AckClientFilter | ACK : " + m);
+ }
+ if (!"ACK".equals(m.getString())) {
+ throw new Exception("expected 'ACK', but encounterred : " + m.getString());
+ }
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_SEND_ACK:
+ case STATE_MESSAGE:
+ ///*
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | AckClientFilter | : " + m.hexDump());
+ }
+ //*/
+ sendAckMessage(session);
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+ nextFilter.messageReceived(session, message);
+ break;
+
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + m);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckFilter.java
new file mode 100644
index 0000000..02cf795
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckFilter.java
@@ -0,0 +1,104 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.ack;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+
+
+abstract public class AckFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ protected static final String FILTER_STATE_KEY = AckFilter.class.getName() + ".STATE";
+ protected static final String SESSION_STATE = "SESSION_STATE";
+
+ protected static enum State {
+ STATE_HANDSHAKE_SERVER_WAIT_HELLO,
+ STATE_HANDSHAKE_CLIENT_WAIT_HELLO_ACK,
+ STATE_WAIT_ACK,
+ STATE_SEND_ACK,
+ STATE_MESSAGE;
+ }
+
+ protected static class FilterState {
+ public State state = null;
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ public AckFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
+ if (parent.contains(AckFilter.class)) {
+ throw new IllegalStateException("A filter chain cannot contain more than one AckFilter.");
+ }
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+ }
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ }
+
+ @Override
+ public void messageSent(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ ByteMessage m = null;
+
+ if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ if (filterState.state == State.STATE_MESSAGE && m.size() != 3 && !"ACK".equals(m.getString())) {
+ filterState.state = State.STATE_WAIT_ACK;
+ setSessionState(session, filterState.state.toString());
+ }
+ }
+
+ protected void sendAckMessage(IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | ACK ");
+ }
+
+ filterState.state = State.STATE_SEND_ACK;
+ setSessionState(session, filterState.state.toString());
+
+// WriteFuture future = session.write("ACK");
+ session.write("ACK");
+ //future.join(context.getTimeout() * 1000L);
+ }
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckServerFilter.java
new file mode 100644
index 0000000..0af7977
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/ack/AckServerFilter.java
@@ -0,0 +1,81 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.ack;
+
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+
+public class AckServerFilter extends AckFilter {
+ public AckServerFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ filterState.state = State.STATE_HANDSHAKE_SERVER_WAIT_HELLO;
+ setSessionState(session, filterState.state.toString());
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ ByteMessage m = (ByteMessage) message;
+
+ switch (filterState.state) {
+ case STATE_HANDSHAKE_SERVER_WAIT_HELLO:
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | AckServerFilter | HELLO : " + m);
+ }
+ if (m.getString().equals(context.getResponseType())) {
+ sendAckMessage(session);
+ } else {
+// WriteFuture future = session.write(new ByteMessage("NACK PROTOCOL VIOLATION"));
+ session.write(new ByteMessage("NACK PROTOCOL VIOLATION"));
+ //future.join(context.getTimeout() * 1000L);
+ adapter.getSessionPool().remove(session);
+ session.close();
+ throw new Exception("invalid handshake message. close connection");
+ }
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_WAIT_ACK:
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | AckServerFilter | ACK : " + m);
+ }
+ if (!"ACK".equals(m.getString())) {
+ throw new Exception("expected 'ACK', but encounterred : " + m.getString());
+ }
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_SEND_ACK:
+ case STATE_MESSAGE:
+ ///*
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | AckServerFilter | : " + m.hexDump());
+ }
+ //*/
+ sendAckMessage(session);
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+ nextFilter.messageReceived(session, message);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + m);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkCodecFactory.java
new file mode 100644
index 0000000..e28d82b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkCodecFactory.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class ChunkCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+ public ChunkCodecFactory(ISocketAdapter adapter) {
+ encoder = new ChunkEncoder(adapter);
+ decoder = new ChunkDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkDecoder.java
new file mode 100644
index 0000000..0758ab9
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkDecoder.java
@@ -0,0 +1,76 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+public class ChunkDecoder extends ProtocolDecoderAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ public static final int MAX_PAYLOAD_SIZE = 25 * 1024 * 1024; // 25MB
+
+ private static final String DECODER_STATE_KEY = ChunkDecoder.class.getName() + ".STATE";
+
+ private static class CodecState {
+ ByteBuffer buffer = ByteBuffer.allocate(0).setAutoExpand(true);
+ //int payloadSize;
+ }
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public ChunkDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | ChunkDecoder | decode : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "ChunkDecoder | decode : " + CommonLib.hexDump(in, context));
+ }
+
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(context.getRecvPayloadLength());
+ //codecState.payloadSize = context.getPayloadLength();
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ codecState.buffer.limit(in.position());
+ codecState.buffer.put(in);
+
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0);
+ codecState.buffer.get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkEncoder.java
new file mode 100644
index 0000000..371b8e5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/ChunkEncoder.java
@@ -0,0 +1,63 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class ChunkEncoder implements ProtocolEncoder {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public ChunkEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ ByteBuffer buffer = ByteBuffer.allocate(m.size()).limit(m.size());
+ buffer.put(m.getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | ChunkEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "ChunkEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderCodecFactory.java
new file mode 100644
index 0000000..4a89e28
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderCodecFactory.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class FixedHeaderCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+ public FixedHeaderCodecFactory(ISocketAdapter adapter) {
+ encoder = new FixedHeaderEncoder(adapter);
+ decoder = new FixedHeaderDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderDecoder.java
new file mode 100644
index 0000000..029490c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderDecoder.java
@@ -0,0 +1,287 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.codec;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+public class FixedHeaderDecoder extends ProtocolDecoderAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ public static final int MAX_PAYLOAD_SIZE = 25 * 1024 * 1024; // 25MB
+
+ private static final String DECODER_STATE_KEY = FixedHeaderDecoder.class.getName() + ".STATE";
+
+ private static enum State {
+ STATE_HEADER_READ, STATE_PAYLOAD_READ;
+ }
+
+ private static class CodecState {
+ State state = State.STATE_HEADER_READ;
+ ByteBuffer buffer = ByteBuffer.allocate(0).setAutoExpand(true);
+ int payloadSize;
+ }
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public FixedHeaderDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @SuppressWarnings("static-access")
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(context.getLlFieldOffset() + context.getLlFieldLength());
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("FixedHeaderDecoder");
+ //sb.append(codecState.state);
+ if (codecState.state == State.STATE_PAYLOAD_READ) {
+ sb.append("(" + codecState.payloadSize + ")");
+ }
+ sb.append(" | decode : " + CommonLib.hexDump(in, context));
+ logger.debug(sb.toString());
+ adapter.addRecentRecvTrace(session, sb.toString());
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+ /**
+ * payload size < 0 인 경우
+ */
+ if (codecState.payloadSize < 0) {
+ throw new EAIException("RECEAINNA008", context.getAdapterName() +
+ " (" + context.getLlFieldType() + "," + context.getLlFieldOffset() + "," + context.getLlFieldLength() +
+ ") | when read header, ll length field is invalid | " + CommonLib.hexDump(codecState.buffer, context));
+ /**
+ * payload size == 0 인 경우
+ */
+ } else if (codecState.payloadSize == 0) {
+ if (context.isSync()) {
+ throw new Exception(" payload size 0 (ping). 'SYNC' response type socket does not support ping(size 0) message.");
+ }
+
+ //codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_INFO ) {
+ logger.info(context.getAdapterName() + " | payload size 0 (ping) -> ignore. - " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "payload size 0 (ping) -> ignore. - " + CommonLib.hexDump(in, context));
+ }
+
+ /**
+ * header 값을 읽은 후 buffer의 position을 이동해 준다.
+ * 이 작업을 안해주면 무한루프에 빠질 수 있다.
+ * 예) 법원 공탁금 (_LAW_IN_SOC_AsS{...})
+ */
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength());
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ break;
+ }
+
+ /**
+ * ll.include = 'Y' - LL을 포함해서 넘긴다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ try {
+ codecState.buffer.position(context.getLlFieldOffset() + context.getLlFieldLength())
+ .limit(codecState.payloadSize + context.getLlFieldLength());
+ } catch(IllegalArgumentException e) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(context.getAdapterName() + " | error when handling buffer | ");
+ sb.append("offset=" + context.getLlFieldOffset() + context.getLlFieldLength());
+ sb.append(", limit=" + codecState.payloadSize + context.getLlFieldLength());
+ logger.error(sb.toString());
+ errLogger.error(sb.toString());
+ adapter.addRecentError(sb.toString());
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA007");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA007");
+ throw e;
+ }
+ /**
+ * ll.include = 'N' - LL을 제외하고 넘긴다.
+ */
+ } else {
+ try {
+ codecState.buffer.position(context.getLlFieldOffset()).limit(codecState.payloadSize);
+ } catch(IllegalArgumentException e) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(context.getAdapterName() + " | error when handling buffer | ");
+ sb.append("offset=" + context.getLlFieldOffset());
+ sb.append(", limit=" + codecState.payloadSize);
+ logger.error(sb.toString());
+ errLogger.error(sb.toString());
+ adapter.addRecentError(sb.toString());
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA007");
+ throw e;
+ }
+ }
+
+ /**
+ * offset + ll 을 읽었고, 더 이상 읽을 것(payload)이 없는 경우
+ * - ll.length value = ll.offset + ll.field.length
+ */
+ if (codecState.buffer.position() == codecState.buffer.limit()) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0);
+ codecState.buffer.get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength());
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ break;
+ }
+
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0);
+ codecState.buffer.get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(context.getLlFieldOffset() + context.getLlFieldLength());
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+
+ break;
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | read header : " + in);
+ }
+ */
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ if ("BIN".equals(context.getLlFieldType())) {
+ codecState.payloadSize = 0;
+ for (int i=0; i MAX_PAYLOAD_SIZE) {
+ throw new Exception("max payload size(" + MAX_PAYLOAD_SIZE + ") exceeded : " +
+ codecState.payloadSize + " | " +
+ CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ /**
+ * ll.field.include = 'Y' - 헤더 길이를 빼 준다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ codecState.payloadSize = codecState.payloadSize - context.getLlFieldLength();
+ }
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 더해서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+ codecState.payloadSize = codecState.payloadSize + context.getLlFieldOffset();
+ }
+
+ /**
+ * ll.length.adjust = 200 - 공통부 header 길이를 더한다. (한은망 평문 테스트용)
+ */
+ if (context.getLlLenAdjust() != 0) {
+ codecState.payloadSize = codecState.payloadSize + context.getLlLenAdjust();
+ }
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ /*
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | read payload : " + in);
+ }
+ */
+
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderEncoder.java
new file mode 100644
index 0000000..d618be0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedheader/codec/FixedHeaderEncoder.java
@@ -0,0 +1,123 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedheader.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class FixedHeaderEncoder implements ProtocolEncoder {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public FixedHeaderEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ /**
+ * ll.include = 'Y' - 통째로 보낸다.
+ */
+ if ("Y".equals(context.getLlInclude())) {
+ ByteBuffer buffer = ByteBuffer.allocate(m.size() - context.getLlFieldLength());
+ buffer.put(m.getBytes(0, context.getLlFieldOffset()));
+ buffer.put(m.getBytes(context.getLlFieldOffset() + context.getLlFieldLength()));
+ buffer.flip();
+ m.setByteBuffer(buffer);
+ }
+
+ int length = m.size();
+ ByteBuffer buffer = ByteBuffer.allocate(context.getLlFieldLength() + length).limit(context.getLlFieldLength() + length);
+
+ /**
+ * ll.field.include = 'Y' - header 길이 포함하여 ll 을 계산한다.
+ */
+ if ("Y".equals(context.getLlFieldInclude())) {
+ length = length + context.getLlFieldLength();
+ }
+
+ /**
+ * ll.offset.exclude = 'Y' - offset 만큼의 크기를 빼서 length를 계산한다.
+ */
+ if ("Y".equals(context.getLlOffsetExclude())) {
+ length = length - context.getLlFieldOffset();
+ }
+
+ /**
+ * ll.length.adjust = 200 - 공통부 header 길이를 더한다. (한은망 평문 테스트용)
+ */
+ if (context.getLlLenAdjust() != 0) {
+ length = length + context.getLlLenAdjust();
+ }
+ /**
+ * [1] before-payload
+ */
+ buffer.put(m.getBytes(0, context.getLlFieldOffset()));
+
+ /**
+ * [2] write header
+ */
+ if ("BIN".equals(context.getLlFieldType())) {
+ int tmpLength = length;
+ byte[] header = new byte[context.getLlFieldLength()];
+ for (int i = context.getLlFieldLength()-1; i>=0; i--) {
+ header[i] = (byte) (tmpLength % 256);
+ tmpLength = tmpLength / 256;
+ }
+ buffer.put(header);
+ } else { // "CHAR"
+ String lenStr = CommonLib.getFormatString(length, context.getLlFieldLength());
+ buffer.put(lenStr.getBytes());
+ }
+
+ /**
+ * [3] after-payload
+ */
+ buffer.put(m.getBytes(context.getLlFieldOffset(), m.getBytes().length - context.getLlFieldOffset()));
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ String dump = CommonLib.hexDump(buffer, context);
+ if(logger.isDebugEnabled()) {
+ logger.debug(context.getAdapterName() + " | FixedHeaderEncoder | encode : " + dump);
+ }
+ adapter.addRecentSendTrace(session, "FixedHeaderEncoder | encode : " + dump);
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ out.flush();
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadClient.java
new file mode 100644
index 0000000..a0cfa27
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadClient.java
@@ -0,0 +1,27 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedpayload;
+
+import com.eactive.eai.adapter.EAIException;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.fixedpayload.codec.FixedPayloadCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.fixedpayload.handshake.IgnoreFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class FixedPayloadClient extends TcpAdapterClient {
+ public FixedPayloadClient(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new FixedPayloadHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedPayloadCodecFactory(this)));
+
+ /**
+ * ignore PING(ACK) message
+ */
+ config.getFilterChain().addAfter("codec", "ignore", new IgnoreFilter(this));
+ }
+
+ @Override
+ public Object sendMessage(Object message) throws EAIException {
+ return super.sendMessage(message);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadHandler.java
new file mode 100644
index 0000000..1f37452
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadHandler.java
@@ -0,0 +1,10 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedpayload;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class FixedPayloadHandler extends ProtocolHandler {
+ public FixedPayloadHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadServer.java
new file mode 100644
index 0000000..2fbdc55
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/FixedPayloadServer.java
@@ -0,0 +1,21 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedpayload;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.fixedpayload.codec.FixedPayloadCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.fixedpayload.handshake.IgnoreFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class FixedPayloadServer extends TcpAdapterServer {
+ public FixedPayloadServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new FixedPayloadHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedPayloadCodecFactory(this)));
+
+ /**
+ * ignore PING(ACK) message
+ */
+ config.getFilterChain().addAfter("codec", "ignore", new IgnoreFilter(this));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadCodecFactory.java
new file mode 100644
index 0000000..59bdcb6
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadCodecFactory.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedpayload.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+public class FixedPayloadCodecFactory implements ProtocolCodecFactory {
+ private ProtocolEncoder encoder;
+ private ProtocolDecoder decoder;
+
+ public FixedPayloadCodecFactory(ISocketAdapter adapter) {
+ encoder = new FixedPayloadEncoder(adapter);
+ decoder = new FixedPayloadDecoder(adapter);
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ return decoder;
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return encoder;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadDecoder.java
new file mode 100644
index 0000000..7d59d4f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadDecoder.java
@@ -0,0 +1,157 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedpayload.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+public class FixedPayloadDecoder extends ProtocolDecoderAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ public static final int MAX_PAYLOAD_SIZE = 25 * 1024 * 1024; // 25MB
+
+ private static final String DECODER_STATE_KEY = FixedPayloadDecoder.class.getName() + ".STATE";
+ private static final String N_DECODER_STATE_KEY = "N" + FixedPayloadDecoder.class.getName() + ".STATE";
+
+ private static class CodecState {
+ ByteBuffer buffer = ByteBuffer.allocate(0).setAutoExpand(true);
+ int payloadSize;
+ boolean beforeFirst = true;
+ }
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public FixedPayloadDecoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | FixedPayloadDecoder | decode : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "FixedPayloadDecoder | decode : " + CommonLib.hexDump(in, context));
+ }
+
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+
+ if ( (codecState == null) && (context.getRecvPayloadLength() > 0) ) {
+ codecState = new CodecState();
+ codecState.buffer.limit(context.getRecvPayloadLength());
+ //codecState.payloadSize = context.getPayloadLength();
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ /**
+ * undefined recvPayloadLength; it must negative value
+ */
+ if (context.getRecvPayloadLength() < 0) {
+ codecState = (CodecState) session.getAttribute(N_DECODER_STATE_KEY);
+
+ if (codecState == null) {
+ codecState = new CodecState();
+ }
+
+ if (codecState.beforeFirst) {
+ byte[] hdr = new byte[49];
+ in.position(0);
+ in.get(hdr);
+ ByteMessage bm = new ByteMessage(hdr);
+ String trCd = new String(bm.getBytes(3, 6));
+ int cnt = Integer.parseInt(new String(bm.getBytes(47, 2)));
+
+ int recvPayloadLength = 49;
+ if ("210905".equals(trCd) || "611204".equals(trCd)) { // 증권수탁배치|펀드원장정보
+ recvPayloadLength = 49 + (1200 + 8) * cnt;
+// context.setRecvPayloadLength(recvPayloadLength);
+ codecState.buffer.limit(recvPayloadLength);
+ } else if ("611202".equals(trCd)) {
+ recvPayloadLength = 49 + (1100 + 8) * cnt;
+// context.setRecvPayloadLength(recvPayloadLength);
+ codecState.buffer.limit(recvPayloadLength);
+ } else { // 개시 및 종료 전문 등이 올수 있슴, Transaction Code 관계없이 49bytes
+// context.setRecvPayloadLength(49);
+ codecState.buffer.limit(recvPayloadLength);
+ }
+
+ in.position(0);
+ codecState.payloadSize = recvPayloadLength;
+ session.setAttribute(N_DECODER_STATE_KEY, codecState);
+ }
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0);
+ codecState.buffer.get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ if (context.getRecvPayloadLength() < 0) {
+ codecState.buffer.position(0).limit(codecState.payloadSize);
+ } else {
+ codecState.buffer.position(0).limit(context.getRecvPayloadLength());
+ }
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ }
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ /**
+ * send size 만큼 와도 message를 생성해서 넘긴다.
+ * SA 또는 SN 으로 시작하는 PING(ACK) 전문이 올 수 있다고 한다.
+ * concern undefined payload length; negative value
+ */
+ if ((context.getSendPayloadLength() > 0)
+ && (context.getSendPayloadLength() < context.getRecvPayloadLength())) {
+
+ if (codecState.buffer.position() + in.remaining() == context.getSendPayloadLength()) {
+ codecState.buffer.limit(context.getSendPayloadLength());
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+ return true;
+ }
+ }
+
+ /**
+ * 읽으려는 size 만큼 아직 data가 오지 못했다.
+ */
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ codecState.beforeFirst = false;
+ return false;
+ }
+
+ /**
+ * 읽으려는 size 에 도달했다.
+ */
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ codecState.beforeFirst = true;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadEncoder.java
new file mode 100644
index 0000000..1631813
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/codec/FixedPayloadEncoder.java
@@ -0,0 +1,70 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedpayload.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class FixedPayloadEncoder implements ProtocolEncoder {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public FixedPayloadEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ int length = context.getSendPayloadLength();
+
+ /**
+ * undefined sendPayloadLength; it must negative value
+ */
+ if (length < 0)
+ length = m.size();
+
+ ByteBuffer buffer = ByteBuffer.allocate(length).limit(length);
+ buffer.put(m.padding(length, (byte) 0x00).getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | FixedPayloadEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "FixedPayloadEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/handshake/IgnoreFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/handshake/IgnoreFilter.java
new file mode 100644
index 0000000..caa7e7d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/fixedpayload/handshake/IgnoreFilter.java
@@ -0,0 +1,53 @@
+package com.eactive.eai.adapter.socket2.protocol.fixedpayload.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+
+public class IgnoreFilter extends IoFilterAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+
+ public IgnoreFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ //KB Case - CMBS_OU_NET_SyC{KOREA} adapter group의 경우 만 적용
+ ByteMessage m = (ByteMessage) message;
+
+ if ( (m.size() >= 2) && (m.getByte(0) == 'S') && (m.getByte(1) == 'A')
+ && "CMBS_OU_NET_SyC{KOREA}".equals(context.getAdapterGroupName()) ) {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | IgnoreFilter - ignore : " + m.hexDump());
+ adapter.addRecentRecvTrace(session, "IgnoreFilter - ignore : " + m.hexDump());
+ }
+ return;
+ }
+
+ // 증권투자수탁 HEADER Check, it must start 'N'
+ if ( (context.getRecvPayloadLength() < 0) && (m.getByte(0) != 'N') ) {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | IgnoreFilter - ignore, HEADER must start 'N' : " + m.hexDump());
+ adapter.addRecentRecvTrace(session, "IgnoreFilter - ignore, HEADER must start 'N' : " + m.hexDump());
+ }
+ return;
+ }
+
+ nextFilter.messageReceived(session, message);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpHandler.java
new file mode 100644
index 0000000..6db6d04
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpHandler.java
@@ -0,0 +1,117 @@
+package com.eactive.eai.adapter.socket2.protocol.http;
+
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.SessionLog;
+
+import java.util.Hashtable;
+
+public class HttpHandler extends ProtocolHandler {
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_");
+
+ static String[] servletList = {
+ "adapters", "com.eactive.eai.adapter.socket2.protocol.http.servlet.AdaptersServlet",
+ "adaptersJson", "com.eactive.eai.adapter.socket2.protocol.http.servlet.AdaptersJsonServlet",
+ "adapter", "com.eactive.eai.adapter.socket2.protocol.http.servlet.AdapterServlet",
+ "adapterJson", "com.eactive.eai.adapter.socket2.protocol.http.servlet.AdapterJsonServlet",
+ "adapterInternal", "com.eactive.eai.adapter.socket2.protocol.http.servlet.AdapterInternalServlet",
+ "check", "com.eactive.eai.adapter.socket2.protocol.http.servlet.CheckServlet",
+ "thread", "com.eactive.eai.adapter.socket2.protocol.http.servlet.ThreadServlet",
+ "memory", "com.eactive.eai.adapter.socket2.protocol.http.servlet.MemoryServlet",
+ "error", "com.eactive.eai.adapter.socket2.protocol.http.servlet.ErrorServlet",
+ "file", "com.eactive.eai.adapter.socket2.protocol.http.servlet.FileServlet",
+ "prop", "com.eactive.eai.adapter.socket2.protocol.http.servlet.PropServlet",
+ "groovy", "com.eactive.eai.adapter.socket2.protocol.http.servlet.GroovyServlet",
+ "transformer", "com.eactive.eai.transformer.servlet.TransformerServlet",
+ "message", "com.eactive.eai.transformer.servlet.LayoutServlet",
+ "layout", "com.eactive.eai.transformer.servlet.LayoutServlet",
+ "transform", "com.eactive.eai.transformer.servlet.TransformServlet",
+ "function", "com.eactive.eai.transformer.servlet.FunctionServlet",
+ "service", "com.eactive.eai.transformer.servlet.ServiceServlet",
+ "bizkey", "com.eactive.eai.transformer.servlet.BizKeyServlet",
+ "control", "com.eactive.eai.adapter.socket2.protocol.http.servlet.ControlServlet",
+ "http", "com.eactive.eai.adapter.http.servlet.HttpAdapterLogServlet",
+ "zombies", "com.eactive.eai.adapter.socket2.protocol.http.servlet.ZombieAdaptersServlet",
+ "token", "com.openbanking.eai.common.token.servlet.AccessTokenServlet",
+ "rolling", "com.eactive.kakao.rolling.servlet.RollingServlet"
+ };
+
+ Hashtable map = new Hashtable();
+
+
+ public HttpHandler(ISocketAdapter adapter) {
+ super(adapter);
+
+ for (int i=0; i= context.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | audit - " + session + " - " + request.getURI());
+ }
+
+ /**
+ * sevlet
+ */
+ try {
+ String servletName = "error";
+ if (!"".equals(request.getContext())) {
+ servletName = request.getContext();
+ }
+ if (servletName.indexOf('/') != -1) {
+ servletName = servletName.substring(0, servletName.indexOf('/'));
+ }
+
+ HttpServlet servlet = (HttpServlet) map.get(servletName);
+ if (servlet == null) {
+ if (!servletName.endsWith(".ico"))
+ logger.warn("404 - > " + servletName);
+ response.setResponseCode(404);
+ } else {
+ servlet.service(request, response);
+ }
+ } catch(Exception e) {
+ response.appendBody("");
+ response.appendBody(ExceptionStackTrace.dump(e));
+ response.appendBody(" ");
+ }
+
+ session.write(response).join();
+ }
+
+ @Override
+ public void sessionIdle(IoSession session, IdleStatus status) {
+ SessionLog.info(session, context.getAdapterName() + " | session idle -> disconnect");
+ sessionPool.remove(session);
+ session.close();
+ }
+
+ @Override
+ public void exceptionCaught(IoSession session, Throwable cause) {
+ sessionPool.remove(session);
+ session.close();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpServer.java
new file mode 100644
index 0000000..8b94843
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpServer.java
@@ -0,0 +1,15 @@
+package com.eactive.eai.adapter.socket2.protocol.http;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class HttpServer extends TcpAdapterServer {
+ public HttpServer(SocketAdapterContext context) throws Exception {
+ super(context);
+ this.handler = new HttpHandler(this);
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new HttpProtocolCodecFactory(context)));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpServlet.java
new file mode 100644
index 0000000..9cf5336
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/HttpServlet.java
@@ -0,0 +1,13 @@
+package com.eactive.eai.adapter.socket2.protocol.http;
+
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+
+abstract public class HttpServlet {
+
+ public void service(HttpRequest request, HttpResponse response) throws Exception {
+ doService(request, response);
+ }
+
+ abstract protected void doService(HttpRequest request, HttpResponse response) throws Exception;
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/Server.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/Server.java
new file mode 100644
index 0000000..d093d96
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/Server.java
@@ -0,0 +1,51 @@
+package com.eactive.eai.adapter.socket2.protocol.http;
+
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpProtocolCodecFactory;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.filter.LoggingFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.transport.socket.nio.SocketAcceptor;
+import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
+
+import java.net.InetSocketAddress;
+
+
+public class Server {
+ /** Default HTTP port */
+ private static final int DEFAULT_PORT = 8080;
+
+ /** Tile server revision number */
+ public static final String VERSION_STRING = "";
+
+ public static void main(String[] args) {
+ int port = DEFAULT_PORT;
+
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equals("-port")) {
+ port = Integer.parseInt(args[i + 1]);
+ }
+ }
+
+ try {
+ // Create an acceptor
+ IoAcceptor acceptor = new SocketAcceptor();
+
+ // Create a service configuration
+ SocketAcceptorConfig cfg = new SocketAcceptorConfig();
+ cfg.setReuseAddress(true);
+ cfg.getFilterChain().addLast(
+ "protocolFilter",
+ new ProtocolCodecFilter(
+ new HttpProtocolCodecFactory(null)));
+ cfg.getFilterChain().addLast("logger", new LoggingFilter());
+
+ acceptor
+ .bind(new InetSocketAddress(port), new ServerHandler(), cfg);
+
+ System.out.println("Server now listening on port " + port);
+ } catch (Exception ex) {
+// ex.printStackTrace();
+ System.out.println("Error" + ex.toString());
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/ServerHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/ServerHandler.java
new file mode 100644
index 0000000..8fb9b74
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/ServerHandler.java
@@ -0,0 +1,40 @@
+package com.eactive.eai.adapter.socket2.protocol.http;
+
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.SessionLog;
+
+
+public class ServerHandler extends IoHandlerAdapter {
+ @Override
+ public void sessionOpened(IoSession session) {
+ // set idle time to 60 seconds
+ session.setIdleTime(IdleStatus.BOTH_IDLE, 60);
+ }
+
+ @Override
+ public void messageReceived(IoSession session, Object message) {
+ // Check that we can service the request context
+ HttpResponse response = new HttpResponse();
+ response.setContentType("text/plain");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody("CONNECTED");
+
+ if (response != null) {
+ session.write(response).join();
+ }
+ }
+
+ @Override
+ public void sessionIdle(IoSession session, IdleStatus status) {
+ SessionLog.info(session, "Disconnecting the idle.");
+ session.close();
+ }
+
+ @Override
+ public void exceptionCaught(IoSession session, Throwable cause) {
+ session.close();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpProtocolCodecFactory.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpProtocolCodecFactory.java
new file mode 100644
index 0000000..7c2ebf7
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpProtocolCodecFactory.java
@@ -0,0 +1,12 @@
+package com.eactive.eai.adapter.socket2.protocol.http.codec;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory;
+
+
+public class HttpProtocolCodecFactory extends DemuxingProtocolCodecFactory {
+ public HttpProtocolCodecFactory(SocketAdapterContext context) {
+ super.register(HttpRequestDecoder.class);
+ super.register(HttpResponseEncoder.class);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpRequest.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpRequest.java
new file mode 100644
index 0000000..d43ca66
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpRequest.java
@@ -0,0 +1,77 @@
+package com.eactive.eai.adapter.socket2.protocol.http.codec;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.mina.common.IoSession;
+
+
+public class HttpRequest {
+ private Map headers = null;
+ private IoSession session = null;
+
+ public void setHeaders(Map headers) {
+ this.headers = headers;
+ }
+
+ public Map getHeaders() {
+ return headers;
+ }
+
+ public String getURI() {
+ String[] uris = (String[]) headers.get("URI");
+ return uris == null ? "" : uris[0];
+ }
+
+ public String getContext() {
+ String[] context = (String[]) headers.get("Context");
+ return context == null ? "" : context[0];
+ }
+
+ public String getParameter(String name) {
+ String[] param = (String[]) headers.get("@".concat(name));
+ return param == null ? "" : param[0];
+ }
+
+ public String[] getParameters(String name) {
+ String[] param = (String[]) headers.get("@".concat(name));
+ return param == null ? new String[] {} : param;
+ }
+
+ public String[] getHeader(String name) {
+ return (String[]) headers.get(name);
+ }
+
+ public void setSession(IoSession session) {
+ this.session = session;
+ }
+
+ public IoSession getSession() {
+ return session;
+ }
+
+ public String toString() {
+ StringBuilder str = new StringBuilder();
+
+ Iterator it = headers.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry e = (Entry) it.next();
+ str.append(e.getKey() + " : "
+ + arrayToString((String[]) e.getValue(), ',') + "\n");
+ }
+ return str.toString();
+ }
+
+ public static String arrayToString(String[] s, char sep) {
+ if (s == null || s.length == 0)
+ return "";
+ StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < s.length; i++) {
+ if (i > 0)
+ buf.append(sep);
+ buf.append(s[i]);
+ }
+ return buf.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpRequestDecoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpRequestDecoder.java
new file mode 100644
index 0000000..da6fc1b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpRequestDecoder.java
@@ -0,0 +1,212 @@
+package com.eactive.eai.adapter.socket2.protocol.http.codec;
+
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+import org.apache.mina.filter.codec.demux.MessageDecoderAdapter;
+import org.apache.mina.filter.codec.demux.MessageDecoderResult;
+import org.apache.mina.util.CharsetUtil;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetDecoder;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link org.apache.mina.filter.codec.demux.MessageDecoder} that decodes {@link HttpRequest}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version
+ */
+public class HttpRequestDecoder extends MessageDecoderAdapter {
+ private static final byte[] CONTENT_LENGTH = "Content-Length:".getBytes();
+
+ //private CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
+
+ private CharsetDecoder decoder = CharsetUtil.getDefaultCharset().newDecoder();
+
+ protected final com.eactive.eai.common.util.Logger logger;
+
+ public HttpRequestDecoder() {
+ logger = SocketLoggerManager.getInstance().getLogger();
+ }
+
+ public MessageDecoderResult decodable(IoSession session, ByteBuffer in) {
+ // Return NEED_DATA if the whole header is not read yet.
+ try {
+ return messageComplete(in) ? MessageDecoderResult.OK
+ : MessageDecoderResult.NEED_DATA;
+ } catch (Exception ex) {
+ logger.debug(ex.toString());
+ }
+
+ return MessageDecoderResult.NOT_OK;
+ }
+
+ public MessageDecoderResult decode(IoSession session, ByteBuffer in,
+ ProtocolDecoderOutput out) throws Exception {
+ // Try to decode body
+ HttpRequest m = decodeBody(in);
+
+ // Return NEED_DATA if the body is not fully read.
+ if (m == null)
+ return MessageDecoderResult.NEED_DATA;
+
+ m.setSession(session);
+ out.write(m);
+ return MessageDecoderResult.OK;
+ }
+
+ private boolean messageComplete(ByteBuffer in) throws Exception {
+ int last = in.remaining() - 1;
+ if (in.remaining() < 4)
+ return false;
+
+ // to speed up things we check if the Http request is a GET or POST
+ if (in.get(0) == (byte) 'G' && in.get(1) == (byte) 'E'
+ && in.get(2) == (byte) 'T') {
+ // Http GET request therefore the last 4 bytes should be 0x0D 0x0A 0x0D 0x0A
+ return (in.get(last) == (byte) 0x0A
+ && in.get(last - 1) == (byte) 0x0D
+ && in.get(last - 2) == (byte) 0x0A && in.get(last - 3) == (byte) 0x0D);
+ } else if (in.get(0) == (byte) 'P' && in.get(1) == (byte) 'O'
+ && in.get(2) == (byte) 'S' && in.get(3) == (byte) 'T') {
+ // Http POST request
+ // first the position of the 0x0D 0x0A 0x0D 0x0A bytes
+ int eoh = -1;
+ for (int i = last; i > 2; i--) {
+ if (in.get(i) == (byte) 0x0A && in.get(i - 1) == (byte) 0x0D
+ && in.get(i - 2) == (byte) 0x0A
+ && in.get(i - 3) == (byte) 0x0D) {
+ eoh = i + 1;
+ break;
+ }
+ }
+ if (eoh == -1)
+ return false;
+ for (int i = 0; i < last; i++) {
+ boolean found = false;
+ for (int j = 0; j < CONTENT_LENGTH.length; j++) {
+ if (in.get(i + j) != CONTENT_LENGTH[j]) {
+ found = false;
+ break;
+ }
+ found = true;
+ }
+ if (found) {
+ // retrieve value from this position till next 0x0D 0x0A
+ StringBuilder contentLength = new StringBuilder();
+ for (int j = i + CONTENT_LENGTH.length; j < last; j++) {
+ if (in.get(j) == 0x0D)
+ break;
+ contentLength.append(new String(
+ new byte[] { in.get(j) }));
+ }
+ // if content-length worth of data has been received then the message is complete
+ return (Integer.parseInt(contentLength.toString().trim())
+ + eoh == in.remaining());
+ }
+ }
+ }
+
+ // the message is not complete and we need more data
+ return false;
+ }
+
+ private HttpRequest decodeBody(ByteBuffer in) {
+ HttpRequest request = new HttpRequest();
+ try {
+ request.setHeaders(parseRequest(new StringReader(in
+ .getString(decoder))));
+ return request;
+ } catch (CharacterCodingException ex) {
+ logger.debug(ex.toString());
+ }
+
+ return null;
+ }
+
+ private Map parseRequest(Reader is) {
+ Map map = new HashMap<>();
+ BufferedReader rdr = new BufferedReader(is);
+
+ try {
+ // Get request URL.
+ String line = rdr.readLine();
+ String[] url = line == null?new String[0]:line.split(" ");
+ if (url.length < 3)
+ return map;
+
+ map.put("URI", new String[] { line });
+ if(url[0] != null) map.put("Method", new String[] { url[0].toUpperCase() });
+ if(url[1] != null) map.put("Context", new String[] { url[1].substring(1) });
+ if(url[2] != null) map.put("Protocol", new String[] { url[2] });
+ // Read header
+ while ((line = rdr.readLine()) != null && line.length() > 0) {
+ String[] tokens = line.split(": ");
+ map.put(tokens[0], new String[] { tokens[1] });
+ }
+
+ // If method 'POST' then read Content-Length worth of data
+ if (url[0].equalsIgnoreCase("POST")) {
+ int len = Integer.parseInt(map.get("Content-Length")[0]);
+ if(len >= 0) {
+ char[] buf = new char[len];
+ if (rdr.read(buf) == len) {
+ line = String.copyValueOf(buf);
+ //System.out.println(line);
+ }
+ }
+ } else if (url[0].equalsIgnoreCase("GET")) {
+ int idx = url[1].indexOf('?');
+ if (idx != -1) {
+ map.put("Context",
+ new String[] { url[1].substring(1, idx) });
+ line = url[1].substring(idx + 1);
+ } else {
+ line = null;
+ }
+ }
+
+ if (line != null) {
+ String[] match = line.split("\\&");
+ for (int i = 0; i < match.length; i++) {
+ String[] params = new String[1];
+ String[] tokens = match[i].split("=");
+ switch (tokens.length) {
+ case 0:
+ map.put("@".concat(match[i]), new String[] {});
+ break;
+ case 1:
+ map.put("@".concat(tokens[0]), new String[] {});
+ break;
+ default:
+ String name = "@".concat(tokens[0]);
+ if (map.containsKey(name)) {
+ params = map.get(name);
+ if(params != null) {
+ String[] tmp = new String[params.length + 1];
+ for (int j = 0; j < params.length; j++)
+ tmp[j] = params[j];
+ params = tmp;
+ }
+ }
+ if(params != null) {
+ params[params.length - 1] = tokens[1].trim();
+ map.put(name, params);
+ }
+ }
+ }
+ }
+ } catch (IOException ex) {
+ logger.debug(ex.toString());
+ }
+
+ return map;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpResponse.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpResponse.java
new file mode 100644
index 0000000..84362ed
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpResponse.java
@@ -0,0 +1,83 @@
+package com.eactive.eai.adapter.socket2.protocol.http.codec;
+
+import com.eactive.eai.adapter.socket2.protocol.http.Server;
+import org.apache.mina.common.ByteBuffer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class HttpResponse {
+ /** HTTP response codes */
+ public static final int HTTP_STATUS_SUCCESS = 200;
+
+ public static final int HTTP_STATUS_NOT_FOUND = 404;
+
+ /** Map */
+ private Map headers = new HashMap();
+
+ /** Storage for body of HTTP response. */
+ private ByteArrayOutputStream body = new ByteArrayOutputStream(1024);
+
+ private int responseCode = HTTP_STATUS_SUCCESS;
+
+ public HttpResponse() {
+ headers.put("Server", "HttpServer (" + Server.VERSION_STRING + ')');
+ headers.put("Cache-Control", "private");
+ headers.put("Content-Type", "text/html; charset='UTF-8'");
+ headers.put("Connection", "keep-alive");
+ headers.put("Keep-Alive", "200");
+ headers.put("Date", DateTimeFormatter.ofPattern(
+ "EEE, dd MMM yyyy HH:mm:ss zzz").format(ZonedDateTime.now()));
+ headers.put("Last-Modified", DateTimeFormatter.ofPattern(
+ "EEE, dd MMM yyyy HH:mm:ss zzz").format(ZonedDateTime.now()));
+ }
+
+ public Map getHeaders() {
+ return headers;
+ }
+
+ public void addHeader(String key, String value) {
+ headers.put(key, value);
+ }
+
+ public void setContentType(String contentType) {
+ headers.put("Content-Type", contentType);
+ }
+
+ public void setResponseCode(int responseCode) {
+ this.responseCode = responseCode;
+ }
+
+ public int getResponseCode() {
+ return this.responseCode;
+ }
+
+ public void appendBody(byte[] b) {
+ try {
+ body.write(b);
+ } catch (IOException ex) {
+ System.out.println("appendBody error");
+ }
+ }
+
+ public void appendBody(String s) {
+ try {
+ body.write(s.getBytes());
+ } catch (IOException ex) {
+ System.out.println("appendBody string error");
+ }
+ }
+
+ public ByteBuffer getBody() {
+ return ByteBuffer.wrap(body.toByteArray());
+ }
+
+ public int getBodyLength() {
+ return body.size();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpResponseEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpResponseEncoder.java
new file mode 100644
index 0000000..8132f2a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/codec/HttpResponseEncoder.java
@@ -0,0 +1,78 @@
+package com.eactive.eai.adapter.socket2.protocol.http.codec;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.apache.mina.filter.codec.demux.MessageEncoder;
+import org.apache.mina.util.CharsetUtil;
+
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetEncoder;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class HttpResponseEncoder implements MessageEncoder {
+ private static final Set> TYPES;
+
+ static {
+ Set> types = new HashSet>();
+ types.add(HttpResponse.class);
+ TYPES = Collections.unmodifiableSet(types);
+ }
+
+ private static final byte[] CRLF = new byte[] { 0x0D, 0x0A };
+
+ public HttpResponseEncoder() {
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out)
+ throws Exception {
+ HttpResponse msg = (HttpResponse) message;
+ ByteBuffer buf = ByteBuffer.allocate(256);
+ // Enable auto-expand for easier encoding
+ buf.setAutoExpand(true);
+
+ try {
+ // output all headers except the content length
+ //CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
+ CharsetEncoder encoder = CharsetUtil.getDefaultCharset().newEncoder();
+ buf.putString("HTTP/1.1 ", encoder);
+ buf.putString(String.valueOf(msg.getResponseCode()), encoder);
+ switch (msg.getResponseCode()) {
+ case HttpResponse.HTTP_STATUS_SUCCESS:
+ buf.putString(" OK", encoder);
+ break;
+ case HttpResponse.HTTP_STATUS_NOT_FOUND:
+ buf.putString(" Not Found", encoder);
+ break;
+ }
+ buf.put(CRLF);
+ for (Iterator it = msg.getHeaders().entrySet().iterator(); it.hasNext();) {
+ Entry entry = (Entry) it.next();
+ buf.putString((String) entry.getKey(), encoder);
+ buf.putString(": ", encoder);
+ buf.putString((String) entry.getValue(), encoder);
+ buf.put(CRLF);
+ }
+ // now the content length is the body length
+ buf.putString("Content-Length: ", encoder);
+ buf.putString(String.valueOf(msg.getBodyLength()), encoder);
+ buf.put(CRLF);
+ buf.put(CRLF);
+ // add body
+ buf.put(msg.getBody());
+ } catch (CharacterCodingException ex) {
+ out.flush();
+ }
+
+ buf.flip();
+ out.write(buf);
+ }
+
+ public Set> getMessageTypes() {
+ return TYPES;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterInternalServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterInternalServlet.java
new file mode 100644
index 0000000..09d3861
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterInternalServlet.java
@@ -0,0 +1,927 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Iterator;
+
+public class AdapterInternalServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String command = request.getContext();
+ if (command.lastIndexOf('/') == -1) {
+ command = "";
+ } else {
+ command = command.substring(command.indexOf('/') + 1);
+ }
+
+ String result = "";
+
+ try {
+ if (command == null || "".equals(command) || "show".equals(command)) {
+ result = show(request.getParameter("adapter"));
+ } else if (command.startsWith("traceLevel")) {
+ result = traceLevel(request.getParameter("adapter"), Integer.parseInt(request.getParameter("level")));
+ } else if (command.startsWith("clear")) {
+ result = clear(request.getParameter("adapter"));
+ } else if (command.startsWith("start")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | start - " + request.getSession());
+ result = start(adapterName);
+ } else if (command.startsWith("stopforcely")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
+ result = stop(adapterName, true);
+ } else if (command.startsWith("stop")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
+ result = stop(adapterName, false);
+ } else if (command.startsWith("error")) {
+ result = error(request.getParameter("adapter"));
+ } else if (command.startsWith("sendRecv")) {
+ result = sendRecv(request.getParameter("adapter"));
+ } else if (command.startsWith("removeSession")) {
+ result = removeSession(request.getParameter("adapter"), request.getParameter("localPort"),
+ request.getParameter("remotePort"));
+ } else if (command.startsWith("sessionValidate")) {
+ result = sessionValidate(request.getParameter("adapter"));
+ } else {
+ response.setResponseCode(404);
+ return;
+ }
+ } catch (Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ response.setContentType("text/html;charset=utf-8;");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+ }
+
+ private String show(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ sb.append(adapterName);
+
+ if (adapter == null) {
+ sb.append(" Not found adapter (" + adapterName + ") ");
+ return sb.toString();
+ }
+ /**
+ * status
+ */
+ if ("STARTED".equals(adapter.getState().name())) {
+ sb.append(" (" + adapter.getState().name() + ")");
+ } else {
+ sb.append(" (" + adapter.getState().name() + ") ");
+ }
+
+ sb.append(" uptime:" + TimeUtil.formatDate(adapter.getUptime().getTime()));
+ sb.append(", pool:" + adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
+ sb.append(", recv:" + adapter.getMessageRecv());
+ sb.append(", send:" + adapter.getMessageSend());
+ if (adapter.getRecentErrorCount() > 0) {
+ sb.append(", ");
+ sb.append("");
+ sb.append("error:" + adapter.getRecentErrorCount());
+ sb.append(" ");
+ } else {
+ sb.append(", error:" + adapter.getRecentErrorCount());
+ }
+
+ // sb.append(", (clear )");
+
+ // sb.append(" (start ");
+ // sb.append("|stop )");
+
+ if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
+ sb.append("\n " + adapter.getContext().getDescription() + "\n");
+ }
+
+ sb.append("\n\n");
+
+ /**
+ * common info
+ */
+ sb.append(String.format("%4s %-30s : %s\n", "", "host.name", adapter.getContext().getHostName()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "port.number", adapter.getContext().getPortNumber()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "local.host.name", adapter.getContext().getLocalHostName()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "local.port.number", adapter.getContext().getLocalPortNumber()));
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "protocol", adapter.getContext().getProtocol()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "bound.usage", adapter.getContext().getBoundUsage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "socket.type", adapter.getContext().getSocketType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "response.type", adapter.getContext().getResponseType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ack.support", adapter.getContext().getAckSupport()));
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "permanent", adapter.getContext().getPermanent()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "blocking(NIO, BIO)", adapter.getContext().getBlocking()));
+ sb.append(String.format("%4s %-30s : %s (sec)\n", "", "timeout", adapter.getContext().getTimeout()));
+ sb.append(String.format("%4s %-30s : %s (sec)\n", "", "idle.timeout", adapter.getContext().getIdleTimeout()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "socket.reuse", adapter.getContext().getSocketReuse()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "business.work.class.code",
+ adapter.getContext().getBwkClsCd()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "max.connection",
+ (adapter.getContext().getCloseExistingConnection() ? "-" : "")
+ + adapter.getContext().getMaxConnection()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "connection.limit.per.ip",
+ adapter.getContext().getConnLimitPerIp()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "max.thread", adapter.getContext().getMaxThread()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "validation.rule", adapter.getContext().getValidationRule()));
+ sb.append(
+ String.format("%4s %-30s : %s\n\n", "", "datacontrol.rule", adapter.getContext().getDataControlRule()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "acl.list", adapter.getContext().getAclList()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "block.ip.list", adapter.getContext().getBlockIpList()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "l4.skip.ip.list", adapter.getContext().getL4SkipIpList()));
+
+ sb.append(
+ String.format("%4s %-30s : %s\n\n", "", "is.single.session", adapter.getContext().getSingleSession()));
+
+ int traceLevel = adapter.getContext().getTraceLevel();
+ sb.append(String.format("%4s %-30s : %s \n", "", "trace.level", adapter.getContext().getTraceLevel()));
+// switch(traceLevel) {
+// case 0:
+// sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+// "0(DEFAULT) ",
+// "1 ",
+// "2 ",
+// "3 "));
+// break;
+// case 1:
+// sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+// "0 ",
+// "1(INFO) ",
+// "2 ",
+// "3 "));
+// break;
+// case 2:
+// sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+// "0 ",
+// "1 ",
+// "2(DEBUG) ",
+// "3 "));
+// break;
+// case 3:
+// sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+// "0 ",
+// "1 ",
+// "2 ",
+// "3(TRACE) "));
+// break;
+// }
+
+ if (adapter.getContext().isPollingUse()) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.use", adapter.getContext().getPollingUse()));
+ if ("".equals(adapter.getContext().getPollingRole().trim())) {
+ if (adapter.getContext().isPollingSender())
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "SENDER (client)"));
+ else
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "RECEIVER (server)"));
+ } else {
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", adapter.getContext().getPollingRole()));
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.oneway", adapter.getContext().getPollingOneway()));
+
+ if (adapter.getContext().isPollingReceiver()) {
+ sb.append("");
+ }
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "polling.timeout", adapter.getContext().getPollingTimeout()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "polling.request", adapter.getContext().getPollingRequest()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.response.pattern",
+ adapter.getContext().getPollingResponsePattern()));
+ if (adapter.getContext().isPollingReceiver()) {
+ sb.append(" ");
+ }
+
+ if (adapter.getContext().isPollingSender()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.request.pattern",
+ adapter.getContext().getPollingRequestPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.replacement",
+ adapter.getContext().getPollingReplacement()));
+ if (adapter.getContext().isPollingSender()) {
+ sb.append(" ");
+ }
+
+ sb.append("\n");
+ }
+
+ // KSH
+ if (adapter.getContext().isInitMsgUse()) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.use", adapter.getContext().getInitMsgUse()));
+ if ("".equals(adapter.getContext().getInitMsgRole().trim())) {
+ if (adapter.getContext().isInitMsgSender())
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "SENDER (client)"));
+ else
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "RECEIVER (server)"));
+ } else {
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "init.msg.role", adapter.getContext().getInitMsgRole()));
+ }
+
+ if (adapter.getContext().isInitMsgReceiver()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request",
+ adapter.getContext().getInitMsgRequest()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.response.pattern",
+ adapter.getContext().getInitMsgResponsePattern()));
+ if (adapter.getContext().isInitMsgReceiver()) {
+ sb.append(" ");
+ }
+
+ if (adapter.getContext().isInitMsgSender()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request.pattern",
+ adapter.getContext().getInitMsgRequestPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.replacement",
+ adapter.getContext().getInitMsgReplacement()));
+ if (adapter.getContext().isInitMsgSender()) {
+ sb.append(" ");
+ }
+
+ sb.append("\n");
+ }
+
+ /**
+ * ll info (fixed length header)
+ */
+ if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "EGSEED".equals(adapter.getContext().getProtocol())
+ || "TCSEED".equals(adapter.getContext().getProtocol()) // 20101213 JGY
+ || "ENVELOP".equals(adapter.getContext().getProtocol())
+ || "XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE2".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())
+ || "XC3EPB".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include",
+ adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude",
+ adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ }
+
+ /**
+ * ll info (variable length payload) 20130719 KSH
+ */
+ if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include",
+ adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude",
+ adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "send.header.length",
+ adapter.getContext().getSendHeaderLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "recv.header.length",
+ adapter.getContext().getRecvHeaderLength()));
+ }
+
+ /**
+ * ll info (fixed length payload)
+ */
+ if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
+ || "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol()) // 20100515 JGY
+ || "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "send.payload.length",
+ adapter.getContext().getSendPayloadLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "recv.payload.length",
+ adapter.getContext().getRecvPayloadLength()));
+ }
+
+ /**
+ * xecure
+ */
+ if ("XECURE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.config.path",
+ adapter.getContext().getXecureConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.remote.cert",
+ adapter.getContext().getXecureRemoteCert()));
+ }
+
+ /**
+ * xecure2
+ */
+ if ("XECURE2".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.config.path",
+ adapter.getContext().getXecure2ConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.sm.ip", adapter.getContext().getXecure2SmIp()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "xecure2.sm.port", adapter.getContext().getXecure2SmPort()));
+ // use CISCO interface only
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
+ }
+
+ /**
+ * xecure3 20100901 JGY
+ */
+ if ("XECURE3".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.store",
+ adapter.getContext().getXecure3CertStore()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.server.cert",
+ adapter.getContext().getXecure3ServerCert()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.client.cert",
+ adapter.getContext().getXecure3ClientCert()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.key",
+ adapter.getContext().getXecure3CertKey()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.password",
+ adapter.getContext().getXecure3CertPassword()));
+ }
+
+ /**
+ * xc3epb 20210929
+ */
+ if ("XC3EPB".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "xc3epb.password", adapter.getContext().getXc3epbPassword()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xc3epb.config.path",
+ adapter.getContext().getXc3epbConfigPath()));
+ }
+
+ /**
+ * inisafe inisafe_payload 20100515 JGY
+ */
+ if ("INISAFE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
+ adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups",
+ adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message",
+ adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message",
+ adapter.getContext().getInisafeStopMessage()));
+ } else if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
+ adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups",
+ adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message",
+ adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message",
+ adapter.getContext().getInisafeStopMessage()));
+ } else if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
+ adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups",
+ adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message",
+ adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message",
+ adapter.getContext().getInisafeStopMessage()));
+ } else if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path",
+ adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.id.password",
+ adapter.getContext().getInisafeIdPassword()));
+ }
+
+ /**
+ * ENVELOP : JGY 20100423
+ */
+ if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signcert.path",
+ adapter.getContext().getEnvelopSigncertPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signkey.path",
+ adapter.getContext().getEnvelopSignkeyPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.password",
+ adapter.getContext().getEnvelopPassword()));
+ }
+
+ /**
+ * TCSEED : JGY 20101213
+ */
+ if ("TCSEED".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "tcseed.key.store",
+ adapter.getContext().getTcseedKeyStore()));
+ }
+
+ if ("DYNAMIC_OFFSET".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(
+ String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include",
+ adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude",
+ adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "dynamic.offset.pattern",
+ adapter.getContext().getDynamicOffsetPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "data.add.rule", adapter.getContext().getDataAddRule()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "data.remove.rule",
+ adapter.getContext().getDataRemoveRule()));
+ }
+
+ /**
+ * script
+ */
+ if (!"".equals(adapter.getContext().getScript().trim())) {
+ sb.append("\n");
+ // sb.append(String.format("%4s %-30s : %s\n", "", "script", "" + adapter.getContext().getScript() +
+ // " "));
+ }
+
+ sb.append("\n");
+
+ /**
+ * session list
+ */
+ sb.append("\nsession pool (remaining) \n");
+ sb.append("");
+ for (Iterator iii = adapter.getSessionPool().iterator(); iii.hasNext();) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");
+ ;
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-")
+ + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append(" ");
+
+ if (adapter.getSessionPool().checkedOut() > 0) {
+ sb.append("session pool (checked out) \n");
+ }
+
+ sb.append("");
+ for (Iterator iii = adapter.getSessionPool().checkedOutIterator(); iii.hasNext();) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");
+ ;
+ // sb.append(" [" + session.getTrafficMask() + "]");
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-")
+ + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ /**
+ * netstat
+ */
+ try {
+ String[] cmd;
+ if (Env.isWindows()) {
+ cmd = new String[] { "cmd.exe", "/c", "netstat -an | findstr " + adapter.getContext().getPortNumber() };
+ } else {
+ cmd = new String[] { "sh", "-c",
+ "netstat -an | grep -E 'tcp|udp' | grep " + adapter.getContext().getPortNumber() };
+ }
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec(cmd);
+
+ StreamForNetstat netstat1 = new StreamForNetstat(process.getInputStream(), adapter);
+ StreamForNetstat netstat2 = new StreamForNetstat(process.getErrorStream(), adapter);
+ netstat1.start();
+ netstat2.start();
+ while (true) {
+ if (!netstat1.isAlive() && !netstat2.isAlive()) { // 두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
+ process.waitFor();
+ sb.append(netstat1.getData());
+ break;
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Error", e);
+ }
+
+ /**
+ * lsof && ps
+ */
+ if (!Env.isWindows()) {
+ try {
+ String[] cmd = new String[] { "sh", "-c",
+ "lsof -iTCP"
+ + ("*".equals(adapter.getContext().getHostName()) ? ""
+ : "@" + adapter.getContext().getHostName())
+ + ":" + adapter.getContext().getPortNumber() +
+ // " | grep " + adapter.getContext().getHostName() +
+ " | grep -E '\\([A-Z0-9_]+\\)$'" };
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec(cmd);
+
+ StreamForLsof lsof1 = new StreamForLsof(process.getInputStream());
+ StreamForLsof lsof2 = new StreamForLsof(process.getErrorStream());
+ lsof1.start();
+ lsof2.start();
+ while (true) {
+ if (!lsof1.isAlive() && !lsof2.isAlive()) { // 두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
+ process.waitFor();
+ sb.append(lsof1.getData());
+ break;
+ }
+ }
+
+// Process process = new ProcessBuilder(cmd).start();
+// InputStream is = process.getInputStream();
+// InputStreamReader isr = new InputStreamReader(is);
+// BufferedReader br = new BufferedReader(isr);
+// int result = process.waitFor();
+//
+// sb.append("\nlsof ");
+// sb.append("\n");
+// String line = "";
+// while ((line = br.readLine()) != null) {
+// String[] cols = line.trim().split("[ ]+");
+// String separator = Env.isWindows() ? ":" : ".";
+// sb.append(" " + line + "\n");
+// }
+// sb.append(" ");
+// sb.append("\n");
+ } catch (Exception e) {
+ logger.error("Error", e);
+ }
+ }
+
+ /**
+ * threads info
+ */
+ sb.append("\nthreads ");
+ sb.append("\n");
+ ThreadGroup it = Thread.currentThread().getThreadGroup();
+ Thread[] threads = new Thread[it.activeCount()];
+ it.enumerate(threads);
+
+ sb.append("");
+ for (int i = 0; i < threads.length; i++) {
+ try {
+ if ((threads[i] != null && threads[i].getName() != null
+ && threads[i].getName()
+ .startsWith(adapterName.substring(adapterName.lastIndexOf('.') + 1) + "-"))
+ || (adapter.getThreadMap().get(threads[i]) != null)) {
+ sb.append("");
+ sb.append(ThreadDumpUtil.getStackTrace(threads[i]));
+ sb.append(" ");
+ }
+ } catch (Exception e) {
+ logger.error("Error", e);
+ }
+ }
+ sb.append("
");
+ sb.append(" ");
+ sb.append("\n");
+
+ return "" + sb.toString() + " ";
+ }
+
+ private String traceLevel(String adapterName, int level) throws Exception {
+// StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter != null)
+ adapter.getContext().setTraceLevel(level);
+ return show(adapterName);
+ }
+
+ private String clear(String adapterName) throws Exception {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.clearStat();
+ return adapterName + " | statistics cleared successfully.";
+ }
+
+ private String start(String adapterName) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ SimpleFuture future = adapter.start();
+ Object result = future.join(60000L);
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ return adapterName + " | adapter successfully started";
+ } else {
+ ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
+ if (adapters == null)
+ throw new Exception("adapter group '" + adapterName + "' does not exist");
+ for (int i = 0; i < adapters.length; i++) {
+ SimpleFuture future = adapters[i].start();
+ Object result = future.join(60000L);
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ }
+ return adapterName + " | adapter group successfully started";
+ }
+ }
+
+ private String stop(String adapterName, boolean isForce) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ return adapterName + " | adapter does not exist";
+ try {
+ SimpleFuture future = null;
+ if (isForce) {
+ future = adapter.stopForcely();
+ } else {
+ future = adapter.stop();
+ }
+ Object result = future.join();
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ return adapterName + " | adapter successfully stopped";
+ } catch (Exception e) {
+ return e.getMessage();
+ }
+ } else {
+ ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
+ if (adapters == null)
+ throw new Exception(adapterName + " | adapter group does not exist");
+ for (int i = 0; i < adapters.length; i++) {
+ SimpleFuture future = null;
+ if (isForce) {
+ future = adapters[i].stopForcely();
+ } else {
+ future = adapters[i].stop();
+ }
+ Object result = future.join();
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ }
+ return adapterName + " | adapter group successfully stopped";
+ }
+ }
+
+ final static String SCRIPT = " \n";
+
+ private String error(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception(adapterName + " - adapter does not exist");
+
+ String[] errors = adapter.getRecentErrors();
+
+ sb.append(SCRIPT);
+ sb.append("adapter = " + adapterName + " ");
+ sb.append("\n");
+ for (int i = errors.length - 1; i >= 0; i--) {
+ sb.append(
+ "");
+ sb.append("
");
+ sb.append(unescape(errors[i]));
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+ }
+ return sb.toString();
+
+ }
+
+ private String sendRecv(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception(adapterName + " - adapter does not exist");
+
+ String[] msgs = adapter.getRecentSendRecv();
+
+ sb.append(SCRIPT);
+ sb.append("adapter = " + adapterName + " ");
+ sb.append("\n");
+ sb.append("");
+ for (int i = msgs.length - 1; i >= 0; i--) {
+ sb.append(
+ "");
+ sb.append("
");
+ sb.append(unescape(msgs[i]));
+ sb.append("\n\n");
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+ }
+ sb.append(" \n");
+ return sb.toString();
+ }
+
+ private String removeSession(String adapterName, String localPort, String remotePort) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.getSessionPool().remove(Integer.parseInt(localPort), Integer.parseInt(remotePort));
+ return adapterName + " | adapter session remove local(" + localPort + ") remote(" + remotePort + ")";
+ }
+ return "fail";
+ }
+
+ private String sessionValidate(String adapterName) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.getSessionPool().sessionValidate();
+ return adapterName + " | adapter session validate";
+ }
+ return "fail";
+ }
+
+ private String unescape(String string) {
+ string = string.replace("", "(b)").replace(" ", "(/b)");
+ string = string.replaceAll("", "(a$1)").replace(" ", "(/a)");
+ string = string.replaceAll("", "(font color='$1')").replace(" ",
+ "(/font)");
+ string = string.replace(">", ">").replace("<", "<");
+ string = string.replace("(b)", "").replace("(/b)", " ");
+ string = string.replaceAll("\\(a( href=\\'[a-zA-Z0-9_/]+\\')\\)", "").replace("(/a)", " ");
+ string = string.replaceAll("\\(font color='([a-zA-Z0-9# ]+)'\\)", "").replace("(/font)",
+ " ");
+ return string;
+ }
+
+ class StreamForNetstat extends Thread {
+ InputStream is;
+ StringBuffer sb;
+ ISocketAdapter adapter;
+
+ public StreamForNetstat(InputStream is, ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.is = is;
+ sb = new StringBuffer();
+ }
+
+ public void run() {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ sb.append("\nnetstat ");
+ sb.append("\n");
+ String line;
+ while ((line = br.readLine()) != null) {
+ if (!line.trim().toUpperCase().startsWith("TCP") && !line.trim().toUpperCase().startsWith("UDP"))
+ continue;
+ String[] cols = line.trim().split("[ ]+");
+ String separator = Env.isWindows() ? ":" : ".";
+ if (Env.isWindows()) {
+ if (adapter.getContext().isServer()) {
+ if (!cols[1].endsWith(separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ } else {
+ if (!cols[2].equals(adapter.getContext().getHostName() + separator
+ + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ }
+ } else {
+ if (adapter.getContext().isServer()) {
+ if (!cols[3].endsWith(separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ } else {
+ if (!cols[4].equals(adapter.getContext().getHostName() + separator
+ + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ }
+ }
+ sb.append(" " + line + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ } catch (IOException ioe) {
+ logger.error("StreamForNetstat", ioe);
+ }
+ }
+
+ public String getData() {
+ return sb.toString();
+ }
+ }
+
+ class StreamForLsof extends Thread {
+ InputStream is;
+ StringBuffer sb;
+
+ public StreamForLsof(InputStream is) {
+ this.is = is;
+ sb = new StringBuffer();
+ }
+
+ public void run() {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ sb.append("\nlsof ");
+ sb.append("\n");
+ String line = "";
+ while ((line = br.readLine()) != null) {
+// String[] cols = line.trim().split("[ ]+");
+// String separator = Env.isWindows() ? ":" : ".";
+ sb.append(" " + line + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ } catch (IOException ioe) {
+ logger.error("StreamForLsof", ioe);
+ }
+ }
+
+ public String getData() {
+ return sb.toString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterJsonServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterJsonServlet.java
new file mode 100644
index 0000000..dec4476
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterJsonServlet.java
@@ -0,0 +1,773 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+import org.json.simple.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Iterator;
+
+public class AdapterJsonServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String command = request.getContext();
+ if (command.lastIndexOf('/') == -1) {
+ command = "";
+ } else {
+ command = command.substring(command.indexOf('/')+1);
+ }
+
+ String result = "";
+
+ try {
+ if (command == null || "".equals(command) || "show".equals(command)) {
+ result = show(request.getParameter("adapter"));
+ } else if (command.startsWith("traceLevel")) {
+ result = traceLevel(request.getParameter("adapter"), Integer.parseInt(request.getParameter("level")));
+ } else if (command.startsWith("clear")) {
+ result = clear(request.getParameter("adapter"));
+ } else if (command.startsWith("start")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | start - " + request.getSession());
+ result = start(adapterName);
+ } else if (command.startsWith("stopforcely")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
+ result = stop(adapterName, true);
+ } else if (command.startsWith("stop")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
+ result = stop(adapterName, false);
+ } else if (command.startsWith("error")) {
+ result = error(request.getParameter("adapter"));
+ } else if (command.startsWith("sendRecv")) {
+ result = sendRecv(request.getParameter("adapter"));
+ } else if (command.startsWith("removeSession")) {
+ result = removeSession(request.getParameter("adapter"),request.getParameter("localPort"),request.getParameter("remotePort"));
+ } else if (command.startsWith("sessionValidate")) {
+ result = sessionValidate(request.getParameter("adapter"));
+ } else {
+ response.setResponseCode(404);
+ return;
+ }
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ response.setContentType("text/html;charset=utf-8;");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+ }
+
+ private String show(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+
+ HashMap detail = new HashMap();
+ detail.put("adapterName", adapterName);
+
+ if(adapter == null) {
+ JSONObject json = new JSONObject();
+ json.putAll(detail);
+ return json.toJSONString();
+ }
+ detail.put("state", adapter.getState().name());
+ detail.put("uptime" , TimeUtil.formatDate(adapter.getUptime().getTime()));
+ detail.put("pool" , adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
+ detail.put("recv", adapter.getMessageRecv());
+ detail.put("send", adapter.getMessageSend());
+ detail.put("error", adapter.getRecentErrorCount());
+ detail.put("trace.level", adapter.getContext().getTraceLevel());
+
+
+ if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
+ sb.append("\n " + adapter.getContext().getDescription() + "\n");
+ }
+
+ sb.append("\n\n");
+
+ /**
+ * common info
+ */
+ sb.append(String.format("%4s %-30s : %s\n", "", "host.name", adapter.getContext().getHostName()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "port.number", adapter.getContext().getPortNumber()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "local.host.name", adapter.getContext().getLocalHostName()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "local.port.number", adapter.getContext().getLocalPortNumber()));
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "protocol", adapter.getContext().getProtocol()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "bound.usage", adapter.getContext().getBoundUsage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "socket.type", adapter.getContext().getSocketType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "response.type", adapter.getContext().getResponseType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ack.support", adapter.getContext().getAckSupport()));
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "permanent", adapter.getContext().getPermanent()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "blocking(NIO, BIO)", adapter.getContext().getBlocking()));
+ sb.append(String.format("%4s %-30s : %s (sec)\n", "", "timeout", adapter.getContext().getTimeout()));
+ sb.append(String.format("%4s %-30s : %s (sec)\n", "", "idle.timeout", adapter.getContext().getIdleTimeout()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "socket.reuse", adapter.getContext().getSocketReuse()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "business.work.class.code", adapter.getContext().getBwkClsCd()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "max.connection", (adapter.getContext().getCloseExistingConnection() ? "-" : "") + adapter.getContext().getMaxConnection()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "connection.limit.per.ip", adapter.getContext().getConnLimitPerIp()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "max.thread", adapter.getContext().getMaxThread()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "validation.rule", adapter.getContext().getValidationRule()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "acl.list", adapter.getContext().getAclList()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "block.ip.list", adapter.getContext().getBlockIpList()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "l4.skip.ip.list", adapter.getContext().getL4SkipIpList()));
+
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "is.single.session", adapter.getContext().getSingleSession()));
+
+
+
+ if (adapter.getContext().isPollingUse()) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.use", adapter.getContext().getPollingUse()));
+ if ("".equals(adapter.getContext().getPollingRole().trim())) {
+ if (adapter.getContext().isPollingSender())
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "SENDER (client)"));
+ else
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "RECEIVER (server)"));
+ } else {
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", adapter.getContext().getPollingRole()));
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.oneway", adapter.getContext().getPollingOneway()));
+
+ if (adapter.getContext().isPollingReceiver()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.timeout", adapter.getContext().getPollingTimeout()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.request", adapter.getContext().getPollingRequest()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.response.pattern", adapter.getContext().getPollingResponsePattern()));
+ if (adapter.getContext().isPollingReceiver()) {
+ sb.append(" ");
+ }
+
+ if (adapter.getContext().isPollingSender()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.request.pattern", adapter.getContext().getPollingRequestPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.replacement", adapter.getContext().getPollingReplacement()));
+ if (adapter.getContext().isPollingSender()) {
+ sb.append(" ");
+ }
+
+ sb.append("\n");
+ }
+
+ //KSH
+ if (adapter.getContext().isInitMsgUse()) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.use", adapter.getContext().getInitMsgUse()));
+ if ("".equals(adapter.getContext().getInitMsgRole().trim())) {
+ if (adapter.getContext().isInitMsgSender())
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "SENDER (client)"));
+ else
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "RECEIVER (server)"));
+ } else {
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", adapter.getContext().getInitMsgRole()));
+ }
+
+ if (adapter.getContext().isInitMsgReceiver()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request", adapter.getContext().getInitMsgRequest()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.response.pattern", adapter.getContext().getInitMsgResponsePattern()));
+ if (adapter.getContext().isInitMsgReceiver()) {
+ sb.append(" ");
+ }
+
+ if (adapter.getContext().isInitMsgSender()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request.pattern", adapter.getContext().getInitMsgRequestPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.replacement", adapter.getContext().getInitMsgReplacement()));
+ if (adapter.getContext().isInitMsgSender()) {
+ sb.append(" ");
+ }
+
+ sb.append("\n");
+ }
+
+ /**
+ * ll info (fixed length header)
+ */
+ if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "EGSEED".equals(adapter.getContext().getProtocol())
+ || "TCSEED".equals(adapter.getContext().getProtocol()) //20101213 JGY
+ || "ENVELOP".equals(adapter.getContext().getProtocol())
+ || "XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE2".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())
+ || "XC3EPB".equals(adapter.getContext().getProtocol())
+ ) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include", adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude", adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ }
+
+ /**
+ * ll info (variable length payload) 20130719 KSH
+ */
+ if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())){
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include", adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude", adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "send.header.length", adapter.getContext().getSendHeaderLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "recv.header.length", adapter.getContext().getRecvHeaderLength()));
+ }
+
+
+ /**
+ * ll info (fixed length payload)
+ */
+ if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
+ || "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol()) // 20100515 JGY
+ || "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "send.payload.length", adapter.getContext().getSendPayloadLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "recv.payload.length", adapter.getContext().getRecvPayloadLength()));
+ }
+
+ /**
+ * xecure
+ */
+ if ("XECURE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.config.path", adapter.getContext().getXecureConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.remote.cert", adapter.getContext().getXecureRemoteCert()));
+ }
+
+ /**
+ * xecure2
+ */
+ if ("XECURE2".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.config.path", adapter.getContext().getXecure2ConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.sm.ip", adapter.getContext().getXecure2SmIp()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.sm.port", adapter.getContext().getXecure2SmPort()));
+ // use CISCO interface only
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
+ }
+
+ /**
+ * xecure3 20100901 JGY
+ */
+ if ("XECURE3".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.store", adapter.getContext().getXecure3CertStore()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.server.cert", adapter.getContext().getXecure3ServerCert()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.client.cert", adapter.getContext().getXecure3ClientCert()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.key", adapter.getContext().getXecure3CertKey()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.password", adapter.getContext().getXecure3CertPassword()));
+ }
+
+ /**
+ * xc3epb 20210929
+ */
+ if ("XC3EPB".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xc3epb.password", adapter.getContext().getXc3epbPassword()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xc3epb.config.path", adapter.getContext().getXc3epbConfigPath()));
+ }
+
+ /**
+ * inisafe
+ * inisafe_payload 20100515 JGY
+ */
+ if ("INISAFE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups", adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message", adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message", adapter.getContext().getInisafeStopMessage()));
+ }
+ else if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups", adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message", adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message", adapter.getContext().getInisafeStopMessage()));
+ }
+ else if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups", adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message", adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message", adapter.getContext().getInisafeStopMessage()));
+ }
+ else if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.id.password", adapter.getContext().getInisafeIdPassword()));
+ }
+
+ /**
+ * ENVELOP : JGY 20100423
+ */
+ if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signcert.path", adapter.getContext().getEnvelopSigncertPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signkey.path", adapter.getContext().getEnvelopSignkeyPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.password", adapter.getContext().getEnvelopPassword()));
+ }
+
+ /**
+ * TCSEED : JGY 20101213
+ */
+ if ("TCSEED".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "tcseed.key.store", adapter.getContext().getTcseedKeyStore()));
+ }
+
+ /**
+ * script
+ */
+ if (!"".equals(adapter.getContext().getScript().trim())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "script", "" + adapter.getContext().getScript() + " "));
+ }
+
+ sb.append("\n");
+
+ /**
+ * session list
+ */
+ sb.append("\nsession pool (remaining)\n");
+ for (Iterator iii = adapter.getSessionPool().iterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");;
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+
+ if (adapter.getSessionPool().checkedOut() > 0) {
+ sb.append("session pool (checked out)\n");
+ }
+
+ for (Iterator iii = adapter.getSessionPool().checkedOutIterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");;
+ //sb.append(" [" + session.getTrafficMask() + "]");
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append("\n");
+
+ /**
+ * netstat
+ */
+ try {
+ String[] cmd;
+ if (Env.isWindows()) {
+ cmd = new String[] {"cmd.exe", "/c", "netstat -an | findstr " + adapter.getContext().getPortNumber()};
+ } else {
+ cmd = new String[] {"sh", "-c", "netstat -an | grep -E 'tcp|udp' | grep " + adapter.getContext().getPortNumber()};
+ }
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec(cmd);
+
+ StreamForNetstat netstat1 = new StreamForNetstat(process.getInputStream(),adapter);
+ StreamForNetstat netstat2 = new StreamForNetstat(process.getErrorStream(),adapter);
+ netstat1.start();
+ netstat2.start();
+ while (true) {
+ if (!netstat1.isAlive() && !netstat2.isAlive()) { //두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
+ process.waitFor();
+ sb.append(netstat1.getData());
+ break;
+ }
+ }
+
+ } catch(Exception e) {
+ logger.error("Error", e) ;
+ }
+
+ /**
+ * lsof && ps
+ */
+ if (!Env.isWindows()) {
+ try {
+ String[] cmd = new String[] {"sh", "-c", "lsof -iTCP" +
+ ("*".equals(adapter.getContext().getHostName()) ? "" : "@" + adapter.getContext().getHostName()) +
+ ":" + adapter.getContext().getPortNumber() +
+ //" | grep " + adapter.getContext().getHostName() +
+ " | grep -E '\\([A-Z0-9_]+\\)$'" };
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec(cmd);
+
+ StreamForLsof lsof1 = new StreamForLsof(process.getInputStream());
+ StreamForLsof lsof2 = new StreamForLsof(process.getErrorStream());
+ lsof1.start();
+ lsof2.start();
+ while (true) {
+ if (!lsof1.isAlive() && !lsof2.isAlive()) { //두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
+ process.waitFor();
+ sb.append(lsof1.getData());
+ break;
+ }
+ }
+
+
+ } catch(Exception e) {
+ logger.error("Error", e) ;
+ }
+ }
+
+
+ /**
+ * threads info
+ */
+ sb.append("\nthreads");
+ ThreadGroup it = Thread.currentThread().getThreadGroup();
+ Thread[] threads = new Thread[it.activeCount()] ;
+ it.enumerate(threads);
+
+ sb.append("");
+ for (int i=0; i");
+ sb.append(ThreadDumpUtil.getStackTrace(threads[i]));
+ sb.append("");
+ }
+ } catch(Exception e) {
+ logger.error("Error", e) ;
+ }
+ }
+ sb.append("
");
+ sb.append("\n");
+
+ detail.put("data", sb.toString());
+
+ JSONObject json = new JSONObject();
+ json.putAll(detail);
+
+ return json.toJSONString();
+ }
+
+ private String traceLevel(String adapterName, int level) throws Exception {
+// StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if(adapter != null) adapter.getContext().setTraceLevel(level);
+ return show(adapterName);
+ }
+
+ private String clear(String adapterName) throws Exception {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.clearStat();
+ return adapterName + " | statistics cleared successfully.";
+ }
+
+ private String start(String adapterName) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ SimpleFuture future = adapter.start();
+ Object result = future.join(60000L);
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ return adapterName + " | adapter successfully started";
+ } else {
+ ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
+ if (adapters == null)
+ throw new Exception("adapter group '" + adapterName + "' does not exist");
+ for (int i=0; i" + ExceptionStackTrace.dump((Throwable) result) + "";
+ }
+ }
+ return adapterName + " | adapter group successfully started";
+ }
+ }
+
+ private String stop(String adapterName, boolean isForce) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ return adapterName + " | adapter does not exist";
+ try {
+ SimpleFuture future = null;
+ if (isForce) {
+ future = adapter.stopForcely();
+ } else {
+ future = adapter.stop();
+ }
+ Object result = future.join();
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ return adapterName + " | adapter successfully stopped";
+ } catch(Exception e) {
+ return e.getMessage();
+ }
+ } else {
+ ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
+ if (adapters == null)
+ throw new Exception(adapterName + " | adapter group does not exist");
+ for (int i=0; i" + ExceptionStackTrace.dump((Throwable) result) + "";
+ }
+ }
+ return adapterName + " | adapter group successfully stopped";
+ }
+ }
+
+ final static String SCRIPT =
+ " \n";
+
+ private String error(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception(adapterName + " - adapter does not exist");
+
+ String[] errors = adapter.getRecentErrors();
+
+ sb.append(SCRIPT);
+ sb.append("adapter = " + adapterName + " ");
+ sb.append("\n");
+ for (int i=errors.length-1; i>=0; i--) {
+ sb.append("");
+ sb.append("
");
+ sb.append(unescape(errors[i]));
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+ }
+ return sb.toString();
+
+ }
+
+ private String sendRecv(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception(adapterName + " - adapter does not exist");
+
+ String[] msgs = adapter.getRecentSendRecv();
+
+ sb.append(SCRIPT);
+ sb.append("adapter = " + adapterName + " ");
+ sb.append("\n");
+ sb.append("");
+ for (int i=msgs.length-1; i>=0; i--) {
+ sb.append("");
+ sb.append("
");
+ sb.append(unescape(msgs[i]));
+ sb.append("\n\n");
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+ }
+ sb.append(" \n");
+ return sb.toString();
+ }
+ private String removeSession(String adapterName, String localPort, String remotePort) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.getSessionPool().remove(Integer.parseInt(localPort), Integer.parseInt(remotePort));
+ return adapterName + " | adapter session remove local("+localPort+") remote("+remotePort+")";
+ }
+ return "fail";
+ }
+ private String sessionValidate(String adapterName) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.getSessionPool().sessionValidate();
+ return adapterName + " | adapter session validate";
+ }
+ return "fail";
+ }
+
+ private String unescape(String string) {
+ string = string.replace("", "(b)").replace(" ", "(/b)");
+ string = string.replaceAll("", "(a$1)").replace(" ", "(/a)");
+ string = string.replaceAll("", "(font color='$1')").replace(" ", "(/font)");
+ string = string.replace(">", ">").replace("<", "<");
+ string = string.replace("(b)", "").replace("(/b)", " ");
+ string = string.replaceAll("\\(a( href=\\'[a-zA-Z0-9_/]+\\')\\)", "").replace("(/a)", " ");
+ string = string.replaceAll("\\(font color='([a-zA-Z0-9# ]+)'\\)", "").replace("(/font)", " ");
+ return string;
+ }
+ class StreamForNetstat extends Thread
+ {
+ InputStream is;
+ StringBuffer sb ;
+ ISocketAdapter adapter;
+ public StreamForNetstat(InputStream is,ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.is = is;
+ sb = new StringBuffer();
+ }
+
+ public void run()
+ {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ sb.append("\nnetstat ");
+ sb.append("\n");
+ String line;
+ while ((line = br.readLine()) != null) {
+ if (!line.trim().toUpperCase().startsWith("TCP") && !line.trim().toUpperCase().startsWith("UDP"))
+ continue;
+ String[] cols = line.trim().split("[ ]+");
+ String separator = Env.isWindows() ? ":" : ".";
+ if (Env.isWindows()) {
+ if (adapter.getContext().isServer()) {
+ if(!cols[1].endsWith(separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ } else {
+ if(!cols[2].equals(adapter.getContext().getHostName() + separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ }
+ } else {
+ if (adapter.getContext().isServer()) {
+ if(!cols[3].endsWith(separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ } else {
+ if(!cols[4].equals(adapter.getContext().getHostName() + separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ }
+ }
+ sb.append(" " + line + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ } catch (IOException ioe) {
+ logger.error("StreamForNetstat", ioe);
+ }
+ }
+ public String getData(){
+ return sb.toString();
+ }
+ }
+ class StreamForLsof extends Thread
+ {
+ InputStream is;
+ StringBuffer sb ;
+ public StreamForLsof(InputStream is) {
+ this.is = is;
+ sb = new StringBuffer();
+ }
+
+ public void run()
+ {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ sb.append("\nlsof ");
+ sb.append("\n");
+ String line = "";
+ while ((line = br.readLine()) != null) {
+// String[] cols = line.trim().split("[ ]+");
+// String separator = Env.isWindows() ? ":" : ".";
+ sb.append(" " + line + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ } catch (IOException ioe) {
+ logger.error("StreamForLsof", ioe);
+ }
+ }
+ public String getData(){
+ return sb.toString();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterServlet.java
new file mode 100644
index 0000000..b10c835
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdapterServlet.java
@@ -0,0 +1,845 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Iterator;
+
+public class AdapterServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String command = request.getContext();
+ if (command.lastIndexOf('/') == -1) {
+ command = "";
+ } else {
+ command = command.substring(command.indexOf('/')+1);
+ }
+
+ String result = "";
+
+ try {
+ if (command == null || "".equals(command) || "show".equals(command)) {
+ result = show(request.getParameter("adapter"));
+ } else if (command.startsWith("traceLevel")) {
+ result = traceLevel(request.getParameter("adapter"), Integer.parseInt(request.getParameter("level")));
+ } else if (command.startsWith("clear")) {
+ result = clear(request.getParameter("adapter"));
+ } else if (command.startsWith("start")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | start - " + request.getSession());
+ result = start(adapterName);
+ } else if (command.startsWith("stopforcely")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
+ result = stop(adapterName, true);
+ } else if (command.startsWith("stop")) {
+ String adapterName = request.getParameter("adapter");
+ logger.fatal("HttpAdapter | " + adapterName + " | stop - " + request.getSession());
+ result = stop(adapterName, false);
+ } else if (command.startsWith("error")) {
+ result = error(request.getParameter("adapter"));
+ } else if (command.startsWith("sendRecv")) {
+ result = sendRecv(request.getParameter("adapter"));
+ } else if (command.startsWith("removeSession")) {
+ result = removeSession(request.getParameter("adapter"),request.getParameter("localPort"),request.getParameter("remotePort"));
+ } else if (command.startsWith("sessionValidate")) {
+ result = sessionValidate(request.getParameter("adapter"));
+ } else {
+ response.setResponseCode(404);
+ return;
+ }
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ response.setContentType("text/html;charset=utf-8;");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+ }
+
+ private String show(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ sb.append(adapterName);
+
+ if(adapter == null) {
+ sb.append(" Not found adapter (" + adapterName + ") ");
+ return sb.toString();
+ }
+ /**
+ * status
+ */
+ if ("STARTED".equals(adapter.getState().name())) {
+ sb.append(" (" + adapter.getState().name() + ")");
+ } else {
+ sb.append(" (" + adapter.getState().name() + ") ");
+ }
+
+ sb.append(" uptime:" + TimeUtil.formatDate(adapter.getUptime().getTime()));
+ sb.append(", pool:" + adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
+ sb.append(", recv:" + "" + adapter.getMessageRecv() + " ");
+ sb.append(", send:" + "" + adapter.getMessageSend() + " ");
+ if (adapter.getRecentErrorCount() > 0) {
+ sb.append(", ");
+ sb.append("");
+ sb.append("error:" + adapter.getRecentErrorCount());
+ sb.append(" ");
+ } else {
+ sb.append(", error:" + adapter.getRecentErrorCount());
+ }
+
+ sb.append(", (clear )");
+
+ sb.append(" (start ");
+ sb.append("|stop )");
+
+ if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
+ sb.append("\n " + adapter.getContext().getDescription() + "\n");
+ }
+
+ sb.append("\n\n");
+
+ /**
+ * common info
+ */
+ sb.append(String.format("%4s %-30s : %s\n", "", "host.name", adapter.getContext().getHostName()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "port.number", adapter.getContext().getPortNumber()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "local.host.name", adapter.getContext().getLocalHostName()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "local.port.number", adapter.getContext().getLocalPortNumber()));
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "protocol", adapter.getContext().getProtocol()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "bound.usage", adapter.getContext().getBoundUsage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "socket.type", adapter.getContext().getSocketType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "response.type", adapter.getContext().getResponseType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ack.support", adapter.getContext().getAckSupport()));
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "permanent", adapter.getContext().getPermanent()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "blocking(NIO, BIO)", adapter.getContext().getBlocking()));
+ sb.append(String.format("%4s %-30s : %s (sec)\n", "", "timeout", adapter.getContext().getTimeout()));
+ sb.append(String.format("%4s %-30s : %s (sec)\n", "", "idle.timeout", adapter.getContext().getIdleTimeout()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "socket.reuse", adapter.getContext().getSocketReuse()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "business.work.class.code", adapter.getContext().getBwkClsCd()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "max.connection", (adapter.getContext().getCloseExistingConnection() ? "-" : "") + adapter.getContext().getMaxConnection()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "connection.limit.per.ip", adapter.getContext().getConnLimitPerIp()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "max.thread", adapter.getContext().getMaxThread()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "validation.rule", adapter.getContext().getValidationRule()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "datacontrol.rule", adapter.getContext().getDataControlRule()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "acl.list", adapter.getContext().getAclList()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "block.ip.list", adapter.getContext().getBlockIpList()));
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "l4.skip.ip.list", adapter.getContext().getL4SkipIpList()));
+
+ sb.append(String.format("%4s %-30s : %s\n\n", "", "is.single.session", adapter.getContext().getSingleSession()));
+
+ int traceLevel = adapter.getContext().getTraceLevel();
+ switch(traceLevel) {
+ case 0:
+ sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+ "0(DEFAULT) ",
+ "1 ",
+ "2 ",
+ "3 "));
+ break;
+ case 1:
+ sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+ "0 ",
+ "1(INFO) ",
+ "2 ",
+ "3 "));
+ break;
+ case 2:
+ sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+ "0 ",
+ "1 ",
+ "2(DEBUG) ",
+ "3 "));
+ break;
+ case 3:
+ sb.append(String.format("%4s %-30s : %s %s %s %s\n", "", "trace.level",
+ "0 ",
+ "1 ",
+ "2 ",
+ "3(TRACE) "));
+ break;
+ }
+
+ if (adapter.getContext().isPollingUse()) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.use", adapter.getContext().getPollingUse()));
+ if ("".equals(adapter.getContext().getPollingRole().trim())) {
+ if (adapter.getContext().isPollingSender())
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "SENDER (client)"));
+ else
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", "RECEIVER (server)"));
+ } else {
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.role", adapter.getContext().getPollingRole()));
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.oneway", adapter.getContext().getPollingOneway()));
+
+ if (adapter.getContext().isPollingReceiver()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.timeout", adapter.getContext().getPollingTimeout()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.request", adapter.getContext().getPollingRequest()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.response.pattern", adapter.getContext().getPollingResponsePattern()));
+ if (adapter.getContext().isPollingReceiver()) {
+ sb.append(" ");
+ }
+
+ if (adapter.getContext().isPollingSender()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.request.pattern", adapter.getContext().getPollingRequestPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "polling.replacement", adapter.getContext().getPollingReplacement()));
+ if (adapter.getContext().isPollingSender()) {
+ sb.append(" ");
+ }
+
+ sb.append("\n");
+ }
+
+ //KSH
+ if (adapter.getContext().isInitMsgUse()) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.use", adapter.getContext().getInitMsgUse()));
+ if ("".equals(adapter.getContext().getInitMsgRole().trim())) {
+ if (adapter.getContext().isInitMsgSender())
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "SENDER (client)"));
+ else
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", "RECEIVER (server)"));
+ } else {
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.role", adapter.getContext().getInitMsgRole()));
+ }
+
+ if (adapter.getContext().isInitMsgReceiver()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request", adapter.getContext().getInitMsgRequest()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.response.pattern", adapter.getContext().getInitMsgResponsePattern()));
+ if (adapter.getContext().isInitMsgReceiver()) {
+ sb.append(" ");
+ }
+
+ if (adapter.getContext().isInitMsgSender()) {
+ sb.append("");
+ }
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.request.pattern", adapter.getContext().getInitMsgRequestPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "init.msg.replacement", adapter.getContext().getInitMsgReplacement()));
+ if (adapter.getContext().isInitMsgSender()) {
+ sb.append(" ");
+ }
+
+ sb.append("\n");
+ }
+
+ /**
+ * ll info (fixed length header)
+ */
+ if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "EGSEED".equals(adapter.getContext().getProtocol())
+ || "TCSEED".equals(adapter.getContext().getProtocol()) //20101213 JGY
+ || "ENVELOP".equals(adapter.getContext().getProtocol())
+ || "XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE2".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())
+ || "XC3EPB".equals(adapter.getContext().getProtocol())
+ ) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include", adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude", adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ }
+
+ /**
+ * ll info (variable length payload) 20130719 KSH
+ */
+ if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())){
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include", adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude", adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "send.header.length", adapter.getContext().getSendHeaderLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "recv.header.length", adapter.getContext().getRecvHeaderLength()));
+ }
+
+
+ /**
+ * ll info (fixed length payload)
+ */
+ if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
+ || "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol()) // 20100515 JGY
+ || "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "send.payload.length", adapter.getContext().getSendPayloadLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "recv.payload.length", adapter.getContext().getRecvPayloadLength()));
+ }
+
+ /**
+ * xecure
+ */
+ if ("XECURE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.config.path", adapter.getContext().getXecureConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.remote.cert", adapter.getContext().getXecureRemoteCert()));
+ }
+
+ /**
+ * xecure2
+ */
+ if ("XECURE2".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.config.path", adapter.getContext().getXecure2ConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.sm.ip", adapter.getContext().getXecure2SmIp()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure2.sm.port", adapter.getContext().getXecure2SmPort()));
+ // use CISCO interface only
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure.type", adapter.getContext().getXecureType()));
+ }
+
+ /**
+ * xecure3 20100901 JGY
+ */
+ if ("XECURE3".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.store", adapter.getContext().getXecure3CertStore()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.server.cert", adapter.getContext().getXecure3ServerCert()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.client.cert", adapter.getContext().getXecure3ClientCert()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.key", adapter.getContext().getXecure3CertKey()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xecure3.cert.password", adapter.getContext().getXecure3CertPassword()));
+ }
+
+ /**
+ * xc3epb 20210929
+ */
+ if ("XC3EPB".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "xc3epb.password", adapter.getContext().getXc3epbPassword()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "xc3epb.config.path", adapter.getContext().getXc3epbConfigPath()));
+ }
+
+ /**
+ * inisafe
+ * inisafe_payload 20100515 JGY
+ */
+ if ("INISAFE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups", adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message", adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message", adapter.getContext().getInisafeStopMessage()));
+ }
+ else if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups", adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message", adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message", adapter.getContext().getInisafeStopMessage()));
+ }
+ else if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.related.adapter.groups", adapter.getContext().getInisafeRelatedAdapterGroups()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.start.message", adapter.getContext().getInisafeStartMessage()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.stop.message", adapter.getContext().getInisafeStopMessage()));
+ }
+ else if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.config.path", adapter.getContext().getInisafeConfigPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "inisafe.id.password", adapter.getContext().getInisafeIdPassword()));
+ }
+
+ /**
+ * ENVELOP : JGY 20100423
+ */
+ if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signcert.path", adapter.getContext().getEnvelopSigncertPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.signkey.path", adapter.getContext().getEnvelopSignkeyPath()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "envelop.password", adapter.getContext().getEnvelopPassword()));
+ }
+
+ /**
+ * TCSEED : JGY 20101213
+ */
+ if ("TCSEED".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "tcseed.key.store", adapter.getContext().getTcseedKeyStore()));
+ }
+
+ if ("DYNAMIC_OFFSET".equals(adapter.getContext().getProtocol()) ) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.type", adapter.getContext().getLlFieldType()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.offset", adapter.getContext().getLlFieldOffset()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.length", adapter.getContext().getLlFieldLength()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.field.include", adapter.getContext().getLlFieldInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.offset.exclude", adapter.getContext().getLlOffsetExclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "ll.include", adapter.getContext().getLlInclude()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "dynamic.offset.pattern", adapter.getContext().getDynamicOffsetPattern()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "data.add.rule", adapter.getContext().getDataAddRule()));
+ sb.append(String.format("%4s %-30s : %s\n", "", "data.remove.rule", adapter.getContext().getDataRemoveRule()));
+ }
+
+ /**
+ * script
+ */
+ if (!"".equals(adapter.getContext().getScript().trim())) {
+ sb.append("\n");
+ sb.append(String.format("%4s %-30s : %s\n", "", "script", "" + adapter.getContext().getScript() + " "));
+ }
+
+ sb.append("\n");
+
+ /**
+ * session list
+ */
+ sb.append("\nsession pool (remaining) \n");
+ sb.append("");
+ for (Iterator iii = adapter.getSessionPool().iterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");;
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append(" ");
+
+ if (adapter.getSessionPool().checkedOut() > 0) {
+ sb.append("session pool (checked out) \n");
+ }
+
+ sb.append("");
+ for (Iterator iii = adapter.getSessionPool().checkedOutIterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");;
+ //sb.append(" [" + session.getTrafficMask() + "]");
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ /**
+ * netstat
+ */
+ try {
+ String[] cmd;
+ if (Env.isWindows()) {
+ cmd = new String[] {"cmd.exe", "/c", "netstat -an | findstr " + adapter.getContext().getPortNumber()};
+ } else {
+ cmd = new String[] {"sh", "-c", "netstat -an | grep -E 'tcp|udp' | grep " + adapter.getContext().getPortNumber()};
+ }
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec(cmd);
+
+ StreamForNetstat netstat1 = new StreamForNetstat(process.getInputStream(),adapter);
+ StreamForNetstat netstat2 = new StreamForNetstat(process.getErrorStream(),adapter);
+ netstat1.start();
+ netstat2.start();
+ while (true) {
+ if (!netstat1.isAlive() && !netstat2.isAlive()) { //두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
+ process.waitFor();
+ sb.append(netstat1.getData());
+ break;
+ }
+ }
+ } catch(Exception e) {
+ logger.error("Error", e) ;
+ }
+
+ /**
+ * lsof && ps
+ */
+ if (!Env.isWindows()) {
+ try {
+ String[] cmd = new String[] {"sh", "-c", "lsof -iTCP" +
+ ("*".equals(adapter.getContext().getHostName()) ? "" : "@" + adapter.getContext().getHostName()) +
+ ":" + adapter.getContext().getPortNumber() +
+ //" | grep " + adapter.getContext().getHostName() +
+ " | grep -E '\\([A-Z0-9_]+\\)$'" };
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec(cmd);
+
+ StreamForLsof lsof1 = new StreamForLsof(process.getInputStream());
+ StreamForLsof lsof2 = new StreamForLsof(process.getErrorStream());
+ lsof1.start();
+ lsof2.start();
+ while (true) {
+ if (!lsof1.isAlive() && !lsof2.isAlive()) { //두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
+ process.waitFor();
+ sb.append(lsof1.getData());
+ break;
+ }
+ }
+
+// Process process = new ProcessBuilder(cmd).start();
+// InputStream is = process.getInputStream();
+// InputStreamReader isr = new InputStreamReader(is);
+// BufferedReader br = new BufferedReader(isr);
+// int result = process.waitFor();
+//
+// sb.append("\nlsof ");
+// sb.append("\n");
+// String line = "";
+// while ((line = br.readLine()) != null) {
+// String[] cols = line.trim().split("[ ]+");
+// String separator = Env.isWindows() ? ":" : ".";
+// sb.append(" " + line + "\n");
+// }
+// sb.append(" ");
+// sb.append("\n");
+ } catch(Exception e) {
+ logger.error("Error", e) ;
+ }
+ }
+
+
+ /**
+ * threads info
+ */
+ sb.append("\nthreads ");
+ sb.append("\n");
+ ThreadGroup it = Thread.currentThread().getThreadGroup();
+ Thread[] threads = new Thread[it.activeCount()] ;
+ it.enumerate(threads);
+
+ sb.append("");
+ for (int i=0; i");
+ sb.append(ThreadDumpUtil.getStackTrace(threads[i]));
+ sb.append("");
+ }
+ } catch(Exception e) {
+ logger.error("Error", e) ;
+ }
+ }
+ sb.append("
");
+ sb.append(" ");
+ sb.append("\n");
+
+ return "" + sb.toString() + " ";
+ }
+
+ private String traceLevel(String adapterName, int level) throws Exception {
+// StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if(adapter != null) adapter.getContext().setTraceLevel(level);
+ return show(adapterName);
+ }
+
+ private String clear(String adapterName) throws Exception {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.clearStat();
+ return adapterName + " | statistics cleared successfully.";
+ }
+
+ private String start(String adapterName) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ SimpleFuture future = adapter.start();
+ Object result = future.join(60000L);
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ return adapterName + " | adapter successfully started";
+ } else {
+ ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
+ if (adapters == null)
+ throw new Exception("adapter group '" + adapterName + "' does not exist");
+ for (int i=0; i" + ExceptionStackTrace.dump((Throwable) result) + "";
+ }
+ }
+ return adapterName + " | adapter group successfully started";
+ }
+ }
+
+ private String stop(String adapterName, boolean isForce) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ return adapterName + " | adapter does not exist";
+ try {
+ SimpleFuture future = null;
+ if (isForce) {
+ future = adapter.stopForcely();
+ } else {
+ future = adapter.stop();
+ }
+ Object result = future.join();
+ if (result instanceof Throwable) {
+ return "" + ExceptionStackTrace.dump((Throwable) result) + " ";
+ }
+ return adapterName + " | adapter successfully stopped";
+ } catch(Exception e) {
+ return e.getMessage();
+ }
+ } else {
+ ISocketAdapter[] adapters = manager.getSocketAdapters(adapterName);
+ if (adapters == null)
+ throw new Exception(adapterName + " | adapter group does not exist");
+ for (int i=0; i" + ExceptionStackTrace.dump((Throwable) result) + "";
+ }
+ }
+ return adapterName + " | adapter group successfully stopped";
+ }
+ }
+
+ final static String SCRIPT =
+ " \n";
+
+ private String error(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception(adapterName + " - adapter does not exist");
+
+ String[] errors = adapter.getRecentErrors();
+
+ sb.append(SCRIPT);
+ sb.append("adapter = " + adapterName + " ");
+ sb.append("\n");
+ for (int i=errors.length-1; i>=0; i--) {
+ sb.append("");
+ sb.append("
");
+ sb.append(unescape(errors[i]));
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+ }
+ return sb.toString();
+
+ }
+
+ private String sendRecv(String adapterName) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception(adapterName + " - adapter does not exist");
+
+ String[] msgs = adapter.getRecentSendRecv();
+
+ sb.append(SCRIPT);
+ sb.append("adapter = " + adapterName + " ");
+ sb.append("\n");
+ sb.append("");
+ for (int i=msgs.length-1; i>=0; i--) {
+ sb.append("");
+ sb.append("
");
+ sb.append(unescape(msgs[i]));
+ sb.append("\n\n");
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+ }
+ sb.append(" \n");
+ return sb.toString();
+ }
+ private String removeSession(String adapterName, String localPort, String remotePort) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.getSessionPool().remove(Integer.parseInt(localPort), Integer.parseInt(remotePort));
+ return adapterName + " | adapter session remove local("+localPort+") remote("+remotePort+")";
+ }
+ return "fail";
+ }
+ private String sessionValidate(String adapterName) throws Exception {
+ if (adapterName.indexOf('.') != -1) {
+ ISocketAdapter adapter = manager.getSocketAdapter(adapterName);
+ if (adapter == null)
+ throw new Exception("adapter does not exist");
+ adapter.getSessionPool().sessionValidate();
+ return adapterName + " | adapter session validate";
+ }
+ return "fail";
+ }
+
+ private String unescape(String string) {
+ string = string.replace("", "(b)").replace(" ", "(/b)");
+ string = string.replaceAll("", "(a$1)").replace(" ", "(/a)");
+ string = string.replaceAll("", "(font color='$1')").replace(" ", "(/font)");
+ string = string.replace(">", ">").replace("<", "<");
+ string = string.replace("(b)", "").replace("(/b)", " ");
+ string = string.replaceAll("\\(a( href=\\'[a-zA-Z0-9_/]+\\')\\)", "").replace("(/a)", " ");
+ string = string.replaceAll("\\(font color='([a-zA-Z0-9# ]+)'\\)", "").replace("(/font)", " ");
+ return string;
+ }
+ class StreamForNetstat extends Thread
+ {
+ InputStream is;
+ StringBuffer sb ;
+ ISocketAdapter adapter;
+ public StreamForNetstat(InputStream is,ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.is = is;
+ sb = new StringBuffer();
+ }
+
+ public void run()
+ {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ sb.append("\nnetstat ");
+ sb.append("\n");
+ String line;
+ while ((line = br.readLine()) != null) {
+ if (!line.trim().toUpperCase().startsWith("TCP") && !line.trim().toUpperCase().startsWith("UDP"))
+ continue;
+ String[] cols = line.trim().split("[ ]+");
+ String separator = Env.isWindows() ? ":" : ".";
+ if (Env.isWindows()) {
+ if (adapter.getContext().isServer()) {
+ if(!cols[1].endsWith(separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ } else {
+ if(!cols[2].equals(adapter.getContext().getHostName() + separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ }
+ } else {
+ if (adapter.getContext().isServer()) {
+ if(!cols[3].endsWith(separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ } else {
+ if(!cols[4].equals(adapter.getContext().getHostName() + separator + adapter.getContext().getPortNumber())) {
+ continue;
+ }
+ }
+ }
+ sb.append(" " + line + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ } catch (IOException ioe) {
+ logger.error("StreamForNetstat", ioe);
+ }
+ }
+ public String getData(){
+ return sb.toString();
+ }
+ }
+ class StreamForLsof extends Thread
+ {
+ InputStream is;
+ StringBuffer sb ;
+ public StreamForLsof(InputStream is) {
+ this.is = is;
+ sb = new StringBuffer();
+ }
+
+ public void run()
+ {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ sb.append("\nlsof ");
+ sb.append("\n");
+ String line = "";
+ while ((line = br.readLine()) != null) {
+// String[] cols = line.trim().split("[ ]+");
+// String separator = Env.isWindows() ? ":" : ".";
+ sb.append(" " + line + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ } catch (IOException ioe) {
+ logger.error("StreamForLsof", ioe);
+ }
+ }
+ public String getData(){
+ return sb.toString();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdaptersJsonServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdaptersJsonServlet.java
new file mode 100644
index 0000000..d5c53e0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdaptersJsonServlet.java
@@ -0,0 +1,364 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+import org.json.simple.JSONArray;
+
+import java.net.URLDecoder;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class AdaptersJsonServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String filter = request.getContext();
+ filter = filter.substring(filter.indexOf('/')+1);
+ if ("adaptersJson".equals(filter)) {
+ filter = null;
+ }
+
+ String result = "";
+ try {
+ result = list(filter);
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ if (!"".equals(request.getParameter("refresh"))) {
+ response.appendBody(" \n\n");
+ }
+
+ response.setContentType("text/html;charset=utf-8;");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+ }
+
+ private String list(String filter) {
+// boolean verbose = false;
+ //StringBuffer sb = new StringBuffer();
+ try{
+ filter = URLDecoder.decode(filter,"UTF-8");
+ }catch(Exception e){
+ if(filter != null) filter = filter.trim();
+ }
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) SocketAdapterManager.getInstance().getSocketAdapterGroups();
+ List list = new ArrayList();
+ String prevAdapterGroupName = "";
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+
+ for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ if (filter != null && adapter.getContext().getAdapterName().toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && adapter.getContext().getProtocol().toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && String.valueOf(adapter.getContext().getPortNumber()).toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && adapter.getContext().getDescription().indexOf(filter.toLowerCase()) == -1)
+ continue;
+
+ HashMap row = new HashMap();
+ row.put("adapterGroupName", adapterGroupName);
+ row.put("adapterName", adapter.getContext().getAdapterName());
+ row.put("state", adapter.getState().name());
+ if (Env.isWindows()) {
+ row.put("status", "");
+ }else{
+ row.put("status", getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
+
+ }
+ row.put("uptime", TimeUtil.formatDate(adapter.getUptime().getTime()));
+ if (adapter.getSessionPool() != null) {
+ row.put("pool", adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
+ }
+ row.put("recv", adapter.getMessageRecv());
+ row.put("send", adapter.getMessageSend());
+
+ row.put("error", adapter.getRecentErrorCount());
+
+ row.put("trace", adapter.getContext().getTraceLevel());
+
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(adapter.getContext().getProtocol());
+ sb.append(", " + adapter.getContext().getBoundUsage() );
+ sb.append(", " + adapter.getContext().getSocketType() );
+ if (adapter.getContext().isClient()) {
+ sb.append(" (" + adapter.getContext().getLocalHostName() + ":" + adapter.getContext().getLocalPortNumber());
+ sb.append("->");
+ sb.append("/" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber() + ")");
+ } else {
+ sb.append(" (" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber());
+ sb.append("<-)");
+ }
+ if(adapter.getContext().isSync()) {
+ sb.append(", SYNC");
+ } else {
+ sb.append(", ASYN");
+ }
+ if ("Y".equals(adapter.getContext().getAckSupport())) {
+ sb.append(", ACK");
+ } else {
+ sb.append(", NO_ACK");
+ }
+ if(adapter.getContext().isPermanent()) {
+ sb.append(", PERMANENT");
+ } else {
+ sb.append(", NON_PERM");
+ }
+ if(adapter.getContext().isBlocking()) {
+ sb.append(", BIO");
+ } else {
+ sb.append(", NIO");
+ }
+ sb.append(", max_conn:" + (adapter.getContext().getCloseExistingConnection() ? "-" : "") + adapter.getContext().getMaxConnection());
+ sb.append(", limit_per_ip:" + adapter.getContext().getConnLimitPerIp());
+ sb.append(", max_thread:" + adapter.getContext().getMaxThread());
+
+// switch(adapter.getContext().getTraceLevel()) {
+// case 0:
+// sb.append(", 0(DEFAULT)");
+// break;
+// case 1:
+// sb.append(", 1(INFO)");
+// break;
+// case 2:
+// sb.append(", 2(DEBUG)");
+// break;
+// case 3:
+// sb.append(", 3(TRACE)");
+// break;
+// }
+
+ if (adapter.getContext().isPollingUse()) {
+ sb.append("\n(");
+ sb.append("POLLING");
+ sb.append(", " + adapter.getContext().getPollingRole());
+ if (adapter.getContext().isPollingOneway()) {
+ sb.append(", oneway");
+ }
+ sb.append(", " + adapter.getContext().getPollingTimeout());
+// sb.append(", " + adapter.getContext().getPollingRequest());
+// sb.append(", " + adapter.getContext().getPollingRequestPattern());
+// sb.append(", " + adapter.getContext().getPollingReplacement());
+// sb.append(", " + adapter.getContext().getPollingResponsePattern());
+ sb.append(")");
+ }
+ //KSH
+ if (adapter.getContext().isInitMsgUse()) {
+ sb.append("\n(");
+ sb.append("INIT_MSG");
+ sb.append(", " + adapter.getContext().getInitMsgRole());
+ sb.append(")");
+ }
+
+ if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol()) //20130719 KSH
+ || "EGSEED".equals(adapter.getContext().getProtocol())
+ || "TCSEED".equals(adapter.getContext().getProtocol()) //20101213 JGY
+ || "ENVELOP".equals(adapter.getContext().getProtocol())
+ || "XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE2".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())
+ || "XC3EPB".equals(adapter.getContext().getProtocol())
+ ) {
+ sb.append("\n(");
+ sb.append("type=" + adapter.getContext().getLlFieldType());
+ sb.append(", offset=" + adapter.getContext().getLlFieldOffset());
+ sb.append(", length=" + adapter.getContext().getLlFieldLength());
+ sb.append(", ll.field.include=" + adapter.getContext().getLlFieldInclude());
+ sb.append(", ll.offset.exclude=" + adapter.getContext().getLlOffsetExclude());
+ sb.append(", ll.include=" + adapter.getContext().getLlInclude());
+ sb.append(")");
+ }
+
+ if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())) { // 20130719 KSH
+ sb.append("\n(");
+ sb.append("send.header.length=");
+ sb.append(adapter.getContext().getSendHeaderLength());
+ sb.append(", recv.header.length=");
+ sb.append(adapter.getContext().getRecvHeaderLength());
+ sb.append(")");
+ }
+
+ if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
+ || "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol()) // 20100515 JGY
+ || "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("send.payload.length=");
+ sb.append(adapter.getContext().getSendPayloadLength());
+ sb.append(", recv.payload.length=");
+ sb.append(adapter.getContext().getRecvPayloadLength());
+ sb.append(")");
+ }
+
+ if ("XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append(adapter.getContext().getXecureType());
+ sb.append(", " + adapter.getContext().getXecureConfigPath());
+ sb.append(", " + adapter.getContext().getXecureRemoteCert());
+ sb.append(")");
+ }
+ if ("XC3EPB".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("XC3EPB");
+ sb.append(", " + adapter.getContext().getXc3epbPassword());
+ sb.append(", " + adapter.getContext().getXc3epbConfigPath());
+ sb.append(")");
+ }
+
+ if ("INISAFE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("INISAFE");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("INISAFE_2020");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("INISAFE_NATN");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ // JGY 20100515
+ if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("INISAFE_PAYLOAD");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeIdPassword());
+ sb.append(")");
+ }
+
+ // JGY 20100423
+ if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("ENVELOP");
+ sb.append(", " + adapter.getContext().getEnvelopSigncertPath());
+ sb.append(", " + adapter.getContext().getEnvelopSignkeyPath());
+ sb.append(", " + adapter.getContext().getEnvelopPassword());
+ sb.append(")");
+ }
+
+ // JGY 20101213
+ if ("TCSEED".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n(");
+ sb.append("TCSEED");
+ sb.append(", " + adapter.getContext().getTcseedKeyStore());;
+ sb.append(")");
+ }
+
+ if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
+ sb.append("\n(" + adapter.getContext().getDescription() + ")");
+ }
+
+
+ row.put("data", sb.toString());
+
+ ArrayList normal = new ArrayList();
+ StringBuffer sessionsb = null;
+ for (Iterator iii = adapter.getSessionPool().iterator() ; iii.hasNext(); ) {
+ sessionsb = new StringBuffer();
+ IoSession session = (IoSession) iii.next();
+ if (!session.isConnected())
+ sessionsb.append("●");
+ else if (session.isClosing())
+ sessionsb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sessionsb.append("⊙");
+ else
+ sessionsb.append("○");
+ sessionsb.append(" Session :");;
+ if (session.isClosing())
+ sessionsb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sessionsb.append(" [NOT CONNECTED]");
+ sessionsb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sessionsb.append(", recv:" + session.getReadMessages());
+ sessionsb.append("(" + session.getReadBytes() + ")");
+ sessionsb.append(", send:" + session.getWrittenMessages());
+ sessionsb.append("(" + session.getWrittenBytes() + ")");
+ sessionsb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sessionsb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) );
+ normal.add(sessionsb.toString());
+ }
+ ArrayList delay = new ArrayList();
+ for (Iterator iii = adapter.getSessionPool().checkedOutIterator() ; iii.hasNext(); ) {
+ sessionsb = new StringBuffer();
+ IoSession session = (IoSession) iii.next();
+ if (!session.isConnected())
+ sessionsb.append("●");
+ else if (session.isClosing())
+ sessionsb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sessionsb.append("⊙");
+ else
+ sessionsb.append("○");
+ sessionsb.append(" Session :");;
+ if (session.isClosing())
+ sessionsb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sessionsb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sessionsb.append(", recv:" + session.getReadMessages());
+ sessionsb.append("(" + session.getReadBytes() + ")");
+ sessionsb.append(", send:" + session.getWrittenMessages());
+ sessionsb.append("(" + session.getWrittenBytes() + ")");
+ sessionsb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sessionsb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ delay.add(sessionsb.toString());
+ }
+ row.put("normal", normal);
+ row.put("delay", delay);
+ list.add(row);
+ prevAdapterGroupName = adapterGroupName;
+ }
+ }
+ JSONArray array = new JSONArray();
+ array.addAll(list);
+ return array.toJSONString();
+ }
+
+// private String prop() {
+// return "";
+// }
+
+ protected boolean getAdapterStatus(String adapterGroupName, String adapterName) {
+ AdapterManager manager = AdapterManager.getInstance();
+ AdapterVO vo = manager.getAdapterVO(adapterGroupName, adapterName);
+ if (vo != null) {
+ return vo.isStatus();
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdaptersServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdaptersServlet.java
new file mode 100644
index 0000000..78db6b0
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/AdaptersServlet.java
@@ -0,0 +1,387 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoSession;
+
+import java.net.URLDecoder;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class AdaptersServlet extends HttpServlet {
+ final static SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String filter = request.getContext();
+ filter = filter.substring(filter.indexOf('/')+1);
+ if ("adapters".equals(filter)) {
+ filter = null;
+ }
+
+ String result = "";
+ try {
+ result = list(filter);
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ if (!"".equals(request.getParameter("refresh"))) {
+ response.appendBody(" \n\n");
+ }
+
+ response.setContentType("text/html;charset=utf-8;");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+ }
+
+ private String list(String filter) {
+// boolean verbose = false;
+ StringBuffer sb = new StringBuffer();
+ try{
+ filter = URLDecoder.decode(filter,"UTF-8");
+ }catch(Exception e){
+ if(filter != null) filter = filter.trim();
+ }
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) SocketAdapterManager.getInstance().getSocketAdapterGroups();
+
+ String prevAdapterGroupName = "";
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+
+ for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ if (filter != null && adapter.getContext().getAdapterName().toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && adapter.getContext().getProtocol().toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && String.valueOf(adapter.getContext().getPortNumber()).toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && adapter.getContext().getDescription().indexOf(filter.toLowerCase()) == -1)
+ continue;
+
+ if (!adapterGroupName.equals(prevAdapterGroupName)) {
+ sb.append("ⓖ " + adapterGroupName);
+ sb.append("\n");
+ }
+
+ sb.append(" ⓐ ");
+ sb.append(adapter.getContext().getAdapterName());
+ sb.append(" ");
+
+ sb.append(" (");
+ if ("STARTED".equals(adapter.getState().name())) {
+ sb.append(adapter.getState().name());
+ } else {
+ sb.append("" + adapter.getState().name() + " ");
+ }
+ if (!Env.isWindows()) {
+ sb.append(", " + getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
+ }
+ sb.append(")");
+
+ sb.append(" uptime:" + TimeUtil.formatDate(adapter.getUptime().getTime()));
+ if (adapter.getSessionPool() != null) {
+ sb.append(", pool:" + adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
+ }
+ sb.append(", recv:" + "" + adapter.getMessageRecv() + " ");
+ sb.append(", send:" + "" + adapter.getMessageSend() + " ");
+ if (adapter.getRecentErrorCount() > 0) {
+ sb.append(", ");
+ sb.append("");
+ sb.append("error:" + adapter.getRecentErrorCount());
+ sb.append(" ");
+ } else {
+ sb.append(", error:" + adapter.getRecentErrorCount());
+ }
+
+ sb.append(" (start ");
+ sb.append("|stop )");
+// sb.append(" sessionValidate ");
+
+ sb.append("\n ");
+ sb.append("");
+ sb.append("");
+ sb.append(adapter.getContext().getProtocol());
+ sb.append(" ");
+ sb.append(", " + adapter.getContext().getBoundUsage() + " ");
+ sb.append(", " + adapter.getContext().getSocketType() + " ");
+ if (adapter.getContext().isClient()) {
+ sb.append(" (" + adapter.getContext().getLocalHostName() + ":" + adapter.getContext().getLocalPortNumber());
+ sb.append("->");
+ sb.append("/" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber() + ")");
+ } else {
+ sb.append(" (" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber());
+ sb.append("<-)");
+ }
+ if(adapter.getContext().isSync()) {
+ sb.append(", SYNC ");
+ } else {
+ sb.append(", ASYN ");
+ }
+ if ("Y".equals(adapter.getContext().getAckSupport())) {
+ sb.append(", ACK");
+ } else {
+ sb.append(", NO_ACK");
+ }
+ if(adapter.getContext().isPermanent()) {
+ sb.append(", PERMANENT ");
+ } else {
+ sb.append(", NON_PERM ");
+ }
+ if(adapter.getContext().isBlocking()) {
+ sb.append(", BIO ");
+ } else {
+ sb.append(", NIO");
+ }
+ sb.append(", max_conn:" + (adapter.getContext().getCloseExistingConnection() ? "-" : "") + adapter.getContext().getMaxConnection());
+ sb.append(", limit_per_ip:" + adapter.getContext().getConnLimitPerIp());
+ sb.append(", max_thread:" + adapter.getContext().getMaxThread());
+
+ switch(adapter.getContext().getTraceLevel()) {
+ case 0:
+ sb.append(", 0(DEFAULT)");
+ break;
+ case 1:
+ sb.append(", 1(INFO)");
+ break;
+ case 2:
+ sb.append(", 2(DEBUG)");
+ break;
+ case 3:
+ sb.append(", 3(TRACE)");
+ break;
+ }
+
+ if (adapter.getContext().isPollingUse()) {
+ sb.append("\n (");
+ sb.append("POLLING ");
+ sb.append(", " + adapter.getContext().getPollingRole());
+ if (adapter.getContext().isPollingOneway()) {
+ sb.append(", oneway");
+ }
+ sb.append(", " + adapter.getContext().getPollingTimeout());
+// sb.append(", " + adapter.getContext().getPollingRequest());
+// sb.append(", " + adapter.getContext().getPollingRequestPattern());
+// sb.append(", " + adapter.getContext().getPollingReplacement());
+// sb.append(", " + adapter.getContext().getPollingResponsePattern());
+ sb.append(")");
+ }
+ //KSH
+ if (adapter.getContext().isInitMsgUse()) {
+ sb.append("\n (");
+ sb.append("INIT_MSG ");
+ sb.append(", " + adapter.getContext().getInitMsgRole());
+ sb.append(")");
+ }
+
+ if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol()) //20130719 KSH
+ || "EGSEED".equals(adapter.getContext().getProtocol())
+ || "TCSEED".equals(adapter.getContext().getProtocol()) //20101213 JGY
+ || "ENVELOP".equals(adapter.getContext().getProtocol())
+ || "XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE2".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())
+ || "XC3EPB".equals(adapter.getContext().getProtocol())
+ ) {
+ sb.append("\n (");
+ sb.append("type=" + adapter.getContext().getLlFieldType());
+ sb.append(", offset=" + adapter.getContext().getLlFieldOffset());
+ sb.append(", length=" + adapter.getContext().getLlFieldLength());
+ sb.append(", ll.field.include=" + adapter.getContext().getLlFieldInclude());
+ sb.append(", ll.offset.exclude=" + adapter.getContext().getLlOffsetExclude());
+ sb.append(", ll.include=" + adapter.getContext().getLlInclude());
+ sb.append(")");
+ }
+
+ if ("VARIABLE_LENGTH_HEADER".equals(adapter.getContext().getProtocol())) { // 20130719 KSH
+ sb.append("\n (");
+ sb.append("send.header.length=");
+ sb.append(adapter.getContext().getSendHeaderLength());
+ sb.append(", recv.header.length=");
+ sb.append(adapter.getContext().getRecvHeaderLength());
+ sb.append(")");
+ }
+
+ if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
+ || "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol()) // 20100515 JGY
+ || "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("send.payload.length=");
+ sb.append(adapter.getContext().getSendPayloadLength());
+ sb.append(", recv.payload.length=");
+ sb.append(adapter.getContext().getRecvPayloadLength());
+ sb.append(")");
+ }
+
+ if ("XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("");
+ sb.append(adapter.getContext().getXecureType());
+ sb.append(" ");
+ sb.append(", " + adapter.getContext().getXecureConfigPath());
+ sb.append(", " + adapter.getContext().getXecureRemoteCert());
+ sb.append(")");
+ }
+ if ("XC3EPB".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("XC3EPB");
+ sb.append(", " + adapter.getContext().getXc3epbPassword());
+ sb.append(", " + adapter.getContext().getXc3epbConfigPath());
+ sb.append(")");
+ }
+ if ("INISAFE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE_2020 ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE_NATN ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ // JGY 20100515
+ if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE_PAYLOAD ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeIdPassword());
+ sb.append(")");
+ }
+
+ // JGY 20100423
+ if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("ENVELOP ");
+ sb.append(", " + adapter.getContext().getEnvelopSigncertPath());
+ sb.append(", " + adapter.getContext().getEnvelopSignkeyPath());
+ sb.append(", " + adapter.getContext().getEnvelopPassword());
+ sb.append(")");
+ }
+
+ // JGY 20101213
+ if ("TCSEED".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("TCSEED ");
+ sb.append(", " + adapter.getContext().getTcseedKeyStore());;
+ sb.append(")");
+ }
+
+ if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
+ sb.append("\n (" + adapter.getContext().getDescription() + ")");
+ }
+
+ sb.append(" ");
+
+ sb.append("\n");
+ for (Iterator iii = adapter.getSessionPool().iterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");;
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) );
+
+// InetSocketAddress local =(InetSocketAddress)session.getLocalAddress();
+// InetSocketAddress remote =(InetSocketAddress)session.getRemoteAddress();
+// sb.append(", remove session " );
+ sb.append("\n");
+ }
+ sb.append(" ");
+
+ sb.append("\n");
+ for (Iterator iii = adapter.getSessionPool().checkedOutIterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");;
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ prevAdapterGroupName = adapterGroupName;
+ }
+ }
+
+ return "" + sb.toString() + " ";
+ }
+
+// private String prop() {
+// return "";
+// }
+
+ protected boolean getAdapterStatus(String adapterGroupName, String adapterName) {
+ AdapterManager manager = AdapterManager.getInstance();
+ AdapterVO vo = manager.getAdapterVO(adapterGroupName, adapterName);
+ if (vo != null) {
+ return vo.isStatus();
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/CheckServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/CheckServlet.java
new file mode 100644
index 0000000..f0490b4
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/CheckServlet.java
@@ -0,0 +1,201 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.*;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class CheckServlet extends HttpServlet {
+ final static SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String option = request.getContext();
+ if (option.lastIndexOf('/') == -1) {
+ option = "";
+ } else {
+ option = option.substring(option.indexOf('/')+1);
+ }
+
+ String result = show("full".equals(option));
+
+ response.setContentType("text/xml");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody("\n");
+ response.appendBody(result); //.getBytes("UTF-8"));
+ }
+
+ private String show(boolean checkConnect) throws Exception {
+ Document document = DocumentHelper.createDocument();
+ Element root = document.addElement("adapters");
+
+ /**
+ * [1] Socket Adapter
+ */
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) SocketAdapterManager.getInstance().getSocketAdapterGroups();
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+
+ for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ Element adapterNode = root.addElement("adapter");
+ adapterNode.addElement("name").addText(adapter.getContext().getAdapterName());
+ adapterNode.addElement("type").addText("socket");
+ adapterNode.addElement("group").addText(adapterGroupName);
+ adapterNode.addElement("desc").addText(adapter.getContext().getDescription());
+
+ /**
+ * status
+ */
+ String cause = "";
+ if (adapter.getContext().isServer()) {
+ if (adapter.getState() == ISocketAdapter.State.STARTED) {
+ if (adapter.getContext().isPermanent()) {
+ if (adapter.getSessionPool().peekSize() > 0) {
+ adapterNode.addElement("status").addText("O");
+ } else {
+ adapterNode.addElement("status").addText("X");
+ cause = "SERVER/PERMANENT - no established session";
+ }
+ } else {
+ adapterNode.addElement("status").addText("O");
+ }
+ } else {
+ adapterNode.addElement("status").addText("X");
+ cause = "SERVER - adapter not started, adapter status = " + adapter.getState().name();
+ }
+ } else {
+ if (adapter.getState() == ISocketAdapter.State.STARTED) {
+ if (adapter.getContext().isPermanent()) {
+ if (adapter.getSessionPool().peekSize() > 0) {
+ adapterNode.addElement("status").addText("O");
+ } else {
+ adapterNode.addElement("status").addText("X");
+ cause = "CLIENT/PERMANENT - no established session";
+ }
+ } else {
+ try {
+ checkRemote(adapter.getContext().getHostName(), adapter.getContext().getPortNumber(), checkConnect);
+ adapterNode.addElement("status").addText("O");
+ } catch(Exception ex) {
+ adapterNode.addElement("status").addText("X");
+ cause = "CLIENT/NON-PERM - cannot connect remote server - " + ex.getMessage();
+ }
+ }
+ } else {
+ if ("INISAFE".equals(adapter.getContext().getProtocol())) {
+ adapterNode.addElement("status").addText("O");
+ }
+ else if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
+ adapterNode.addElement("status").addText("O");
+ }
+ else if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
+ adapterNode.addElement("status").addText("O");
+ }
+ else {
+ adapterNode.addElement("status").addText("X");
+ cause = "CLIENT - adapter not started, adapter status = " + adapter.getState().name();
+ }
+ }
+ }
+
+ adapterNode.addElement("cause").addText(cause);
+ }
+ }
+
+ /**
+ * [2] Http Adapter
+ */
+ List groups = AdapterManager.getInstance().getAllAdapterGroupNames();
+ for (Iterator iter = groups.iterator(); iter.hasNext();) {
+ String groupName = (String) iter.next();
+ AdapterGroupVO groupVO = AdapterManager.getInstance().getAdapterGroupVO(groupName);
+
+ if (!"HTT".equals(groupVO.getType())
+ && !"HQS".equals(groupVO.getType())
+ && !"HXC".equals(groupVO.getType())) {
+ continue;
+ }
+
+ for (Iterator iter2 = groupVO.getAdapters() ; iter2.hasNext() ;) {
+ AdapterVO adapterVO = (AdapterVO) iter2.next();
+ //PropGroupVO propGroupVO = PropManager.getInstance().getPropGroupVO(adapterVO.getPropGroupName());
+ AdapterPropGroupVO propGroupVO = AdapterPropManager.getInstance().getAdapterPropGroupVO(adapterVO.getPropGroupName());
+ Element adapterNode = root.addElement("adapter");
+ adapterNode.addElement("name").addText(adapterVO.getName());
+ adapterNode.addElement("type").addText("http");
+ adapterNode.addElement("group").addText(groupName);
+ adapterNode.addElement("desc").addText(adapterVO.getDescription());
+
+ //adapterNode.addElement("status").addText(adapterVO.getListenerClass());
+ //adapterNode.addElement("cause").addText(adapterVO.getPropGroupName());
+
+ /**
+ * status
+ */
+ String cause = "";
+ if ("I".equals(groupVO.getGubun())) {
+ if (adapterVO.isStatus()) {
+ adapterNode.addElement("status").addText("O");
+ } else {
+ adapterNode.addElement("status").addText("X");
+ }
+ } else {
+ if (adapterVO.isStatus()) {
+ String urlString = propGroupVO.getProperty("URL");
+ try {
+ URL url = new URL(urlString);
+ checkRemote(url.getHost(), url.getPort(), checkConnect);
+ adapterNode.addElement("status").addText("O");
+ } catch(SocketTimeoutException ex) {
+ adapterNode.addElement("status").addText("X");
+ cause = "CLIENT - cannot connect remote server - " + urlString;
+ } catch(Exception ex) {
+ adapterNode.addElement("status").addText("X");
+ cause = ex.getMessage();
+ }
+ } else {
+ adapterNode.addElement("status").addText("X");
+ }
+ }
+
+ adapterNode.addElement("cause").addText(cause);
+ }
+ }
+
+ return root.asXML();
+ }
+
+ private boolean checkRemote(String host, int port, boolean checkConnect) throws Exception {
+ if (!checkConnect) {
+ return true;
+ }
+
+ Socket socket = null;
+ try {
+ socket = new Socket();
+ socket.connect(new InetSocketAddress(host, port), 2000);
+ return true;
+ } finally {
+ if (socket != null)
+ try { socket.close(); } catch(Exception e) {}
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ControlServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ControlServlet.java
new file mode 100644
index 0000000..c649476
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ControlServlet.java
@@ -0,0 +1,197 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URLDecoder;
+
+public class ControlServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String command = request.getContext();
+ if (command.lastIndexOf('/') == -1) {
+ command = "";
+ } else {
+ command = command.substring(command.indexOf('/')+1);
+ }
+ String result = "";
+ try {
+ if (command == null || "".equals(command) || "list".equals(command)) {
+ result += list(request.getParameter("adapter"));
+ } else if (command.startsWith("start")) {
+ result += start(request.getParameter("adapter"));
+ } else if (command.startsWith("stop")) {
+ result += stop(request.getParameter("adapter"));
+ } else if (command.startsWith("free")) {
+ result += free(request.getParameter("adapter"));
+ } else {
+ response.setResponseCode(404);
+ return;
+ }
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+// if (!"".equals(request.getParameter("refresh"))) {
+// response.appendBody(" \n\n");
+// }
+
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+
+ }
+
+ private String list(String filter) {
+// boolean verbose = false;
+// StringBuffer sb = new StringBuffer();
+ try{
+ filter = URLDecoder.decode(filter,"UTF-8");
+ }catch(Exception e){
+ filter = null;
+ }
+ if (filter == null){
+ return cmd(" ps -ef | grep tcp ");
+ }else{
+ return cmd(" ps -ef | grep tcp | grep "+filter);
+ }
+ }
+ private String free(String filter) {
+// boolean verbose = false;
+// StringBuffer sb = new StringBuffer();
+ try{
+ filter = URLDecoder.decode(filter,"UTF-8");
+ }catch(Exception e){
+ filter = null;
+ }
+ if (filter == null){
+ return "";
+ }else{
+ return cmd(filter);
+ }
+ }
+ private String start(String filter) {
+// boolean verbose = false;
+// StringBuffer sb = new StringBuffer();
+ try{
+ filter = URLDecoder.decode(filter,"UTF-8");
+ }catch(Exception e){
+ filter = null;
+ }
+ if (filter == null){
+ return "";
+ }else{
+ return cmd(" devstart "+filter);
+ }
+ }
+ private String stop(String filter) {
+// boolean verbose = false;
+// StringBuffer sb = new StringBuffer();
+ try{
+ filter = URLDecoder.decode(filter,"UTF-8");
+ }catch(Exception e){
+ filter = null;
+ }
+ if (filter == null){
+ return "";
+ }else{
+ return cmd(" devstop "+filter);
+ }
+ }
+
+ private String cmd(String command){
+
+ StringBuffer sb = new StringBuffer();
+ try {
+ String[] cmd = new String[] {"sh", "-c", command};
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec(cmd);
+
+// Process process = new ProcessBuilder(cmd).start();
+
+ StreamGobbler gb1 = new StreamGobbler(process.getInputStream());
+ StreamGobbler gb2 = new StreamGobbler(process.getErrorStream());
+ gb1.start();
+ gb2.start();
+
+ while (true) {
+ if (!gb1.isAlive() && !gb2.isAlive()) { //두개의 스레드가 정지할면 프로세스 종료때까지 기다린다.
+ process.waitFor();
+ sb.append(gb1.getData());
+ break;
+ }
+ }
+
+// InputStream is = process.getInputStream();
+// InputStreamReader isr = new InputStreamReader(is);
+// BufferedReader br = new BufferedReader(isr);
+// int result = process.waitFor();
+// sb.append("");
+// String line;
+// while ((line = br.readLine()) != null) {
+// sb.append("");
+// sb.append( line + "\n");
+// sb.append("
");
+// }
+// sb.append(" ");
+ } catch(Exception e) {
+ // ignore
+ sb.append("cmd failed");
+ }
+ return sb.toString();
+ }
+// private String prop() {
+// return "";
+// }
+
+ protected boolean getAdapterStatus(String adapterGroupName, String adapterName) {
+ AdapterManager manager = AdapterManager.getInstance();
+ AdapterVO vo = manager.getAdapterVO(adapterGroupName, adapterName);
+ if (vo != null) {
+ return vo.isStatus();
+ }
+ return false;
+ }
+ class StreamGobbler extends Thread
+ {
+ InputStream is;
+ StringBuffer sb ;
+ public StreamGobbler(InputStream is) {
+ this.is = is;
+ sb = new StringBuffer();
+ }
+
+ public void run()
+ {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ sb.append("");
+ String line;
+ while ((line = br.readLine()) != null) {
+ sb.append("");
+ sb.append( line + "\n");
+ sb.append("
");
+ }
+ sb.append(" ");
+ } catch (IOException ioe) {
+ logger.info("run error - "+ ioe.toString());
+ }
+ }
+ public String getData(){
+ return sb.toString();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ErrorServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ErrorServlet.java
new file mode 100644
index 0000000..311610d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ErrorServlet.java
@@ -0,0 +1,83 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.SocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+
+public class ErrorServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+ static String uptime = TimeUtil.formatDate(System.currentTimeMillis());
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String filter = request.getContext();
+ filter = filter.substring(filter.indexOf('/')+1);
+ if ("error".equals(filter)) {
+ filter = null;
+ }
+
+ String result = "";
+
+ try {
+ result = error(filter);
+ } catch(Throwable e) {
+ result = ExceptionStackTrace.dump(e);
+ }
+
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody("uptime : " + uptime + " ");
+ response.appendBody(" ");
+ response.appendBody("socket adapters ");
+ response.appendBody("socket zombies | ");
+ response.appendBody("http adapters | ");
+// response.appendBody("socket adapters error | ");
+ //2020.03.04 링크추가요청반영
+ response.appendBody("layout ");
+ response.appendBody("transform ");
+ response.appendBody("transformer/error ");
+ response.appendBody(" ");
+ response.appendBody(result);
+ }
+
+ final static String SCRIPT =
+ " \n";
+
+ private String error(String filter) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ String[] errors = SocketAdapter.getGlobalErrors();
+
+ sb.append(SCRIPT);
+ sb.append("socket adapter global errors ");
+ for (int i=errors.length-1; i>=0; i--) {
+ if (filter != null && errors[i].toLowerCase().indexOf(filter.toLowerCase()) == -1) {
+ continue;
+ }
+
+ sb.append("");
+ sb.append("
");
+ sb.append(errors[i].replace(">", ">").replace("<", "<"));
+ sb.append(" ");
+ sb.append("
");
+ sb.append("
");
+ }
+ return sb.toString();
+
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/FileServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/FileServlet.java
new file mode 100644
index 0000000..fcc9f3f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/FileServlet.java
@@ -0,0 +1,62 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+
+public class FileServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String fname = request.getContext();
+ fname = fname.substring(fname.indexOf('/')+1);
+ if ("file".equals(fname)) {
+ fname = null;
+ }
+
+ String result = "";
+ try {
+ result = fread(fname);
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+
+ }
+
+ private String fread(String fname) throws Exception {
+ StringBuilder sb = new StringBuilder();
+ BufferedReader in = new BufferedReader(new FileReader(fname));
+ try {
+ sb.append("");
+ String line;
+ while ((line = in.readLine()) != null) {
+ sb.append(line + "\n");
+ }
+ sb.append(" ");
+ }
+ catch(Exception e) {
+ logger.error(e);
+ }
+ finally {
+ try {
+ if(in != null) in.close();
+ }
+ catch(Exception e) {
+ logger.error(e);
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/GroovyServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/GroovyServlet.java
new file mode 100644
index 0000000..93dd245
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/GroovyServlet.java
@@ -0,0 +1,56 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+import groovy.lang.Binding;
+import groovy.lang.GroovyShell;
+
+public class GroovyServlet extends HttpServlet {
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String method = request.getHeader("Method")[0];
+ if ("GET".equals(method)) {
+ doGet(request, response);
+ } else {
+ doPost(request, response);
+ }
+ }
+
+ protected void doGet(HttpRequest request, HttpResponse response) throws Exception {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("");
+
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(sb.toString());
+ }
+
+ protected void doPost(HttpRequest request, HttpResponse response) throws Exception {
+// System.out.println(request.getParameter(""));
+
+ StringBuilder sb = new StringBuilder();
+
+ Binding binding = new Binding();
+ binding.setVariable("request", request);
+ binding.setVariable("response", request);
+ GroovyShell shell = new GroovyShell(binding);
+
+ shell.evaluate(request.getParameter(""));
+ //return (byte[]) binding.getVariable("response");
+
+ sb.append(request);
+
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(sb.toString());
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/MemoryServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/MemoryServlet.java
new file mode 100644
index 0000000..8e1a331
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/MemoryServlet.java
@@ -0,0 +1,37 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+
+import java.text.DecimalFormat;
+
+public class MemoryServlet extends HttpServlet {
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody("");
+ response.appendBody(memoryStat());
+ response.appendBody(" ");
+ }
+
+ private String memoryStat() throws Exception {
+ Runtime rt = Runtime.getRuntime();
+ long total = rt.totalMemory();
+ long free = rt.freeMemory();
+ long max = rt.maxMemory();
+
+ DecimalFormat df = new DecimalFormat("###,###,###");;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("total : %15s B\n", df.format(total)));
+ sb.append(String.format(" used : %15s B\n", df.format(total-free)));
+ sb.append(String.format(" free : %15s B\n", df.format(free)));
+ sb.append(String.format(" max : %15s B\n", df.format(max)));
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/PropServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/PropServlet.java
new file mode 100644
index 0000000..964bab2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/PropServlet.java
@@ -0,0 +1,73 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+public class PropServlet extends HttpServlet {
+ final static SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String fname = request.getContext();
+ fname = fname.substring(fname.indexOf('/')+1);
+ if ("file".equals(fname)) {
+ fname = null;
+ }
+
+ String result = "";
+ try {
+ result = fread(fname);
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+
+ }
+
+ private String fread(String fname) throws Exception {
+ StringBuilder sb = new StringBuilder();
+ URL url = ISocketAdapter.class.getResource("adapter_properties.txt");
+ sb.append("");
+ if(url == null) {
+ sb.append("url is null");
+ }
+ else {
+ BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
+
+ String line;
+
+ try {
+ while ((line = in.readLine()) != null) {
+ sb.append(line + "\n");
+ }
+ }
+ catch(Exception e) {
+ logger.error("fread error", e);
+ }
+ finally {
+ try {
+ if(in != null) in.close();
+ }
+ catch(Exception e) {
+ logger.warn(e.toString());
+ }
+ }
+ }
+
+ sb.append(" ");
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ThreadDumpUtil.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ThreadDumpUtil.java
new file mode 100644
index 0000000..0aa0972
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ThreadDumpUtil.java
@@ -0,0 +1,153 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import java.util.Arrays;
+import java.util.Hashtable;
+
+
+public class ThreadDumpUtil {
+ @SuppressWarnings("deprecation")
+ public static void kill(String threadName) {
+ ThreadGroup it = Thread.currentThread().getThreadGroup();
+ Thread[] threads = new Thread[it.activeCount()] ;
+ it.enumerate(threads);
+ for (int i=0; i
");
+
+ Thread[] threads = new Thread[it.activeCount()] ;
+ //sb.append("thread count : " + it.activeCount() + "
");
+ it.enumerate(threads);
+ sb.append("
");
+
+ String[] threadNames = new String[threads.length];
+ for (int i=0; i");
+ //sb.append(getStackTrace(threads[i]));
+ sb.append(getStackTrace(thread));
+ sb.append("");
+ }
+ filterThreadCount++;
+ }
+ sb.append("
");
+
+ StringBuilder sbb = new StringBuilder();
+ sbb.append("thread count : " + filterThreadCount + " / " + it.activeCount() + " ");
+ sbb.append(sb);
+ return sbb.toString();
+ }
+
+ static public String getStackTrace(Thread thread) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("■ \"" + thread.getName() + " \" ");
+ sb.append("prio=" + thread.getPriority() + " ");
+ sb.append(thread.isDaemon() ? "daemon " : " ");
+
+ StackTraceElement stack[] = thread.getStackTrace();
+
+ if (stack==null || stack.length<1)
+ return sb.toString();
+
+ if (stack[0].getMethodName().equals("wait"))
+ sb.append("wait ");
+ else if (stack[0].getMethodName().equals("sleep"))
+ sb.append("sleep ");
+ else
+ sb.append("running or blocked ");
+
+ //sb.append(" (kill )");
+ sb.append("\n");
+
+ for (int i=0; iat ");
+ else
+ sb.append(" at ");
+ sb.append(className + "." + methodName);
+ sb.append("(" + filename + ":" + (isNativeMethod ? "native" : String.valueOf(line)) + ")");
+ if (className.startsWith("java")
+ || className.startsWith("org.")
+ || className.startsWith("sun.")
+ || className.startsWith("com.sun.")
+ || className.startsWith("edu.emory."))
+ sb.append("");
+ sb.append("\n");
+ }
+
+ if (stack[0].getMethodName().equals("wait"))
+ return "" + sb.toString() + " ";
+ else if (stack[0].getMethodName().equals("sleep"))
+ return "" + sb.toString() + " ";
+ else
+ return "" + sb.toString() + " ";
+ }
+
+
+// static public String dump() {
+// StringBuffer sb = new StringBuffer();
+// ThreadGroup it = Thread.currentThread().getThreadGroup();
+// sb.append("[group] " + it.getName() + "\n");
+// Thread[] threads = new Thread[it.activeCount()] ;
+// sb.append("active count : "+it.activeCount() + "\n");
+// it.enumerate(threads);
+//
+// //----------------------------------------------------------------------
+// ///*
+// String[] threadNames = new String[threads.length];
+// for (int i=0; i" + ThreadDumpUtil.dump(filter) + "");
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ZombieAdaptersServlet.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ZombieAdaptersServlet.java
new file mode 100644
index 0000000..7161fd5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/http/servlet/ZombieAdaptersServlet.java
@@ -0,0 +1,402 @@
+package com.eactive.eai.adapter.socket2.protocol.http.servlet;
+
+import java.net.URLDecoder;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.temporal.ChronoField;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.mina.common.IoSession;
+
+import com.eactive.eai.adapter.AdapterManager;
+import com.eactive.eai.adapter.AdapterVO;
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
+import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
+import com.eactive.eai.common.util.Logger;
+
+public class ZombieAdaptersServlet extends HttpServlet {
+ static final SocketAdapterManager manager = SocketAdapterManager.getInstance();
+ static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
+
+ protected void doService(HttpRequest request, HttpResponse response) throws Exception {
+ String filter = request.getContext();
+ filter = filter.substring(filter.indexOf('/')+1);
+ if ("zombies".equals(filter)) {
+ filter = null;
+ }
+
+ String result = "";
+ try {
+ result = list(filter);
+ } catch(Throwable e) {
+ result = "" + ExceptionStackTrace.dump(e) + " ";
+ }
+
+ if (!"".equals(request.getParameter("refresh"))) {
+ response.appendBody(" \n\n");
+ }
+
+ response.setContentType("text/html");
+ response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
+ response.appendBody(result);
+ }
+ public static String getDate(String flagDate, int time) throws Exception {
+ ZonedDateTime nowDateTime = ZonedDateTime.now();
+ DateTimeFormatter fmt = new DateTimeFormatterBuilder()
+ .appendPattern("MM-dd HH:mm:ss")
+ .parseDefaulting(ChronoField.YEAR,Long.parseLong(DateTimeFormatter.ofPattern("yyyy").format(nowDateTime)))
+ .toFormatter();
+
+ LocalDateTime ldt = LocalDateTime.parse(flagDate,fmt).plusMinutes(time);
+ ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
+ return fmt.format(zdt);
+ }
+ public static long getParseDate(String flagDate) throws Exception {
+ ZonedDateTime nowDateTime = ZonedDateTime.now();
+ DateTimeFormatter fmt = new DateTimeFormatterBuilder()
+ .appendPattern("MM-dd HH:mm:ss")
+ .parseDefaulting(ChronoField.YEAR,Long.parseLong(DateTimeFormatter.ofPattern("yyyy").format(nowDateTime)))
+ .toFormatter();
+
+ LocalDateTime ldt = LocalDateTime.parse(flagDate,fmt);
+ return ldt.toInstant(OffsetDateTime.now().getOffset()).toEpochMilli();
+ }
+
+ private String list(String filter) throws Exception {
+// boolean verbose = false;
+ StringBuilder sb = new StringBuilder();
+ try{
+ filter = URLDecoder.decode(filter,"UTF-8");
+ }catch(Exception e){
+ logger.warn("URLDecoder.decode error", e);
+ }
+ ConcurrentHashMap adapterGroups = (ConcurrentHashMap) SocketAdapterManager.getInstance().getSocketAdapterGroups();
+
+ String prevAdapterGroupName = "";
+ for (Enumeration e = adapterGroups.keys(); e.hasMoreElements();) {
+ String adapterGroupName = (String) e.nextElement();
+ ConcurrentHashMap adapters = (ConcurrentHashMap) adapterGroups.get(adapterGroupName);
+
+ for (Enumeration ee = adapters.elements() ; ee.hasMoreElements() ;) {
+ ISocketAdapter adapter = (ISocketAdapter) ee.nextElement();
+ if(adapter == null) continue;
+ if (filter != null && adapter.getContext().getAdapterName().toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && adapter.getContext().getProtocol().toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && String.valueOf(adapter.getContext().getPortNumber()).toLowerCase().indexOf(filter.toLowerCase()) == -1
+ && adapter.getContext().getDescription().indexOf(filter.toLowerCase()) == -1)
+ continue;
+
+ ISocketAdapter adapter_imsi = manager.getSocketAdapter(adapterGroupName + "." + adapter.getContext().getAdapterName());
+
+ if (adapter_imsi != null){
+ if((adapter.getRecentErrorCount() < 3)|| ("CLIENT".equals((adapter_imsi.getContext().getSocketType())))){
+ continue;
+ }
+ String currentTime = DateTimeFormatter.ofPattern("MM-dd HH:mm:ss").format(ZonedDateTime.now());
+ String flagTime = getDate(currentTime,-10);
+ String[] errors = adapter_imsi.getRecentErrors();
+ String errMsg = errors[errors.length-1];
+ String errTime = errMsg.substring(1,15);
+ long errDate = getParseDate(errTime);
+ long flagDate = getParseDate(flagTime);
+
+ //10분 이내 에러난 것과, connection.limit.per.ip 에러가 아닌건 모두다 pass
+ if (errDate-flagDate < 0 || errMsg.indexOf("limit") < 0){
+ continue;
+ }
+ }
+
+ if (!adapterGroupName.equals(prevAdapterGroupName)) {
+ sb.append("ⓖ " + adapterGroupName);
+ sb.append("\n");
+ }
+
+ sb.append(" ⓐ ");
+ sb.append(adapter.getContext().getAdapterName());
+ sb.append(" ");
+
+ sb.append(" (");
+ if ("STARTED".equals(adapter.getState().name())) {
+ sb.append(adapter.getState().name());
+ } else {
+ sb.append("" + adapter.getState().name() + " ");
+ }
+ if (!Env.isWindows()) {
+ sb.append(", " + getAdapterStatus(adapterGroupName, adapter.getContext().getAdapterName()));
+ }
+ sb.append(")");
+
+ sb.append(" uptime:" + TimeUtil.formatDate(adapter.getUptime().getTime()));
+ if (adapter.getSessionPool() != null) {
+ sb.append(", pool:" + adapter.getSessionPool().remaining() + "/" + (adapter.getSessionPool().peekSize()));
+ }
+ sb.append(", recv:" + "" + adapter.getMessageRecv() + " ");
+ sb.append(", send:" + "" + adapter.getMessageSend() + " ");
+ if (adapter.getRecentErrorCount() > 0) {
+ sb.append(", ");
+ sb.append("");
+ sb.append("error:" + adapter.getRecentErrorCount());
+ sb.append(" ");
+ } else {
+ sb.append(", error:" + adapter.getRecentErrorCount());
+ }
+
+ sb.append(" (start ");
+ sb.append("|stop )");
+
+ sb.append("\n ");
+ sb.append("");
+ sb.append("");
+ sb.append(adapter.getContext().getProtocol());
+ sb.append(" ");
+ sb.append(", " + adapter.getContext().getBoundUsage() + " ");
+ sb.append(", " + adapter.getContext().getSocketType() + " ");
+ if (adapter.getContext().isClient()) {
+ sb.append(" (" + adapter.getContext().getLocalHostName() + ":" + adapter.getContext().getLocalPortNumber());
+ sb.append("->");
+ sb.append("/" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber() + ")");
+ } else {
+ sb.append(" (" + adapter.getContext().getHostName() + ":" + adapter.getContext().getPortNumber());
+ sb.append("<-)");
+ }
+ if(adapter.getContext().isSync()) {
+ sb.append(", SYNC ");
+ } else {
+ sb.append(", ASYN ");
+ }
+ if ("Y".equals(adapter.getContext().getAckSupport())) {
+ sb.append(", ACK");
+ } else {
+ sb.append(", NO_ACK");
+ }
+ if(adapter.getContext().isPermanent()) {
+ sb.append(", PERMANENT ");
+ } else {
+ sb.append(", NON_PERM ");
+ }
+ if(adapter.getContext().isBlocking()) {
+ sb.append(", BIO ");
+ } else {
+ sb.append(", NIO");
+ }
+ sb.append(", max_conn:" + (adapter.getContext().getCloseExistingConnection() ? "-" : "") + adapter.getContext().getMaxConnection());
+ sb.append(", limit_per_ip:" + adapter.getContext().getConnLimitPerIp());
+ sb.append(", max_thread:" + adapter.getContext().getMaxThread());
+
+ switch(adapter.getContext().getTraceLevel()) {
+ case 0:
+ sb.append(", 0(DEFAULT)");
+ break;
+ case 1:
+ sb.append(", 1(INFO)");
+ break;
+ case 2:
+ sb.append(", 2(DEBUG)");
+ break;
+ case 3:
+ sb.append(", 3(TRACE)");
+ break;
+ default :
+ }
+
+ if (adapter.getContext().isPollingUse()) {
+ sb.append("\n (");
+ sb.append("POLLING ");
+ sb.append(", " + adapter.getContext().getPollingRole());
+ if (adapter.getContext().isPollingOneway()) {
+ sb.append(", oneway");
+ }
+ sb.append(", " + adapter.getContext().getPollingTimeout());
+// sb.append(", " + adapter.getContext().getPollingRequest());
+// sb.append(", " + adapter.getContext().getPollingRequestPattern());
+// sb.append(", " + adapter.getContext().getPollingReplacement());
+// sb.append(", " + adapter.getContext().getPollingResponsePattern());
+ sb.append(")");
+ }
+
+ if ("FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "UDP_FIXED_LENGTH_HEADER".equals(adapter.getContext().getProtocol())
+ || "EGSEED".equals(adapter.getContext().getProtocol())
+ || "TCSEED".equals(adapter.getContext().getProtocol()) //20101213 JGY
+ || "ENVELOP".equals(adapter.getContext().getProtocol())
+ || "XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE2".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("type=" + adapter.getContext().getLlFieldType());
+ sb.append(", offset=" + adapter.getContext().getLlFieldOffset());
+ sb.append(", length=" + adapter.getContext().getLlFieldLength());
+ sb.append(", ll.field.include=" + adapter.getContext().getLlFieldInclude());
+ sb.append(", ll.offset.exclude=" + adapter.getContext().getLlOffsetExclude());
+ sb.append(", ll.include=" + adapter.getContext().getLlInclude());
+ sb.append(")");
+ }
+
+ if ("FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())
+ || "INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol()) // 20100515 JGY
+ || "UDP_FIXED_LENGTH_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("send.payload.length=");
+ sb.append(adapter.getContext().getSendPayloadLength());
+ sb.append(", recv.payload.length=");
+ sb.append(adapter.getContext().getRecvPayloadLength());
+ sb.append(")");
+ }
+
+ if ("XECURE".equals(adapter.getContext().getProtocol())
+ || "XECURE3".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("");
+ sb.append(adapter.getContext().getXecureType());
+ sb.append(" ");
+ sb.append(", " + adapter.getContext().getXecureConfigPath());
+ sb.append(", " + adapter.getContext().getXecureRemoteCert());
+ sb.append(")");
+ }
+
+ if ("INISAFE".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+ else if ("INISAFE_2020".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE_2020 ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ if ("INISAFE_NATN".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE_NATN ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeRelatedAdapterGroups());
+ sb.append(", " + adapter.getContext().getInisafeStartMessage());
+ sb.append(", " + adapter.getContext().getInisafeStopMessage());
+ sb.append(")");
+ }
+
+ // JGY 20100515
+ if ("INISAFE_PAYLOAD".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("INISAFE_PAYLOAD ");
+ sb.append(", " + adapter.getContext().getInisafeConfigPath());
+ sb.append(", " + adapter.getContext().getInisafeIdPassword());
+ sb.append(")");
+ }
+
+ // JGY 20100423
+ if ("ENVELOP".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("ENVELOP ");
+ sb.append(", " + adapter.getContext().getEnvelopSigncertPath());
+ sb.append(", " + adapter.getContext().getEnvelopSignkeyPath());
+ sb.append(", " + adapter.getContext().getEnvelopPassword());
+ sb.append(")");
+ }
+
+ // JGY 20101213
+ if ("TCSEED".equals(adapter.getContext().getProtocol())) {
+ sb.append("\n (");
+ sb.append("TCSEED ");
+ sb.append(", " + adapter.getContext().getTcseedKeyStore());
+ sb.append(")");
+ }
+
+ if (adapter.getContext().getDescription() != null && !"".equals(adapter.getContext().getDescription().trim())) {
+ sb.append("\n (" + adapter.getContext().getDescription() + ")");
+ }
+
+ sb.append(" ");
+
+ sb.append("\n");
+ for (Iterator iii = adapter.getSessionPool().iterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append(" ");
+
+ sb.append("\n");
+ for (Iterator iii = adapter.getSessionPool().checkedOutIterator() ; iii.hasNext(); ) {
+ IoSession session = (IoSession) iii.next();
+ sb.append(" ");
+ if (!session.isConnected())
+ sb.append("●");
+ else if (session.isClosing())
+ sb.append("◐");
+ else if (System.currentTimeMillis() - session.getLastIoTime() < 1000L)
+ sb.append("⊙");
+ else
+ sb.append("○");
+ sb.append(" Session :");
+ if (session.isClosing())
+ sb.append(" [CLOSING]");
+ if (!session.isConnected())
+ sb.append(" [NOT CONNECTED]");
+ sb.append(" " + session.getLocalAddress() + (adapter.getContext().isClient() ? "->" : "<-") + session.getRemoteAddress());
+ sb.append(", recv:" + session.getReadMessages());
+ sb.append("(" + session.getReadBytes() + ")");
+ sb.append(", send:" + session.getWrittenMessages());
+ sb.append("(" + session.getWrittenBytes() + ")");
+ sb.append(", created:" + TimeUtil.formatDate(session.getCreationTime()));
+ sb.append(", idle:" + TimeUtil.elapsedTime(session.getLastIoTime()) + "\n");
+ }
+ sb.append(" ");
+ sb.append("\n");
+
+ prevAdapterGroupName = adapterGroupName;
+ }
+ }
+
+ return "" + sb.toString() + " ";
+ }
+
+ protected boolean getAdapterStatus(String adapterGroupName, String adapterName) {
+ AdapterManager adapterManager = AdapterManager.getInstance();
+ AdapterVO vo = adapterManager.getAdapterVO(adapterGroupName, adapterName);
+ if (vo != null) {
+ return vo.isStatus();
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisClient.java
new file mode 100644
index 0000000..3b4fa1f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisClient.java
@@ -0,0 +1,12 @@
+package com.eactive.eai.adapter.socket2.protocol.inicis;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+
+public class InicisClient extends TcpAdapterClient{
+
+ public InicisClient(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisHandler.java
new file mode 100644
index 0000000..2d422d2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisHandler.java
@@ -0,0 +1,14 @@
+package com.eactive.eai.adapter.socket2.protocol.inicis;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+
+public class InicisHandler extends ProtocolHandler{
+
+ public InicisHandler(ISocketAdapter adapter) {
+ super(adapter);
+
+ }
+
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisServer.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisServer.java
new file mode 100644
index 0000000..b68249c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/InicisServer.java
@@ -0,0 +1,22 @@
+package com.eactive.eai.adapter.socket2.protocol.inicis;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.fixedheader.codec.FixedHeaderCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.inicis.handshake.InicisServerFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+public class InicisServer extends TcpAdapterServer{
+
+ public InicisServer(SocketAdapterContext context) throws Exception {
+ super(context);
+
+
+ this.handler = new InicisHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new FixedHeaderCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "inicis", new InicisServerFilter(this));
+ }
+
+
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisCodec.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisCodec.java
new file mode 100644
index 0000000..12f0e5a
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisCodec.java
@@ -0,0 +1,90 @@
+package com.eactive.eai.adapter.socket2.protocol.inicis.handshake;
+
+import kr.co.extrus.exafe.ie2e.ExafeiE2E;
+
+public class InicisCodec {
+
+ private static InicisCodec instance;
+
+ private static ExafeiE2E ie2e;
+
+ private InicisCodec() {
+
+ }
+
+ public static synchronized InicisCodec getInstance(String keyPath, String keyPass) throws Exception {
+ if(instance==null) {
+
+ instance = new InicisCodec();
+
+ String E2E_KEYFILE = "";
+ String E2E_CERTFILE = "";
+ String E2E_CODE = "";
+
+ try {
+
+ E2E_KEYFILE = keyPath + "/key.pem";
+ E2E_CERTFILE = keyPath + "/cert.pem";
+ E2E_CODE = keyPass;
+
+ // 암호화 모듈 초기화 - 한번만 수행
+ ie2e = new ExafeiE2E();
+ ie2e.InitCert(E2E_KEYFILE, E2E_CERTFILE, E2E_CODE);
+
+ } catch (Exception e) {
+ throw new Exception("InicisCodec | Exafei 초기화 에러: " + e.getMessage() + ", keyPath|keyPass: " + keyPath + "|" + keyPass
+ + ", E2E_KEYFILE|E2E_CERTFILE|E2E_CODE: " + E2E_KEYFILE + "|" + E2E_CERTFILE + "|" + E2E_CODE);
+ }
+ }
+ return instance;
+ }
+
+ public byte[] decrypt(byte[] bytes) throws Exception {
+
+ byte[] decrypted = null;
+
+ try {
+ decrypted = ie2e.Decryption(new String(bytes)).getBytes();
+ } catch (Exception e) {
+ throw new Exception("InicisCodec | Exafei 복호화 에러: " + e.getMessage());
+ }
+
+ return decrypted;
+ }
+
+ public static byte[] encrypt(byte[] bytes) {
+
+ return bytes;
+ }
+
+
+
+// public static void main(String[] args){
+//
+// ExafeiE2E ie2e;
+// String E2E_KEYFILE = "/";
+// String E2E_CERTFILE = "/";
+// String E2E_CODE = "/";
+//
+// ie2e = new ExafeiE2E();
+// byte[] input_data = "00000274RD8160 T20120719095522banktpg 1DK 0 00990007 ^|BT|^CRYPTO=Y,GSID= ,FIELD_SIZE=592,DEC_LEN=11,PW_LEN=15,PAD= ,ALIGN=L,ENC_DATA=rn3f7p6cqgN5jJo9aRjbhQ==,ENVELOP_DATA=MIIBQQYJKoZIhvcNAQcDoIIBMjCCAS4CAQAxgeswgegCAQAwUTBEMQswCQYDVQQGEwJLUjEPMA0GA1UECBMGSmVvbmp1MQ8wDQYDVQQKEwZKQkJhbmsxEzARBgNVBAMUCkUyRV9TZXJ2ZXICCQCq5nr6/7/EOzANBgkqhkiG9w0BAQEFAASBgCssAOhR2yRUxjwUhIgBWoROnfkBMrGZOyYgcOafwnGwYG429ZoXC3iwtqwHlq2X5JlT84JB39U36mUHJH2rq/PYS/yEQWgoaYyHO/bvE/DtAIJW2SBztGuPMIn6spDQAoyka4ZUQyEi2zn9MxauV/Iz5F2F8K1N3ZOKr67nTjNmMDsGCSqGSIb3DQEHATAcBggqgxqMmkQBBAQQLi5FeGFmZUUyRS4uISEuLoAQrn3f7p6cqgN5jJo9aRjbhQ==^|BT|^".getBytes();
+// byte[] result = null;
+//
+// // 암호화 모듈 초기화 - 한번만 수행
+// try {
+// ie2e.InitCert(E2E_KEYFILE, E2E_CERTFILE, E2E_CODE);
+// } catch (Exception e) {
+// System.out.println("InicisServerFilter | Exafei 초기화 에러.");
+// }
+//
+// try {
+// result = InicisCodec.decrypt(input_data, ie2e);
+// } catch (Exception e) {
+//
+// e.printStackTrace();
+// }
+//
+// System.out.println("decrypt : " + CommonLib.hexDump(result));
+//
+// }
+}
\ No newline at end of file
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisFilter.java
new file mode 100644
index 0000000..8579267
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisFilter.java
@@ -0,0 +1,97 @@
+package com.eactive.eai.adapter.socket2.protocol.inicis.handshake;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.common.util.Logger;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+
+public class InicisFilter extends IoFilterAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ private static final String NEXT_FILTER = InicisFilter.class.getName() + ".NextFilter";
+ protected static final String FILTER_STATE_KEY = InicisFilter.class.getName() + ".STATE";
+ protected static final String SESSION_STATE = "SESSION_STATE";
+
+ protected enum State {
+ STATE_HANDSHAKE,
+ STATE_MESSAGE;
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ protected static class FilterState {
+ public State state = State.STATE_MESSAGE;
+ public byte[] userKey = new byte[16];
+ public int[] roundKey = new int[32];
+ }
+
+ public InicisFilter(ISocketAdapter adapter) {
+
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
+
+ if (parent.contains(InicisFilter.class)) {
+ throw new IllegalStateException("A filter chain cannot contain more than one DesFilter.");
+ }
+
+ IoSession session = parent.getSession();
+ session.setAttribute(NEXT_FILTER, nextFilter);
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ nextFilter.sessionCreated(session);
+ }
+
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = null;
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ if (filterState.state == State.STATE_MESSAGE) {
+ byte[] encrypted = InicisCodec.encrypt(m.getBytes());
+ m = new ByteMessage(encrypted);
+ }
+
+ /**
+ * next filter
+ */
+ nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisServerFilter.java
new file mode 100644
index 0000000..56e35a5
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inicis/handshake/InicisServerFilter.java
@@ -0,0 +1,43 @@
+package com.eactive.eai.adapter.socket2.protocol.inicis.handshake;
+
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+public class InicisServerFilter extends InicisFilter{
+
+ public InicisServerFilter(ISocketAdapter adapter) {
+
+ super(adapter);
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ ByteMessage m = (ByteMessage) message;
+
+ switch (filterState.state) {
+ case STATE_MESSAGE:
+ /**
+ * decrypt
+ */
+ byte[] decrypted = InicisCodec.getInstance(context.getInicisKeyPath(),context.getInicisKeyPass()).decrypt(m.getBytes());
+ if (decrypted == null || decrypted.length == 0) {
+ throw new Exception("received message is invalid - check if message is encrypted : " + m.hexDump());
+ }
+ m.setBytes(decrypted);
+
+ /**
+ * next filter
+ */
+ nextFilter.messageReceived(session, m);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + m.hexDump());
+ }
+ }
+}
+
+
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeClient.java
new file mode 100644
index 0000000..a742e8f
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeClient.java
@@ -0,0 +1,39 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe;
+
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.inisafe.codec.InisafeCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.inisafe.handshake.InisafeClientFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class InisafeClient extends TcpAdapterClient {
+ boolean isBooting = true;
+
+ public InisafeClient(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ this.handler = new InisafeClientHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new InisafeCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "inisafe.codec", new InisafeClientFilter(this));
+ }
+
+ @Override
+ public SimpleFuture start() throws Exception {
+ if (isBooting && !Env.isTest()) {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | inisafe client protocol - skip start process when booting ...");
+ }
+ isBooting = false;
+
+ SimpleFuture future = new SimpleFuture();
+ future.set(Boolean.TRUE);
+ return future;
+ } else {
+ return super.start();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeClientHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeClientHandler.java
new file mode 100644
index 0000000..5de40db
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeClientHandler.java
@@ -0,0 +1,40 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class InisafeClientHandler extends InisafeHandler {
+ public InisafeClientHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void sessionOpened(IoSession session) throws Exception {
+ super.sessionOpened(session);
+ }
+
+ @Override
+ public void sessionClosed(IoSession session) throws Exception {
+ super.sessionClosed(session);
+ /**
+ * client-server pair 로 작업한다.
+ */
+ doSessionClosed(session);
+ }
+
+ protected String messageReplace (String str){
+ Matcher matcher = Pattern.compile("%d\\{([a-zA-Z \\-]+)\\}").matcher(str);
+
+ while (matcher.find()) {
+ String datePattern = matcher.group(1);
+ DateFormat dateFormat = new SimpleDateFormat(datePattern);
+ str = str.replaceFirst("%d\\{([a-zA-Z \\-]+)\\}", dateFormat.format(System.currentTimeMillis()));
+ }
+ return str;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeErrorMessage.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeErrorMessage.java
new file mode 100644
index 0000000..6cc2bc8
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeErrorMessage.java
@@ -0,0 +1,26 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe;
+
+import java.util.Hashtable;
+
+public class InisafeErrorMessage {
+ static Hashtable hash = new Hashtable<>();
+
+ static {
+ hash.put("-1910", "ERR_POLICY_RESERVED_CN | 이미 등록되어 있은 CN 입니다.");
+ }
+
+ private InisafeErrorMessage() {
+
+ }
+ public static String getErrorMessage(String key) {
+ String value = hash.get(key);
+ if (value == null) {
+ return "Unknown Error.";
+ }
+ return value;
+ }
+
+ public static String getErrorMessage(int key) {
+ return getErrorMessage(String.valueOf(key));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeHandler.java
new file mode 100644
index 0000000..a4ba40e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/InisafeHandler.java
@@ -0,0 +1,37 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeHandler extends ProtocolHandler {
+ public InisafeHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ protected void doSessionClosed (IoSession session) throws Exception {
+ /**
+ * client-server pair (in same adapter group)
+ */
+
+ ISocketAdapter[] adapters = SocketAdapterManager.getInstance().getSocketAdapters(adapter.getContext().getAdapterGroupName());
+ for (int i=0; i= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | InisafeDecoder | decode : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "InisafeDecoder | decode : " + CommonLib.hexDump(in, context));
+ }
+
+ boolean isHandshakeState = false;
+ FilterState filterState = (FilterState) session.getAttribute(InisafeFilter.FILTER_STATE_KEY);
+ if (filterState != null && filterState.state != InisafeFilter.State.STATE_MESSAGE) {
+ isHandshakeState = true;
+ }
+
+ if (isHandshakeState) {
+ decodeHandshake(session, in, out);
+ } else {
+ decodeMessage(session, in, out);
+ }
+ }
+
+ private void decodeHandshake(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(InisafeConstants.COMMON_PART_LENGTH);
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+ codecState.buffer.position(200).limit(200+codecState.payloadSize);
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] individualLL = new byte[4];
+ codecState.buffer.position(200).get(individualLL);
+ int individualLength = Integer.parseInt(new String(individualLL));
+ byte[] bytes = new byte[individualLength-4];
+ codecState.buffer.position(204).get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(200);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private void decodeMessage(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(InisafeConstants.COMMON_PART_LENGTH);
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+ /**
+ * payload size°¡ 0ÀÎ °æ¿ì
+ */
+ if (codecState.payloadSize == 0) {
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0).get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(InisafeConstants.COMMON_PART_LENGTH);
+ } else {
+ codecState.buffer.position(200).limit(codecState.payloadSize+200);
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0).get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(InisafeConstants.COMMON_PART_LENGTH);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ codecState.buffer.flip();
+ try {
+ byte[] commonLL = new byte[5];
+ codecState.buffer.position(0).get(commonLL);
+ codecState.payloadSize = Integer.parseInt(new String(commonLL));
+ codecState.buffer.position(0);
+ } catch (NumberFormatException e) {
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA008");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA008");
+ throw new EAIException("RECEAINNA008", context.getAdapterName() +
+ "when read header, number format is invalid - "
+ + e.getMessage() + " | " + CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ if (codecState.payloadSize > MAX_PAYLOAD_SIZE) {
+ throw new Exception("max payload size(" + MAX_PAYLOAD_SIZE + ") exceeded : " + codecState.payloadSize);
+ }
+
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/codec/InisafeEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/codec/InisafeEncoder.java
new file mode 100644
index 0000000..8ef2257
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/codec/InisafeEncoder.java
@@ -0,0 +1,164 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.inisafe.handshake.InisafeFilter;
+import com.eactive.eai.adapter.socket2.protocol.inisafe.handshake.InisafeFilter.FilterState;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class InisafeEncoder implements ProtocolEncoder {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public InisafeEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ boolean isHandshakeState = false;
+ FilterState filterState = (FilterState) session.getAttribute(InisafeFilter.FILTER_STATE_KEY);
+ if (filterState != null && filterState.state != InisafeFilter.State.STATE_MESSAGE) {
+ isHandshakeState = true;
+ }
+
+ if (isHandshakeState) {
+ encodeHandshake(session, m, out);
+ } else {
+ encodeMessage(session, m, out);
+ }
+ }
+
+
+ private void encodeHandshake(IoSession session, ByteMessage m, ProtocolEncoderOutput out) throws Exception {
+ int length = m.size();
+ int totalLength = InisafeConstants.COMMON_PART_LENGTH + length;
+
+ ByteBuffer buffer = ByteBuffer.allocate(totalLength).limit(totalLength);
+
+ /**
+ * [1] common ll
+ */
+ String commonLL = CommonLib.getFormatString(totalLength-InisafeConstants.COMMON_PART_LENGTH, InisafeConstants.COMMON_LL_LENGTH);
+ buffer.put(commonLL.getBytes()); // 1 전문송신 Byte 수 5 N * 비고 1) 참조
+
+ /**
+ * [2] common rest
+ */
+ buffer.put(getTransactionType(session)); // 2 거래구분코드 9 AN * 비고 2) 참조
+ buffer.put("BOK".getBytes()); // 3 System ID 3 A * BOK (단, 증권예탁결제원간 거래는 DVP)
+ buffer.put("0000".getBytes()); // 4 전문종별 코드 4 N * 비고 3) 참조
+ buffer.put("YYYYMMDD".getBytes()); // 5 영업일자 8 N * YYYYMMDD
+ buffer.put(" ".getBytes()); // 6 STATUS 4 N * 비고 4) 참조
+ buffer.put("0000".getBytes()); // 7 응답코드 4 AN * <별첨1> 참조
+ buffer.put("00000000000000000000".getBytes()); // 8 전문관리번호 20 N * 비고 5) 참조
+ buffer.put("YYYYMMDDhhmmss".getBytes()); // 9 전문전송시간 14 N * YYYYMMDDhhmmss
+ buffer.put("00000000000000000000".getBytes()); // 10 참조번호 20 N B 비고 6) 참조
+ buffer.put("1051".getBytes()); // 11 송신기관 4 N * <별첨3> 참조, 비고 7)참조
+ buffer.put("1016".getBytes()); // 12 수신기관 4 N * <별첨3> 참조, 비고 8)참조
+ buffer.put("N".getBytes()); // 13 암호화 여부 1 A * Y/N
+ buffer.put("001".getBytes()); // 14 전송횟수 3 N * 전송한 횟수 * 최초전송번호 : 1
+ buffer.put(StringUtils.leftPad("", 65).getBytes()); // 15 공란 65 A * Space
+ buffer.put(" ".getBytes()); // 16 참가기관 ID 16 AN SR 한국은행에 등록된 ID
+ buffer.put(" ".getBytes()); // 17 참가기관 비밀번호 16 AN SR 참가기관의 비밀번호
+
+ /**
+ * [3] individual part
+ */
+ buffer.put(m.getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | InisafeEncoder | encode (handshake) : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "InisafeEncoder | encode (handshake) : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+
+ private byte[] getTransactionType(IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(InisafeFilter.FILTER_STATE_KEY);
+ if (filterState == null) {
+ throw new Exception("session does not have filter state");
+ }
+
+ switch (filterState.state) {
+ case STATE_INIT :
+ if (adapter.getContext().isClient()) {
+ return "000000001".getBytes();
+ } else {
+ return "000000002".getBytes();
+ }
+ case STATE_UPDATE :
+ if (adapter.getContext().isClient()) {
+ return "000000003".getBytes();
+ } else {
+ return "000000004".getBytes();
+ }
+ case STATE_FINAL :
+ return "000000005".getBytes();
+ default :
+ throw new Exception("invalid state");
+ }
+ }
+
+ private void encodeMessage(IoSession session, ByteMessage m, ProtocolEncoderOutput out) throws Exception {
+ /**
+ * copy byte[] to buffer
+ */
+ int length = m.size();
+ ByteBuffer buffer = ByteBuffer.allocate(length).limit(length);
+ buffer.put(m.getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | InisafeEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "InisafeEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+
+ public void dispose(IoSession session) throws Exception {
+ // empty
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeClientFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeClientFilter.java
new file mode 100644
index 0000000..d07282d
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeClientFilter.java
@@ -0,0 +1,189 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe.handshake;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.initech.inisafenet.HandShakeManager_RSA;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeClientFilter extends InisafeFilter {
+ public InisafeClientFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ HandShakeManager_RSA inisafeSession = new HandShakeManager_RSA();
+ inisafeSession.TEST_MODE = false;
+ session.setAttribute(INISAFE_SESSION_KEY, inisafeSession);
+
+ process(nextFilter, session, null);
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ process(nextFilter, session, m);
+ }
+
+ protected void process(NextFilter nextFilter, IoSession session, ByteMessage message) throws Exception {
+ try {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+ HandShakeManager_RSA inisafeSession = (HandShakeManager_RSA) session.getAttribute(INISAFE_SESSION_KEY);
+
+ /**
+ * State machine
+ */
+ ByteBuffer buffer = null;
+
+ switch (filterState.state) {
+ case STATE_INIT:
+ /*
+ * handshake timeout 설정함
+ * timeout 에서 5초 전 설정
+ */
+ if (context.getTimeout() <= 5 ) {
+ throw new Exception("invalid timeout("+context.getTimeout()+") value . set timeout must be 5 or more. ");
+ }
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout() - 5);
+ /**
+ * change state to INIT
+ */
+ filterState.state = State.STATE_INIT;
+ session.setAttribute(SESSION_STATE, filterState.state.toString());
+
+ /**
+ * create INIT key
+ */
+ byte[] initKey = inisafeSession.initHandShakeClient(null);
+ String initIndividualLL = CommonLib.getFormatString(initKey.length+4, 4);
+ //byte[] paddedInitKey = StringUtils.rightPad(new String(initKey), 92).getBytes();
+
+ buffer = ByteBuffer.allocate(4+initKey.length).limit(4+initKey.length);
+ buffer.put(initIndividualLL.getBytes());
+ buffer.put(initKey);
+
+ byte[] initIndividualBytes = new byte[4+initKey.length];
+ buffer.position(0).get(initIndividualBytes);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_INIT");
+ }
+ session.write(initIndividualBytes);
+
+ /**
+ * change state to UPDATE
+ */
+ filterState.state = State.STATE_UPDATE;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_UPDATE:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_INIT response");
+ }
+ if(message == null) throw new Exception("Message is NULL");
+ /**
+ * send UPDATE
+ */
+ byte[] updateKey = inisafeSession.updateHandShakeClient(message.getBytes());
+ String updateIndividualLL = CommonLib.getFormatString(updateKey.length+4, 4);
+ //byte[] paddedUpdateKey = StringUtils.rightPad(new String(updateKey), 268).getBytes();
+
+ buffer = ByteBuffer.allocate(4+updateKey.length).limit(4+updateKey.length);
+ buffer.put(updateIndividualLL.getBytes());
+ buffer.put(updateKey);
+
+ byte[] updateIndividualBytes = new byte[4+updateKey.length];
+ buffer.position(0).get(updateIndividualBytes);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_UPDATE");
+ }
+ session.write(updateIndividualBytes);
+
+ /**
+ * change state to FINAL
+ */
+ filterState.state = State.STATE_FINAL;
+ setSessionState(session, filterState.state.toString());
+
+ break;
+
+ case STATE_FINAL:
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_UPDATE response");
+ }
+ if(message == null) throw new Exception("Message is NULL");
+ /**
+ * send FINAL
+ */
+ byte[] finalKey = inisafeSession.finalHandShakeClient(message.getBytes());
+ String finalIndividualLL = CommonLib.getFormatString(finalKey.length+4, 4);
+ //byte[] paddedFinalKey = StringUtils.rightPad(new String(finalKey), 92).getBytes();
+
+ buffer = ByteBuffer.allocate(4+finalKey.length).limit(4+finalKey.length);
+ buffer.put(finalIndividualLL.getBytes());
+ buffer.put(finalKey);
+
+ byte[] finalIndividualBytes = new byte[4+finalKey.length];
+ buffer.position(0).get(finalIndividualBytes);
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_FINAL");
+ }
+ session.write(finalIndividualBytes);
+
+ /**
+ * change state
+ */
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ /**
+ * finish handshake
+ */
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ adapter.addRecentLog(context.getAdapterName() + " | InisafeClientFilter | handshake finished ...");
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | handshake finished ...");
+ }
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+
+ break;
+
+ case STATE_MESSAGE:
+ if(message == null) throw new Exception("Message is NULL");
+ validateMessage(message);
+ message = decrypt(message, session);
+ nextFilter.messageReceived(session, message);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + message);
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+ nextFilter.filterClose(session);
+
+ adapter.getSessionPool().remove(session);
+ session.close();
+ throw new Exception(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeFilter.java
new file mode 100644
index 0000000..c7de204
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeFilter.java
@@ -0,0 +1,209 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe.handshake;
+
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+import com.initech.inisafenet.HandShakeManager_RSA;
+import com.initech.provider.crypto.InitechProvider;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+
+abstract public class InisafeFilter extends IoFilterAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+ private final Object lockObj = new Object();
+// private static final String NEXT_FILTER = InisafeFilter.class.getName() + ".NextFilter";
+ public static final String FILTER_STATE_KEY = InisafeFilter.class.getName() + ".STATE";
+
+ public static final String SESSION_STATE = "SESSION_STATE";
+ public static final String INISAFE_SESSION_KEY = "INISAFE_SESSION_KEY";
+
+ public enum State {
+ STATE_START,
+ STATE_INIT,
+ STATE_UPDATE,
+ STATE_FINAL,
+ STATE_MESSAGE;
+ }
+
+ public static class FilterState {
+ public State state = null;
+ public byte[] key; // token?
+
+ public FilterState() {}
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ protected byte[] cert;
+ protected byte[] key;
+ protected String password;
+ protected byte[] remoteCert;
+
+ static {
+ new InitechProvider();
+ }
+
+ public InisafeFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ synchronized(lockObj) {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ filterState.state = State.STATE_INIT;
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ //setSessionState(session, filterState.state.toString());
+ }
+ }
+
+ // handshake future
+ session.setAttribute(ProtocolHandler.HANDSHAKE_FUTURE, new SimpleFuture());
+ }
+
+ @Override
+ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
+// HandShakeManager_RSA inisafeSession = (HandShakeManager_RSA) session.getAttribute(INISAFE_SESSION_KEY);
+// inisafeSession.close();
+
+ nextFilter.sessionClosed(session);
+ }
+
+
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+ ByteMessage m = null;
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteBuffer) {
+ m = new ByteMessage((ByteBuffer) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ /**
+ * encrypt
+ */
+ try {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+// HandShakeManager_RSA inisafeSession = (HandShakeManager_RSA) session.getAttribute(INISAFE_SESSION_KEY);
+
+ switch (filterState.state) {
+ case STATE_MESSAGE:
+ validateMessage(m);
+// String sessionState = (String) session.getAttribute(ProtocolHandler.SESSION_STATE);
+ m = encrypt(m, session);
+ break;
+
+ default:
+ break;
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+ throw new Exception(context.getAdapterName() + " | initech error - " + e.getMessage());
+ }
+
+ nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+ @Override
+ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState.state != State.STATE_MESSAGE){
+ StringBuffer sb = new StringBuffer();
+ sb.append("idle:" + TimeUtil.elapsedTime(session.getLastIoTime()));
+ sb.append(", handshake timeout:" + (context.getTimeout() -5));
+ sb.append(", protocol:" + context.getProtocol());
+ if (filterState != null) {
+ sb.append(", state:" + filterState.state.toString());
+ }
+ sb.append("/" + session.getAttribute(SESSION_STATE));
+ logger.error(context.getAdapterName() + " | handshake timeout -> disconnecting (" + session + ") " + sb.toString());
+ adapter.addRecentError(context.getAdapterName() + " | handshake timeout -> disconnecting (" + session + ") " + sb.toString());
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ adapter.getSessionPool().remove(session);
+ session.close();
+
+
+ }else{
+ nextFilter.sessionIdle(session, status);
+ }
+ }
+
+ protected String getSessionState(IoSession session) {
+ return (String) session.getAttribute(SESSION_STATE);
+ }
+
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+
+
+ protected void validateMessage(ByteMessage m) throws Exception {
+ if (m.size() < 200) {
+ throw new Exception("cannot send message - message size < 200 - " + m.hexDump());
+ }
+
+ String ll = new String(m.getBytes(0, 5));
+ if (!ll.matches("[0-9]{5}")) {
+ throw new Exception("ll field (0-5) of message is not number - " + m.hexDump());
+ }
+ }
+
+
+ protected ByteMessage encrypt(ByteMessage m, IoSession session) throws Exception {
+ /**
+ * 암호화 여부 체크
+ */
+ if ('Y' != m.getByte(99))
+ return m;
+
+ HandShakeManager_RSA inisafeSession = (HandShakeManager_RSA) session.getAttribute(INISAFE_SESSION_KEY);
+ byte[] encryptPart = inisafeSession.i_encrypt(m.getBytes(200-16-16));
+ ByteMessage encrypted = new ByteMessage(m.getBytes(0, 200-16-16)).append(encryptPart);
+
+ return encrypted;
+ }
+
+ protected ByteMessage decrypt(ByteMessage m, IoSession session) throws Exception {
+ /**
+ * 암호화 여부 체크
+ */
+ if ('Y' != m.getByte(99))
+ return m;
+
+ HandShakeManager_RSA inisafeSession = (HandShakeManager_RSA) session.getAttribute(INISAFE_SESSION_KEY);
+ byte[] decryptPart = inisafeSession.i_decrypt(m.getBytes(200-16-16));
+ ByteMessage decrypted = new ByteMessage(m.getBytes(0, 200-16-16)).append(decryptPart);
+
+ return decrypted;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeServerFilter.java
new file mode 100644
index 0000000..f6fd7c3
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe/handshake/InisafeServerFilter.java
@@ -0,0 +1,207 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe.handshake;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.initech.inisafenet.HandShakeManager_RSA;
+import com.initech.inisafenet.exception.INISAFENetException;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeServerFilter extends InisafeFilter {
+ public InisafeServerFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ try {
+ HandShakeManager_RSA inisafeSession = new HandShakeManager_RSA(context.getInisafeConfigPath());
+ session.setAttribute(INISAFE_SESSION_KEY, inisafeSession);
+ } catch(INISAFENetException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ //validateMessage(m);
+ process(nextFilter, session, m);
+ }
+
+ protected void process(NextFilter nextFilter, IoSession session, ByteMessage message) throws Exception {
+ HandShakeManager_RSA inisafeSession = null;
+
+ try {
+ /**
+ * get filter state
+ */
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ /**
+ * check inisafe session
+ */
+ inisafeSession = (HandShakeManager_RSA) session.getAttribute(INISAFE_SESSION_KEY);
+ if (inisafeSession == null) {
+ throw new Exception("inisafe session is not established");
+ }
+
+ /**
+ * state machine
+ */
+ ByteBuffer buffer = null;
+
+ switch (filterState.state) {
+ case STATE_INIT:
+ /*
+ * handshake timeout 설정함
+ * timeout 에서 5초 전 설정
+ */
+ if (context.getTimeout() <= 5 ) {
+ throw new Exception("invalid timeout("+context.getTimeout()+") value . set timeout must be 5 or more. ");
+ }
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_INIT");
+ }
+
+ /**
+ * send INIT response
+ */
+ byte[] initKey = inisafeSession.initHandShake(message.getBytes());
+ String initIndividualLL = CommonLib.getFormatString(initKey.length+4, 4);
+ //byte[] paddedInitKey = StringUtils.rightPad(new String(initKey), 1792).getBytes();
+
+ buffer = ByteBuffer.allocate(4+initKey.length).limit(4+initKey.length);
+ buffer.put(initIndividualLL.getBytes());
+ buffer.put(initKey);
+
+ byte[] initIndividualBytes = new byte[4+initKey.length];
+ buffer.position(0).get(initIndividualBytes);
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_INIT response");
+ }
+ session.write(initIndividualBytes);
+
+ /**
+ * change state to UPDATE
+ */
+ filterState.state = State.STATE_UPDATE;
+ setSessionState(session, filterState.state.toString());
+
+ break;
+
+ case STATE_UPDATE:
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_UPDATE");
+ }
+
+ /**
+ * send UPDATE response
+ */
+ byte[] updateKey = inisafeSession.updateHandShake(message.getBytes());
+ String updateIndividualLL = CommonLib.getFormatString(updateKey.length+4, 4);
+ //byte[] paddedUpdateKey = StringUtils.rightPad(new String(updateKey), 108).getBytes();
+
+ buffer = ByteBuffer.allocate(4+updateKey.length).limit(4+updateKey.length);
+ buffer.put(updateIndividualLL.getBytes());
+ buffer.put(updateKey);
+
+ byte[] updateIndividualBytes = new byte[4+updateKey.length];
+ buffer.position(0).get(updateIndividualBytes);
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_UPDATE response");
+ }
+ session.write(updateIndividualBytes);
+
+ /**
+ * change state to FINAL
+ */
+ filterState.state = State.STATE_FINAL;
+ setSessionState(session, filterState.state.toString());
+
+ break;
+
+ case STATE_FINAL:
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_FINAL");
+ }
+
+ // 20200409 ASIS 에는 없던 TOBE 추가로직을 삽입함
+ //-------------------------------------------------------------------
+ int result = inisafeSession.finalHandShake(message.getBytes());
+
+ if (result !=1){
+ throw new Exception(" invalid message during handshake .. : " + message);
+ }
+ //-------------------------------------------------------------------
+ /**
+ * change state to MESSAGE
+ */
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ /**
+ * start client pair socket adapter (in same socket adapter group)
+ */
+ ISocketAdapter[] adapters = SocketAdapterManager.getInstance().getSocketAdapters(adapter.getContext().getAdapterGroupName());
+ if(adapters == null) return;
+ for (int i=0; i= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ adapter.addRecentLog("InisafeServerFilter | handshake finished ...");
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | handshake finished ...");
+ }
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ //nextFilter.messageReceived(session, new ByteMessage("STARTED"));
+
+ break;
+
+ case STATE_MESSAGE:
+ validateMessage(message);
+ message = decrypt(message, session);
+ nextFilter.messageReceived(session, message);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + message);
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+
+ nextFilter.filterClose(session);
+
+ adapter.getSessionPool().remove(session);
+ session.close();
+
+ throw new Exception(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/Inisafe2020Client.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/Inisafe2020Client.java
new file mode 100644
index 0000000..8edd086
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/Inisafe2020Client.java
@@ -0,0 +1,38 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020;
+
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.codec.InisafeCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.handshake.InisafeClientFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class Inisafe2020Client extends TcpAdapterClient {
+ boolean isBooting = true;
+
+ public Inisafe2020Client(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ this.handler = new InisafeClientHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new InisafeCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "inisafe.codec", new InisafeClientFilter(this));
+ }
+
+ public SimpleFuture start() throws Exception {
+ if (isBooting && !Env.isTest()) {
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | inisafe client protocol - skip start process when booting ...");
+ }
+ isBooting = false;
+
+ SimpleFuture future = new SimpleFuture();
+ future.set(Boolean.TRUE);
+ return future;
+ } else {
+ return super.start();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/Inisafe2020Server.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/Inisafe2020Server.java
new file mode 100644
index 0000000..0f72bea
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/Inisafe2020Server.java
@@ -0,0 +1,19 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterServer;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.codec.InisafeCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.handshake.InisafeServerFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class Inisafe2020Server extends TcpAdapterServer {
+ public Inisafe2020Server(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ this.handler = new InisafeServerHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new InisafeCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "inisafe.codec", new InisafeServerFilter(this));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeClientHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeClientHandler.java
new file mode 100644
index 0000000..817de66
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeClientHandler.java
@@ -0,0 +1,38 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class InisafeClientHandler extends InisafeHandler {
+ public InisafeClientHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ public void sessionOpened(IoSession session) throws Exception {
+ super.sessionOpened(session);
+ }
+
+ public void sessionClosed(IoSession session) throws Exception {
+ super.sessionClosed(session);
+ /**
+ * client-server pair 로 작업한다.
+ */
+ doSessionClosed(session);
+ }
+
+ protected String messageReplace (String str){
+ Matcher matcher = Pattern.compile("%d\\{([a-zA-Z \\-]+)\\}").matcher(str);
+
+ while (matcher.find()) {
+ String datePattern = matcher.group(1);
+ DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(datePattern);
+ str = str.replaceFirst("%d\\{([a-zA-Z \\-]+)\\}", dateFormat.format(ZonedDateTime.now()));
+ }
+ return str;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeErrorMessage.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeErrorMessage.java
new file mode 100644
index 0000000..b310ee2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeErrorMessage.java
@@ -0,0 +1,24 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020;
+
+import java.util.Hashtable;
+
+
+public class InisafeErrorMessage {
+ static Hashtable hash = new Hashtable();
+
+ static {
+ hash.put("-1910", "ERR_POLICY_RESERVED_CN | 이미 등록되어 있은 CN 입니다.");
+ }
+
+ static public String getErrorMessage(String key) {
+ String value = hash.get(key);
+ if (value == null) {
+ return "Unknown Error.";
+ }
+ return value;
+ }
+
+ static public String getErrorMessage(int key) {
+ return getErrorMessage(String.valueOf(key));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeHandler.java
new file mode 100644
index 0000000..8f8e22c
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/InisafeHandler.java
@@ -0,0 +1,38 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeHandler extends ProtocolHandler {
+ public InisafeHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ protected void doSessionClosed (IoSession session) throws Exception {
+ /**
+ * client-server pair (in same adapter group)
+ */
+
+ ISocketAdapter[] adapters = SocketAdapterManager.getInstance().getSocketAdapters(adapter.getContext().getAdapterGroupName());
+ if(adapters == null) return;
+ for (int i=0; i= context.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | InisafeDecoder | decode : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "InisafeDecoder | decode : " + CommonLib.hexDump(in, context));
+ }
+
+ boolean isHandshakeState = false;
+ FilterState filterState = (FilterState) session.getAttribute(InisafeFilter.FILTER_STATE_KEY);
+ if (filterState != null && filterState.state != InisafeFilter.State.STATE_MESSAGE) {
+ isHandshakeState = true;
+ }
+
+ if (isHandshakeState) {
+ decodeHandshake(session, in, out);
+ } else {
+ decodeMessage(session, in, out);
+ }
+ }
+
+ private void decodeHandshake(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(InisafeConstants.COMMON_PART_LENGTH);
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+ codecState.buffer.position(200).limit(200+codecState.payloadSize);
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] individualLL = new byte[4];
+ codecState.buffer.position(200).get(individualLL);
+ int individualLength = Integer.parseInt(new String(individualLL));
+ byte[] bytes = new byte[individualLength-4];
+ codecState.buffer.position(204).get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(200);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private void decodeMessage(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(InisafeConstants.COMMON_PART_LENGTH);
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) {
+ /**
+ * payload size°¡ 0ÀÎ °æ¿ì
+ */
+ if (codecState.payloadSize == 0) {
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0).get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(InisafeConstants.COMMON_PART_LENGTH);
+ } else {
+ codecState.buffer.position(200).limit(codecState.payloadSize+200);
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit()];
+ codecState.buffer.position(0).get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(InisafeConstants.COMMON_PART_LENGTH);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ codecState.buffer.flip();
+ try {
+ byte[] commonLL = new byte[5];
+ codecState.buffer.position(0).get(commonLL);
+ codecState.payloadSize = Integer.parseInt(new String(commonLL));
+ codecState.buffer.position(0);
+ } catch (NumberFormatException e) {
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA008");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA008");
+ throw new EAIException("RECEAINNA008", context.getAdapterName() +
+ "when read header, number format is invalid - "
+ + e.getMessage() + " | " + CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ if (codecState.payloadSize > MAX_PAYLOAD_SIZE) {
+ throw new Exception("max payload size(" + MAX_PAYLOAD_SIZE + ") exceeded : " + codecState.payloadSize);
+ }
+
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/codec/InisafeEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/codec/InisafeEncoder.java
new file mode 100644
index 0000000..584948b
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/codec/InisafeEncoder.java
@@ -0,0 +1,164 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.handshake.InisafeFilter;
+import com.eactive.eai.adapter.socket2.protocol.inisafe2020.handshake.InisafeFilter.FilterState;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class InisafeEncoder implements ProtocolEncoder {
+ protected final Logger logger;
+ protected final Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public InisafeEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ boolean isHandshakeState = false;
+ FilterState filterState = (FilterState) session.getAttribute(InisafeFilter.FILTER_STATE_KEY);
+ if (filterState != null && filterState.state != InisafeFilter.State.STATE_MESSAGE) {
+ isHandshakeState = true;
+ }
+
+ if (isHandshakeState) {
+ encodeHandshake(session, m, out);
+ } else {
+ encodeMessage(session, m, out);
+ }
+ }
+
+
+ private void encodeHandshake(IoSession session, ByteMessage m, ProtocolEncoderOutput out) throws Exception {
+ int length = m.size();
+ int totalLength = InisafeConstants.COMMON_PART_LENGTH + length;
+
+ ByteBuffer buffer = ByteBuffer.allocate(totalLength).limit(totalLength);
+
+ /**
+ * [1] common ll
+ */
+ String commonLL = CommonLib.getFormatString(totalLength-InisafeConstants.COMMON_PART_LENGTH, InisafeConstants.COMMON_LL_LENGTH);
+ buffer.put(commonLL.getBytes()); // 1 전문송신 Byte 수 5 N * 비고 1) 참조
+
+ /**
+ * [2] common rest
+ */
+ buffer.put(getTransactionType(session)); // 2 거래구분코드 9 AN * 비고 2) 참조
+ buffer.put("BOK".getBytes()); // 3 System ID 3 A * BOK (단, 증권예탁결제원간 거래는 DVP)
+ buffer.put("0000".getBytes()); // 4 전문종별 코드 4 N * 비고 3) 참조
+ buffer.put("YYYYMMDD".getBytes()); // 5 영업일자 8 N * YYYYMMDD
+ buffer.put(" ".getBytes()); // 6 STATUS 4 N * 비고 4) 참조
+ buffer.put("0000".getBytes()); // 7 응답코드 4 AN * <별첨1> 참조
+ buffer.put("00000000000000000000".getBytes()); // 8 전문관리번호 20 N * 비고 5) 참조
+ buffer.put("YYYYMMDDhhmmss".getBytes()); // 9 전문전송시간 14 N * YYYYMMDDhhmmss
+ buffer.put("00000000000000000000".getBytes()); // 10 참조번호 20 N B 비고 6) 참조
+ buffer.put("1051".getBytes()); // 11 송신기관 4 N * <별첨3> 참조, 비고 7)참조
+ buffer.put("1016".getBytes()); // 12 수신기관 4 N * <별첨3> 참조, 비고 8)참조
+ buffer.put("N".getBytes()); // 13 암호화 여부 1 A * Y/N
+ buffer.put("001".getBytes()); // 14 전송횟수 3 N * 전송한 횟수 * 최초전송번호 : 1
+ buffer.put(StringUtils.leftPad("", 65).getBytes()); // 15 공란 65 A * Space
+ buffer.put(" ".getBytes()); // 16 참가기관 ID 16 AN SR 한국은행에 등록된 ID
+ buffer.put(" ".getBytes()); // 17 참가기관 비밀번호 16 AN SR 참가기관의 비밀번호
+
+ /**
+ * [3] individual part
+ */
+ buffer.put(m.getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | InisafeEncoder | encode (handshake) : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "InisafeEncoder | encode (handshake) : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+
+ private byte[] getTransactionType(IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(InisafeFilter.FILTER_STATE_KEY);
+ if (filterState == null) {
+ throw new Exception("session does not have filter state");
+ }
+
+ switch (filterState.state) {
+ case STATE_INIT :
+ if (adapter.getContext().isClient()) {
+ return "000000001".getBytes();
+ } else {
+ return "000000002".getBytes();
+ }
+ case STATE_UPDATE :
+ if (adapter.getContext().isClient()) {
+ return "000000003".getBytes();
+ } else {
+ return "000000004".getBytes();
+ }
+ case STATE_FINAL :
+ return "000000005".getBytes();
+ default :
+ throw new Exception("invalid state");
+ }
+ }
+
+ private void encodeMessage(IoSession session, ByteMessage m, ProtocolEncoderOutput out) throws Exception {
+ /**
+ * copy byte[] to buffer
+ */
+ int length = m.size();
+ ByteBuffer buffer = ByteBuffer.allocate(length).limit(length);
+ buffer.put(m.getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | InisafeEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "InisafeEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+
+ public void dispose(IoSession session) throws Exception {
+ // empty
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeClientFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeClientFilter.java
new file mode 100644
index 0000000..5226dda
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeClientFilter.java
@@ -0,0 +1,187 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020.handshake;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.initech.inisafenet.HandShakeManager;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeClientFilter extends InisafeFilter {
+ public InisafeClientFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ HandShakeManager inisafeSession = new HandShakeManager(context.getInisafeConfigPath());
+// inisafeSession.TEST_MODE = false;
+ session.setAttribute(INISAFE_SESSION_KEY, inisafeSession);
+
+ process(nextFilter, session, null);
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ process(nextFilter, session, m);
+ }
+
+ protected void process(NextFilter nextFilter, IoSession session, ByteMessage message) throws Exception {
+ try {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+ HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+
+ /**
+ * State machine
+ */
+ ByteBuffer buffer = null;
+
+ switch (filterState.state) {
+ case STATE_INIT:
+ /*
+ * handshake timeout 설정함
+ * timeout 에서 5초 전 설정
+ */
+ if (context.getTimeout() <= 5 ) {
+ throw new Exception("invalid timeout("+context.getTimeout()+") value . set timeout must be 5 or more. ");
+ }
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout() - 5);
+ /**
+ * change state to INIT
+ */
+ filterState.state = State.STATE_INIT;
+ session.setAttribute(SESSION_STATE, filterState.state.toString());
+
+ /**
+ * create INIT key
+ */
+ byte[] initKey = inisafeSession.initHandShakeClient(null);
+ String initIndividualLL = CommonLib.getFormatString(initKey.length+4, 4);
+ //byte[] paddedInitKey = StringUtils.rightPad(new String(initKey), 92).getBytes();
+
+ buffer = ByteBuffer.allocate(4+initKey.length).limit(4+initKey.length);
+ buffer.put(initIndividualLL.getBytes());
+ buffer.put(initKey);
+
+ byte[] initIndividualBytes = new byte[4+initKey.length];
+ buffer.position(0).get(initIndividualBytes);
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_INIT");
+ }
+ session.write(initIndividualBytes);
+
+ /**
+ * change state to UPDATE
+ */
+ filterState.state = State.STATE_UPDATE;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_UPDATE:
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_INIT response");
+ }
+
+ /**
+ * send UPDATE
+ */
+ byte[] updateKey = inisafeSession.updateHandShakeClient(message.getBytes());
+ String updateIndividualLL = CommonLib.getFormatString(updateKey.length+4, 4);
+ //byte[] paddedUpdateKey = StringUtils.rightPad(new String(updateKey), 268).getBytes();
+
+ buffer = ByteBuffer.allocate(4+updateKey.length).limit(4+updateKey.length);
+ buffer.put(updateIndividualLL.getBytes());
+ buffer.put(updateKey);
+
+ byte[] updateIndividualBytes = new byte[4+updateKey.length];
+ buffer.position(0).get(updateIndividualBytes);
+
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_UPDATE");
+ }
+ session.write(updateIndividualBytes);
+
+ /**
+ * change state to FINAL
+ */
+ filterState.state = State.STATE_FINAL;
+ setSessionState(session, filterState.state.toString());
+
+ break;
+
+ case STATE_FINAL:
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_UPDATE response");
+ }
+
+ /**
+ * send FINAL
+ */
+ byte[] finalKey = inisafeSession.finalHandShakeClient(message.getBytes());
+ String finalIndividualLL = CommonLib.getFormatString(finalKey.length+4, 4);
+ //byte[] paddedFinalKey = StringUtils.rightPad(new String(finalKey), 92).getBytes();
+
+ buffer = ByteBuffer.allocate(4+finalKey.length).limit(4+finalKey.length);
+ buffer.put(finalIndividualLL.getBytes());
+ buffer.put(finalKey);
+
+ byte[] finalIndividualBytes = new byte[4+finalKey.length];
+ buffer.position(0).get(finalIndividualBytes);
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | KEY_FINAL");
+ }
+ session.write(finalIndividualBytes);
+
+ /**
+ * change state
+ */
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ /**
+ * finish handshake
+ */
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ adapter.addRecentLog(context.getAdapterName() + " | InisafeClientFilter | handshake finished ...");
+ logger.debug(context.getAdapterName() + " | InisafeClientFilter | handshake finished ...");
+ }
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+
+ break;
+
+ case STATE_MESSAGE:
+ validateMessage(message);
+ message = decrypt(message, session);
+ nextFilter.messageReceived(session, message);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + message);
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+ nextFilter.filterClose(session);
+
+ adapter.getSessionPool().remove(session);
+ session.close();
+ throw new Exception(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeFilter.java
new file mode 100644
index 0000000..5665406
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeFilter.java
@@ -0,0 +1,210 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020.handshake;
+
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.common.util.Logger;
+import com.initech.inisafenet.HandShakeManager;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+
+abstract public class InisafeFilter extends IoFilterAdapter {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+// private static final String NEXT_FILTER = InisafeFilter.class.getName() + ".NextFilter";
+ public static final String FILTER_STATE_KEY = InisafeFilter.class.getName() + ".STATE";
+
+ public static final String SESSION_STATE = "SESSION_STATE";
+ public static final String INISAFE_SESSION_KEY = "INISAFE_SESSION_KEY";
+ public static final byte[] INITIAL_VECTOR = "INISAFE NETWORK.".getBytes();
+
+ public static enum State {
+ STATE_START,
+ STATE_INIT,
+ STATE_UPDATE,
+ STATE_FINAL,
+ STATE_MESSAGE;
+ }
+
+ public static class FilterState {
+ public State state = null;
+ public byte[] key; // token?
+
+ public FilterState() {}
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ protected byte[] cert;
+ protected byte[] key;
+ protected String password;
+ protected byte[] remoteCert;
+
+// static {
+// new InitechProvider();
+// }
+
+ public InisafeFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ synchronized(session) {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ filterState.state = State.STATE_INIT;
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ //setSessionState(session, filterState.state.toString());
+ }
+ }
+
+ // handshake future
+ session.setAttribute(ProtocolHandler.HANDSHAKE_FUTURE, new SimpleFuture());
+ }
+
+ @Override
+ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
+// HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+// inisafeSession.close();
+
+ nextFilter.sessionClosed(session);
+ }
+
+
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+ ByteMessage m = null;
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteBuffer) {
+ m = new ByteMessage((ByteBuffer) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ /**
+ * encrypt
+ */
+ try {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+// HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+
+ switch (filterState.state) {
+ case STATE_MESSAGE:
+ validateMessage(m);
+// String sessionState = (String) session.getAttribute(ProtocolHandler.SESSION_STATE);
+ m = encrypt(m, session);
+ break;
+
+ default:
+ break;
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+ throw new Exception(context.getAdapterName() + " | initech error - " + e.getMessage());
+ }
+
+ nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+
+ @Override
+ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState.state != State.STATE_MESSAGE){
+ StringBuffer sb = new StringBuffer();
+ sb.append("idle:" + TimeUtil.elapsedTime(session.getLastIoTime()));
+ sb.append(", handshake timeout:" + (context.getTimeout() -5));
+ sb.append(", protocol:" + context.getProtocol());
+ if (filterState != null) {
+ sb.append(", state:" + filterState.state.toString());
+ }
+ sb.append("/" + session.getAttribute(SESSION_STATE));
+ logger.error(context.getAdapterName() + " | handshake timeout -> disconnecting (" + session + ") " + sb.toString());
+ adapter.addRecentError(context.getAdapterName() + " | handshake timeout -> disconnecting (" + session + ") " + sb.toString());
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ adapter.getSessionPool().remove(session);
+ session.close();
+
+
+ }else{
+ nextFilter.sessionIdle(session, status);
+ }
+ }
+
+ protected String getSessionState(IoSession session) {
+ return (String) session.getAttribute(SESSION_STATE);
+ }
+
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+
+
+ protected void validateMessage(ByteMessage m) throws Exception {
+ if (m.size() < 200) {
+ throw new Exception("cannot send message - message size < 200 - " + m.hexDump());
+ }
+
+ String ll = new String(m.getBytes(0, 5));
+ if (!ll.matches("[0-9]{5}")) {
+ throw new Exception("ll field (0-5) of message is not number - " + m.hexDump());
+ }
+ }
+
+
+ protected ByteMessage encrypt(ByteMessage m, IoSession session) throws Exception {
+ /**
+ * 암호화 여부 체크
+ */
+ if ('Y' != m.getByte(99))
+ return m;
+
+ HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+ byte[] encryptPart = inisafeSession.encrypt(m.getBytes(200-16-16));
+ ByteMessage encrypted = new ByteMessage(m.getBytes(0, 200-16-16)).append(encryptPart);
+
+ return encrypted;
+ }
+
+ protected ByteMessage decrypt(ByteMessage m, IoSession session) throws Exception {
+ /**
+ * 암호화 여부 체크
+ */
+ if (m == null || 'Y' != m.getByte(99))
+ return m;
+
+ HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+ byte[] decryptPart = inisafeSession.decrypt(m.getBytes(200-16-16));
+ ByteMessage decrypted = new ByteMessage(m.getBytes(0, 200-16-16)).append(decryptPart);
+
+ return decrypted;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeServerFilter.java
new file mode 100644
index 0000000..bd7cba2
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafe2020/handshake/InisafeServerFilter.java
@@ -0,0 +1,203 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafe2020.handshake;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.initech.inisafenet.HandShakeManager;
+import com.initech.inisafenet.exception.INISAFENetException;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeServerFilter extends InisafeFilter {
+ public InisafeServerFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ try {
+ HandShakeManager inisafeSession = new HandShakeManager(context.getInisafeConfigPath());
+ session.setAttribute(INISAFE_SESSION_KEY, inisafeSession);
+ } catch(INISAFENetException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ //validateMessage(m);
+ process(nextFilter, session, m);
+ }
+
+ protected void process(NextFilter nextFilter, IoSession session, ByteMessage message) throws Exception {
+ HandShakeManager inisafeSession = null;
+
+ try {
+ /**
+ * get filter state
+ */
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ /**
+ * check inisafe session
+ */
+ inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+ if (inisafeSession == null) {
+ throw new Exception("inisafe session is not established");
+ }
+
+ /**
+ * state machine
+ */
+ ByteBuffer buffer = null;
+
+ switch (filterState.state) {
+ case STATE_INIT:
+ /*
+ * handshake timeout 설정함
+ * timeout 에서 5초 전 설정
+ */
+ if (context.getTimeout() <= 5 ) {
+ throw new Exception("invalid timeout("+context.getTimeout()+") value . set timeout must be 5 or more. ");
+ }
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_INIT");
+ }
+
+ /**
+ * send INIT response
+ */
+ byte[] initKey = inisafeSession.initHandShake(message.getBytes());
+ String initIndividualLL = CommonLib.getFormatString(initKey.length+4, 4);
+ //byte[] paddedInitKey = StringUtils.rightPad(new String(initKey), 1792).getBytes();
+
+ buffer = ByteBuffer.allocate(4+initKey.length).limit(4+initKey.length);
+ buffer.put(initIndividualLL.getBytes());
+ buffer.put(initKey);
+
+ byte[] initIndividualBytes = new byte[4+initKey.length];
+ buffer.position(0).get(initIndividualBytes);
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_INIT response");
+ }
+ session.write(initIndividualBytes);
+
+ /**
+ * change state to UPDATE
+ */
+ filterState.state = State.STATE_UPDATE;
+ setSessionState(session, filterState.state.toString());
+
+ break;
+
+ case STATE_UPDATE:
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_UPDATE");
+ }
+
+ /**
+ * send UPDATE response
+ */
+ byte[] updateKey = inisafeSession.updateHandShake(message.getBytes());
+ String updateIndividualLL = CommonLib.getFormatString(updateKey.length+4, 4);
+ //byte[] paddedUpdateKey = StringUtils.rightPad(new String(updateKey), 108).getBytes();
+
+ buffer = ByteBuffer.allocate(4+updateKey.length).limit(4+updateKey.length);
+ buffer.put(updateIndividualLL.getBytes());
+ buffer.put(updateKey);
+
+ byte[] updateIndividualBytes = new byte[4+updateKey.length];
+ buffer.position(0).get(updateIndividualBytes);
+
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_UPDATE response");
+ }
+ session.write(updateIndividualBytes);
+
+ /**
+ * change state to FINAL
+ */
+ filterState.state = State.STATE_FINAL;
+ setSessionState(session, filterState.state.toString());
+
+ break;
+
+ case STATE_FINAL:
+ if ( context.getTraceLevel() >= context.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | KEY_FINAL");
+ }
+ int result = inisafeSession.finalHandShake(message.getBytes());
+
+ if (result !=1){
+ throw new Exception(" invalid message during handshake .. : " + message);
+ }
+
+ /**
+ * change state to MESSAGE
+ */
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ /**
+ * start client pair socket adapter (in same socket adapter group)
+ */
+ ISocketAdapter[] adapters = SocketAdapterManager.getInstance().getSocketAdapters(adapter.getContext().getAdapterGroupName());
+ if(adapters == null) return;
+ for (int i=0; i= context.TRACE_LEVEL_DEBUG ) {
+ adapter.addRecentLog("InisafeServerFilter | handshake finished ...");
+ logger.debug(context.getAdapterName() + " | InisafeServerFilter | handshake finished ...");
+ }
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ //nextFilter.messageReceived(session, new ByteMessage("STARTED"));
+
+ break;
+
+ case STATE_MESSAGE:
+ validateMessage(message);
+ message = decrypt(message, session);
+ nextFilter.messageReceived(session, message);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + message);
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+
+ nextFilter.filterClose(session);
+
+ adapter.getSessionPool().remove(session);
+ session.close();
+
+ throw new Exception(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnErrorMessage.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnErrorMessage.java
new file mode 100644
index 0000000..db2832e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnErrorMessage.java
@@ -0,0 +1,27 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn;
+
+import java.util.Hashtable;
+
+
+public class InisafeNatnErrorMessage {
+ static Hashtable hash = new Hashtable<>();
+
+ static {
+ hash.put("-1910", "ERR_POLICY_RESERVED_CN | 이미 등록되어 있은 CN 입니다.");
+ }
+
+ private InisafeNatnErrorMessage() {
+
+ }
+ public static String getErrorMessage(String key) {
+ String value = hash.get(key);
+ if (value == null) {
+ return "Unknown Error.";
+ }
+ return value;
+ }
+
+ public static String getErrorMessage(int key) {
+ return getErrorMessage(String.valueOf(key));
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadClient.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadClient.java
new file mode 100644
index 0000000..cecdd74
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadClient.java
@@ -0,0 +1,39 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn;
+
+import com.eactive.eai.adapter.socket2.common.Env;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.TcpAdapterClient;
+import com.eactive.eai.adapter.socket2.protocol.inisafenatn.codec.InisafeNatnPayloadCodecFactory;
+import com.eactive.eai.adapter.socket2.protocol.inisafenatn.handshake.InisafeNatnPayloadClientFilter;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+
+
+public class InisafeNatnPayloadClient extends TcpAdapterClient {
+ boolean isBooting = true;
+
+ public InisafeNatnPayloadClient(SocketAdapterContext context) throws Exception {
+ super(context);
+
+ this.handler = new InisafeNatnPayloadClientHandler(this);
+
+ config.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new InisafeNatnPayloadCodecFactory(this)));
+ config.getFilterChain().addAfter("codec", "inisafe.codec", new InisafeNatnPayloadClientFilter(this));
+ }
+
+ @Override
+ public SimpleFuture start() throws Exception {
+ if (isBooting && !Env.isTest()) {
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_INFO) {
+ logger.info(context.getAdapterName() + " | InisafeNatnPayloadClient protocol - skip start process when booting ...");
+ }
+ isBooting = false;
+
+ SimpleFuture future = new SimpleFuture();
+ future.set(Boolean.TRUE);
+ return future;
+ } else {
+ return super.start();
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadClientHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadClientHandler.java
new file mode 100644
index 0000000..00d016e
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadClientHandler.java
@@ -0,0 +1,40 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn;
+
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import org.apache.mina.common.IoSession;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class InisafeNatnPayloadClientHandler extends InisafeNatnPayloadHandler {
+ public InisafeNatnPayloadClientHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ @Override
+ public void sessionOpened(IoSession session) throws Exception {
+ super.sessionOpened(session);
+ }
+
+ @Override
+ public void sessionClosed(IoSession session) throws Exception {
+ super.sessionClosed(session);
+ /**
+ * client-server pair 로 작업한다.
+ */
+ doSessionClosed(session);
+ }
+
+ protected String messageReplace (String str){
+ Matcher matcher = Pattern.compile("%d\\{([a-zA-Z \\-]+)\\}").matcher(str);
+
+ while (matcher.find()) {
+ String datePattern = matcher.group(1);
+ DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(datePattern);
+ str = str.replaceFirst("%d\\{([a-zA-Z \\-]+)\\}", dateFormat.format(ZonedDateTime.now()));
+ }
+ return str;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadHandler.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadHandler.java
new file mode 100644
index 0000000..bc94ddb
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/InisafeNatnPayloadHandler.java
@@ -0,0 +1,38 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn;
+
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeNatnPayloadHandler extends ProtocolHandler {
+ public InisafeNatnPayloadHandler(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+ protected void doSessionClosed (IoSession session) throws Exception {
+ /**
+ * client-server pair (in same adapter group)
+ */
+
+ ISocketAdapter[] adapters = SocketAdapterManager.getInstance().getSocketAdapters(adapter.getContext().getAdapterGroupName());
+ if(adapters == null) return;
+ for (int i=0; i= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnPayloadDecoder | handshake : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "InisafeNatnPayloadDecoder | handshake : " + CommonLib.hexDump(in, context));
+ }
+
+ CodecState codecState = (CodecState) session.getAttribute(H_DECODER_STATE_KEY);
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(InisafeNatnPayloadConstants.COMMON_LENGTH); // LL Field 길이값(4): 전체전문 - LL필드길이
+ session.setAttribute(H_DECODER_STATE_KEY, codecState);
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+
+ switch (codecState.state) {
+ case STATE_HEADER_READ:
+ if (readHeader(session, codecState, in)) { //length 읽은 이후?
+ //데이터 읽기
+ codecState.buffer.position(InisafeNatnPayloadConstants.COMMON_LENGTH).limit(4+codecState.payloadSize);
+ codecState.state = State.STATE_PAYLOAD_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ case STATE_PAYLOAD_READ:
+ if (readPayload(session, codecState, in)) {
+ //암호화 부분 : (length) + 암호회
+ byte[] individualLL = new byte[4];
+ codecState.buffer.position(InisafeNatnPayloadConstants.COMMON_LENGTH).get(individualLL);
+ int individualLength = Integer.parseInt(new String(individualLL));
+ byte[] bytes = new byte[individualLength-4];
+ codecState.buffer.position(InisafeNatnPayloadConstants.COMMON_LENGTH+4).get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(InisafeNatnPayloadConstants.COMMON_LENGTH);
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ codecState.state = State.STATE_HEADER_READ;
+ session.setAttribute(ProtocolHandler.CODEC_STATE, codecState.state.toString());
+ }
+ break;
+ default :
+ }
+
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private void decodeMessage(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_TRACE ) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnPayloadDecoder | decode : " + CommonLib.hexDump(in, context));
+ adapter.addRecentRecvTrace(session, "InisafeNatnPayloadDecoder | decode : " + CommonLib.hexDump(in, context));
+ }
+
+ CodecState codecState = (CodecState) session.getAttribute(DECODER_STATE_KEY);
+
+ int ll = context.getLlFieldLength();
+ if (codecState == null) {
+ codecState = new CodecState();
+ codecState.buffer.limit(ll + context.getRecvPayloadLength());
+ session.setAttribute(DECODER_STATE_KEY, codecState);
+ }
+
+ while(in.hasRemaining()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout());
+ if (readPayload(session, codecState, in)) {
+ byte[] bytes = new byte[codecState.buffer.limit() - ll];
+ codecState.buffer.position(ll);
+ codecState.buffer.get(bytes);
+ ByteMessage message = new ByteMessage(bytes);
+ out.write(message);
+
+ codecState.buffer.position(0).limit(ll + context.getRecvPayloadLength());
+
+ if (context.isClient() && context.isPermanent() && context.isPollingUse()) {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getPollingTimeout());
+ } else {
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getIdleTimeout());
+ }
+ }
+ session.setAttribute(ProtocolHandler.CODEC_STATE_BUFFER, CommonLib.hexDumpRead(codecState.buffer, context));
+ }
+ }
+
+ private boolean readHeader(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ codecState.buffer.flip();
+ try {
+ byte[] commonLL = new byte[4];
+ codecState.buffer.position(0).get(commonLL);
+ codecState.payloadSize = Integer.parseInt(new String(commonLL)); //전문 전체 크기
+ codecState.buffer.position(0);
+ } catch (NumberFormatException e) {
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA008");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA008");
+ throw new EAIException("RECEAINNA008", context.getAdapterName() +
+ "when read header, number format is invalid - "
+ + e.getMessage() + " | " + CommonLib.hexDump(codecState.buffer, context));
+ }
+
+ if (codecState.payloadSize > MAX_PAYLOAD_SIZE) {
+ throw new Exception("max payload size(" + MAX_PAYLOAD_SIZE + ") exceeded : " + codecState.payloadSize);
+ }
+
+ return true;
+ }
+
+ private boolean readPayload(IoSession session, CodecState codecState, ByteBuffer in) throws Exception {
+ if (codecState.buffer.remaining() > in.remaining()) {
+ codecState.buffer.put(in);
+ return false;
+ }
+
+ while(codecState.buffer.hasRemaining()) {
+ codecState.buffer.put(in.get());
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/codec/InisafeNatnPayloadEncoder.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/codec/InisafeNatnPayloadEncoder.java
new file mode 100644
index 0000000..c00e8dd
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/codec/InisafeNatnPayloadEncoder.java
@@ -0,0 +1,177 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn.codec;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.inisafenatn.handshake.InisafeNatnPayloadFilter;
+import com.eactive.eai.adapter.socket2.protocol.inisafenatn.handshake.InisafeNatnPayloadFilter.FilterState;
+import com.eactive.eai.common.util.Logger;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class InisafeNatnPayloadEncoder implements ProtocolEncoder {
+ final protected Logger logger;
+ final protected Logger errLogger;
+
+ SocketAdapterContext context;
+ ISocketAdapter adapter;
+
+ public InisafeNatnPayloadEncoder(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+ ByteMessage m = null;
+ if (message == null) {
+ throw new Exception("cannot write null message.");
+ } else if (message instanceof ByteMessage) {
+ m = (ByteMessage) message;
+ } else if (message instanceof String) {
+ m = new ByteMessage((String) message);
+ } else if (message instanceof byte[]) {
+ m = new ByteMessage((byte[]) message);
+ } else {
+ throw new Exception("cannot write unknow format message.");
+ }
+
+ boolean isHandshakeState = false;
+ FilterState filterState = (FilterState) session.getAttribute(InisafeNatnPayloadFilter.FILTER_STATE_KEY);
+ if (filterState != null && filterState.state != InisafeNatnPayloadFilter.State.STATE_MESSAGE) {
+ isHandshakeState = true;
+ }
+
+ if (isHandshakeState) {
+ encodeHandshake(session, m, out);
+ } else {
+ encodeMessage(session, m, out);
+ }
+ }
+
+
+ private void encodeHandshake(IoSession session, ByteMessage m, ProtocolEncoderOutput out) throws Exception {
+ int length = m.size();
+ int totalLength = InisafeNatnPayloadConstants.COMMON_LENGTH + length;
+
+ ByteBuffer buffer = ByteBuffer.allocate(totalLength).limit(totalLength);
+
+ /**
+ * [1] common ll
+ */
+ String commonLL = CommonLib.getFormatString(totalLength-InisafeNatnPayloadConstants.COMMON_LL_LENGTH, InisafeNatnPayloadConstants.COMMON_LL_LENGTH);
+ buffer.put(commonLL.getBytes()); // 1 전문송신 Byte 수 4 N * 비고 1) 참조
+
+ /**
+ * [2] common rest
+ */
+ buffer.put(getTransactionType(session)); // 2 거래구분코드 9 A
+ buffer.put("00".getBytes()); // 3 업무코드 2 A * Space
+ buffer.put("00".getBytes()); // 4 거래종류코드 2 A * Space
+ buffer.put(" ".getBytes()); // 5 요청응답구분코드 1 A * Space
+ buffer.put(" ".getBytes()); // 6 송신기관코드 3 A * Space
+ buffer.put(" ".getBytes()); // 7 수신기관코드 3 A * Space
+ buffer.put(" ".getBytes()); // 8 거래일자 8 N * Space
+ buffer.put(" ".getBytes()); // 9 거래시각 6 N * Space
+ buffer.put(" ".getBytes()); // 10 전문관리번호 7 N * Space
+ buffer.put(" ".getBytes()); // 11 처리기관코드 3 N * Space
+ buffer.put(" ".getBytes()); // 12 처리결과코드 4 A * Space
+ buffer.put(" ".getBytes()); // 13 코드변환구분 1 A * Space
+ buffer.put(StringUtils.leftPad("", 61).getBytes()); // 14 공란1 61 A * Space
+ buffer.put(StringUtils.leftPad("", 20).getBytes()); // 15 사용자ID 20 A * Space
+ buffer.put(" ".getBytes()); // 16 Password 8 A * Space
+
+ /**
+ * [3] individual part
+ */
+ buffer.put(m.getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnPayloadEncoder | encode (handshake) : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "InisafeNatnPayloadEncoder | encode (handshake) : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+
+ private byte[] getTransactionType(IoSession session) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(InisafeNatnPayloadFilter.FILTER_STATE_KEY);
+ if (filterState == null) {
+ throw new Exception("session does not have filter state");
+ }
+
+ switch (filterState.state) {
+ case STATE_INIT :
+ if (adapter.getContext().isClient()) {
+ return "000000001".getBytes();
+ } else {
+ return "000000002".getBytes();
+ }
+ case STATE_UPDATE :
+ if (adapter.getContext().isClient()) {
+ return "000000003".getBytes();
+ } else {
+ return "000000004".getBytes();
+ }
+ case STATE_FINAL :
+ return "000000005".getBytes();
+ default :
+ throw new Exception("invalid state");
+ }
+ }
+
+ private void encodeMessage(IoSession session, ByteMessage m, ProtocolEncoderOutput out) throws Exception {
+ /**
+ * copy byte[] to buffer
+ */
+ int length = m.size();
+ //ByteBuffer buffer = ByteBuffer.allocate(length).limit(length);
+ ByteBuffer buffer = ByteBuffer.allocate(context.getLlFieldLength() + length).limit(context.getLlFieldLength() + length);
+
+ /**
+ * ll.include = 'Y' - 길이필드 붙이기
+ * BOK - payload 사이즈 ll필드를 붙이는 기관이 존재
+ */
+// if ("Y".equals(context.getLlInclude())) {
+// String lenStr = CommonLib.getFormatString(context.getSendPayloadLength(), context.getLlFieldLength());
+// buffer.put(lenStr.getBytes());
+// }
+ if(context.getLlFieldLength() > 0){
+ String lenStr = CommonLib.getFormatString(context.getSendPayloadLength(), context.getLlFieldLength());
+ buffer.put(lenStr.getBytes());
+ }
+
+ buffer.put(m.getBytes());
+
+ /**
+ * write
+ */
+ int mark = buffer.position();
+ buffer.position(0);
+ if (context.getTraceLevel() >= context.TRACE_LEVEL_TRACE) {
+ logger.debug(context.getAdapterName() + " | InisafeEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ adapter.addRecentSendTrace(session, "InisafeEncoder | encode : " + CommonLib.hexDump(buffer, context));
+ }
+ buffer.position(mark);
+ buffer.flip();
+ out.write(buffer);
+ }
+
+
+ public void dispose(IoSession session) throws Exception {
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadClientFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadClientFilter.java
new file mode 100644
index 0000000..a143352
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadClientFilter.java
@@ -0,0 +1,189 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn.handshake;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.initech.inisafenet.HandShakeManager;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeNatnPayloadClientFilter extends InisafeNatnPayloadFilter {
+ public InisafeNatnPayloadClientFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ HandShakeManager inisafeSession = new HandShakeManager(context.getInisafeConfigPath());
+// inisafeSession.TEST_MODE = false;
+ session.setAttribute(INISAFE_SESSION_KEY, inisafeSession);
+
+ process(nextFilter, session, null);
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ process(nextFilter, session, m);
+ }
+
+ protected void process(NextFilter nextFilter, IoSession session, ByteMessage message) throws Exception {
+ try {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+ HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+
+ /**
+ * State machine
+ */
+ ByteBuffer buffer = null;
+
+ switch (filterState.state) {
+ case STATE_INIT:
+ /*
+ * handshake timeout 설정함
+ * timeout 에서 5초 전 설정
+ */
+ if (context.getTimeout() <= 5 ) {
+ throw new Exception("invalid timeout("+context.getTimeout()+") value . set timeout must be 5 or more. ");
+ }
+ session.setIdleTime(IdleStatus.BOTH_IDLE, context.getTimeout() - 5);
+ /**
+ * change state to INIT
+ */
+ filterState.state = State.STATE_INIT;
+ session.setAttribute(SESSION_STATE, filterState.state.toString());
+
+ /**
+ * create INIT key
+ */
+ byte[] initKey = inisafeSession.initHandShakeClient(null);
+ String initIndividualLL = CommonLib.getFormatString(initKey.length+4, 4);
+ //byte[] paddedInitKey = StringUtils.rightPad(new String(initKey), 92).getBytes();
+
+ buffer = ByteBuffer.allocate(4+initKey.length).limit(4+initKey.length);
+ buffer.put(initIndividualLL.getBytes());
+ buffer.put(initKey);
+
+ byte[] initIndividualBytes = new byte[4+initKey.length];
+ buffer.position(0).get(initIndividualBytes);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnClientFilter | KEY_INIT");
+ }
+ session.write(initIndividualBytes);
+
+ /**
+ * change state to UPDATE
+ */
+ filterState.state = State.STATE_UPDATE;
+ setSessionState(session, filterState.state.toString());
+ break;
+
+ case STATE_UPDATE:
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnClientFilter | KEY_INIT response");
+ }
+ if(message == null) throw new Exception("Message is NULL");
+ /**
+ * send UPDATE
+ */
+ byte[] updateKey = inisafeSession.updateHandShakeClient(message.getBytes());
+ String updateIndividualLL = CommonLib.getFormatString(updateKey.length+4, 4);
+ //byte[] paddedUpdateKey = StringUtils.rightPad(new String(updateKey), 268).getBytes();
+
+ buffer = ByteBuffer.allocate(4+updateKey.length).limit(4+updateKey.length);
+ buffer.put(updateIndividualLL.getBytes());
+ buffer.put(updateKey);
+
+ byte[] updateIndividualBytes = new byte[4+updateKey.length];
+ buffer.position(0).get(updateIndividualBytes);
+
+ if (context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnClientFilter | KEY_UPDATE");
+ }
+ session.write(updateIndividualBytes);
+
+ /**
+ * change state to FINAL
+ */
+ filterState.state = State.STATE_FINAL;
+ setSessionState(session, filterState.state.toString());
+
+ break;
+
+ case STATE_FINAL:
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnClientFilter | KEY_UPDATE response");
+ }
+ if(message == null) throw new Exception("Message is NULL");
+ /**
+ * send FINAL
+ */
+ byte[] finalKey = inisafeSession.finalHandShakeClient(message.getBytes());
+ String finalIndividualLL = CommonLib.getFormatString(finalKey.length+4, 4);
+ //byte[] paddedFinalKey = StringUtils.rightPad(new String(finalKey), 92).getBytes();
+
+ buffer = ByteBuffer.allocate(4+finalKey.length).limit(4+finalKey.length);
+ buffer.put(finalIndividualLL.getBytes());
+ buffer.put(finalKey);
+
+ byte[] finalIndividualBytes = new byte[4+finalKey.length];
+ buffer.position(0).get(finalIndividualBytes);
+
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnClientFilter | KEY_FINAL");
+ }
+ session.write(finalIndividualBytes);
+
+ /**
+ * change state
+ */
+ filterState.state = State.STATE_MESSAGE;
+ setSessionState(session, filterState.state.toString());
+
+ /**
+ * finish handshake
+ */
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ adapter.addRecentLog(context.getAdapterName() + " | InisafeNatnClientFilter | handshake finished ...");
+ logger.debug(context.getAdapterName() + " | InisafeNatnClientFilter | handshake finished ...");
+ }
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+
+ break;
+
+ case STATE_MESSAGE:
+ if(message == null) throw new Exception("Message is NULL");
+ //validateMessage(message);
+ message = decrypt(message, session);
+ nextFilter.messageReceived(session, message);
+ break;
+
+ default:
+ throw new Exception(" invalid message during handshake .. : " + message);
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+ nextFilter.filterClose(session);
+
+ adapter.getSessionPool().remove(session);
+ session.close();
+ throw new Exception(context.getAdapterName() + " | inisafe error - " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadFilter.java
new file mode 100644
index 0000000..9442c02
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadFilter.java
@@ -0,0 +1,209 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn.handshake;
+
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.common.SimpleFuture;
+import com.eactive.eai.adapter.socket2.common.TimeUtil;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.eactive.eai.adapter.socket2.protocol.ProtocolHandler;
+import com.eactive.eai.adapter.socket2.protocol.inisafenatn.codec.InisafeNatnPayloadConstants;
+import com.eactive.eai.common.util.Logger;
+import com.initech.inisafenet.HandShakeManager;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+
+public abstract class InisafeNatnPayloadFilter extends IoFilterAdapter {
+ protected final Logger logger;
+ protected final Logger errLogger;
+ private final Object lockObj = new Object();
+// private static final String NEXT_FILTER = InisafeNatnPayloadFilter.class.getName() + ".NextFilter";
+ public static final String FILTER_STATE_KEY = InisafeNatnPayloadFilter.class.getName() + ".STATE";
+
+ public static final String SESSION_STATE = "SESSION_STATE";
+ public static final String INISAFE_SESSION_KEY = "INISAFE_SESSION_KEY";
+ public static final byte[] INITIAL_VECTOR = "INISAFE NETWORK.".getBytes();
+
+ public enum State {
+ STATE_START,
+ STATE_INIT,
+ STATE_UPDATE,
+ STATE_FINAL,
+ STATE_MESSAGE;
+ }
+
+ public static class FilterState {
+ public State state = null;
+ public byte[] key; // token?
+
+ public FilterState() {}
+ }
+
+ protected SocketAdapterContext context;
+ protected ISocketAdapter adapter;
+
+ protected byte[] cert;
+ protected byte[] key;
+ protected String password;
+ protected byte[] remoteCert;
+
+/* static {
+ new InitechProvider();
+ }*/
+
+ public InisafeNatnPayloadFilter(ISocketAdapter adapter) {
+ this.adapter = adapter;
+ this.context = adapter.getContext();
+
+ logger = SocketLoggerManager.getInstance().getLogger(context.getAdapterGroupName());
+ errLogger = SocketLoggerManager.getInstance().getErrLogger();
+ }
+
+ @Override
+ public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
+ synchronized(lockObj) {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ filterState.state = State.STATE_INIT;
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ //setSessionState(session, filterState.state.toString());
+ }
+ }
+
+ // handshake future
+ session.setAttribute(ProtocolHandler.HANDSHAKE_FUTURE, new SimpleFuture());
+ }
+
+ @Override
+ public void sessionClosed(NextFilter nextFilter, IoSession session) throws Exception {
+// HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+// inisafeSession.close();
+
+ nextFilter.sessionClosed(session);
+ }
+
+
+ @Override
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
+ ByteMessage m = null;
+
+ if (writeRequest.getMessage() instanceof byte[]) {
+ m = new ByteMessage((byte[]) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteMessage) {
+ m = (ByteMessage) writeRequest.getMessage();
+ } else if (writeRequest.getMessage() instanceof String) {
+ m = new ByteMessage((String) writeRequest.getMessage());
+ } else if (writeRequest.getMessage() instanceof ByteBuffer) {
+ m = new ByteMessage((ByteBuffer) writeRequest.getMessage());
+ } else {
+ throw new Exception("Unknown data format");
+ }
+
+ /**
+ * encrypt
+ */
+ try {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+// HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+
+ switch (filterState.state) {
+ case STATE_MESSAGE:
+ //validateMessage(m);
+// String sessionState = (String) session.getAttribute(ProtocolHandler.SESSION_STATE);
+ m = encrypt(m, session);
+ break;
+
+ default:
+ break;
+ }
+ } catch(Exception e) {
+ adapter.addRecentError(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ logger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+ errLogger.error(context.getAdapterName() + " | initech error - " + e.getMessage(), e);
+// SMSLogger.loggingSMSWithCode(context.getAdapterName(), "RECEAINNA012");
+ SMSLogger.loggingSMS4Soc(context.getAdapterName(), context.getDescription(), "RECEAINNA012");
+ throw new Exception(context.getAdapterName() + " | initech error - " + e.getMessage());
+ }
+
+ nextFilter.filterWrite(session, new WriteRequest(m, writeRequest.getFuture(), writeRequest.getDestination()));
+ }
+
+ @Override
+ public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if(filterState == null) {
+ logger.error(context.getAdapterName() + " | filterState is NULL");
+ }
+ else {
+ if (filterState.state != State.STATE_MESSAGE){
+ StringBuilder sb = new StringBuilder();
+ sb.append("idle:" + TimeUtil.elapsedTime(session.getLastIoTime()));
+ sb.append(", handshake timeout:" + (context.getTimeout() -5));
+ sb.append(", protocol:" + context.getProtocol());
+ sb.append(", state:" + filterState.state.toString());
+ sb.append("/" + session.getAttribute(SESSION_STATE));
+ logger.error(context.getAdapterName() + " | handshake timeout -> disconnecting (" + session + ") " + sb.toString());
+ adapter.addRecentError(context.getAdapterName() + " | handshake timeout -> disconnecting (" + session + ") " + sb.toString());
+
+ nextFilter.sessionCreated(session);
+ nextFilter.sessionOpened(session);
+ adapter.getSessionPool().remove(session);
+ session.close();
+ }else{
+ nextFilter.sessionIdle(session, status);
+ }
+ }
+ }
+
+ protected String getSessionState(IoSession session) {
+ return (String) session.getAttribute(SESSION_STATE);
+ }
+
+
+ protected void setSessionState(IoSession session, String state) {
+ session.setAttribute(SESSION_STATE, state);
+ }
+
+
+ protected void validateMessage(ByteMessage m) throws Exception {
+ if (m.size() < 200) {
+ throw new Exception("cannot send message - message size < 200 - " + m.hexDump());
+ }
+
+ String ll = new String(m.getBytes(0, 5));
+ if (!ll.matches("[0-9]{5}")) {
+ throw new Exception("ll field (0-5) of message is not number - " + m.hexDump());
+ }
+ }
+
+
+ protected ByteMessage encrypt(ByteMessage m, IoSession session) throws Exception {
+
+ HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+ int llLen = 0;
+
+// if ("Y".equals(context.getLlInclude())) {
+// llLen = 4;
+// }
+
+ byte[] encryptPart = inisafeSession.encrypt(m.getBytes(InisafeNatnPayloadConstants.UN_ENC_LENGTH+llLen));
+ return new ByteMessage(m.getBytes(0, InisafeNatnPayloadConstants.UN_ENC_LENGTH)).append(encryptPart);
+ }
+
+ protected ByteMessage decrypt(ByteMessage m, IoSession session) throws Exception {
+
+ HandShakeManager inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+
+ int llLen = 0;
+// if ("Y".equals(context.getLlInclude())) {
+// llLen = 4;
+// }
+ byte[] decryptPart = inisafeSession.decrypt(m.getBytes(InisafeNatnPayloadConstants.UN_ENC_LENGTH+llLen));
+ return new ByteMessage(m.getBytes(0, InisafeNatnPayloadConstants.UN_ENC_LENGTH)).append(decryptPart);
+ }
+}
diff --git a/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadServerFilter.java b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadServerFilter.java
new file mode 100644
index 0000000..8226d02
--- /dev/null
+++ b/src/main/java/com/eactive/eai/adapter/socket2/protocol/inisafenatn/handshake/InisafeNatnPayloadServerFilter.java
@@ -0,0 +1,205 @@
+package com.eactive.eai.adapter.socket2.protocol.inisafenatn.handshake;
+
+import com.eactive.eai.adapter.socket2.common.CommonLib;
+import com.eactive.eai.adapter.socket2.common.SMSLogger;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterContext;
+import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
+import com.eactive.eai.adapter.socket2.protocol.ByteMessage;
+import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
+import com.initech.inisafenet.HandShakeManager;
+import com.initech.inisafenet.exception.INISAFENetException;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+
+
+public class InisafeNatnPayloadServerFilter extends InisafeNatnPayloadFilter {
+ public InisafeNatnPayloadServerFilter(ISocketAdapter adapter) {
+ super(adapter);
+ }
+
+
+ @Override
+ public void sessionOpened(NextFilter nextFilter, IoSession session) throws Exception {
+ try {
+ //KeyStorageManager ksm = new KeyStorageManager(null);
+ HandShakeManager inisafeSession = new HandShakeManager(context.getInisafeConfigPath());
+ session.setAttribute(INISAFE_SESSION_KEY, inisafeSession);
+ } catch(INISAFENetException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
+ ByteMessage m = (ByteMessage) message;
+ //validateMessage(m);
+ process(nextFilter, session, m);
+ }
+
+ protected void process(NextFilter nextFilter, IoSession session, ByteMessage message) throws Exception {
+ HandShakeManager inisafeSession = null;
+
+ try {
+ /**
+ * get filter state
+ */
+ FilterState filterState = (FilterState) session.getAttribute(FILTER_STATE_KEY);
+ if (filterState == null) {
+ filterState = new FilterState();
+ session.setAttribute(FILTER_STATE_KEY, filterState);
+ }
+
+ /**
+ * check inisafe session
+ */
+ inisafeSession = (HandShakeManager) session.getAttribute(INISAFE_SESSION_KEY);
+ if (inisafeSession == null) {
+ throw new Exception("inisafe session is not established");
+ }
+
+ /**
+ * state machine
+ */
+ ByteBuffer buffer = null;
+
+ switch (filterState.state) {
+ case STATE_INIT:
+ /*
+ * handshake timeout 설정함
+ * timeout 에서 5초 전 설정
+ */
+ if (context.getTimeout() <= 5 ) {
+ throw new Exception("invalid timeout("+context.getTimeout()+") value . set timeout must be 5 or more. ");
+ }
+ if ( context.getTraceLevel() >= SocketAdapterContext.TRACE_LEVEL_DEBUG ) {
+ logger.debug(context.getAdapterName() + " | InisafeNatnPayloadServerFilter |