share project nexacro-core

This commit is contained in:
ParkSeongMin
2015-10-13 00:29:20 +00:00
parent 1ee58e9e59
commit c523f11699
99 changed files with 9630 additions and 0 deletions

29
.classpath Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

41
.project Normal file
View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>nexacro-core</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8

View File

@@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="nexacro-core">
<wb-resource deploy-path="/" source-path="/src/main/java"/>
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
</wb-module>
</project-modules>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.7"/>
</faceted-project>

View File

@@ -0,0 +1,2 @@
disabled=06target
eclipse.preferences.version=1

21
install/maven.txt Normal file
View File

@@ -0,0 +1,21 @@
# central에 존재하지 않는 library는 아래 3개이다.
mvn install:install-file -Dfile=./lib/nexacro-xapi-1.0.jar -DgroupId=com.nexacro -DartifactId=nexacro-xapi -Dversion=1.0 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/nexacro-xeni-1.2.jar -DgroupId=com.nexacro -DartifactId=nexacro-xeni -Dversion=1.2 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/xstream-1.4.2.jar -DgroupId=xstream -DartifactId=xstream -Dversion=1.4.2 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/commons-logging-1.1.jar -DgroupId=commons-logging -DartifactId=commons-logging -Dversion=1.1 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/commons-codec-1.5.jar -DgroupId=commons-codec -DartifactId=commons-codec -Dversion=1.5 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/commons-fileupload-1.3.1.jar -DgroupId=commons-fileupload -DartifactId=commons-fileupload -Dversion=1.3.1 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/commons-io-2.2.jar -DgroupId=commons-io -DartifactId=commons-io -Dversion=2.2 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/dom4j-1.6.1.jar -DgroupId=dom4j -DartifactId=dom4j -Dversion=1.6.1 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/log4j-1.2.13.jar -DgroupId=log4j -DartifactId=log4j -Dversion=1.2.13 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/poi-3.9-20121203.jar -DgroupId=org.apache.poi -DartifactId=poi -Dversion=3.9 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/poi-ooxml-3.9-20121203.jar -DgroupId=org.apache.poi -DartifactId=poi-ooxml -Dversion=3.9 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/poi-ooxml-schemas-3.9-20121203.jar -DgroupId=org.apache.poi -DartifactId=poi-ooxml-schemas -Dversion=3.9 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/poi-scratchpad-3.9-20121203.jar -DgroupId=org.apache.poi -DartifactId=poi-scratchpad -Dversion=3.9 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/stax-api-1.0.1.jar -DgroupId=stax -DartifactId=stax-api -Dversion=1.0.1 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/xmlbeans-2.3.0.jar -DgroupId=org.apache.xmlbeans -DartifactId=xmlbeans -Dversion=2.3.0 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/xmlpull-1.1.3.1.jar -DgroupId=xmlpull -DartifactId=xmlpull -Dversion=1.1.3.1 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/xpp3_min-1.1.4c.jar -DgroupId=xpp3 -DartifactId=xpp3_min -Dversion=1.1.4c -Dpackaging=jar
mvn install:install-file -Dfile=./lib/able-core-1.2.1.jar -DgroupId=able -DartifactId=able-core -Dversion=1.2.1 -Dpackaging=jar

BIN
lib/commons-codec-1.5.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/commons-io-2.2.jar Normal file

Binary file not shown.

BIN
lib/commons-logging-1.1.jar Normal file

Binary file not shown.

BIN
lib/dom4j-1.6.1.jar Normal file

Binary file not shown.

BIN
lib/log4j-1.2.13.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/nexacro-xapi-1.0.jar Normal file

Binary file not shown.

BIN
lib/nexacro-xeni-1.2.jar Normal file

Binary file not shown.

BIN
lib/poi-3.9-20121203.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/stax-api-1.0.1.jar Normal file

Binary file not shown.

BIN
lib/xmlbeans-2.3.0.jar Normal file

Binary file not shown.

BIN
lib/xmlpull-1.1.3.1.jar Normal file

Binary file not shown.

BIN
lib/xpp3_min-1.1.4c.jar Normal file

Binary file not shown.

BIN
lib/xstream-1.4.2.jar Normal file

Binary file not shown.

182
pom.xml Normal file
View File

@@ -0,0 +1,182 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nexacro.spring</groupId>
<version>${project.parent.version}</version>
<artifactId>nexacro-core</artifactId>
<packaging>jar</packaging>
<name>nexacro-core</name>
<url>http://maven.apache.org</url>
<organization>
<name>nexacro-core Dev Group</name>
</organization>
<description>Description of nexacro-core</description>
<parent>
<groupId>com.nexacro</groupId>
<artifactId>nexacro-pom-parent</artifactId>
<version>1.0.0</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version><!--$NO-MVN-MAN-VER$-->
<configuration>
<argLine>
-Dsun.jnu.encoding=${encoding}
-Dfile.encoding=${encoding}
</argLine>
<systemPropertyVariables>
<sun.jnu.encoding>${encoding}</sun.jnu.encoding>
<file.encoding>${encoding}</file.encoding>
</systemPropertyVariables>
<skipTests>false</skipTests>
<reportFormat>xml</reportFormat>
<forkMode>once</forkMode>
<!-- "never" : Maven과 같은 process "once" (default) : 새로운
하나의 jvm process에서 모든 Test 실행 "always" : 각 Test 마다 다른 JVM process 실행 "perthread" -->
<!-- paralel mode setting -->
<parallel>classes</parallel><!-- classes, methods -->
<threadCount>10</threadCount>
<!-- <excludes> <exclude>**/Abstract*.java</exclude>
<exclude>**/*Suite.java</exclude> </excludes> <includes> <include>**/*Test.java</include>
</includes> -->
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.12</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.maven.ide.eclipse</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>0.9.9-SNAPSHOT</version>
<configuration>
<mappingId>generic</mappingId>
<configurators></configurators>
<mojoExecutions></mojoExecutions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.nexacro</groupId>
<artifactId>nexacro-xapi</artifactId>
<version>1.0</version>
<scope>compile</scope>
<systemPath></systemPath>
</dependency>
<!-- spring config -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.maven.artifact.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springmodules</groupId>
<artifactId>spring-modules-jakarta-commons</artifactId>
<version>0.8a</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.6</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<org.slf4j-version>1.7.5</org.slf4j-version>
</properties>
</project>

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@@ -0,0 +1,51 @@
package com.nexacro.spring;
/**
*
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConstants.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 5.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 5. Park SeongMin 최초 생성
* </pre>
*/
public final class NexacroConstants {
// attribute data
public final class ATTRIBUTE {
public static final String NEXACRO_REQUEST = "NexacroRequest";
public static final String NEXACRO_CACHE_DATA = "NexacroCachedData";
public static final String NEXACRO_PLATFORM_DATA = "NexacroPlatformData";
public static final String NEXACRO_FILE_DATA = "NexacroFileData";
}
// error
public final class ERROR {
public final static int DEFAULT_ERROR_CODE = 0;
public final static String ERROR_CODE = "ErrorCode"; // nexacro 결과 코드값 (ex '0' 이상 일경우 성공)
public final static String ERROR_MSG = "ErrorMsg"; // nexacro 에러 메시지
}
// first row
public final class ERROR_FIRST_ROW {
public final static String ERROR_DATASET = "FirstRowStatus"; // exception after firstrow
public final static String ERROR_CODE = ERROR.ERROR_CODE;
public final static String ERROR_MSG = ERROR.ERROR_MSG;
}
public static final String PERFORMANCE_LOGGER = "com.nexacro.performance";
}

View File

@@ -0,0 +1,76 @@
package com.nexacro.spring;
/**
*
* <p>Nexacro 예외를 의미하는 <code>Exception</code>이다.
*
* @ClassName : NexacroException.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 30.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 30. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroException extends Exception {
/* serialVersionUID */
private static final long serialVersionUID = 4095922735986385233L;
public static final int DEFAULT_ERROR_CODE = -1;
public static final String DEFAULT_MESSAGE = "An Error Occured. check the ErrorCode for detail of error infomation.";
private int errorCode = DEFAULT_ERROR_CODE;
private String errorMsg = DEFAULT_MESSAGE;
/**
* 기본 생성자이다.
*/
public NexacroException() {
;
}
/**
* 메시지를 가지는 생성자이다.
*
* @param message
* 메시지
*/
public NexacroException(String message) {
super(message);
}
/**
* 메시지와 원천(cause) 예외를 가지는 생성자이다.
*
* @param message
* 메시지
* @param cause
* 원천 예외
*/
public NexacroException(String message, Throwable cause) {
super(message, cause);
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}

View File

@@ -0,0 +1,13 @@
package com.nexacro.spring.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ java.lang.annotation.ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamDataSet {
public abstract String name();
}

View File

@@ -0,0 +1,13 @@
package com.nexacro.spring.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ java.lang.annotation.ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamVariable {
public abstract String name();
}

View File

@@ -0,0 +1,31 @@
package com.nexacro.spring.data;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : DataSetRowTypeAccessor.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 31.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 31. Park SeongMin 최초 생성
* </pre>
*/
public interface DataSetRowTypeAccessor {
static final String NAME = "DataSetRowType";
int getRowType();
void setRowType(int rowType);
}

View File

@@ -0,0 +1,30 @@
package com.nexacro.spring.data;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : DataSetSavedDataAccessor.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 31.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 31. Park SeongMin 최초 생성
* </pre>
*/
public interface DataSetSavedDataAccessor<T> {
static final String NAME = "DataSetSavedData";
T getData();
void setData(T t);
}

View File

@@ -0,0 +1,102 @@
package com.nexacro.spring.data;
import java.io.File;
import com.nexacro.spring.resolve.NexacroHandlerMethodReturnValueHandler;
/**
* <pre>
* nexacro platform으로 File 데이터를 전송하기 위한 정보를 가진다.
* </pre>
*
* @ClassName : NexacroFileResult.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 18.
* @version 1.0
* @see NexacroHandlerMethodReturnValueHandler
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 18. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroFileResult {
private File file;
private String contentType;
private String charset;
private String originalName;
public NexacroFileResult(File file) {
if(file == null) {
throw new IllegalArgumentException("file must not be null.");
}
this.file = file;
}
/**
* @return the file
*/
public File getFile() {
return file;
}
/**
* @param file
* the file to set
*/
public void setFile(File file) {
this.file = file;
}
/**
* @return the contentType
*/
public String getContentType() {
return contentType;
}
/**
* @param contentType
* the contentType to set
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* @return the charset
*/
public String getCharset() {
return charset;
}
/**
* @param charset
* the charset to set
*/
public void setCharset(String charset) {
this.charset = charset;
}
/**
* @return the originalName
*/
public String getOriginalName() {
return originalName;
}
/**
* @param originalName
* the originalName to set
*/
public void setOriginalName(String originalName) {
this.originalName = originalName;
}
}

View File

@@ -0,0 +1,51 @@
package com.nexacro.spring.data;
import com.nexacro.xapi.tx.HttpPartPlatformResponse;
import com.nexacro.xapi.tx.PlatformException;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroFirstRowAccessor.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 5.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 5. Park SeongMin 최초 생성
* </pre>
*/
public abstract class NexacroFirstRowAccessor {
public static HttpPartPlatformResponse getHttpPartPlatformResponse(NexacroFirstRowHandler handler) {
return handler.getHttpPartPlatformResponse();
}
public static void end(NexacroFirstRowHandler handler) throws PlatformException {
handler.end();
}
public static String[] getSendOutVariableNames(NexacroFirstRowHandler handler) {
return handler.getSendOutVariableNames();
}
public static int getSendOutVariableCount(NexacroFirstRowHandler handler) {
return handler.getSendOutVariableCount();
}
public static String[] getSendOutDataSetNames(NexacroFirstRowHandler handler) {
return handler.getSendOutDataSetNames();
}
public static int getSendOutDataSetCount(NexacroFirstRowHandler handler) {
return handler.getSendOutDataSetCount();
}
}

View File

@@ -0,0 +1,238 @@
package com.nexacro.spring.data;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletResponse;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.DataSetList;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
import com.nexacro.xapi.data.VariableList;
import com.nexacro.xapi.tx.HttpPartPlatformResponse;
import com.nexacro.xapi.tx.PlatformException;
import com.nexacro.xapi.tx.PlatformRequest;
import com.nexacro.xapi.tx.PlatformType;
/**
* <pre>
* Nexacro Platform에서 지원하는 FirstRow를 처리 한다.
* 데이터의 전송은 <Code>Variable</Code> 부터 <Code>DataSet</Code> 순으로 전송 된다.
* </pre>
*
* @ClassName : NexacroFirstRowHandler.java
* @author Park SeongMin
* @since 2015. 8. 5.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 5. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroFirstRowHandler {
private PlatformRequest platformRequest;
private HttpServletResponse httpResponse;
private HttpPartPlatformResponse partPlatformResponse = null;
private PrintWriter writer = null;
private String contentType;
private DataSet data = null;
private boolean isFirstRowFired = false;
private boolean dataSetSended = false;
private boolean isInit = false;
private boolean isEncrypted = false;
private Set sendOutVariableNameSet = new HashSet();
private Set sendOutDataSetNameSet = new HashSet();
/**
*
*
*
* @param httpServletResponse
*/
public NexacroFirstRowHandler(HttpServletResponse httpServletResponse) {
this(httpServletResponse, null);
}
public NexacroFirstRowHandler(HttpServletResponse httpServletResponse, PlatformRequest platformRequest) {
if(httpServletResponse == null) {
throw new IllegalArgumentException("HttpServletResponse should not be null.");
}
this.httpResponse = httpServletResponse;
this.platformRequest = platformRequest;
}
public String getContentType() {
return contentType;
}
/**
*
* set send ContentType
* <p>must be set before the transfer.
*
* @param contentType
* @see PlatformType#CONTENT_TYPE_XML
* @see PlatformType#CONTENT_TYPE_BINARY
* @see PlatformType#CONTENT_TYPE_SSV
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
public void sendPlatformData(PlatformData platformData) throws PlatformException {
isFirstRowFired = true;
VariableList variableList = platformData.getVariableList();
DataSetList dataSetList = platformData.getDataSetList();
for (int variableListIndex = 0; variableListIndex < variableList.size(); variableListIndex++) {
sendVariable(variableList.get(variableListIndex));
}
for (int datasetListIndex = 0; datasetListIndex < dataSetList.size(); datasetListIndex++) {
sendDataSet(dataSetList.get(datasetListIndex));
}
}
public void sendVariable(Variable variable) throws PlatformException {
isFirstRowFired = true;
intPartPlatformResponse();
if (dataSetSended) {
throw new PlatformException("DataSet aleady sended. can't send a variable after sending dataSet.");
}
partPlatformResponse.sendVariable(variable);
sendOutVariableNameSet.add(variable.getName());
}
public void sendDataSet(DataSet dataSet) throws PlatformException {
if (dataSet == null) {
return;
}
isFirstRowFired = true;
dataSetSended = true;
intPartPlatformResponse();
// 기존에 firstRow 로 전송 된 DataSet 잉여 data 전송.
// if(data == ds) {
if (data != null && !data.getName().equals(dataSet.getName())) {
partPlatformResponse.sendDataSet(data);
}
partPlatformResponse.sendDataSet(dataSet);
data = dataSet;
sendOutDataSetNameSet.add(dataSet.getName());
}
public boolean isFirstRowStarted() {
return isFirstRowFired;
}
private void intPartPlatformResponse() {
if (!isInit) {
if(platformRequest == null) {
partPlatformResponse = new HttpPartPlatformResponse(httpResponse);
} else {
partPlatformResponse = new HttpPartPlatformResponse(httpResponse, platformRequest);
}
if(contentType != null) {
partPlatformResponse.setContentType(contentType);
}
//setWriter();
isInit = true;
}
}
/**
*
* check current first row status
* <p><Code>PlatformType.CONTENT_TYPE_SSV</Code> or <Code>CONTENT_TYPE_BIN</Code> may not operate normally.
*
* @return errorStatus
*/
public boolean checkError() {
setWriter();
if (writer != null) {
return writer.checkError();
}
return false;
}
private void setWriter() {
// writer or outputstream choice
if (this.httpResponse != null && this.writer != null) {
try {
this.writer = this.httpResponse.getWriter();
} catch(UnsupportedEncodingException e) {
} catch(IllegalStateException e) {
} catch (IOException e) {
// log.
}
}
}
int getSendOutVariableCount() {
return sendOutVariableNameSet.size();
}
String[] getSendOutVariableNames() {
List sendOutVariableNameList = new ArrayList();
Iterator iterator = sendOutVariableNameSet.iterator();
while (iterator.hasNext()) {
sendOutVariableNameList.add(iterator.next());
}
String[] sendOutVariableNames = new String[sendOutVariableNameList.size()];
return (String[]) sendOutVariableNameList.toArray(sendOutVariableNames);
}
int getSendOutDataSetCount() {
return sendOutDataSetNameSet.size();
}
String[] getSendOutDataSetNames() {
List sendOutDataSetNameList = new ArrayList();
Iterator iterator = sendOutDataSetNameSet.iterator();
while (iterator.hasNext()) {
sendOutDataSetNameList.add(iterator.next());
}
String[] sendOutDataSetNames = new String[sendOutDataSetNameList.size()];
return (String[]) sendOutDataSetNameList.toArray(sendOutDataSetNames);
}
HttpPartPlatformResponse getHttpPartPlatformResponse() {
return partPlatformResponse;
}
void end() throws PlatformException {
if (isInit) {
isInit = false;
partPlatformResponse.end();
}
}
}

View File

@@ -0,0 +1,159 @@
package com.nexacro.spring.data;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.nexacro.spring.resolve.NexacroHandlerMethodReturnValueHandler;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
/**
* <pre>
* nexacro platform으로 데이터를 송신하기 위한 정보를 가진다.
* 데이터 삽입 시 변환은 이루어지지 않으며, NexacroHandlerMethodReturnValueHandler에서 데이터 변환이 이루어진다.
* </pre>
*
* @ClassName : NexacroResult.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 27.
* @version 1.0
* @see NexacroHandlerMethodReturnValueHandler
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 27. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroResult {
private PlatformData platformData;
private Map<String, List> dataSetMaps;
private Map<String, Object> variableMaps;
// result status
private int errorCode;
private String errorMsg;
private boolean registedError = false;
public NexacroResult() {
initResult();
}
private void initResult() {
dataSetMaps = new HashMap<String, List>();
variableMaps = new HashMap<String, Object>();
platformData = new PlatformData();
}
/**
*
* <code>DataSet<code>을 추가한다.
*
* @param dataSet
*/
public void addDataSet(DataSet dataSet) {
platformData.addDataSet(dataSet);
}
/**
*
* 입력받은 dataSetName(DataSet 이름)으로 List를 <code>DataSet</code>으로 추가한다.
* <p><code>List</code>의 값은 <code>java.util.Map<code> 혹은 VO class만 설정가능하다.
*
* @param dataSetName
* @param beans
*/
public void addDataSet(String dataSetName, List beans) {
checkName(dataSetName);
checkBean(beans);
dataSetMaps.put(dataSetName, beans);
}
/**
*
* <code>Variable</code>을 추가한다.
*
* @param variable
*/
public void addVariable(Variable variable) {
platformData.addVariable(variable);
}
/**
*
* 입력받은 variableName(Variable 이름)으로 Object를 <code>Variable</code>으로 추가한다.
*
* @param variableName
* @param object
*/
public void addVariable(String variableName, Object object) {
checkName(variableName);
variableMaps.put(variableName, object);
}
public Map<String, List> getDataSets() {
return Collections.unmodifiableMap(dataSetMaps);
}
public Map<String, Object> getVariables() {
return Collections.unmodifiableMap(variableMaps);
}
private void checkName(String dataName) {
if(dataName == null) {
throw new IllegalArgumentException("No name specified");
}
}
private void checkBean(List bean) {
}
public PlatformData getPlatformData() {
return platformData;
}
public void setPlatformData(PlatformData platformData) {
this.platformData = platformData;
}
/**
* @return the errorCode
*/
public int getErrorCode() {
return errorCode;
}
/**
* @param errorCode the errorCode to set
*/
public void setErrorCode(int errorCode) {
this.registedError = true;
this.errorCode = errorCode;
}
public boolean registedErrorCode() {
return this.registedError;
}
/**
* @return the errorMsg
*/
public String getErrorMsg() {
return errorMsg;
}
/**
* @param errorMsg the errorMsg to set
*/
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}

View File

@@ -0,0 +1,81 @@
package com.nexacro.spring.data.convert;
import com.nexacro.xapi.data.DataSet;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ConvertDataSetEvent.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public class ConvertDataSetEvent extends ConvertEvent {
/* serialVersionUID */
private static final long serialVersionUID = -174881582977983877L;
private int rowIndex;
private int columnIndex;
private boolean isSavedData;
private boolean isRemovedData;
public ConvertDataSetEvent(DataSet source, Object targetValue, int rowIndex, int columnIndex) {
this(source, targetValue, rowIndex, columnIndex, false, false);
}
public ConvertDataSetEvent(DataSet source, Object targetValue, int rowIndex, int columnIndex, boolean isSavedData, boolean isRemovedData) {
super(source, targetValue);
this.rowIndex = rowIndex;
this.columnIndex = columnIndex;
this.isSavedData = isSavedData;
this.isRemovedData = isRemovedData;
}
/**
* @return the rowIndex
*/
public int getRowIndex() {
return rowIndex;
}
/**
* @return the columnIndex
*/
public int getColumnIndex() {
return columnIndex;
}
public String getColumnName() {
DataSet ds = (DataSet) getSource();
return ds.getColumn(columnIndex).getName();
}
/**
* @return the isSavedData
*/
public boolean isSavedData() {
return isSavedData;
}
/**
* @return the isRemovedData
*/
public boolean isRemovedData() {
return isRemovedData;
}
}

View File

@@ -0,0 +1,81 @@
package com.nexacro.spring.data.convert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConvertDefinition.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class ConvertDefinition {
private String name;
private Class genericType; // for generic
private boolean isIgnoreException = false;
public ConvertDefinition(String name) {
setName(name);
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name
* the name to set
*/
public void setName(String name) {
if(name == null || name.length() == 0) {
throw new IllegalArgumentException("converted name must be not null");
}
this.name = name;
}
/**
* @return the isIgnoreException
*/
public boolean isIgnoreException() {
return isIgnoreException;
}
/**
* @param isIgnoreException
* the isIgnoreException to set
*/
public void setIgnoreException(boolean isIgnoreException) {
this.isIgnoreException = isIgnoreException;
}
/**
* @return the genericType
*/
public Class getGenericType() {
return genericType;
}
/**
* @param genericType the genericType to set
*/
public void setGenericType(Class genericType) {
this.genericType = genericType;
}
}

View File

@@ -0,0 +1,56 @@
package com.nexacro.spring.data.convert;
import java.util.EventObject;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ConvertEvent.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public class ConvertEvent extends EventObject {
/* serialVersionUID */
private static final long serialVersionUID = -8987092428557969722L;
/* converted value */
private Object value;
/**
* Statements
*
* @param source
*/
public ConvertEvent(Object source, Object value) {
super(source);
this.value = value;
}
/**
* @return the convertedValue
*/
public Object getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(Object value) {
this.value = value;
}
}

View File

@@ -0,0 +1,38 @@
package com.nexacro.spring.data.convert;
import com.nexacro.xapi.data.Variable;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ConvertVariableEvent.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public class ConvertVariableEvent extends ConvertEvent {
/* serialVersionUID */
private static final long serialVersionUID = 7527494468054562758L;
/**
* Statements
*
* @param source
*/
public ConvertVariableEvent(Variable source, Object targetValue) {
super(source, targetValue);
}
}

View File

@@ -0,0 +1,58 @@
package com.nexacro.spring.data.convert;
import com.nexacro.spring.NexacroException;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConvertException.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroConvertException extends NexacroException {
/* serialVersionUID */
private static final long serialVersionUID = 2572392591528637297L;
/**
* 기본 생성자이다.
*/
public NexacroConvertException() {
;
}
/**
* 메시지를 가지는 생성자이다.
*
* @param message
* 메시지
*/
public NexacroConvertException(String message) {
super(message);
}
/**
* 메시지와 원천(cause) 예외를 가지는 생성자이다.
*
* @param message
* 메시지
* @param cause
* 원천 예외
*/
public NexacroConvertException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,28 @@
package com.nexacro.spring.data.convert;
import java.util.EventListener;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConverterListener.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public interface NexacroConvertListener extends EventListener {
void convertedValue(ConvertEvent event);
}

View File

@@ -0,0 +1,88 @@
package com.nexacro.spring.data.convert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public interface NexacroConverter<S, T> {
/**
*
* Convert the source of type S to target type T.
*
* @param Source
* @return
* @throws NexacroConvertException
*/
T convert(S source, ConvertDefinition definition) throws NexacroConvertException;
boolean canConvert(Class source, Class target);
void addListener(NexacroConvertListener listener);
void removeListener(NexacroConvertListener listener);
public static final class ConvertiblePair {
private final Class<?> sourceType;
private final Class<?> targetType;
public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
this.sourceType = sourceType;
this.targetType = targetType;
}
public Class<?> getSourceType() {
return this.sourceType;
}
public Class<?> getTargetType() {
return this.targetType;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || obj.getClass() != ConvertiblePair.class) {
return false;
}
ConvertiblePair other = (ConvertiblePair) obj;
// return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType);
// support sub class
return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType);
}
@Override
public int hashCode() {
return this.sourceType.hashCode() * 31 + this.targetType.hashCode();
}
@Override
public String toString() {
return this.sourceType.getName() + "->" + this.targetType.getName();
}
}
}

View File

