001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.plugin.daemon;
017
018 import java.util.ArrayList;
019 import java.util.Date;
020 import java.util.HashMap;
021 import java.util.LinkedHashMap;
022 import java.util.LinkedHashSet;
023 import java.util.List;
024 import java.util.Map;
025 import java.util.Set;
026
027 import org.opengion.fukurou.db.DBUtil;
028 import org.opengion.fukurou.db.Transaction;
029 import org.opengion.fukurou.db.TransactionReal;
030 import org.opengion.fukurou.transfer.TransferConfig;
031 import org.opengion.fukurou.transfer.TransferExec;
032 import org.opengion.fukurou.util.ApplicationInfo;
033 import org.opengion.fukurou.util.LogWriter;
034 import org.opengion.fukurou.util.StringUtil;
035 import org.opengion.hayabusa.common.HybsSystem;
036 import org.opengion.hayabusa.common.HybsSystemException;
037
038 /**
039 * 【伝é?シスãƒ?ƒ 】旧伝é?DB(CB01)を監視して、実行方法に応じたå?ç�??ログラãƒ?‚’呼び出しますã?
040 *
041 * こã?ãƒ??モンは、伝é?定義マスタの読取方法が、旧伝é?DB読å�?CB01)の定義を対象として実行されますã?
042 * 読取対象は、旧伝é?DB(CB01)で、データコードã?送り先ã?ãƒ?‚スト種別、状æ³?'1'を条件に読み込まれますã?
043 * 伝é?定義マスタ上では、読取対象にて、以下ã?形式で定義するå¿?¦�がありますã?
044 * (ãƒ??タコーãƒ? (送りå…? (ãƒ?‚スト種別) ä¾?:"3 D9 B119"
045 * 処ç�?®Ÿ行後ã?、読み取ったã?ãƒ?ƒ€ーãƒ??タの状況を'2'に更新しますã?
046 * ä½?�—、読取パラメーターに"NOUPDATE"を指定したå?合ã?処ç�?¾Œã?更新は行われませんã€?
047 * またã?エラーが発生したå?合ã?ヘッãƒ??ãƒ??タの状況を'9'に更新しますã?
048 *
049 * トランザクションは、読取対象の単位になりますã?
050 * 同じ読取対象で、異なる実行方法ã?実行対象を定義した場合ã?同じãƒ??タに対してè¤?•°回å?ç�?�Œ行われますã?
051 * しかしã?こã?場合においてもã?トランザクションは読取対象の単位で生æ?されるためã?è¤?•°回ã?処ç�??å†??
052 * 1回でもエラーが発生したå?合ã?、同じ読取対象でそれまでに処ç�?�—たå?につã�?�¦もrollbackされますã?
053 *
054 * またã?こã?伝é?ãƒ??モン(読取方æ³?は、旧伝é?DB(CB01)に対するクエリ回数を減らすためã?旧伝é?DB(CB01)と
055 * 伝é?定義マスタ(GE62)をJOINしてä¸?‹¬でãƒ??タを取得してã�?�¾すã?
056 * こã?ため、他ã?伝é?ãƒ??モン(読取方æ³?とは読取部åˆ??実è£?–¹法が異なってã�?�¾すã?
057 * 具体的には、{@link org.opengion.fukurou.transfer.TransferRead}インターフェースを利用せずにã€?
058 * こã?ãƒ??モン自体に読取及びスãƒ??タス更新の処ç�?‚’実è£?�—てã�?�¾すã?
059 *
060 * ※処ç�?¸に何らかã?エラーã�?度でも発生したå?合ã?こã?ãƒ??モンは停止しますã?
061 *
062 * こã?クラスは、HybsTimerTask を継承した タイマã?タスククラスですã?
063 * startDaemon() がタイマã?タスクによって、呼び出されますã?
064 *
065 * @og.rev 5.4.1.0 (2011/11/01) 伝é?シスãƒ?ƒ 対å¿?
066 * @og.group ãƒ??モン
067 *
068 * @version 5.0
069 * @author Hiroki Nakamura
070 * @since JDK6.0,
071 */
072 public class Daemon_Transfer_CB01 extends Daemon_Transfer {
073 //* こã?プログラãƒ??VERSIONæ–?—å?を設定しますã? {@value} */
074 private static final String VERSION = "5.4.1.0 (2011/11/01)" ;
075
076 // 実行方法に対応する実è£?‚¯ラスの基準名
077 private static final String EXEC_CLS_BASE = "org.opengion.fukurou.transfer.TransferExec_" ;
078
079 // 伝é?ãƒ??タ取得用SQL(クエリ回数を減らすため旧伝é?DBと伝é?定義マスタをJOINして検索)
080 private static final String GE62CB01_SELECT =
081 "SELECT B.KBREAD,B.READOBJ,B.READPRM,B.KBEXEC,B.EXECDBID,B.EXECOBJ,B.EXECPRM,B.ERROR_SENDTO,A.HTCNO" +
082 " FROM CB01 A,GE62 B" +
083 " WHERE A.HCDD = SUBSTR(B.READOBJ,1,INSTR(B.READOBJ,' ',1,1)-1)" + // "3 D9 B119"の"3"
084 " AND A.HTO = RPAD(SUBSTR(B.READOBJ,INSTR(B.READOBJ,' ',1,1)+1,INSTR(B.READOBJ,' ',1,2)-INSTR(B.READOBJ,' ',1,1)-1),8)" + // "3 D9 B119"の"D9"
085 " AND A.HSYU = RPAD(SUBSTR(B.READOBJ,INSTR(B.READOBJ,' ',1,2)+1),4)" + // "3 D9 B119"の"B119"
086 " AND A.HCDJ = '1'" +
087 " AND B.FGJ = '1'";
088
089 // コネクションにアプリケーションæƒ??を追記するかどã�?�‹æŒ?®?
090 private static final boolean USE_DB_APPLICATION_INFO = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
091
092 // HTTP接続時のプロキシホスãƒ?
093 private static final String HTTP_PROXY_HOST = HybsSystem.sys( "HTTP_PROXY_HOST" );
094
095 // HTTP接続時のプロキシポã?ãƒ?
096 private static final int HTTP_PROXY_PORT = HybsSystem.sysInt( "HTTP_PROXY_PORT" );
097
098 // 呼び出しå?ホストコーãƒ?
099 private static final String HFROM = HybsSystem.sys( "TRANSFER_HOST_CODE" );
100
101 // ループカウンタã‚?4回に設å®?
102 private static final int LOOP_COUNTER = 24;
103
104 private boolean running = true;
105 private int loopCnt = 0;
106
107 private String ge62Cb01Select = null;
108 private String dmnName = null;
109
110 private ApplicationInfo appInfo = null;
111 private boolean debug = false;
112
113 /**
114 * こã?タイマã?タスクによって初期化されるアクションですã?
115 * パラメータを使用した初期化を行いますã?
116 *
117 */
118 @Override
119 public void initDaemon() {
120 debug = StringUtil.nval( getValue( "DEBUG" ),debug );
121
122 dmnName = getName();
123
124 StringBuilder buf = new StringBuilder();
125 buf.append( GE62CB01_SELECT );
126
127 // シスãƒ?ƒ IDはå¿??æŒ?®?
128 String systemId = getValue( "SYSTEM_ID" );
129 if( StringUtil.isNull( systemId ) ) {
130 String errMsg = "シスãƒ?ƒ ID方法ã?å¿??æŒ?®šですã?" ;
131 throw new HybsSystemException( errMsg );
132 }
133 else {
134 buf.append( " AND B.SYSTEM_ID='" ).append( systemId ).append( "'" );
135 }
136
137 // 読取方法ã?å¿??æŒ?®?
138 String kbRead = getValue( "KBREAD" );
139 if( StringUtil.isNull( kbRead ) ) {
140 String errMsg = "読取方法ã?å¿??æŒ?®šですã?" ;
141 throw new HybsSystemException( errMsg );
142 }
143 else {
144 buf.append( " AND B.KBREAD='" ).append( kbRead ).append( "'" );
145 }
146
147 // ãƒ??モングループã?å¿??æŒ?®?
148 String dmnGroup = getValue( "DMN_GRP" );
149 if( StringUtil.isNull( dmnGroup ) ) {
150 String errMsg = "ãƒ??モングループã?å¿??æŒ?®šですã?" ;
151 throw new HybsSystemException( errMsg );
152 }
153 else {
154 buf.append( " AND B.DMN_GRP='" ).append( dmnGroup ).append( "'" );
155 }
156
157 buf.append( " ORDER BY A.HTC" );
158
159 ge62Cb01Select = buf.toString() ;
160
161 if( debug ) {
162 System.out.println( "DMN_NAME=[" + dmnName + "]" );
163 System.out.println( "QUERY=[" + ge62Cb01Select + "]" );
164 }
165
166 if( USE_DB_APPLICATION_INFO ) {
167 appInfo = new ApplicationInfo();
168 // ユーザーID,IPアドレス,ホスト名
169 appInfo.setClientInfo( systemId,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME );
170 // 画面ID,操ä½?プログラãƒ?D
171 appInfo.setModuleInfo( "TransferDaemon",dmnName,dmnName );
172 }
173 else {
174 appInfo = null;
175 }
176 }
177
178 /**
179 * タイマã?タスクのãƒ??モン処ç�??開始ã?イントですã?
180 *
181 */
182 @Override
183 protected void startDaemon() {
184 if( loopCnt % LOOP_COUNTER == 0 ) {
185 loopCnt = 1;
186 System.out.println();
187 System.out.print( toString() + " " + new Date() + " " );
188 }
189 else {
190 System.out.print( "." );
191 loopCnt++ ;
192 }
193
194 // 伝é?DB読å�?
195 String[][] vals = null;
196 GE62CB01Data ge62Cb01Data = new GE62CB01Data();
197 try {
198 vals = DBUtil.dbExecute( ge62Cb01Select,null,appInfo );
199 if( vals != null && vals.length > 0 ) {
200 for( int row=0; running && row<vals.length; row++ ) {
201 ge62Cb01Data.addData( vals[row] );
202 }
203 }
204 }
205 catch( Throwable ex ) {
206 String header = "伝é?読取エラー?šDMN_NAME=[" + dmnName + "] , DMN_HOST=[" + HybsSystem.HOST_NAME + "] , QUERY=[" + ge62Cb01Select + "]";
207 String errMsg = header + HybsSystem.CR + StringUtil.stringStackTrace( ex ) ;
208 System.out.println( errMsg );
209 LogWriter.log( errMsg );
210 String errorSendto = HybsSystem.sys( "ERROR_MAIL_TO_USERS" );
211 sendMail( header, errMsg, errorSendto );
212 }
213
214 // 処ç�?®Ÿè¡?
215 // 読取対象の単位でトランザクションを生成しますã?
216 for( String tranKey : ge62Cb01Data.getTranSet() ) {
217 Transaction tran = null;
218 TransferConfig conf = null;
219 String[] htcnoArr = null;
220 boolean isUpdate = true;
221 try {
222 tran = new TransactionReal( appInfo );
223
224 // 読取対象+実行方æ³?実行対象の単位で処ç�?‚’行いますã?
225 for( String confKey : ge62Cb01Data.getExecKeySet( tranKey ) ) {
226 conf = ge62Cb01Data.getConfig( confKey );
227 htcnoArr = ge62Cb01Data.getHtcno( confKey );
228
229 // ãƒ?ƒ�ãƒ?‚°æƒ??をå?力しますã?
230 if( debug ) {
231 System.out.println();
232 System.out.print( " START = " + new Date() );
233 System.out.print( "[" + dmnName + "]:[" + StringUtil.array2csv( htcnoArr ) + "]:[" + conf.toString() + "]" );
234 }
235
236 // 伝é?ãƒ??タを読み出しますã?
237 String[] val = read( htcnoArr, tran );
238 // 実行方法ã?オブジェクトを生æ?しますã?
239 TransferExec exec = (TransferExec)StringUtil.newInstance( EXEC_CLS_BASE + conf.getKbExec() );
240 // 処ç�?‚’実行しますã?
241 exec.execute( val, conf, tran );
242
243 // ãƒ?ƒ�ãƒ?‚°æƒ??をå?力しますã?
244 if( debug ) {
245 System.out.println();
246 System.out.print( " END = " + new Date() );
247 System.out.print( "[" + dmnName + "]:[" + StringUtil.array2csv( htcnoArr ) + "]:[" + conf.toString() + "]" );
248 }
249
250 // 対象となるã?スタのå†??読取パラメーターに?‘つでã‚?NOUPDATE"が指定されてã�?‚‹場合ã?、CB01の状況を更新しなã�?
251 if( "NOUPDATE".equalsIgnoreCase( conf.getReadPrm() ) ) {
252 isUpdate = false;
253 }
254 }
255
256 // 対象となるã?スタのå†??読取パラメーターに?‘つでã‚?NOUPDATE"が指定されてã�?‚‹場合ã?、CB01の状況を更新しなã�?
257 if( isUpdate ) {
258 complete( htcnoArr, tran );
259 }
260 }
261 catch( Throwable ex ) {
262 // エラーが発生したå?合ã?ãƒ??モンを停止しますã?
263 cancel();
264
265 if( tran != null ) {
266 tran.rollback();
267 tran.close();
268 tran = null; // エラー発生時は、接続を終äº?�—ますã?(次の状況更新でãƒ?ƒƒドロãƒ?‚¯になるたã‚?
269 }
270
271 if( htcnoArr != null && htcnoArr.length > 0 ) {
272 error( htcnoArr ); // エラー発生時はCB01>状態を9:エラーに更新
273 }
274
275 String header = "伝é?エラー?šDMN_NAME=[" + dmnName + "] , DMN_HOST=[" + HybsSystem.HOST_NAME + "]";
276 String errorSendto = null;
277 if( htcnoArr != null && htcnoArr.length > 0 ) {
278 header += " , HTCNO=[" + StringUtil.array2csv( htcnoArr ) + "]";
279 }
280 if( conf != null ) {
281 header += " , CONFIG=[" + conf.toString() + "]";
282 errorSendto = conf.getErrorSendto();
283 }
284
285 String errMsg = header + HybsSystem.CR + StringUtil.stringStackTrace( ex ) ;
286 System.out.println( errMsg );
287 LogWriter.log( errMsg );
288 sendMail( header, errMsg, errorSendto );
289 }
290 finally {
291 if( tran != null ) { tran.close(); }
292 }
293 }
294 }
295
296 /**
297 * こã?タイマã?タスクのcancel() メソãƒ?ƒ‰をオーバã?ライドしますã?
298 * HybsTimerTaskManager#cancelTask( int ) を実行しますã?
299 *
300 * @return スケジュールされてã�?‚‹ 1 回以上実行されなã�??合に true
301 * @see java.util.TimerTask#cancel()
302 */
303 @Override
304 public boolean cancel() {
305 running = false;
306 return super.cancel();
307 }
308
309 /**
310 * CB01を読み込みãƒ??タをé?列で返しますã?
311 *
312 * @param htcnoArr 読取対象の通番NO(配å?)
313 * @param tran トランザクション
314 *
315 * @return ãƒ??タ(配å?)
316 */
317 private String[] read( final String[] htcnoArr, final Transaction tran ) {
318 if( htcnoArr == null || htcnoArr.length == 0 ) { return new String[0]; }
319
320 String htcnos = StringUtil.array2csv( htcnoArr );
321 StringBuilder buf = new StringBuilder();
322 buf.append( "SELECT A.HTEXT" );
323 buf.append( " FROM CB01 A" );
324 buf.append( " WHERE A.HCDJ = '5'" );
325 buf.append( " AND A.HTCNO IN (" );
326 buf.append( htcnos );
327 buf.append( ") ORDER BY A.HTC, A.HTCNO" );
328
329 String[][] vals = DBUtil.dbExecute( buf.toString(),null,tran );
330 String[] rtn = new String[vals.length];
331 for( int i=0; i<vals.length; i++ ) {
332 rtn[i] = vals[i][0];
333 }
334 return rtn;
335 }
336
337 /**
338 * CB01のヘッãƒ??ãƒ??タの状況を2:抜å?済みに更新しますã?
339 *
340 * @param htcnoArr 更新対象の通番NO(配å?)
341 * @param tran トランザクション
342 */
343 private void complete( final String[] htcnoArr, final Transaction tran ) {
344 if( htcnoArr == null || htcnoArr.length == 0 ) { return; }
345
346 String htcnos = StringUtil.array2csv( htcnoArr );
347 StringBuilder buf = new StringBuilder();
348 buf.append( "UPDATE CB01 A" );
349 buf.append( " SET A.HCDJ = '2'" );
350 buf.append( " WHERE A.HCDJ = '1'" );
351 buf.append( " AND A.HTCNO IN (" );
352 buf.append( htcnos );
353 buf.append( ")" );
354
355 DBUtil.dbExecute( buf.toString(),null,tran );
356 }
357
358 /**
359 * CB01のヘッãƒ??ãƒ??タの状況を9:エラーに更新しますã?
360 *
361 * @param htcnoArr 更新対象の通番NO(配å?)
362 */
363 private void error( final String[] htcnoArr ) {
364 if( htcnoArr == null || htcnoArr.length == 0 ) { return; }
365
366 String htcnos = StringUtil.array2csv( htcnoArr );
367 StringBuilder buf = new StringBuilder();
368 buf.append( "UPDATE CB01 A" );
369 buf.append( " SET A.HCDJ = '9'" );
370 buf.append( " WHERE A.HCDJ in ('1','2')" ); // 既に実行PGで抜å?済みに更新されてã�?‚‹可能性があã‚?
371 buf.append( " AND A.HTCNO IN (" );
372 buf.append( htcnos );
373 buf.append( ")" );
374
375 DBUtil.dbExecute( buf.toString(),null,appInfo ); // エラー更新はトランザクションをå?けて処ç�?�™ã‚?
376 }
377
378 /**
379 * 伝é?定義マスタ及ã?旧伝é?DBから読み出したãƒ??タを管ç�?�—ますã?
380 */
381 private static class GE62CB01Data {
382
383 // トランザクションを生成するキーのセãƒ?ƒˆ(読取対象単ä½?
384 private final Set<String> tranSet = new LinkedHashSet<String>();
385 // トランザクションキー(読取対象)に対する、å?ç�?‚ー(読取対象+実行方æ³?実行対象)のセãƒ?ƒˆ
386 private final Map<String,Set<String>> tran2ExecKeySet = new LinkedHashMap<String,Set<String>>();
387 // 処ç�?‚ー(読取対象+実行方æ³?実行対象)に対する設定オブジェクトã?マッピング
388 private final Map<String,TransferConfig> execKey2Conf = new HashMap<String,TransferConfig>();
389 // 処ç�?‚ー(読取対象+実行方æ³?実行対象)に対する通番NO(配å?)のマッピング
390 private final Map<String,List<String>> execKey2HtcnoArr = new LinkedHashMap<String,List<String>>();
391
392 /**
393 * GE62及ã?CB01読取データを追åŠ?�—ますã?
394 *
395 * @param data GE62及ã?CB01読取データ
396 */
397 private void addData( final String[] data ) {
398 String kbRead = data[0];
399 String readObj = data[1];
400 String readPrm = data[2];
401 String kbExec = data[3];
402 String execDbid = data[4];
403 String execObj = data[5];
404 String execPrm = data[6];
405 String errorSendto = data[7];
406 String htcno = data[8];
407
408 String tranKey = readObj;
409 tranSet.add( tranKey );
410
411 // 読取対象 + 実行方æ³?+ 実行対象 単位に処ç�?¯¾象通番NOを集ç´?�™ã‚?
412 String execKey = readObj + kbExec + execObj;
413 Set<String> execKeySet = tran2ExecKeySet.get( tranKey );
414 if( execKeySet == null ) {
415 execKeySet = new LinkedHashSet<String>();
416 }
417 execKeySet.add( execKey );
418 tran2ExecKeySet.put( tranKey, execKeySet );
419
420 // 伝é?設定オブジェクトã?マッãƒ?
421 TransferConfig conf = execKey2Conf.get( execKey );
422 if( conf == null ) {
423 conf = new TransferConfig(
424 kbRead, readObj, readPrm
425 , kbExec, execDbid, execObj, execPrm
426 , errorSendto, HFROM, HTTP_PROXY_HOST, HTTP_PROXY_PORT );
427 execKey2Conf.put( execKey, conf );
428 }
429
430 // 通番NOのマッãƒ?
431 List<String> htcnoArr = execKey2HtcnoArr.get( execKey );
432 if( htcnoArr == null ) {
433 htcnoArr = new ArrayList<String>();
434 }
435 htcnoArr.add( htcno );
436 execKey2HtcnoArr.put( execKey, htcnoArr );
437 }
438
439 /**
440 * トランザクション生æ?キー(読取対象)のセãƒ?ƒˆを返しますã?
441 *
442 * @return トランザクション生æ?キー(読取対象)のセãƒ?ƒˆ
443 */
444 private Set<String> getTranSet() {
445 return tranSet;
446 }
447
448 /**
449 * トランザクション生æ?キー(読取対象)に対する処ç�?‚ー(読取対象+実行方æ³?実行対象)のセãƒ?ƒˆを返しますã?
450 *
451 * @param tranKey トランザクション生æ?キー(読取対象)
452 * @return トランザクション生æ?キー(読取対象)に対する処ç�?‚ー(読取対象+実行方æ³?実行対象)のセãƒ?ƒˆ
453 */
454 private Set<String> getExecKeySet( final String tranKey ) {
455 return tran2ExecKeySet.get( tranKey );
456 }
457
458 /**
459 * 処ç�?‚ー(読取対象+実行方æ³?実行対象)に対する設定オブジェクトを返しますã?
460 *
461 * @param execKey 処ç�?‚ー(読取対象+実行方æ³?実行対象)
462 * @return 設定オブジェクãƒ?
463 */
464 private TransferConfig getConfig( final String execKey ) {
465 return execKey2Conf.get( execKey );
466 }
467
468 /**
469 * 処ç�?‚ー(読取対象+実行方æ³?実行対象)に対する通番NO(配å?)を返しますã?
470 *
471 * @param execKey 処ç�?‚ー(読取対象+実行方æ³?実行対象)
472 * @return 通番NO(配å?)
473 */
474 private String[] getHtcno( final String execKey ) {
475 List<String> lst = execKey2HtcnoArr.get( execKey );
476 if( lst == null ) { return new String[0]; }
477 // else { return lst.toArray( new String[0] ); }
478 else { return lst.toArray( new String[lst.size()] ); }
479 }
480 }
481 }