    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.db.DBTableModel;
    021import org.opengion.hayabusa.db.Query;
    022import org.opengion.hayabusa.resource.GUIInfo;
    023
    024import org.opengion.fukurou.util.StringUtil ;
    025import static org.opengion.fukurou.util.StringUtil.nval ;
    026
    027/**
    028 * 【廃止】SQL文を直接指定して、データベースに追加/更新/削除を行います(queryType="JDBCPrepared")。
    029 *
    030 * 存在チェックを行う場合は、tableExist タグと併用してください。
    031 * 複雑な処理が必要な場合は、従来より使用しています、PLSQLをCALLする、
    032 * plsqlUpdateタグを使用してください。
    033 *
    034 * ※ このタグは、Transaction タグの対象です。
    035 *
    036 * @og.formSample
    037 * ●形式：&lt;og:update command="…" names="…" queryType="JDBCPrepared" &gt;
    038 *             {&#064;SQL}
    039 *         &lt;/og:update&gt;
    040 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
    041 *
    042 * ●Tag定義：
    043 *   &lt;og:update
    044 *       queryType          【廃止】Query を発行する為のクラスIDを指定します(初期値:JDBCPrepared)
    045 *       command            【TAG】コマンド(NEW,RENEW)をセットします(PlsqlUpdateTag,UpdateTag の場合は、ENTRY)
    046 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
    047 *       displayMsg         【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=])
    048 *       names              【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します
    049 *       quotCheck          【TAG】リクエスト情報の クォーティション(') 存在チェックを実施するかどうか[true/false]を設定します(初期値:USE_SQL_INJECTION_CHECK)
    050 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
    051 *       dbid               【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します
    052 *       xssCheck           【TAG】リクエスト情報の HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true])
    053 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    054 *   &gt;   ... Body ...
    055 *   &lt;/og:update&gt;
    056 *
    057 * ●使用例
    058 *    ・引数/プロシジャーを他のJSPから渡す場合
    059 *    【copy.jsp】
    060 *        &lt;og:value scope=&quot;session&quot; key=&quot;names&quot; value=&quot;CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG&quot; /&gt;
    061 *        &lt;og:value scope=&quot;session&quot; key=&quot;SQL&quot; &gt;
    062 *          INSERT INTO GE41
    063 *               (CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG,
    064 *               FGJ,DYSET,DYUPD,USRSET,USRUPD,PGUPD)
    065 *          VALUES
    066 *               (?,?,?,?,?,?,
    067 *               &#39;1&#39;,&#39;{&#064;USER.YMDH}&#39;,&#39;{&#064;USER.YMDH}&#39;,&#39;{&#064;USER.ID}&#39;,&#39;{&#064;USER.ID}&#39;,&#39;{&#064;GUI.KEY}&#39;)
    068 *        &lt;/og:value&gt;
    069 *
    070 *    【entry.jsp】
    071 *        &lt;og:update
    072 *            command   = &quot;{&#064;command}&quot;
    073 *            queryType = &quot;JDBCPrepared&quot;
    074 *            names     = &quot;{&#064;names}&quot;  &gt;
    075 *        {&#064;SQL}
    076 *        &lt;/og:update&gt;
    077 *
    078 *        &lt;!-- 前画面で指定のSQL文を削除します。(scope=&quot;session&quot;なので削除が必要。) --&gt;
    079 *        &lt;og:value scope=&quot;session&quot; key=&quot;names&quot; command=&quot;REMOVE&quot; /&gt;
    080 *        &lt;og:value scope=&quot;session&quot; key=&quot;SQL&quot;   command=&quot;REMOVE&quot; /&gt;
    081 *
    082 *    ・引数/プロシジャーを直接書く場合
    083 *    【entry.jsp】
    084 *        &lt;og:update
    085 *            command   = &quot;{&#064;command}&quot;
    086 *            queryType = &quot;JDBCPrepared&quot;
    087 *            names     = &quot;CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG&quot;
    088 *        &gt;
    089 *            INSERT INTO GE41
    090 *                (CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG,
    091 *                 FGJ,DYSET,DYUPD,USRSET,USRUPD,PGUPD)
    092 *            VALUES
    093 *                (?,?,?,?,?,?,
    094 *                 &#39;1&#39;,&#39;{&#064;USER.YMDH}&#39;,&#39;{&#064;USER.YMDH}&#39;,&#39;{&#064;USER.ID}&#39;,&#39;{&#064;USER.ID}&#39;,&#39;{&#064;GUI.KEY}&#39;)
    095 *        &lt;/og:update&gt;
    096 *
    097 * @og.rev 4.0.0.0 (2005/01/31) 廃止
    098 * @og.group (廃止)ＤＢ登録
    099 *
    100 * @deprecated 4.0.0 (2005/01/31) 廃止。tableUpdate を利用するようにしてください。
    101 * @version  4.0
    102 * @author   Kazuhiko Hasegawa
    103 * @since    JDK5.0,
    104 */
    105@Deprecated public class UpdateTag extends QueryTag {
    106        //* このプログラムのVERSION文字列を設定します。   {@value} */
    107        private static final String VERSION = "4.0.0.0 (2005/01/31)" ;
    108
    109        private static final long serialVersionUID = 400020050131L ;
    110
    111        /** command 引数に渡す事の出来る コマンド  登録{@value} */
    112        public static final String CMD_ENTRY  = "ENTRY" ;
    113        /** command 引数に渡す事の出来る コマンド リスト  */
    114        private static final String COMMAND_LIST = CMD_ENTRY;
    115
    116        /**
    117         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    118         *
    119         * @return      後続処理の指示
    120         */
    121        @Override
    122        public int doStartTag() {
    123                dyStart = System.currentTimeMillis();
    124
    125                table = (DBTableModel)getObject( tableId );
    126                if( table == null || table.getRowCount() == 0 ||
    127                        ! check( command, COMMAND_LIST ) ) { return SKIP_BODY ; }
    128                return EVAL_BODY_BUFFERED ;     // Body を評価する。( extends BodyTagSupport 時)
    129        }
    130
    131        /**
    132         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    133         *
    134         * @og.rev 3.5.5.8 (2004/05/20) ErrorMessage オブジェクトを、正常終了時、クリア
    135         *
    136         * @return      後続処理の指示
    137         */
    138        @Override
    139        public int doEndTag() {
    140                debugPrint();           // 4.0.0 (2005/02/28)
    141
    142                if( check( command, COMMAND_LIST ) ) {
    143                        removeSessionAttribute( errMsgId );
    144                }
    145
    146                executeCount = getParameterRows().length ;              // チェック行の数が登録件数と仮定
    147
    148                // 4.0.0 (2005/01/31) 処理時間集計
    149                long dyTime = System.currentTimeMillis()-dyStart;
    150
    151                // 4.0.0 (2005/01/31) セキュリティチェック(データアクセス件数登録)
    152                GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY );
    153                if( guiInfo != null ) { guiInfo.addWriteCount( executeCount,dyTime,sql ); }
    154
    155                return EVAL_PAGE ;
    156        }
    157
    158        /**
    159         * Query を実行します。
    160         *
    161         * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更
    162         * @og.rev 3.4.0.0 (2003/09/01) 登録エラー時のキーと値を表示するように変更。
    163         * @og.rev 3.5.0.0 (2003/09/17) カラム名ではなく、カラム番号を先に求めておく方式に変更。
    164         * @og.rev 3.5.6.0 (2004/06/18) DBRowHeader のパッケージプライベート化に伴なう変更
    165         * @og.rev 4.0.0.0 (2005/01/31) getParameterRows() を使用するように変更
    166         *
    167         * @param   query オブジェクト
    168         */
    169        @Override
    170        protected void execute( final Query query ) {
    171                // long st = System.currentTimeMillis();
    172                String[] values    = null;
    173                int row = 0;
    174                try {
    175                        if( names == null ) {
    176                                query.execute( null );
    177                        }
    178                        else {
    179                                int[] rowNo = getParameterRows();               // 4.0.0 (2005/01/31)
    180                                if( rowNo.length > 0 ) {
    181                                        int[] clmNo = getTableColumnNo( StringUtil.csv2Array( names ) );
    182                                        values    = null;
    183                                        // 逆順にDELETEしないと、行番号がずれてしまう。
    184                                        for( int j=rowNo.length-1; j>=0; j-- ) {
    185                                                row = rowNo[j];
    186                                                values = getTableModelData( clmNo,row );        // 3.5.0.0
    187                                                query.execute( values );
    188                                                if( DBTableModel.DELETE_TYPE.equals( table.getModifyType( row ) ) ) {
    189                                                        table.removeValue( row );
    190                                                }
    191                                                else {
    192                                                        table.resetModify( row );
    193                                                }
    194                                        }
    195                                }
    196                        }
    197                        if( query.isUpdate() ) { query.commit(); }
    198                }
    199                catch( HybsSystemException ex ) {
    200                        query.rollback();
    201        // 3.4.0.0 (2003/09/01) 登録エラー時のキーと値を表示するように変更。
    202                        String errMsg = "DATABASE ERROR! "
    203                                + "rowNo=[" + ( row ) + "] " + HybsSystem.CR
    204                                + "nameArray=[" + names + "]" + HybsSystem.CR
    205                                + "values=[" + StringUtil.array2csv( values ) + "]" + HybsSystem.CR ;
    206                        throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
    207                }
    208                finally {
    209                        if( query != null ) { query.close(); }
    210                }
    211                // System.out.println( ( System.currentTimeMillis() - st ) + " ms" );
    212        }
    213
    214        /**
    215         *  カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。
    216         *
    217         * @og.rev 3.5.0.0 (2003/09/17) 新規追加
    218         *
    219         * @param       nameArray カラム名配列
    220         *
    221         * @return      カラムNo配列
    222         */
    223        private int[] getTableColumnNo( final String[] nameArray ) {
    224                int[] clmNo = new int[ nameArray.length ];
    225                for( int i=0; i<clmNo.length; i++ ) {
    226                        clmNo[i] = table.getColumnNo( nameArray[i] );
    227                }
    228                return clmNo;
    229        }
    230
    231        /**
    232         *  指定の行番号の、カラムNo配列(int[])に対応した値の配列を返します。
    233         *
    234         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を
    235         * 処理の対象とします。
    236         *
    237         * @og.rev 3.5.0.0 (2003/09/17) カラム名ではなく、カラム番号を受け取るように修正。
    238         *
    239         * @param       clmNo   カラムNo配列
    240         * @param       row             行番号
    241         *
    242         * @return      行番号とカラムNo配列に対応した、値の配列
    243         */
    244        private String[] getTableModelData( final int[] clmNo,final int row ) {
    245                String[] values = new String[ clmNo.length ];
    246                for( int i=0; i<values.length; i++ ) {
    247                        values[i] = table.getValue( row,clmNo[i] ) ;
    248                }
    249                return values;
    250        }
    251
    252        /**
    253         * 【廃止】Query を発行する為のクラスIDを指定します({@og.doc03Link queryType 初期値:JDBCPrepared})。
    254         *
    255         * @og.tag
    256         * 登録を実行する手段は、Query インターフェースの実装クラスになります。
    257         * このタグでは、Query.execute( String[] ) メソッドが複数回呼ばれます。
    258         * これは、DBTableModelの選択された行に対して、繰り返し呼ばれます。
    259         *
    260         * 通常、このタグを使用する場合は、queryType="JDBCPrepared" を指定します。
    261         *
    262         * タグにより使用できる／出来ないがありますが、これは、org.opengion.hayabusa.db
    263         * 以下の Query_**** クラスの **** を与えます。
    264         * これらは、Query インターフェースを継承したサブクラスです。
    265         * {@og.doc03Link queryType Query_**** クラス}
    266         *
    267         * @og.rev 3.5.4.2 (2003/12/15) JavaDocコメント用にメソッド追加。
    268         *
    269         * @param       id Query を発行する為の実クラス ID
    270         * @see         org.opengion.hayabusa.db.Query  Queryのサブクラス
    271         * @see         org.opengion.hayabusa.db.Query#execute( String[] )
    272         * @deprecated クラスが廃止
    273         */
    274        @Deprecated public void setQueryType( final String id ) {
    275                super.setQueryType( nval( id,"JDBCPrepared" ) );
    276        }
    277}