@@ -0,0 +1,173 @@
package com.nexacro.spring.data.convert;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nexacro.spring.data.convert.NexacroConverter.ConvertiblePair;
import com.nexacro.spring.data.support.DataSetToListConverter;
import com.nexacro.spring.data.support.ListToDataSetConverter;
import com.nexacro.spring.data.support.ObjectToVariableConverter;
import com.nexacro.spring.data.support.VariableToObjectConverter;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConverterFactory.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroConverterFactory {
private static Logger logger = LoggerFactory.getLogger(NexacroConverterFactory.class);
private static Set<NexacroConverter> converterSets = new HashSet<NexacroConverter>();
private static Map<ConvertiblePair, NexacroConverter> convertibleCacheMap = new HashMap<ConvertiblePair, NexacroConverter>();
private static final NexacroConverterFactory INSTANCE = new NexacroConverterFactory();
private NexacroConverterFactory() {
addDefaultConverter();
}
private void addDefaultConverter() {
NexacroConverterFactory.register(new DataSetToListConverter());
NexacroConverterFactory.register(new ListToDataSetConverter());
NexacroConverterFactory.register(new VariableToObjectConverter());
NexacroConverterFactory.register(new ObjectToVariableConverter());
}
public static NexacroConverterFactory getInstance() {
return INSTANCE;
}
public static NexacroConverter getConverter(Class source, Class target) {
if(source == null || target == null) {
throw new IllegalArgumentException("source and target class must not be null.");
}
NexacroConverter converter = findConvertibleCache(source, target);
if(converter == null) {
converter = findSupportedConverter(source, target);
}
if(converter == null) {
// new NullConverter(source, target);
return null;
}
return converter;
}
private static NexacroConverter findConvertibleCache(Class source, Class target) {
ConvertiblePair convertiblePair = new ConvertiblePair(source, target);
NexacroConverter converter = convertibleCacheMap.get(convertiblePair);
return converter;
}
private static NexacroConverter findSupportedConverter(Class source, Class target) {
for(NexacroConverter converter: converterSets) {
boolean canConvertible = converter.canConvert(source, target);
if(canConvertible) {
ConvertiblePair pair = new ConvertiblePair(source, target);
convertibleCacheMap.put(pair, converter);
return converter;
}
}
return null;
}
public static synchronized void register(Set<NexacroConverter> converters) {
if(converters == null) {
return;
}
for(NexacroConverter converter: converters) {
register(converter);
}
}
public static synchronized void register(NexacroConverter converter) {
if(converter == null) {
throw new IllegalArgumentException(NexacroConverter.class.getName()+" must not be null.");
}
if(converterSets.contains(converter)) {
return;
}
if(logger.isDebugEnabled()) {
logger.debug(converter.getClass() + " registered.");
}
converterSets.add(converter);
// Set<ConvertiblePair> defaultConvertibleTypes = converter.getDefaultConvertibleTypes();
// for(ConvertiblePair pair: defaultConvertibleTypes) {
// if(convertibleCacheMap.containsKey(pair)) {
// continue;
// }
//
// convertibleCacheMap.put(pair, converter);
// if(logger.isDebugEnabled()) {
// logger.debug(pair + " registered.");
// }
// }
}
private static String getConvertibleKey(Object source, Object target) {
return getConvertibleKey(source.getClass(), target.getClass());
}
private static String getConvertibleKey(Class source, Class target) {
return source.getName() + "->" + target.getName();
}
private static class NullConverter implements NexacroConverter {
private Class source;
private Class target;
private NullConverter(Class source, Class target) {
this.source = source;
this.target = target;
}
public boolean canConvert(Class source, Class target) {
return false;
}
public Object convert(Object source, ConvertDefinition definition) throws NexacroConvertException {
throw new UnsupportedOperationException("Unsupported convert type. source="+source+", target="+target);
}
public void addListener(NexacroConvertListener listener) {
}
public void removeListener(NexacroConvertListener listener) {
}
}
}

View File

@@ -0,0 +1,61 @@
package com.nexacro.spring.data.convert;
import java.util.Set;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConverterFactoryBean.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroConverterFactoryBean implements FactoryBean<NexacroConverterFactory>, InitializingBean {
private Set<NexacroConverter> converters;
private NexacroConverterFactory converterFactory;
/**
* @param converters the converters to set
*/
public void setConverters(Set<NexacroConverter> converters) {
this.converters = converters;
}
@Override
public void afterPropertiesSet() throws Exception {
this.converterFactory = NexacroConverterFactory.getInstance();
converterFactory.register(converters);
}
@Override
public NexacroConverterFactory getObject() throws Exception {
return converterFactory;
}
@Override
public Class<NexacroConverterFactory> getObjectType() {
return NexacroConverterFactory.class;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@@ -0,0 +1,30 @@
package com.nexacro.spring.data.metadata;
import java.util.ArrayList;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroList.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 6.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 6. Park SeongMin 최초 생성
* </pre>
*/
public abstract class NexacroMetaData extends ArrayList {
public abstract void setMetaData(Object obj);
public abstract Object getMetaData();
}

View File

@@ -0,0 +1,59 @@
package com.nexacro.spring.data.metadata.support;
import com.nexacro.spring.data.metadata.NexacroMetaData;
import com.nexacro.spring.data.support.NexacroBeanWrapper;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroBeanMetaData.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 6.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 6. Park SeongMin 최초 생성
* </pre>
*/
public class BeanMetaData extends NexacroMetaData {
private Object metaDataObject;
public BeanMetaData(Object obj) {
setMetaData(obj);
}
public BeanMetaData(Class<?> genericType) {
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(genericType);
Object insatance = beanWrapper.getInsatance();
setMetaData(insatance);
}
@Override
public void setMetaData(Object obj) {
if(!(obj instanceof NexacroBeanWrapper)) {
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(obj);
this.metaDataObject = beanWrapper.getInsatance();
} else {
this.metaDataObject = obj;
}
}
@Override
public Object getMetaData() {
return this.metaDataObject;
}
@Override
public String toString() {
return "BeanMetaData [class=" + this.metaDataObject.getClass() + "]";
}
}

View File

@@ -0,0 +1,55 @@
package com.nexacro.spring.data.metadata.support;
import java.util.Map;
import com.nexacro.spring.data.metadata.NexacroMetaData;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : MapMetaData.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 6.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 6. Park SeongMin 최초 생성
* </pre>
*/
public class MapMetaData extends NexacroMetaData {
private Map<String, Object> metaDataMap;
/**
* Statements
*
* @param mapData
*/
public MapMetaData(Map<String, Object> mapData) {
setMetaData(mapData);
}
@Override
public void setMetaData(Object metaDataMap) {
this.metaDataMap = (Map) metaDataMap;
}
@Override
public Object getMetaData() {
return this.metaDataMap;
}
@Override
public String toString() {
return "MapMetaData [metaDataMap=" + metaDataMap + "]";
}
}

View File

@@ -0,0 +1,43 @@
package com.nexacro.spring.data.metadata.support;
import com.nexacro.spring.data.metadata.NexacroMetaData;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : UnsupportedMetaData.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 6.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 6. Park SeongMin 최초 생성
* </pre>
*/
public class UnsupportedMetaData extends NexacroMetaData {
private String message;
public UnsupportedMetaData(String message) {
this.message = message;
}
@Override
public void setMetaData(Object obj) {
// throw new UnsupportedOperationException(this.message);
}
@Override
public Object getMetaData() {
// throw new UnsupportedOperationException(this.message);
return message;
}
}

View File

@@ -0,0 +1,293 @@
package com.nexacro.spring.data.support;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.PropertyAccessException;
import com.nexacro.spring.data.DataSetRowTypeAccessor;
import com.nexacro.spring.data.DataSetSavedDataAccessor;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.util.ReflectionUtil;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.datatype.DataType;
import com.nexacro.xapi.data.datatype.PlatformDataType;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : AbstractDataSetConverterHandler.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 11.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 11. Park SeongMin 최초 생성
* </pre>
*/
public class AbstractDataSetConverter extends AbstractListenerHandler {
/***************************************************************************************************/
/************************************** Object -> DataSet ****************************************/
/***************************************************************************************************/
/**
* Statements
*
* @param ds
* @param obj
* @throws NexacroConvertException
*/
protected void addRowIntoDataSet(DataSet ds, Map map) throws NexacroConvertException {
// ignore null data.
if(map == null) {
return;
}
int newRow = ds.newRow();
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
if(!(key instanceof String)) {
throw new NexacroConvertException("must be Map<String, Object> if you use List<Map>. target="+ds.getName());
}
String columnName = (String) key;
// Byte[] 변환
Object object = NexacroConverterHelper.toObject(value);
int columnIndex = ds.indexOfColumn(columnName);
// fire event
object = fireDataSetConvertedValue(ds, object, newRow, columnIndex, false, false);
// add data
ds.set(newRow, columnName, object);
}
}
protected void addRowIntoDataSet(DataSet ds, Object obj) {
if(obj == null) { // ignore null data
return;
}
int newRow = ds.newRow();
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(obj);
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
// ignore static. constColumn..
if(property.isStatic()) {
continue;
}
String propertyName = property.getPropertyName();
Object propertyValue = beanWrapper.getPropertyValue(property);
// Byte[] 변환
Object object = NexacroConverterHelper.toObject(propertyValue);
int columnIndex = ds.indexOfColumn(propertyName);
// fire event
object = fireDataSetConvertedValue(ds, object, newRow, columnIndex, false, false);
// add data
ds.set(newRow, columnIndex, object);
}
}
protected void addColumnIntoDataSet(DataSet ds, Map map) throws NexacroConvertException {
Iterator iterator = map.keySet().iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
if(!(key instanceof String)) {
throw new NexacroConvertException("must be Map<String, Object> if you use List<Map>. target="+ds.getName());
}
String columnName = (String) key;
if(value == null) {
ds.addColumn(columnName, PlatformDataType.UNDEFINED);
continue;
}
// add column
if(!NexacroConverterHelper.isConvertibleType(value.getClass())) {
continue;
}
DataType dataTypeOfValue = NexacroConverterHelper.getDataTypeOfValue(value);
ds.addColumn(columnName, dataTypeOfValue);
}
}
protected void addColumnIntoDataSet(DataSet ds, Object availableFirstData) {
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(availableFirstData);
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
String propertyName = property.getPropertyName();
Class<?> propertyType = property.getPropertyType();
if(!NexacroConverterHelper.isConvertibleType(propertyType)) {
continue;
}
DataType dataTypeOfValue = NexacroConverterHelper.getDataType(propertyType);
if(property.isStatic()) {
Object staticValue = beanWrapper.getPropertyValue(property);
// Byte[] 변환
staticValue = NexacroConverterHelper.toObject(staticValue);
int columnIndex = ds.indexOfColumn(propertyName);
// fire event
staticValue = fireDataSetConvertedValue(ds, staticValue, -1, columnIndex, false, false);
ds.addConstantColumn(propertyName, dataTypeOfValue, staticValue);
} else {
ds.addColumn(propertyName, dataTypeOfValue);
}
}
}
protected String[] getDataSetColumnNames(DataSet ds) {
int columnCount = ds.getColumnCount();
String[] columnNames = new String[columnCount];
for(int i=0; i<columnNames.length; i++) {
columnNames[i] = ds.getColumn(i).getName();
}
return columnNames;
}
/***************************************************************************************************/
/************************************** DataSet -> Object ****************************************/
/***************************************************************************************************/
protected void addRowIntoMap(Map<String, Object> dataMap, DataSet ds, int rowIndex, String[] columnNames) {
int rowType = ds.getRowType(rowIndex);
for(int columnIndex=0; columnIndex<columnNames.length; columnIndex++) {
Object object = ds.getObject(rowIndex, columnIndex);
// fire event
object = fireDataSetConvertedValue(ds, object, rowIndex, columnIndex, false, false);
dataMap.put(columnNames[columnIndex], object);
}
// saved data
if(ds.hasSavedRow(rowIndex)) {
Map<String, Object> savedDataRow = new HashMap<String, Object>();
for(int columnIndex=0; columnIndex<columnNames.length; columnIndex++) {
Object object = ds.getSavedData(rowIndex, columnIndex);
// fire event
object = fireDataSetConvertedValue(ds, object, rowIndex, columnIndex, true, false);
savedDataRow.put(columnNames[columnIndex], object);
}
// set saved data
dataMap.put(DataSetSavedDataAccessor.NAME, savedDataRow);
}
// row type
dataMap.put(DataSetRowTypeAccessor.NAME, rowType);
}
protected void addRowAndOrgRowIntoBean(NexacroBeanWrapper beanWrapper, DataSet ds, int rowIndex) throws NexacroConvertException {
boolean isSavedData = false;
boolean isRemovedData = false;
addRowIntoBean(beanWrapper, ds, rowIndex, isSavedData, isRemovedData);
// set saved data
if(ds.hasSavedRow(rowIndex)) {
Object bean = beanWrapper.getInsatance();
Class<?> beanType = bean.getClass();
if(ReflectionUtil.isImplemented(beanType, DataSetSavedDataAccessor.class)) {
isSavedData = true;
NexacroBeanWrapper savedBeanWrapper = NexacroBeanWrapper.createBeanWrapper(beanType);
addRowIntoBean(savedBeanWrapper, ds, rowIndex, isSavedData, isRemovedData);
DataSetSavedDataAccessor accessor = (DataSetSavedDataAccessor) bean;
accessor.setData(savedBeanWrapper.getInsatance());
}
}
}
protected void addRowIntoBean(NexacroBeanWrapper beanWrapper,
DataSet ds, int rowIndex, boolean isSavedData, boolean isRemovedData) throws NexacroConvertException {
NexacroBeanProperty[] beanProperties = beanWrapper.getProperties();
for(NexacroBeanProperty property: beanProperties) {
String propertyName = property.getPropertyName();
int columnIndex = ds.indexOfColumn(propertyName);
if(columnIndex == -1) {
continue;
}
Class<?> propertyType = property.getPropertyType();
Object convertDataSetValue =
NexacroConverterHelper.toObjectFromDataSetValue(ds, rowIndex, columnIndex, propertyType, isSavedData, isRemovedData);
// fire event
convertDataSetValue = fireDataSetConvertedValue(ds, convertDataSetValue, rowIndex, columnIndex, isSavedData, isRemovedData);
try {
beanWrapper.setPropertyValue(property, convertDataSetValue);
} catch (InvalidPropertyException e) {
throw new NexacroConvertException(e.getMessage(), e);
} catch (PropertyAccessException e) {
throw new NexacroConvertException(e.getMessage(), e);
} catch (BeansException e) {
throw new NexacroConvertException(e.getMessage(), e);
}
}
Object bean = beanWrapper.getInsatance();
Class beanType = bean.getClass();
// row type
if(ReflectionUtil.isImplemented(beanType, DataSetRowTypeAccessor.class)) {
int rowType;
if(isRemovedData) {
rowType = DataSet.ROW_TYPE_DELETED;
} else if(isSavedData){
rowType = DataSet.ROW_TYPE_NORMAL;
} else {
rowType = ds.getRowType(rowIndex);
}
DataSetRowTypeAccessor accessor = (DataSetRowTypeAccessor) bean;
accessor.setRowType(rowType);
}
}
}

View File

@@ -0,0 +1,120 @@
package com.nexacro.spring.data.support;
import javax.swing.event.EventListenerList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nexacro.spring.data.convert.ConvertDataSetEvent;
import com.nexacro.spring.data.convert.ConvertVariableEvent;
import com.nexacro.spring.data.convert.NexacroConvertListener;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.Variable;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : AbstractNexacroConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public abstract class AbstractListenerHandler {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
/* EventListenerList */
private EventListenerList listenerList;
/**
* <code>NexacroConverterListener</code>를 등록한다.
*
* @param listener NexacroConverterListener
* @see #removeListener(NexacroConvertListener)
*/
public void addListener(NexacroConvertListener listener) {
if (listenerList == null) {
listenerList = new EventListenerList();
}
if (logger.isDebugEnabled()) {
logger.debug("addListener=" + listener);
}
listenerList.add(NexacroConvertListener.class, listener);
}
/**
* <code>NexacroConverterListener</code>를 제거한다.
*
* @param listener NexacroConverterListener
* @see #addListener(NexacroConvertListener)
*/
public void removeListener(NexacroConvertListener listener) {
if (listenerList == null || listenerList.getListenerCount() == 0) {
int listenerCount = (listenerList == null) ? -1 : listenerList.getListenerCount();
if (logger.isDebugEnabled()) {
logger.debug("removeListener:"
+ " listenerCount=" + listenerCount
+ ", listener=" + listener);
}
return;
}
if (logger.isDebugEnabled()) {
logger.debug("removeListener=" + listener);
}
listenerList.remove(NexacroConvertListener.class, listener);
}
public Object fireDataSetConvertedValue(DataSet ds, Object targetValue, int rowIndex, int columnIndex, boolean isSavedData, boolean isRemovedData) {
if (listenerList == null || listenerList.getListenerCount() == 0) {
return targetValue;
}
ConvertDataSetEvent event = new ConvertDataSetEvent(ds, targetValue, rowIndex, columnIndex, isSavedData, isRemovedData);
Object[] listeners = listenerList.getListenerList();
for (int i=0; i<listeners.length; i += 2) {
if (listeners[i] == NexacroConvertListener.class) {
((NexacroConvertListener) listeners[i+1]).convertedValue(event);
}
}
return event.getValue();
}
public Object fireVariableConvertedValue(Variable var, Object targetValue) {
if (listenerList == null || listenerList.getListenerCount() == 0) {
return targetValue;
}
ConvertVariableEvent event = new ConvertVariableEvent(var, targetValue);
Object[] listeners = listenerList.getListenerList();
for (int i=0; i<listeners.length; i += 2) {
if (listeners[i] == NexacroConvertListener.class) {
((NexacroConvertListener) listeners[i+1]).convertedValue(event);
}
}
return event.getValue();
}
}

View File

@@ -0,0 +1,221 @@
package com.nexacro.spring.data.support;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.nexacro.spring.data.DataSetRowTypeAccessor;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.xapi.data.DataSet;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : DataSetToListConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class DataSetToListConverter extends AbstractDataSetConverter implements NexacroConverter<DataSet, List> {
@Override
public boolean canConvert(Class source, Class target) {
if(source == null || target == null) {
return false;
}
// support type
if(DataSet.class.equals(source) && List.class.equals(target)) {
return true;
}
return false;
}
/*
* @see com.nexacro.spring.data.NexacroConverter#convert(java.lang.Object)
*/
@Override
public List convert(DataSet ds, ConvertDefinition definition) throws NexacroConvertException {
if(definition ==null) {
throw new NexacroConvertException(ConvertDefinition.class.getSimpleName()+" must not be null.");
}
// bean 혹은 Map만을 대상으로 한다.
Class genericType = definition.getGenericType();
if(ds == null) {
// return ReflectionUtil.instantiateClass(genericType);
return new ArrayList();
}
if(genericType == null) {
throw new NexacroConvertException("List<> generic type must be declared.");
}
List dataList = null;
if(Map.class.equals(genericType)) {
dataList = convertDataSetToListMap(ds, definition);
} else {
dataList = convertDataSetToListBean(ds, definition);
}
return dataList;
}
private List<Map<String, Object>> convertDataSetToListMap(DataSet ds, ConvertDefinition definition) {
String[] columnNames = getDataSetColumnNames(ds);
// default row
List<Map<String, Object>> dataListMap = new ArrayList<Map<String, Object>>();
int rowCount = ds.getRowCount();
for(int rowIndex=0; rowIndex<rowCount; rowIndex++) {
addRowIntoListMap(dataListMap, ds, rowIndex, columnNames);
}
// removed row
int removedRowCount = ds.getRemovedRowCount();
for(int removedIndex=0; removedIndex<removedRowCount; removedIndex++) {
addRemovedRowIntoListMap(dataListMap, ds, removedIndex, columnNames);
}
return dataListMap;
}
/**
* Statements
*
* @param ds
* @param columnCount
* @param columnNames
* @param hasSavedData
* @param dataListMap
* @param rowIndex
*/
private void addRowIntoListMap(List<Map<String, Object>> dataListMap, DataSet ds, int rowIndex, String[] columnNames) {
// default row
Map<String, Object> dataRow = new HashMap<String, Object>();
addRowIntoMap(dataRow, ds, rowIndex, columnNames);
// set data
dataListMap.add(dataRow);
}
/**
* Statements
*
* @param ds
* @param columnCount
* @param columnNames
* @param dataList
* @param removedIndex
*/
private void addRemovedRowIntoListMap(List<Map<String, Object>> dataList, DataSet ds, int removedIndex, String[] columnNames) {
// removed data
Map<String, Object> dataRow = new HashMap<String, Object>();
for(int columnIndex=0; columnIndex<columnNames.length; columnIndex++) {
Object object = ds.getRemovedData(removedIndex, columnIndex);
// fire event
object = fireDataSetConvertedValue(ds, object, removedIndex, columnIndex, false, true);
dataRow.put(columnNames[columnIndex], object);
}
// row type
dataRow.put(DataSetRowTypeAccessor.NAME, DataSet.ROW_TYPE_DELETED);
// set removed data
dataList.add(dataRow);
}
private List<?> convertDataSetToListBean(DataSet ds, ConvertDefinition definition) throws NexacroConvertException {
Class genericType = definition.getGenericType();
// 지원하는 형식인지 확인 한다.
if(!NexacroConverterHelper.isSupportedBean(genericType)) {
throw new NexacroConvertException("unsupported source type. type="+genericType);
}
// 데이터 변환이 가능한 field 목록을 획득한다.
// Map<String, Field> adjustConvertibleFields = NexacroConverterHelper.getAdjustConvertibleFields(genericType, ds);
List dataList = new ArrayList();
boolean isOrgData = false;
boolean isRemovedData = false;
// default row
int rowCount = ds.getRowCount();
for(int rowIndex=0; rowIndex<rowCount; rowIndex++) {
addRowIntoListBean(dataList, genericType, ds, rowIndex);
}
// removed row
int removedRowCount = ds.getRemovedRowCount();
for(int removedIndex=0; removedIndex<removedRowCount; removedIndex++) {
addRemovedRowIntoListBean(dataList, genericType, ds, removedIndex);
}
return dataList;
}
/**
* Statements
*
* @param ds
* @param beanType
* @param adjustConvertibleFields
* @param keySet
* @param dataList
* @param rowIndex
* @throws NexacroConvertException
*/
private void addRowIntoListBean(List dataList, Class beanType, DataSet ds, int rowIndex) throws NexacroConvertException {
// Object bean = ReflectionUtil.instantiateClass(beanType);
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(beanType);
addRowAndOrgRowIntoBean(beanWrapper, ds, rowIndex);
Object bean = beanWrapper.getInsatance();
dataList.add(bean);
}
private void addRemovedRowIntoListBean(List dataList, Class beanType, DataSet ds, int removedIndex)
throws NexacroConvertException {
// Object bean = ReflectionUtil.instantiateClass(beanType);
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(beanType);
Object bean = beanWrapper.getInsatance();
boolean isSavedData = false;
boolean isRemovedData = true;
addRowIntoBean(beanWrapper, ds, removedIndex, isSavedData, isRemovedData);
dataList.add(bean);
}
}

View File

@@ -0,0 +1,105 @@
package com.nexacro.spring.data.support;
import java.util.HashMap;
import java.util.Map;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.spring.util.ReflectionUtil;
import com.nexacro.xapi.data.DataSet;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : DataSetToObjectConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 17.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 17. Park SeongMin 최초 생성
* </pre>
*/
public class DataSetToObjectConverter extends AbstractDataSetConverter implements NexacroConverter<DataSet, Object> {
@Override
public boolean canConvert(Class source, Class target) {
if(source == null || target == null) {
return false;
}
// support type
if(DataSet.class.equals(source) && NexacroConverterHelper.isSupportedBean(target)) {
return true;
}
return false;
}
@Override
public Object convert(DataSet source, ConvertDefinition definition) throws NexacroConvertException {
if(definition ==null) {
throw new NexacroConvertException(ConvertDefinition.class.getSimpleName()+" must not be null.");
}
// bean 혹은 Map만을 대상으로 한다.
Class genericType = definition.getGenericType();
if(source == null) {
return ReflectionUtil.instantiateClass(genericType);
}
if(genericType == null) {
throw new NexacroConvertException("generic type must be declared.");
}
Object obj = null;
if(Map.class.equals(genericType)) {
obj = convertDataSetToMap(source, definition);
} else {
obj = convertDataSetToBean(source, definition);
}
return obj;
}
private Object convertDataSetToBean(DataSet ds, ConvertDefinition definition) throws NexacroConvertException {
Class genericType = definition.getGenericType();
// 지원하는 형식인지 확인 한다.
if(!NexacroConverterHelper.isSupportedBean(genericType)) {
throw new NexacroConvertException("unsupported generic type. type="+genericType);
}
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(genericType);
addRowAndOrgRowIntoBean(beanWrapper, ds, 0);
Object bean = beanWrapper.getInsatance();
return bean;
}
private Object convertDataSetToMap(DataSet ds, ConvertDefinition definition) {
String[] columnNames = getDataSetColumnNames(ds);
// default row
Map<String, Object> dataRow = new HashMap<String, Object>();
addRowIntoMap(dataRow, ds, 0, columnNames);
return dataRow;
}
}

View File

@@ -0,0 +1,137 @@
package com.nexacro.spring.data.support;
import java.util.List;
import java.util.Map;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.spring.data.metadata.NexacroMetaData;
import com.nexacro.xapi.data.DataSet;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ListToDataSetConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class ListToDataSetConverter extends AbstractDataSetConverter implements NexacroConverter<List, DataSet> {
private static final int CHECK_INDEX = 0;
@Override
public boolean canConvert(Class source, Class target) {
if(source == null || target == null) {
return false;
}
// support list sub class
if(List.class.isAssignableFrom(source) && DataSet.class.equals(target)) {
return true;
}
return false;
}
/*
* @see com.nexacro.spring.data.NexacroConverter#convert(java.lang.Object)
*/
@Override
public DataSet convert(List source, ConvertDefinition definition) throws NexacroConvertException {
if(definition ==null) {
throw new IllegalArgumentException(ConvertDefinition.class.getSimpleName()+" must not be null.");
}
if(source == null) {
return new DataSet(definition.getName());
}
// check first value
Object availableFirstData = checkAvailable(source);
if(availableFirstData == null) {
return new DataSet(definition.getName());
}
// DataSet SavedType은 처리 하지 않는다. (UI 처리 불필요)
DataSet ds = null;
if(availableFirstData instanceof Map) {
ds = convertListMapToDataSet(source, definition, (Map) availableFirstData);
} else {
ds = convertListBeanToDataSet(source, definition, availableFirstData);
}
return ds;
}
private Object checkAvailable(List source) {
// for ibatis empty data
if(source instanceof NexacroMetaData) {
NexacroMetaData metaData = (NexacroMetaData) source;
return metaData.getMetaData();
}
if(source.size() == 0) {
return null;
}
for(Object obj: source) {
if(obj != null) {
return obj;
}
}
return null;
}
private DataSet convertListMapToDataSet(List source, ConvertDefinition definition, Map availableFirstData) throws NexacroConvertException {
DataSet ds = new DataSet(definition.getName());
// dynamic하게 변경 된 데이터는 처리 하지 않는다.
addColumnIntoDataSet(ds, availableFirstData);
for(Object obj: source) {
if(!(obj instanceof Map)) {
throw new NexacroConvertException("list should use the generic type. target="+ds.getName());
}
addRowIntoDataSet(ds, (Map) obj);
}
return ds;
}
private DataSet convertListBeanToDataSet(List source, ConvertDefinition definition, Object availableFirstData) throws NexacroConvertException {
// 지원하는 형식인지 확인 한다.
if(!NexacroConverterHelper.isSupportedBean(availableFirstData.getClass())) {
throw new NexacroConvertException("unsupported generic type. type="+availableFirstData.getClass());
}
DataSet ds = new DataSet(definition.getName());
addColumnIntoDataSet(ds, availableFirstData);
for(Object obj: source) {
addRowIntoDataSet(ds, obj);
}
return ds;
}
}

