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 org.opengion.hayabusa.common.HybsSystem; 019import org.opengion.hayabusa.common.HybsSystemException; 020import org.opengion.hayabusa.resource.GUIInfo; 021import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 022import org.opengion.fukurou.util.ArraySet; // 6.4.3.4 (2016/03/11) 023 024import static org.opengion.fukurou.util.StringUtil.nval ; 025 026import jakarta.servlet.ServletRequest ; 027import jakarta.servlet.http.HttpSession ; 028 029import java.util.Set; // 6.4.3.4 (2016/03/11) 030import java.util.Map; 031import java.util.HashMap; 032 033/** 034 * 戻るリンクで戻る場合に使用する、検索時の request 情報をキャッシュするタグです(通常はquery.jsp に組込み)。 035 * 036 * requestタグをキャッシュすることにより、 再検索時や、各画面遷移時の項目の持ち回りを行います。 037 * command = "NEW" で、キャッシュし、"RENEW" で、取り出します。 038 * 暫定的にこのタグは、共通JSPファイルに設定し、HTMLそのもののキャッシュ制御も 039 * 行うように設定しています。 040 * 041 * @og.formSample 042 * ●形式:<og:requestCache cacheKey="[・・・]" /> 043 * ●body:なし 044 * 045 * ●Tag定義: 046 * <og:requestCache 047 * cacheKey 【TAG】キャッシュするサブキーを指定します(初期値:"") 048 * action 【TAG】アクション(SET,DELETE)をセットします 049 * keys 【TAG】リンク先に渡すキーを指定します 050 * vals 【TAG】keys属性に対応する値をCSV形式で複数指定します 051 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 052 * /> 053 * 054 * ●使用例 055 * <og:requestCache 056 * cacheKey="{@GUI.KEY}" キャッシュするサブキーを指定します。 057 * /> 058 * 059 * @og.group 画面制御 060 * 061 * @version 4.0 062 * @author Kazuhiko Hasegawa 063 * @since JDK5.0, 064 */ 065public class RequestCacheTag extends CommonTagSupport { 066 /** このプログラムのVERSION文字列を設定します。 {@value} */ 067 private static final String VERSION = "7.0.1.0 (2018/10/15)" ; 068 private static final long serialVersionUID = 701020181015L ; 069 070 private static final String CACHE_KEY = HybsSystem.REQ_CACHE_KEY; 071 072 /** command 引数に渡す事の出来る アクションコマンド ニュー {@value} */ 073 public static final String CMD_NEW = "NEW" ; 074 /** command 引数に渡す事の出来る アクションコマンド レニュー {@value} */ 075 public static final String CMD_RENEW = "RENEW" ; 076 /** command 引数に渡す事の出来る アクションコマンド イニット {@value} */ 077 public static final String CMD_INIT = "INIT" ; 078 /** command 引数に渡す事の出来る アクションコマンド リセット {@value} */ 079 public static final String CMD_RESET = "RESET" ; // 3.5.5.0 (2004/03/12) 追加 080 081 // 3.8.8.0 (2006/12/22) 082 /** action 引数に渡す事の出来る アクション 設定 {@value} */ 083 public static final String ACT_SET = "SET" ; 084 /** action 引数に渡す事の出来る アクション 削除 {@value} */ 085 public static final String ACT_DELETE = "DELETE" ; 086 087 // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 088 private static final Set<String> ACTION_SET = new ArraySet<>( ACT_SET , ACT_DELETE ); 089 090 private String cacheKey = ""; 091 private String action ; 092 private String[] keys ; 093 private String[] vals ; 094 095 /** 096 * デフォルトコンストラクター 097 * 098 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 099 */ 100 public RequestCacheTag() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 101 102 /** 103 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 104 * 105 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 106 * @og.rev 3.1.1.2 (2003/04/04) 継承元を、CommonTagSupport から TagSupport に変更する。 107 * @og.rev 3.1.3.0 (2003/04/10) Cache-Control ヘッダーのセットを削除します。 108 * @og.rev 3.1.6.0 (2003/04/24) キャッシュすべき値を、キー毎に指定できるように、cacheKey 属性を追加。 109 * @og.rev 3.1.7.0 (2003/05/02) command=INIT または、null のときに、キャッシュを削除するように変更する。 110 * @og.rev 3.1.7.0 (2003/05/02) command=INIT または、null のときに、キャッシュを削除するように変更する。 111 * @og.rev 3.1.8.0 (2003/05/16) BACK_GAMENID のキャッシュの設定先を変更する。 112 * @og.rev 3.5.1.0 (2003/10/03) GAMENID 情報を取得し、backGamenIdSetメソッドに渡すように変更。 113 * @og.rev 3.7.0.3 (2005/03/01) BACK_ROW 情報を取得し、backGamenIdSetメソッドに渡すように変更。 114 * @og.rev 4.0.1.0 (2007/12/17) BackAddress対応 115 * 116 * @return 後続処理の指示 117 */ 118 @Override 119 public int doEndTag() { 120 debugPrint(); // 4.0.0 (2005/02/28) 121 // request をキャッシュするタグなので、直接取り込む。 122 final ServletRequest request = pageContext.getRequest(); 123 final String command = request.getParameter( "command" ); 124 final String backGamenId = request.getParameter( "BACK_GAMENID" ); 125 final String gamenId = request.getParameter( "GAMENID" ); // 3.5.1.0 (2003/10/03) 126 final String backRow = request.getParameter( "BACK_ROW" ); // 3.7.0.3 (2005/03/01) 127 final String backAdrs = request.getParameter( "BACK_ADDRESS" ); // 4.0.1.0 (2007/12/17) 128 129 commandExec( command,request ); 130 backGamenIdSet( command,backGamenId,gamenId,backRow,backAdrs ); // 4.0.1.0 (2007/12/17) 131 132 return EVAL_PAGE ; // ページの残りを評価する。 133 } 134 135 /** 136 * タグリブオブジェクトをリリースします。 137 * 138 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 139 * 140 * @og.rev 3.5.5.3 (2004/04/09) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 141 * @og.rev 3.8.8.0 (2006/12/22) action,keys,vals 追加 142 * 143 */ 144 @Override 145 protected void release2() { 146 super.release2(); 147 cacheKey = ""; 148 action = null; 149 keys = null; 150 vals = null; 151 } 152 153 /** 154 * アクションを実行します。 155 * アクションは,指定のアクションコマンドに対応する処理を入力データに 156 * 対して行います。 157 * 158 * @og.rev 3.1.1.2 (2003/04/04) 継承元を、CommonTagSupport から TagSupport に変更する。 159 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。HybsRequestWrapper 廃止。直接 Mapでキャッシュする。 160 * @og.rev 3.1.6.0 (2003/04/24) キャッシュすべき値を、キー毎に指定できるように、cacheKey 属性を追加。 161 * @og.rev 3.1.7.0 (2003/05/02) RENEW のときに、キャッシュを削除しないように変更する。 162 * @og.rev 3.1.7.0 (2003/05/02) command=INIT または、null のときに、キャッシュを削除するように変更する。 163 * @og.rev 3.5.5.0 (2004/03/12) command=RESET時にも、キャッシュを取り出すように変更する。 164 * @og.rev 3.8.6.3 (2006/11/30) debug 処理を追加 165 * @og.rev 3.8.8.0 (2006/12/22) actionCacheData 処理を追加 166 * @og.rev 5.6.8.1 (2013/09/13) UserInfo に、request 情報を渡してキャッシュ対象情報をセットします。 167 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 168 * @og.rev 6.4.3.3 (2016/03/04) ServletRequest#getParameterMap() が、not null保証は無いので、ConcurrentHashMap に置き換えできない。 169 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 170 * 171 * @param command アクションコマンド (public static final 宣言されている文字列) 172 * @param request リクエストオブジェクト 173 */ 174// @SuppressWarnings(value={"unchecked"}) 175 private void commandExec( final String command,final ServletRequest request ) { 176 final String key = CACHE_KEY + cacheKey ; 177 final HttpSession session = pageContext.getSession(); 178 String msg = null; // 3.8.6.3 (2006/11/30) 179 180 if( CMD_NEW.equals( command ) ) { 181 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 182 final Map<String,String[]> map = actionCacheData( new HashMap<>( request.getParameterMap() ) ); // 6.4.3.3 (2016/03/04) 183 session.setAttribute( key,map ); 184 185 // 5.6.8.1 (2013/09/13) UserInfo に、request 情報を渡してキャッシュ対象情報をセットします。 186 getUser().setLastRequestMap( map ); 187 msg = "command=[NEW] CACHE=[Set]" ; 188 } 189 else if( cacheKey.length() > 0 && 190 ( CMD_RENEW.equals( command ) || CMD_RESET.equals( command ) ) ) { 191 @SuppressWarnings(value={"unchecked"}) // 8.2.1.0 (2022/07/15) メソッド全体から局所化 192 Map<String,String[]> map = (Map<String,String[]>)session.getAttribute( key ); 193 if( map != null ) { 194 map = actionCacheData( map ); 195 session.setAttribute( CACHE_KEY,map ); // 共有キャッシュにセット 196 msg = "command=[" + command + "] CACHE=[Load]" ; 197 } 198 } 199 else if( CMD_INIT.equals( command ) || command == null || command.isEmpty() ) { 200 session.removeAttribute( key ); 201 msg = "command=[" + command + "] CACHE=[remove]" ; 202 } 203 204 // 3.8.6.3 (2006/11/30) 205 if( isDebug() ) { 206// jspPrint( msg + "<br />" ); 207 jspPrint( msg + "<br>" ); // 7.0.1.0 (2018/10/15) 208 } 209 } 210 211 /** 212 * キャッシュデータに対して、追記、削除を行います。 213 * 214 * @og.rev 3.8.8.0 (2006/12/22) 新規追加 215 * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMapではないが、not null制限のチェック追加 216 * 217 * @param map キャッシュデータ 218 * 219 * @return 追記、削除のキャッシュデータのマップ(入力のMapと同一) 220 */ 221 private Map<String,String[]> actionCacheData( final Map<String,String[]> map ) { 222 if( action != null && map != null && keys != null && vals != null ) { 223 if( ACT_SET.equalsIgnoreCase( action ) ) { 224 for( int i=0; i<keys.length; i++ ) { 225 final String[] val = new String[] { vals[i] } ; 226 if( keys[i] != null ) { map.put( keys[i],val ); } // 6.4.3.3 (2016/03/04) 227 } 228 } 229 else if( ACT_DELETE.equalsIgnoreCase( action ) ) { 230 for( int i=0; i<keys.length; i++ ) { 231 if( keys[i] != null ) { map.remove( keys[i] ); } // 6.4.3.3 (2016/03/04) 232 } 233 } 234 } 235 236 return map ; 237 } 238 239 /** 240 * BACK_GAMENID のキャッシュの設定先を変更します。 241 * 242 * @og.rev 3.1.8.0 (2003/05/16) BACK_GAMENID のキャッシュの設定先を変更する。 243 * @og.rev 3.5.1.0 (2003/10/03) BACK_GAMENID のリクエストがNULLのときの処理(バグ)訂正。 244 * @og.rev 3.7.0.3 (2005/03/01) BACK_ROW 情報を取得し、backGamenIdSetメソッドに渡すように変更。 245 * @og.rev 3.8.6.3 (2006/11/30) debug 処理を追加 246 * @og.rev 4.0.1.0 (2007/12/17) BACK_ADDRESSを追加 247 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 248 * 249 * @param command アクションコマンド (public static final 宣言されている文字列) 250 * @param backGamenId リクエストから取得したBACK_GAMENID 251 * @param gamenId 画面ID 252 * @param backRow Stringリクエストから取得したBACK_ROW 253 * @param backAdrs Stringリクエストから取得したBACK_ADDRESS 254 */ 255 private void backGamenIdSet( final String command,final String backGamenId,final String gamenId,final String backRow,final String backAdrs) { // 3.5.1.0 (2003/10/03) 256 final HttpSession session = pageContext.getSession(); 257 258 // この画面自身のID 259 final GUIInfo guiInfo = (GUIInfo)session.getAttribute( HybsSystem.GUIINFO_KEY ); 260 final String guiId = guiInfo.getAttribute( "KEY" ); 261 262 final String guikey = HybsSystem.BACK_GAMENID_KEY + guiId ; 263 final String rowkey = HybsSystem.BACK_ROW_KEY + guiId ; // 3.7.0.3 (2005/03/01) 264 String msg = null; // 3.8.6.3 (2006/11/30) 265 final String adrskey = HybsSystem.BACK_ADDRESS_KEY + guiId; // 4.0.1.0 (2007/12/17) 266 if( CMD_NEW.equals( command ) && backGamenId != null && ! backGamenId.equals( guiId ) ) { 267 session.setAttribute( guikey,backGamenId ); 268 session.setAttribute( rowkey,backRow ); // 3.7.0.3 (2005/03/01) 269 session.setAttribute( adrskey,backAdrs ); // 4.0.1.0 (2007/12/17) 270 msg = "command=[" + command + "] backGamenId=[Set]" ; 271 } 272 else if( CMD_INIT.equals( command ) || command == null || command.isEmpty() ) { 273 session.removeAttribute( guikey ); 274 session.removeAttribute( rowkey ); // 3.7.0.3 (2005/03/01) 275 msg = "command=[" + command + "] backGamenId=[command Remove]" ; 276 session.removeAttribute( adrskey ); // 4.0.1.0 (2007/12/17) 277 } 278 // 以下 追加 3.5.1.0 (2003/10/03) 279 // 変更 4.0.1.0 (2007/12/17) 280 else if( ( gamenId == null || gamenId.isEmpty() ) && 281 ( backGamenId == null || backGamenId.isEmpty() ) && 282 ( backAdrs == null || backAdrs.isEmpty() )) { 283 session.removeAttribute(guikey ); 284 session.removeAttribute( rowkey ); // 3.7.0.3 (2005/03/01) 285 msg = "command=[" + command + "] backGamenId=[null Remove] " ; 286 session.removeAttribute( adrskey ); // 4.0.1.0 (2007/12/17) 287 } 288 289 // 3.8.6.3 (2006/11/30) 290 if( isDebug() ) { 291// jspPrint( msg + "<br />" ); 292 jspPrint( msg + "<br>" ); // 7.0.1.0 (2018/10/15) 293 } 294 } 295 296 /** 297 * 【TAG】キャッシュするサブキーを指定します(初期値:"")。 298 * 299 * @og.tag 300 * キャッシュすべき値を、キー毎に指定できるようにします。 301 * 例えば、これに、画面IDを追加しておけば、画面ごとに、自分のリクエスト情報を 302 * キャッシュしておき、自分の画面が呼ばれたら、再度使用することができる様になります。 303 * NEW でキャッシュ登録を行い、RENEW で、通常のキャッシュキーに値を取り出します。 304 * 305 * @og.rev 3.1.6.0 (2003/04/24) キャッシュすべき値を、キー毎に指定できるように、cacheKey 属性を追加。 306 * 307 * @param ck キャッシュするサブキー 308 */ 309 public void setCacheKey( final String ck ) { 310 cacheKey = nval( getRequestParameter( ck ),cacheKey ); 311 } 312 313 /** 314 * 【TAG】アクション(SET,DELETE)をセットします。 315 * 316 * @og.tag 317 * アクションは,HTMLから(get/post)指定されますので,ACT_xxx で設定される 318 * フィールド定数値のいづれかを、指定できます。 319 * 無指定の場合は、なにもしません。 320 * 321 * <table class="plain"> 322 * <caption>アクションの説明</caption> 323 * <tr><th>action </th><th>名称</th><th>機能</th></tr> 324 * <tr><td>SET </td><td>登録</td><td>指定の keys のキーに vals のキャッシュをセットします。</td></tr> 325 * <tr><td>DELETE </td><td>削除</td><td>指定の keys のキャッシュを削除します。 </td></tr> 326 * </table> 327 * 328 * @og.rev 6.3.4.0 (2015/08/01) Arrays.toString から String.join に置き換え。 329 * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。 330 * 331 * @param act アクション (public static final 宣言されている文字列) 332 * @see <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.RequestCacheTag.ACT_DELETE">アクション定数</a> 333 */ 334 public void setAction( final String act ) { 335 action = nval( getRequestParameter( act ),action ); 336 337 if( action != null && !check( action, ACTION_SET ) ) { 338 final String errMsg = "指定のアクションは実行できません。アクションエラー" + CR 339 + "action=[" + action + "] " + CR 340 + "actionList=" + String.join( ", " , ACTION_SET ) ; 341 throw new HybsSystemException( errMsg ); 342 } 343 } 344 345 /** 346 * 【TAG】リンク先に渡すキーを指定します。 347 * 348 * @og.tag 349 * 戻る時に、検索時のキャッシュに指定した引数以外に指定したり、別の値に置き換えたり 350 * する場合のキーを設定できます。CSV形式で複数指定できます。 351 * vals 属性には、キーに対応する値を、設定してください。 352 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 353 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 354 * 355 * @og.rev 3.8.8.0 (2006/12/22) 新規追加 356 * 357 * @param key リンク先に渡すキー 358 */ 359 public void setKeys( final String key ) { 360 keys = getCSVParameter( key ); 361 } 362 363 /** 364 * 【TAG】keys属性に対応する値をCSV形式で複数指定します。 365 * 366 * @og.tag 367 * キーに設定した値を、CSV形式で複数して出来ます。 368 * 指定順序は、キーと同じにしておいて下さい。 369 * 分解方法は、CSV変数を先に分解してから、getRequestParameter で値を取得します。 370 * こうしないとデータ自身にカンマを持っている場合に分解をミスる為です。 371 * 372 * @og.rev 3.8.8.0 (2006/12/22) 新規追加 373 * 374 * @param val keys属性に対応する値 375 */ 376 public void setVals( final String val ) { 377 vals = getCSVParameter( val ); 378 } 379 380 /** 381 * このオブジェクトの文字列表現を返します。 382 * 基本的にデバッグ目的に使用します。 383 * 384 * @return このクラスの文字列表現 385 * @og.rtnNotNull 386 */ 387 @Override 388 public String toString() { 389 return ToString.title( this.getClass().getName() ) 390 .println( "VERSION" ,VERSION ) 391 .println( "cacheKey" ,cacheKey ) 392 .println( "Other..." ,getAttributes().getAttribute() ) 393 .fixForm().toString() ; 394 } 395}