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.util.concurrent.ConcurrentMap; 019import java.util.concurrent.ConcurrentHashMap; 020import java.util.StringJoiner; 021import java.util.Arrays; 022import java.util.List; 023import java.nio.file.Path; 024 025import org.opengion.fukurou.util.StringUtil; 026 027/** 028 * AppliExec は、アプリケーションの実行を行う共通の処理クラスです。 029 * 030 *<pre> 031 * 032 * ここでは、GE72の処理IDに応じた方法で実行します。 033 * 034 *</pre> 035 * 036 * @og.rev 7.0.0.0 (2017/07/07) 新規作成 037 * 038 * @version 7.0 039 * @author Kazuhiko Hasegawa 040 * @since JDK1.8, 041 */ 042public final class AppliExec { 043 private static final XLogger LOGGER= XLogger.getLogger( AppliExec.class.getSimpleName() ); // ログ出力 044 045 /** GE72 テーブルのカラム定義の enum */ 046 public enum GE72 { 047// public static enum GE72 { 048 /** GE72 テーブルから検索するカラム名 */ 049// RUNTYPE,RUNPG,CLMS,PARAMS,DBID,TABLE_NAME,SHT_NOS,FILE_ENC,SKIP_CNT ; 050 /** GE72 カラム */ EXECID, 051 /** GE72 カラム */ RUNTYPE, 052 /** GE72 カラム */ RUNPG, 053 /** GE72 カラム */ CLMS, 054 /** GE72 カラム */ PARAMS, 055 /** GE72 カラム */ DBID, 056 /** GE72 カラム */ TABLE_NAME, 057 /** GE72 カラム */ SHT_NOS, 058 /** GE72 カラム */ FILE_ENC, 059 /** GE72 カラム */ SKIP_CNT ; // 7.2.1.0 (2020/03/13) EXECID 追加 060 061 /** order by で、開始日時(ST_TIME)順に処理されるようにしておきます。 */ 062 private static final String FROM_WHERE = " from GE72 where SYSTEM_ID=? and EXECID=? and FGJ='1'" ; // 1件のみのはず 063 064 /** 列挙子のCSV形式文字列 のキャッシュ */ 065 public static final String SELECT ; 066 static { 067 final StringJoiner sj = new StringJoiner( "," , "select " , FROM_WHERE ); 068 Arrays.stream( values() ).forEachOrdered( v -> sj.add( v.name() ) ); 069 SELECT = sj.toString(); 070 } 071 072 /** 列挙子の序数(カラムの並び順) */ 073 public final int NO ; 074 075 /** private コンストラクター */ 076 GE72() { NO = ordinal(); } 077// private GE72() { NO = ordinal(); } 078 } // 8.5.4.2 (2024/01/12) PMD 7.0.0 UnnecessarySemicolon 079 080 /** GE72()のユニークキーは、systemId + execId だが、GE70()のユニークキーは、systemId + rsrv_no */ 081 private static final ConcurrentMap<String,AppliExec> APP_EXEC_MAP = new ConcurrentHashMap<>(); 082 083 private final String[] ge72Data ; 084 085 private final RunExec runexec ; // これもキャッシュできますが、とりあえず動くまでは毎回作成します。 086 087 /** 088 * private コンストラクタ 089 * 090 * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加 091 * @og.rev 8.5.5.1 (2024/02/29) switch式の使用 092 * 093 * @param systemId システムID 094 * @param execId 処理ID 095 */ 096 private AppliExec( final String systemId , final String execId ) { 097 LOGGER.debug( () -> "⑥ systemId=" + systemId + " , execId=" + execId ); 098 099 final List<String[]> cmdRow = DBUtil.dbQuery( GE72.SELECT , systemId , execId ); 100 101 if( cmdRow.isEmpty() ) { 102 // MSG3001 = コマンドリストに、予約番号,取込ID,処理IDは必須です。[{0}] 103 throw MsgUtil.throwException( "MSG3001" , "SYSTEM_ID=" + systemId + " , EXECID=" + execId ); 104 } 105 106 ge72Data = cmdRow.get(0); // 1件のみのはず 107 final String type = ge72Data[GE72.RUNTYPE.NO]; 108 109 // 8.5.5.1 (2024/02/29) switch式の使用 110// final String key ; 111// switch( type ) { 112// case "0" : key = "NONE"; break; // なにもしない 113// case "1" : key = "DBIN"; break; // DB入力 114// // case "2" : key = "PLSQL"; break; // PL/SQLコール 115// case "3" : key = "BAT"; break; // BATファイルコール 116// // case "4" : key = "JSP"; break; // JSPファイルコール(URLコネクション) 117// default : key = null; break; // なにもしない(runTypeなしエラー) 118// } 119 final String key = switch( type ) { 120 case "0" -> "NONE"; // なにもしない 121 case "1" -> "DBIN"; // DB入力 122 // case "2" -> "PLSQL"; // PL/SQLコール 123 case "3" -> "BAT"; // BATファイルコール 124 // case "4" -> "JSP"; // JSPファイルコール(URLコネクション) 125 default -> null; // なにもしない(runTypeなしエラー) 126 }; 127 128 if( key == null ) { 129 // MSG3002 = RUNTYPEに対応するRunExec実装クラスがありません。[{0}] 130 throw MsgUtil.throwException( "MSG3002" , "RUNTYPE=" + type + " , systemId=" + systemId + " , execId=" + execId ); 131 } 132 133 runexec = (RunExec)StringUtil.newInstance( "org.opengion.fukurou.fileexec.RunExec_" + key ); 134 } 135 136 /** 137 * システムIDと処理IDから、対応するAppliExecオブジェクトを返します。 138 * 139 * AppliExecオブジェクトを、動的に作成し、システムID + 予約番号 をキーにキャッシュします。 140 * 141 * 何らかの Exception が、throw された場合は、null を返します。 142 * 143 * @og.rev 7.2.1.0 (2020/03/13) APP_EXEC_MAPのキーを、systemId + rsrv_no に変更します。 144 * 145 * @param systemId システムID 146 * @param rsrvNo 予約番号(文字列のまま扱います) 147 * @param execId 処理ID 148 * @return AppliDataオブジェクト(作成できなければ、null) 149 */ 150// public static AppliExec newInstance( final String systemId , final String execId ) { 151 public static AppliExec newInstance( final String systemId , final String rsrvNo , final String execId ) { 152// final String mapKey = systemId + "_" + execId ; 153 final String mapKey = systemId + "_" + rsrvNo ; 154 155 return APP_EXEC_MAP.computeIfAbsent( mapKey , key -> new AppliExec( systemId,execId ) ); 156 } 157 158 /** 159 * システムID + 予約番号 をキーにキャッシュからAppliExecオブジェクトを削除します。 160 * 161 * 新しい AppliExecオブジェクトを作成する際に、GE72 を再読み込みします。 162 * 何か定義変更を行った後、読み取りスレッドを停止すると同時に、キャッシュを削除すれば、 163 * 次回起動時には、DBの設定を再読み込みします。 164 * 165 * @og.rev 7.2.1.0 (2020/03/13) APP_EXEC_MAPのキーを、systemId + rsrv_no に変更します。 166 * 167 * @param systemId システムID 168 * @param rsrvNo 予約番号(文字列のまま扱います) 169 */ 170 public static void removeInstance( final String systemId , final String rsrvNo ) { 171 final String mapKey = systemId + "_" + rsrvNo ; 172 173 APP_EXEC_MAP.remove( mapKey ); 174 } 175 176 /** 177 * GE72.RUNTYPE に基づいて、各種処理を実行します。 178 * 179 * @og.rev 6.8.1.5 (2017/09/08) LOGGER.debug 情報の追加 180 * 181 * @param path 処理するファイルパス 182 * @return 処理件数(正は成功、マイナスは異常時の行番号) 183 */ 184 public int exec( final Path path ) { 185 return runexec.exec( path,ge72Data ) ; 186 } 187 188 /** 189 * GE72.RUNTYPE に基づいて、各種処理を実行します。 190 * 191 * @og.rev 7.2.1.0 (2020/03/13) 新規追加 192 * 193 * @param path 処理するファイルパス 194 * @param fgtkan 取込完了フラグ(0:取込なし , 1:処理中 , 2:済 , 7:デーモンエラー , 8:アプリエラー) 195 * @param errMsg エラーメッセージ 196 */ 197 public void endExec( final Path path , final String fgtkan , final String errMsg ) { 198 runexec.endExec( path,ge72Data,fgtkan,errMsg ) ; 199 } 200}