View File

@@ -0,0 +1,84 @@
package com.nexacro.spring.data.support;
import java.lang.reflect.Method;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroBeanProperty.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 10.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 10. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroBeanProperty {
private final String propertyName;
private final Class<?> propertyType;
private boolean isStatic;
private String originalPropertyName;
// for performance..
// private PropertyDescriptor descriptor;
// descriptor의 getWriteMethod 시 synchoronized
private Method writeMethod;
public NexacroBeanProperty(String propertyName, Class<?> propertyType) {
this.propertyName = propertyName;
this.propertyType = propertyType;
}
public String getPropertyName() {
return propertyName;
}
public Class<?> getPropertyType() {
return propertyType;
}
void setStatic(boolean isStatic) {
this.isStatic = isStatic;
}
public boolean isStatic() {
return isStatic;
}
String getOriginalPropertyName() {
return originalPropertyName;
}
void setOriginalPropertyName(String originalPropertyName) {
this.originalPropertyName = originalPropertyName;
}
Method getWriteMethod() {
return writeMethod;
}
void setWriteMethod(Method writeMethod) {
this.writeMethod = writeMethod;
}
// PropertyDescriptor getPropertyDescriptor() {
// return this.descriptor;
// }
//
// void setPropertyDescriptor(PropertyDescriptor descriptor) {
// this.descriptor = descriptor;
// }
}

View File

@@ -0,0 +1,353 @@
package com.nexacro.spring.data.support;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.NotWritablePropertyException;
import org.springframework.util.ReflectionUtils;
import com.nexacro.spring.util.ReflectionFailException;
import com.nexacro.spring.util.ReflectionUtil;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroBeanWrapper.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 4.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 4. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroBeanWrapper {
/*
BeanWrapper의 경우 Method 명칭에 해당하는 property 명칭으로 값을 설정한다.
하지만 field가 boolean일 경우 eclipseis에서 generation 되는 메서드의 명칭은 is가 생략되기 때문에
해당부분만을 처리하며, 나머지는 spring으로 위임한다.
*/
private BeanWrapper beanWrapper;
private CachedBeanMappings cachedMapping;
private NexacroBeanWrapper(Object obj) {
beanWrapper = new BeanWrapperImpl(obj);
}
private NexacroBeanWrapper(Class<?> clazz) {
beanWrapper = new BeanWrapperImpl(clazz);
}
public NexacroBeanProperty[] getProperties() {
return getCachedBeanMappings().getProperties();
}
public NexacroBeanProperty getProperty(String propertyName) {
return getCachedBeanMappings().getProperty(propertyName);
}
public void setPropertyValue(NexacroBeanProperty property, Object value) {
if(property == null) {
return;
}
// 데이터 설정 시 beanwrapper를 사용하지 않고 직접 처리 한다.
// 데이터 변경에 대한 Event 처리, Data Type 처리 등에 따른 속도 저하..
// 10만건 처리 시 5초 vs 1초 정도 차이.
// PropertyDescriptor propertyDescriptor = property.getPropertyDescriptor();
// Method writeMethod = propertyDescriptor.getWriteMethod();
Method writeMethod = property.getWriteMethod();
try {
ReflectionUtil.makeAccessible(writeMethod);
writeMethod.invoke(getInsatance(), value);
} catch (IllegalArgumentException e) {
throw new NotWritablePropertyException(getInsatance().getClass(), property.getPropertyName(), "Could not set object property", e);
} catch (IllegalAccessException e) {
throw new NotWritablePropertyException(getInsatance().getClass(), property.getPropertyName(), "Could not set object property", e);
} catch (InvocationTargetException e) {
throw new NotWritablePropertyException(getInsatance().getClass(), property.getPropertyName(), "Could not set object property", e.getTargetException());
}
// if(property.getOriginalPropertyName() != null) {
// beanWrapper.setPropertyValue(property.getOriginalPropertyName(), value);
// } else {
// beanWrapper.setPropertyValue(property.getPropertyName(), value);
// }
}
public void setPropertyValue(String propertyName, Object value) {
NexacroBeanProperty property = getCachedBeanMappings().getProperty(propertyName);
if(property == null ) {
throw new NotWritablePropertyException(getInsatance().getClass(), propertyName);
}
setPropertyValue(property, value);
}
public Object getPropertyValue(NexacroBeanProperty property) {
if(property == null) {
return null;
}
String propertyName = property.getPropertyName();
if(property.getOriginalPropertyName() != null) {
propertyName = property.getOriginalPropertyName();
}
// if(beanWrapper.isReadableProperty(propertyName)) {
return beanWrapper.getPropertyValue(propertyName);
}
public Object getPropertyValue(String propertyName) {
NexacroBeanProperty property = getCachedBeanMappings().getProperty(propertyName);
if(property == null) {
throw new NotWritablePropertyException(getInsatance().getClass(), propertyName);
}
return getPropertyValue(property);
}
public Object getInsatance() {
return beanWrapper.getWrappedInstance();
}
private CachedBeanMappings getCachedBeanMappings() {
if(cachedMapping != null) {
return cachedMapping;
}
cachedMapping = CachedBeanMappings.beanMappings(beanWrapper);
return cachedMapping;
}
public static NexacroBeanWrapper createBeanWrapper(Object obj) {
return new NexacroBeanWrapper(obj);
}
public static NexacroBeanWrapper createBeanWrapper(Class<?> clazz) {
return new NexacroBeanWrapper(clazz);
}
private static class CachedBeanMappings {
private static Logger logger = LoggerFactory.getLogger(NexacroBeanWrapper.class);
private static final String IS = "is";
private static Map<Class, CachedBeanMappings> classCache = Collections.synchronizedMap(new HashMap<Class, CachedBeanMappings>());
private Map<String, NexacroBeanProperty> propertyCache;
/* supported all properties */
private NexacroBeanProperty[] beanProperties;
private CachedBeanMappings(BeanWrapper beanWrapper) {
initBeanPropertyNames(beanWrapper);
}
static CachedBeanMappings beanMappings(BeanWrapper beanWrapper) {
Class wrappedClass = beanWrapper.getWrappedClass();
CachedBeanMappings mapping = classCache.get(wrappedClass);
if(mapping != null) {
return mapping;
}
mapping = new CachedBeanMappings(beanWrapper);
classCache.put(wrappedClass, mapping);
return mapping;
}
private void initBeanPropertyNames(BeanWrapper beanWrapper) {
propertyCache = new HashMap<String, NexacroBeanProperty>();
List<NexacroBeanProperty> tmpList = new ArrayList<NexacroBeanProperty>();
Class wrappedClass = beanWrapper.getWrappedClass();
// not ordered..
PropertyDescriptor[] propertyDescriptors = beanWrapper.getPropertyDescriptors();
for(PropertyDescriptor descriptor: propertyDescriptors) {
if(!validateReadAndWriteMethod(wrappedClass, descriptor)) {
continue;
}
// ignore row type
if("rowType".equalsIgnoreCase(descriptor.getName())) {
continue;
}
String name = descriptor.getName();
Class<?> propertyType = descriptor.getPropertyType();
boolean isConverted = false;
String adjustName = name;
if(propertyType == boolean.class) {
if(!name.startsWith(IS)) {
try {
// check exist field
if(wrappedClass.getField(IS + getBaseName(name)) != null) {
adjustName = IS + getBaseName(name);
isConverted = true;
}
} catch (SecurityException e) {
} catch (NoSuchFieldException e) {
}
}
}
NexacroBeanProperty beanProperty = new NexacroBeanProperty(adjustName, propertyType);
if(isConverted) {
beanProperty.setOriginalPropertyName(name);
}
if(isStaticProperty(descriptor)) {
beanProperty.setStatic(true);
}
// beanProperty.setPropertyDescriptor(descriptor);
beanProperty.setWriteMethod(descriptor.getWriteMethod());
tmpList.add(beanProperty);
propertyCache.put(adjustName, beanProperty);
}
beanProperties = new NexacroBeanProperty[tmpList.size()];
beanProperties = tmpList.toArray(beanProperties);
}
public NexacroBeanProperty[] getProperties() {
return beanProperties;
}
public NexacroBeanProperty getProperty(String name) {
return propertyCache.get(name);
}
private boolean validateReadAndWriteMethod(Class<?> clazz, PropertyDescriptor descriptor) {
String name = descriptor.getName();
Method readMethod = descriptor.getReadMethod();
Method writeMethod = descriptor.getWriteMethod();
if(name == null) {
return false;
}
if(!NexacroConverterHelper.isConvertibleType(descriptor.getPropertyType())) {
// unsupported type
return false;
}
if(readMethod == null && writeMethod != null) {
// find static method.. introspection is unsupported static getter.
String findPropertyName = "get"+getBaseName(name);
Method findedMethod = ReflectionUtils.findMethod(clazz, findPropertyName);
if(findedMethod != null) {
if(ReflectionUtil.isStaticMethod(findedMethod)) {
setStaticReadMethodIntoDescriptor(descriptor, findedMethod);
}
}
readMethod = descriptor.getReadMethod();
if(readMethod != null) {
return true;
}
if(logger.isDebugEnabled()) {
logger.debug("skipped property {} of bean class[{}]:" +
" Bean Property {} is not readable or has an invalid getter or setter." +
" Does the return type of the getter match the parameter type of the setter"
, name, clazz, name);
}
} else if(readMethod == null || writeMethod == null) {
return false;
}
return true;
}
private void setStaticReadMethodIntoDescriptor(PropertyDescriptor descriptor, Method staticMethod) {
// for spring GenericTypeAwarePropertyDescriptor
Field field = null;
try {
field = ReflectionUtil.getField(descriptor.getClass(), "readMethod");
} catch(ReflectionFailException e) {
// nothing..
}
if(field != null) {
ReflectionUtil.makeAccessible(field);
try {
field.set(descriptor, staticMethod);
} catch (IllegalArgumentException e) {
logger.error("{} finded static gerrer '{}' method setting failed.", descriptor.getName(), staticMethod);
return;
} catch (IllegalAccessException e) {
logger.error("{} finded static gerrer '{}' method setting failed.", descriptor.getName(), staticMethod);
return;
}
} else {
try {
descriptor.setReadMethod(staticMethod);
} catch (IntrospectionException e) {
logger.error("{} finded static gerrer '{}' method setting failed.", descriptor.getName(), staticMethod);
return;
}
}
}
private boolean isStaticProperty(PropertyDescriptor descriptor) {
Method readMethod = descriptor.getReadMethod();
Method writeMethod = descriptor.getWriteMethod();
if(ReflectionUtil.isStaticMethod(readMethod) && ReflectionUtil.isStaticMethod(writeMethod)) {
return true;
}
return false;
}
private String getBaseName(String name) {
if (name == null || name.length() == 0) {
return name;
}
return name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1);
}
}
// private static class GenericTypeAwarePropertyDescriptorWrapper extends GenericTypeAwarePropertyDescriptor {
//
// private Method staticReadMethod;
//
//
// }
}

View File

@@ -0,0 +1,470 @@
package com.nexacro.spring.data.support;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.nexacro.spring.data.convert.NexacroConverter.ConvertiblePair;
import com.nexacro.spring.util.ReflectionUtil;
import com.nexacro.xapi.data.ColumnHeader;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.DataTypes;
import com.nexacro.xapi.data.Variable;
import com.nexacro.xapi.data.datatype.DataType;
import com.nexacro.xapi.data.datatype.DataTypeFactory;
import com.nexacro.xapi.data.datatype.PlatformDataType;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : VariableConverterHelper.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public abstract class NexacroConverterHelper {
private static final Set<ConvertiblePair> listToDataSetConvertibleSets = Collections.singleton(new ConvertiblePair(List.class, DataSet.class));
private static final Set<ConvertiblePair> dataSetToListConvertibleSets = Collections.singleton(new ConvertiblePair(DataSet.class, List.class));
private static final Set<ConvertiblePair> objectToVariableConvertibleSets = new HashSet<ConvertiblePair>();
private static final Set<ConvertiblePair> variableToObjectConvertibleSets = new HashSet<ConvertiblePair>();
private static final Map<Class<?>, Class<?>> primitiveTypeWrapperMap = new HashMap<Class<?>, Class<?>>(8);
private static final Map<Class<?>, Class<?>> nonPrimitiveTypeMap = new HashMap<Class<?>, Class<?>>(4);
static {
// byte[], int, long, float, double, boolean, Object, String, BigDecimal, Date
// byte, char, short는 지원하지 않는다.
primitiveTypeWrapperMap.put(byte[].class, Byte[].class);
// 아래 항목 지원 시 데이터 유실이 발생할 수 있다.
// primitiveWrapperTypeMap.put(byte.class, Byte.class);
// primitiveWrapperTypeMap.put(char.class, Character.class);
// primitiveWrapperTypeMap.put(short.class, Short.class);
primitiveTypeWrapperMap.put(int.class, Integer.class);
primitiveTypeWrapperMap.put(long.class, Long.class);
primitiveTypeWrapperMap.put(float.class, Float.class);
primitiveTypeWrapperMap.put(double.class, Double.class);
primitiveTypeWrapperMap.put(boolean.class, Boolean.class);
nonPrimitiveTypeMap.put(Object.class, Object.class);
nonPrimitiveTypeMap.put(String.class, String.class);
nonPrimitiveTypeMap.put(BigDecimal.class, BigDecimal.class);
nonPrimitiveTypeMap.put(Date.class, Date.class);
Set<Class<?>> keySet = primitiveTypeWrapperMap.keySet();
for(Class<?> clazz: keySet) {
objectToVariableConvertibleSets.add(new ConvertiblePair(clazz, Variable.class));
objectToVariableConvertibleSets.add(new ConvertiblePair(primitiveTypeWrapperMap.get(clazz), Variable.class));
}
for(Class<?> clazz: keySet) {
variableToObjectConvertibleSets.add(new ConvertiblePair(Variable.class, clazz));
variableToObjectConvertibleSets.add(new ConvertiblePair(Variable.class, primitiveTypeWrapperMap.get(clazz)));
}
Set<Class<?>> nonKeySet = nonPrimitiveTypeMap.keySet();
for(Class<?> clazz: nonKeySet) {
objectToVariableConvertibleSets.add(new ConvertiblePair(clazz, Variable.class));
}
for(Class<?> clazz: nonKeySet) {
variableToObjectConvertibleSets.add(new ConvertiblePair(Variable.class, clazz));
}
}
static Set<ConvertiblePair> getObjectToVariableConvertibleTypes() {
return objectToVariableConvertibleSets;
}
static Set<ConvertiblePair> getVariableToObjectConvertibleTypes() {
return variableToObjectConvertibleSets;
}
static Set<ConvertiblePair> getListToDataSetConvertibleTypes() {
return listToDataSetConvertibleSets;
}
static Set<ConvertiblePair> getDataSetToListConvertibleTypes() {
return dataSetToListConvertibleSets;
}
public static Object getDefaultValue(DataType dataType) {
int type = dataType.getType();
if(type == DataTypes.STRING) {
return DataTypes.DEFAULT_VALUE_STRING;
} else if(type == DataTypes.INT) {
return DataTypes.DEFAULT_VALUE_INT;
} else if(type == DataTypes.LONG) {
return DataTypes.DEFAULT_VALUE_LONG;
} else if(type == DataTypes.FLOAT) {
return DataTypes.DEFAULT_VALUE_FLOAT;
} else if(type == DataTypes.DOUBLE) {
return DataTypes.DEFAULT_VALUE_DOUBLE;
} else if(type == DataTypes.BOOLEAN) {
return DataTypes.DEFAULT_VALUE_BOOLEAN;
} else if(type == DataTypes.DATE) {
return DataTypes.DEFAULT_VALUE_DATE;
} else if(type == DataTypes.DATE_TIME) {
return DataTypes.DEFAULT_VALUE_DATE_TIME;
} else if(type == DataTypes.TIME) {
return DataTypes.DEFAULT_VALUE_TIME;
} else if(type == DataTypes.BIG_DECIMAL) {
return DataTypes.DEFAULT_VALUE_BIG_DECIMAL;
} else if(type == DataTypes.BLOB) {
return DataTypes.DEFAULT_VALUE_BLOB;
}
return DataTypes.DEFAULT_VALUE_OBJECT;
}
public static Object getDefaultMetaDataValue(DataType dataType) {
int type = dataType.getType();
if(type == DataTypes.STRING) {
return "";
} else if(type == DataTypes.INT) {
return DataTypes.DEFAULT_VALUE_INT;
} else if(type == DataTypes.LONG) {
return DataTypes.DEFAULT_VALUE_LONG;
} else if(type == DataTypes.FLOAT) {
return DataTypes.DEFAULT_VALUE_FLOAT;
} else if(type == DataTypes.DOUBLE) {
return DataTypes.DEFAULT_VALUE_DOUBLE;
} else if(type == DataTypes.BOOLEAN) {
return DataTypes.DEFAULT_VALUE_BOOLEAN;
} else if(type == DataTypes.DATE) {
return new Date();
} else if(type == DataTypes.DATE_TIME) {
return new Date();
} else if(type == DataTypes.TIME) {
return new Date();
} else if(type == DataTypes.BIG_DECIMAL) {
return new BigDecimal(0);
} else if(type == DataTypes.BLOB) {
return new byte[0];
}
return DataTypes.DEFAULT_VALUE_OBJECT;
}
public static DataType getDataType(Class targetClass) {
// DataTypeFactory의 byte[] 문제.
if(String.class.equals(targetClass)) {
return PlatformDataType.STRING;
} else if(int.class.equals(targetClass) || Integer.class.equals(targetClass)) {
return PlatformDataType.INT;
} else if(long.class.equals(targetClass) || Long.class.equals(targetClass)) {
return PlatformDataType.LONG;
} else if(float.class.equals(targetClass) || Float.class.equals(targetClass)) {
return PlatformDataType.FLOAT;
} else if(double.class.equals(targetClass) || Double.class.equals(targetClass)) {
return PlatformDataType.DOUBLE;
} else if(boolean.class.equals(targetClass) || Boolean.class.equals(targetClass)) {
return PlatformDataType.BOOLEAN;
} else if(Date.class.equals(targetClass)) {
return PlatformDataType.DATE_TIME;
} else if(BigDecimal.class.equals(targetClass)) {
return PlatformDataType.BIG_DECIMAL;
} else if(Object.class.equals(targetClass)) {
return PlatformDataType.UNDEFINED;
} else if(targetClass.isArray() && (byte[].class.equals(targetClass) || Byte[].class.equals(targetClass))) {
return PlatformDataType.BLOB;
}
return PlatformDataType.UNDEFINED;
}
static DataType getDataTypeOfValue(Object value) {
if(value == null) {
return PlatformDataType.UNDEFINED;
}
DataType dataTypeOfValue = DataTypeFactory.getDataTypeOfValue(value);
if(dataTypeOfValue.getType() == PlatformDataType.UNDEFINED.getType()) {
if(value instanceof Byte[]) {
dataTypeOfValue = PlatformDataType.BLOB;
}
} else if(dataTypeOfValue.getType() == PlatformDataType.DATE.getType()) {
// data는 DATE_TIME으로 변경.
dataTypeOfValue = PlatformDataType.DATE_TIME;
}
return dataTypeOfValue;
}
static Variable toVariable(String name, Object value) {
Variable var = new Variable(name);
if(value == null) {
return var;
}
// 최초 type 설정이 안되어 있을 경우 설정된 값에 따라 Type이 설정 된다.
if(value instanceof Byte[]) {
var.set(toPrimitive((Byte[]) value));
} else {
var.set(value);
}
return var;
}
static Object toObject(Variable variable, Class<?> targetClass) {
// 직접 변환할까..
if(String.class.equals(targetClass)) {
return variable.getString();
} else if(int.class.equals(targetClass) || Integer.class.equals(targetClass)) {
return variable.getInt();
} else if(long.class.equals(targetClass) || Long.class.equals(targetClass)) {
return variable.getLong();
} else if(float.class.equals(targetClass) || Float.class.equals(targetClass)) {
return variable.getFloat();
} else if(double.class.equals(targetClass) || Double.class.equals(targetClass)) {
return variable.getDouble();
} else if(boolean.class.equals(targetClass) || Boolean.class.equals(targetClass)) {
return variable.getBoolean();
} else if(Date.class.equals(targetClass)) {
return variable.getDateTime();
} else if(BigDecimal.class.equals(targetClass)) {
return variable.getBigDecimal();
} else if(Object.class.equals(targetClass)) {
return variable.getObject();
} else if(targetClass.isArray()) {
if(byte[].class.equals(targetClass)) {
return variable.getBlob();
} else if(Byte[].class.equals(targetClass)) {
byte[] blob = variable.getBlob();
return toObject(blob);
}
}
return variable.getObject();
}
static Object toObject(Object obj) {
if(obj == null) {
return null;
}
if(obj instanceof Byte[]) {
return toPrimitive((Byte[])obj);
}
return obj;
}
static Object toObjectFromDataSetValue(DataSet ds, int rowIndex, int colIndex, Class<?> targetClass, boolean isSavedData, boolean isRemovedData) {
if(Object.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedData(rowIndex, colIndex);
} else {
return ds.getObject(rowIndex, colIndex);
}
} else if(String.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedStringData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedStringData(rowIndex, colIndex);
} else {
return ds.getString(rowIndex, colIndex);
}
} else if(int.class.equals(targetClass) || Integer.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedIntData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedIntData(rowIndex, colIndex);
} else {
return ds.getInt(rowIndex, colIndex);
}
} else if(long.class.equals(targetClass) || Long.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedLongData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedLongData(rowIndex, colIndex);
} else {
return ds.getLong(rowIndex, colIndex);
}
} else if(float.class.equals(targetClass) || Float.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedFloatData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedFloatData(rowIndex, colIndex);
} else {
return ds.getFloat(rowIndex, colIndex);
}
} else if(double.class.equals(targetClass) || Double.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedDoubleData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedDoubleData(rowIndex, colIndex);
} else {
return ds.getDouble(rowIndex, colIndex);
}
} else if(boolean.class.equals(targetClass) || Boolean.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedBooleanData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedBooleanData(rowIndex, colIndex);
} else {
return ds.getBoolean(rowIndex, colIndex);
}
} else if(Date.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedDateTimeData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedDateTimeData(rowIndex, colIndex);
} else {
return ds.getDateTime(rowIndex, colIndex);
}
} else if(BigDecimal.class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedBigDecimalData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedBigDecimalData(rowIndex, colIndex);
} else {
return ds.getBigDecimal(rowIndex, colIndex);
}
} else if(targetClass.isArray()) {
if(byte[].class.equals(targetClass)) {
if(isSavedData) {
return ds.getSavedBlobData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedBlobData(rowIndex, colIndex);
} else {
return ds.getBlob(rowIndex, colIndex);
}
} else if(Byte[].class.equals(targetClass)) {
byte[] blob;
if(isSavedData) {
blob = ds.getSavedBlobData(rowIndex, colIndex);
return toObject(blob);
} else if(isRemovedData) {
blob = ds.getRemovedBlobData(rowIndex, colIndex);
return toObject(blob);
} else {
blob = ds.getBlob(rowIndex, colIndex);
return toObject(blob);
}
}
}
// return object
if(isSavedData) {
return ds.getSavedData(rowIndex, colIndex);
} else if(isRemovedData) {
return ds.getRemovedData(rowIndex, colIndex);
} else {
return ds.getObject(rowIndex, colIndex);
}
}
static boolean isSupportedBean(Class clazz) {
if(!clazz.isInterface() && !clazz.isPrimitive() && !clazz.isEnum() && !clazz.isArray()) {
return true;
}
return false;
}
static Map<String, Field> getAdjustConvertibleFields(Class clazz, DataSet ds) {
Map<String, Field> accessibleFields = getAccessibleFields(clazz);
Map<String, Field> adjustConvertibleFields = new HashMap<String, Field>();
// 획득한 field와 dataset field를 검사하여 실제로 사용될 field 들을 추려둔다.
int columnCount = ds.getColumnCount();
for(int i=0; i<columnCount; i++) {
ColumnHeader column = ds.getColumn(i);
String columnName = column.getName();
// 대소문자를 구별한다!
Field field = accessibleFields.get(columnName);
if(field != null) {
adjustConvertibleFields.put(columnName, field);
}
}
return adjustConvertibleFields;
}
static Map<String, Field> getAccessibleFields(Class clazz) {
Map<String, Field> accessibleFields = new HashMap<String, Field>();
Class<?> searchType = clazz;
while (!Object.class.equals(searchType) && searchType != null) {
Field[] fields = searchType.getDeclaredFields();
for (Field field : fields) {
Class<?> type = field.getType();
if(isConvertibleType(type)) {
ReflectionUtil.makeAccessible(field);
accessibleFields.put(field.getName(), field);
}
}
searchType = searchType.getSuperclass();
}
return accessibleFields;
}
static boolean isConvertibleType(Class<?> type) {
if(primitiveTypeWrapperMap.get(type) != null) {
return true;
} else if(nonPrimitiveTypeMap.get(type) != null) {
return true;
} else if(primitiveTypeWrapperMap.containsValue(type)) {
return true;
} else if(nonPrimitiveTypeMap.containsValue(type)) {
return true;
}
return false;
}
/* commons.lang.ArrayUtils source*/
private static Byte[] toObject(byte[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
return new Byte[0];
}
final Byte[] result = new Byte[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = new Byte(array[i]);
}
return result;
}
private static byte[] toPrimitive(Byte[] array) {
if (array == null) {
return null;
} else if (array.length == 0) {
return new byte[0];
}
final byte[] result = new byte[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = array[i].byteValue();
}
return result;
}
}

View File

