001/* 002 * Copyright (c) 2017 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.fukurou.fileexec; 017 018import java.nio.file.Files; 019import java.nio.file.Path; 020import java.util.Arrays; 021 022import static org.opengion.fukurou.fileexec.CommandLine.GE70; // enum を簡素化して使用するための定義 023 024/** 025 * FileExec は、処理の中心で、デーモン一つに対応する処理開始クラスです。 026 * 027 *<pre> 028 * このクラスは、ファイルスキャンのフォルダ単位に、起動され、ファイルのイベントを処理します。 029 *</pre> 030 * 031 * @og.rev 7.0.0.0 (2017/07/07) 新規作成 032 * 033 * @version 7.0 034 * @author Kazuhiko Hasegawa 035 * @since JDK1.8, 036 */ 037public class FileExec { 038 private static final XLogger LOGGER= XLogger.getLogger( FileExec.class.getName() ); // ログ出力 039 040 /** システム依存の改行記号(String)。 */ 041 public static final String CR = System.getProperty("line.separator"); 042 043 private final GE71 tableGE71 ; 044 045 private final String systemId ; // システムID 046 private final String rsrvNo; // 予約番号 047 private final String execId; // 処理ID 048 049 private final String fileFltr ; // 検索条件 050 051 private final BasePath basePath ; // 各種パスを管理しているクラス 052 053 private final FileWatch fWatch ; // 取込フォルダをイベントで監視する 054 055 /** 056 * コマンドラインを引数に取るコンストラクター 057 * 058 * ファイルの監視を開始します。 059 * 060 * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加 061 * 062 * @param cmndLine コマンドラインオブジェクト 063 */ 064 public FileExec( final CommandLine cmndLine ) { 065 LOGGER.debug( () -> "② CommandLine=" + cmndLine ); 066 067 systemId = cmndLine.getValue( GE70.SYSTEM_ID ); // システムID 068 rsrvNo = cmndLine.getValue( GE70.RSRV_NO ); // 予約番号 069 execId = cmndLine.getValue( GE70.EXECID ); // 処理ID 070 fileFltr = cmndLine.getValue( GE70.FILE_FILTER ); // 検索条件 071 072 basePath = new BasePath( 073 cmndLine.getValue( GE70.DIR_BASE ) , // 取込ベースフォルダ 074 cmndLine.getValue( GE70.DIR_SUB ) , // 取込サブフォルダ 075 cmndLine.getValue( GE70.DIR_WORK ) , // 処理フォルダ(WORK) 076 cmndLine.getValue( GE70.DIR_BKUP_OK ) , // 処理済フォルダ(正常) 077 cmndLine.getValue( GE70.DIR_BKUP_NG ) ); // 処理済フォルダ(異常) 078 079 tableGE71 = new GE71( systemId,rsrvNo,execId ); 080 081 fWatch = new FileWatch( basePath.SUB_PATH ); // サブフォルダをイベントで監視する 082 } 083 084 /** 085 * このコマンドに対応するフォルダの監視を開始します。 086 * 087 * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加 088 */ 089 public void watchStart() { 090 LOGGER.debug( () -> "④ [watchStart()]" ); 091 092 fWatch.setEventKinds( FileWatch.CREATE , FileWatch.MODIFY ); 093 fWatch.setPathMatcher( new PathMatcherSet().addFileName( fileFltr ) ); // ファイルの検索条件 094 fWatch.callback( (event,fPath) -> checkFile( event,fPath ) ); 095 fWatch.start(); 096 } 097 098 /** 099 * このコマンドに対応するフォルダの監視を終了します。 100 * 101 * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加 102 */ 103 public void watchStop() { 104 LOGGER.debug( () -> "③ [watchStop()]" ); 105 106 fWatch.stop(); 107 } 108 109 /** 110 * 更新されたファイルをチェックします。 111 * 112 * ※ バックアップ処理してから、DB取り込み処理を行います。 113 * よって、DB登録処理中にエラーが発生した場合でも、バックアップ済みです 114 * 115 * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加 116 * 117 * @param event 発生イベントの名称 118 * @param filePath ファイルパス(相対パス) 119 */ 120 private void checkFile( final String event,final Path filePath ) { 121 Path bkup = null; 122 Path okFile = null; 123 Path ngFile = null; 124 String errMsg = ""; 125 126 try { 127 // FileUtil.stablePath は、書き込まれている途中かもしれないので、安定するまで待つ。 128 if( FileUtil.stablePath( filePath ) ) { 129 LOGGER.debug( () -> "⑤ event=" + event + " , Path=" + filePath ); 130 131 // ワークへ移動してから、DB取り込み処理を行います。 132 bkup = FileUtil.backup( filePath,basePath.WORK_PATH ); // WORKに移動します。 133 134 final String tmStr = StringUtil.getTimeFormat(); // 開始時刻 135 136 final AppliExec appli = AppliExec.newInstance( systemId,execId ); 137 138 final int suKekka = appli.exec( bkup ); 139 140 final String fgtKan ; // 取込完了フラグ 1:処理中 2:済 7:デーモンエラー 8:アプリエラー 141 if( suKekka >= 0 ) { 142 okFile = FileUtil.backup( bkup,basePath.OK_PATH ); // 処理済OKフォルダに移動 143 fgtKan = "2" ; 144 } 145 else { 146 ngFile = FileUtil.backup( bkup,basePath.NG_PATH ); // 処理済NGフォルダに移動 147 fgtKan = "8" ; 148 } 149 150 tableGE71.dbInsert( fgtKan , tmStr , filePath , okFile , ngFile , suKekka , errMsg ); 151 152 LOGGER.info( () -> "DAT execute. " + filePath + " , FGTKAN=" + fgtKan + " , kensu=" + suKekka ); 153 } 154 else { 155 // エラーにせず、保留にします。 156 LOGGER.info( () -> "checkFile Not stablePath. " + filePath ); 157 } 158 } 159 catch( final Throwable th ) { 160 // MSG0021 = 予期せぬエラーが発生しました。\n\tメッセージ=[{0}] 161 errMsg = MsgUtil.errPrintln( th , "MSG0021" , filePath ); 162 163 if( Files.exists( bkup ) ) { // WORKに移動するところまでは、成功しており、その後の、移動ができていない。 164 ngFile = FileUtil.backup( bkup,basePath.NG_PATH ); // 処理済NGフォルダに移動 165 } 166 167 tableGE71.dbInsert( "7" , StringUtil.getTimeFormat() , filePath , null , ngFile , -1 , errMsg ); // -1 は、エラーを示します。 168 } 169 } 170 171 /** 172 *このクラスの文字列表現を返します。 173 * 174 * @return クラスの文字列表現 175 */ 176 @Override 177 public String toString() { 178 return systemId + " , " + execId ; 179 } 180 181 /** 182 * GE71 実行結果をデータベースに書き込む内部クラスです。 183 */ 184 private static final class GE71 { 185 private static final String[] KEYS = new String[] { "SYSTEM_ID","RSRV_NO","EXECID","FGTKAN","TMSTR","TMEND" 186 , "FILE_IN","FILE_OK","FILE_NG","SUTORI ","ERRMSG " 187 , "DYSET","DYUPD" }; 188 private static final String[] CON_KEYS = new String[] { "FGJ","PGSET" ,"PGUPD" }; 189 private static final String[] CON_VALS = new String[] { "1" ,"FileExec","FileExec" }; 190 191 private static final String INS_QUERY = DBUtil.getInsertSQL( "GE71",KEYS,CON_KEYS,CON_VALS ); 192 193 private final String systemId ; // システムID 194 private final String rsrvNo; // 予約番号 195 private final String execId ; // 処理ID 196 197 /** 198 * GE71 データベースにインサート処理を行うクラスのコンストラクター 199 * 200 * @param sysId システムID 201 * @param rsNo 予約番号 202 * @param exId 処理ID 203 */ 204 public GE71( final String sysId , final String rsNo ,final String exId ) { 205 systemId = sysId ; 206 rsrvNo = rsNo ; 207 execId = exId; 208 } 209 210 /** 211 * データベースにインサート処理を行います。 212 * 213 * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加 214 * 215 * @param fgtKan 取込完了フラグ 216 * @param tmStr 開始時刻 217 * @param fIn 取込ファイルパス 218 * @param fOk 処理済OKファイルパス 219 * @param fNg 処理済NGファイルパス 220 * @param sutori 取込数 221 * @param errMsg エラーメッセージ 222 */ 223 public void dbInsert( final String fgtKan , final String tmStr , final Path fIn , final Path fOk , final Path fNg , final int sutori , final String errMsg ) { 224 final String NOW = StringUtil.getTimeFormat(); 225 226 final String fileIn = fIn == null ? "" : fIn.toString() ; 227 final String fileOk = fOk == null ? "" : fOk.toString() ; 228 final String fileNg = fNg == null ? "" : fNg.toString() ; 229 230 // GE71 テーブルのカラム 231 final String[] values = new String[] { 232 systemId // システムID SYSTEM_ID 233 , rsrvNo // 予約番号 RSRV_NO 234 , execId // 処理ID EXECID 235 , fgtKan // 取込完了フラグ FGTKAN 236 , tmStr // 開始時刻 TMSTR 237 , NOW // 完了時刻 TMEND 238 , fileIn // 取込ファイル FILE_IN 239 , fileOk // 処理済OKファイル FILE_OK 240 , fileNg // 処理済NGファイル FILE_NG 241 , String.valueOf( sutori ) // 取込件数 SUTORI 242 , errMsg // エラーメッセージ ERRMSG 243 , NOW // 登録日時 DYSET 244 , NOW // 更新日時 DYUPD 245 } ; 246 247 LOGGER.debug( () -> "⑥ GE71.dbInsert query=" + INS_QUERY + "\n\t values=" + Arrays.toString( values ) ); 248 249 DBUtil.execute( INS_QUERY , values ); 250 } 251 } 252}