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.fukurou.util; 017 018import java.util.TimerTask; 019import java.util.Date; 020 021import java.util.Map; 022import java.util.HashMap; 023import java.util.concurrent.atomic.AtomicInteger; // 5.5.2.6 (2012/05/25) findbugs対応 024 025/** 026 * HybsTimerTask.java は、String 型キーにString型値を Map するクラスです。 027 * 028 * HTMLのPOST/GET等の受け渡しや、String型の引数が多い場合に効果があります。 029 * 特に、getHybsTimerTask( String[] param ) による属性リスト作成は、 030 * HTMLタグの属性定義を行う上で,非常に便利に利用できます。 031 * 032 * この実装は同期化されません。 033 * 034 * @version 4.0 035 * @author Kazuhiko Hasegawa 036 * @since JDK5.0, 037 */ 038public abstract class HybsTimerTask extends TimerTask implements Comparable<HybsTimerTask> { // 4.3.3.6 (2008/11/15) Generics警告対応 039 private static AtomicInteger counter = new AtomicInteger(); // 5.5.2.6 (2012/05/25) findbugs対応 040 041 private final int uniqKey ; // タイマータスクのユニークキー 042 private final long createTime = System.currentTimeMillis() ; // オブジェクトが生成された時刻 043 private String name = null; // タイマータスクの名称 044 private String comment = null; // タイマータスクの説明 045 // 3.2.2.0 (2003/05/31) HybsTimerTask に対して、設定値を渡せるように変更。 046 private Map<String,String> paramMap = null; // タイマータスクのパラメータ 3.6.0.7 (2004/11/06) 047 private String body = null; // タイマータスクのボディー要素 048 private String startTime = "000000"; // 24時間制の開始時刻 049 private String stopTime = "000000"; // 24時間制の終了時刻 050 private int startStop = 0; // 24時間制の日付またがりをチェック。 051 private boolean aliveFlag = true ; // 活きているかどうか 052 private int errorSleep = 0; // TimerTask がエラーのときのスリープ時間(s) 3.7.0.4 (2005/03/14) 053 054 /** 055 * デフォルトコンストラクター 056 * オブジェクトは、newInstance でのみ、生成されます。 057 * 058 * @og.rev 5.5.2.6 (2012/05/25) findbugs対応。staticフィールドへの書き込みに、AtomicInteger を利用します。 059 */ 060 public HybsTimerTask() { 061 // 4.3.4.4 (2009/01/01) 062 uniqKey = counter.getAndIncrement() ; // 5.5.2.6 (2012/05/25) findbugs対応 063 } 064 065 /** 066 * このタイマータスクによって実行されるアクションです。 067 * ここでは、エラートラップを入れていますので、サブクラスで 068 * 再定義できないように、final 化しています。 069 * サブクラスでは、stratDaemon() をオーバーライドしてください。 070 * 071 * @see java.util.TimerTask#run() 072 * @see #startDaemon() 073 */ 074 @Override 075 public final void run() { 076 try { 077 if( isExecution() ) { 078 startDaemon(); 079 } 080 } 081 catch (Throwable th) { 082 // 3.7.0.4 (2005/03/14) 083 if( errorSleep > 0 ) { 084 try { Thread.sleep( errorSleep * 1000L ); } 085 catch( InterruptedException ex ) { LogWriter.log( ex ); } 086 System.out.println( th.getMessage() ); 087 } 088 else { 089 cancel(); 090 throw new RuntimeException( th ); 091 } 092 } 093 } 094 095 /** 096 * このタイマータスクによって実行されるアクションです。 097 * run メソッドより呼ばれます。 098 * サブクラスでは、startDaemon() をオーバーライドしてください。 099 * 100 * @see #run() 101 */ 102 abstract protected void startDaemon() ; 103 104 /** 105 * このタイマータスクによって初期化されるアクションです。 106 * サブクラスでは、initDaemon() をオーバーライドしてください。 107 * 108 */ 109 public void initDaemon() { 110 // ここでは処理を行いません。 111 } 112 113 /** 114 * タイマータスクの名称(ユニークキー)を設定します。 115 * 116 * @param nm タイマータスクの名称 117 */ 118 public void setName( final String nm ) { 119 name = nm; 120 } 121 122 /** 123 * タイマータスクの名称(ユニークキー)を取得します。 124 * 125 * @return タイマータスクの名称 126 */ 127 public String getName() { 128 return name; 129 } 130 131 /** 132 * タイマータスクの説明を設定します。 133 * 134 * @param cmt タイマータスクの説明 135 */ 136 public void setComment( final String cmt ) { 137 comment = cmt; 138 } 139 140 /** 141 * タイマータスクの説明を取得します。 142 * 143 * @return タイマータスクの説明 144 */ 145 public String getComment() { 146 return comment; 147 } 148 149 /** 150 * このオブジェクトの内部ユニークキー値を返します。 151 * オブジェクト生成毎に、+1 されて、内部に持っています。 152 * 153 * @return オブジェクトの内部ユニークキー 154 */ 155 public int getUniqKey() { 156 return uniqKey; 157 } 158 159 /** 160 * このオブジェクトが生成された時刻をミリ秒で返します。 161 * オブジェクト生成時に、System.currentTimeMillis() の値を取得しています。 162 * 163 * @return オブジェクトが生成された時刻(ミリ秒) 164 */ 165 public long getCreateTime() { 166 return createTime; 167 } 168 169 /** 170 * 内部で使用するパラメータを設定します。 171 * 172 * 外部より、引数として渡されてきます。これを利用して、各サブシステムは、 173 * パラメーターを設定したり、初期化したり利用出来ます。 174 * 175 * @param map パラメータマップ 176 */ 177 public void setParameter( final Map<String,String> map ) { 178 if( map != null ) { 179 paramMap = new HashMap<String,String>( map ); 180 } 181 } 182 183 /** 184 * 内部で使用するパラメータのキーに対する値を取得します。 185 * 186 * 各サブシステムは、パラメーターを設定したり、初期化したり利用出来ます。 187 * 188 * @param key 引数のキー 189 * 190 * @return キーに対する値 191 */ 192 public String getValue( final String key ) { 193 if( paramMap != null && key != null ) { 194 return paramMap.get( key ); 195 } 196 197 return null; 198 } 199 200 /** 201 * 内部で使用するBody要素の値を設定します。 202 * 203 * 外部より、引数として渡されてきます。これを利用して、各サブシステムは、 204 * パラメーターを設定したり、初期化したり利用出来ます。 205 * 206 * @param body Body要素の値 207 */ 208 public void setBody( final String body ) { 209 this.body = body ; 210 } 211 212 /** 213 * 内部で使用するBody要素の値を取得します。 214 * 215 * 各サブシステムは、パラメーターを設定したり、初期化したり利用出来ます。 216 * 217 * @return Body要素の値 218 */ 219 public String getBody() { 220 return body ; 221 } 222 223 /** 224 * 24時間制(YYMMDD)の開始時刻を設定します。 225 * 226 * 指定時刻範囲内での実行のみ許可するように開始時刻を設定します。 227 * これは、タイマーで指定した間隔ごとにチェックを入れるので、チェック時間が 228 * 長い場合は、正確に開始時刻から始まるというものではありません。 229 * 初期値は、"000000" です。 230 * 231 * @param st 開始時刻 232 */ 233 public void setStartTime( final String st ) { 234 if( st == null || st.length() != 6 ) { 235 String errMsg = "startTime is inaccurate." + 236 "startTime=[" + st + "]" ; 237 throw new RuntimeException( errMsg ); 238 } 239 startTime = st ; 240 initStartStop(); 241 } 242 243 /** 244 * 24時間制(YYMMDD)の終了時刻を設定します。 245 * 246 * 指定時刻範囲内での実行のみ許可するように終了時刻を設定します。 247 * これは、タイマーで指定した間隔ごとにチェックを入れるので、チェック時間が 248 * 長い場合は、正確に終了時刻で終了するというものではありません。 249 * (終了時刻を越えてからの新規実行はありません。) 250 * 初期値は、"000000" です。 251 * 252 * @param st 終了時刻 253 */ 254 public void setStopTime( final String st ) { 255 if( st == null || st.length() != 6 ) { 256 String errMsg = "stopTime is inaccurate." + 257 "stopTime=[" + st + "]" ; 258 throw new RuntimeException( errMsg ); 259 } 260 stopTime = st ; 261 initStartStop(); 262 } 263 264 /** 265 * TimerTask がエラー発生時のスリープ時間(s) 設定します(初期値:0)。 266 * 267 * これは、予期せぬエラー(たとえば、データベースが落ちていたなど)が 268 * 発生したときでも、TimerTask を終了させずに、Sleep させて待機させる 269 * 事により、原因が除去された場合に、自動復帰するようにします。 270 * これに、0 を設定すると、エラー時に即 終了します。 271 * 設定は、秒で指定してください。 272 * 273 * @param erTime スリープ時間(s)(初期値:0) 274 */ 275 public void setErrorSleepSec( final int erTime ) { 276 errorSleep = erTime ; 277 } 278 279 /** 280 * 24時間制の開始/終了時刻の日付またがりを初期設定します。 281 * 282 * 開始時刻、終了時刻は、24時間制でしか指定できません。(日付指定できない) 283 * そのため、朝7:00から夜22:00などの 開始<終了 の時は単純な範囲チェックで 284 * 判断できますが、夜22:00から朝7:00に実行したい場合は、異なるチェックが 285 * 必要になります。 286 * また、開始時刻と終了時刻が未設定の場合や、同じ時刻の場合は、常に実行する必要が 287 * あります。これらのチェックを毎回行うのではなく、開始/終了時刻設定時にチェックして 288 * おきます。 289 * 290 */ 291 private void initStartStop() { 292 if( startTime == null || stopTime == null ) { 293 startStop = 0; 294 } 295 else { 296 startStop = startTime.compareTo( stopTime ); 297 } 298 } 299 300 /** 301 * 実行可能時間内かどうかを判定します。 302 * 303 * 設定された開始時刻と終了時刻に基づいて、現時刻で実行可能かどうか 304 * 判断します。 305 * 306 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 307 * 308 * @return (true:実行許可 false:停止) 309 */ 310 private boolean isExecution() { 311 boolean rtnFlag = false; 312 String time = HybsDateUtil.getDate( "HHmmss" ); // 5.5.7.2 (2012/10/09) HybsDateUtil を利用 313 314 if( startStop == 0 ) { 315 rtnFlag = true; 316 } 317 else if( startStop < 0 ) { 318 if( startTime.compareTo( time ) < 0 && 319 time.compareTo( stopTime ) < 0 ) { 320 rtnFlag = true; 321 } 322 } 323 else if( startStop > 0 ) { 324 if( startTime.compareTo( time ) < 0 || 325 time.compareTo( stopTime ) < 0 ) { 326 rtnFlag = true; 327 } 328 } 329 return rtnFlag; 330 } 331 332 /** 333 * このオブジェクトと指定されたオブジェクトの順序を比較します。 334 * このオブジェクトが指定されたオブジェクトより小さい場合は負の整数、 335 * 等しい場合はゼロ、大きい場合は正の整数を返します。 336 * 337 * @param other 比較対象の Object 338 * 339 * @return このオブジェクトが指定されたオブジェクトより小さい場合は負の整数、等しい場合はゼロ、大きい場合は正の整数 340 * @throws ClassCastException 指定されたオブジェクトの型が原因で、この Object と比較できない場合 341 */ 342 public int compareTo( final HybsTimerTask other ) { // 4.3.3.6 (2008/11/15) Generics警告対応 343 344 if( name == null && other.name != null ) { return -1; } 345 if( name != null && other.name == null ) { return 1; } 346 347 if( name != null && other.name != null ) { 348 int nmComp = name.compareTo( other.name ); 349 if( nmComp != 0 ) { return nmComp; } 350 } 351 352 return uniqKey - other.uniqKey ; 353 } 354 355 /** 356 * このオブジェクトの文字列表現を返します。 357 * 基本的にデバッグ目的に使用します。 358 * 359 * @return このクラスの文字列表現 360 */ 361 @Override 362 public String toString() { 363 return name + " [" + uniqKey + "]"; 364 } 365 366 /** 367 * このオブジェクトと他のオブジェクトが等しいかどうかを示します。 368 * 369 * @param object 比較対象の参照オブジェクト 370 * 371 * @return 引数に指定されたオブジェクトとこのオブジェクトが等しい場合は true、そうでない場合は false 372 */ 373 @Override 374 public boolean equals( final Object object ) { 375 if( object == null || !getClass().equals( object.getClass() ) ) { return false; } 376 if( !super.equals( object ) ) { return false; } 377 378 HybsTimerTask other = (HybsTimerTask)object; 379 return uniqKey == other.uniqKey ; 380 } 381 382 /** 383 * オブジェクトが生存しているかどうかを判定します。 384 * 385 * @return 生存しているかどうか。true:生存 / false:キャンセル済み 386 */ 387 public boolean isAlive() { 388 return aliveFlag ; 389 } 390 391 /** 392 * オブジェクトのハッシュコード値を返します。 393 * 394 * @return このオブジェクトのハッシュコード値 395 */ 396 @Override 397 public int hashCode() { 398 return uniqKey ; 399 } 400 401 /** 402 * このタイマータスクのcancel() メソッドをオーバーライドします。 403 * 404 * @return キャンセルが正常に終了できたかどうか 405 * @see java.util.TimerTask#cancel() 406 */ 407 @Override 408 public boolean cancel() { 409 if( aliveFlag ) { 410 System.out.println(); 411 System.out.println( toString() + " " + new Date() + " Stoped" ); 412 aliveFlag = false; // cancelTask を呼ぶ前に必ず『false』にしておく。 413 } 414 return super.cancel(); 415 } 416}