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.taglib; 017 018import static org.opengion.fukurou.util.StringUtil.*; 019 020import java.io.IOException; 021import java.io.ObjectInputStream; 022import java.io.ObjectOutputStream; 023import java.util.ArrayList; 024import java.util.List; 025import java.util.Locale; 026 027import org.opengion.fukurou.db.DBUtil; 028import org.opengion.fukurou.db.Transaction; 029import org.opengion.fukurou.db.TransactionReal; 030import org.opengion.fukurou.util.ErrorMessage; 031import org.opengion.fukurou.util.StringUtil; 032import org.opengion.hayabusa.common.HybsSystem; 033import org.opengion.hayabusa.common.HybsSystemException; 034import org.opengion.hayabusa.db.DBColumn; 035import org.opengion.hayabusa.db.DBEditConfig; 036import org.opengion.hayabusa.db.DBTableModel; 037import org.opengion.hayabusa.db.Query; 038import org.opengion.hayabusa.db.QueryFactory; 039import org.opengion.hayabusa.resource.GUIInfo; 040 041/** 042 * データベースの検索を行うタグです。 043 * 044 * このタグの内容に、SQL文を記述します。 whereタグ、 andタグ を使うと引数に応じて 045 * 実行されるSQL文が異なります(使用例参照)。 046 * また、PL/SQLのSPで検索を行うときもこのタグを使います。 047 * SystemData の USE_SQL_INJECTION_CHECK が true か、quotCheck 属性が true の場合は、 048 * SQLインジェクション対策用のクォーティションチェックを行います。リクエスト引数に 049 * クォーティション(')が含まれると、エラーになります。 050 * 同様にUSE_XSS_CHECKがtrueか、xssCheck属性がtrueの場合は、 051 * クロスサイトススクリプティング(XSS)対策のためless/greater than signのチェックを行います。 052 * 053 * ※ このタグは、Transaction タグの対象です。 054 * 055 * @og.formSample 056 * ●形式: 057 * ・<og:query command="NEW" > 058 * SELECT文 059 * </og:query> 060 * ・<og:query command="NEW" names="・・・" queryType="JDBCErrMsg" > 061 * { call PL/SQL(?,?,?,? ) } 062 * </og:query> 063 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 064 * 065 * ●Tag定義: 066 * <og:query 067 * queryType 【TAG】Query を発行する為のクラスID(JDBC,JDBCCallable,JDBCErrMsg,JDBCUpdate)を指定します{@og.doc03Link queryType 初期値:JDBC}) 068 * command 【TAG】コマンド(NEW,RENEW)をセットします(PlsqlUpdateTag,UpdateTag の場合は、ENTRY) 069 * scope 【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session) 070 * maxRowCount 【TAG】(通常は使いません)データの最大読み込み件数を指定します (初期値:DB_MAX_ROW_COUNT[=1000])(0:[無制限]) 071 * skipRowCount 【TAG】(通常は使いません)データの読み始めの初期値を指定します 072 * displayMsg 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=]) 073 * overflowMsg 【TAG】検索データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました]) 074 * notfoundMsg 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした]) 075 * names 【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します 076 * stopZero 【TAG】検索結果が0件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する]) 077 * tableId 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 078 * dbid 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します 079 * trace 【TAG】引数の SQL 文を EXPLAIN PLAN を[true:行う/それ以外:行わない]を指定します(初期値:false) 080 * checkNames 【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します 081 * modifyType 【TAG】DB検索時の モディファイタイプを指定します[A:追加/C:更新/D:削除] 082 * quotCheck 【TAG】リクエスト情報の クォーティション(') 存在チェックを実施するかどうか[true/false]を設定します(初期値:USE_SQL_INJECTION_CHECK) 083 * stopError 【TAG】PLSQL/SQL処理エラーの時に処理を中止するかどうか[true/false]を設定します(初期値:true) 084 * dispError 【TAG】エラー時にメッセージを表示するか[true/false]を設定します。通常はstopErrorと併用(初期値:true) 085 * xssCheck 【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true]) 086 * mainTrans 【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true) 087 * caseKey 【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 088 * caseVal 【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 089 * caseNN 【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:true) 090 * caseNull 【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true) 091 * useBeforeHtmlTag 【TAG】 処理時間(queryTime)などの情報出力[true:有効/false:無効]を指定します(初期値:true) 092 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 093 * > ... Body ... 094 * </og:query> 095 * 096 * ●使用例 097 * <og:query command="NEW"> 098 * select PN,YOBI,NMEN,HINM from XX01 where PN = '{@PN}' order by PN 099 * </og:query> 100 * 101 * ・検索条件が入力された時({@PN}がNOT NULLのとき) 102 * 作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 where PN = 'AAA' order by PN 103 * ・検索条件が入力されなかった時({@PN}がNULLのとき) 104 * 作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 where PN = '' order by PN 105 * 106 * <og:query command="NEW"> 107 * select PN,YOBI,NMEN,HINM from XX01 108 * <og:where> 109 * <og:and value="PN = '{@PN}%'" /> 110 * <og:and value="YOBI like '{@YOBI}%'" /> 111 * </og:where> 112 * order by PN 113 * </og:query> 114 * 115 * ・検索条件が入力された時({@PN}がNOT NULLのとき) 116 * 作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 PN = 'AAA%' and YOBI like 'BBB%' order by PN 117 * ・検索条件が入力されなかった時({@PN}がNULLのとき) WHERE句がなくなる。 118 * 作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 order by PN 119 * 120 * 注意:WhereTagを使った場合、下のようにはなりません。 121 * select PN,YOBI,NMEN,HINM from XX01 PN = '' and YOBI like '%' order by PN 122 * 123 * <og:query command="NEW"> 124 * select PN,YOBI,NMEN,HINM from XX01 where PN="11111" 125 * <og:where startKey="and"> 126 * <og:and value="YOBI like '{@PN}%'" /> 127 * </og:where> 128 * order by PN 129 * </og:query> 130 * 131 * ・検索条件が入力された時({@YOBI}がNOT NULLのとき) 132 * 作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 PN = '11111' and YOBI like 'BBB%' order by PN 133 * ・検索条件が入力されなかった時({@YOBI}がNULLのとき) WHERE句がなくなる。 134 * 作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 PN = '11111' order by PN 135 * 136 * <og:query 137 * command = "NEW" 138 * names = "SYSTEM_ID,LANG,CLM,NAME_JA,LABEL_NAME,KBSAKU,USER.ID" 139 * checkNames = "CLM,NAME_JA" 140 * queryType = "JDBCErrMsg" 141 * displayMsg = ""> 142 * {call TYPE3B01.TYPE3B01(?,?,?,?)} 143 * </og:query> 144 * 145 * ・queryType に JDBCErrMsg を指定して、PL/SQL をコールできます。 146 * 引数は、names 属性をキーにリクエスト変数から読み込みます。 147 * ・checkNames にカラム名を指定すると、columns.valueSet による 148 * リクエスト変数の正規化を行います。 149 * 150 * @og.group DB検索 151 * @og.group DB登録 152 * 153 * @version 4.0 154 * @author Kazuhiko Hasegawa 155 * @since JDK5.0, 156 */ 157public class QueryTag extends CommonTagSupport { 158 //* このプログラムのVERSION文字列を設定します。 {@value} */ 159 private static final String VERSION = "5.6.5.3 (2013/06/28)" ; 160 161 private static final long serialVersionUID = 565320130628L ; 162 163 /** command 引数に渡す事の出来る コマンド 新規 {@value} */ 164 public static final String CMD_NEW = "NEW" ; 165 /** command 引数に渡す事の出来る コマンド 再検索 {@value} */ 166 public static final String CMD_RENEW = "RENEW" ; 167 /** command 引数に渡す事の出来る コマンド リスト */ 168 private static final String[] COMMAND_LIST = new String[] { CMD_NEW , CMD_RENEW }; 169 170 /** エラーメッセージID {@value} */ 171 protected static final String errMsgId = HybsSystem.ERR_MSG_KEY; 172 173 private String queryType = null; 174 // 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 175// private String dbid = "DEFAULT"; 176 private String dbid = null ; 177 protected transient DBTableModel table = null; 178 protected transient ErrorMessage errMessage = null; 179 protected String tableId = HybsSystem.TBL_MDL_KEY; 180 protected String command = CMD_NEW; 181 protected int skipRowCount = 0; 182 protected int maxRowCount = -1; 183 protected String sql = null; 184 protected int executeCount = -1; // 検索/実行件数 185 protected String names = null; 186 protected boolean outMessage = true; 187 protected int errCode = ErrorMessage.OK; 188 protected boolean quotCheck = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" ); // 4.0.0 (2005/08/31) 189 private boolean trace = false; // 4.0.0 (2005/01/31) 廃止 190 private boolean stopZero = false; 191 private String modifyType = null; // 3.8.5.1 (2006/05/08) modifyType 属性を追加します。 192// private String displayMsg = "MSG0033"; // 件検索しました。 193 protected String displayMsg = HybsSystem.sys( "VIEW_DISPLAY_MSG" ); 194 private String overflowMsg = "MSG0007"; // 検索結果が、制限行数を超えましたので、残りはカットされました。 195 private String notfoundMsg = "MSG0077"; // 対象データはありませんでした。 196 private boolean isMainTrans = true; // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し 197 198 // 3.5.4.7 (2004/02/06) 実行時間測定用のDIV要素を出力します。 199 protected long dyStart = 0; 200 // 4.3.3.0 (2008/09/22) PLSQL/SQL実行エラーの際に、処理を中止するかどうか。 201 protected boolean stopError = true; 202 203 // 5.9.26.1 (2017/11/10) 実行エラーの際に、エラーを画面に出力するかどうか。 204 protected boolean dispError = true; 205 206 private StringBuilder debugMsg = null; // 3.5.6.0 (2004/06/18) 207 208 // 3.8.0.5 (2005/08/20) リクエスト変数の正規化を行います。 209 private String checkNames = null; 210 211 // 3.8.5.3 (2006/08/07) トレース時のメッセージ文字列を保存しておきます。 212 private String traceMsg = null; 213 214 protected boolean xssCheck = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.0.0.2 (2009/09/15) 215 216 // 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。 217 private boolean useBeforeHtmlTag = true ; 218 219 // 5.10.2.1 (2018/08/18) where-andタグのplaceHolder情報を保持する 220 private transient List<String> listPlaceValue = null; 221 222 /** 223 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 224 * 225 * @og.rev 3.5.4.7 (2004/02/06) 実行時間測定用に、開始時刻を取得します。 226 * @og.rev 3.5.6.5 (2004/08/09) 暫定的に、DBTableModelを先行削除します。 227 * @og.rev 3.6.0.0 (2004/09/24) DBTableModel の先行削除は、scope="session" の場合のみ。 228 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。 229 * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応 230 * @og.rev 5.10.23.0 (2020/06/01) SKIPBODY時もstopZeroを動作させる7.2.5.0対応を入れておく 231 * 232 * @return 後続処理の指示 233 */ 234 @Override 235 public int doStartTag() { 236 // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応 237 if( useTag() ) { 238 dyStart = System.currentTimeMillis(); 239// if( ! check( command, COMMAND_LIST ) ) { return(SKIP_BODY); } 240 if( ! check( command, COMMAND_LIST ) ) { // 5.10.23.0 241 table = (DBTableModel)getObject( tableId ); 242 if( table != null ) { executeCount = table.getRowCount(); } 243 244 return SKIP_BODY ; 245 } 246 247 useMainTrans( isMainTrans ); // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し 248 startQueryTransaction( tableId ); // 3.6.0.8 (2004/11/19) 249 250 // 3.5.6.5 (2004/08/09) 削除するのは、セッションのオブジェクトでよい。 251 // 3.6.0.0 (2004/09/24) 削除するのは、scope="session" の場合のみ。 252 if( "session".equals( getScope() ) ) { 253 removeSessionAttribute( tableId ); 254 removeSessionAttribute( HybsSystem.VIEWFORM_KEY ); 255 } 256 257 return( EVAL_BODY_BUFFERED ); // Body を評価する。( extends BodyTagSupport 時) 258 } 259 return ( SKIP_BODY ); // Body を評価しない 260 } 261 262 /** 263 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 264 * 265 * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。 266 * @og.rev 3.6.0.8 (2004/11/19) エラー発生時に確実にリリースされるように try finally 追加 267 * @og.rev 3.8.5.3 (2006/08/07) USER.LASTSQL へのSQL文の保存は、実行前に行っておきます。 268 * @og.rev 3.8.6.3 (2006/11/30) SQL 文の前後のスペースを取り除きます。 269 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 270 * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更 271 * @og.rev 4.0.0.0 (2005/08/31) useQuotCheck() によるSQLインジェクション対策 272 * @og.rev 4.3.4.0 (2008/12/01) GE20(ユーザー定数)へ登録するかのフラグへの対応 273 * @og.rev 5.0.0.2 (2009/09/15) XSS対応 274 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。 275 * @og.rev 5.1.9.0 (2010/08/01) TransactionTag 対応。上位に TransactionTag があれば、そこからConnection をもらう。 276 * @og.rev 5.3.6.0 (2011/06/01) 集計、合計などのEdit機能に対応します。 277 * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更 278 * @og.rev 5.3.7.0 (2011/07/01) PL/SQLかつscope="request"で正しく出力するためqueryType,namesも保存する。 279 * @og.rev 5.3.8.0 (2011/08/01) Transaction発生箇所でclose() 280 * @og.rev 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更。 281 * @og.rev 5.6.5.3 (2013/06/28) LASTQUERYTYPE ⇒ LASTSQLTYPE 変更。 282 * 283 * @return 後続処理の指示(SKIP_BODY) 284 */ 285 @Override 286 public int doAfterBody() { 287 288 // 4.0.0 (2005/08/31) useQuotCheck() によるSQLインジェクション対策 289 useQuotCheck( quotCheck ); 290 // 5.0.0.2 (2009/09/15) XSS対策 291 useXssCheck( xssCheck ); 292 293 sql = getBodyString().trim(); 294 295 // 3.2.1.0 (2003/05/28) 最終SQL文を、UserInfo に、キャッシュしておく。 296// setUserInfo( "LASTSQL", sql ); 297 // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し 298 if( isMainTrans ) { 299 setUserInfo( "LASTSQL", sql, false ); 300 // 5.3.7.0 (2011/07/01) PL/SQLかつscope="request"で正しく出力するためqueryType,namesも保存する。 301// setUserInfo( "LASTQUERYTYPE", queryType, false ); 302 setUserInfo( "LASTSQLTYPE", queryType, false ); // 5.6.5.3 (2013/06/28) 303 setUserInfo( "LASTNAMES", names, false ); 304 } 305 306 Query query = QueryFactory.newInstance( queryType ); 307 Transaction tran = null; 308 try { 309 if( maxRowCount < 0 ) { 310 maxRowCount = sysInt( "DB_MAX_ROW_COUNT" ); 311 } 312 313 // 5.1.9.0 (2010/08/01) TransactionTag 対応 314// final Transaction tran ; 315 TransactionTag tranTag = (TransactionTag)findAncestorWithClass( this,TransactionTag.class ); 316 if( tranTag == null ) { 317// tran = new TransactionReal( dbid,getApplicationInfo() ); 318 tran = new TransactionReal( getApplicationInfo() ); // 5.3.7.0 (2011/07/01) 引数変更 319 } 320 else { 321 tran = tranTag.getTransaction(); 322 } 323 query.setTransaction( dbid,tran ); // 5.1.9.0 (2010/08/01) TransactionTag 対応 324 325 query.setSkipRowCount( skipRowCount ); 326 query.setMaxRowCount( maxRowCount ); 327// query.setConnectionID( dbid ); 328 query.setResourceManager( getResource() ); // 4.0.0 (2005/01/31) 329 330 if( trace ) { 331// traceMsg = traceQuery( sql ); 332 traceMsg = traceQuery( sql,tran ); // 5.1.9.0 (2010/08/01) TransactionTag 対応 333 // 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更 334// query.setMaxRowCount( 1 ); 335 return(SKIP_BODY); 336 } 337 query.setStatement( sql ); 338// query.setApplicationInfo( getApplicationInfo() ); // 3.8.7.0 (2006/12/15) 339 340 // 5.3.6.0 (2011/06/01) 集計、合計などのEdit機能に対応します。 341 if( isMainTrans ) { 342 String guikey = getGUIInfoAttri( "KEY" ); 343 String editName = getRequestValue( "editName" ); 344 DBEditConfig config = getUser().getEditConfig( guikey, editName ); 345 if( config != null ) { 346 query.setEditConfig( config ); 347 } 348 } 349 350 execute( query ); 351 352 executeCount = query.getExecuteCount(); 353 if( errCode < ErrorMessage.NG && executeCount >= 0 ) { // 異常以外の場合 354 table = query.getDBTableModel(); 355 // 3.8.5.1 (2006/05/08) modifyType 属性を追加します。 356 if( modifyType != null ) { 357 for( int row=0; row<executeCount; row++ ) { 358 table.setModifyType( row,modifyType ); 359 } 360 } 361 } 362 } 363 finally { 364// if( query != null ) { query.close(); } 365 QueryFactory.close( query ); 366 if( tran != null ) { tran.close(); } // 5.3.8.0 (2011/08/01) Transaction発生箇所でclose() 367 } 368 return(SKIP_BODY); 369 } 370 371 /** 372 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 373 * 374 * @og.rev 2.0.0.8 (2002/10/09) command="NEW" のときのみ、displayMsg を表示させます。 375 * @og.rev 2.1.1.4 (2002/11/25) デバッグ時に最終SQLをユーザー情報をセットするように変更。 376 * @og.rev 2.1.2.1 (2002/11/27) ErrorMessage をクリアしないように変更。 377 * @og.rev 3.1.1.0 (2003/03/28) JspWriter オブジェクトの使用箇所を、jspPrint() を使用するように変更。 378 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 379 * @og.rev 3.2.1.0 (2003/05/28) 最終SQL文を、UserInfo に、キャッシュしておく。 380 * @og.rev 3.3.3.3 (2003/08/06) 検索結果の件数を、"DB.COUNT" キーでリクエストにセットする。 381 * @og.rev 3.3.3.3 (2003/08/06) 検索結果を、"DB.ERR_CODE" キーでリクエストにセットする。 382 * @og.rev 3.5.4.7 (2004/02/06) 実行時間測定用のDIV要素を出力しておきます。 383 * @og.rev 3.5.4.9 (2004/02/25) 警告時に停止していましたが、継続処理させます。 384 * @og.rev 3.5.5.0 (2004/03/12) ErrorMessage オブジェクトを、query が成功した時にもクリアするように変更 385 * @og.rev 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用 386 * @og.rev 3.5.5.8 (2004/05/20) ErrorMessage オブジェクトを、コマンドが NEW の場合のみ、クリア 387 * @og.rev 3.5.6.0 (2004/06/18) debugMsg 属性を出力するように修正します。 388 * @og.rev 3.6.0.8 (2004/11/19) DBTableModel をセーブする時に、トランザクションチェックを行います。 389 * @og.rev 3.8.5.3 (2006/08/07) USER.LASTSQL へのSQL文の保存は、実行前に行っておきます。 390 * @og.rev 4.0.0.0 (2006/11/14) notfoundMsg 属性を追加。displayMsg は、VIEW_USE_DISPLAY_MSG で制御 391 * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel ) 392 * @og.rev 4.3.3.0 (2008/09/22) 属性 stopError の設定により、JSP処理を中止するかどうかを制御します。 393 * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応 394 * @og.rev 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。 395 * @og.rev 5.5.0.3 (2012/03/13) オーバーフローメッセージが存在しないときは、何もしない。(改行も入れない) 396 * @og.rev 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更。 397 * @og.rev 5.6.3.0 (2013/04/01) エラー時メッセージ変更 398 * @og.rev 5.9.16.1 (2017/11/10) dispErrorの動作追加 399 * @og.rev 5.10.2.2 (2018/08/24) 一部のエラーをjspPrintから標準のErrorMessageに変更 400 * 401 * @return 後続処理の指示 402 */ 403 @Override 404 public int doEndTag() { 405 debugPrint(); // 4.0.0 (2005/02/28) 406 // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応 407 if( !useTag() ) { return(EVAL_PAGE); } 408 409 if( trace ) { 410 jspPrint( traceMsg ); 411 return (SKIP_PAGE); // 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更。 412 } 413 414 String label = ""; // 4.0.0 (2005/11/30) 検索しなかった場合。 415 if( check( command, COMMAND_LIST ) ) { 416 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL ); 417 418 // 実行件数の表示 command="NEW" のときのみ、displayMsg を表示させます。 419 // 4.0.0 (2005/11/30) 出力順の変更。一番最初に出力します。 420// boolean useStatusBar = HybsSystem.sysBool( "VIEW_USE_DISPLAY_MSG" ); 421 if( CMD_NEW.equals( command ) ) { 422// if( useStatusBar && executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) { 423 if( executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) { 424 buf.append( executeCount ); 425// buf.append( getResource().getMessage( displayMsg ) ); 426 buf.append( getResource().getLabel( displayMsg ) ); 427 buf.append( HybsSystem.BR ); 428 } 429 else if( executeCount == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) { 430// buf.append( getResource().getMessage( notfoundMsg ) ); 431 buf.append( getResource().getLabel( notfoundMsg ) ); 432 buf.append( HybsSystem.BR ); 433 } 434 } 435 436 // 3.3.3.3 (2003/08/06) 検索結果の件数を、"DB.COUNT" キーでリクエストにセットする。 437 setRequestAttribute( "DB.COUNT" , String.valueOf( executeCount ) ); 438 // 3.3.3.3 (2003/08/06) 検索結果を、"DB.ERR_CODE" キーでリクエストにセットする。 439 setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) ); 440 441 // オーバーフロー時のメッセージを表示 442// if( table != null && table.isOverflow() ) { 443 // 5.5.0.3 (2012/03/09) オーバーフローメッセージが存在しないときは、何もしない。(改行も入れない) 444 if( table != null && table.isOverflow() && overflowMsg != null && overflowMsg.length() > 0 ) { 445// buf.append( getResource().getMessage( overflowMsg ) ); 446 buf.append( getResource().getLabel( overflowMsg ) ); 447 buf.append( HybsSystem.BR ); 448 } 449 450 // 5.10.2.2 (2018/08/24) 6.9.9.0 「ERR0041:検索処理中に割り込みの検索要求がありました」エラーを、標準のErrorMessageに追加するようにします。 451 if( table != null && ! commitTableObject( tableId, table ) ) { 452 if( errMessage == null ) { errMessage = new ErrorMessage( "QueryTag Query Error!" ); } 453 // ERR0041:検索処理中に割り込みの検索要求がありました。処理されません。 454 errMessage.addMessage( 0,ErrorMessage.NG,"ERR0041" ); 455 errCode = ErrorMessage.NG; 456 } 457 458 // 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用 459 String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource() ); 460 if( err != null && err.length() > 0 ) { 461 buf.append( err ); 462 setSessionAttribute( errMsgId,errMessage ); 463 } 464 else if( CMD_NEW.equals( command ) ) { // 3.5.5.8 (2004/05/20) 465 removeSessionAttribute( errMsgId ); 466 } 467 label = buf.toString(); 468 469 // 5.9.26.1 (2017/11/10) エラーメッセージをリクエスト変数で持つようにしておく 470 setRequestAttribute( "DB.ERR_MSG", label ); 471// // 5.10.2.2 (2018/08/24) 6.9.9.0 472// if( table != null && ! commitTableObject( tableId, table ) ) { 473// // 3.6.0.8 (2004/11/19) トランザクションチェックを行います。 474// // jspPrint( "QueryTag Query処理が割り込まれました。DBTableModel は登録しません。" ); 475// 476// // 5.6.4.0 (2013/04/01) リソースから出力するように対応 477// ErrorMessage errMsgObj = new ErrorMessage( "QueryTag Query Error!" ); 478// errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0041" ); 479// jspPrint( TaglibUtil.makeHTMLErrorTable( errMsgObj,getResource() ) ); 480// 481// return (SKIP_PAGE); 482// } 483 } 484 485 // 5.9.26.1 (2017/11/10) dispErrorで表示をコントロール 486 if( dispError ) { 487 jspPrint( label ); 488 } 489 490 // 3.5.4.9 (2004/02/25) 警告時に停止していましたが、継続処理させます。 491// int rtnCode = EVAL_PAGE; 492 final int rtnCode ; 493 if( errCode >= ErrorMessage.NG ) { // 異常 494 if( stopError ) { // 4.3.3.0 (2008/09/22) 属性 stopError の設定により、処理を中止するかを判断します。 495 rtnCode = SKIP_PAGE; 496 } 497 else { 498 rtnCode = EVAL_PAGE; 499 } 500 } 501 else { 502 // 件数0件かつ stopZero = true 503 if( executeCount == 0 && stopZero ) { 504 rtnCode = SKIP_PAGE; 505 } 506 else { 507 rtnCode = EVAL_PAGE; 508 } 509 } 510 511 // 3.5.4.7 (2004/02/06) 512 long dyTime = System.currentTimeMillis()-dyStart; 513 514 // 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。 515 if( useBeforeHtmlTag ) { 516 jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" ); // 3.5.6.3 (2004/07/12) 517 } 518 519 // 4.0.0 (2005/01/31) セキュリティチェック(データアクセス件数登録) 520 GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY ); 521 if( guiInfo != null ) { guiInfo.addReadCount( executeCount,dyTime,sql ); } 522 523 return( rtnCode ); 524 } 525 526 /** 527 * タグリブオブジェクトをリリースします。 528 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 529 * 530 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加 531 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 532 * @og.rev 3.5.4.7 (2004/02/06) 実行時間測定用に、dyStart を追加します。 533 * @og.rev 3.5.6.0 (2004/06/18) debugMsg 属性を追加します。 534 * @og.rev 3.8.0.5 (2005/08/20) checkNames 属性を追加します。 535 * @og.rev 3.8.5.1 (2006/05/08) modifyType 属性を追加します。 536 * @og.rev 3.8.5.1 (2006/05/08) traceMsg 属性(トレース時のメッセージ文字列)を追加します。 537 * @og.rev 4.0.0.0 (2005/08/31) quotCheck 属性の追加 538 * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更 539 * @og.rev 4.3.3.0 (2008/09/22) stopError 属性の追加 540 * @og.rev 5.0.0.2 (2009/09/15) XSS対応 541 * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。 542 * @og.rev 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。 543 * @og.rev 5.9.26.1 (2017/11/10) dispError追加 544 * @og.rev 5.10.2.1 (2018/08/18) プレースホルダ対応 545 * 546 */ 547 @Override 548 protected void release2() { 549 super.release2(); 550 tableId = HybsSystem.TBL_MDL_KEY; 551 queryType = null; 552// dbid = "DEFAULT"; 553 dbid = null; 554 command = CMD_NEW; 555 skipRowCount = 0; 556 maxRowCount = -1; 557 table = null; 558 sql = null; 559// displayMsg = "MSG0033"; // 件検索しました。 560 displayMsg = HybsSystem.sys( "VIEW_DISPLAY_MSG" ); 561 overflowMsg = "MSG0007"; // 検索結果が、制限行数を超えましたので、残りはカットされました。 562 notfoundMsg = "MSG0077"; // 対象データはありませんでした。 563 executeCount = -1; // 検索/実行件数 564 names = null; 565 outMessage = true; 566 trace = false; 567 errCode = ErrorMessage.OK; 568 errMessage = null; 569 stopZero = false; 570 stopError = true; // 4.3.3.0 (2008/09/22) 571 dyStart = 0; 572 debugMsg = null; // 3.5.6.0 (2004/06/18) 573 checkNames = null; // 3.8.0.5 (2005/08/20) 574 quotCheck = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" ); // 4.0.0 (2005/08/31) 575 modifyType = null; // 3.8.5.1 (2006/05/08) 576 traceMsg = null; // 3.8.5.3 (2006/08/07) 577 xssCheck = HybsSystem.sysBool( "USE_XSS_CHECK" ); // 5.0.0.2 (2009/09/15) 578 isMainTrans = true; // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し 579 useBeforeHtmlTag = true ; // 5.3.5.0 (2011/05/01) 580 dispError = true; // 5.9.26.1 (2017/11/10) 581 listPlaceValue = null; // 5.10.2.1 (2018/08/18) 582 } 583 584 /** 585 * Query を実行します。 586 * 587 * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更 588 * @og.rev 3.4.0.0 (2003/09/01) 登録エラー時のキーと値を表示するように変更。 589 * @og.rev 3.5.6.0 (2004/06/18) デバッグ情報出力用に、printDebug メソッドを追加。 590 * @og.rev 3.6.1.0 (2005/01/05) エラーコードによる commit/rollback の判断追加 591 * @og.rev 5.3.7.0 (2011/07/01) nameの判定にゼロ文字列を付加 592 * @og.rev 5.10.2.1 (2018/08/18) プレースホルダ対応 593 * 594 * @param query オブジェクト 595 */ 596 protected void execute( final Query query ) { 597 String[] nameArray = null; 598 String[] values = null; 599 try { 600// if( names == null ) { 601 if( names == null || names.length() == 0 ) { 602 // 5.10.2.1 (2018/08/18) 603 // query.execute(); 604 if(listPlaceValue != null && !listPlaceValue.isEmpty()) { 605 // listPlaceValueに値が存在する場合は、listPlaceValueの値を渡す 606 values = listPlaceValue.toArray(new String[listPlaceValue.size()]); 607 query.execute(values); 608 }else { 609 query.execute(); 610 } 611 } 612 else { 613 nameArray = StringUtil.csv2Array( names ); 614 // 5.10.2.1 (2018/08/18) 615// values = getRequest( nameArray ); 616 if(listPlaceValue != null && !listPlaceValue.isEmpty()) { 617 // listPlaceValueに値が存在する場合は、listPlaceValueの値を設定 618 values = listPlaceValue.toArray(new String[listPlaceValue.size()]); 619 }else { 620 values = getRequest( nameArray ); 621 } 622 623 // 3.5.6.0 (2004/06/18) デバッグ情報出力用 624 if( isDebug() ) { printDebug( nameArray,values ); } 625 626 query.execute( values ); 627 } 628 errCode = query.getErrorCode(); 629 errMessage = query.getErrorMessage(); 630 // 3.6.1.0 (2005/01/05) エラーコードによる commit/rollback の判断追加 631// if( query.getUpdateFlag() ) { 632 if( query.isUpdate() ) { 633 if( errCode < ErrorMessage.NG ) { // 異常以下の場合 634 query.commit(); 635 } 636 else { 637 query.rollback(); 638 } 639 } 640 } 641 catch( HybsSystemException ex ) { 642 query.rollback(); 643 644 // 4.0.0 (2005/02/28) エラー時の表示とデバッグ時の表示を統一する。 645 String errMsg = "DATABASE ERROR! " + HybsSystem.CR ; 646 if( nameArray != null ) { 647 printDebug( nameArray,values ); 648 errMsg += debugMsg; 649 } 650 throw new HybsSystemException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 651 } 652 finally { 653 if( query != null ) { query.close(); } 654 } 655 } 656 657 /** 658 * デバッグ用に、配列データを書き出します。 659 * 660 * @og.rev 3.5.6.0 (2004/06/18) 新規追加 661 * 662 * @param nms 引数 names の配列データ 663 * @param vals names に対応するリクエスト情報の配列 664 */ 665 private void printDebug( final String[] nms,final String[] vals ) { 666 if( debugMsg == null ) { debugMsg = new StringBuilder(); } 667 668 debugMsg.append( " names=[" ); 669 debugMsg.append( StringUtil.array2csv( nms ) ); 670 debugMsg.append( "]" ); 671 debugMsg.append( HybsSystem.CR ); 672 debugMsg.append( " values=[" ); 673 debugMsg.append( StringUtil.array2csv( vals ) ); 674 debugMsg.append( "]" ); 675 debugMsg.append( HybsSystem.CR ); 676 } 677 678 /** 679 * 名称配列を元に、リクエスト情報のデータを取得します。 680 * checkNames 属性に設定されているカラムがあれば、値を正規化します。 681 * 682 * @og.rev 3.8.0.5 (2005/08/20) リクエスト変数の正規化(checkNames)対応 683 * 684 * @param nameArray キーとなる名称の配列 685 * 686 * @return そのリクエスト情報の配列 687 */ 688 protected String[] getRequest( final String[] nameArray ) { 689 String[] rtn = new String[nameArray.length]; 690 691 for( int i=0; i<rtn.length; i++ ) { 692 rtn[i] = getRequestValue( nameArray[i] ); 693 694 // 3.8.0.5 (2005/08/20) checkNames があり、rtn[i] がある場合。 695 if( checkNames != null && checkNames.length() > 0 && rtn[i].length() > 0 ) { 696 if( ( "," + checkNames + "," ).indexOf( "," + nameArray[i] + "," ) >= 0 ) { 697 DBColumn dbColumn = getDBColumn( nameArray[i] ); 698 String val = dbColumn.valueSet( rtn[i] ); 699 if( val != null ) { rtn[i] = val; } 700 } 701 } 702 } 703 704 return rtn; 705 } 706 707 /** 708 * 子タグ(andタグ)でプレースホルダーを設定した時に利用するメソッドです。 709 * queryタグ内部のプレースホルダリストに追加します。 710 * 711 * @og.rev 5.10.2.1 (2018/08/18) 新規追加 712 * @param trg 追加分 713 */ 714 protected void addListPlaceValue(final String trg) { 715 if(listPlaceValue == null) { 716 // listTestの初期化(初期化時にnamesの値を設定する) 717 listPlaceValue = new ArrayList<String>(); 718 // namesをリストに追加 719 String[] nameArray = StringUtil.csv2Array( names ); 720 String[] values = getRequest( nameArray ); 721 722 for(int i=0; i<values.length; i++) { 723 listPlaceValue.add(values[i]); 724 } 725 } 726 727 // カンマで分割 728 String[] arrayTrg = StringUtil.csv2Array( trg ); 729 for(int i=0; i<arrayTrg.length; i++) { 730 // リクエストパラメータの値を変換して、リストに追加 731 listPlaceValue.add(getRequestParameter(arrayTrg[i])); 732 } 733 } 734 735 /** 736 * 【TAG】(通常は使いません)データの読み始めの初期値を指定します。 737 * 738 * @og.tag 739 * データベース自体の検索は,指定されたSQLの全件を検索しますが, 740 * DBTableModelのデータとしては、スキップ件数分は登録されません。 741 * サーバーのメモリ資源と応答時間の確保の為です。 742 * 743 * @param count 読み始めの初期値 744 */ 745 public void setSkipRowCount( final String count ) { 746 skipRowCount = nval( getRequestParameter( count ),skipRowCount ); 747 } 748 749 /** 750 * 【TAG】(通常は使いません)データの最大読み込み件数を指定します 751 * (初期値:DB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。 752 * 753 * @og.tag 754 * データベース自体の検索は,指定されたSQLの全件を検索しますが, 755 * DBTableModelのデータとして登録する最大件数をこの値に設定します。 756 * サーバーのメモリ資源と応答時間の確保の為です。 757 * 0 をセットすると、無制限(Integer.MAX_VALUE)になります。 758 * (初期値:ユーザー定数のDB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。 759 * 760 * @og.rev 5.5.8.5 (2012/11/27) 0を無制限として処理します。 761 * 762 * @param count 最大読み込み件数 763 * @see org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT 764 */ 765 public void setMaxRowCount( final String count ) { 766 maxRowCount = nval( getRequestParameter( count ),maxRowCount ); 767 if( maxRowCount == 0 ) { maxRowCount = Integer.MAX_VALUE ; } // 5.5.8.5 (2012/11/27) 768 } 769 770 /** 771 * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します 772 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。 773 * 774 * @og.tag 775 * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に 776 * 渡す場合に、通常は、session を利用します。その場合の登録キーです。 777 * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、 778 * この tableId 属性を利用して、メモリ空間を分けます。 779 * (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。 780 * 781 * @param id sessionに登録する時の ID 782 */ 783 public void setTableId( final String id ) { 784 tableId = nval( getRequestParameter( id ),tableId ); // 3.8.0.9 (2005/10/17) 785 } 786 787 /** 788 * 【TAG】Query を発行する為のクラスID(JDBC,JDBCCallable,JDBCErrMsg,JDBCUpdate)を指定します({@og.doc03Link queryType 初期値:JDBC})。 789 * 790 * @og.tag 791 * 検索を実行する手段は、Query インターフェースの実装クラスになります。 792 * このタグでは、Query.execute( String[] ) メソッドが呼ばれます。 793 * 例えば、ストアドプロシージャ等を実行する場合に、queryType="JDBCErrMsg" 794 * を指定することができます。 795 * 初期値は、"JDBC" です。 796 * queryType は、システムリソースの Query_**** 宣言の **** を与えます。 797 * これらは、Query インターフェースを継承したサブクラスである必要があります。 798 * 標準で、org.opengion.hayabusa.db 以下の Query_**** クラスが、Query_**** 宣言 と 799 * して、定義されています。 800 * 属性クラス定義の {@link org.opengion.hayabusa.db.Query Query} を参照願います。 801 * {@og.doc03Link queryType Query_**** クラス} 802 * 803 * @param id Query を発行する為の実クラス ID 804 * @see org.opengion.hayabusa.db.Query Queryのサブクラス 805 * @see org.opengion.hayabusa.db.Query#execute( String[] ) 806 */ 807 public void setQueryType( final String id ) { 808 queryType = getRequestParameter( id ); 809 } 810 811 /** 812 * 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します。 813 * 814 * @og.tag 815 * Queryオブジェクトを作成する時のDB接続IDを指定します。 816 * これは、システムリソースで、DEFAULT_DB_URL 等で指定している データベース接続先 817 * 情報に、XX_DB_URL を定義することで、 dbid="XX" とすると、この 接続先を使用して 818 * データベースにアクセスできます。 819 * 820 * @param id データベース接続ID 821 */ 822 public void setDbid( final String id ) { 823 dbid = nval( getRequestParameter( id ),dbid ); 824 } 825 826 /** 827 * 【TAG】コマンド(NEW,RENEW)をセットします(PlsqlUpdateTag,UpdateTag の場合は、ENTRY)。 828 * 829 * @og.tag 830 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される 831 * フィールド定数値のいづれかを、指定できます。 832 * 833 * @param cmd コマンド(public static final 宣言されている文字列) 834 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.QueryTag.CMD_NEW">コマンド定数</a> 835 */ 836 public void setCommand( final String cmd ) { 837 String cmd2 = getRequestParameter( cmd ); 838 if( cmd2 != null && cmd2.length() >= 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); } 839 } 840 841 /** 842 * 【TAG】検索結果が0件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])。 843 * 844 * @og.tag 845 * 初期値は、false(続行する)です。 846 * 847 * @param cmd 検索結果が0件のとき、[true:処理を中止する/false:続行する] 848 */ 849 public void setStopZero( final String cmd ) { 850 stopZero = nval( getRequestParameter( cmd ),stopZero ); 851 } 852 853 /** 854 * 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します 855 * (初期値:VIEW_DISPLAY_MSG[={@og.value org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG}])。 856 * 857 * @og.tag 858 * ここでは、検索結果の件数や登録された件数をまず出力し、 859 * その次に、ここで指定したメッセージをリソースから取得して表示します。 860 * 件数を表示させたい場合は、displayMsg = "MSG0033"[ 件検索しました] をセットしてください。 861 * 表示させたくない場合は, displayMsg = "" をセットしてください。 862 * (初期値:システム定数のVIEW_DISPLAY_MSG[={@og.value org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG}])。 863 * 864 * @param id ディスプレイに表示させるメッセージ ID 865 * @see org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG 866 */ 867 public void setDisplayMsg( final String id ) { 868 String ids = getRequestParameter( id ); 869 if( ids != null ) { displayMsg = ids; } 870 } 871 872 /** 873 * 【TAG】検索データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します 874 * (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました])。 875 * 876 * @og.tag 877 * 検索結果が、maxRowCount で設定された値より多い場合、何らかのデータは検索されず 878 * 切り捨てられたことになります。 879 * ここでは、displayMsg を表示した後、必要に応じて、このメッセージを表示します。 880 * 表示させたくない場合は, overflowMsg = "" をセットしてください。 881 * 初期値は、MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました]です。 882 * 883 * @param id ディスプレイに表示させるメッセージ ID 884 */ 885 public void setOverflowMsg( final String id ) { 886 String ids = getRequestParameter( id ); 887 if( ids != null ) { overflowMsg = ids; } 888 } 889 890 /** 891 * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。 892 * 893 * @og.tag 894 * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。 895 * 従来は、displayMsg と兼用で、『0 件検索しました』という表示でしたが、 896 * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。 897 * 表示させたくない場合は, notfoundMsg = "" をセットしてください。 898 * 初期値は、MSG0077[対象データはありませんでした]です。 899 * 900 * @param id ディスプレイに表示させるメッセージ ID 901 */ 902 public void setNotfoundMsg( final String id ) { 903 String ids = getRequestParameter( id ); 904 if( ids != null ) { notfoundMsg = ids; } 905 } 906 907 /** 908 * 【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します。 909 * 910 * @og.tag 911 * 複数ある場合は、カンマ区切り文字で渡します。 912 * names 属性は、queryType に応じて設定可否が異なりますので、ご注意ください。 913 * names なし:JDBC,JDBCUpdate 914 * names あり:JDBCCallable,JDBCErrMsg,JDBCUpdate 915 * (JDBCUpdateは、names 属性のあり/なし両方に対応しています。) 916 * 917 * @og.rev 3.0.1.3 (2003/03/11) names 属性に null で渡す場合のバグを修正 918 * 919 * @param nm 引数の名称(複数ある場合は、カンマ区切り文字) 920 */ 921 public void setNames( final String nm ) { 922 names = nval( getRequestParameter( nm ),names ); 923 } 924 925 /** 926 * 【TAG】検索結果のメッセージを表示する/しない[true/false]を指定します(初期値:true)。 927 * 928 * @og.tag 929 * 初期値は、表示する:true です。 930 * 931 * @param flag [true:表示する/それ以外:含めない] 932 */ 933 public void setOutMessage( final String flag ) { 934 outMessage = nval( getRequestParameter( flag ),outMessage ); 935 } 936 937 /** 938 * 【TAG】引数の SQL 文を EXPLAIN PLAN を[true:行う/それ以外:行わない]を指定します(初期値:false)。 939 * 940 * @og.tag 941 * 942 * ここでは、以下の処理を行います。 943 * 1.引数の SQL 文を画面に表示します。 944 * 2.引数の SQL 文を EXPLAIN PLAN した結果を、画面に表示します。 945 * なお、以前は、セッションのトレースを行っていましたが、その機能は、廃止いたします。 946 * 初期値は、行わない:false です。 947 * 948 * @param flag トレース [true:行う/それ以外:行わない] 949 */ 950 public void setTrace( final String flag ) { 951 trace = nval( getRequestParameter( flag ),trace ); 952 } 953 954 /** 955 * 【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します。 956 * 957 * @og.tag 958 * PL/SQLを利用する場合の引数にセットすべき データを、リクエスト変数の 959 * 値そのままではなく、カラムオブジェクトの valueSet メソッド経由で正規化 960 * した値を使用するようにします。 961 * 962 * @og.rev 3.8.0.5 (2005/08/20) 新規追加 963 * 964 * @param nm リクエスト変数の正規化を行うカラム 965 */ 966 public void setCheckNames( final String nm ) { 967 checkNames = nval( getRequestParameter( nm ),checkNames ); 968 } 969 970 /** 971 * 【TAG】DB検索時の モディファイタイプを指定します[A:追加/C:更新/D:削除]。 972 * 973 * @og.tag 974 * DB検索時に、そのデータをA(追加)、C(更新)、D(削除)のモディファイタイプを 975 * つけた状態にします。 976 * その状態で、そのまま、update する事が可能になります。 977 * 978 * @og.rev 3.8.5.1 (2006/05/08) 新規追加 979 * 980 * @param type DB検索時の モディファイタイプ [A:追加/C:更新/D:削除] 981 */ 982 public void setModifyType( final String type ) { 983 modifyType = nval( getRequestParameter( type ),modifyType ); 984 } 985 986 /** 987 * 【TAG】リクエスト情報の クォーティション(') 存在チェックを実施するかどうか[true/false]を設定します 988 * (初期値:USE_SQL_INJECTION_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_SQL_INJECTION_CHECK}])。 989 * 990 * @og.tag 991 * SQLインジェクション対策の一つとして、暫定的ではありますが、SQLのパラメータに 992 * 渡す文字列にクォーティション(') を許さない設定にすれば、ある程度は防止できます。 993 * 数字タイプの引数には、 or 5=5 などのクォーティションを使用しないコードを埋めても、 994 * 数字チェックで検出可能です。文字タイプの場合は、必ず (')をはずして、 995 * ' or 'A' like 'A のような形式になる為、(')チェックだけでも有効です。 996 * (') が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。 997 * 初期値は、SystemData#USE_SQL_INJECTION_CHECK です。 998 * 999 * @og.rev 4.0.0.0 (2005/08/31) 新規追加 1000 * 1001 * @param flag クォーティションチェック [true:する/それ以外:しない] 1002 */ 1003 public void setQuotCheck( final String flag ) { 1004 quotCheck = nval( getRequestParameter( flag ),quotCheck ); 1005 } 1006 1007 /** 1008 * 【TAG】リクエスト情報の HTMLTag開始/終了文字(><) 存在チェックを実施するかどうか[true/false]を設定します 1009 * (初期値:USE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。 1010 * 1011 * @og.tag 1012 * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。 1013 * (><) が含まれていたエラーにする(true)/かノーチェックか(false)を指定します。 1014 * (初期値:システム定数のUSE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}]) 1015 * 1016 * @og.rev 5.0.0.2 (2009/09/15) 新規追加 1017 * 1018 * @param flag XSSチェック [true:する/false:しない] 1019 * @see org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK 1020 */ 1021 public void setXssCheck( final String flag ) { 1022 xssCheck = nval( getRequestParameter( flag ),xssCheck ); 1023 } 1024 1025 /** 1026 * 【TAG】PLSQL/SQL処理エラーの時に処理を中止するかどうか[true/false]を設定します(初期値:true)。 1027 * 1028 * @og.tag 1029 * false(中止しない)に設定する場合、後続処理では、{@DB.ERR_CODE}の値により、 1030 * PLSQL/SQLの異常/正常終了によって分岐処理は可能となります。 1031 * 初期値は、true(中止する)です。 1032 * 1033 * @og.rev 4.3.3.0 (2008/09/22) 新規追加 1034 * 1035 * @param flag [true:中止する/false:中止しない] 1036 */ 1037 public void setStopError( final String flag ) { 1038 stopError = nval( getRequestParameter( flag ),stopError ); 1039 } 1040 1041 /** 1042 * 【TAG】PLSQL/SQL処理エラーの時にエラーを画面表示するか[true/false]を設定します(初期値:true)。 1043 * 1044 * @og.tag 1045 * false(表示しない)に設定する場合、後続処理では、{@DB.ERR_MSG}の値により、 1046 * 本来表示されるはずだったメッセージを取得可能です。 1047 * stopErrorと併用して、JSON形式でエラーを返す場合等に利用します。 1048 * 初期値は、true(表示する)です。 1049 * ※false指定の場合は件数や、overFlowメッセージ等も表示されなくなります。 1050 * 1051 * @og.rev 5.9.26.1 (2017/11/10) 新規追加 1052 * 1053 * @param flag [true:表示する/false:表示しない] 1054 */ 1055 public void setDispError( final String flag ) { 1056 dispError = nval( getRequestParameter( flag ),dispError ); 1057 } 1058 1059 1060 /** 1061 * 引数の SQL 文を EXPLAIN PLAN します。 1062 * 1063 * ここでは、以下の処理を行います。 1064 * 1.引数の SQL 文を画面に表示します。 1065 * 2.引数の SQL 文を EXPLAIN PLAN した結果を、画面に表示します。 1066 * なお、この処理は、ORACLE 専用処理です。 1067 * 1068 * @og.rev 3.8.5.3 (2006/08/07) 新規追加 1069 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定 1070 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。 1071 * @og.rev 5.5.3.4 (2012/06/19) getUserInfo は、キー部分だけで処理します。 1072 * 1073 * @param sql EXPLAIN PLANするSQL 文 1074 * @param tran Transactionオブジェクト 1075 * 1076 * @return トレース結果の文字列 1077 */ 1078// private String traceQuery( final String sql ) { 1079 private String traceQuery( final String sql , final Transaction tran ) { 1080// ApplicationInfo appInfo = getApplicationInfo(); 1081 1082// String userId = getUserInfo( "USER.ID" ) ; 1083 String userId = getUserInfo( "ID" ) ; // 5.5.3.4 (2012/06/19) getUserInfo は、キー部分だけで処理します。 1084 1085 String[] arg1 = new String[] { userId }; 1086// DBUtil.dbExecute( "DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = ?",arg1,appInfo,dbid ); 1087 DBUtil.dbExecute( "DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = ?",arg1,tran,dbid ); // 5.1.9.0 (2010/08/01) 1088 1089 String explan1 = "EXPLAIN PLAN SET STATEMENT_ID = '" + userId + "' FOR " + sql ; 1090// DBUtil.dbExecute( explan1,null,appInfo,dbid ); 1091 DBUtil.dbExecute( explan1,null,tran,dbid ); // 5.1.9.0 (2010/08/01) 1092 1093 String[] arg2 = new String[] { userId,userId,userId }; 1094// String explan2 = "SELECT LEVEL,LPAD(' ',LEVEL,' ') || RTRIM( OPERATION ) || ' ' ||" 1095// + " RTRIM( OPTIONS ) || ' ' || RTRIM( OBJECT_NAME )" 1096// + " FROM PLAN_TABLE" 1097// + " WHERE STATEMENT_ID = ?" 1098// + " CONNECT BY PRIOR ID = PARENT_ID" 1099// + " AND STATEMENT_ID = ?" 1100// + " START WITH ID = 0" 1101// + " AND STATEMENT_ID = ?" ; 1102 String explan2 = "select LEVEL as LVL" 1103 + ",lpad(' ',LEVEL,' ') || rtrim( OPERATION ) || ' ' || rtrim( OPTIONS ) || ' ' || rtrim( OBJECT_NAME ) as EXECUTION_PLAN" 1104 + ",OBJECT_NAME as OBJ_NAME" 1105 + ",DECODE(INSTR(OBJECT_TYPE,' '),0,OBJECT_TYPE,SUBSTR(OBJECT_TYPE,1,INSTR(OBJECT_TYPE,' ')-1)) as OBJ_TYPE" 1106 + ",OPTIMIZER as OPT" 1107 + ",COST as CST" 1108 + ",CARDINALITY as CARD" 1109 + ",BYTES as BYTE" 1110 + ",ACCESS_PREDICATES as ACCS" 1111 + ",FILTER_PREDICATES as FILTER" 1112 + " from PLAN_TABLE" 1113 + " where STATEMENT_ID = ?" 1114 + " start with ID = 0" 1115 + " and STATEMENT_ID = ?" 1116 + " connect by prior ID = PARENT_ID" 1117 + " and STATEMENT_ID = ?" ; 1118// String[][] plan = DBUtil.dbExecute( explan2,arg2,appInfo,dbid ); 1119// String[][] plan = DBUtil.dbExecute( explan2,arg2,tran,dbid ); // 5.1.9.0 (2010/08/01) 1120 1121// StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 1122// buf.append( "<pre>" ).append( sql ).append( "</pre>" ).append( HybsSystem.BR ); 1123// buf.append( "<table>" ); 1124// buf.append( "<tr class=\"row_h\"><th>LEVEL</th><th>EXECUTION_PLAN</th></tr>" ); 1125// for( int i=0; i<plan.length; i++ ) { 1126// buf.append( "<tr class=\"row_" ).append( i%2 ).append( "\">" ); 1127// buf.append( "<td>" ).append( plan[i][0] ).append( "</td>" ); 1128// buf.append( "<td><pre>" ).append( plan[i][1] ).append( "</td></tr>" ); 1129// } 1130// buf.append( "</table>" ).append( HybsSystem.BR ); 1131 1132 String[][] plan = DBUtil.dbExecute( explan2,arg2,tran,dbid,true ); // 5.5.3.4 (2012/06/19) ヘッダー情報も同時に取得する。 1133 1134 StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE ); 1135 buf.append( "<pre>" ).append( sql ).append( "</pre>" ).append( HybsSystem.BR ); 1136 buf.append( "<table>" ); 1137 // 1行目のヘッダーの出力 1138 int colsize = plan[0].length; 1139 buf.append( "<tr class=\"row_h\">" ); 1140 for( int j=0; j<colsize; j++ ) { 1141 buf.append( "<th>" ).append( plan[0][j] ).append( "</th>" ); 1142 } 1143 buf.append( "</tr>" ); 1144 1145 for( int i=1; i<plan.length; i++ ) { 1146 buf.append( "<tr class=\"row_" ).append( i%2 ).append( "\">" ); 1147 for( int j=0; j<colsize; j++ ) { 1148 if( j==1 ) { 1149 buf.append( "<td><pre>" ).append( plan[i][1] ).append( "</pre></td>" ); 1150 } 1151 else { 1152 buf.append( "<td>" ).append( plan[i][j] ).append( "</td>" ); 1153 } 1154 } 1155 buf.append( "</tr>" ); 1156 } 1157 buf.append( "</table>" ).append( HybsSystem.BR ); 1158 return buf.toString(); 1159 } 1160 1161 /** 1162 * 【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true)。 1163 * 1164 * @og.tag 1165 * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが 1166 * ファイルダウンロードの対象の表になります。 1167 * 1168 * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。 1169 * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい 1170 * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から 1171 * 除外することができます。 1172 * 1173 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 1174 * 1175 * @param flag メイントランザクションかどうか 1176 */ 1177 public void setMainTrans( final String flag ) { 1178 isMainTrans = nval( getRequestParameter( flag ),isMainTrans ); 1179 } 1180 1181 /** 1182 * 【TAG】 処理時間(queryTime)などの情報出力[true:有効/false:無効]を指定します(初期値:true)。 1183 * 1184 * @og.tag 1185 * Query で、検索する場合に、処理時間(queryTime)などの情報を出力していますが、 1186 * ViewForm で、CustomData などの 非HTML表示ビューを使用する場合、データとして、 1187 * 紛れ込んでしまうため、出力を抑制する必要があります。 1188 * true(有効)にすると、これらのHTMLが出力されます。false にすると、出力されません。 1189 * 初期値は、true(有効) です。 1190 * 1191 * @og.rev 5.3.5.0 (2011/05/01) 新規追加 1192 * 1193 * @param useTag 情報出力の有効/無効を指定 [true:有効/false:無効] 1194 */ 1195 public void setUseBeforeHtmlTag( final String useTag ) { 1196 useBeforeHtmlTag = nval( getRequestParameter( useTag ),useBeforeHtmlTag ); 1197 } 1198 1199 /** 1200 * シリアライズ用のカスタムシリアライズ書き込みメソッド 1201 * 1202 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 1203 * @serialData 一部のオブジェクトは、シリアライズされません。 1204 * 1205 * @param strm ObjectOutputStreamオブジェクト 1206 * @throws IOException 入出力エラーが発生した場合 1207 */ 1208 private void writeObject( final ObjectOutputStream strm ) throws IOException { 1209 strm.defaultWriteObject(); 1210 } 1211 1212 /** 1213 * シリアライズ用のカスタムシリアライズ読み込みメソッド 1214 * 1215 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。 1216 * 1217 * @og.rev 4.0.0.0 (2006/09/31) 新規追加 1218 * @serialData 一部のオブジェクトは、シリアライズされません。 1219 * 1220 * @param strm ObjectInputStreamオブジェクト 1221 * @see #release2() 1222 * @throws IOException シリアライズに関する入出力エラーが発生した場合 1223 * @throws ClassNotFoundException クラスを見つけることができなかった場合 1224 */ 1225 private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException { 1226 strm.defaultReadObject(); 1227 } 1228 1229 /** 1230 * このオブジェクトの文字列表現を返します。 1231 * 基本的にデバッグ目的に使用します。 1232 * 1233 * @return このクラスの文字列表現 1234 */ 1235 @Override 1236 public String toString() { 1237 return sql ; 1238 1239 // return org.opengion.fukurou.util.ToString.title( this.getClass().getName() ) 1240 // .println( "VERSION" ,VERSION ) 1241 // .println( "tableId" ,tableId ) 1242 // .println( "queryType" ,queryType ) 1243 // .println( "dbid" ,dbid ) 1244 // .println( "command" ,command ) 1245 // .println( "skipRowCount" ,skipRowCount ) 1246 // .println( "maxRowCount" ,maxRowCount ) 1247 // .println( "sql" ,sql ) 1248 // .println( "displayMsg" ,displayMsg ) 1249 // .println( "overflowMsg" ,overflowMsg ) 1250 // .println( "executeCount" ,executeCount ) 1251 // .println( "names" ,names ) 1252 // .println( "outMessage" ,outMessage ) 1253 // .println( "trace" ,trace ) 1254 // .println( "errCode" ,errCode ) 1255 // .println( "stopZero" ,stopZero ) 1256 // .println( "quotCheck" ,quotCheck ) 1257 // .println( "dyStart" ,dyStart ) 1258 // .println( "checkNames" ,checkNames ) 1259 // .println( "Other..." ,getAttributes().getAttribute() ) 1260 // .fixForm().toString() ; 1261 } 1262}