@@ -0,0 +1,111 @@
package com.nexacro.spring.data.support;
import java.util.Map;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.xapi.data.DataSet;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ObjectToDataSetConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 17.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 17. Park SeongMin 최초 생성
* </pre>
*/
public class ObjectToDataSetConverter extends AbstractDataSetConverter implements NexacroConverter<Object, DataSet> {
@Override
public boolean canConvert(Class source, Class target) {
if(source == null || target == null) {
return false;
}
// support list sub class
if(NexacroConverterHelper.isSupportedBean(source) && DataSet.class.equals(target)) {
return true;
}
return false;
}
@Override
public DataSet convert(Object source, ConvertDefinition definition) throws NexacroConvertException {
if(definition ==null) {
throw new IllegalArgumentException(ConvertDefinition.class.getSimpleName()+" must not be null.");
}
if(source == null) {
return new DataSet(definition.getName());
}
if(source == null) {
return new DataSet(definition.getName());
}
// DataSet SavedType은 처리 하지 않는다. (UI 처리 불필요)
DataSet ds = null;
if(source instanceof Map) {
ds = convertMapToDataSet((Map)source, definition);
} else {
ds = convertBeanToDataSet(source, definition);
}
return null;
}
private DataSet convertBeanToDataSet(Object source, ConvertDefinition definition) throws NexacroConvertException {
// 지원하는 형식인지 확인 한다.
if(!NexacroConverterHelper.isSupportedBean(source.getClass())) {
throw new NexacroConvertException("unsupported source type. type="+source.getClass());
}
DataSet ds = new DataSet(definition.getName());
addColumnIntoDataSet(ds, source);
addRowIntoDataSet(ds, source);
return ds;
}
private DataSet convertMapToDataSet(Map source, ConvertDefinition definition) throws NexacroConvertException {
DataSet ds = new DataSet(definition.getName());
addColumnIntoDataSet(ds, source);
addRowIntoDataSet(ds, source);
return ds;
}
@Override
public void addColumnIntoDataSet(DataSet ds, Map source) throws NexacroConvertException {
super.addColumnIntoDataSet(ds, source);
}
@Override
public void addColumnIntoDataSet(DataSet ds, Object source) {
super.addColumnIntoDataSet(ds, source);
}
@Override
public void addRowIntoDataSet(DataSet ds, Map source) throws NexacroConvertException {
super.addRowIntoDataSet(ds, source);
}
@Override
public void addRowIntoDataSet(DataSet ds, Object source) {
super.addRowIntoDataSet(ds, source);
}
}

View File

@@ -0,0 +1,61 @@
package com.nexacro.spring.data.support;
import java.util.Set;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.xapi.data.Variable;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ObjectToVariableConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class ObjectToVariableConverter extends AbstractListenerHandler implements NexacroConverter<Object, Variable> {
@Override
public boolean canConvert(Class source, Class target) {
if(source == null || target == null) {
return false;
}
ConvertiblePair comparePair = new ConvertiblePair(source, target);
Set<ConvertiblePair> objectToVariableConvertibleTypes = NexacroConverterHelper.getObjectToVariableConvertibleTypes();
for(ConvertiblePair pair: objectToVariableConvertibleTypes) {
if(pair.equals(comparePair)) {
return true;
}
}
return false;
}
@Override
public Variable convert(Object source, ConvertDefinition definition) throws NexacroConvertException {
Variable variable = NexacroConverterHelper.toVariable(definition.getName(), source);
// fire event
Object obj = fireVariableConvertedValue(variable, variable.getObject());
variable.set(obj);
return variable;
}
}

View File

@@ -0,0 +1,63 @@
package com.nexacro.spring.data.support;
import java.util.Set;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.xapi.data.Variable;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : VariableToObjectConverter.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class VariableToObjectConverter extends AbstractListenerHandler implements NexacroConverter<Variable, Object> {
@Override
public boolean canConvert(Class source, Class target) {
if(source == null || target == null) {
return false;
}
ConvertiblePair comparePair = new ConvertiblePair(source, target);
Set<ConvertiblePair> variableToObjectConvertibleTypes = NexacroConverterHelper.getVariableToObjectConvertibleTypes();
for(ConvertiblePair pair: variableToObjectConvertibleTypes) {
if(pair.equals(comparePair)) {
return true;
}
}
return false;
}
/*
* @see com.nexacro.spring.data.NexacroConverter#convert(java.lang.Object)
*/
@Override
public Object convert(Variable source, ConvertDefinition definition) throws NexacroConvertException {
Object object = NexacroConverterHelper.toObject(source, definition.getGenericType());
// fire event
object = fireVariableConvertedValue(source, object);
return object;
}
}

View File

@@ -0,0 +1,14 @@
package com.nexacro.spring.interceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExceptionTracer {
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionTracer.class);
public void trace(Exception exception) throws Exception {
LOGGER.error(exception.getMessage());
}
}

View File

@@ -0,0 +1,8 @@
/**
*
*/
/**
* @author Park SeongMin
*
*/
package com.nexacro.spring;

View File

@@ -0,0 +1,231 @@
package com.nexacro.spring.resolve;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.View;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.spring.data.NexacroFileResult;
import com.nexacro.spring.data.NexacroResult;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.spring.data.convert.NexacroConverterFactory;
import com.nexacro.spring.view.NexacroFileView;
import com.nexacro.spring.view.NexacroView;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
/**
* <pre>
* Controller에서 반환되는 데이터를 nexacro platform 데이터 형식으로 데이터 변환을 수행한다.
*
* 지원하는 형식은 다음과 같다.
*
* <li>NexacroResult</li>
* <li>NexacroFileResult</li>
* <li>PlatformData</li>
* </pre>
*
* @ClassName : NexacroHandlerMethodReturnValueHandler.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 27.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 27. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
private Logger logger = LoggerFactory.getLogger(NexacroHandlerMethodReturnValueHandler.class);
private Logger performanceLogger = LoggerFactory.getLogger(NexacroConstants.PERFORMANCE_LOGGER);
private View view;
private View fileView;
public View getView() {
if(view == null) {
return new NexacroView();
} else {
return view;
}
}
public void setView(View view) {
this.view = view;
}
public View getFileView() {
if(fileView == null) {
return new NexacroFileView();
} else {
return fileView;
}
}
public void setFileView(View fileView) {
this.fileView = fileView;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
Class<?> parameterType = returnType.getParameterType();
if(NexacroResult.class.isAssignableFrom(parameterType)) {
return true;
} else if(PlatformData.class.isAssignableFrom(parameterType)) {
return true;
} else if(NexacroFileResult.class.isAssignableFrom(parameterType)) {
return true;
}
return false;
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
Class<?> parameterType = returnType.getParameterType();
if(returnValue == null) {
mavContainer.setView(getView());
return;
}
View responseView = null;
StopWatch sw = new StopWatch(getClass().getSimpleName());
sw.start("resolve return value");
try {
if(NexacroResult.class.isAssignableFrom(parameterType)) {
// first use platform data
NexacroResult nexacroResult = (NexacroResult) returnValue;
PlatformData platformData = nexacroResult.getPlatformData();
// add datasets
addDataSetsIntoPlatformData(platformData, nexacroResult);
// add variables
addVariablesIntoPlatformData(platformData, nexacroResult);
addErrorInformationIntoPlatformData(platformData, nexacroResult);
// 변환 된 PlatformData 전달.
mavContainer.addAttribute(NexacroConstants.ATTRIBUTE.NEXACRO_PLATFORM_DATA, platformData);
responseView = getView();
} else if(PlatformData.class.isAssignableFrom(parameterType)) {
PlatformData platformData = (PlatformData) returnValue;
mavContainer.addAttribute(NexacroConstants.ATTRIBUTE.NEXACRO_PLATFORM_DATA, platformData);
responseView = getView();
} else if(NexacroFileResult.class.isAssignableFrom(parameterType)) {
NexacroFileResult fileResult = (NexacroFileResult) returnValue;
mavContainer.addAttribute(NexacroConstants.ATTRIBUTE.NEXACRO_FILE_DATA, fileResult);
responseView = getFileView();
} else {
// default..
responseView = getView();
}
} catch(Exception e) {
logger.error("Error handling return value. value"+returnValue+", e="+e +", message="+e.getMessage());
throw e;
} finally {
sw.stop();
if(performanceLogger.isTraceEnabled()) {
performanceLogger.trace(sw.prettyPrint());
}
}
mavContainer.setView(responseView);
}
private void addDataSetsIntoPlatformData(PlatformData platformData, NexacroResult nexacroResult) throws NexacroConvertException {
Map<String, List> dataSets = nexacroResult.getDataSets();
Set<String> dataSetKeySet = dataSets.keySet();
for(String name: dataSetKeySet) {
List list = dataSets.get(name);
NexacroConverter dataSetConverter = getDataSetConverter(list.getClass());
ConvertDefinition definition = new ConvertDefinition(name);
Object convert = dataSetConverter.convert(list, definition);
if(convert != null && convert instanceof DataSet) {
platformData.addDataSet((DataSet) convert);
}
}
}
private void addVariablesIntoPlatformData(PlatformData platformData, NexacroResult nexacroResult) throws NexacroConvertException {
Map<String, Object> variables = nexacroResult.getVariables();
Set<String> variableKeySets = variables.keySet();
for(String name: variableKeySets) {
Object object = variables.get(name);
NexacroConverter variableConverter = getVariableConverter(object.getClass());
ConvertDefinition definition = new ConvertDefinition(name);
Object convert = variableConverter.convert(object, definition);
if(convert != null && convert instanceof Variable) {
platformData.addVariable((Variable) convert);
}
}
}
/**
* Statements
*
* @param platformData
* @param nexacroResult
*/
private void addErrorInformationIntoPlatformData(PlatformData platformData, NexacroResult nexacroResult) {
// result status
if(nexacroResult.registedErrorCode()) {
int errorCode = nexacroResult.getErrorCode();
String errorMsg = nexacroResult.getErrorMsg();
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_CODE, errorCode));
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_MSG, errorMsg));
} else {
if(platformData.getVariable(NexacroConstants.ERROR.ERROR_CODE) == null) {
// binary 통신 시 반드시 필요.
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_CODE, NexacroConstants.ERROR.DEFAULT_ERROR_CODE));
}
}
}
private NexacroConverter getDataSetConverter(Class source) {
return getConverter(source, DataSet.class);
}
private NexacroConverter getVariableConverter(Class source) {
return getConverter(source, Variable.class);
}
private NexacroConverter getConverter(Class source, Class target) {
return NexacroConverterFactory.getConverter(source, target);
}
}

View File

@@ -0,0 +1,383 @@
package com.nexacro.spring.resolve;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.spring.annotation.ParamDataSet;
import com.nexacro.spring.annotation.ParamVariable;
import com.nexacro.spring.data.NexacroFirstRowHandler;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.convert.NexacroConvertListener;
import com.nexacro.spring.data.convert.NexacroConverter;
import com.nexacro.spring.data.convert.NexacroConverterFactory;
import com.nexacro.spring.servlet.NexacroContext;
import com.nexacro.spring.servlet.NexacroContextHolder;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.DataSetList;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
import com.nexacro.xapi.data.VariableList;
import com.nexacro.xapi.tx.HttpPlatformRequest;
import com.nexacro.xapi.tx.HttpPlatformResponse;
import com.nexacro.xapi.tx.PlatformException;
/**
*
* <pre>
* Nexacro platform을 위한 <code>HandlerMethodArgumentResolver</code>이다.
*
* 지원하는 형식은 다음과 같다.
*
* ...
*
* </pre>
*
* @ClassName : NexacroMethodArgumnetResolver.java
* @author Park SeongMin
* @since 2015. 7. 27.
* @version 1.0
* @see NexacroHandlerMethodReturnValueHandler
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 27. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroMethodArgumentResolver implements HandlerMethodArgumentResolver {
private Logger logger = LoggerFactory.getLogger(NexacroMethodArgumentResolver.class);
private Logger performanceLogger = LoggerFactory.getLogger(NexacroConstants.PERFORMANCE_LOGGER);
// convert에서 사용가능한 event listener를 등록할 수 있어야 한다.
private static final Map<Class<?>, Object> primitiveTypeDefaultValueMap = new HashMap<Class<?>, Object>(8);
private List<NexacroConvertListener> convertListeners;
static {
primitiveTypeDefaultValueMap.put(byte.class, 0);
primitiveTypeDefaultValueMap.put(short.class, 0);
primitiveTypeDefaultValueMap.put(int.class, 0);
primitiveTypeDefaultValueMap.put(long.class, 0l);
primitiveTypeDefaultValueMap.put(float.class, 0.0f);
primitiveTypeDefaultValueMap.put(double.class, 0.0d);
primitiveTypeDefaultValueMap.put(char.class, '\u0000');
primitiveTypeDefaultValueMap.put(boolean.class, false);
}
public NexacroMethodArgumentResolver() {
if(logger.isDebugEnabled()) {
logger.debug("NexacroMethodArgumnetResolver() " + this);
}
}
public void setConvertListeners(List<NexacroConvertListener> convertListeners) {
this.convertListeners = convertListeners;
}
@Override
public boolean supportsParameter(MethodParameter param) {
if(isDefaultParameter(param)) {
return true;
} else if(isExtendedParameter(param)) {
return true;
}
return false;
}
private boolean isDefaultParameter(MethodParameter param) {
Class paramClass = param.getParameterType();
if(PlatformData.class.equals(paramClass)) {
return true;
} else if(DataSetList.class.equals(paramClass)) {
return true;
} else if(VariableList.class.equals(paramClass)) {
return true;
} else if(HttpPlatformRequest.class.equals(paramClass)) {
return true;
} else if(HttpPlatformResponse.class.equals(paramClass)) {
return true;
} else if(NexacroFirstRowHandler.class.equals(paramClass)) {
return true;
} else {
}
return false;
}
private boolean isExtendedParameter(MethodParameter param) {
if(param.getParameterAnnotation(ParamDataSet.class) != null) {
return true;
} else if(param.getParameterAnnotation(ParamVariable.class) != null) {
return true;
} else {
// nothing.
}
return false;
}
@Override
public Object resolveArgument(MethodParameter param, ModelAndViewContainer arg1, NativeWebRequest nativeWebRequest,
WebDataBinderFactory arg3) throws Exception {
NexacroContext nexacroCachedData = prepareResolveArguments(nativeWebRequest);
StopWatch sw = new StopWatch(getClass().getSimpleName());
sw.start("resolve argument (" +param.getParameterName()+ ")");
Object obj = null;
try {
if(isDefaultParameter(param)) {
obj = extractDefaultParameter(param, nexacroCachedData);
} else {
obj = extractExtendedParameter(param, nexacroCachedData);
}
} finally {
sw.stop();
if(performanceLogger.isTraceEnabled()) {
performanceLogger.trace(sw.prettyPrint());
}
}
obj = postResolveArguments(param, obj);
return obj;
}
/**
* <pre>
* 데이터 변환을 수행하기 전 Request로 부터 Platform 데이터로의 변환을 수행한다.
* </pre>
*
* @param nativeWebRequest
* @return NexacroCachedData
* @throws PlatformException
*/
private NexacroContext prepareResolveArguments(NativeWebRequest nativeWebRequest) throws PlatformException {
NexacroContext cache = (NexacroContext) parsePlatformRequestOrGetAttribute(nativeWebRequest);
return cache;
}
private Object postResolveArguments(MethodParameter param, Object resolvedObject) {
if(resolvedObject != null) {
return resolvedObject;
}
// primitive type의 경우 해당 데이터 타입으로 전달해야 한다.
// null로 전달할 경우 IllegalArgumentException이 발생한다.
Class<?> parameterType = param.getParameterType();
if(primitiveTypeDefaultValueMap.containsKey(parameterType)) {
return primitiveTypeDefaultValueMap.get(parameterType);
}
return resolvedObject;
}
private Object extractDefaultParameter(MethodParameter param, NexacroContext nexacroCachedData) {
Class<?> parameterType = param.getParameterType();
if(PlatformData.class.equals(parameterType)) {
return nexacroCachedData.getPlatformData();
} else if(DataSetList.class.equals(parameterType)) {
return nexacroCachedData.getPlatformData().getDataSetList();
} else if(VariableList.class.equals(parameterType)) {
return nexacroCachedData.getPlatformData().getVariableList();
} else if(HttpPlatformRequest.class.equals(parameterType)) {
return nexacroCachedData.getPlatformRequest();
} else if(HttpPlatformResponse.class.equals(parameterType)) {
return nexacroCachedData.getPlatformResponse();
} else if(NexacroFirstRowHandler.class.equals(parameterType)) {
return nexacroCachedData.getFirstRowHandler();
} else {
// nothing.
}
return null;
}
private Object extractExtendedParameter(MethodParameter param, NexacroContext nexacroCachedData) throws NexacroConvertException {
if(param.getParameterAnnotation(ParamDataSet.class) != null) {
return extractDataSetParameter(param, nexacroCachedData);
} else if(param.getParameterAnnotation(ParamVariable.class) != null) {
return extractVariableParameter(param, nexacroCachedData);
} else {
// nothing.
}
return null;
}
private Object extractDataSetParameter(MethodParameter param, NexacroContext nexacroCachedData) throws NexacroConvertException {
Class<?> parameterType = param.getParameterType();
ParamDataSet paramDataSet = param.getParameterAnnotation(ParamDataSet.class);
String dsName = paramDataSet.name();
DataSet dataSet = nexacroCachedData.getPlatformData().getDataSet(dsName);
if(dataSet == null) {
if(logger.isDebugEnabled()) {
logger.debug(dsName + " is null.");
}
return null;
}
// return dataset
if(DataSet.class.equals(parameterType)) {
return dataSet;
}
// support only list parameter
if(!List.class.equals(parameterType)) {
throw new IllegalArgumentException(ParamDataSet.class.getSimpleName()+" annotation support List<?> and DataSet parameter.");
}
Class convertedGenericType = findGenericType(param);
if(convertedGenericType == null) {
// Generic이 null 일 경우에 Map으로 할지? 혹은 바로 오류를 내보낼지 처리 하도록 하자.
throw new IllegalArgumentException(ParamDataSet.class.getSimpleName()+" annotation must be List<?>.");
}
ConvertDefinition definition = new ConvertDefinition(dsName);
definition.setGenericType(convertedGenericType);
Class<?> fromType = DataSet.class;
Class<?> toType = parameterType;
NexacroConverter<DataSet, List> converter = NexacroConverterFactory.getConverter(fromType, toType);
if(converter == null) {
throw new IllegalArgumentException("invalid @ParamDataSet. supported type={DataSet, List<?>}");
}
try {
addConvertListeners(converter);
return converter.convert(dataSet, definition);
} finally {
removeConvertListeners(converter);
}
}
private Object extractVariableParameter(MethodParameter param, NexacroContext nexacroCachedData) throws NexacroConvertException {
Class<?> parameterType = param.getParameterType();
// support only list parameter
ParamVariable paramVariable = param.getParameterAnnotation(ParamVariable.class);
String varName = paramVariable.name();
Variable variable = nexacroCachedData.getPlatformData().getVariable(varName);
if(variable == null) {
if(logger.isDebugEnabled()) {
logger.debug(varName + " is null.");
}
return null;
//throw new IllegalArgumentException("invalid @ParamVariable. ex)@ParamVariable(name=\"variableName\") Object var");
}
// reutrn variable
if(Variable.class.equals(parameterType)) {
return variable;
}
Class<?> fromType = Variable.class;
Class<?> toType = parameterType;
NexacroConverter<Variable, Object> converter = NexacroConverterFactory.getConverter(fromType, toType);
if(converter == null) {
throw new IllegalArgumentException("invalid @ParamVariable. supported type={Variable, Object, String, int, boolean, long, float, double, BigDecimal, Date, byte[]} ");
}
ConvertDefinition definition = new ConvertDefinition(varName);
definition.setGenericType(parameterType);
try {
addConvertListeners(converter);
return converter.convert(variable, definition);
} finally {
removeConvertListeners(converter);
}
}
private Class findGenericType(MethodParameter param) {
Type genericParameterType = param.getGenericParameterType();
if (genericParameterType instanceof ParameterizedType) {
Type[] types = ((ParameterizedType) genericParameterType).getActualTypeArguments();
return (Class) types[0];
}
return null;
}
private Object getAttribute(NativeWebRequest nativeWebRequest, String attrName) {
return nativeWebRequest.getAttribute(attrName, RequestAttributes.SCOPE_REQUEST);
}
private void setAttribute(NativeWebRequest nativeWebRequest, String attrName, Object obj) {
nativeWebRequest.setAttribute(attrName, obj, RequestAttributes.SCOPE_REQUEST);
}
/**
* NexacroPlatform 형식의 Cache 데이터를 반환 한다.
*
* @return
* @throws PlatformException
*/
private NexacroContext parsePlatformRequestOrGetAttribute(NativeWebRequest nativeWebRequest) throws PlatformException {
// when already parsed. ex - methodArgumentResolver or interceptor
NexacroContext cache = NexacroContextHolder.getNexacroContext();
if(cache != null) {
return cache;
}
HttpServletRequest servletRequest = (HttpServletRequest) nativeWebRequest.getNativeRequest();
HttpServletResponse servletResponse = (HttpServletResponse) nativeWebRequest.getNativeResponse();
cache = NexacroContextHolder.getNexacroContext(servletRequest, servletResponse);
return cache;
}
private void addConvertListeners(NexacroConverter converter) {
if(this.convertListeners == null) {
return;
}
for(NexacroConvertListener listener: this.convertListeners) {
converter.addListener(listener);
}
}
private void removeConvertListeners(NexacroConverter converter) {
if(this.convertListeners == null) {
return;
}
for(NexacroConvertListener listener: this.convertListeners) {
converter.removeListener(listener);
}
}
}

View File

@@ -0,0 +1,78 @@
package com.nexacro.spring.resolve;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import com.nexacro.spring.NexacroException;
import com.nexacro.spring.util.NexacroUtil;
import com.nexacro.spring.view.NexacroModelAndView;
import com.nexacro.spring.view.NexacroView;
public class NexcroMappingExceptionResolver extends AbstractHandlerExceptionResolver {
private final Logger logger = LoggerFactory.getLogger(NexcroMappingExceptionResolver.class);
private View view;
public View getView() {
if(view == null) {
return new NexacroView();
} else {
return view;
}
}
public void setView(View view) {
this.view = view;
}
public NexcroMappingExceptionResolver() {
}
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// nexacro 요청이 아닌 경우 별도 ExceptionResolver 가 처리 할 수 있도록 null을 반환 한다.
if(NexacroUtil.isNexacroRequest(request)) {
// for able framework
prepareResolveException(request, response, handler, ex);
// Nexacro Exception 만을 handling 하도록 한다.
// for nexacro request
NexacroModelAndView mav = new NexacroModelAndView(getView());
if(ex instanceof NexacroException){ // NexacroConvertException
NexacroException nexaExp = (NexacroException) ex;
mav.setErrorCode(nexaExp.getErrorCode());
mav.setErrorMsg(nexaExp.getErrorMsg());
} else {
// PlatformException..
mav.setErrorCode(NexacroException.DEFAULT_ERROR_CODE); //Undefined error Code
// mav.setErrorMsg(NexacroException.DEFAULT_MESSAGE);
mav.setErrorMsg(ex.toString());
}
return mav;
}
return null;
}
private void prepareResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Resolving exception from handler [" + handler + "]: " + ex);
}
logException(ex, request);
}
}

View File

@@ -0,0 +1,68 @@
package com.nexacro.spring.security;
import com.nexacro.spring.data.convert.ConvertEvent;
import com.nexacro.spring.data.convert.NexacroConvertListener;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : WebSecurityListener.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroWebSecurityListener implements NexacroConvertListener {
@Override
public void convertedValue(ConvertEvent event) {
if(event == null) {
return;
}
// security
checkSecurity(event);
}
/**
* Statements
*
* @param event
* @throws Exception
*/
private void checkSecurity(ConvertEvent event) {
Object value = event.getValue();
if(value == null) {
return;
}
String strValue = value.toString();
try {
SecurityUtil.checkPathTraversal(strValue);
} catch (Exception e) {
}
String convertXSS = SecurityUtil.convertXSS(strValue);
if(!strValue.equals(convertXSS)) {
event.setValue(value);
}
}
}

View File

@@ -0,0 +1,186 @@
package com.nexacro.spring.security;
import java.util.HashMap;
import java.util.Map;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.DataSetList;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
import com.nexacro.xapi.data.VariableList;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : SecurityUtil.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 11.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 11. Park SeongMin 최초 생성
* </pre>
*/
public abstract class SecurityUtil {
public static void checkSecurity(PlatformData platformData) throws SecurityException {
VariableList variableList = platformData.getVariableList();
int size = variableList.size();
for(int i=0; i<size; i++) {
Variable variable = variableList.get(i);
checkSecurity(variable);
}
DataSetList dataSetList = platformData.getDataSetList();
size = dataSetList.size();
for(int i=0; i<size; i++) {
DataSet ds = dataSetList.get(i);
checkSecurity(ds);
}
}
public static void checkSecurity(Variable variable) throws SecurityException {
String value = null;
try {
value = variable.getString();
} catch(Exception e) {
// ignore
return;
}
checkPathTraversal(value);
// convert xss
String convertedValue = convertXSS(value);
if(value != null && !value.equals(convertedValue)) {
variable.set(convertedValue);
}
}
public static void checkSecurity(DataSet ds) throws SecurityException {
int rowCount = ds.getRowCount();
int colCount = ds.getColumnCount();
for(int rowIndex=0; rowIndex<rowCount; rowIndex++) {
boolean hasSavedRow = ds.hasSavedRow(rowIndex);
for(int colIndex=0; colIndex<colCount; colIndex++) {
String value = ds.getString(rowIndex, colIndex);
checkPathTraversal(value);
// convert xss
String convertedValue = convertXSS(value);
if(value != null && !value.equals(convertedValue)) {
ds.set(rowIndex, colIndex, value);
}
// saved data..
if(hasSavedRow) {
value = ds.getSavedStringData(rowIndex, colIndex);
checkPathTraversal(value);
// convert xss
convertedValue = convertXSS(value);
if(value != null && !value.equals(convertedValue)) {
ds.setSavedData(rowIndex, colIndex, convertedValue);
}
}
}
} // end data
int removedCount = ds.getRemovedRowCount();
for(int removedIndex=0; removedIndex<removedCount; removedIndex++) {
for(int colIndex=0; colIndex<colCount; colIndex++) {
String value = null;
try {
value = ds.getRemovedStringData(removedIndex, colIndex);
} catch(Exception e) {
// ignore
continue;
}
checkPathTraversal(value);
// convert xss
String convertedValue = convertXSS(value);
if(value != null && !value.equals(convertedValue)) {
ds.setRemovedData(removedIndex, colIndex, convertedValue);
}
}
} // end removed data
}
public static void checkUploadFileExt(String fileName) throws SecurityException {
if(fileName == null) {
return;
}
Map<String, String> securityResult = new HashMap<String, String>();
// // check file extention
// securityResult = WebSecurityUtil.uploadFileExtCheck(fileName, "uploadExt");
// if ("true".equals(securityResult.get("result"))) {
// throw new SecurityException("Web Security Violation " + ((String)securityResult.get("securitySort")) + ", Violation Char:: ' " + ((String)securityResult.get("violationChar")) + "'");
// }
//
// // check file upload detour
// securityResult = WebSecurityUtil.uploadFileExtCheck(fileName, "uploadDetour");
// if ("true".equals(securityResult.get("result"))) {
// throw new SecurityException("Web Security Violation : " + ((String)securityResult.get("securitySort")) + ", Violation Char:: ' " + ((String)securityResult.get("violationChar")) + "'");
// }
}
public static void checkPathTraversal(String value) throws SecurityException {
if(value == null) {
return;
}
// check path traversal attack..
Map<String, String> securityResult = new HashMap<String, String>();
// try {
// securityResult = WebSecurityUtil.checkDownloadParams(value);
// } catch (UnsupportedEncodingException e) {
// // logging..
// throw new SecurityException("encoding format does not support. value="+value, e);
// }
if ("true".equals(securityResult.get("result"))) {
// logging..
throw new SecurityException("Web Security Violation : " + ((String) securityResult.get("securitySort"))
+ ", Violation Char:: ' " + ((String) securityResult.get("violationChar")) + "'");
}
}
public static String convertXSS(String value) {
if(value == null) {
return null;
}
String convertedValue = value;
// String convertedValue = WebSecurityUtil.convertXSSParam(value);
return convertedValue;
}
}

