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 = "7.0.1.0 (2018/10/15)" ; 078 private static final long serialVersionUID = 701020181015L ; 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 return XHTMLTag.link( getAttributes(),urlEnc ) ; 252 } 253 254 /** 255 * URLエンコードを行ったリンク情報を作成します。 256 * 257 * @og.rev 3.1.0.0 (2003/03/20) Vector を使用している箇所で、非同期でも構わない箇所を、ArrayList に置換え。 258 * @og.rev 3.1.2.0 (2003/04/07) 画面IDと実画面ディレクトリとの関連見直し(DIRの代りにGAMENIDを渡すように変更) 259 * @og.rev 3.1.8.0 (2003/05/16) 内部で作成している GAMENID 属性をセットしないように変更。 260 * @og.rev 4.0.0.0 (2007/07/11) submitTag で作成されたボタンパラメータは、次ページへ転送しません。 261 * @og.rev 5.0.0.2 (2009/09/15) xssチェック対応 262 * 263 * @param request HttpServletRequestオブジェクト 264 * 265 * @return URLエンコードを行ったリンク情報 266 * @og.rtnNotNull 267 */ 268 private String makeUrlEncode( final HttpServletRequest request ) { 269 final Enumeration<?> enume = request.getParameterNames(); // 4.3.3.6 (2008/11/15) Generics警告対応 270 final ArrayList<String> v_keys = new ArrayList<>(); 271 final ArrayList<String> v_vals = new ArrayList<>(); 272 while( enume.hasMoreElements() ) { 273 final String key = String.valueOf( enume.nextElement() ); 274 if( key != null && key.startsWith( HybsSystem.NO_XFER_KEY ) ) { 275 continue; 276 } 277 278 // String val = getRequestValue( key ); 279 final String val = getRequestValue( key, false ); // 5.0.0.2 (2009/09/15) 280 if( val != null && val.length() > 0 ) { 281 v_keys.add( key ); 282 v_vals.add( val ); 283 } 284 } 285 286 final String[] keys = v_keys.toArray( new String[v_keys.size()] ); 287 final String[] vals = v_vals.toArray( new String[v_vals.size()] ); 288 289 return XHTMLTag.urlEncode( keys,vals ); 290 } 291 292 /** 293 * お気に入りアイコンを取得します。 294 * 295 * @og.rev 4.1.1.0 (2008/02/12) 新規追加 296 * @og.rev 6.2.2.0 (2015/03/27) BRと\nを相互に変換する処理を追加 297 * @og.rev 6.2.2.3 (2015/04/10) htmlフィルターに、BR→改行処理機能を追加。 298 * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。 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 .append( "\" ></a>" ); // 7.0.1.0 (2018/10/15) 345 } 346 347 return buf.toString(); 348 } 349 350 /** 351 * 【TAG】直接アクセスできる形式のリンクを作成するかどうか[true/false]を指定します(初期値:false)。 352 * 353 * @og.tag 354 * trueは、指定の画面のフレームレベルでの指定になります。false は、トップフレームを 355 * 含む形なので、通常の登録画面と同じ形式になります。 356 * 初期値は、false(直接リンクしない)です。 357 * 358 * @param flag 作成可否 [true:する/false:しない] 359 */ 360 public void setDirect( final String flag ) { 361 direct = nval( getRequestParameter( flag ),direct ); 362 } 363 364 /** 365 * 【TAG】リンク先の文書を表示させるフレーム、またはウィンドウの名前を指定します(初期値:_blank)。 366 * 367 * @og.tag リンク先のフレーム名(ターゲット属性)を設定します。 368 * 369 * @param name リンク先の文書のフレーム名(ターゲット属性) 370 */ 371 public void setTarget( final String name ) { 372 target = nval( getRequestParameter( name ),target ); 373 } 374 375 /** 376 * 【TAG】リンクを作成する時の転送先アドレスを指定します(初期値:index.jsp)。 377 * 378 * @og.tag 379 * direct="false"(初期値)に使用されるリンクの転送先アドレスを指定します。 380 * 初期値は、index.jspです。 381 * 382 * @param url 転送先アドレス 383 */ 384 public void setHref( final String url ) { 385 href = nval( getRequestParameter( url ),href ); 386 } 387 388 /** 389 * 【TAG】リンクの作成元となるメソッド[POST/GET/ALL]を指定します(初期値:GET)。 390 * 391 * @og.tag 392 * ここで指定したメソッドでリクエストされた場合のみ、リンクを作成します。 393 * 初期値は、GET です。(つまり GET のみリンクを作成します。) 394 * これは、POST では、引数が付かない為です。(実際は付ける事ができますが・・・) 395 * ALL は、どちらの場合でもリンクを作成しますが、先に述べたように POST では 396 * 引数がつきません。 397 * 初期値は、GETです。 398 * 399 * @param flag リンクの作成元となるメソッド [POST/GET/ALL] 400 */ 401 public void setMethod( final String flag ) { 402 method = nval( getRequestParameter( flag ),method ); 403 } 404 405 /** 406 * 【TAG】リンクをキャッシュするかどうか[true/false]を指定します(初期値:false)。 407 * 408 * @og.tag 409 * この、favoriteLink で指定された画面を、ユーザー毎にキャッシュします。 410 * キャッシュされた画面は、lastQuery を指定することで、取り出し(転送) 411 * することが出来ます。 412 * ここでのキャッシュは、direct="true" を指定した場合のアドレスです。 413 * direct="false" は、index.jsp からのフレーム形式の為、メール等で 414 * 送り、後ほど再開するような使い方(または、ワークフロー的な使い方) 415 * を想定していますが、direct="true" により単独フレームデータを、 416 * リアルタイムで使用するケース(EXCELのWebクエリーなど)で使用します。 417 * 初期値は、falseです。 418 * 419 * @og.rev 3.5.5.9 (2004/06/07) リンクキャッシュより最終画面を転送表示します。 420 * 421 * @param flag リンクキャッシュ [true:する/false:しない] 422 */ 423 public void setLinkCache( final String flag ) { 424 linkCache = nval( getRequestParameter( flag ),linkCache ); 425 } 426 427 /** 428 * 【TAG】キャッシュされたリンク先に転送するかどうか[true/false]を指定します(初期値:false)。 429 * 430 * @og.tag 431 * この、favoriteLink で指定された画面を、キャッシュします。 432 * キャッシュされた画面は、lastQuery を指定することで、取り出し(転送) 433 * することが出来ます。 434 * ここでのキャッシュは、direct="true" を指定した場合のアドレスです。 435 * direct="false" は、index.jsp からのフレーム形式の為、メール等で 436 * 送り、後ほど再開するような使い方(または、ワークフロー的な使い方) 437 * を想定していますが、direct="true" により単独フレームデータを、 438 * リアルタイムで使用するケース(EXCELのWebクエリーなど)で使用します。 439 * 初期値は、falseです。 440 * 441 * @og.rev 3.5.5.9 (2004/06/07) リンクキャッシュより最終画面を転送表示します。 442 * 443 * @param flag リンク先転送 [true:する/false:しない] 444 */ 445 public void setLastQueryRedirect( final String flag ) { 446 redirect = nval( getRequestParameter( flag ),redirect ); 447 } 448 449 /** 450 * 【TAG】お気に入りアイコンリンクを作成するかどうか[true/false]を指定します(初期値:false)。 451 * 452 * @og.tag 453 * 初期値は、falseです。 454 * 455 * @og.rev 4.1.1.0 (2008/02/13) 新規追加。 456 * 457 * @param flag お気に入りアイコンリンク作成 [true:する/false:しない] 458 */ 459 public void setUseIcon( final String flag ) { 460 useIcon = nval( getRequestParameter( flag ),useIcon ); 461 } 462 463 /** 464 * リンクキャッシュをクリアします。 465 * この時、poolされているオブジェクトは、ResourceManager#clear() メソッドを 466 * 呼び出します。 467 * 468 * @og.rev 3.5.5.9 (2004/06/07) 新規作成 469 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 470 */ 471 public static void clear() { 472 LAST_QUERY.clear(); 473 } 474 475 /** 476 * このオブジェクトの文字列表現を返します。 477 * 基本的にデバッグ目的に使用します。 478 * 479 * @return このクラスの文字列表現 480 * @og.rtnNotNull 481 */ 482 @Override 483 public String toString() { 484 return ToString.title( this.getClass().getName() ) 485 .println( "VERSION" ,VERSION ) 486 .println( "direct" ,direct ) 487 .println( "target" ,target ) 488 .println( "method" ,method ) 489 .println( "linkCache" ,linkCache ) 490 .println( "redirect" ,redirect ) 491 .println( "Other..." ,getAttributes().getAttribute() ) 492 .fixForm().toString() ; 493 } 494}