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 */ 016package org.opengion.plugin.daemon; 017 018import java.util.Arrays; 019import java.util.Date; 020import java.util.LinkedHashMap; 021import java.util.LinkedHashSet; 022import java.util.Map; 023import java.util.Set; 024 025import org.opengion.fukurou.db.DBUtil; 026import org.opengion.fukurou.mail.MailTX; 027import org.opengion.fukurou.transfer.TransferConfig; 028import org.opengion.fukurou.transfer.TransferProcess; 029import org.opengion.fukurou.util.ApplicationInfo; 030import org.opengion.fukurou.util.HybsTimerTask; 031import org.opengion.fukurou.util.LogWriter; 032import org.opengion.fukurou.util.StringUtil; 033import org.opengion.hayabusa.common.HybsSystem; 034import org.opengion.hayabusa.common.HybsSystemException; 035 036/** 037 * 【伝送システム】各読取方法、実行方法に応じて伝送処理を行うためのデーモンです。 038 * 039 * 読取、及び実行における具体的な処理については、{@link org.opengion.fukurou.transfer}パッケージ内の 040 * 各実装クラスのドキュメントを参照して下さい。 041 * 042 * なお、各処理の実行について、トランザクションは、読取対象の単位になります。 043 * 同じ読取対象で、異なる実行方法、実行対象を定義した場合、同じデータに対して複数回処理が行われます。 044 * しかし、この場合においても、トランザクションは読取対象の単位で生成されるため、複数回の処理の内、 045 * 1回でもエラーが発生した場合は、同じ読取対象でそれまでに処理した分についてもrollbackされます。 046 * 047 * 発生したエラーをメールで通知する場合は以下の設定を行う必要があります。 048 * [システムリソース] 049 * COMMON_MAIL_SERVER 050 * ERROR_MAIL_FROM_USER 051 * [伝送定義マスタ] 052 * エラー送信先 053 * ※伝送定義マスタ読取時にエラーが発生した場合は、システムリソースの"ERROR_MAIL_TO_USERS"で 054 * 設定さえたユーザーにメールが送信されます。 055 * 056 * ※処理中に何らかのエラーが1度でも発生した場合、このデーモンは停止します。 057 * 058 * このクラスは、HybsTimerTask を継承した タイマータスククラスです。 059 * startDaemon() がタイマータスクによって、呼び出されます。 060 * 061 * @og.rev 5.4.1.0 (2011/11/01) 伝送システム対応 062 * @og.group デーモン 063 * 064 * @version 5.0 065 * @author Hiroki Nakamura 066 * @since JDK6.0, 067 */ 068public class Daemon_Transfer extends HybsTimerTask { 069 //* このプログラムのVERSION文字列を設定します。 {@value} */ 070 private static final String VERSION = "5.5.5.1 (2012/08/07)" ; 071 072 // 伝送定義マスタ検索用SQL 073 private static final String GE62_SELECT = 074 "SELECT A.KBREAD,A.READOBJ,A.READPRM,A.KBEXEC,A.EXECDBID,A.EXECOBJ,A.EXECPRM,A.ERROR_SENDTO" + 075 " FROM GE62 A" + 076 " WHERE A.FGJ = '1'"; 077 078 // コネクションにアプリケーション情報を追記するかどうか指定 079 private static final boolean USE_DB_APPLICATION_INFO = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ; 080 081 // HTTP接続時のプロキシホスト 082 private static final String HTTP_PROXY_HOST = HybsSystem.sys( "HTTP_PROXY_HOST" ); 083 084 // HTTP接続時のプロキシポート 085 private static final int HTTP_PROXY_PORT = HybsSystem.sysInt( "HTTP_PROXY_PORT" ); 086 087 // 呼び出し元ホストコード 088 private static final String HFROM = HybsSystem.sys( "TRANSFER_HOST_CODE" ); 089 090 // ループカウンタを24回に設定 091 private static final int LOOP_COUNTER = 24; 092 093 private boolean running = true; 094 private int loopCnt = 0; 095 096 private String ge62Select = null; 097 private String dmnName = null; 098 099 private ApplicationInfo appInfo = null; 100 private boolean debug = false; 101 102 protected final String DBID = HybsSystem.sys( "RESOURCE_DBID" ); // 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応 103 104 /** 105 * このタイマータスクによって初期化されるアクションです。 106 * パラメータを使用した初期化を行います。 107 * 108 */ 109 @Override 110 public void initDaemon() { 111 debug = StringUtil.nval( getValue( "DEBUG" ),debug ); 112 113 dmnName = getName(); 114 115 StringBuilder buf = new StringBuilder(); 116 buf.append( GE62_SELECT ); 117 118 // システムIDは必須指定 119 String systemId = getValue( "SYSTEM_ID" ); 120 if( StringUtil.isNull( systemId ) ) { 121 String errMsg = "システムID方法は必須指定です。" ; 122 throw new HybsSystemException( errMsg ); 123 } 124 else { 125 buf.append( " AND A.SYSTEM_ID='" ).append( systemId ).append( "'" ); 126 } 127 128 // 読取方法は必須指定 129 String kbRead = getValue( "KBREAD" ); 130 if( StringUtil.isNull( kbRead ) ) { 131 String errMsg = "読取方法は必須指定です。" ; 132 throw new HybsSystemException( errMsg ); 133 } 134 else { 135 buf.append( " AND A.KBREAD='" ).append( kbRead ).append( "'" ); 136 } 137 138 // デーモングループは必須指定 139 String dmnGroup = getValue( "DMN_GRP" ); 140 if( StringUtil.isNull( dmnGroup ) ) { 141 String errMsg = "デーモングループは必須指定です。" ; 142 throw new HybsSystemException( errMsg ); 143 } 144 else { 145 buf.append( " AND A.DMN_GRP='" ).append( dmnGroup ).append( "'" ); 146 } 147 148 buf.append( " ORDER BY A.READOBJ,A.KBEXEC,A.EXECOBJ" ); 149 150 ge62Select = buf.toString() ; 151 152 if( debug ) { 153 System.out.println( "DMN_NAME=[" + dmnName + "]" ); 154 System.out.println( "QUERY=[" + ge62Select + "]" ); 155 } 156 157 if( USE_DB_APPLICATION_INFO ) { 158 appInfo = new ApplicationInfo(); 159 // ユーザーID,IPアドレス,ホスト名 160 appInfo.setClientInfo( systemId,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME ); 161 // 画面ID,操作,プログラムID 162 appInfo.setModuleInfo( "TransferDaemon",dmnName,dmnName ); 163 } 164 else { 165 appInfo = null; 166 } 167 } 168 169 /** 170 * タイマータスクのデーモン処理の開始ポイントです。 171 * 172 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策 173 */ 174 @Override 175 protected void startDaemon() { 176 if( loopCnt % LOOP_COUNTER == 0 ) { 177 loopCnt = 1; 178 System.out.println(); 179 System.out.print( toString() + " " + new Date() + " " ); 180 } 181 else { 182 System.out.print( "." ); 183 loopCnt++ ; 184 } 185 186 // 伝送DB読取 187 String[][] vals = null; 188 GE62Data ge62Data = new GE62Data(); 189 try { 190 vals = DBUtil.dbExecute( ge62Select,null,appInfo,DBID ); // 5.5.5.1 (2012/08/07) 191 if( vals != null && vals.length > 0 ) { 192 for( int row=0; running && row<vals.length; row++ ) { 193 ge62Data.addData( vals[row] ); 194 } 195 } 196 } 197 catch( Throwable ex ) { 198 String header = "伝送読取エラー:DMN_NAME=[" + dmnName + "] , DMN_HOST=[" + HybsSystem.HOST_NAME + "] , QUERY=[" + ge62Select + "]"; 199 String errMsg = header + HybsSystem.CR + StringUtil.stringStackTrace( ex ) ; 200 System.out.println( errMsg ); 201 LogWriter.log( errMsg ); 202 String errorSendto = HybsSystem.sys( "ERROR_MAIL_TO_USERS" ); 203 sendMail( header, errMsg, errorSendto ); 204 } 205 206 // 処理実行 207 // 読取対象の単位で処理を実行します。(トランザクションもこの単位になります) 208 for( String tranKey : ge62Data.getTranSet() ) { 209 TransferProcess proc = null; 210 try { 211 proc = new TransferProcess( ge62Data.getConfSet( tranKey ) ); 212 proc.setDmnName( dmnName ); 213 proc.setAppInfo( appInfo ); 214 if( debug ) { 215 proc.setDebug(); 216 } 217 218 proc.process(); 219 } 220 catch( Throwable ex ) { 221 // エラーが発生した場合はデーモンを停止します。 222 cancel(); 223 224 // 最後に処理した伝送設定オブジェクトを下にエラーを出力します。 225 String header = "伝送エラー:DMN_NAME=[" + dmnName + "] , DMN_HOST=[" + HybsSystem.HOST_NAME + "]"; 226 String errorSendto = null; 227 if( proc != null ) { // 5.5.2.6 (2012/05/25) findbugs対応 228 TransferConfig config = proc.getLastConfig(); 229 if( config != null ) { 230 header += " , CONFIG=[" + config.toString() + "]"; 231 errorSendto = config.getErrorSendto(); 232 } 233 } 234 235 String errMsg = header + HybsSystem.CR + StringUtil.stringStackTrace( ex ) ; 236 System.out.println( errMsg ); 237 LogWriter.log( errMsg ); 238 sendMail( header, errMsg, errorSendto ); 239 } 240 } 241 } 242 243 /** 244 * このタイマータスクのcancel() メソッドをオーバーライドします。 245 * HybsTimerTaskManager#cancelTask( int ) を実行します。 246 * 247 * @return スケジュールされている 1 回以上実行されない場合に true 248 * @see java.util.TimerTask#cancel() 249 */ 250 @Override 251 public boolean cancel() { 252 running = false; 253 return super.cancel(); 254 } 255 256 /** 257 * エラー情報のメール送信を行います。 258 * エラーメールは、システムパラメータ の COMMON_MAIL_SERVER(メールサーバー)と 259 * ERROR_MAIL_FROM_USER(エラーメール発信元)と、ERROR_MAIL_TO_USERS(エラーメール受信者) 260 * がすべて設定されている場合に、送信されます。 261 * 262 * @param inHeader ヘッダーメッセージ 263 * @param inErrMsg エラーメッセージ 264 * @param errorSendto エラー送信先 265 */ 266 protected void sendMail( final String inHeader, final String inErrMsg, final String errorSendto ) { 267 268 String host = HybsSystem.sys( "COMMON_MAIL_SERVER" ); 269 String from = HybsSystem.sys( "ERROR_MAIL_FROM_USER" ); 270 String[] to = StringUtil.csv2Array( errorSendto ); 271 272 if( host != null && from != null && to.length > 0 ) { 273 try { 274 MailTX tx = new MailTX( host ); 275 tx.setFrom( from ); 276 tx.setTo( to ); 277 tx.setSubject( inHeader ); 278 tx.setMessage( inErrMsg ); 279 tx.sendmail(); 280 } 281 catch( Throwable ex ) { 282 String errMsg = "エラー時メール送信に失敗しました。" + HybsSystem.CR 283 + " SUBJECT:" + inHeader + HybsSystem.CR 284 + " HOST:" + host + HybsSystem.CR 285 + " FROM:" + from + HybsSystem.CR 286 + " TO:" + Arrays.toString( to ) + HybsSystem.CR 287 + ex.getMessage(); 288 LogWriter.log( errMsg ); 289 LogWriter.log( ex ); 290 } 291 } 292 } 293 294 /** 295 * 伝送定義マスタから読み出したデータを管理します。 296 */ 297 private static class GE62Data { 298 299 // トランザクションを生成するキーのセット(読取対象単位) 300 private final Set<String> tranSet = new LinkedHashSet<String>(); 301 // トランザクションキー(読取対象)に対する、設定オブジェクトのセット 302 private final Map<String,Set<TransferConfig>> tran2ConfSet = new LinkedHashMap<String,Set<TransferConfig>>(); 303 304 /** 305 * GE62読取データを追加します。 306 * 307 * @param data GE62読取データ 308 */ 309 private void addData( final String[] data ) { 310 String kbRead = data[0]; 311 String readObj = data[1]; 312 String readPrm = data[2]; 313 String kbExec = data[3]; 314 String execDbid = data[4]; 315 String execObj = data[5]; 316 String execPrm = data[6]; 317 String errorSendto = data[7]; 318 319 String tranKey = readObj; 320 tranSet.add( tranKey ); 321 322 Set<TransferConfig> confSet = tran2ConfSet.get( tranKey ); 323 if( confSet == null ) { 324 confSet = new LinkedHashSet<TransferConfig>(); 325 } 326 TransferConfig conf = new TransferConfig( 327 kbRead, readObj, readPrm 328 , kbExec, execDbid, execObj, execPrm 329 , errorSendto, HFROM, HTTP_PROXY_HOST, HTTP_PROXY_PORT ); 330 confSet.add( conf ); 331 tran2ConfSet.put( tranKey, confSet ); 332 } 333 334 /** 335 * トランザクション生成キー(読取対象)のセットを返します。 336 * 337 * @return トランザクション生成キー(読取対象)のセット 338 */ 339 private Set<String> getTranSet() { 340 return tranSet; 341 } 342 343 /** 344 * トランザクション生成キー(読取対象)に対する設定オブジェクトのセットを返します。 345 * 346 * @param tranKey トランザクション生成キー(読取対象) 347 * @return 設定オブジェクトのセット 348 */ 349 private Set<TransferConfig> getConfSet( final String tranKey ) { 350 return tran2ConfSet.get( tranKey ); 351 } 352 } 353}