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.hayabusa.report2; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.List; 021// import java.io.File; // 8.0.0.1 (2021/10/08) 022 023import org.opengion.fukurou.system.ThrowUtil ; // 6.4.2.0 (2016/01/29) 024import org.opengion.hayabusa.common.HybsSystem; 025// import org.opengion.hayabusa.io.HybsFileOperationFactory; // 8.0.1.0 (2021/10/29) ExecThread → ExecProcess 026// import org.opengion.fukurou.model.FileOperation; // 8.0.0.1 (2021/10/08) 027// import org.opengion.fukurou.util.FileUtil; // 8.0.0.1 (2021/10/08) 028 029// import static org.opengion.fukurou.system.HybsConst.CR ; // 6.1.0.0 (2014/12/26) 030import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 031 032/** 033 * 帳票要求スレッドの本体です。 034 * 外部からスタックされたキューを先入れ先出しの順番に処理します。 035 * 036 * あるキューに対してエラーが発生すると、システムリソースのRETRY_COUNTで設定された回数再処理を試みます。 037 * この回数分エラーが発生した場合は、そのキューのみがアプリエラーとなります。 038 * 039 * このスレッドは一度生成されると、外部から明示的に終了の要求を起こさない限り生存し続けます。 040 * 終了するには、finish()メソッドを呼び出します。 041 * このメソッドが呼ばれると、内部でスタックしているキューは全てクリアされるため、その時点で 042 * 処理されているキューの処理が完了した時点で、スレッドが終了します。 043 * 044 * @og.group 帳票システム 045 * 046 * @version 4.0 047 * @author Hiroki.Nakamura 048 * @since JDK1.6 049 */ 050public class ExecThread extends Thread { 051 052 /** ステータスの enum */ 053 private enum Status { EXECUTE, WAIT } // 8.5.4.2 (2024/01/12) PMD 7.0.0 UnnecessarySemicolon 054// private static enum Status { EXECUTE, WAIT }; 055 private Status state = Status.EXECUTE; 056 057 private static final int RETRY_COUNT = HybsSystem.sysInt( "REPORT_RETRY_COUNT" ); 058 059 private final List<ExecQueue> queues = Collections.synchronizedList( new ArrayList<>() ); 060 061 private long threadStart ; 062 private long execStart ; 063 private long execEnd ; 064 private final boolean debug; // 4.3.0.0 (2008/07/15) デバッグの追加 065 066 /** 067 * コンストラクタ 068 * OOoへの接続を生成します。 069 * 070 * @param id スレッドID 071 */ 072 public ExecThread( final String id ) { 073 // threadStart = System.currentTimeMillis(); 074 // setName( id ); // スタックトレース時にスレッドIDを出すためにセット 075 this ( id , false ); 076 } 077 078 /** 079 * コンストラクタ 080 * OOoへの接続を生成します。 081 * 082 * @og.rev 4.3.0.0 (2008/07/15) デバッグフラグを追加します。 083 * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor 084 * @og.rev 8.5.3.2 (2023/10/13) JDK21対応。警告: デフォルトのコンストラクタの使用で、コメントが指定されていません 085 * 086 * @param id スレッドID 087 * @param debugFlag デバッグフラグ[true/false] 088 */ 089 public ExecThread( final String id , final boolean debugFlag ) { 090// super(); 091 super( id ); // 8.5.3.2 (2023/10/13) JDK21対応 092 threadStart = System.currentTimeMillis(); 093// setName( id ); // スタックトレース時にスレッドIDを出すためにセット 094 debug = debugFlag; // 4.2.5.0 (2008/06/26) デバッグ処理の追加 095 } 096 097 /** 098 * Map#compute で対応 出来るように、start() 実行後の 新規に作成した ExecThread を返します。 099 * 100 * @og.rev 6.4.3.3 (2016/03/04) Map#compute で対応する。 101 * 102 * @param id スレッドID 103 * @param debugFlag デバッグフラグ[true/false] 104 * @return startメソッド実行後の新規に作成したExecThreadオブジェクト 105 */ 106 public static final ExecThread startExecThread( final String id , final boolean debugFlag ) { 107 final ExecThread oet = new ExecThread( id, debugFlag ); 108 oet.start(); 109 return oet; 110 } 111 112 /** 113 * キューをスタックします。 114 * 115 * @og.rev 4.3.0.0 (2008/07/15) debug追加 116 * @param queue ExecQueueオブジェクト 117 * 118 * @return スタックが受け付けられたかどうか 119 */ 120 public boolean stackQueue( final ExecQueue queue ) { 121 queue.addMsg( "[INFO]QUEUE STACK:THREAD-ID=" + queue.getThreadId() + ",YKNO=" + queue.getYkno() ); 122 123 queues.add( queue ); 124 125 queue.setExecute(); 126 if( debug ) { queue.addMsg( "[INFO]QUEUE STACKED" ); } 127 128 synchronized( this ) { 129 if( state == Status.WAIT ) { 130 this.interrupt(); 131 if( debug ) { queue.addMsg( "[INFO]INTERRUPT" ); } 132 } 133 } 134 return true; 135 } 136 137 /** 138 * このスレッドの実行を開始します。Java仮想マシンは、このスレッドのrunメソッドを呼び出します。 139 * 140 * ここでは、実行されたときのメッセージを表示するために、Override しています。 141 * 142 * @og.rev 6.4.3.3 (2016/03/04) 処理メッセージを表示します。 143 */ 144 @Override // Thread 145 public void start() { 146 System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + getName() ); 147 super.start(); 148 } 149 150 /** 151 * スレッド本体 152 * スタックされたキューを順番に取り出し処理を行います。 153 * 154 * @og.rev 8.0.0.2 (2021/10/15) ローカルファイルとクラウドファイル間の移動 155 * @og.rev 8.0.1.0 (2021/10/29) ローカルファイルとクラウドファイル間の移動は、ExecProcess#output(String...) で行う。 156 */ 157 @Override 158 public void run() { 159 while( true ) { 160 synchronized( this ) { 161 while( queues.isEmpty() ) { 162 try { 163 state = Status.WAIT; 164 wait(); 165 } 166 catch( final InterruptedException ex ) { 167 state = Status.EXECUTE; 168 } 169 } 170 } 171 172 final ExecQueue queue = popQueue(); 173 if( queue != null ) { 174 if( "_FINALIZE".equals( queue.getYkno() ) ) { 175 if( debug ) { queue.addMsg( "[INFO]END" ); } 176 break; 177 } 178 else { 179 if( debug ) { queue.addMsg( "[INFO]QUEUE START" ); } 180 exec( queue ); 181 182// // 8.0.0.2 (2021/10/15) ローカルファイルとクラウドファイル間の移動 183// // 5.10.9.0 (2019/03/01) クラウドストレージ指定の場合は、アップロードする。 184// // 8.0.1.0 (2021/10/29) ローカルファイルとクラウドファイル間の移動は、ExecProcess#output(String...) で行う。 185// HybsFileOperationFactory.local2cloud( () -> new File( queue.getOutputName() ) ); 186// // final FileOperation cloudFile = HybsFileOperationFactory.create( queue.getOutputName() ); 187// // if( cloudFile.isCloud() ) { 188// // final File localFile = new File( queue.getOutputName() ); 189// // FileUtil.copy( localFile, cloudFile ); 190// // localFile.delete(); 191// // } 192 193 // System.out.println( queue.getMsg() ); 194 System.out.print( queue.getMsg() ); // 4.3.0.0 (2008/07/15) 195 } 196 } 197 } 198 } 199 200 /** 201 * スレッドを終了させるためのキューを追加します。 202 * 203 * このメソッドが呼ばれると、内部にスタックしているキューは全てクリアされます。 204 * 205 * @og.rev 6.4.3.3 (2016/03/04) 処理メッセージを表示します。 206 */ 207 public void finish() { 208 queues.clear(); 209 210 System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + getName() ); 211 212 final ExecQueue qu = new ExecQueue(); 213 qu.setYkno( "_FINALIZE" ); 214 stackQueue( qu ); 215 } 216 217 /** 218 * スレッドを終了させるためのキューを追加します。 219 * 220 * このメソッドでは、既にスタックされているキューはクリアされず、全て処理された後で、 221 * スレッドを終了します。 222 * 223 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 224 */ 225 public void finishAfterExec() { 226 final ExecQueue qu = new ExecQueue(); 227 qu.setYkno( "_FINALIZE" ); 228 stackQueue( qu ); 229 } 230 231 /** 232 * 帳票処理を行います。 233 * 234 * @og.rev 5.1.2.0 (2010/01/01) 256シートを超えた場合でも、正しく処理できるように対応 235 * 236 * @param queue ExecQueueオブジェクト 237 */ 238 private void exec( final ExecQueue queue ) { 239 execStart = System.currentTimeMillis(); 240 241 final ExecProcess oep = new ExecProcess( queue, debug ); 242 for( int i=0; i <= RETRY_COUNT; i++ ) { 243 try { 244 // 5.1.2.0 (2010/01/01) データが終わるまで処理を継続する。 245 while( !queue.isEnd() ) { 246 oep.process(); 247 } 248 queue.setComplete(); 249 break; 250 } 251 catch( final Throwable th ) { 252 queue.addMsg( "[ERROR] OCCURRED!" ); 253 queue.addMsg( ThrowUtil.ogStackTrace( th ) ); // 6.4.2.0 (2016/01/29) 254 255 if( i == RETRY_COUNT ) { 256 queue.addMsg( "[ERROR]UPTO RETRY COUNT!" ); 257 queue.setError(); 258 } 259 } 260 } 261 262 execEnd = System.currentTimeMillis(); 263 } 264 265 /** 266 * キューを取り出します。 267 * 268 * @return キュー 269 */ 270 private ExecQueue popQueue() { 271 return queues.remove( 0 ); 272 } 273 274 /** 275 * このクラスの文字列表現を返します。 276 * 277 * @og.rev 4.3.0.0 (2008/07/15) debugを追加 278 * 279 * @return 文字列表現 280 * @og.rtnNotNull 281 */ 282 @Override 283 public String toString() { 284 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ) 285 .append( "STATE=" ).append( state.toString() ) 286 .append( ", START=" ).append( HybsSystem.getDate( threadStart ) ) 287 .append( ", POOL=" ).append( queues.size() ) 288 .append( ", EXEC-START=" ).append( HybsSystem.getDate( execStart ) ) 289 .append( ", EXEC-END=" ).append( HybsSystem.getDate( execEnd ) ) 290 .append( ", DEBUG=" ).append( debug ); // 4.3.0.0 (2008/07/15) デバッグの追加 291 292 return buf.toString(); 293 } 294}