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