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 */ 016 package org.opengion.hayabusa.taglib; 017 018 import org.opengion.hayabusa.common.HybsSystem; 019 import org.opengion.hayabusa.common.HybsSystemException; 020 import org.opengion.hayabusa.common.BuildNumber; 021 import org.opengion.hayabusa.resource.UserInfo; 022 import org.opengion.hayabusa.resource.GUIInfo; 023 024 import org.opengion.fukurou.util.EnumType ; 025 import org.opengion.fukurou.util.ErrorMessage; 026 import org.opengion.fukurou.util.LogSender; 027 import org.opengion.fukurou.mail.MailTX ; 028 import org.opengion.fukurou.util.StringUtil ; 029 import static org.opengion.fukurou.util.StringUtil.nval ; 030 031 /** 032 * JSPのエラー発生時の処?行うタグです? 033 * 034 * JSPでは、エラー発生時に、エラーペ?ジに飛?す機?があります?現在のエンジンでは? 035 * common/error.jsp ペ?ジ?、??行って?すが、表示形式?整形、エラーメールの送信? 036 * ログへの出力?エラー??の表示(Exceptionをそのままユーザーに見せる?は良くな? 037 * などの、細かい対応が?です? 038 * ここでは、それらをタグ化して、属?で?できるようにしました? 039 * 040 * エラー発生時にメールでエラー?を飛?すことも可能です? 041 * これは、シス?パラメータの COMMON_MAIL_SERVER に、ERROR_MAIL_TO_USERS に送信します? 042 * ERROR_MAIL_TO_USERS が未設定?場合???信しません? 043 * 044 * @og.formSample 045 * ●形式? 046 * <og:error 047 * useMail = "[true|false]" メール送信可否を指定しま?初期値:true) 048 * logMsgType = "[LONG|MEDIUM|SHORT|NONE]" ログに書き込??ージの形式を??初期値:MEDIUM) 049 * viewMsgType = "[LONG|MEDIUM|SHORT|NONE|ALLNONE|TABLE]" 画面に表示するメ?ージの形式を??初期値:SHORT) 050 * /> 051 * 052 * ●body?あ? 053 * 054 * ●Tag定義?? 055 * <og:error 056 * useMail 【TAG】メール送信可否を指定しま?初期値:true) 057 * logMsgType 【TAG】ログに書き込??ージの形式を??初期値:MEDIUM) 058 * viewMsgType 【TAG】画面に書き込??ージの形式を??初期値:MEDIUM) 059 * debug 【TAG】デバッグ??を?力するかど?[true/false]を指定しま?初期値:false) 060 * skipPage 【TAG】エラーが発生した時に、以降?処?スキ??する?初期値:false[=スキ??しない]) 061 * > ... Body ... 062 * </og:error> 063 * 064 * ●使用? 065 * <og:error /> 066 * 067 * @og.rev 4.0.0.0 (2005/08/31) 新規作? 068 * @og.group エラー処? 069 * 070 * @version 4.0 071 * @author Kazuhiko Hasegawa 072 * @since JDK5.0, 073 */ 074 public class ErrorTag extends CommonTagSupport { 075 //* こ?プログラ??VERSION??を設定します? {@value} */ 076 private static final String VERSION = "5.1.8.0 (2010/07/01)" ; 077 078 private static final long serialVersionUID = 518020100701L ; 079 080 /** 081 * ログメ?ージタイ?属?として?できる選択肢を定義します? 082 */ 083 private static final EnumType<String> LOG_MSGTYPE = 084 new EnumType<String>( "ログメ?ージタイ? , "MEDIUM" ) 085 .append( "LONG" ,"詳細メ?ージを作?します?" ) 086 .append( "MEDIUM" ,"標準メ?ージを作?します?" ) 087 .append( "SHORT" ,"簡易メ?ージを作?します?" ) 088 .append( "NONE" ,"メ?ージを作?しません? ) ; 089 090 /** 091 * 表示メ?ージタイ?属?として?できる選択肢を定義します? 092 */ 093 private static final EnumType<String> VIEW_MSGTYPE = 094 new EnumType<String>( "表示メ?ージタイ? , "SHORT" ) 095 .append( "LONG" ,"詳細メ?ージを作?します?" ) 096 .append( "MEDIUM" ,"標準メ?ージを作?します?" ) 097 .append( "SHORT" ,"簡易メ?ージを作?します?" ) 098 .append( "NONE" ,"メ?ージを作?しません? ) 099 .append( "ALLNONE" ,"何も出力しません? ) 100 .append( "TABLE" ,"??ブル形式でエラーメ?ージのみを表示します?" ); 101 102 private final String MAIL_SERVER = nval( HybsSystem.sys( "COMMON_MAIL_SERVER" ),null ); 103 private final String MAIL_USERS = nval( HybsSystem.sys( "ERROR_MAIL_TO_USERS" ),null ) ; 104 // private final String FROM_USER = nval( HybsSystem.sys( "MAIL_DAEMON_DEFAULT_USER" ),"ENGINE" ) 105 // + "@" 106 // + nval( HybsSystem.sys( "ERROR_MAIL_TO_USERS" ),"DUMMY" ) ; 107 private final String FROM_USER = nval( HybsSystem.sys( "ERROR_MAIL_FROM_USER" ),"ENGINE@DUMMY" ); // 4.4.0.1 (2009/08/08) 108 109 private final String TITLE = "? + HybsSystem.sys( "SYSTEM_ID" ) + "? 110 + HybsSystem.sys( "GUI_TOP_TITLE" ) + "Error!" ; 111 112 private boolean useMail = true; 113 private String logMsgType = LOG_MSGTYPE.getDefault(); 114 private String viewMsgType = VIEW_MSGTYPE.getDefault(); 115 116 private boolean skipPage = false; // 4.1.0.0 (2008/01/11) 117 private String messageBody = null; // 4.1.0.0 (2008/01/11) 118 119 /** 120 * Taglibの開始タグが見つかったときに処??doStartTag() ?オーバ?ライドします? 121 * 122 * @og.rev 4.1.0.0 (2008/01/11) 新規作? 123 * 124 * @return 後続????( EVAL_BODY_BUFFERED ) 125 */ 126 @Override 127 public int doStartTag() { 128 return( EVAL_BODY_BUFFERED ); // Body を評価する? extends BodyTagSupport ? 129 } 130 131 /** 132 * Taglibのタグ本体を処??doAfterBody() ?オーバ?ライドします? 133 * 134 * @og.rev 4.1.0.0 (2008/01/11) 新規作? 135 * 136 * @return 後続????(SKIP_BODY) 137 */ 138 @Override 139 public int doAfterBody() { 140 messageBody = getBodyString(); 141 return(SKIP_BODY); 142 } 143 144 /** 145 * Taglibの終?グが見つかったときに処??doEndTag() ?オーバ?ライドします? 146 * 147 * @og.rev 4.0.0.0 (2005/12/31) UserInfo が存在しな??合?処?追?ます? 148 * @og.rev 4.1.0.0 (2008/01/11) ボディー部??メ?ージを表示する? 149 * @og.rev 5.0.0.4 (2009/08/28) ALLNONE追? 150 * @og.rev 5.1.8.0 (2010/07/01) ??ブル形式メ?ージ表示対? 151 * 152 * @return 後続???? 153 */ 154 @Override 155 public int doEndTag() { 156 debugPrint(); // 4.0.0 (2005/02/28) 157 158 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 159 buf.append( HybsSystem.CR ); 160 buf.append( "Title :" ).append( TITLE ).append( HybsSystem.CR ); 161 buf.append( "Version :" ).append( BuildNumber.ENGINE_INFO ).append( HybsSystem.CR ); 162 163 // 4.0.0 (2005/12/31) UserInfo が存在しな??合?処?追?ます? 164 String userId = null; 165 try { 166 UserInfo userInfo = getUser() ; 167 userId = userInfo.getUserID(); 168 buf.append( "ID=[" ).append( userId ); 169 // buf.append( "] NAME=[" ).append( userInfo.getJname() ); 170 buf.append( "] LOGIN=[" ).append( HybsSystem.getDate( userInfo.getLoginTime() ) ); 171 buf.append( "]" ); 172 } 173 catch( HybsSystemException ex ) { 174 buf.append( "User is null" ); 175 } 176 buf.append( HybsSystem.CR ); 177 178 GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY ); 179 buf.append( "GUI Information : " ); 180 final String guiId ; 181 if( guiInfo != null ) { 182 guiInfo.addErrorCount(); 183 guiId = guiInfo.getKey(); 184 buf.append( "KEY=[" ).append( guiId ); 185 buf.append( "] LABEL=[" ).append( guiInfo.getLabel() ); 186 buf.append( "]" ); 187 } 188 else { 189 guiId = null ; 190 buf.append( "GUI is null" ); 191 } 192 buf.append( HybsSystem.CR ); 193 194 Throwable th = pageContext.getException() ; 195 if( th != null ) { 196 buf.append( th.getMessage() ).append( HybsSystem.CR ); 197 } 198 buf.append( "-----" ).append( HybsSystem.CR ); 199 200 String errHeader = buf.toString(); 201 202 // ログ??出? 203 String logMsg = getStackTrace( th ,logMsgType ); 204 205 // 4.0.0 (2005/12/31) UserInfo が存在しな??合?処?追?ます? 206 LogSender log = new LogSender( userId ); 207 log.setGuiId( guiId ); 208 log.setMsgId( messageBody ); // 4.1.0.0 (2008/01/12) 209 log.error( errHeader ); 210 log.error( logMsg ); 211 log.flush(); 212 213 // メール送信 214 if( useMail && MAIL_SERVER != null && MAIL_USERS != null ) { 215 String[] to = StringUtil.csv2Array( MAIL_USERS ); 216 217 MailTX tx = new MailTX( MAIL_SERVER ); 218 // tx.setHost( MAIL_SERVER ); 219 tx.setFrom( FROM_USER ); 220 tx.setTo( to ); 221 tx.setSubject( TITLE ); 222 tx.setMessage( errHeader + logMsg ); 223 tx.sendmail(); 224 } 225 226 // 画面出? 227 // 5.0.0.2 (2009/09/15) ALLNONE以外?み出? 228 if( !"ALLNONE".equals( viewMsgType ) ) { 229 final String viewMsg ; 230 if( logMsgType.equals( viewMsgType ) ) { 231 viewMsg = errHeader + logMsg ; 232 } 233 // 5.1.8.0 (2010/07/01) ??ブル形式メ?ージ表示対? 234 else if( "TABLE".equals( viewMsgType ) ) { 235 viewMsg = getTableMsg( pageContext.getException() ); 236 } 237 else { 238 viewMsg = errHeader + getStackTrace( pageContext.getException() ,viewMsgType ); 239 } 240 jspPrint( viewMsg ); 241 } 242 243 // return(EVAL_PAGE); 244 if( skipPage ) { 245 return SKIP_PAGE; 246 } 247 else { 248 return EVAL_PAGE; 249 } 250 } 251 252 /** 253 * タグリブオブジェクトをリリースします? 254 * キャ?ュされて再利用される?で、フィールド?初期設定を行います? 255 * 256 */ 257 @Override 258 protected void release2() { 259 super.release2(); 260 useMail = true; 261 logMsgType = LOG_MSGTYPE.getDefault(); 262 viewMsgType = VIEW_MSGTYPE.getDefault(); 263 skipPage = false; // 4.1.0.0 (2008/01/11) 264 messageBody = null; // 4.1.0.0 (2008/01/11) 265 } 266 267 /** 268 * こ? Throwable オブジェクト?詳細メ?ージ??を返します? 269 * こ?クラスは、発生?の Throwable の StackTrace を?例外チェーン機? 270 * を利用して取得して?す? 271 * また?"org.opengion." を含?タ?トレースのみ、メ?ージとして追?ます? 272 * 273 * @og.rev 5.0.0.2 (2009/09/15) ALLNONE追? 274 * 275 * @param thr Throwableオブジェク? 276 * @param type スタ?トレースを行うタイ?LONG|MEDIUM|SHORT|NONE) 277 * 278 * @return メ?ージ 279 */ 280 private String getStackTrace( final Throwable thr,final String type ) { 281 // if( "NONE".equals( type ) ) { return ""; } 282 if( "NONE".equals( type ) || "ALLNONE".equals( type ) ) { return ""; } // 5.0.0.2 (2009/09/15) 283 284 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 285 StringBuilder trace = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 286 287 Throwable th = thr ; 288 while( th != null ) { 289 trace = getStackData( trace,th,type ); 290 291 // 同じメ?ージがあれ?、登録しな?? 292 String msg = th.getMessage(); 293 if( msg != null && buf.indexOf( msg ) < 0 ) { 294 buf.append( msg ).append( HybsSystem.CR ); 295 } 296 297 th = th.getCause(); 298 } 299 300 buf.append( trace.toString() ); 301 buf.append( "------------------------------------------------------" ).append( HybsSystem.CR ); 302 303 return buf.toString(); 304 } 305 306 /** 307 * タイプに応じたスタ?トレース???StringBuilder に追?て返します? 308 * スタ?トレース??は、type が?NONE では、作?しません? 309 * SHORT の場合?、???に現れた org.opengionパッケージのみを追?ます? 310 * 311 * @og.rev 5.0.0.2 (2009/09/15) ALLNONE追? 312 * 313 * @param buf 以前?エラーメ?ージ 314 * @param th スタ?トレースを取り?すThrowableオブジェク? 315 * @param type スタ?トレースを行うタイ?LONG|MEDIUM|SHORT|NONE) 316 * 317 * @return メ?ージ 318 */ 319 private StringBuilder getStackData( final StringBuilder buf,final Throwable th,final String type ) { 320 // type が?NONE は、引数の StringBuilder をそのまま返します? 321 // if( "NONE".equals( type ) ) { return buf; } 322 if( "NONE".equals( type ) || "ALLNONE".equals( type ) ) { return buf; } // 5.0.0.2 (2009/09/15) 323 324 String pkgKey = "org.opengion."; // type="SHORT,MEDIUM" の初期値 325 int stcCnt = 5; // type="MEDIUM" の初期値 326 327 if( "LONG".equals( type ) ) { 328 pkgKey = ""; 329 stcCnt = 100; 330 } 331 332 if( "SHORT".equals( type ) ) { 333 stcCnt = 0; 334 } 335 336 if( th != null ) { 337 int cnt = 0; 338 StackTraceElement[] trace = th.getStackTrace(); 339 for( int i=0; i<trace.length; i++ ) { 340 String msg = trace[i].toString(); 341 if( msg != null && buf.indexOf( msg ) < 0 ) { 342 if( msg.indexOf( pkgKey ) >= 0 ) { 343 buf.append( "\tat " ).append( msg ).append( HybsSystem.CR ); 344 if( "SHORT".equals( type ) ) { break; } 345 } 346 else if( cnt++ < stcCnt ) { 347 buf.append( "\tat " ).append( msg ).append( HybsSystem.CR ); 348 } 349 // else if( cnt++ == stcCnt ) { 350 // buf.append( "\t ......" ).append( HybsSystem.CR ); 351 // } 352 } 353 } 354 buf.append( "\t ... more ..." ).append( HybsSystem.CR ); 355 } 356 return buf; 357 } 358 359 /** 360 * こ? Throwable オブジェクト?エラーメ?ージ??をテーブル形式で返します? 361 * こ?形式では、スタ?トレースなどは表示されず?エラーメ?ージのみが表示されます? 362 * 363 * @og.rev 5.1.8.0 (2010/07/01) ??ブル形式メ?ージ表示対? 364 * 365 * @param thr Throwableオブジェク? 366 * 367 * @return メ?ージ 368 */ 369 private String getTableMsg( final Throwable thr ) { 370 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 371 Throwable th = thr; 372 ErrorMessage errMsgObj = new ErrorMessage( "System Error!" ); 373 while( th != null ) { 374 String msg = StringUtil.nval( th.getMessage(), "System Error(null)" ); 375 // 重??ージは登録しな?? 376 if( msg != null && buf.indexOf( msg ) < 0 ) { 377 buf.append( msg ); 378 // // org.opengion.hayabusa.common.HybsSystemException: xxx のパッケージ部??除外す? 379 // int pkgIdx = msg.indexOf( ':' ); 380 // if( pkgIdx >= 0 && msg.length() > pkgIdx ) { 381 // msg = msg.substring( pkgIdx + 1 ); 382 // } 383 errMsgObj.addMessage( 0,ErrorMessage.NG,"SYSERR",msg ); 384 } 385 th = th.getCause(); 386 } 387 return TaglibUtil.makeHTMLErrorTable( errMsgObj, getResource() ); 388 } 389 390 /** 391 * 【TAG】メール送信可否を指定しま?初期値:true)? 392 * 393 * @og.tag 394 * エラー発生時に管??にメールを?信するかど?を指定します? 395 * メールは、シス?パラメータの COMMON_MAIL_SERVER に、ERROR_MAIL_TO_USERS に送信します? 396 * ERROR_MAIL_TO_USERS が未設定?場合???信しません? 397 * 初期値は、true(送信する)です? 398 * 399 * @param flag メール送信可否 400 */ 401 public void setUseMail( final String flag ) { 402 useMail = nval( getRequestParameter( flag ),useMail ); 403 } 404 405 /** 406 * 【TAG】ログに書き込??ージの形式を??初期値:MEDIUM)? 407 * 408 * @og.tag 409 * ログ、およ?、メール送信時?メ?ージの形式を?します? 410 * エラー時?Exceptionは?層構?になっており、ルートまでさかのぼること? 411 * 可能です?また?通常は、スタ?とレース??より、エラーのプログラ? 412 * 特定することで、早く対応することが可能になります? 413 * メ?ージの形式には、LONG|MEDIUM|SHORT|NONE が指定できます? 414 * ボディー部?記述されたメ?ージは全ての場合で出力されます? 415 * ・ 416 * <lo>LONG :すべてのスタ?トレース??を取得します?<lo> 417 * <lo>MEDIUM:org.opengion以下?パッケージのみスタ?トレース??を取得します?<lo> 418 * <lo>SHORT :メ?ージ部??み??を取得します?<lo> 419 * <lo>NONE :取得しません?lo> 420 * 421 * 初期値は、MEDIUM です? 422 * 423 * @param logType ログに書き込??ージの形?[LONG|MEDIUM|SHORT|NONE] 424 * @see #setViewMsgType( String ) 425 */ 426 public void setLogMsgType( final String logType ) { 427 logMsgType = LOG_MSGTYPE.nval( logType ); 428 } 429 430 /** 431 * 【TAG】画面に書き込??ージの形式を??初期値:MEDIUM)? 432 * 433 * @og.tag 434 * 画面に表示するメ?ージの形式を?します? 435 * エラー時?Exceptionは?層構?になっており、ルートまでさかのぼること? 436 * 可能です?また?通常は、スタ?とレース??より、エラーのプログラ? 437 * 特定することで、早く対応することが可能になります? 438 * メ?ージの形式には、LONG|MEDIUM|SHORT|NONE|ALLNONE|TABLE が指定できます? 439 * ボディー部?記述されたメ?ージは全ての場合で出力されます? 440 * 441 * ・LONG :すべてのスタ?トレース??を取得します? 442 * ・MEDIUM :org.opengion以下?パッケージのみスタ?トレース??を取得します? 443 * ・SHORT :メ?ージ部??み??を取得します? 444 * ・NONE :取得しません? 445 * ・ALLNONE:ヘッ?表示しません? 446 * ・TABLE :??ブル形式でエラーメ?ージのみを表示します? 447 * 448 * 初期値は、SHORT です? 449 * 450 * @param viewType 画面に出力するメ?ージの形?[LONG|MEDIUM|SHORT|NONE|ALLNONE|TABLE] 451 * @see #setLogMsgType( String ) 452 */ 453 public void setViewMsgType( final String viewType ) { 454 viewMsgType = VIEW_MSGTYPE.nval( viewType ); 455 } 456 457 /** 458 * 【TAG】エラーが発生した時に、以降?処?スキ??する?初期値:false[=スキ??しない])? 459 * 460 * @og.tag 461 * エラーが発生した時に、以降?処?スキ??するかを設定します? 462 * trueが設定された場合?、以降?処?スキ??します? 463 * 464 * 初期値は、false(スキ??しな? です? 465 * 466 * @param flag 以降?処??スキ??する? 467 */ 468 public void setSkipPage( final String flag ) { 469 skipPage = nval( getRequestParameter( flag ),skipPage ); 470 } 471 472 /** 473 * ??時???を返します? 474 * 475 * @return こ?オブジェクト???表現?? 476 */ 477 @Override 478 public String toString() { 479 return org.opengion.fukurou.util.ToString.title( this.getClass().getName() ) 480 .println( "VERSION" ,VERSION ) 481 .println( "useMail" ,useMail ) 482 .println( "logMsgType" ,logMsgType ) 483 .println( "viewMsgType" ,viewMsgType) 484 .println( "messageBody" ,messageBody) 485 .println( "skipPage" ,skipPage) 486 .println( "COMMON_MAIL_SERVER" ,MAIL_SERVER ) 487 .println( "ERROR_MAIL_TO_USERS" ,MAIL_USERS ) 488 .println( "MAIL_DAEMON_DEFAULT_USER" ,FROM_USER ) 489 .println( "Other..." ,getAttributes().getAttribute() ) 490 .fixForm().toString() ; 491 } 492 }