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