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?あ?EVAL_BODY_BUFFERED:BODYを評価し?{@XXXX} を解析しま?
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 * ・LONG :すべてのスタ?トレース??を取得します?
417 * ・MEDIUM:org.opengion以下?パッケージのみスタ?トレース??を取得します?
418 * ・SHORT :メ?ージ部??み??を取得します?
419 * ・NONE :取得しません?
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 }