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