'BSI Tax Factory'에 해당되는 글 1건

  1. 2011.11.03 BSI Tax Factory 통합

BSI Tax Factory 통합

일상 2011. 11. 3. 07:28

1)BSI Tax Factory 에 관한 건 아래 링크 와 소개글 참고, 한줄 요약하면 미국 세금 계산 툴이다.

BSI- BUSINESS SOFTWARE INC.http://www.bsi.com/

BSI software is mandatory for Tax calculation in US Payroll.
BSI TaxFactory™ offers the most comprehensive and cost effective payroll tax solution in the industry.
BSI Tax Factory does tax calculations and generates tax wage types along with Tax Authorities and Tax Models maintained in the SAP Payroll module.
Before the SAP Payroll component sends any data to the BSI TaxFactory for tax calculation,
the payroll driver goes through a number of steps to determine exactly which taxes will be applied for each payment or deduction wage type.
These steps depend largely on how you configure wage types, tax types, tax authorities, and taxability models in the Tax section of the Payroll: USA IMG.
BSI issued EIN(employer identification number) to thier clients.By this number payroll will integrates BSI.BSI connect to main sap system through RFC T CODE IS SM59.

Refer following link to set up BSI tax factory,



2)이 엔진을 자바환경으로 통합시키는 태스크이다.일단, 윈도우즈 환경에서(tf9api.dll 을 이용) 통합한다.
이 태스크를 위해 제공된 정보는 클라이언트용 BSI_Windows32Bit.exe 파일 하나였다.이 파일을 인스톨 하게 되면 tf9api.h 파일과 dll 파일, 그리고 샘플 c 소스코드가 있다.

간단하게 말해서, "자바에서 tf9api.dll 의 내부 함수를 jna 를 이용해서 호줄하는 태스크이다"

일단, 원본 소스가 없기 때문에 jni 보다는 jna 를 이용하기로 결정.tf9api.h 파일에 함수 시그니처가 있어서 그 함수 정의를 참고로 jna 를 쓰기위한 인터페이스 작성.

첫번째 문제는,헤더파일에 정의 되어있는 함수가 dll 에 없었다.그 함수를 예상하고 작성한 자바 클래스에서 에러 발생.
사용자 삽입 이미지

dll export 함수 리스트를 확인해보니(PE Explorer 를 썼다, 그 외에 공개툴도 많다) 구조체에 대한 정의 밖에 없었다.혹시나 dll packing 되었나 싶어서(좀 지나친 감은 있었지만, 크래킹이나 리버싱 해본 경험이 있으면 늘(?!) 한번씩 하는 과정이다),PEiD 를 써서 확인해보니 패킹된 건 아니다.
사용자 삽입 이미지


tf9api.h 파일에 함수 시그니처가 있기 때문에, 랩퍼 dll 을 만들어 해당 구조체를 이용해 포인터를 이용한 간접호출을 시도해보기로 결정.하지만, 윈도우즈 dll 을 마지막으로 짜본게 언제더라~

공개용 C 컴파일러인 MinGW를 이용하기로 하고, 다운 받아서 c 코드 작성, 그리고 dll 컴파일 명령어는 아래와 같다.

gcc -mno-cygwin -I./include -I./include/win32 -Wl,--add-stdcall-alias -shared -o TF9APIWrapper.dll TF9APIWrapper.c

참고로, include 파일안의 헤더파일들은 위에서 설치한 파일 안에 있는 헤더파일들을 썼다.
#include "tf9api.h"
#include "tf9tools.h"

Dll 컴파일 후 Export 리스트를 확인해보면 아래와 같다.
사용자 삽입 이미지


자바쪽에서 tf9api.dll 함수 호출 성공한 화면은 아래와 같다. dll 내부의 ConnectToDataSource 함수를 호출한 경우이다.
사용자 삽입 이미지


두번째 문제는, tf9api.h 파일안에 정의되어 있는 구조체를 java 쪽에서 선언 후(jna) 넘겨주면, dll 에서 제대로 처리하지 못하고 있었다.
몇 일동안 이런 저런 시도하다가, 우연히 점심을 먹다 동료와 요즘 무슨일 하고 있냐는 평범한 대화속에,
jnaerator 툴을 알게 되었다,한번 이걸로 c 에서 선언한 구조체를 java 의 클래스 타입으로 제너레이팅 해서 해보라는 조언을 해줬다.

사실 큰 기대는 없었다, 그런데 아래처럼 관련 클래스를 만들고(기존에는 직접 해당 클래스를 작성했엇다, 차이점은 c 데이타 타입에 맞는 java 타입으로 선언해줫었다,문자 그대로 그렇게만 선언을 해줬다)