View File

@@ -0,0 +1,165 @@
package com.nexacro.spring.servlet;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.nexacro.spring.data.NexacroFirstRowHandler;
import com.nexacro.spring.util.CharsetUtil;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.tx.HttpPlatformRequest;
import com.nexacro.xapi.tx.HttpPlatformResponse;
import com.nexacro.xapi.tx.PlatformException;
import com.nexacro.xapi.tx.PlatformType;
import com.nexacro.xapi.util.StringUtils;
/**
*
* <pre>
* cache 데이터
* </pre>
*
* @ClassName : NexacroCachedData.java
* @Description : cache 데이터
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroContext {
/* 데이터 수신시 HTTP GET 데이터 등록 여부의 키 */
private static final String REGISTER_GET_PARAMETER = "http.getparameter.register";
/* HTTP GET 데이터 등록시 Variable 형식으로 변환 여부의 키 */
private static final String GET_PARAMETER_AS_VARIABLE = "http.getparameter.asvariable";
private HttpServletRequest request;
private HttpServletResponse response;
private HttpPlatformRequest platformRequest;
private HttpPlatformResponse platformResponse;
private NexacroFirstRowHandler firstRowHandler;
public NexacroContext(HttpServletRequest request, HttpServletResponse response) throws PlatformException {
parseRequest(request, response);
}
private void parseRequest(HttpServletRequest request, HttpServletResponse response) throws PlatformException {
this.request = request;
this.response = response;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
} catch (IOException e) {
throw new PlatformException("Could not get HTTP InputStream", e);
}
String charsetOfRequest = CharsetUtil.getCharsetOfRequest(request, PlatformType.DEFAULT_CHAR_SET);
String httpContentType = request.getContentType();
String userAgent = request.getHeader("User-Agent");
String contentType = findContentType(httpContentType, userAgent);
// SSV 자동처리를 위해 inputStream을 사용하도록 한다.
HttpPlatformRequest httpPlatformRequest = new HttpPlatformRequest(inputStream);
if(PlatformType.HTTP_CONTENT_TYPE_BINARY.equals(httpContentType)) {
httpPlatformRequest.setContentType(contentType);
}
httpPlatformRequest.receiveData();
// SSV 일 경우에만 contentType 존재. 그 외 처리를 위해 설정.
if(httpPlatformRequest.getContentType() == null) {
httpPlatformRequest.setContentType(contentType);
}
HttpPlatformResponse httpPlatformResponse = new HttpPlatformResponse(response, httpPlatformRequest);
this.platformRequest = httpPlatformRequest;
this.platformResponse = httpPlatformResponse;
}
public HttpPlatformRequest getPlatformRequest() {
return platformRequest;
}
public HttpPlatformResponse getPlatformResponse() {
if(platformResponse != null) {
return platformResponse;
}
platformResponse = new HttpPlatformResponse(response, platformRequest);
return platformResponse;
}
public NexacroFirstRowHandler getFirstRowHandler() {
if(firstRowHandler != null) {
return firstRowHandler;
}
firstRowHandler = new NexacroFirstRowHandler(response, platformRequest);
return firstRowHandler;
}
public boolean isFirstRowFired() {
if(firstRowHandler != null) {
return firstRowHandler.isFirstRowStarted();
}
return false;
}
public PlatformData getPlatformData() {
return this.platformRequest != null ? this.platformRequest.getData(): null;
}
/* HTTP의 ContentType으로부터 송수신 형식을 검색한다. */
String findContentType(String httpContentType, String userAgent) {
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
if (StringUtils.isEmpty(httpContentType)) {
return null;
}
int index = httpContentType.indexOf(';');
String contentType = (index == -1) ? httpContentType : httpContentType.substring(0, index);
if (PlatformType.HTTP_CONTENT_TYPE_XML.equals(contentType)) {
if (isMiPlatform(userAgent)) {
return PlatformType.CONTENT_TYPE_MI_XML;
} else {
return PlatformType.CONTENT_TYPE_XML;
}
} else if (PlatformType.HTTP_CONTENT_TYPE_BINARY.equals(contentType)) {
if (isMiPlatform(userAgent)) {
return PlatformType.CONTENT_TYPE_MI_BINARY;
} else {
return PlatformType.CONTENT_TYPE_BINARY;
}
} else if (PlatformType.HTTP_CONTENT_TYPE_HTML.equals(contentType)) {
return PlatformType.CONTENT_TYPE_HTML;
}
return null;
}
/* MiPlatform 여부 */
private boolean isMiPlatform(String userAgent) {
// MiPlatform 3.1;win32;1400x1050
if (userAgent == null) {
return false;
} else {
return (userAgent.startsWith("MiPlatform"));
}
}
}

View File

@@ -0,0 +1,54 @@
package com.nexacro.spring.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.xapi.tx.PlatformException;
/**
* <pre>
* 현재 Thread 단위의 Web 요청에 대한 Nexacro Platform 데이터를 가진다.
* </pre>
*
* @ClassName : NexacroContextHolder.java
* @author Park SeongMin
* @since 2015. 8. 11.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 11. Park SeongMin 최초 생성
* </pre>
*/
public abstract class NexacroContextHolder {
public static NexacroContext getNexacroContext(HttpServletRequest request, HttpServletResponse response) throws PlatformException {
NexacroContext nexacroContext = new NexacroContext(request, response);
RequestContextHolder.getRequestAttributes().setAttribute(NexacroConstants.ATTRIBUTE.NEXACRO_REQUEST, NexacroConstants.ATTRIBUTE.NEXACRO_REQUEST, RequestAttributes.SCOPE_REQUEST);
setNexacroContext(nexacroContext);
return nexacroContext;
}
public static void setNexacroContext(NexacroContext context) {
RequestContextHolder.getRequestAttributes().setAttribute(NexacroConstants.ATTRIBUTE.NEXACRO_CACHE_DATA, context, RequestAttributes.SCOPE_REQUEST);
}
public static NexacroContext getNexacroContext() {
Object context = RequestContextHolder.getRequestAttributes().getAttribute(NexacroConstants.ATTRIBUTE.NEXACRO_CACHE_DATA, RequestAttributes.SCOPE_REQUEST);
if(context == null) {
return null;
}
if(context instanceof NexacroContext) {
return (NexacroContext) context;
}
return null;
}
}

View File

@@ -0,0 +1,93 @@
package com.nexacro.spring.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.xapi.data.Debugger;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.tx.HttpPlatformRequest;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroWebSecurityInterceptor.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 11.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 11. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroInterceptor extends HandlerInterceptorAdapter {
private Logger logger = LoggerFactory.getLogger(NexacroInterceptor.class);
private Logger performanceLogger = LoggerFactory.getLogger(NexacroConstants.PERFORMANCE_LOGGER);
/**
* This implementation always returns <code>true</code>.
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
parseNexacroRequest(request, response, handler);
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
super.afterCompletion(request, response, handler, ex);
}
private void parseNexacroRequest(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// check in able framework
// checkSecurityWithServletRequest(request);
// checkSecurityMultipart(request);
StopWatch sw = new StopWatch(getClass().getSimpleName());
try {
sw.start("parse request");
NexacroContext context = NexacroContextHolder.getNexacroContext(request, response);
HttpPlatformRequest platformRequest = context.getPlatformRequest();
// sw.start("check security");
// checkSecurityWithPlatformRequest(platformRequest);
} finally {
sw.stop();
if(performanceLogger.isTraceEnabled()) {
performanceLogger.trace(sw.prettyPrint());
}
}
}
private void checkSecurityWithPlatformRequest(HttpPlatformRequest request) throws SecurityException {
PlatformData platformData = request.getData();
// SecurityUtil.checkSecurity(platformData);
if(logger.isDebugEnabled()) {
logger.debug("got request=[{}]", new Debugger().detail(platformData));
}
}
}

View File

@@ -0,0 +1,245 @@
package com.nexacro.spring.util;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CharsetUtil {
private static Properties languageMappingProperties = new Properties();
private static String languageMappingResourceName = "language_mapping.properties";
private static final Logger logger = LoggerFactory.getLogger(CharsetUtil.class);
static {
InputStream inputStream = null;
try {
inputStream = CharsetUtil.class.getResourceAsStream(languageMappingResourceName);
languageMappingProperties.load(inputStream);
} catch (IOException e) {
if(logger.isWarnEnabled()) {
logger.warn("fail to reading language to charset mapping file. properties file='"+languageMappingResourceName+"'");
}
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ignore) {
}
}
}
}
public static String getCharsetOfRequest(HttpServletRequest request, String defaultChasrset) {
String charset = null;
String contentsType = HttpUtil.getHeaderValue(request, HttpUtil.HEADER_CONTENT_TYPE);
charset = getCharsetOfContentType(contentsType);
if (charset == null) {
String charsetValue = HttpUtil.getHeaderValue(request, HttpUtil.HEADER_ACCEPT_CHARSET);
charset = getCharsetOfAcceptCharset(charsetValue);
}
// "ko-kr,ko;q=0.8,en-us;q=0.5,en;q=0.3"와 같이 여러개가 오는 경우가 있다.
if (charset == null) {
String languageValue = HttpUtil.getHeaderValue(request, HttpUtil.HEADER_ACCEPT_LANGUAGE);
charset = getCharsetOfAcceptLanguage(languageValue);
}
if (charset == null) {
charset = defaultChasrset;
}
if (charset == null) {
// do nothing
}
// 이래도 null이면 그대로 반환해야 한다.
// null도 의미를 갖는다.
// 만약 null이 발생할 수 없다면 모델에 설정된 charset이 사용될 수 없다.
return getTrimValue(charset);
}
private static String getCharsetOfContentType(String contentsType) {
if (contentsType == null) {
return null;
}
String charset = null;
String[] contentsTypes = contentsType.split(";");
boolean isUTF8Enabled = false;
boolean isUTF16Enabled = false;
for (int i = 0; i < contentsTypes.length; i++) {
String[] keyAndValue = contentsTypes[i].split("=");
if (keyAndValue.length == 2) {
String trimedValue = keyAndValue[0].trim();
if (trimedValue.equalsIgnoreCase("charset")) {
charset = keyAndValue[1];
if (!isUTF8Enabled) {
isUTF8Enabled = isUTF8Enabled(charset);
}
if (!isUTF16Enabled) {
isUTF16Enabled = isUTF16Enabled(charset);
}
}
}
}
return getOutputCharset(getTrimValue(charset), isUTF8Enabled, isUTF16Enabled);
}
private static String getCharsetOfAcceptCharset(String acceptCharsets) {
if (acceptCharsets == null) {
return null;
}
String charset = null;
boolean isUTF8Enabled = false;
boolean isUTF16Enabled = false;
// "EUC-KR,utf-8;q=0.7,*;q=0.7"와 같이 여러개가 오는 경우가 있다.
String[] charsetValues = acceptCharsets.split(",");
double maxQuality = 0.0d;
for (int i = 0; i < charsetValues.length; i++) {
int index = charsetValues[i].indexOf(";q=");
String charsetName = charsetValues[i];
try {
if (!Charset.isSupported(charsetName)) {
continue;
}
} catch (IllegalCharsetNameException e) {
// do nothing
}
if (!isUTF8Enabled) {
isUTF8Enabled = isUTF8Enabled(charsetName);
}
if (!isUTF16Enabled) {
isUTF16Enabled = isUTF16Enabled(charsetName);
}
double quality = 1.0d;
if (index >= 0) {
charsetName = charsetValues[i].substring(0, index - 1);
quality = Double.valueOf(charsetValues[i].substring(index + ";q=".length()));
}
if (quality >= maxQuality && maxQuality <= 1.0d) {
charset = charsetName;
maxQuality = quality;
}
}
return getOutputCharset(getTrimValue(charset), isUTF8Enabled, isUTF16Enabled);
}
private static String getCharsetOfAcceptLanguage(String languagevalue) {
if (languagevalue == null) {
return null;
}
String charset = null;
boolean isUTF8Enabled = false;
boolean isUTF16Enabled = false;
String[] languageValues = languagevalue.split(",");
String charsetName = null;
double maxQuality = 0.0d;
for (int i = 0; i < languageValues.length; i++) {
int index = languageValues[i].indexOf(";q=");
String languageName = languageValues[i];
double quality = 1.0d;
if (index >= 0) {
languageName = languageValues[i].substring(0, index - 1);
quality = Double.valueOf(languageValues[i].substring(index + ";q=".length()));
}
charsetName = languageMappingProperties.getProperty(languageName);
if (!isUTF8Enabled) {
isUTF8Enabled = isUTF8Enabled(charsetName);
}
if (!isUTF16Enabled) {
isUTF16Enabled = isUTF16Enabled(charsetName);
}
// 여기서는 위에서와 같이 isSupporting을 확인하지 않는다. properties파일에 설정되어 있는 값은
// 유효하다는 전제 하에.
if (charsetName != null) {
if (quality >= maxQuality && maxQuality <= 1.0d) {
charset = charsetName;
maxQuality = quality;
}
break;
}
}
if (languageValues != null && charset == null) {
// Accept-Language 체크를 한다는 것은 Accept-Charset이 없고 Accept-Charset만 있는
// 경우이다.
// 그럼에도 불구하고 charset이 null이라면 X-UP에서 해당 언어가 뭔지를 모르는 것이다.
// 이경우에는 기본값을 사용하자.
charset = "UTF-8";
}
return getOutputCharset(getTrimValue(charset), isUTF8Enabled, isUTF16Enabled);
}
private static String getTrimValue(String charset) {
if (charset != null) {
return charset.trim();
} else {
return charset;
}
}
private static boolean isUTF8Enabled(String charset) {
if (charset != null && charset.trim().equalsIgnoreCase("utf-8")) {
return true;
} else {
return false;
}
}
private static boolean isUTF16Enabled(String charset) {
if (charset != null && charset.trim().equalsIgnoreCase("utf-16")) {
return true;
} else {
return false;
}
}
private static String getOutputCharset(String charset, boolean isUTF8Enabled, boolean isUTF16Enabled) {
if (isUTF8Enabled) {
return "utf-8";
} else if (isUTF16Enabled) {
return "utf-16";
} else {
return charset;
}
}
}

View File

@@ -0,0 +1,54 @@
package com.nexacro.spring.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
public class FileUtils {
public static void copyFile(File sourceFile, File destFile) throws IOException {
long writedSize = 0;
long sourceSize = sourceFile.length();
if (!destFile.exists()) {
destFile.createNewFile();
}
FileChannel source = null;
FileChannel destination = null;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
while (writedSize < sourceSize) {
writedSize += destination.transferFrom(source, writedSize, sourceSize - writedSize);
}
} finally {
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
}
}
public static boolean isFileUsed(File file) {
if(file == null) { return false; }
if(file.isHidden()) {
return false;
}
else if(!file.exists()) {
return false;
}
else if(!file.canRead()) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,113 @@
package com.nexacro.spring.util;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
/**
*
* <pre>
* HTTP Util class
* </pre>
*
* @ClassName : HttpUtil.java
* @Description : HTTP Util class
* @author Park SeongMin
* @since 2015. 7. 27.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 27. Park SeongMin 최초 생성
* </pre>
*/
public abstract class HttpUtil {
public static final String HEADER_USER_AGENT = "User-Agent";
public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
public static final String HEADER_CONTENT_TYPE = "Content-Type";
public static final String HEADER_ACCEPT_CHARSET = "Accept-Charset";
public static final String HEADER_ACCEPT_LANGUAGE = "Accept-Language";
public static String getHeaderValue(HttpServletRequest request, String targetHeaderName) {
if (targetHeaderName == null) {
return null;
}
@SuppressWarnings("unchecked")
Enumeration enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String headerName = (String) enumeration.nextElement();
if (targetHeaderName.equalsIgnoreCase(headerName)) {
return request.getHeader(headerName);
}
}
return null;
}
public static String getRemoteAddr(HttpServletRequest request) {
/*
* http://lesstif.com/pages/viewpage.action?pageId=20775886
*
* WAS 는 보통 2차 방화벽 안에 있고 Web Server 를 통해 client 에서 호출되거나 cluster로 구성되어
* load balancer 에서 호출되는데 이럴 경우에서 getRemoteAddr() 을 호출하면 웹서버나 load
* balancer의 IP 가 나옴
* WebLogic 의 web server 연계 모듈인 weblogic connector 는
* 위 헤더를 사용하지 않고 Proxy-Client-IP 나 WL-Proxy-Client-IP 를 사용하므로
* weblogic 에서 도는 application 작성시 수정이 필요함
*/
String clientIp = request.getHeader("X-Forwarded-For");
if (!isEmpty(clientIp)) {
return getFirstIp(clientIp);
}
clientIp = request.getHeader("Proxy-Client-IP");
if (!isEmpty(clientIp)) {
return getFirstIp(clientIp);
}
clientIp = request.getHeader("WL-Proxy-Client-IP");
if (!isEmpty(clientIp)) {
return getFirstIp(clientIp);
}
clientIp = request.getHeader("HTTP_CLIENT_IP");
if (!isEmpty(clientIp)) {
return getFirstIp(clientIp);
}
clientIp = request.getHeader("HTTP_X_FORWARDED_FOR");
if (!isEmpty(clientIp)) {
return getFirstIp(clientIp);
}
return request.getRemoteAddr();
}
private static boolean isEmpty(String str) {
if (str == null || str.length() == 0 || "unknown".equalsIgnoreCase(str)) {
return true;
}
return false;
}
private static String getFirstIp(String ip) {
if (ip == null) {
return null;
}
String[] split = ip.split(",");
return split[0];
}
}

View File

@@ -0,0 +1,87 @@
package com.nexacro.spring.util;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.datatype.PlatformDataType;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroUtil.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 7. 28.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 7. 28. Park SeongMin 최초 생성
* </pre>
*/
public abstract class NexacroUtil {
public static final String ATTR_PLATFORM_REQUEST = "PlatformRequest";
public static DataSet createFirstRowStatusDataSet(int errorCode, String errorMsg) {
DataSet ds = new DataSet(NexacroConstants.ERROR_FIRST_ROW.ERROR_DATASET);
ds.addColumn(NexacroConstants.ERROR_FIRST_ROW.ERROR_CODE, PlatformDataType.INT);
ds.addColumn(NexacroConstants.ERROR_FIRST_ROW.ERROR_MSG, PlatformDataType.STRING);
int newRow = ds.newRow();
ds.set(newRow, NexacroConstants.ERROR_FIRST_ROW.ERROR_CODE, errorCode);
ds.set(newRow, NexacroConstants.ERROR_FIRST_ROW.ERROR_MSG, errorMsg);
return ds;
}
public static boolean isNexacroRequest(HttpServletRequest request) {
// runtime 버전의 경우에만 userAgent 값이 설정 된다.
Object nexacroRequest = RequestContextHolder.getRequestAttributes().getAttribute(NexacroConstants.ATTRIBUTE.NEXACRO_REQUEST, RequestAttributes.SCOPE_REQUEST);
if(NexacroConstants.ATTRIBUTE.NEXACRO_REQUEST.equals(nexacroRequest)) {
return true;
}
String userAgent = request.getHeader(HttpUtil.HEADER_USER_AGENT);
if(userAgent != null) {
userAgent = userAgent.trim().toLowerCase();
if(userAgent.startsWith(HEADER_NEXACRO.USER_AGENT_KEY.toLowerCase())) {
return true;
} else if (userAgent.startsWith(HEADER_XPLATFORM.USER_AGENT_KEY.toLowerCase())) {
return true;
} else if (userAgent.startsWith(HEADER_MIPLATFORM.USER_AGENT_KEY.toLowerCase())) {
return true;
}
}
return false;
}
public static class HEADER_NEXACRO {
public final static String USER_AGENT_KEY = "nexacro";
public final static String USER_AGENT_SAMPLE = "nexacroplatform14-Win32/2014 (compatible; Mozilla/4.0; MSIE 7.0)";
}
public static class HEADER_XPLATFORM {
public final static String USER_AGENT_KEY = "XPLATFORM";
public final static String USER_AGENT_SAMPLE = "XPLATFORM-Win32/2009 (compatible; Mozilla/4.0; MSIE 7.0)";
}
public static class HEADER_MIPLATFORM {
public final static String USER_AGENT_KEY = "MiPlatform";
public final static String USER_AGENT_SAMPLE = "MiPlatform 3.1;win32;1280x800";
}
}

View File

@@ -0,0 +1,12 @@
package com.nexacro.spring.util;
public class ReflectionFailException extends RuntimeException {
public ReflectionFailException(String message) {
super(message);
}
public ReflectionFailException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,403 @@
package com.nexacro.spring.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ReflectionUtil {
public static Field[] getFields(String className) throws ReflectionFailException {
Field[] fields = null;
try {
Class<?> cls = Class.forName(className);
fields = cls.getFields();
} catch (ClassNotFoundException e) {
throw new ReflectionFailException("class not found.", e);
}
return fields;
}
public static String[] getPublicFieldNames(String className) throws ReflectionFailException {
Field[] fields = getFields(className);
List<String> fieldNameList = new ArrayList<String>();
for (int fieldsIndex = 0; fieldsIndex < fields.length; fieldsIndex++) {
if (Modifier.isPublic(fields[fieldsIndex].getModifiers())) {
fieldNameList.add(fields[fieldsIndex].getName());
}
}
String[] fieldsNames = new String[fieldNameList.size()];
fieldsNames = fieldNameList.toArray(fieldsNames);
return fieldsNames;
}
public static Method[] getMethods(Class<?> clazz) throws ReflectionFailException {
Method[] methods = null;
methods = clazz.getDeclaredMethods();
return methods;
}
public static Method[] getMethods(Class<?> clazz, String methodName) throws ReflectionFailException {
Method[] methods = getMethods(clazz);
int foundCount = 0;
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(methodName)) {
foundCount++;
}
}
Method[] foundMethods = new Method[foundCount];
int foundMethodIndex = 0;
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(methodName)) {
foundMethods[foundMethodIndex] = methods[i];
foundMethodIndex++;
}
}
return foundMethods;
}
/**
* Attempt to find a {@link Method} on the supplied class with the supplied
* name
* and parameter types. Searches all superclasses up to {@code Object}.
* <p>
* Returns {@code null} if no {@link Method} can be found.
*
* @param clazz
* the class to introspect
* @param name
* the name of the method
* @param paramTypes
* the parameter types of the method
* (may be {@code null} to indicate any signature)
* @return the Method object, or {@code null} if none found
* @throws ReflectionFailException
*/
public static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
if (clazz == null) {
throw new IllegalArgumentException("Class should not be null");
}
if (name == null) {
throw new IllegalArgumentException("Method name should not be null");
}
Class<?> searchType = clazz;
while (searchType != null) {
Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());
for (Method method : methods) {
if (name.equals(method.getName())
&& (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) {
return method;
}
}
searchType = searchType.getSuperclass();
}
return null;
}
public static Method[] getMethods(String className) throws ReflectionFailException {
Class<?> cls = null;
Method[] methods = null;
try {
cls = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new ReflectionFailException("class not found.", e);
}
return getMethods(cls);
}
public static Method[] getMethods(Object object) throws ReflectionFailException {
if (object == null) {
return null;
}
return getMethods(object.getClass());
}
public static String[] getPublicMethodNames(String className) throws ReflectionFailException {
Method[] methods = getMethods(className);
List<String> methodNameList = new ArrayList<String>();
for (int i = 0; i < methods.length; i++) {
if (Modifier.isPublic(methods[i].getModifiers())) {
methodNameList.add(methods[i].getName());
}
}
String[] methodNames = new String[methodNameList.size()];
methodNames = methodNameList.toArray(methodNames);
return methodNames;
}
public static Object executeMethod(Method method, Object instanceObject, Object[] parameterValueObject)
throws ReflectionFailException {
Object retobj = null;
try {
retobj = method.invoke(instanceObject, parameterValueObject);
} catch (IllegalArgumentException e) {
throw new ReflectionFailException("execution method failed.", e);
} catch (IllegalAccessException e) {
throw new ReflectionFailException("execution method failed.", e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
StackTraceElement[] stackTraceElements = cause.getStackTrace();
StringBuffer stackTraceBuffer = new StringBuffer();
for (int i = 0; i < stackTraceElements.length; i++) {
stackTraceBuffer.append(" at ");
stackTraceBuffer.append(stackTraceElements[i].getClassName()).append(".");
stackTraceBuffer.append(stackTraceElements[i].getMethodName());
stackTraceBuffer.append("(").append(stackTraceElements[i].getFileName());
stackTraceBuffer.append(":").append(stackTraceElements[i].getLineNumber()).append(")");
stackTraceBuffer.append("\n");
}
throw new ReflectionFailException(stackTraceBuffer.toString(), e);
}
return retobj;
}
public static boolean isImplemented(Class targetClass, Class interfaceClass) {
Class[] interfaceClasses = targetClass.getInterfaces();
for (int i = 0; i < interfaceClasses.length; i++) {
if (interfaceClasses[i] == interfaceClass) {
return true;
}
}
Class superClass = targetClass.getSuperclass();
if (superClass != null) {
return isImplemented(superClass, interfaceClass);
}
return false;
}
public static boolean isStaticField(Field field) {
if(field == null) {
return false;
}
return isStatic(field.getModifiers());
}
public static boolean isStaticMethod(Method method) {
if(method == null) {
return false;
}
return isStatic(method.getModifiers());
}
public static boolean isStatic(int modifiers) {
return Modifier.isStatic(modifiers);
}
public static Object getFieldInstance(Object object, String fieldName) throws ReflectionFailException {
if (object == null) {
return null;
}
if (fieldName == null) {
return null;
}
String[] fieldNames = fieldName.split("\\.");
return getFieldInstance(object, fieldNames);
}
public static Field getField(Object object, String fieldName) throws ReflectionFailException {
if (object == null) {
return null;
}
if (fieldName == null) {
return null;
}
Field field = null;
Class clazz = null;
clazz = object.getClass();
return getField(clazz, fieldName);
}
public static Field getField(Class clazz, String fieldName) throws ReflectionFailException {
if (clazz == null) {
return null;
}
if (fieldName == null) {
return null;
}
Field field = null;
Exception rootException = null;
try {
field = clazz.getDeclaredField(fieldName);
return field;
} catch (SecurityException e) {
rootException = e;
} catch (NoSuchFieldException e) {
rootException = e;
}
Class superClass = clazz.getSuperclass();
while (superClass != null) {
try {
field = superClass.getDeclaredField(fieldName);
return field;
} catch (SecurityException e) {
} catch (NoSuchFieldException e) {
}
superClass = superClass.getSuperclass();
}
throw new ReflectionFailException("getting field " + fieldName + " failed.", rootException);
}
public static Object getFieldInstance(Object object, String[] fieldNames) throws ReflectionFailException {
if (object == null) {
return null;
}
if (fieldNames == null) {
return null;
}
if (fieldNames.length == 0) {
return null;
}
try {
Field field = getField(object, fieldNames[0]);
field.setAccessible(true);
if (fieldNames.length == 1) {
Object value = field.get(object);
return value;
} else {
Object subObject = field.get(object);
if (subObject == null) {
return null;
}
String[] subFieldNames = new String[fieldNames.length - 1];
String subFieldName = "";
for (int i = 1; i < fieldNames.length; i++) {
subFieldNames[i - 1] = fieldNames[i];
}
return getFieldInstance(subObject, subFieldNames);
}
} catch (SecurityException e) {
throw new ReflectionFailException("getting field value failed.", e);
} catch (IllegalArgumentException e) {
throw new ReflectionFailException("getting field value failed.", e);
} catch (IllegalAccessException e) {
throw new ReflectionFailException("getting field value failed.", e);
}
}
public static Method[] getAllDeclaredMethods(Class<?> leafClass) {
final List<Method> methods = new ArrayList<Method>(32);
doWithMethods(leafClass, methods);
return methods.toArray(new Method[methods.size()]);
}
private static void doWithMethods(Class clazz, List<Method> methodList) {
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
methodList.add(methods[i]);
}
if (clazz.getSuperclass() != null) {
doWithMethods(clazz.getSuperclass(), methodList);
} else if (clazz.isInterface()) {
for (Class<?> superIfc : clazz.getInterfaces()) {
doWithMethods(superIfc, methodList);
}
}
}
public static void makeAccessible(Field field) {
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
.isFinal(field.getModifiers())) && !field.isAccessible()) {
field.setAccessible(true);
}
}
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
public static void makeAccessible(Constructor<?> ctor) {
if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers()))
&& !ctor.isAccessible()) {
ctor.setAccessible(true);
}
}
public static <T> T instantiateClass(Class<T> clazz) throws ReflectionFailException {
if(clazz == null) {
throw new ReflectionFailException("Class must not be null");
}
if (clazz.isInterface()) {
throw new ReflectionFailException(clazz+ " specified class is an interface");
}
try {
return instantiateClass(clazz.getDeclaredConstructor());
} catch (NoSuchMethodException ex) {
throw new ReflectionFailException(clazz+ " no default constructor found", ex);
}
}
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws ReflectionFailException {
if(ctor == null) {
throw new ReflectionFailException("Constructor must not be null");
}
try {
makeAccessible(ctor);
return ctor.newInstance(args);
} catch (InstantiationException ex) {
throw new ReflectionFailException(ctor.getDeclaringClass()+ " is it an abstract class?", ex);
} catch (IllegalAccessException ex) {
throw new ReflectionFailException(ctor.getDeclaringClass() + " is the constructor accessible?", ex);
} catch (IllegalArgumentException ex) {
throw new ReflectionFailException(ctor.getDeclaringClass() + " illegal arguments for constructor", ex);
} catch (InvocationTargetException ex) {
throw new ReflectionFailException(ctor.getDeclaringClass() + " constructor threw exception", ex.getTargetException());
}
}
}

