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.hayabusa.resource.UserInfo; 022import org.opengion.hayabusa.resource.FavoriteGUIData; 023import org.opengion.fukurou.util.XHTMLTag; 024import org.opengion.fukurou.util.ToString; // 6.1.1.0 (2015/01/17) 025import org.opengion.fukurou.util.StringUtil ; // 6.2.2.0 (2015/03/27) 026 027import static org.opengion.fukurou.util.StringUtil.nval ; 028 029import jakarta.servlet.http.HttpServletRequest ; 030import jakarta.servlet.http.HttpServletResponse; 031 032import java.util.Enumeration; 033import java.util.ArrayList; 034import java.util.Map; 035import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring 036 037import java.io.IOException; 038 039/** 040 * お気に入りリンクを作成するタグです(通常はresult.jspに組込み)。 041 * 042 * 画面検索時の引数やユーザー情報を元にして、ダイレクトに再検索できる 043 * リンクを作成します。このリンクをお気に入り等にセーブしておき、次回検索時にも 044 * 使用できるようにします。 045 * 046 * @og.formSample 047 * ●形式:<og:favoriteLink direct="true" target="_blank" method="GET" /> 048 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{@XXXX} を解析します) 049 * 050 * ●Tag定義: 051 * <og:favoriteLink 052 * target 【TAG】リンク先の文書を表示させるフレーム、またはウィンドウの名前を指定します(初期値:_blank) 053 * direct 【TAG】直接アクセスできる形式のリンクを作成するかどうか[true/false]を指定します(初期値:false) 054 * method 【TAG】リンクの作成元となるメソッド[POST/GET/ALL]を指定します(初期値:GET) 055 * href 【TAG】リンクを作成する時の転送先アドレスを指定します(初期値:index.jsp) 056 * lbl 【TAG】ラベルリソースのラベルIDを指定します 057 * linkCache 【TAG】リンクをキャッシュするかどうか[true/false]を指定します(初期値:false) 058 * lastQueryRedirect 【TAG】キャッシュされたリンク先に転送するかどうか[true/false]を指定します(初期値:false) 059 * debug 【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false) 060 * useIcon 【TAG】お気に入りアイコンリンクを作成するかどうか[true/false]を指定します(初期値:false) 061 * > ... Body ... 062 * </og:favoriteLink> 063 * 064 * ●使用例: 065 * 直接お気に入りのリンクを作成する。 066 * デフォルト属性を使用(direct="true" target="_blank" method="GET") 067 * <og:favoriteLink > Favorite Link </og:favoriteLink > 068 * 069 * @og.rev 7.3.2.3 (2021/04/09) システム定数のJSP_IMGを使用します。(※ SYS.JSP + SYS.IMAGE_DIR) 070 * @og.group 画面部品 071 * 072 * @version 4.0 073 * @author Kazuhiko Hasegawa 074 * @since JDK5.0, 075 */ 076public class FavoriteLinkTag extends CommonTagSupport { 077 /** このプログラムのVERSION文字列を設定します。 {@value} */ 078 private static final String VERSION = "7.3.2.3 (2021/04/09)" ; 079 private static final long serialVersionUID = 732320210409L ; 080 081 // 7.3.2.3 (2021/04/09) システム定数のJSP_IMGを使用します。(※ SYS.JSP + SYS.IMAGE_DIR) 082 private static final String JSP_IMG = HybsSystem.sys( "JSP_IMG" ) + "/" ; 083 084 /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */ 085 private static final Map<String,String> LAST_QUERY = new ConcurrentHashMap<>(); // 6.4.1.1 (2016/01/16) lastQuery → LAST_QUERY refactoring 086 087 private boolean direct ; // 3.0.0.0 初期値変更 088 private String target = "_blank"; // 3.6.0.7 (2004/11/06) 089 private String method = "GET"; 090 private String href = "index.jsp"; // 3.8.8.2 (2007/01/26) 091 private boolean linkCache ; // 3.5.5.9 (2004/06/07) 092 private boolean redirect ; // 3.5.5.9 (2004/06/07) 093 private boolean useIcon ; // 4.1.1.0 (2008/02/13) 094 095 /** 096 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。 097 * 098 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。ボディが存在する場合のみボディが呼ばれる対応。 099 * @og.rev 3.5.5.9 (2004/06/07) リンクキャッシュより最終画面を転送表示します。 100 * @og.rev 5.0.0.2 (2009/09/15) xss対応⇒チェックする 101 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 102 * 103 * @return 後続処理の指示 104 */ 105 @Override 106 public int doStartTag() { 107 // 5.0.0.2 (2009/09/15) 強制False 108 // useXssCheck( false ); 109 110 // 3.5.5.9 (2004/06/07) リンクキャッシュより最終画面を転送表示 111 if( redirect ) { 112 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。key,val は、not null 制限。 113 final String uid = getUserInfo( "ID" ); 114 115 final String page = uid == null ? null : LAST_QUERY.get( uid ) ; 116 117 if( page != null ) { 118 final HttpServletResponse response = (HttpServletResponse)pageContext.getResponse(); 119 final String url = response.encodeRedirectURL( page ); 120 try { 121 response.sendRedirect( url ); 122 } 123 catch( final IOException ex ) { 124 final String errMsg = "最終画面の転送時のリダイレクトエラー" + toString(); 125 throw new HybsSystemException( errMsg,ex ); 126 } 127 128 return SKIP_BODY ; 129 } 130 } 131 132 set( "body",getMsglbl() ); 133 return EVAL_BODY_BUFFERED ; // Body を評価する。( extends BodyTagSupport 時) 134 } 135 136 /** 137 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。 138 * 139 * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。 140 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。ボディが存在する場合のみボディが呼ばれる対応。 141 * 142 * @return 後続処理の指示(SKIP_BODY) 143 */ 144 @Override 145 public int doAfterBody() { 146 147 final String label = getBodyString(); 148 149 if( label != null && label.length() > 0 ) { 150 set( "body",label ); 151 } 152 153 return SKIP_BODY ; 154 } 155 156 /** 157 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。 158 * 159 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 160 * @og.rev 4.1.1.0 (2008/0213) お気に入りアイコンリンクの作成 161 * 162 * @return 後続処理の指示 163 */ 164 @Override 165 public int doEndTag() { 166 debugPrint(); // 4.0.0 (2005/02/28) 167 168 // method による条件判断。 169 final String requestMethod = ((HttpServletRequest)getRequest()).getMethod(); 170 if( method != null && 171 ( "ALL".equalsIgnoreCase( method ) || 172 method.equalsIgnoreCase( requestMethod ) ) ) { 173 // 4.1.1.0 (2008/0213) お気に入りアイコンリンクの作成 174 if( useIcon ) { 175 jspPrint( getFavoriteIcon() ); 176 } 177 else { 178 jspPrint( makeTag() ); 179 } 180 } 181 182 return EVAL_PAGE ; 183 } 184 185 /** 186 * タグリブオブジェクトをリリースします。 187 * キャッシュされて再利用されるので、フィールドの初期設定を行います。 188 * 189 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加 190 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。 191 * @og.rev 3.5.5.9 (2004/06/07) linkCache , redirect 属性を追加 192 * @og.rev 3.6.0.7 (2004/11/06) target 属性の初期値を _new から _blank に変更 193 * @og.rev 3.8.8.2 (2007/01/26) href 属性を追加 194 * 195 */ 196 @Override 197 protected void release2() { 198 super.release2(); 199 direct = false; 200 target = "_blank"; // 3.6.0.7 (2004/11/06) 201 method = "GET"; 202 href = "index.jsp"; // 3.8.8.2 (2007/01/26) 203 linkCache = false; // 3.5.5.9 (2004/06/07) 204 redirect = false; // 3.5.5.9 (2004/06/07) 205 } 206 207 /** 208 * お気に入りリンクを作成します。 209 * 210 * @og.rev 3.8.8.2 (2007/01/26) href 属性を追加 211 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 212 * 213 * @return お気に入りリンクタグ文字列 214 * @og.rtnNotNull 215 */ 216 protected String makeTag() { 217 final HttpServletRequest request = (HttpServletRequest)getRequest(); 218 219 // ダイレクトリンク時の設定 220 // リンクの作成 221 // http://C00000:C00000@hn50g5:8080/dbdef/jsp/index.jsp?GAMENID=xxx&command=NEW&key=val 222 final StringBuilder link = new StringBuilder( BUFFER_MIDDLE ) 223 .append( "http://" ) 224 .append( request.getServerName() ).append( ':' ) // hn50g5: // 6.0.2.5 (2014/10/31) char を append する。 225 .append( request.getServerPort() ) // 8823 226 .append( request.getContextPath() ) // /dbdef 227 .append( "/jsp/" ); 228 229 // 4.0.0 (2005/01/31) 230 final String direct_jsp = getGUIInfoAttri( "ADDRESS" ) + "/" + (String)getSessionAttribute( "JSPID" ); 231 232 final String hrefUrl = link.toString() ; 233 if( direct ) { 234 set( "href" , hrefUrl + direct_jsp ); 235 } 236 else { 237 set( "href" , hrefUrl + href ); // 3.8.8.2 (2007/01/26) 238 } 239 240 set( "target" ,target ); 241 set( "title" ,getGUIInfoAttri( "LABEL" ) ); // 4.0.0 (2005/01/31) 242 243 final String urlEnc = makeUrlEncode( request ); 244 245 // linkCache による、最終リクエストのアドレスを格納しておきます。 246 if( linkCache ) { 247 // 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。key,val は、not null 制限。 248 final String uid = getUserInfo( "ID" ); 249 if( uid != null ) { 250 final String val = hrefUrl + direct_jsp + "?" + urlEnc ; 251 LAST_QUERY.put( uid,val ); 252 } 253 } 254 255 return XHTMLTag.link( getAttributes(),urlEnc ) ; 256 } 257 258 /** 259 * URLエンコードを行ったリンク情報を作成します。 260 * 261 * @og.rev 3.1.0.0 (2003/03/20) Vector を使用している箇所で、非同期でも構わない箇所を、ArrayList に置換え。 262 * @og.rev 3.1.2.0 (2003/04/07) 画面IDと実画面ディレクトリとの関連見直し(DIRの代りにGAMENIDを渡すように変更) 263 * @og.rev 3.1.8.0 (2003/05/16) 内部で作成している GAMENID 属性をセットしないように変更。 264 * @og.rev 4.0.0.0 (2007/07/11) submitTag で作成されたボタンパラメータは、次ページへ転送しません。 265 * @og.rev 5.0.0.2 (2009/09/15) xssチェック対応 266 * 267 * @param request HttpServletRequestオブジェクト 268 * 269 * @return URLエンコードを行ったリンク情報 270 * @og.rtnNotNull 271 */ 272 private String makeUrlEncode( final HttpServletRequest request ) { 273 final Enumeration<?> enume = request.getParameterNames(); // 4.3.3.6 (2008/11/15) Generics警告対応 274 final ArrayList<String> v_keys = new ArrayList<>(); 275 final ArrayList<String> v_vals = new ArrayList<>(); 276 while( enume.hasMoreElements() ) { 277 final String key = String.valueOf( enume.nextElement() ); 278 if( key != null && key.startsWith( HybsSystem.NO_XFER_KEY ) ) { 279 continue; 280 } 281 282 // String val = getRequestValue( key ); 283 final String val = getRequestValue( key, false ); // 5.0.0.2 (2009/09/15) 284 if( val != null && val.length() > 0 ) { 285 v_keys.add( key ); 286 v_vals.add( val ); 287 } 288 } 289 290 final String[] keys = v_keys.toArray( new String[v_keys.size()] ); 291 final String[] vals = v_vals.toArray( new String[v_vals.size()] ); 292 293 return XHTMLTag.urlEncode( keys,vals ); 294 } 295 296 /** 297 * お気に入りアイコンを取得します。 298 * 299 * @og.rev 4.1.1.0 (2008/02/12) 新規追加 300 * @og.rev 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加 301 * @og.rev 6.2.2.3 (2015/04/10) htmlフィルターに、BR→改行処理機能を追加。 302 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 303 * @og.rev 7.3.2.3 (2021/04/09) システム定数のJSP_IMGを使用します。(※ SYS.JSP + SYS.IMAGE_DIR) 304 * 305 * @return お気に入りアイコンのリンクを返します。 306 * @og.rtnNotNull 307 */ 308 private String getFavoriteIcon() { 309 final GUIInfo guiInfo = ( GUIInfo )getSessionAttribute( HybsSystem.GUIINFO_KEY ); 310 final String mscVal = getRequestValue( "MSC" ); 311 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 312 313 if( guiInfo.isRead() && mscVal.length() != 0 ) { 314 final String gamenId = guiInfo.getKey(); 315 final UserInfo userInfo = getUser(); 316 final Map<String,FavoriteGUIData> favoriteMap = userInfo.getFavoriteMap(); 317 318 // 6.3.9.0 (2015/11/06) Use one line for each declaration, it enhances code readability.(PMD) 319 final String fgEdit; 320 final String image; 321 final String updateLabel; 322 if( favoriteMap.containsKey( gamenId ) ){ 323 fgEdit = "0"; 324 image = "FAV_MENU_OUT.gif"; 325 updateLabel = getLabel( "DELETE" ); 326 } 327 else { 328 fgEdit = "1"; 329 image = "FAV_MENU_IN.gif"; 330 updateLabel = getLabel( "INSERT" ); 331 } 332 333 final String geContextName = HybsSystem.sys( "GE_CONTEXT_NAME" ); 334 if( geContextName.isEmpty() ) { 335 final String errMsg = "システムパラメータ GE_CONTEXT_NAME が設定されていません。"; 336 throw new HybsSystemException( errMsg ); 337 } 338 339 buf.append( "<a href=\"/").append( geContextName ) 340 .append("/jsp/GE0014/update.jsp?fgEdit=" ).append( fgEdit ) 341 .append( "&command=NEW&SYSTEM_ID=" ).append( userInfo.getParameter( "SYSTEM_ID" ) ) 342 .append( "&GUIKEY=" ).append( gamenId ) 343 .append( "&CONTEXT_URL=" ).append( userInfo.getParameter( "CONTEXT_URL" ) ) 344 // 7.3.2.3 (2021/04/09) システム定数のJSP_IMGを使用します。(※ SYS.JSP + SYS.IMAGE_DIR) 345// .append( "\"><img src=\"" ).append( userInfo.getParameter( "JSP" ) ) 346// .append( "/image/" ).append( image ) 347 .append( "\"><img src=\"" ).append( JSP_IMG ).append( image ) 348 .append( "\" title=\"" ).append( StringUtil.htmlFilter( getLabel( "FAVORITE_MENU" ),true ) ) // 6.2.2.0 (2015/03/27) 349 .append( ' ' ).append( updateLabel ) 350// .append( "\" /></a>" ); 351 .append( "\" ></a>" ); // 7.0.1.0 (2018/10/15) 352 } 353 354 return buf.toString(); 355 } 356 357 /** 358 * 【TAG】直接アクセスできる形式のリンクを作成するかどうか[true/false]を指定します(初期値:false)。 359 * 360 * @og.tag 361 * trueは、指定の画面のフレームレベルでの指定になります。false は、トップフレームを 362 * 含む形なので、通常の登録画面と同じ形式になります。 363 * 初期値は、false(直接リンクしない)です。 364 * 365 * @param flag 作成可否 [true:する/false:しない] 366 */ 367 public void setDirect( final String flag ) { 368 direct = nval( getRequestParameter( flag ),direct ); 369 } 370 371 /** 372 * 【TAG】リンク先の文書を表示させるフレーム、またはウィンドウの名前を指定します(初期値:_blank)。 373 * 374 * @og.tag リンク先のフレーム名(ターゲット属性)を設定します。 375 * 376 * @param name リンク先の文書のフレーム名(ターゲット属性) 377 */ 378 public void setTarget( final String name ) { 379 target = nval( getRequestParameter( name ),target ); 380 } 381 382 /** 383 * 【TAG】リンクを作成する時の転送先アドレスを指定します(初期値:index.jsp)。 384 * 385 * @og.tag 386 * direct="false"(初期値)に使用されるリンクの転送先アドレスを指定します。 387 * 初期値は、index.jspです。 388 * 389 * @param url 転送先アドレス 390 */ 391 public void setHref( final String url ) { 392 href = nval( getRequestParameter( url ),href ); 393 } 394 395 /** 396 * 【TAG】リンクの作成元となるメソッド[POST/GET/ALL]を指定します(初期値:GET)。 397 * 398 * @og.tag 399 * ここで指定したメソッドでリクエストされた場合のみ、リンクを作成します。 400 * 初期値は、GET です。(つまり GET のみリンクを作成します。) 401 * これは、POST では、引数が付かない為です。(実際は付ける事ができますが・・・) 402 * ALL は、どちらの場合でもリンクを作成しますが、先に述べたように POST では 403 * 引数がつきません。 404 * 初期値は、GETです。 405 * 406 * @param flag リンクの作成元となるメソッド [POST/GET/ALL] 407 */ 408 public void setMethod( final String flag ) { 409 method = nval( getRequestParameter( flag ),method ); 410 } 411 412 /** 413 * 【TAG】リンクをキャッシュするかどうか[true/false]を指定します(初期値:false)。 414 * 415 * @og.tag 416 * この、favoriteLink で指定された画面を、ユーザー毎にキャッシュします。 417 * キャッシュされた画面は、lastQuery を指定することで、取り出し(転送) 418 * することが出来ます。 419 * ここでのキャッシュは、direct="true" を指定した場合のアドレスです。 420 * direct="false" は、index.jsp からのフレーム形式の為、メール等で 421 * 送り、後ほど再開するような使い方(または、ワークフロー的な使い方) 422 * を想定していますが、direct="true" により単独フレームデータを、 423 * リアルタイムで使用するケース(EXCELのWebクエリーなど)で使用します。 424 * 初期値は、falseです。 425 * 426 * @og.rev 3.5.5.9 (2004/06/07) リンクキャッシュより最終画面を転送表示します。 427 * 428 * @param flag リンクキャッシュ [true:する/false:しない] 429 */ 430 public void setLinkCache( final String flag ) { 431 linkCache = nval( getRequestParameter( flag ),linkCache ); 432 } 433 434 /** 435 * 【TAG】キャッシュされたリンク先に転送するかどうか[true/false]を指定します(初期値:false)。 436 * 437 * @og.tag 438 * この、favoriteLink で指定された画面を、キャッシュします。 439 * キャッシュされた画面は、lastQuery を指定することで、取り出し(転送) 440 * することが出来ます。 441 * ここでのキャッシュは、direct="true" を指定した場合のアドレスです。 442 * direct="false" は、index.jsp からのフレーム形式の為、メール等で 443 * 送り、後ほど再開するような使い方(または、ワークフロー的な使い方) 444 * を想定していますが、direct="true" により単独フレームデータを、 445 * リアルタイムで使用するケース(EXCELのWebクエリーなど)で使用します。 446 * 初期値は、falseです。 447 * 448 * @og.rev 3.5.5.9 (2004/06/07) リンクキャッシュより最終画面を転送表示します。 449 * 450 * @param flag リンク先転送 [true:する/false:しない] 451 */ 452 public void setLastQueryRedirect( final String flag ) { 453 redirect = nval( getRequestParameter( flag ),redirect ); 454 } 455 456 /** 457 * 【TAG】お気に入りアイコンリンクを作成するかどうか[true/false]を指定します(初期値:false)。 458 * 459 * @og.tag 460 * 初期値は、falseです。 461 * 462 * @og.rev 4.1.1.0 (2008/02/13) 新規追加。 463 * 464 * @param flag お気に入りアイコンリンク作成 [true:する/false:しない] 465 */ 466 public void setUseIcon( final String flag ) { 467 useIcon = nval( getRequestParameter( flag ),useIcon ); 468 } 469 470 /** 471 * リンクキャッシュをクリアします。 472 * この時、poolされているオブジェクトは、ResourceManager#clear() メソッドを 473 * 呼び出します。 474 * 475 * @og.rev 3.5.5.9 (2004/06/07) 新規作成 476 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 477 */ 478 public static void clear() { 479 LAST_QUERY.clear(); 480 } 481 482 /** 483 * このオブジェクトの文字列表現を返します。 484 * 基本的にデバッグ目的に使用します。 485 * 486 * @return このクラスの文字列表現 487 * @og.rtnNotNull 488 */ 489 @Override 490 public String toString() { 491 return ToString.title( this.getClass().getName() ) 492 .println( "VERSION" ,VERSION ) 493 .println( "direct" ,direct ) 494 .println( "target" ,target ) 495 .println( "method" ,method ) 496 .println( "linkCache" ,linkCache ) 497 .println( "redirect" ,redirect ) 498 .println( "Other..." ,getAttributes().getAttribute() ) 499 .fixForm().toString() ; 500 } 501}