java -jar jnaerator-0.9.8-shaded.jar -library tf9api tf9api.h -o . -v -noJar -noComp

위 명령어를 실행하면 tf9api 폴더가 생겨나고 그 안에 클래스 파일들이 만들어진다,c 구조체에 대한 java 클래스 파일들을 봣더니, 생성자부터 초기화 시켜주는 메소드들이 있었다.기존의 클래스들을 이 파일들로 교체 후 테스트 하니 제대로 전달이 되었다.

주의, public interface Tf9apiLibrary extends Library {..} 이런식으로 인터페이스 마저 생성해주는데. 인터페이스는 이걸 쓰지는 않았다.단순히 c 함수 정의에 맞는 인터페이스만 선언한(물론 Library를 확장한 클래스이다) 클래스 파일을 썼다.

일반 변수와,구조체에 대한 함수 콜을 확인 후(c 소스내에서  fprintf 문으로 확인)코볼 개발자와 자바 통합을 담당하는 개발자에게 프로젝트와 c 소스를 넘겼다.

하지만,운영 환경에서 동작하는 걸 확인하지 못해서,모든 함수 호출이 제대로 동작하는지는 미 검증이다.

3)아래는 gcc 를 이용한 윈도우즈 dll 만들기 와 unix 용 so( so 파일은 미 검증) 만드는 명령어 이다

Windows 용 dll
gcc -mno-cygwin -I./include -I./include/win32 -Wl,--add-stdcall-alias -shared -o TF9APIWrapper.dll TF9APIWrapper.c

Unix 용 so
gcc -c -w -fPIC -I$./linuxinclude -I$./linuxinclude/linux -o TF9APIWrapper.o TF9APIWrapper.C
gcc -o TF9APIWrapper.so -shared TF9APIWrapper.o -lgcc


마지막으로,자바쪽에서 C dll 로 넘긴 구조체의 길이를(?) 제대로 처리하지 못하는 것 같다, 왜 이런 원인이 생기는지는 모르겠다,그래서 아래처럼 해결을 했다(원인을 정확히 파악하지 못했기 때문에 이것 역시 100% 확신할 수 없다, 테스트 시스템은 64Bit 윈도우즈 환경이다)

BSI_SHORT ConnectToDataSet(BSI_CHAR *ds, BSI_CHAR *user, BSI_CHAR *pwd, pTF9_SESSION sess, BSI_SHORT *rtncd){

    BSI_CHAR        str[256] = "";
    TF9_SESSION     Session;
    BSI_CHAR        User[100] = "";
    BSI_CHAR        Pass[100] = "";
    BSI_SHORT       ret;

    LoadAPI();

//아래 처럼 다시 한번 구조체를 선언 후, 할당 시켰다
Session = *sess;

//특수문자가 깨진 것이 보인다.
fprintf(stdout,"ConnectToDataSet function, %s %s %s %s\n", ds, user, pwd ,rtncd);
fprintf(stdout,"sess->SESS value is : %s\n", sess->SESS);
fprintf(stdout,"sess->Filler value is : %s\n", sess->Filler);

fprintf(stdout,"\n");
//예상대로 동작한다.
fprintf(stdout,"ConnectToDataSet function, %s %s %s %s\n", ds, user, pwd ,rtncd);
fprintf(stdout,"Session.SESS value is : %s\n",  Session.SESS);
fprintf(stdout,"Session.Filler value is : %s\n", Session.Filler);
//fprintf(stdout,"sess %s \n", sess.SESS);
//fprintf(stdout,"filer %s \n", sess.Filler);
//USER_FUNCTIONS->ConnectToDataSet(ds, user, pwd,sess,rtncd);
if (!USER_FUNCTIONS->ConnectToDataSet(ds, user, pwd, &Session,rtncd)) {
        fprintf(stderr, "Connect to data set error: %s.\n", ds);
        //exit(1);
    }

    return 1;
}

위 코드에 대한 스크린 캡쳐는 아래와 같다.
사용자 삽입 이미지


이 프로젝트를 정리하기 전에,잊지 않기 위해 다시 한번 적어둔다.

'일상' 카테고리의 다른 글

세상 참 좁다  (0) 2011.11.19
재밌는 쿼리  (0) 2011.11.04
유럽발 금융위기의 여파  (0) 2011.10.30
크리스마스 파티 초대  (0) 2011.10.28
Mouseland  (0) 2011.10.26
Posted by iamyhs
,