きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

z/OSでJavaを活用するためのJZOSのTips

com.ibm.jzos.CatalogSearchクラスというのがある。

当然ながら、カタログに登録されてないものは取ってこれない。
まあカタログに登録しない使い方をすることは稀だろう。

前に作ったコードを思い出しながら解説しよう。

CatalogSearch cs = new CatalogSearch("HLQ.**");
cs.search();
while(cs.hasNext()){
  CatalogSearch.Entry e = (CatalogSearch.Entry)cs.next();
  if(e.isCatalogEntry()){
      // do something
  }
  if(e.isDatasetEntry()){
      // do something
  }
}

ざっくり、こんな使い方。
しょっぱなでコンストラクタに渡すフィルターで検索する。
ワイルドカードの使い方を間違えると期待した結果にならないので注意が必要。
一般的な正規表現とは違うはずだ。
search()は必ず呼ばないといけない。
Entryのタイプは2種類あるので、判定して処理をする。


デフォルトではユーザーカタログ、マスターカタログの両方を見る感じだったはずだが、
両方見ないやり方も書こうと思えば出来る。


setEntryTypesによって、タイプを指定することも出来る。(search()の前に書く)
NON-VSAMだけ相手にしたいなら"A"を指定する。


実際、前に書いたコードでは、NON-VSAMを相手に、データセットを削除した。
ZFile.remove("//'HLQ.HOGE'")で消せないことがあるので、
そこはAccessMethodServiceを使えば消える。


AcessMethodServiceは、SYSIN相当を設定、SYSOUT相当を設定して、execute()する。
SYSINは、IDCAMのマニュアル読めばいい。
SYSOUTは、まずダミーのDDを作るところが必要になる。
ZFile.allocDummyDDName()した後に、そのDDに実際に割り振るためには、ZFile.bpxwdyn()を使う。
bpxwdynはUSSのマニュアルに載ってたはず。
割り当てが済んだら、setOutputDDName()して、execute()。
OutputDDNameが設定されていても、結果行数が大きいと制限にかかるので、
必要に応じてsetOutputBufLen()を増やす必要がある。
結果はgetOutputLines()で取ってくるのだが、戻り値がStringなんで、長すぎる結果には向かない。
あと、動的に割り当てたDDはfinallyでFREEしとくように。


実行環境を意識して動かしたい場合、ZUtil.getEnv("HOST")がとりあえず有効。
ただ、自分もまだ試してないけど、ZUtil.substituteSystemSymbols()も有効。
これはIEASYMxxで書いてるような書き方で動作するものだろう。
このあたりを使いこなすと、SYSPLEX名等が異なる環境でも動くものが作れる。
ただし、さまざまな命名規則が整備されてないと無理。


あと、ZUtil.getCurrentUser()なんてのも使える。
自分の場合は、TDUMP(JavaのSystem Dump)を出力させていたので、
オプション-Xdump:systemで変えるのを面倒臭がって、
デフォルトをそのまま使えるようにとプログラム側でHLQになるユーザー名を拾ったわけだ。(削除するために)
getCurrentJobname()やgetCurrentJobId()も使いどころはある。


JZOSにはExecというクラスもある。自分は使ったことないけど。
普通のProcessBuilderでも動かせる。
USSにはsubmitコマンドがあるので、外部プロセスからJOBをsubmitすることが出来る。
FTPで投げるって手もある。JESINTERFACELEVELの話なんかもあるので、FTPでやるべきかは難しい。
USSのsubmitコマンドは、STDOUTにJOBIDを返す。
うん、非同期だ。もともとJOBなんてのは非同期だ。
非同期となると、監視せにゃならん。
そこで、どうやったほうがいいかというと、SDSF for Javaの登場。
多少、通さないといけないライブラリが増える。
あと、ISFPRMxxの設定とかを変更しないと権限不足になったりする。
Hパネルを監視しとくようなイメージになるだろう。


submitコマンド以外では、REXXをかます方法がある。
JZOSなんかはREXXを絡めたサンプルまで付いてるくらいだ。
jobStatusもREXXでやる感じ。


MVSCommandCallBackインタフェースの使い方。
デフォルトでは、コマンドリスナースレッドが1つコマンドを受け付けように動いている。
その動きはさせないためには、環境変数をJZOS_ENABLE_MVS_COMMANDS=falseにする。
MVSCommandCallbackを使う場合は、2スレッドで動いているということを意識して書く必要がある。


こんなのだと、Mainスレッドが終了してと終わってしまう。

public static void main(String[] args){
  if(!MVSConsole.isListening()){
      MVSConsole.startMvsCommandListener();
  }
  MVSCommandCallback callback = new MVSCommandCallbackImpl();
  MVSConsole.registerMvsCommandCallback(callback)

}


最悪でも、こんなのにする。

public static void main(String[] args){
  if(!MVSConsole.isListening()){
      MVSConsole.startMvsCommandListener();
  }
  MVSCommandCallbackImpl callback = new MVSCommandCallbackImpl();
  Stopper stop = new Stopper();
  callback.setStopper(stop)
  MVSConsole.registerMvsCommandCallback(callback)

  // コールバックがSTOPコマンドを受け付けたら、Stopperに関与してメインスレッドを終わらせる感じ。
  while(!stop.isStop()){
     try{
         Thread.sleep(1000L);
     }catch(InterruptedException e){
         e.printStackTrace();
     }
  }
}


個人的に試したかったが試してないのはDfSortクラスとEnqueueクラス。