ZipServiceの例
このプログラム例では以下のステップを実行します。
1. ZipServiceのロードに必要な一連の呼び出しを行います。
2. IFSの/LIZIPOUTディレクトリにLIZIPIN.ZIPというZipファイルを作成します。
3. /LIZIPINディレクトリの内容をZipファイルに圧縮してファイルを閉じます。
4. Zipファイルを再度開いて読み込みます。
5. Zipファイルのエントリーのリストを複数のオカレンス・データ構造に取り出します。
6. 最初のZipエントリーを/LIZIPOUTディレクトリに解凍します。
7. Zipファイルを閉じ、サービスをアンロードしてJSMサーバーとの接続を閉じます。
注:
· この例について意味のあるテストをするには、IFSに2つのフォルダー/LIZIPINと/LIZIPOUTを作成し、選択したファイルの小さなまとまりを/LIZIPINフォルダーに追加する必要があります。どのファイルも使用できます。使用するファイルは、プログラム例で圧縮されるファイルです。
· プログラム例では、Zipファイルのエントリー数が999以下の場合のみ正常に取得できます。そのため、これよりも多いファイルを/LIZIPINフォルダーに追加しないでください。
· 互換性を最大限に利用する場合、プログラム例で扱うことができるのは最大256文字長までのファイル・パスのみになります。どれか1つのファイル・パスでもこの制限を超える場合、/LIZIPINにファイルやフォルダーを追加しないでください。これよりも長いパスを処理するには、必要に応じて独自のプログラムを作成できます。
詳細については、例のコメントとコードを参照してください。
このアプリケーションを機能させるには、以下の3つのステップが必要です。
1. 構造XMLを作成する
ZipServiceのGET ENTRY(*LIST)コマンドを呼び出すと、複数のオカレンス・データ構造が渡されます。このデータ構造では最大で999のZipファイルのエントリーのリストが取得されます。これが機能するには、LANSA Integratorサービスでこの構造の特性を把握する必要があります。そのためには、構造を記述するXMLファイルを提供します。
この例の場合、必要なXMLが以下に示されています。このXMLをインストールするには、以下のステップを実行する必要があります。
a. JSMサーバーのJSMインスタンス・フォルダーでstructureフォルダーを探します。
b. ZipEntryList.xmlというファイルを作成します。
c. このファイルをテキスト・エディタで編集し、以下のxmlを貼り付けます。
構造XMLで使用されるフィールド名が、RPGプログラムで使用される変数名と一致する必要はありません(この例では一致しません)。重要なのは、注文、タイプ、長さになります。
<?xml version="1.0" encoding="UTF-8"?>
<rdml:structure xmlns:rdml="http://www.lansa.com/2000/XML/Function">
<rdml:field name="ZIPENT" type="A" length="256" />
</rdml:structure>
2. 構造XMLをJSMサーバーに登録する
以下のプログラム例が、シンボル名ZIP.ZipEntryListで上記の構造XMLを参照するには、GET ENTRY(*LIST)コマンドのSERVICE_STRUCTUREキーワードにそのシンボル名を指定します。
このシンボル名と、ステップ1で作成された構造XMLファイルの実際の名前および場所とのリンクをJSMサーバーに提供する必要があります。このためには、以下のステップを実行してください。
a. JSMサーバーのJSMインスタンス・フォルダーでsystemフォルダーを探します。
b. structure.propertiesファイルをテキスト・エディタで編集し、以下のエントリーを貼り付けます(新しいエントリーが単体で個別の行に記述されるようにします)。
structure.ZIP.ZipEntryList=structure/ZipEntryList.xml
c. 変更内容を保存します。
d. JSMサーバー・インスタンスを再起動または更新します(「Java Service Managerの更新」を参照)。
3. ILE RPGプログラム例を作成して実行する
LANSA Integratorの最新インストールには、以下のプログラム例のソースがすでに含まれています。含まれていない場合は、ソースをコピーしてソース・ファイル・メンバーに貼り付けることができます。
プログラムを作成するには、CRTRPGMODコマンドとCRTPGMコマンドを使用する必要があります。必ずソース・メンバーに指定したパラメータ値を使用します。
*************************************************
* ZIP: example in RPG ILE of using the LANSA Integrator
* ZipService
*
* Note: This is an example program containing only
* rudimentary exception handling
*
* To create this program you must execute the following commands,
* supplying the indicated parameter values and any others that are
* necessary in your installation:
*
* CRTRPGMOD MODULE(<modlib>/ZIP)
* SRCFILE(<srclib>/<srcfil>)
*
* CRTPGM PGM(<pgmlib>/ZIP)
* MODULE(<modlib>/ZIP)
* BNDSRVPGM(<jsmpgmlib>/DCXS882X)
* ACTGRP(*CALLER)
*************************************************
* IFS folders used by this program
* - to try this program you need to create these folders in your IFS
* and add one or more files to the /LIZIPIN folder
d flrzipin c const('/LIZIPIN')
d flrzipout c const('/LIZIPOUT')
d zipfilepath s 255a
* Declare variables for the JSM calls
d jsmsrv s 50a inz(*blanks)
d jsmsts s 20a inz(*blanks)
d jsmmsg s 255a inz(*blanks)
d jsmcmd s 255a inz(*blanks)
d bytelength s 10i 0 inz(*zero)
* Declare structure to send or receive zip file entries
* - the structure must contain the following fields as defined
* by the GET command of the ZipService
* o Zip entry (path and/or file names)
* NB: This MUST match the structure xml provided to the JSM Server!
d ziplist ds occurs(zipocur)
d zipentry 256a
d zipocur c const(999)
d zipsize c const(%size(ziplist))
d zipcount s 9p 0 inz(0)
* Completion messages
d CompMsg10 c 'JSMOPEN call completed.'
d CompMsg20 c ' SERVICE_LOAD call completed.'
d CompMsg30 c ' CREATE call completed.'
d CompMsg40 c ' OPEN call completed.'
d CompMsg50 c ' ADD call completed.'
d CompMsg60 c ' GET ENTRY(*LIST) call completed.'
d CompMsg65 c ' GET ENTRY(*READ) call completed.'
d CompMsg70 c ' CLOSE call completed.'
d CompMsg80 c ' SERVICE_UNLOAD call completed.'
d CompMsg99 c 'JSMCLOSE call completed.'
* Procedure prototypes
d CheckResult pr
d crjsts const like(jsmsts)
d crjmsg const like(jsmmsg)
d SendMessage pr
d smText 512a VALUE
d smType 10a VALUE
* Prototypes for the JSM calls
/COPY QRPGLESRC,JSM_PROC.H
* Open a connection to the default JSM server
* - because the server parameter is blank, details of the default
* JSM server are obtained from the data area JSMCTLDTA on IBM i
* or from the file jsmctldta.txt on other supported platforms)
c callp p_jsmopen(jsmsrv:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg10:'*COMP')
* Load the ZipService
* - this example explicitly turns tracing on, overriding the
* settings in the manager.properties file
c eval jsmcmd = 'SERVICE_LOAD'
c + ' SERVICE(ZIPSERVICE) TRACE(*YES)'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg20:'*COMP')
* Create the zip file: /LIZIPOUT/LIZIPIN.ZIP
* - we place it in the /LIZIPOUT folder
* - we will zip the contents of /LIZIPIN into it
c eval zipfilepath = flrzipout + flrzipin + '.ZIP'
c eval jsmcmd = 'CREATE'
c + ' FILE(' + %trim(zipfilepath) + ')'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg30:'*COMP')
* Add the contents of the folder /LIZIPIN to the zip file
* - by specifying BASE(*CURRENT) we request that path information stored
* in the zip entries is only for descendant folders of /LIZIPIN
c eval jsmcmd = 'ADD'
c + ' PATH(' + flrzipin + ') BASE(*CURRENT)'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg50:'*COMP')
* Close the current archive
c eval jsmcmd = 'CLOSE'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg70:'*COMP')
* Reopen the zip file: /LIZIPOUT/LIZIPIN.ZIP
* - we will retrieve a list of its contents
* - we will unzip the first file into /LIZIPOUT
c eval jsmcmd = 'OPEN'
c + ' FILE(' + %trim(zipfilepath) + ')'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg40:'*COMP')
* Load a list of zip entries from the current archive
* - although this passes the multiple occurrence data structure
* (ziplist) in which to receive the list, the data is not actually
* received into the structure until the JSMBYTERECV call below
* - the structure is described to the ZipService by the
* structure XML identified by the SERVICE_STRUCTURE keyword - there
* must be a matching entry in the structure.properties file and a
* corresponding structure XML file, usually in the JSMInstance\Structure
* folder
* NOTE: this call uses the JSMCMDX api in order to be able to send and/or
* receive variable data (in this case the list)
c eval jsmcmd = 'GET ENTRY(*LIST)'
c + ' SERVICE_STRUCTURE(ZIP.ZipEntryList)'
c + ' OCCURS(' + %char(zipocur) + ')'
c + ' SIZE(' + %char(zipsize) + ')'
c eval %occur(ziplist) = 1
c eval bytelength = zipocur * zipsize
c callp p_jsmcmdx(jsmcmd:ziplist:bytelength:
c jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg60:'*COMP')
* Get the length of the received data structure
* - only continue to attempt to receive it if the length is valid
c callp p_jsmbytelngth(bytelength)
c if (bytelength > 0)
c and (bytelength <= zipocur * zipsize)
* ... receive the zip entry list into
* our multiple occurrence data structure
* - don't forget to set the DS occurrence to 1 before the call
c callp p_jsmbyterecv(ziplist)
* ... calculate the number of entries
c eval zipcount = bytelength / zipsize
* ... unzip the first entry only into /LIZIPOUT
c eval jsmcmd = 'GET ENTRY(*READ)'
c + ' FILE(' + %trim(zipentry) + ')'
c + ' TO(' + flrzipout + ')'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg65:'*COMP')
c endif
* Close the current archive
c eval jsmcmd = 'CLOSE'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg70:'*COMP')
* Unload the ZipService
c eval jsmcmd = 'SERVICE_UNLOAD'
c callp p_jsmcmd(jsmcmd:jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg80:'*COMP')
* Close the connection to the JSM server and finish
c callp p_jsmclose(jsmsts:jsmmsg)
c callp CheckResult(jsmsts:jsmmsg)
c callp SendMessage(CompMsg99:'*COMP')
c eval *inlr = *on
c return
*************************************************
* Procedure to check the result of a Java Service Manager call
*************************************************
p CheckResult b
d CheckResult pi
d crjsts const like(jsmsts)
d crjmsg const like(jsmmsg)
d crText s 512a
d crMsg1 c const('JSM Status : ')
d crMsg2 c const('JSM Message: ')
d crMsg3 c const('JSM Service error has +
d occurred')
c if crjsts <> 'OK'
c eval crText = crMsg1 + crjsts
c callp SendMessage(crText:'*DIAG')
c eval crText = crMsg2 + crjmsg
c callp SendMessage(crText:'*DIAG')
c callp SendMessage(crMsg3:'*ESCAPE')
c endif
p CheckResult e
*************************************************
* Procedure to send a program message
*************************************************
p SendMessage b
d SendMessage pi
d smText 512a VALUE
d smMsgT 10a VALUE
d smMsgI s 7a inz('CPF9897')
d smMsgF s 20a inz('QCPFMSG *LIBL ')
d smDtaL s 10i 0 inz(%size(smText))
d smStkE s 10a inz('*')
d smStkC s 10i 0 inz(1)
d smMsgK s 4a
d smErrC s 10i 0 inz(0)
c if smMsgT = '*ESCAPE'
c eval smMsgI = 'CPF9898'
c endif
c call 'QMHSNDPM'
c parm smMsgI
c parm smMsgF
c parm smText
c parm smDtaL
c parm smMsgT
c parm smStkE
c parm smStkC
c parm smMsgK
c parm smErrC
p e