View File

@@ -0,0 +1,19 @@
#ko-kr=euc-kr
ko-kr=utf-8
#ko=euc-kr
ko=utf-8
ko.coderange=/uac00-/ud7af
#en=ios8859-1
en=utf-8
#en-us=ios8859-1
en-us=utf-8
en.coderange=
#jp=Shift-JIS
jp=utf-8
jp.coderange=/u3040-/u30ff/u3400-/u4db5/u4e00-/u9fcb/uf900-/ufa6a
ja=utf-8
ja.coderange=/u3040-/u30ff/u3400-/u4db5/u4e00-/u9fcb/uf900-/ufa6a
zh=utf-8
zh.coderange=/u4e00-/u9fff/u20000-/u2a6df/uf900-/ufaff/u2f800-/u2fa1f

View File

@@ -0,0 +1,94 @@
package com.nexacro.spring.view;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.FileCopyUtils;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.spring.NexacroException;
import com.nexacro.spring.data.NexacroFileResult;
import com.nexacro.spring.util.CharsetUtil;
import com.nexacro.spring.util.FileUtils;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
import com.nexacro.xapi.tx.PlatformException;
public class NexacroFileView extends NexacroView {
public NexacroFileView() {
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
Object object = model.get(NexacroConstants.ATTRIBUTE.NEXACRO_FILE_DATA);
if(object == null || !(object instanceof NexacroFileResult)) {
sendResponse(request, response);
return;
}
NexacroFileResult fileResult = (NexacroFileResult) object;
String charset = fileResult.getCharset();
String contentType = fileResult.getContentType();
String originalName = fileResult.getOriginalName();
File file = fileResult.getFile();
if(file == null) {
sendFailResponse(request, response, "send response failed. file is null.");
return;
}
if(!FileUtils.isFileUsed(file)) {
sendFailResponse(request, response, "send response failed. '" + file.getName() + "' can not be used.");
return;
}
if(contentType == null) {
contentType = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(file);
}
charset = charset != null? charset: CharsetUtil.getCharsetOfRequest(request, "utf-8");
contentType = contentType != null? contentType: "application/octet-stream";
originalName = originalName != null? originalName: file.getName();
String enName = URLEncoder.encode(originalName, "utf-8");
response.setContentType(contentType + "; charset=" + charset);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition", "attachment; filename=" + enName + "; size=" + file.length());
response.setHeader("Content-Description", "...");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "-1");
OutputStream out = response.getOutputStream();
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
FileCopyUtils.copy(fis, out);
} catch (Exception e) {
sendFailResponse(request, response, e.getMessage());
} finally {
if (fis != null) { try { fis.close(); } catch (Exception e) {}}
}
}
private void sendFailResponse(HttpServletRequest request, HttpServletResponse response, String errorMsg) throws PlatformException {
PlatformData platformData = new PlatformData();
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_CODE, NexacroException.DEFAULT_ERROR_CODE));
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_MSG, errorMsg));
sendResponse(request, response, platformData);
}
}

View File

@@ -0,0 +1,61 @@
package com.nexacro.spring.view;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
public class NexacroModelAndView extends ModelAndView {
private PlatformData platformData = new PlatformData();
public NexacroModelAndView(){
setNexacroObject();
}
public NexacroModelAndView(String viewName){
super(viewName);
setNexacroObject();
}
public NexacroModelAndView(View view){
super(view);
setNexacroObject();
}
public PlatformData getPlatformData() {
return platformData;
}
public void setPlatformData(PlatformData platformData) {
this.platformData = platformData;
setNexacroObject();
}
public void addVariable(Variable var) {
this.platformData.addVariable(var);
}
public void addDataSet(DataSet ds) {
this.platformData.addDataSet(ds);
}
public void setErrorCode(int code){
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_CODE, code));
setNexacroObject();
}
public void setErrorMsg(String msg){
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_MSG, msg));
setNexacroObject();
}
private void setNexacroObject() {
super.addObject(NexacroConstants.ATTRIBUTE.NEXACRO_PLATFORM_DATA, platformData);
}
}

View File

@@ -0,0 +1,235 @@
package com.nexacro.spring.view;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;
import org.springframework.web.servlet.view.AbstractView;
import com.nexacro.spring.NexacroConstants;
import com.nexacro.spring.data.NexacroFirstRowAccessor;
import com.nexacro.spring.data.NexacroFirstRowHandler;
import com.nexacro.spring.servlet.NexacroContext;
import com.nexacro.spring.servlet.NexacroContextHolder;
import com.nexacro.spring.util.NexacroUtil;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.DataSetList;
import com.nexacro.xapi.data.Debugger;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
import com.nexacro.xapi.data.VariableList;
import com.nexacro.xapi.tx.HttpPlatformResponse;
import com.nexacro.xapi.tx.PlatformException;
import com.nexacro.xapi.tx.PlatformType;
public class NexacroView extends AbstractView {
private Logger logger = LoggerFactory.getLogger(NexacroView.class);
private Logger performanceLogger = LoggerFactory.getLogger(NexacroConstants.PERFORMANCE_LOGGER);
private String defaultContentType;
private String defaultCharset;
public NexacroView(){
}
public String getDefaultContentType() {
if(defaultContentType == null) {
return PlatformType.CONTENT_TYPE_XML;
} else {
return defaultContentType;
}
}
public void setDefaultContentType(String defaultContentType) {
this.defaultContentType = defaultContentType;
}
public String getDefaultCharset() {
if(defaultContentType == null) {
return PlatformType.DEFAULT_CHAR_SET;
} else {
return defaultCharset;
}
}
public void setDefaultCharset(String defaultCharset) {
this.defaultCharset = defaultCharset;
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response) throws Exception {
Object object = model.get(NexacroConstants.ATTRIBUTE.NEXACRO_PLATFORM_DATA);
if(object == null || !(object instanceof PlatformData)) {
sendResponse(request, response);
return;
}
sendResponse(request, response, (PlatformData) object);
}
protected void sendResponse(HttpServletRequest request, HttpServletResponse response) throws PlatformException{
sendResponse(request, response, generatePlatformData());
}
protected void sendResponse(HttpServletRequest request, HttpServletResponse response, PlatformData platformData) throws PlatformException{
NexacroContext cachedData = getCachedData(request, response);
HttpPlatformResponse platformResponse = null;
StopWatch sw = new StopWatch(getClass().getSimpleName());
sw.start("rendering platformdata");
try {
if(cachedData != null) {
if(cachedData.isFirstRowFired()) {
NexacroFirstRowHandler firstRowHandler = cachedData.getFirstRowHandler();
sendFirstRowData(platformData, firstRowHandler, true);
return;
} else {
platformResponse = cachedData.getPlatformResponse();
platformResponse.setData(platformData);
platformResponse.sendData();
}
} else {
// TODO default 혹은 request parsing..
platformResponse = new HttpPlatformResponse(response);
platformResponse.setContentType(getDefaultContentType());
platformResponse.setCharset(getDefaultCharset());
platformResponse.setData(platformData);
platformResponse.sendData();
}
} finally {
sw.stop();
if(performanceLogger.isTraceEnabled()) {
performanceLogger.trace(sw.prettyPrint());
}
}
if(logger.isDebugEnabled()) {
logger.debug("response platformdata=[{}]", new Debugger().detail(platformData));
}
}
private void sendFirstRowData(PlatformData platformData, NexacroFirstRowHandler firstRowHandler, boolean isCallEndMethod)
throws PlatformException {
removeTransferData(firstRowHandler, platformData);
// add first row status DataSet
platformData.addDataSet(NexacroUtil.createFirstRowStatusDataSet(NexacroConstants.ERROR.DEFAULT_ERROR_CODE, null));
if(logger.isDebugEnabled()) {
logger.debug("response platformdata=[{}]", new Debugger().detail(platformData));
}
firstRowHandler.sendPlatformData(platformData);
if(isCallEndMethod) {
NexacroFirstRowAccessor.end(firstRowHandler);
}
}
/**
* Statements
*
* @param firstRowHandler
* @param variableList
*/
private void removeTransferData(NexacroFirstRowHandler firstRowHandler, PlatformData platformData) {
VariableList variableList = platformData.getVariableList();
if(NexacroFirstRowAccessor.getSendOutDataSetCount(firstRowHandler) > 0) {
// dataset already sended..
int size = variableList.size();
for(int i=0; i<size; i++) {
if (logger.isInfoEnabled()) {
logger.info("DataSet aleady sended. ignore variable="+variableList.get(i).getName());
}
}
platformData.setVariableList(new VariableList());
} else {
removeTransferVariables(firstRowHandler, variableList);
}
DataSetList dataSetList = platformData.getDataSetList();
removeTransferDataSets(firstRowHandler, dataSetList);
}
private void removeTransferVariables(NexacroFirstRowHandler firstRowHandler, VariableList variableList) {
String[] sendOutVariableNames = NexacroFirstRowAccessor.getSendOutVariableNames(firstRowHandler);
Variable var = null;
int variableListSize = variableList.size();
for(int variableListIndex = variableListSize-1 ; variableListIndex>=0 ; variableListIndex--) {
var = variableList.get(variableListIndex);
if(var == null) {
continue;
}
boolean isSended = false;
for(int sendedVariableIndex = 0; sendedVariableIndex<sendOutVariableNames.length; sendedVariableIndex++) {
if(var.getName().equals(sendOutVariableNames[sendedVariableIndex])) {
isSended = true;
break;
}
}
if(isSended) {
variableList.remove(variableListIndex);
}
}
}
private void removeTransferDataSets(NexacroFirstRowHandler firstRowHandler, DataSetList dataSetList) {
String[] sendOutDataSetNames = NexacroFirstRowAccessor.getSendOutDataSetNames(firstRowHandler);
DataSet dataSet = null;
int dataSetListSize = dataSetList.size();
for(int datasetListIndex = dataSetListSize - 1 ; datasetListIndex >= 0; datasetListIndex--) {
dataSet = dataSetList.get(datasetListIndex);
if(dataSet == null) {
continue;
}
boolean isSended = false;
for(int sendedDataSetIndex = 0; sendedDataSetIndex<sendOutDataSetNames.length; sendedDataSetIndex++) {
if(dataSet.getName().equals(sendOutDataSetNames[sendedDataSetIndex])) {
isSended = true;
break;
}
}
if(isSended) {
dataSetList.remove(datasetListIndex);
}
}
}
private PlatformData generatePlatformData() {
PlatformData platformData = new PlatformData();
platformData.addVariable(Variable.createVariable(NexacroConstants.ERROR.ERROR_CODE, NexacroConstants.ERROR.DEFAULT_ERROR_CODE));
return platformData;
}
private NexacroContext getCachedData(HttpServletRequest request, HttpServletResponse response) {
// get already parsed request
NexacroContext nexacroContext = NexacroContextHolder.getNexacroContext();
if(nexacroContext != null) {
return nexacroContext;
}
return nexacroContext;
}
}

39
src/site/site.xml Normal file
View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="nexacro able sample">
<bannerLeft>
<name>Maven</name>
<src>http://maven.apache.org/images/apache-maven-project.png
</src>
<href>http://maven.apache.org/</href>
</bannerLeft>
<bannerRight>
<src>http://maven.apache.org/images/maven-small.gif</src>
</bannerRight>
<skin>
<groupId>org.apache.maven.skins</groupId>
<artifactId>maven-fluido-skin</artifactId>
<version>1.4</version>
</skin>
<body>
<links>
<item name="Apache" href="http://www.apache.org/" />
<item name="Maven 1.x" href="http://maven.apache.org/maven-1.x/" />
<item name="Maven 2" href="http://maven.apache.org/" />
</links>
<!--
<menu name="Maven 2.0">
<item name="Introduction" href="index.html" />
<item name="Download" href="download.html" />
<item name="Release Notes" href="release-notes.html" />
<item name="General Information" href="about.html" />
<item name="For Maven 1.x Users" href="maven1.html" />
<item name="Road Map" href="roadmap.html" />
</menu>
-->
<menu ref="reports" />
</body>
</project>

View File

@@ -0,0 +1,154 @@
package com.nexacro.spring.data;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
public class FirstRowHttpResponse implements HttpServletResponse {
ServletOutputStream outputStream = null;
String charsetEncoding = null;
String contentType = null;
public void setContentType(String arg0) {
this.contentType = arg0;
}
public String getContentType() {
return this.contentType;
}
public String getCharacterEncoding() {
return this.charsetEncoding;
}
public void setCharacterEncoding(String charsetEncoding) {
this.charsetEncoding = charsetEncoding;
}
public ServletOutputStream getOutputStream() throws IOException {
return this.outputStream;
}
public void setOutputStream(ServletOutputStream outputStream) {
this.outputStream = outputStream;
}
public void addCookie(Cookie arg0) {
}
public void addDateHeader(String arg0, long arg1) {
}
public void addHeader(String arg0, String arg1) {
}
public void addIntHeader(String arg0, int arg1) {
}
public boolean containsHeader(String arg0) {
return false;
}
public String encodeRedirectURL(String arg0) {
return null;
}
public String encodeRedirectUrl(String arg0) {
return null;
}
public String encodeURL(String arg0) {
return null;
}
public String encodeUrl(String arg0) {
return null;
}
public void sendError(int arg0) throws IOException {
}
public void sendError(int arg0, String arg1) throws IOException {
}
public void sendRedirect(String arg0) throws IOException {
}
public void setDateHeader(String arg0, long arg1) {
}
public void setHeader(String arg0, String arg1) {
}
public void setIntHeader(String arg0, int arg1) {
}
public void setStatus(int arg0) {
}
public void setStatus(int arg0, String arg1) {
}
public void flushBuffer() throws IOException {
}
public int getBufferSize() {
return 0;
}
public Locale getLocale() {
return null;
}
public PrintWriter getWriter() throws IOException {
return new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"));
}
public boolean isCommitted() {
return false;
}
public void reset() {
}
public void resetBuffer() {
}
public void setBufferSize(int arg0) {
}
public void setContentLength(int arg0) {
}
public void setLocale(Locale arg0) {
}
// @Override
// public String getHeader(String name) {
// return null;
// }
//
// @Override
// public Collection<String> getHeaderNames() {
// return null;
// }
//
// @Override
// public Collection<String> getHeaders(String headerName) {
// return null;
// }
//
// @Override
// public int getStatus() {
// return 0;
// }
}

View File

@@ -0,0 +1,109 @@
package com.nexacro.spring.data;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletOutputStream;
public class FirstRowTrackableServletOutputStream extends ServletOutputStream {
ByteArrayOutputStream output = new ByteArrayOutputStream();
List<byte[]> flushedByteArrayList = new ArrayList<byte[]>();
Object syncronizeObject = new Object();
byte[] resultData = null;
boolean isClose = false;
@Override
public void write(int b) throws IOException {
write(new byte[] { (byte) b });
}
public void close() throws IOException {
// ByteArrayOutputStream 은 close 시 아무런 영향이 없다.
// 메모리 대상이기 때문에 Garbage Collector 에 의해 소멸된다.
output.close();
isClose = true;
}
public boolean equals(Object obj) {
return output.equals(obj);
}
public void flush() throws IOException {
synchronized (syncronizeObject) {
resultData = output.toByteArray();
output.reset();
flushedByteArrayList.add(resultData);
if (isClose) {
throw new IOException("connection reset by peer");
}
}
}
public List<byte[]> getFlushedByteList() {
return flushedByteArrayList;
}
public int hashCode() {
return output.hashCode();
}
public void reset() {
output.reset();
}
public int size() {
return output.size();
}
public byte[] toByteArray() {
return output.toByteArray();
}
public String toString() {
return output.toString();
}
@SuppressWarnings("deprecation")
public String toString(int hibyte) {
return output.toString(hibyte);
}
public String toString(String enc) throws UnsupportedEncodingException {
return output.toString(enc);
}
public void write(byte[] b, int off, int len) {
output.write(b, off, len);
}
public void write(byte[] b) throws IOException {
output.write(b);
}
public void writeTo(OutputStream out) throws IOException {
output.writeTo(out);
}
public OutputStream getOutputStream() {
return this.output;
}
public byte[] getResultData() {
return resultData;
}
public void setResultData(byte[] resultData) {
this.resultData = resultData;
}
}

View File

@@ -0,0 +1,176 @@
package com.nexacro.spring.data;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import javax.servlet.ServletOutputStream;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.PlatformData;
import com.nexacro.xapi.data.Variable;
import com.nexacro.xapi.tx.DataDeserializer;
import com.nexacro.xapi.tx.DataSerializerFactory;
import com.nexacro.xapi.tx.PlatformException;
import com.nexacro.xapi.tx.PlatformType;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroFirstRowHandlerTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 18.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 18. Park SeongMin 최초 생성
* </pre>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/context-*.xml" } )
public class NexacroFirstRowHandlerTest {
// @Autowired
// private LargeDataService largeService;
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testSendVariableAfterSendDataSet() {
FirstRowTrackableServletOutputStream outputStream = new FirstRowTrackableServletOutputStream();
NexacroFirstRowHandler firstRowHandler = createFirstRowHandler(outputStream);
DataSet ds = new DataSet("ds1");
try {
firstRowHandler.sendDataSet(ds);
} catch (PlatformException e) {
Assert.fail("send dataset failed. e=" + e);
}
Variable var = Variable.createVariable("var1", "test");
try {
firstRowHandler.sendVariable(var);
Assert.fail("DataSet aleady sended. can't send a variable after sending dataSet.");
} catch (PlatformException e) {
}
}
// @Test
public void testFirstRowIbatis() {
boolean useJdbcTemplate = false;
doCallService(useJdbcTemplate);
}
// @Test
public void testFirstRowJdbcTemplate() {
boolean useJdbcTemplate = true;
doCallService(useJdbcTemplate);
}
private void doCallService(boolean useJdbcTemplate) {
FirstRowTrackableServletOutputStream outputStream = new FirstRowTrackableServletOutputStream();
NexacroFirstRowHandler firstRowHandler = createFirstRowHandler(outputStream);
String sendDataSetName = "firstRowData";
int initDataCount = 1000;
int firstRowCount = 100;
// call service
// if(useJdbcTemplate) {
// largeService.selectJdbcLargeData(firstRowHandler, sendDataSetName, firstRowCount, initDataCount);
// } else {
// largeService.selectLargeData(firstRowHandler, sendDataSetName, firstRowCount, initDataCount);
// }
// end tag
try {
NexacroFirstRowAccessor.end(firstRowHandler);
} catch (PlatformException e) {
Assert.fail("fail. call end method. e=" + e);
}
PlatformData platformData = readPlatformData(outputStream);
Assert.assertNotNull("first row function is not work. check it.", platformData);
DataSet sendedDataSet = platformData.getDataSet(sendDataSetName);
Assert.assertNotNull("first row function is not work. check it.", sendedDataSet);
int actualRowCount = sendedDataSet.getRowCount();
int expectedRowCount = initDataCount;
Assert.assertEquals("sended row count not same.", expectedRowCount, actualRowCount);
}
private NexacroFirstRowHandler createFirstRowHandler(ServletOutputStream outputStream) {
// response를 생성한다.
FirstRowHttpResponse httpServletResponse = new FirstRowHttpResponse();
// output stream을 입력합니다.
httpServletResponse.setOutputStream(outputStream);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/xml;charset=UTF-8");
NexacroFirstRowHandler firstRowHandler = new NexacroFirstRowHandler(httpServletResponse);
return firstRowHandler;
}
private PlatformData readPlatformData(FirstRowTrackableServletOutputStream outputStream) {
// check outputstream..
List<byte[]> flushedOutputList = outputStream.getFlushedByteList();
String platformXml = "";
int flushedSize = flushedOutputList.size();
for (int listIndex = 0; listIndex < flushedSize; listIndex++) {
byte[] outputBytes = (byte[]) flushedOutputList.get(listIndex);
String xmlflagment = new String(outputBytes);
platformXml = platformXml + xmlflagment;
// the data of last flush by xapi, aways come a blank data. so check
// without last data for blank data.
if (listIndex != (flushedSize - 1) && xmlflagment.trim().equals("")) {
Assert.fail("xml flagment must not be blank");
}
}
DataDeserializer deserializer = DataSerializerFactory.getDeserializer(PlatformType.CONTENT_TYPE_XML);
InputStream inputStream = new ByteArrayInputStream(platformXml.getBytes());
PlatformData platformData = null;
try {
platformData = deserializer.readData(inputStream, null, "utf8");
} catch (PlatformException e) {
Assert.fail("get platformData failed. e=" + e);
}
return platformData;
}
}

View File

@@ -0,0 +1,30 @@
package com.nexacro.spring.data.convert;
import org.junit.Test;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConvertListenerTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 9.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 9. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroConvertListenerTest {
@Test
public void testNothing() {
}
}

View File

@@ -0,0 +1,121 @@
package com.nexacro.spring.data.convert;
import java.util.Collection;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.Variable;
import junit.framework.Assert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroConverterFactoryTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 4.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 4. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroConverterFactoryTest {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testDefaultConverter() {
Class<?> source, target;
NexacroConverter converter = null;
source = Object.class;
target = Variable.class;
converter = NexacroConverterFactory.getConverter(source, target);
Assert.assertNotNull(source + " -> " + target + " converter not registed.", converter);
source = Variable.class;
target = Object.class;
converter = NexacroConverterFactory.getConverter(source, target);
Assert.assertNotNull(source + " -> " + target + " converter not registed.", converter);
source = List.class;
target = DataSet.class;
converter = NexacroConverterFactory.getConverter(source, target);
Assert.assertNotNull(source + " -> " + target + " converter not registed.", converter);
source = DataSet.class;
target = List.class;
converter = NexacroConverterFactory.getConverter(source, target);
Assert.assertNotNull(source + " -> " + target + " converter not registed.", converter);
}
@Test
public void testRegistConverter() {
Class<?> source, target;
source = Collection.class;
target = DataSet.class;
UndefinedConverter undefinedConverter = new UndefinedConverter(source, target);
NexacroConverterFactory.register(undefinedConverter);
NexacroConverter converter = NexacroConverterFactory.getConverter(source, target);
Assert.assertNotNull(source + " -> " + target + " converter not registed.", converter);
}
private static class UndefinedConverter implements NexacroConverter {
private Class<?> sourceType;
private Class<?> targetType;
UndefinedConverter(Class<?> sourceType, Class<?> targetType) {
this.sourceType = sourceType;
this.targetType = targetType;
}
@Override
public Object convert(Object source, ConvertDefinition definition) throws NexacroConvertException {
return null;
}
@Override
public boolean canConvert(Class source, Class target) {
if (sourceType.equals(source) && targetType.equals(target)) {
return true;
}
return false;
}
@Override
public void addListener(NexacroConvertListener listener) {
}
@Override
public void removeListener(NexacroConvertListener listener) {
}
}
}

View File

