    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.resource.UserInfo;
    019import org.opengion.hayabusa.db.DBTableModel;
    020import org.opengion.hayabusa.db.Query;
    021import org.opengion.hayabusa.db.QueryFactory;
    022import org.opengion.fukurou.db.Transaction;
    023import org.opengion.fukurou.util.ToString;                                              // 6.1.1.0 (2015/01/17)
    024import org.opengion.fukurou.util.ArraySet;                                              // 6.4.3.4 (2016/03/11)
    025
    026import static org.opengion.fukurou.util.StringUtil.nval ;
    027
    028import java.util.Set;                                                                                   // 6.4.3.4 (2016/03/11)
    029import java.util.Locale ;
    030
    031/**
    032 * ユーザー情報を管理しているタグです。
    033 *
    034 * 設定した値は、{&#064;USER.XXXX} 形式で 取り出すことができます。
    035 * また、command 属性で 直接画面に値を書き出すことも可能です。
    036 *
    037 * 以下の値は UserInfo オブジェクトの項目から取得します。
    038 * ・USER.JNAME     ユーザー日本語名称
    039 * ・USER.ID        ユーザーＩＤ
    040 * ・USER.IDNO      USER.ID が５Byte以上の時のみ先頭１文字を除いたユーザーＩＤ
    041 * ・USER.INFO      ユーザー情報(ユーザーID：日本語名称)
    042 * ・USER.LANG      言語
    043 * ・USER.ROLES     ロール
    044 * ・USER.IPADDRESS IPアドレス
    045 * ・USER.LOGINTIME ログイン時刻
    046 *
    047 * 以下の値はあらかじめ、動的に作成されます。
    048 * ・USER.YMD       ８byte の今日のシステム日付
    049 * ・USER.YMDH    １４byte の今日のシステム日時
    050 *
    051 * それ以外は、外部より設定された値です。
    052 *
    053 * ※ このタグは、Transaction タグの対象です。
    054 *
    055 * @og.formSample
    056 * ●形式：&lt;og:userInfo command="[…]" key="[…]" value="[…]" /&gt;
    057 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
    058 *
    059 * ●Tag定義：
    060 *   &lt;og:userInfo
    061 *       command            【TAG】コマンド (SET,GET,NVLGET,REMOVE,SQL)をセットします(初期値:SET)
    062 *       key                【TAG】UserInfo に登録するキーをセットします(予約語:JNAME,ID,PASSWD,IDNO,INFO,LANG,ROLE,IPADDRESS,LOGINTIME)
    063 *       value              【TAG】UserInfo に登録する値をセットします
    064 *       dbid               【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します
    065 *       save               【TAG】UserInfo に登録した値を永続化するかを指定します(初期値:false)
    066 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
    067 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
    068 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
    069 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
    070 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
    071 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    072 *   &gt;   ... Body ...
    073 *   &lt;/og:userInfo&gt;
    074 *
    075 * ●使用例
    076 *      &lt;og:userInfo
    077 *         command       = &quot;コマンド (SET,GET,NVLGET,REMOVE,SQL)をセットします(初期値:SET)。&quot;
    078 *         key           = &quot;UserInfo に登録するキーをセットします(予約語:JNAME,ID,PASSWD,IDNO,INFO,LANG,ROLE,IPADDRESS,LOGINTIME)。&quot;
    079 *         value         = &quot;UserInfo に登録する値をセットします。&quot;
    080 *         dbid          = &quot;(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します。&quot;
    081 *      &gt;
    082 *
    083 * @og.group その他部品
    084 *
    085 * @version  4.0
    086 * @author   Kazuhiko Hasegawa
    087 * @since    JDK5.0,
    088 */
    089public class UserInfoTag extends CommonTagSupport {
    090        /** このプログラムのVERSION文字列を設定します。   {@value} */
    091        private static final String VERSION = "6.4.3.4 (2016/03/11)" ;
    092        private static final long serialVersionUID = 643420160311L ;
    093
    094        /** command 引数に渡す事の出来る コマンド  セット {@value} */
    095        public static final String CMD_SET   = "SET" ;
    096        /** command 引数に渡す事の出来る コマンド  ゲット {@value} */
    097        public static final String CMD_GET   = "GET" ;
    098        /** command 引数に渡す事の出来る コマンド  ゲット {@value} */
    099        public static final String CMD_REMOVE   = "REMOVE" ;
    100        /** command 引数に渡す事の出来る コマンド  ゲット {@value} */
    101        public static final String CMD_SQL   = "SQL" ;
    102        // 3.5.5.3 (2004/04/09) 値が null の場合は、""(ゼロ文字列)を返すNVLGETを採用
    103        /** command 引数に渡す事の出来る コマンド  NVLゲット {@value} */
    104        public static final String CMD_NVLGET   = "NVLGET" ;
    105
    106        // 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
    107        private static final Set<String> COMMAND_SET = new ArraySet<>( CMD_SET , CMD_GET , CMD_NVLGET , CMD_REMOVE , CMD_SQL );
    108
    109        // 3.5.6.0 (2004/06/18) すべてを protected から private に変更します。
    110        private String                  command         = CMD_SET;
    111        private String                  key                     ;
    112        private String                  value           ;
    113        private transient DBTableModel table;
    114        // 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
    115        private String                  dbid            ;
    116        private String                  sql                     ;
    117        // 4.3.4.0 (2008/12/01) save属性追加
    118        private boolean                 save            ;
    119
    120        /**
    121         * デフォルトコンストラクター
    122         *
    123         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
    124         */
    125        public UserInfoTag() { super(); }               // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    126
    127        /**
    128         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    129         *
    130         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    131         *
    132         * @return      後続処理の指示
    133         */
    134        @Override
    135        public int doStartTag() {
    136                // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
    137                return useTag() && CMD_SQL.equals( command )
    138                                        ? EVAL_BODY_BUFFERED                            // Body を評価する
    139                                        : SKIP_BODY ;                                           // Body を評価しない
    140
    141        }
    142
    143        /**
    144         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
    145         *
    146         * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
    147         * @og.rev 3.6.0.8 (2004/11/19) エラー発生時に確実にリリースされるように try finally 追加
    148         * @og.rev 3.8.6.3 (2006/11/30) SQL 文の前後のスペースを取り除きます。
    149         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
    150         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
    151         * @og.rev 5.1.9.0 (2010/08/01) TransactionTag 対応。上位に TransactionTag があれば、そこからConnection をもらう。
    152         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
    153         * @og.rev 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()
    154         * @og.rev 6.3.1.1 (2015/07/10) BodyString,BodyRawStringは、CommonTagSupport で、trim() します。
    155         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
    156         * @og.rev 6.3.6.1 (2015/08/28) QueryFactory.close( Query ) 廃止。Queryはキャッシュしません。
    157         *
    158         * @return      後続処理の指示(SKIP_BODY)
    159         */
    160        @Override
    161        public int doAfterBody() {
    162                sql = getBodyString();
    163
    164                // 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
    165                try( final Transaction tran = getTransaction() ) {
    166                        final Query query = QueryFactory.newInstance();         // 4.0.0 (2005/01/31)
    167                        query.setConnection( tran.getConnection( dbid ) );                      // 6.3.6.1 (2015/08/28)
    168                        query.setResourceManager( getResource() );      // 4.0.0 (2005/01/31)
    169                        query.setStatement( sql );
    170                        query.execute();
    171
    172                        table = query.getDBTableModel();
    173                        tran.commit();                          // 6.3.6.1 (2015/08/28)
    174                }
    175                return SKIP_BODY ;
    176        }
    177
    178        /**
    179         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    180         *
    181         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
    182         * @og.rev 3.5.5.3 (2004/04/09) 値が null の場合は、""(ゼロ文字列)を返すフラグを採用
    183         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    184         * @og.rev 6.4.3.4 (2016/03/11) String配列 から、Setに置き換えます。
    185         *
    186         * @return      後続処理の指示
    187         */
    188        @Override
    189        public int doEndTag() {
    190                debugPrint();           // 4.0.0 (2005/02/28)
    191                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    192                if( useTag() && check( command, COMMAND_SET ) ) {
    193                        commandExec( command );
    194
    195                        if( CMD_GET.equals( command ) ) {
    196                                jspPrint( value );
    197                        }
    198                        else if( CMD_NVLGET.equals( command ) ) {       // 3.5.5.3 (2004/04/09)
    199                                jspPrint( nval(value,"") );
    200                        }
    201                }
    202
    203                return EVAL_PAGE ;
    204        }
    205
    206        /**
    207         * タグリブオブジェクトをリリースします。
    208         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    209         *
    210         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
    211         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
    212         * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
    213         * @og.rev 4.3.4.0 (2008/12/01) save属性対応
    214         *
    215         */
    216        @Override
    217        protected void release2() {
    218                super.release2();
    219                command         = CMD_SET;
    220                key                     = null;
    221                value           = null;
    222                table           = null;
    223                dbid            = null;
    224                sql                     = null;
    225                save            = false;
    226        }
    227
    228        /**
    229         * コマンドを実行します。
    230         *
    231         * コマンドは,HTMLから(get/post)指定されますので,setCommand()メソッドで
    232         * 登録します。
    233         * コマンドを登録すると同時に,実行も行ないます。
    234         *
    235         * @og.rev 3.5.5.3 (2004/04/09) 値が null の場合は、""(ゼロ文字列)を返すフラグを採用
    236         *
    237         * @param   command コマンド (public static final 宣言されている文字列)
    238         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.UserInfoTag.CMD_GET">コマンド定数</a>
    239         */
    240        protected void commandExec( final String command ) {
    241                if( CMD_SQL.equals( command ) ) { setSQLAttribute() ; }
    242                else if( CMD_SET.equals(    command ) ) { setAttribute() ;    }
    243                else if( CMD_GET.equals(    command ) ) { getAttribute() ;    }
    244                else if( CMD_NVLGET.equals( command ) ) { getAttribute() ;    } // 3.5.5.3 (2004/04/09)
    245                else if( CMD_REMOVE.equals( command ) ) { removeAttribute() ; }
    246        }
    247
    248        /**
    249         * UserInfoの文字列を登録します。
    250         *
    251         * @og.rev 4.3.4.0 (2008/12/01) GE20(ユーザー定数)へ登録するかのフラグを追加
    252         *
    253         */
    254        private void setAttribute() {
    255                setUserInfo( key, value, save );
    256        }
    257
    258        /**
    259         * UserInfoの文字列を作成します。
    260         *
    261         */
    262        private void getAttribute() {
    263                value = getUserInfo( key );
    264        }
    265
    266        /**
    267         * UserInfoの文字列を削除します。
    268         *
    269         * @og.rev 5.3.6.0 (2011/06/01) GE20(ユーザー定数)から削除するかのフラグを追加
    270         */
    271        private void removeAttribute() {
    272                final UserInfo userInfo = getUser();
    273                userInfo.removeAttribute( key, save );
    274        }
    275
    276        /**
    277         * UserInfoの文字列を指定のSQL文より作成します。
    278         *
    279         * @og.rev 4.3.4.0 (2008/12/01) GE20(ユーザー定数)へ登録するかのフラグを追加
    280         *
    281         */
    282        private void setSQLAttribute() {
    283                if( table == null || table.getRowCount() == 0 ) { return ; }
    284
    285                final int row    = 0;
    286                final int clmCnt = table.getColumnCount();
    287                for( int clm=0; clm<clmCnt; clm++ ) {
    288                        final String clmkey = table.getColumnName( clm );
    289                        final String clmval = table.getValue( row,clm );
    290                        setUserInfo( clmkey, clmval, save );
    291                }
    292        }
    293
    294        /**
    295         * 【TAG】コマンド (SET,GET,NVLGET,REMOVE,SQL)をセットします(初期値:SET)。
    296         *
    297         * @og.tag
    298         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
    299         * フィールド定数値のいずれかを、指定できます。
    300         * 何も設定されない、または、null の場合は、"SET" が初期値にセットされます。
    301         * SQL の場合、検索結果の戻り値が複数存在する場合は、最初の１件目のみ使用します。
    302         *
    303         * @param       cmd コマンド (public static final 宣言されている文字列)
    304         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.UserInfoTag.CMD_SET">コマンド定数</a>
    305         */
    306        public void setCommand( final String cmd ) {
    307                final String cmd2 = getRequestParameter( cmd );
    308                if( cmd2 != null && cmd2.length() > 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
    309        }
    310
    311        /**
    312         * 【TAG】UserInfo に登録するキーをセットします(予約語:JNAME,ID,PASSWD,IDNO,INFO,LANG,ROLE,IPADDRESS,LOGINTIME)。
    313         *
    314         * @og.tag UserInfo に登録するキーをセットします。
    315         *
    316         * @param       inkey 登録するキー
    317         */
    318        public void setKey( final String inkey ) {
    319                key = getRequestParameter( inkey ).toUpperCase(Locale.JAPAN);
    320                if( key.startsWith( "USER." ) ) {
    321                        key = key.substring( 5 );
    322                }
    323        }
    324
    325        /**
    326         * 【TAG】UserInfo に登録する値をセットします。
    327         *
    328         * @og.tag UserInfo に登録する値をセットします。
    329         *
    330         * @param       val     登録値
    331         */
    332        public void setValue( final String val ) {
    333                value = getRequestParameter( val );
    334        }
    335
    336        /**
    337         * 【TAG】UserInfo に登録した値を永続化するかを指定します(初期値:false)。
    338         *
    339         * @og.tag
    340         * UserInfo に登録した値を永続化するかを指定します。
    341         * trueが指定された場合、UserInfoに設定された値は、GE20(ユーザー定数)に保存され、
    342         * UserInfoが再作成されるタイミングで自動的に復元されます。
    343         * ここで、登録された値は、そのユーザーの全てのロールに対して有効となります。
    344         * 初期値は、false(永続化しない)です。
    345         *
    346         * @param       sv      登録値を永続化するか
    347         */
    348        public void setSave( final String sv ) {
    349                save = nval( getRequestParameter( sv ),save );
    350        }
    351
    352        /**
    353         * 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します。
    354         *
    355         * @og.tag Queryオブジェクトを作成する時のDB接続IDを指定します。
    356         *
    357         * @param       id データベース接続ID
    358         */
    359        public void setDbid( final String id ) {
    360                dbid = nval( getRequestParameter( id ),dbid );
    361        }
    362
    363        /**
    364         * このオブジェクトの文字列表現を返します。
    365         * 基本的にデバッグ目的に使用します。
    366         *
    367         * @return このクラスの文字列表現
    368         * @og.rtnNotNull
    369         */
    370        @Override
    371        public String toString() {
    372                return ToString.title( this.getClass().getName() )
    373                                .println( "VERSION"                     ,VERSION        )
    374                                .println( "command"                     ,command        )
    375                                .println( "key"                         ,key            )
    376                                .println( "value"                       ,value          )
    377                                .println( "dbid"                        ,dbid           )
    378                                .println( "sql"                         ,sql            )
    379                                .println( "save"                        ,save           )
    380                                .println( "Other..."    ,getAttributes().getAttribute() )
    381                                .fixForm().toString() ;
    382        }
    383}