@@ -0,0 +1,702 @@
package com.nexacro.spring.data.support;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.StopWatch;
import com.nexacro.spring.data.DataSetRowTypeAccessor;
import com.nexacro.spring.data.DataSetSavedDataAccessor;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.support.NexacroTestUtil.DataSetRowTypeBean;
import com.nexacro.spring.data.support.NexacroTestUtil.DataSetSavedDataBean;
import com.nexacro.spring.data.support.NexacroTestUtil.StaticPropertyBean;
import com.nexacro.spring.data.support.bean.DefaultBean;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.datatype.PlatformDataType;
import junit.framework.Assert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : DataSetToListConverterTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 4.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 4. Park SeongMin 최초 생성
* </pre>
*/
public class DataSetToListConverterTest {
private DataSetToListConverter converter;
@Before
public void setUp() {
converter = new DataSetToListConverter();
}
@Test
public void testSupportedType() {
Class<?> source;
Class<?> target;
source = DataSet.class;
target = List.class;
boolean canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
}
@Test
public void testUnSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = DataSet.class;
target = ArrayList.class;
canConvert = converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
source = List.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
}
@Test
public void testConvertDataSetToListBean() {
DataSet defaultDataSet = NexacroTestUtil.createDefaultDataSet();
ConvertDefinition definition = new ConvertDefinition(defaultDataSet.getName());
definition.setGenericType(DefaultBean.class); // for bean
Object convertedList = null;
try {
convertedList = converter.convert(defaultDataSet, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
NexacroTestUtil.compareDefaultBeans((List<DefaultBean>) convertedList);
}
@Test
public void testConvertDataSetToListMap() {
DataSet defaultDataSet = NexacroTestUtil.createDefaultDataSet();
ConvertDefinition definition = new ConvertDefinition(defaultDataSet.getName());
definition.setGenericType(Map.class); // for map
Object convertedList = null;
try {
convertedList = converter.convert(defaultDataSet, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
NexacroTestUtil.compareDefaultMaps((List<Map<String, Object>>) convertedList);
}
@Test
public void testUndefinedGenericType() {
DataSet defaultDataSet = NexacroTestUtil.createDefaultDataSet();
ConvertDefinition definition = new ConvertDefinition(defaultDataSet.getName());
// definition.setGenericType(DefaultBean.class);
Object convertedList = null;
try {
convertedList = converter.convert(defaultDataSet, definition);
Assert.fail("generic type not declared. exception must be occured.");
} catch (NexacroConvertException e) {
// nothing..
}
}
@Test
public void testNullData() {
DataSet ds = null;
ConvertDefinition definition = new ConvertDefinition("ds");
definition.setGenericType(DefaultBean.class);
List list = null;
try {
list = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("converted list should not be null", list);
Assert.assertEquals(ArrayList.class, list.getClass());
}
@Test
public void testStaticColumns() {
double commissionPercent = 10.0d;
DataSet ds = new DataSet("static");
ds.addConstantColumn("commissionPercent", PlatformDataType.DOUBLE, commissionPercent);
ds.addColumn("name", PlatformDataType.STRING);
int newRow;
newRow = ds.newRow();
ds.set(newRow, "name", "tom");
newRow = ds.newRow();
ds.set(newRow, "name", "david");
ConvertDefinition definition = new ConvertDefinition(ds.getName());
definition.setGenericType(StaticPropertyBean.class);
List convertedList = null;
try {
convertedList = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("converted list should not be null.", convertedList);
StaticPropertyBean staticBean = (StaticPropertyBean) convertedList.get(0);
Assert.assertEquals("tom", staticBean.getName());
Assert.assertEquals(commissionPercent, staticBean.getCommissionPercent());
staticBean = (StaticPropertyBean) convertedList.get(1);
Assert.assertEquals("david", staticBean.getName());
Assert.assertEquals(commissionPercent, staticBean.getCommissionPercent());
}
@Test
public void testUpperCase() {
}
@Test
public void testLowerCase() {
}
@Test
public void testDataSetRowTypeWithBean() {
Class convertedType = DataSetRowTypeBean.class;// for bean
DataSet ds = new DataSet("dsRowType");
ds.addColumn("name", PlatformDataType.STRING);
int newRow = ds.newRow();
ds.set(newRow, "name", "tom");
// update..
ds.startStoreDataChanges();
ds.set(newRow, "name", "david");
ConvertDefinition definition = new ConvertDefinition(ds.getName());
definition.setGenericType(convertedType);
List convertedList = null;
try {
convertedList = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
Assert.assertNotNull("converted list should not be null.", convertedList);
int expectedCnt = ds.getRowCount();
int actualCnt = convertedList.size();
Assert.assertEquals(expectedCnt, actualCnt);
DataSetRowTypeBean rowTypeBean = (DataSetRowTypeBean) convertedList.get(0);
Assert.assertEquals("david", rowTypeBean.getName());
// expected DataSet.ROW_TYPE_NAME_UPDATED
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_UPDATED, rowTypeBean.getRowType());
}
@Test
public void testDataSetRowTypeWithMap() {
Class convertedType = Map.class;
DataSet ds = new DataSet("dsRowType");
ds.addColumn("name", PlatformDataType.STRING);
int newRow = ds.newRow();
ds.set(newRow, "name", "tom");
// update..
ds.startStoreDataChanges();
ds.set(newRow, "name", "david");
ConvertDefinition definition = new ConvertDefinition(ds.getName());
definition.setGenericType(convertedType);
List convertedList = null;
try {
convertedList = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
Assert.assertNotNull("converted list should not be null.", convertedList);
int expectedCnt = ds.getRowCount();
int actualCnt = convertedList.size();
Assert.assertEquals(expectedCnt, actualCnt);
Map rowTypeMap = (Map) convertedList.get(0);
Assert.assertEquals("david", rowTypeMap.get("name"));
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_UPDATED, rowTypeMap.get(DataSetRowTypeAccessor.NAME));
}
@Test
public void testDataSetSavedDataWithBean() {
Class convertedType = DataSetSavedDataBean.class;// for bean
DataSet ds = new DataSet("dsRowType");
ds.addColumn("name", PlatformDataType.STRING);
int newRow = ds.newRow();
ds.set(newRow, "name", "tom");
// update..
ds.startStoreDataChanges();
ds.set(newRow, "name", "david");
// inserted..
newRow = ds.newRow();
ds.set(newRow, "name", "tom");
ConvertDefinition definition = new ConvertDefinition(ds.getName());
definition.setGenericType(convertedType);
List convertedList = null;
try {
convertedList = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
Assert.assertNotNull("converted list should not be null.", convertedList);
int expectedCnt = ds.getRowCount();
int actualCnt = convertedList.size();
Assert.assertEquals(expectedCnt, actualCnt);
DataSetSavedDataBean bean, savedData = null;
String expectedSavedData, actualSavedData;
// first row is updated data..
bean = (DataSetSavedDataBean) convertedList.get(0);
Assert.assertEquals("david", bean.getName());
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_UPDATED, bean.getRowType());
savedData = bean.getData();
expectedSavedData = "tom";
actualSavedData = savedData.getName();
Assert.assertEquals("saved data should be maintained.", expectedSavedData, actualSavedData);
// second row is inserted data..
bean = (DataSetSavedDataBean) convertedList.get(1);
Assert.assertEquals("tom", bean.getName());
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_INSERTED, bean.getRowType());
savedData = bean.getData();
Assert.assertNull("additional data should be null data.", savedData);
}
@Test
public void testDataSetSavedDataWithMap() {
Class convertedType = Map.class; // for map
DataSet ds = new DataSet("dsRowType");
ds.addColumn("name", PlatformDataType.STRING);
int newRow = ds.newRow();
ds.set(newRow, "name", "tom");
// update..
ds.startStoreDataChanges();
ds.set(newRow, "name", "david");
// inserted..
newRow = ds.newRow();
ds.set(newRow, "name", "tom");
ConvertDefinition definition = new ConvertDefinition(ds.getName());
definition.setGenericType(convertedType);
List convertedList = null;
try {
convertedList = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
Assert.assertNotNull("converted list should not be null.", convertedList);
int expectedCnt = ds.getRowCount();
int actualCnt = convertedList.size();
Assert.assertEquals(expectedCnt, actualCnt);
Map<String, Object> dataMap, savedData = null;
String expectedSavedData, actualSavedData;
// first row is updated data..
dataMap = (Map<String, Object>) convertedList.get(0);
Assert.assertEquals("david", dataMap.get("name"));
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_UPDATED, dataMap.get(DataSetRowTypeAccessor.NAME));
savedData = (Map<String, Object>) dataMap.get(DataSetSavedDataAccessor.NAME);
expectedSavedData = "tom";
actualSavedData = (String) savedData.get("name");
Assert.assertEquals("saved data should be maintained.", expectedSavedData, actualSavedData);
// second row is inserted data..
dataMap = (Map<String, Object>) convertedList.get(1);
Assert.assertEquals("tom", dataMap.get("name"));
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_INSERTED, dataMap.get(DataSetRowTypeAccessor.NAME));
savedData = (Map<String, Object>) dataMap.get(DataSetSavedDataAccessor.NAME);
Assert.assertNull("additional data should be null data.", savedData);
}
@Test
public void testRemovedDataWithBean() {
Class convertedType = DataSetSavedDataBean.class;
DataSet ds = new DataSet("dsRowType");
ds.addColumn("name", PlatformDataType.STRING);
int newRow = ds.newRow();
ds.set(newRow, "name", "tom");
// delete..
ds.startStoreDataChanges();
ds.set(newRow, "name", "david");
ds.removeRow(0);
// inserted..
newRow = ds.newRow();
ds.set(newRow, "name", "tom");
ConvertDefinition definition = new ConvertDefinition(ds.getName());
definition.setGenericType(convertedType); // for bean
List convertedList = null;
try {
convertedList = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
Assert.assertNotNull("converted list should not be null.", convertedList);
int expectedCnt = ds.getRowCount() + 1; // +1 is removed data..
int actualCnt = convertedList.size();
Assert.assertEquals(expectedCnt, actualCnt);
DataSetSavedDataBean bean, savedData = null;
// first row is inserted data.
bean = (DataSetSavedDataBean) convertedList.get(0);
Assert.assertEquals("tom", bean.getName());
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_INSERTED, bean.getRowType());
savedData = bean.getData();
Assert.assertNull("additional data should be null data.", savedData);
// second row is deleted data..
bean = (DataSetSavedDataBean) convertedList.get(1);
Assert.assertEquals("deleted data must be saved data", "tom", bean.getName()); // original data..
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_DELETED, bean.getRowType());
savedData = bean.getData();
Assert.assertNull("saved data must be null.", savedData);
}
@Test
public void testRemovedDataWithMap() {
Class convertedType = Map.class;
DataSet ds = new DataSet("dsRowType");
ds.addColumn("name", PlatformDataType.STRING);
int newRow = ds.newRow();
ds.set(newRow, "name", "tom");
// delete..
ds.startStoreDataChanges();
ds.set(newRow, "name", "david");
ds.removeRow(0);
// inserted..
newRow = ds.newRow();
ds.set(newRow, "name", "tom");
ConvertDefinition definition = new ConvertDefinition(ds.getName());
definition.setGenericType(convertedType); // for bean
List convertedList = null;
try {
convertedList = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(convertedList instanceof List)) {
Assert.fail("converted object must be implemented List");
}
Assert.assertNotNull("converted list should not be null.", convertedList);
int expectedCnt = ds.getRowCount() + 1; // +1 is removed data..
int actualCnt = convertedList.size();
Assert.assertEquals(expectedCnt, actualCnt);
Map<String, Object> dataMap, savedData = null;
String expectedSavedData, actualSavedData;
// first row is inserted data.
dataMap = (Map<String, Object>) convertedList.get(0);
Assert.assertEquals("tom", dataMap.get("name"));
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_INSERTED, dataMap.get(DataSetRowTypeAccessor.NAME));
savedData = (Map<String, Object>) dataMap.get(DataSetSavedDataAccessor.NAME);
Assert.assertNull("additional data should be null data.", savedData);
// second row is deleted data..
dataMap = (Map<String, Object>) convertedList.get(1);
Assert.assertEquals("deleted data must be saved data", "tom", dataMap.get("name")); // original data..
Assert.assertEquals("rowType data should be maintained.", DataSet.ROW_TYPE_DELETED, dataMap.get(DataSetRowTypeAccessor.NAME));
savedData = (Map<String, Object>) dataMap.get(DataSetSavedDataAccessor.NAME);
Assert.assertNull("saved data must be null.", savedData);
}
@Test
public void testStaticSpringBeanWrapper() {
BeanWrapper wrapper = new BeanWrapperImpl(StaticPropertyBean.class);
wrapper.setPropertyValue("commissionPercent", 10.0d);
// System.out.println(wrapper.getPropertyValue("comissionPercent"));
StaticPropertyBean bean = (StaticPropertyBean) wrapper.getWrappedInstance();
// System.out.println(bean.getComissionPercent());
}
// @Test
public void testStaticIbatis() {
// StaticPropertyBean bean = new StaticPropertyBean();
// bean.setCommissionPercent(10.0d);
//
// ClassInfo ref = ClassInfo.getInstance(StaticPropertyBean.class);
//
// Invoker setInvoker = ref.getSetInvoker("commissionPercent");
// try {
// setInvoker.invoke(bean, new Object[]{11.0d});
// } catch (IllegalAccessException e1) {
// e1.printStackTrace();
// } catch (InvocationTargetException e1) {
// e1.printStackTrace();
// }
//
// Invoker getInvoker = ref.getGetInvoker("commissionPercent");
// try {
// Object invoke = getInvoker.invoke(bean, new Object[]{});
//// System.out.println(invoke);
// } catch (IllegalAccessException e) {
// e.printStackTrace();
// } catch (InvocationTargetException e) {
// e.printStackTrace();
// }
}
@Test
public void testConvertPerformance() {
StopWatch sw = new StopWatch(getClass().getSimpleName());
int columnCount = 10;
DataSet ds = new DataSet("ds");
for(int i=0; i<columnCount; i++) {
ds.addColumn("column"+i, PlatformDataType.STRING);
}
sw.start("set data");
int rowCount = 10000;
for(int rowIndex=0; rowIndex<rowCount; rowIndex++) {
int newRow = ds.newRow();
for(int colIndex=0; colIndex<columnCount; colIndex++) {
ds.set(newRow, colIndex, "value"+rowIndex+colIndex);
}
}
sw.stop();
sw.start("get data");
for(int rowIndex=0; rowIndex<rowCount; rowIndex++) {
for(int colIndex=0; colIndex<columnCount; colIndex++) {
ds.getString(rowIndex, colIndex);
}
}
sw.stop();
DataSetToListConverter converter = new DataSetToListConverter();
ConvertDefinition definition = new ConvertDefinition("ds");
definition.setGenericType(Map.class);
try {
sw.start("convert List<Map>");
java.util.List convert = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
} finally {
sw.stop();
}
definition.setGenericType(DataSetObj.class);
try {
sw.start("convert List<DataSetObj>");
java.util.List convert = converter.convert(ds, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
} finally {
sw.stop();
}
System.out.println(sw.prettyPrint());
}
public static class DataSetObj {
private String column0;
private String column1;
private String column2;
private String column3;
private String column4;
private String column5;
private String column6;
private String column7;
private String column8;
private String column9;
public String getColumn0() {
return column0;
}
public void setColumn0(String column0) {
this.column0 = column0;
}
public String getColumn1() {
return column1;
}
public void setColumn1(String column1) {
this.column1 = column1;
}
public String getColumn2() {
return column2;
}
public void setColumn2(String column2) {
this.column2 = column2;
}
public String getColumn3() {
return column3;
}
public void setColumn3(String column3) {
this.column3 = column3;
}
public String getColumn4() {
return column4;
}
public void setColumn4(String column4) {
this.column4 = column4;
}
public String getColumn5() {
return column5;
}
public void setColumn5(String column5) {
this.column5 = column5;
}
public String getColumn6() {
return column6;
}
public void setColumn6(String column6) {
this.column6 = column6;
}
public String getColumn7() {
return column7;
}
public void setColumn7(String column7) {
this.column7 = column7;
}
public String getColumn8() {
return column8;
}
public void setColumn8(String column8) {
this.column8 = column8;
}
public String getColumn9() {
return column9;
}
public void setColumn9(String column9) {
this.column9 = column9;
}
}
}

View File

@@ -0,0 +1,372 @@
package com.nexacro.spring.data.support;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.spring.data.support.NexacroTestUtil.StaticPropertyBean;
import com.nexacro.spring.data.support.bean.DefaultBean;
import com.nexacro.xapi.data.ColumnHeader;
import com.nexacro.xapi.data.ConstantColumnHeader;
import com.nexacro.xapi.data.DataSet;
import junit.framework.Assert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ListToDataSetConverterTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 4.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 4. Park SeongMin 최초 생성
* </pre>
*/
public class ListToDataSetConverterTest {
private ListToDataSetConverter converter;
@Before
public void setUp() {
converter = new ListToDataSetConverter();
}
@Test
public void testSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = List.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
// List sub class support.
source = ArrayList.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
}
@Test
public void testUnSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = Object.class;
target = DataSet.class;
canConvert = converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
List list = new ArrayList();
list.add(new Object[]{1, 2});
list.add(new Object[]{3, 4});
ConvertDefinition definition = new ConvertDefinition("ds");
try {
converter.convert(list, definition);
Assert.fail("Object[] is unsupported type.");
} catch (NexacroConvertException e) {
}
}
@Test
public void testConvertListBeanToDataSet() {
List<DefaultBean> defaultBean = NexacroTestUtil.createDefaultBeans();
ConvertDefinition definition = new ConvertDefinition("ds");
Object ds = null;
try {
ds = converter.convert(defaultBean, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(ds instanceof DataSet)) {
Assert.fail("converted object must be implemented DataSet");
}
NexacroTestUtil.compareDefaultDataSet((DataSet) ds);
}
@Test
public void testConvertListMapToDataSet() {
List<Map<String, Object>> defaultMap = NexacroTestUtil.createDefaultMaps();
ConvertDefinition definition = new ConvertDefinition("ds");
Object ds = null;
try {
ds = converter.convert(defaultMap, definition);
} catch (NexacroConvertException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
if(!(ds instanceof DataSet)) {
Assert.fail("converted object must be implemented DataSet");
}
NexacroTestUtil.compareDefaultDataSet((DataSet) ds);
}
@Test
public void testNullData() {
List list = null;
ConvertDefinition definition = new ConvertDefinition("ds");
DataSet ds = null;
try {
ds = converter.convert(list, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("dataset should not be null", ds);
Assert.assertEquals("ds", ds.getName());
}
@Test
public void testStaticColumns() {
StaticPropertyBean staticBean;
double commissionPercent = 10.0d;
List<StaticPropertyBean> staticBeanList = new ArrayList<StaticPropertyBean>();
staticBean = new StaticPropertyBean();
staticBean.setName("tom");
staticBean.setCommissionPercent(commissionPercent);
staticBeanList.add(staticBean);
staticBean = new StaticPropertyBean();
staticBean.setName("david");
staticBeanList.add(staticBean);
ConvertDefinition definition = new ConvertDefinition("ds");
DataSet ds = null;
try {
ds = converter.convert(staticBeanList, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("converted list should not be null.", ds);
int columnCount = ds.getColumnCount();
Assert.assertEquals("two columns must be exist.", 2, ds.getColumnCount());
ColumnHeader column = ds.getColumn("name");
Assert.assertFalse(column.isConstant());
column = ds.getColumn("commissionPercent");
Assert.assertTrue(column.isConstant());
ConstantColumnHeader constColumn = (ConstantColumnHeader) column;
// check const column value
Assert.assertEquals(commissionPercent, constColumn.getValue());
Assert.assertEquals("tom", ds.getString(0, "name"));
Assert.assertEquals("david", ds.getString(1, "name"));
}
@Test
public void testUpperCase() {
}
@Test
public void testLowerCase() {
}
//
@Test
public void testNotSupportedRowType() {
}
@Test
public void testNotSupportedSavedData() {
}
@Test
public void testNotSupportedRemovedData() {
}
@Test
public void testListConvert() {
List<DefaultBean> beanList = new ArrayList<DefaultBean>();
// Result result = new Result();
//// List<?> list = result.getList();
//
//
// DefaultBean bean = new DefaultBean();
// beanList.add(bean);
//
// Object[] array = beanList.toArray();
// array[0].getClass();
//
// Class<? extends List> clazz= beanList.getClass();
//
// ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
// System.out.println(parameterizedType.getRawType());
//
// Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
// for(Type type: actualTypeArguments) {
// System.out.println(type);
// }
DefaultBean bean = new DefaultBean();
beanList.add(bean);
System.out.println("key = " + beanList);
Class<?> clazz = beanList.getClass();
System.out.println("clazz = " + clazz);
ParameterizedType superclass = (ParameterizedType) clazz.getGenericSuperclass();
Type[] types = superclass.getActualTypeArguments();
Class<?> actualdataType = null;
if(types != null && types.length >0 && (types[0] instanceof Class<?>) ) {
actualdataType = (Class<?>) (Class<?>) types[0];
}
System.out.println("actualdataType = " + actualdataType);
}
@Test
public void testListType() {
List<DefaultBean> beanList = new ArrayList<DefaultBean>();
Type[] parameterizedTypes = getParameterizedTypes(beanList);
Class<?> class1;
try {
class1 = getClass(parameterizedTypes[0]);
System.out.println(class1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// List<DefaultBean> beanList = new ArrayList<DefaultBean>();
//
// Class<?> class1 = getClass(beanList.getClass());
// System.out.println(class1);
// System.out.println(getClass(class1));
}
private static final String TYPE_CLASS_NAME_PREFIX = "class ";
private static final String TYPE_INTERFACE_NAME_PREFIX = "interface ";
public static String getClassName(Type type) {
if (type==null) {
return "";
}
String className = type.toString();
if (className.startsWith(TYPE_CLASS_NAME_PREFIX)) {
className = className.substring(TYPE_CLASS_NAME_PREFIX.length());
} else if (className.startsWith(TYPE_INTERFACE_NAME_PREFIX)) {
className = className.substring(TYPE_INTERFACE_NAME_PREFIX.length());
}
return className;
}
/**
* Returns the {@code Class} object associated with the given {@link Type}
* depending on its fully qualified name.
*
* @param type the {@code Type} whose {@code Class} is needed.
* @return the {@code Class} object for the class with the specified name.
*
* @throws ClassNotFoundException if the class cannot be located.
*
* @see {@link ReflectionUtil#getClassName(Type)}
*/
public static Class<?> getClass(Type type) throws ClassNotFoundException {
String className = getClassName(type);
if (className==null || className.isEmpty()) {
return null;
}
return Class.forName(className);
}
public static Type[] getParameterizedTypes(Object object) {
Type superclassType = object.getClass().getGenericSuperclass();
if (!ParameterizedType.class.isAssignableFrom(superclassType.getClass())) {
return null;
}
return ((ParameterizedType)superclassType).getActualTypeArguments();
}
// public static Class<?> getClass(Type type) {
// if (type instanceof Class) {
// return (Class) type;
// }
// else if (type instanceof ParameterizedType) {
// return getClass(((ParameterizedType) type).getRawType());
// }
// else if (type instanceof GenericArrayType) {
// Type componentType = ((GenericArrayType) type).getGenericComponentType();
// Class<?> componentClass = getClass(componentType);
// if (componentClass != null ) {
// return Array.newInstance(componentClass, 0).getClass();
// }
// else {
// return null;
// }
// }
// else {
// return null;
// }
// }
private static class Result {
private List<?> list;
public void setList(List<?> list) {
this.list = list;
}
public List<?> getList() {
return null;
}
}
}

View File

@@ -0,0 +1,79 @@
package com.nexacro.spring.data.support;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.NotWritablePropertyException;
import com.nexacro.spring.data.support.bean.DefaultBean;
import junit.framework.Assert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroBeanWrapperTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 4.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 4. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroBeanWrapperTest {
@Test
public void testInstantiateClass() {
NexacroBeanWrapper accessor = createAccessor(DefaultBean.class);
Object insatance = accessor.getInsatance();
assertNotNull(insatance);
if(!(insatance instanceof DefaultBean)) {
fail("instantiate class must be instance of " + DefaultBean.class);
}
}
@Test
public void testSetPropertyValue() {
NexacroBeanWrapper accessor = createAccessor(DefaultBean.class);
accessor.setPropertyValue("firstName", "tom");
DefaultBean target = (DefaultBean) accessor.getInsatance();
assertTrue("Set name to tom", target.getFirstName().equals("tom"));
}
@Rule
public ExpectedException thrown= ExpectedException.none();
@Test
// @Test (expected=NotWritablePropertyException.class)
public void testSetInvalidPropertyValue() {
thrown.expect(NotWritablePropertyException.class);
thrown.expectMessage("Invalid property 'invalid'");
NexacroBeanWrapper accessor = createAccessor(DefaultBean.class);
accessor.setPropertyValue("invalid", "tom");
DefaultBean target = (DefaultBean) accessor.getInsatance();
Assert.assertEquals("Set name to tom", "tom", target.getFirstName());
}
private NexacroBeanWrapper createAccessor(Class clazz) {
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(clazz);
return beanWrapper;
}
}

View File

@@ -0,0 +1,409 @@
package com.nexacro.spring.data.support;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Assert;
import com.nexacro.spring.data.DataSetRowTypeAccessor;
import com.nexacro.spring.data.DataSetSavedDataAccessor;
import com.nexacro.spring.data.support.bean.DefaultBean;
import com.nexacro.xapi.data.ColumnHeader;
import com.nexacro.xapi.data.DataSet;
import com.nexacro.xapi.data.datatype.DataType;
import com.nexacro.xapi.data.datatype.PlatformDataType;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : TestDataUtil.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 10.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 10. Park SeongMin 최초 생성
* </pre>
*/
public abstract class NexacroTestUtil {
private static String[] dsPropertyNames;
private static List<Object[]> dsValuesList;
private static DataType[] dsDataTypes;
// private static List<Map<String, Object>> dataMapList;
// private static Map<String, DataType> dataTypeMap;
private static Map<Class, Object> supportedClassesValue;
static {
initSupportedClassesValue();
initDsPropertyNames();
initDsValueList();
initDsDataTypes();
}
static Map<Class, Object> getSupportedClassesValue() {
return Collections.unmodifiableMap(supportedClassesValue);
}
private static void initSupportedClassesValue() {
supportedClassesValue = new HashMap<Class, Object>();
Calendar instance = null;
Date hireDate = null;
instance = Calendar.getInstance();
instance.set(2009, Calendar.JANUARY, 1);
hireDate = new Date(instance.getTimeInMillis());
supportedClassesValue.put(int.class, 11);
supportedClassesValue.put(Integer.class, new Integer(11));
supportedClassesValue.put(long.class, 11l);
supportedClassesValue.put(Long.class, new Long(11l));
supportedClassesValue.put(float.class, 180.1f);
supportedClassesValue.put(Float.class, new Float(180.1f));
supportedClassesValue.put(double.class, 11.1d);
supportedClassesValue.put(Double.class, new Double(11.1d));
supportedClassesValue.put(boolean.class, true);
supportedClassesValue.put(Boolean.class, Boolean.TRUE);
supportedClassesValue.put(byte[].class, new byte[] { 1, 1 });
supportedClassesValue.put(Byte[].class, new Byte[] { 1, 1 });
supportedClassesValue.put(String.class, "seongmin");
supportedClassesValue.put(Date.class, hireDate);
supportedClassesValue.put(BigDecimal.class, new BigDecimal("10001"));
supportedClassesValue.put(Object.class, new Object());
}
private static void initDsPropertyNames() {
dsPropertyNames = new String[] { "employeeId", "access", "height", "commissionPercent", "male", "image",
"firstName", "lastName", "email", "hireDate", "salary", "obj" };
}
private static void initDsValueList() {
dsValuesList = new ArrayList<Object[]>();
Calendar instance = null;
Date hireDate = null;
instance = Calendar.getInstance();
instance.set(2009, Calendar.JANUARY, 1);
hireDate = new Date(instance.getTimeInMillis());
Object[] firstValues = new Object[] { 11, 11l, 180.1f, 11.1d, true, new byte[] { 1, 1 }, "seongmin", "park",
"seongmin@tobesoft.com", hireDate, new BigDecimal("10001"), new Object() };
dsValuesList.add(firstValues);
instance = Calendar.getInstance();
instance.set(2009, Calendar.JANUARY, 2);
hireDate = new Date(instance.getTimeInMillis());
Object[] secondValues = new Object[] { 12, 12l, 180.2f, 11.2d, false, new byte[] { 1, 2 }, "hyena", "lee",
"hyena@tobesoft.com", hireDate, new BigDecimal("10002"), new Object() };
dsValuesList.add(secondValues);
}
private static void initDsDataTypes() {
dsDataTypes = new DataType[] { PlatformDataType.INT, PlatformDataType.LONG, PlatformDataType.FLOAT,
PlatformDataType.DOUBLE, PlatformDataType.BOOLEAN, PlatformDataType.BLOB, PlatformDataType.STRING,
PlatformDataType.STRING, PlatformDataType.STRING, PlatformDataType.DATE_TIME,
PlatformDataType.BIG_DECIMAL, PlatformDataType.UNDEFINED };
}
public static List<DefaultBean> createDefaultBeans() {
List<DefaultBean> beanList = new ArrayList<DefaultBean>();
for (Object[] value : dsValuesList) {
NexacroBeanWrapper wrapper = NexacroBeanWrapper.createBeanWrapper(DefaultBean.class);
for (int i=0; i<dsPropertyNames.length; i++) {
wrapper.setPropertyValue(dsPropertyNames[i], value[i]);
}
Object bean = wrapper.getInsatance();
beanList.add((DefaultBean) bean);
}
return beanList;
}
public static DataSet createDefaultDataSet() {
DataSet ds = new DataSet("employee");
for (int i = 0; i < dsPropertyNames.length; i++) {
ds.addColumn(dsPropertyNames[i], dsDataTypes[i]);
}
for (Object[] value : dsValuesList) {
int newRow = ds.newRow();
for (int i = 0; i < dsPropertyNames.length; i++) {
ds.set(newRow, dsPropertyNames[i], value[i]);
}
}
return ds;
}
public static List<Map<String, Object>> createDefaultMaps() {
List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
for (Object[] value : dsValuesList) {
Map<String, Object> dataMap = new HashMap<String, Object>();
for (int i=0; i<dsPropertyNames.length; i++) {
dataMap.put(dsPropertyNames[i], value[i]);
}
mapList.add(dataMap);
}
return mapList;
}
public static void compareDefaultBeans(List<DefaultBean> beanList) {
if (beanList == null) {
Assert.fail("bean list is null");
}
int expectedSize = dsValuesList.size();
int actualSize = beanList.size();
Assert.assertEquals("bean list size does not matched. please check converted columns. expected=" + expectedSize
+ ", actual=" + actualSize, expectedSize, actualSize);
for (int rowIndex = 0; rowIndex < actualSize; rowIndex++) {
DefaultBean defaultBean = beanList.get(rowIndex);
NexacroBeanWrapper beanWrapper = NexacroBeanWrapper.createBeanWrapper(defaultBean);
NexacroBeanProperty[] properties = beanWrapper.getProperties();
if (dsPropertyNames.length != properties.length) {
Assert.fail("bean properties does not matched. please check converted columns. expected="
+ dsPropertyNames.length + ", actual=" + properties.length);
}
Object[] values = dsValuesList.get(rowIndex);
for (int propertyIndex = 0; propertyIndex < dsPropertyNames.length; propertyIndex++) {
NexacroBeanProperty property = beanWrapper.getProperty(dsPropertyNames[propertyIndex]);
Object expectedValue = values[propertyIndex];
Object actualValue = beanWrapper.getPropertyValue(dsPropertyNames[propertyIndex]);
Assert.assertEquals("row(" + rowIndex + ") property(" + dsPropertyNames[propertyIndex]
+ ") value does not matched. expected=" + expectedValue + ", actual=" + actualValue,
expectedValue, actualValue);
}
}
}
public static void compareDefaultDataSet(DataSet ds) {
if (ds == null) {
Assert.fail("compare DataSet is null");
}
int expectedSize = dsPropertyNames.length;
int actualSize = ds.getColumnCount();
Assert.assertEquals("DataSet column does not matched. please check converted columns. expected=" + expectedSize
+ ", actual=" + actualSize, expectedSize, actualSize);
// check column
for (int propertyIndex = 0; propertyIndex < dsPropertyNames.length; propertyIndex++) {
String propertyName = dsPropertyNames[propertyIndex];
ColumnHeader column = ds.getColumn(propertyName);
if (!propertyName.equals(column.getName())) {
Assert.fail("column name does not matched. expected=" + dsPropertyNames[propertyIndex] + ", autual="
+ column.getName());
}
if (!dsDataTypes[propertyIndex].equals(column.getPlatformDataType())) {
Assert.fail(column.getName() + " data type does not matched. expected=" + dsDataTypes[propertyIndex] + ", autual="
+ column.getPlatformDataType());
}
}
// check values
int rowCount = ds.getRowCount();
if (dsValuesList.size() != rowCount) {
Assert.fail("DataSet rows does not matched. expected=" + dsValuesList.size() + ", actual=" + rowCount);
}
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
Object[] values = dsValuesList.get(rowIndex);
for (int propertyIndex = 0; propertyIndex < dsPropertyNames.length; propertyIndex++) {
String propertyName = dsPropertyNames[propertyIndex];
Object expectedValue = values[propertyIndex];
Object actualValue = ds.getObject(rowIndex, propertyName);
Assert.assertEquals("row(" + rowIndex + ") property(" + dsPropertyNames[propertyIndex]
+ ") value does not matched. expected=" + expectedValue + ", actual=" + actualValue,
expectedValue, actualValue);
}
}
}
public static void compareDefaultMaps(List<Map<String, Object>> mapList) {
if (mapList == null) {
Assert.fail("map list is null");
}
int size = mapList.size();
if (dsValuesList.size() != size) {
Assert.fail("map list size does not matched. expected=" + dsValuesList.size() + ", actual=" + size);
}
for (int rowIndex = 0; rowIndex < size; rowIndex++) {
Map<String, Object> dataMap = mapList.get(rowIndex);
Set<String> keySet = dataMap.keySet();
// row type이 추가되어 있다.
int expectedSize = dsPropertyNames.length + 1;
int actualSize = keySet.size();
Assert.assertEquals("map properties does not matched. please check converted columns. expected="
+ expectedSize + ", actual=" + actualSize, expectedSize, actualSize);
Object[] values = dsValuesList.get(rowIndex);
for (int propertyIndex = 0; propertyIndex < dsPropertyNames.length; propertyIndex++) {
String propertyName = dsPropertyNames[propertyIndex];
Object expectedValue = values[propertyIndex];
Object actualValue = dataMap.get(propertyName);
Assert.assertEquals("row(" + rowIndex + ") property(" + dsPropertyNames[propertyIndex]
+ ") value does not matched. expected=" + expectedValue + ", actual=" + actualValue,
expectedValue, actualValue);
}
}
}
public static class StaticPropertyBean {
private String name;
private static double commissionPercent;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the commissionPercent
*/
public static double getCommissionPercent() {
return commissionPercent;
}
/**
* @param commissionPercent the commissionPercent to set
*/
public static void setCommissionPercent(double commissionPercent) {
StaticPropertyBean.commissionPercent = commissionPercent;
}
}
public static class DataSetRowTypeBean implements DataSetRowTypeAccessor {
private String name;
private int rowType;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int getRowType() {
return this.rowType;
}
@Override
public void setRowType(int rowType) {
this.rowType = rowType;
}
}
public static class DataSetSavedDataBean implements DataSetSavedDataAccessor<DataSetSavedDataBean>, DataSetRowTypeAccessor {
private String name;
private int rowType;
private DataSetSavedDataBean savedData;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public DataSetSavedDataBean getData() {
return this.savedData;
}
@Override
public void setData(DataSetSavedDataBean savedData) {
this.savedData = savedData;
}
@Override
public int getRowType() {
return this.rowType;
}
@Override
public void setRowType(int rowType) {
this.rowType = rowType;
}
}
}

View File

@@ -0,0 +1,151 @@
package com.nexacro.spring.data.support;
import java.util.Map;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.xapi.data.Variable;
import junit.framework.Assert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ObjectToVariableTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 19.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 19. Park SeongMin 최초 생성
* </pre>
*/
public class ObjectToVariableConverterTest {
private ObjectToVariableConverter converter;
@Before
public void setUp() {
converter = new ObjectToVariableConverter();
}
@Test
public void testSupportedType() {
Class target = Variable.class;
boolean canConvert;
Map<Class, Object> supportedClassValues = NexacroTestUtil.getSupportedClassesValue();
Set<Class> classSet = supportedClassValues.keySet();
for(Class clazz: classSet) {
Class source = clazz;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
}
}
@Test
public void testUnSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
target = Variable.class;
source = byte.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
source = char.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
source = short.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
source = java.sql.Date.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
}
@Test
public void testConvertAll() {
Map<Class, Object> supportedClassValues = NexacroTestUtil.getSupportedClassesValue();
Set<Class> classSet = supportedClassValues.keySet();
for(Class clazz: classSet) {
String variableName = "var";
Object value = supportedClassValues.get(clazz);
ConvertDefinition definition = new ConvertDefinition(variableName);
Variable convertedVar = null;
try {
convertedVar = converter.convert(value, definition);
} catch (NexacroConvertException e) {
Assert.fail(clazz + " -> variable convert failed. e="+e.getMessage());
}
Assert.assertNotNull("'"+clazz + " -> variable' converted value should not be null.", convertedVar);
String actualVariableName = convertedVar.getName();
Assert.assertEquals(variableName, actualVariableName);
// compare data.
Object actualValue = convertedVar.getObject();
if(Byte[].class.equals(clazz)) {
// Byte[]의 경우 Variable은 byte[]로 존재하기 때문에 실제데이터를 비교한다.
Byte[] expected = (Byte[]) value;
byte[] actual = (byte[]) convertedVar.getBlob();
Assert.assertEquals("Byte[] data was not properly converted.", expected.length, actual.length);
for(int i=0; i<expected.length; i++) {
Assert.assertEquals("Byte[] data was not properly converted.", expected[i].byteValue(), actual[i]);
}
} else {
Assert.assertEquals("'"+clazz + " -> variable' data was not properly converted.", value, actualValue);
}
}
}
@Test
public void testSupportAutomaticConversionByteArr() {
Byte[] byteArr = new Byte[]{1, 2};
ConvertDefinition definition = new ConvertDefinition("var");
Variable convertedVar = null;
try {
convertedVar = converter.convert(byteArr, definition);
} catch (NexacroConvertException e) {
Assert.fail("variable -> Byte[] convert failed. e="+e.getMessage());
}
Assert.assertNotNull("'Byte[] -> variable' converted value should not be null.", convertedVar);
byte[] actualByteArr = convertedVar.getBlob();
Assert.assertNotNull("'Byte[] -> variable' converted value should not be null.", actualByteArr);
Assert.assertEquals("Byte[] data was not properly converted.", byteArr.length, actualByteArr.length);
for(int i=0; i<byteArr.length; i++) {
Assert.assertEquals("Byte[] data was not properly converted.", byteArr[i].byteValue(), actualByteArr[i]);
}
}
}

View File

@@ -0,0 +1,261 @@
package com.nexacro.spring.data.support;
import java.util.Map;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import com.nexacro.spring.data.convert.ConvertDefinition;
import com.nexacro.spring.data.convert.NexacroConvertException;
import com.nexacro.xapi.data.Variable;
import junit.framework.Assert;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : VariableToObjectConverterTest.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 19.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 19. Park SeongMin 최초 생성
* </pre>
*/
public class VariableToObjectConverterTest {
private VariableToObjectConverter converter;
@Before
public void setUp() {
converter = new VariableToObjectConverter();
}
@Test
public void testSupportedType() {
Class source = Variable.class;
Class target;
boolean canConvert;
Map<Class, Object> supportedClassValues = NexacroTestUtil.getSupportedClassesValue();
Set<Class> classSet = supportedClassValues.keySet();
for(Class clazz: classSet) {
target = clazz;
canConvert = converter.canConvert(source, target);
Assert.assertTrue(source + " to " + target + " must be converted", canConvert);
}
}
@Test
public void testUnSupportedType() {
Class<?> source;
Class<?> target;
boolean canConvert;
source = Variable.class;
target = byte.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
target = char.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
target = short.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
target = java.sql.Date.class;
canConvert= converter.canConvert(source, target);
Assert.assertFalse(source + " to " + target + " can not convertible", canConvert);
}
@Test
public void testConvertAll() {
Map<Class, Object> supportedClassValues = NexacroTestUtil.getSupportedClassesValue();
Set<Class> classSet = supportedClassValues.keySet();
for(Class clazz: classSet) {
Object value = supportedClassValues.get(clazz);
Variable var = new Variable("var");
// variable에 Byte[]는 삽입되어서는 안된다. Byte[]는 byte[]로 변환되어 삽입되어져야 한다.
if(Byte[].class.equals(clazz)) {
Object object = NexacroConverterHelper.toObject(value);
var.set(object);
} else {
var.set(value);
}
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(clazz);
Object convertedObj = null;
try {
convertedObj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail("variable -> " + clazz + " convert failed. e="+e.getMessage());
}
Assert.assertNotNull("'variable -> " + clazz + "' converted value should not be null.", convertedObj);
if(Byte[].class.equals(clazz)) {
// Byte[]의 경우 실제데이터를 비교한다.
Byte[] expected = (Byte[]) value;
Byte[] actual = (Byte[]) convertedObj;
Assert.assertEquals("Byte[] data was not properly converted.", expected.length, actual.length);
for(int i=0; i<expected.length; i++) {
Assert.assertEquals("Byte[] data was not properly converted.", expected[i], actual[i]);
}
} else {
Assert.assertEquals("'variable -> " + clazz + "' data was not properly converted", value, convertedObj);
}
}
}
@Test
public void testUnSupportedByteArrInsertedVariable() {
Byte[] byteArr = new Byte[]{1, 2};
Variable var = new Variable("var");
var.set(byteArr);
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(byteArr.getClass());
Object convertedObj = null;
try {
convertedObj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail("variable -> Byte[] convert failed. e="+e.getMessage());
}
Assert.assertNull("Byte[] is inserted in the variable is not supported.", convertedObj);
}
@Test
public void testInteger() {
int value = 1;
Variable var = Variable.createVariable("var", value);
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(int.class);
Object obj = null;
try {
obj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("object should not be null.", obj);
Assert.assertEquals(value, obj);
}
@Test
public void testIntegerWrapper() {
Integer value = new Integer(1);
Variable var = Variable.createVariable("var", value);
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(Integer.class);
Object obj = null;
try {
obj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("object should not be null.", obj);
Assert.assertEquals(value, obj);
}
@Test
public void testLong() {
long value = 1l;
Variable var = Variable.createVariable("var", value);
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(long.class);
Object obj = null;
try {
obj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("object should not be null.", obj);
Assert.assertEquals(value, obj);
}
@Test
public void testLongWrapper() {
Long value = new Long(1l);
Variable var = Variable.createVariable("var", value);
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(Long.class);
Object obj = null;
try {
obj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("object should not be null.", obj);
Assert.assertEquals(value, obj);
}
@Test
public void testFloat() {
float value = 1.1f;
Variable var = Variable.createVariable("var", value);
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(float.class);
Object obj = null;
try {
obj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("object should not be null.", obj);
Assert.assertEquals(value, obj);
}
@Test
public void testFloatWrapper() {
Float value = 1.1f;
Variable var = Variable.createVariable("var", value);
ConvertDefinition definition = new ConvertDefinition(var.getName());
definition.setGenericType(Float.class);
Object obj = null;
try {
obj = converter.convert(var, definition);
} catch (NexacroConvertException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull("object should not be null.", obj);
Assert.assertEquals(value, obj);
}
}

View File

@@ -0,0 +1,215 @@
package com.nexacro.spring.data.support.bean;
import java.math.BigDecimal;
import java.util.Date;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : DefaultBean.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 4.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 4. Park SeongMin 최초 생성
* </pre>
*/
public class DefaultBean {
private int employeeId;
private long access;
private float height;
private double commissionPercent;
private boolean male;
private byte[] image;
private String firstName;
private String lastName;
private String email;
private Date hireDate;
private BigDecimal salary;
private Object obj;
private DefaultBean savedData;
private int rowType;
/**
* @return the employeeId
*/
public int getEmployeeId() {
return employeeId;
}
/**
* @param employeeId the employeeId to set
*/
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
/**
* @return the access
*/
public long getAccess() {
return access;
}
/**
* @param access the access to set
*/
public void setAccess(long access) {
this.access = access;
}
/**
* @return the height
*/
public float getHeight() {
return height;
}
/**
* @param height the height to set
*/
public void setHeight(float height) {
this.height = height;
}
/**
* @return the commissionPercent
*/
public double getCommissionPercent() {
return commissionPercent;
}
/**
* @param commissionPercent the commissionPercent to set
*/
public void setCommissionPercent(double commissionPercent) {
this.commissionPercent = commissionPercent;
}
/**
* @return the male
*/
public boolean isMale() {
return male;
}
/**
* @param male the male to set
*/
public void setMale(boolean male) {
this.male = male;
}
/**
* @return the image
*/
public byte[] getImage() {
return image;
}
/**
* @param image the image to set
*/
public void setImage(byte[] image) {
this.image = image;
}
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* @param firstName the firstName to set
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* @return the lastName
*/
public String getLastName() {
return lastName;
}
/**
* @param lastName the lastName to set
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* @return the email
*/
public String getEmail() {
return email;
}
/**
* @param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
/**
* @return the hireDate
*/
public Date getHireDate() {
return hireDate;
}
/**
* @param hireDate the hireDate to set
*/
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
/**
* @return the salary
*/
public BigDecimal getSalary() {
return salary;
}
/**
* @param salary the salary to set
*/
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
/**
* @return the obj
*/
public Object getObj() {
return obj;
}
/**
* @param obj the obj to set
*/
public void setObj(Object obj) {
this.obj = obj;
}
}

View File

@@ -0,0 +1,50 @@
package com.nexacro.spring.data.support.bean;
import com.nexacro.spring.data.DataSetRowTypeAccessor;
import com.nexacro.spring.data.DataSetSavedDataAccessor;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : NexacroBean.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 4.
* @version 1.0
* @see
* @Modification Information
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 4. Park SeongMin 최초 생성
* </pre>
*/
public class NexacroSupportedBean extends DefaultBean implements DataSetRowTypeAccessor, DataSetSavedDataAccessor<NexacroSupportedBean>{
private int rowType;
private NexacroSupportedBean savedData;
@Override
public NexacroSupportedBean getData() {
return savedData;
}
@Override
public void setData(NexacroSupportedBean t) {
this.savedData = t;
}
@Override
public int getRowType() {
return this.rowType;
}
@Override
public void setRowType(int rowType) {
this.rowType = rowType;
}
}

View File

@@ -0,0 +1,61 @@
package com.nexacro.spring.data.support.bean;
import java.util.List;
/**
* <pre>
* Statements
* </pre>
*
* @ClassName : ExtendedBean.java
* @Description : 클래스 설명을 기술합니다.
* @author Park SeongMin
* @since 2015. 8. 10.
* @version 1.0
* @see
* @Modification Information
*
* <pre>
* since author description
* =========== ============= ===========================
* 2015. 8. 10. Park SeongMin 최초 생성
* </pre>
*/
public class UnsupportedBean extends DefaultBean {
private List<String> stringList;
private DefaultBean unsupportedBean;
/**
* @return the unsupportedBean
*/
public DefaultBean getUnsupportedBean() {
return unsupportedBean;
}
/**
* @param unsupportedBean
* the unsupportedBean to set
*/
public void setUnsupportedBean(DefaultBean unsupportedBean) {
this.unsupportedBean = unsupportedBean;
}
/**
* @return the stringList
*/
public List<String> getStringList() {
return stringList;
}
/**
* @param stringList
* the stringList to set
*/
public void setStringList(List<String> stringList) {
this.stringList = stringList;
}
}

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<!-- ConsoleAppender -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<!-- ref.) attr : Encoding, ImmediateFlush, Target, Threshold -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p [%c] %m%n" />
</layout>
<!-- String 매칭 되는 Log 삭제
<filter class="org.apache.log4j.varia.StringMatchFilter">
<param name="StringToMatch" value="Result" />
<param name="AcceptOnMatch" value="false" />
</filter>
-->
</appender>
<!-- FileAppender -->
<appender name="appLog" class="org.apache.log4j.FileAppender">
<param name="Encoding" value="UTF-8" />
<param name="File" value="/DES/logs/was/pilot/applog/app.log" />
<param name="ImmediateFlush" value="true" />
<param name="Append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p [%c] %m%n" />
</layout>
</appender>
<!-- FileAppender : XML
<appender name="appLog" class="org.apache.log4j.FileAppender">
<param name="Encoding" value="UTF-8" />
<param name="File" value="/DES/logs/was/pilot/appxmllog/appxml.log" />
<param name="ImmediateFlush" value="true" />
<param name="Append" value="true" />
<layout class="org.apache.log4j.xml.XMLLayout"></layout>
</appender>
-->
<!-- RollingFileAppender -->
<appender name="sqlLog" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="/DES/logs/was/pilot/sqllog/sql.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="1000KB" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p [%c] %m%n" />
</layout>
</appender>
<!-- JDBCAppender
<appender name="jdbcAppender" class="org.apache.log4j.jdbc.JDBCAppender">
<param name="Driver" value="oracle.jdbc.driver.OracleDriver"/>
<param name="URL" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
<param name="User" value="scott"/>
<param name="Password" value="tiger"/-->
<!--param name="bufferSize" value="1"/--><!-- 주석처리 해 둘 것 -->
<!--param name="Sql" value="INSERT INTO tb_log (message, class, priority, log_date)
VALUES ('%m', '%l', '%p', '%d')"/>
</appender>
-->
<!--
JDBCAppender를 사용하여 case by case로 DB에 저장을 하게되면 DBMS에 많은 부담을 줄 수 있다.
AsyncAppender를 사용하여 큐에 쌓았다가 한꺼번에 저장하는 방식을 추천한다.
<appender name="asyncAppender" class="org.apache.log4j.AsyncAppender">
<param name="locationInfo" value="false"/>
<! bufferSize 모아서 보낼 로그 수(이벤트의 수). 디폴트 128
<param name="bufferSize" value="128"/>
<appender-ref ref="jdbcAppender" />
</appender>
-->
<!-- DailyRollingFileAppender -->
<appender name="dailyRollingFile" class="org.apache.log4j.DailyRollingFileAppender">
<!-- ref.) attr : FileAppender + DatePattern -->
<!--param name="File" value="C:/DES/workspace/projects/engineer/src/main/webapp/WEB-INF/logs/sample.log" /-->
<param name="File" value="/DES/logs/was/pilot/console.log" />
<param name="Append" value="true" />
<!--
SimpleDateFormat 을 따름. ex.) .yyyy-ww : 첫날 기준 매주마다,
.yyyy-MM : 월단위
.yyyy-MM-ww : 주단위
.yyyy-MM-dd : 일단위
.yyyy-MM-dd-a : 12시간단위
.yyyy-MM-dd-HH : 시간단위
.yyyy-MM-dd-HH-mm : 매분마다
-->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p [%c] %m%n" />
</layout>
</appender>
<!-- log SQL with timing information, post execution
-->
<logger name="aes" additivity="false">
<level value="DEBUG" />
<appender-ref ref="console" />
<appender-ref ref="dailyRollingFile" />
</logger>
<logger name="able" additivity="false">
<level value="DEBUG" />
<appender-ref ref="console" />
</logger>
<!-- SQL Result Log -->
<logger name="java.sql" additivity="false">
<level value="DEBUG" />
<appender-ref ref="console" />
<!--appender-ref ref="jdbcAppender"/ --> <!-- Oracle DBMS TABLE 에 로그를 남기고 있음 -->
</logger>
<!-- controlling scope -->
<logger name="org.springframework.web.servlet.DispatcherServlet" additivity="false">
<level value="DEBUG" />
<appender-ref ref="console" />
</logger>
<logger name="org.springframework.web.context.ContextLoader" additivity="false">
<level value="DEBUG" />
<appender-ref ref="console" />
</logger>
<logger name="com.nexacro.xapi" additivity="false">
<level value="FATAL" />
<appender-ref ref="console" />
</logger>
<logger name="com.nexacro.performance" additivity="false">
<level value="TRACE" />
<appender-ref ref="console" />
</logger>
<root>
<priority value ="INFO" />
<appender-ref ref="console"/>
<!--
<appender-ref ref="dailyRollingFile"/>
-->
</root>
</log4j:configuration>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<license version="1.0">
<product>
<name>nexacro&#32;platform</name>
<version>14</version>
<function>Windows,&#32;WindowsRT,&#32;MAC,&#32;iOS,&#32;Android</function>
</product>
<customer>
<name>TOBESOFT</name>
<coreCount>0</coreCount>
<ipAddress>0.0.0.0</ipAddress>
<targetPlatform>Runtime,HTML5</targetPlatform>
</customer>
<date>
<activation>2015-09-01</activation>
<term unit="month">2</term>
</date>
<key>H3UWWYFVJJT5R4JHVWCWQGAZFWTQX96NX</key>
</license>