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 static org.opengion.fukurou.util.StringUtil.nval;
019
020import java.io.File;
021
022import org.opengion.fukurou.db.ConnectionFactory;
023import org.opengion.fukurou.db.DatabaseConfig;
024import org.opengion.fukurou.util.StringUtil;
025import org.opengion.hayabusa.common.HybsSystem;
026import org.opengion.hayabusa.common.HybsSystemException;
027import org.opengion.hayabusa.db.DBTableModel;
028import org.opengion.hayabusa.db.DBTableModelUtil;
029
030/**
031 * DBConfig.xmlの編集を行うためのタグです。
032 *
033 * 自分自身のコンテキストのDBConfig.xmlの編集及び、ファイルパスを指定して他の
034 * コンテキストのDBConfig.xmlの編集を行うことができます。
035 *
036 * 編集タイプは、type属性により、「DBドライバークラス」と「DBIDの設定情報」の2つを
037 * 切り替えることができます。
038 *
039 * また、このタグ自体の機能としては、「取得」、「保存」、「情報」に分離されています。
040 *
041 * (1)取得(command="GET")
042 *  type属性で指定された情報を読み取り、DBTableModel形式に変換し、セッションに登録します。
043 *  (tableIdは"DEFAULT"です)
044 *
045 * (2)保存(command="SET")
046 *  セッションからDBTableModelを読み取り、type属性で指定された情報の形式にオブジェクト化し、
047 *  DBConfig.xmlに保存します。
048 *  (DBTableModelを取得するtableIdは"DEFAULT"です)
049 *
050 *  保存を実行すると、元のDBConfig.xmlファイルと同じ場所に、タイプスタンプ付きのバックアップ
051 *  ファイルが自動的に作成されます。
052 *
053 *  また、xmlFile(DBConfig.xml)を指定しない状態で、保存(command="SET")を行うと、
054 *  内部にキャッシュしている接続情報は、一旦全てクリアされます。
055 *
056 * (3)情報(command="INFO")
057 *  DBID情報のキーとタイトルから、プルダウンメニューを作成するための情報を画面出力します。
058 *  この値を、valueタグで取込み、columnタグのcodeKeyVal変数にセットすれば、DBIDの選択メニューを
059 *  作成できます。開発用に接続先を切り替える処理等に使います。
060 *
061 * @og.formSample
062 * ●形式:<dbConfigEditor command="..." type="..." xmlFile="..." />
063 * ●body:なし
064 *
065 * ●Tag定義:
066 *   <og:dbConfigEditor
067 *       command            【TAG】DBConfig.xmlに対する操作のコマンド(GET/SET/INFO)を指定します(初期値:GET)
068 *       type               【TAG】DBConfig.xmlに対する操作のタイプ(DBID/CLASS)を指定します(初期値:DBID)
069 *       xmlFile            【TAG】編集を行うDBConfig.xmlのファイルのパスを指定します(初期値:自身のDBConfig.xml)
070 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
071 *   />
072 *
073 * ●使用例
074 *    ・取得
075 *        <dbConfigEditor command="GET" type="{@TYPE}" xmlFile="{@DBCXML}" />
076 *
077 *    ・保存
078 *        <dbConfigEditor command="SET" type="{@MEM.TYPE}" xmlFile="{@MEM.DBCXML}" />
079 *
080 *    ・情報
081 *        <value command="SET" key="DBID_INFO" >
082 *          <dbConfigEditor command="INFO" />
083 *        </value>
084 *
085 *        <column name="DBID_INFO" codeKeyVal="{@DBID_INFO}" />
086 *
087 * @og.group その他部品
088 *
089 * @version  4.0
090 * @author       Hiroki Nakamura
091 * @since    JDK5.0,
092 */
093public class DBConfigEditorTag extends CommonTagSupport {
094        //* このプログラムのVERSION文字列を設定します。   {@value} */
095        private static final String VERSION = "5.6.7.0 (2013/07/27)" ;
096
097        private static final long serialVersionUID = 567020130727L ;
098
099        private transient DBTableModel  table   = null;         // 5.1.9.0 (2010/08/01) transient 追加
100        private String                  command = "GET";
101        private String                  type    = "DBID";
102        private String                  xmlFile = null;
103
104        /**
105         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
106         *
107         * @return      後続処理の指示( SKIP_BODY )
108         */
109        @Override
110        public int doStartTag() {
111                startQueryTransaction( HybsSystem.TBL_MDL_KEY );
112                return  SKIP_BODY ;
113        }
114
115        /**
116         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
117         *
118         * @og.rev 5.6.7.0 (2013/07/27) command="INFO" 対応
119         *
120         * @return      後続処理の指示
121         */
122        @Override
123        public int doEndTag() {
124                debugPrint();
125
126                // DatabaseConfigオブジェクトを取得します。
127                DatabaseConfig dbc = null;
128                if( xmlFile == null ) {
129                        dbc = new DatabaseConfig();
130                }
131                else {
132                        if( !( new File( xmlFile ) ).exists() ) {
133                                throw new HybsSystemException( "編集対象のDBConfig.xmlが存在しません。File=[" + xmlFile + "]" );
134                        }
135                        dbc = new DatabaseConfig( xmlFile );
136                }
137
138                // 編集タイプに応じてキー情報をセットします。
139                String[] keys = null;
140                if( "DBID".equals( type ) ) {
141                        keys = DatabaseConfig.getDbidInfoKeys();
142                }
143                else if( "CLASS".equals( type ) ) {
144                        keys = new String[1];
145                        keys[0] = DatabaseConfig.getDriverKey();
146                }
147
148                // DBConfig.xmlから情報を取得します。
149                if( "GET".equals( command ) ) {
150                        table = getDBConfig( dbc, keys );
151
152                        if( table != null && !commitTableObject( HybsSystem.TBL_MDL_KEY, table ) ) {
153                                jspPrint( "QueryTag Query処理が割り込まれました。DBTableModel は登録しません。" );
154                                return SKIP_PAGE ;
155                        }
156                }
157                // DBConfig.xmlに情報を保存します。
158                else if( "SET".equals( command ) ) {
159                        setDBConfig( dbc, keys );
160
161                        // xmlFileが指定されていない(=自信のDBConfig.xml)を書き換えた場合は、キャッシュをクリアします。
162                        if( xmlFile == null ) {
163                                ConnectionFactory.realClose();
164                                ConnectionFactory.init( HybsSystem.getContextName(), null );
165                        }
166                }
167                // 5.6.7.0 (2013/07/27) command="INFO" 対応
168                else if( "INFO".equals( command ) ) {
169                        jspPrint( dbc.getCodeKeyVal() );
170                }
171
172                return EVAL_PAGE ;
173        }
174
175        /**
176         * DBConfig.xmlから情報を取得します。
177         *
178         * @param       dbc             DatabaseConfigオブジェクト
179         * @param       keys    編集する情報のカラムキー配列
180         *
181         * @return      テーブルモデル
182         */
183        private DBTableModel getDBConfig( final DatabaseConfig dbc, final String[] keys ) {
184                String[][] vals = null;
185                if( "DBID".equals( type ) ) {
186                        vals = dbc.getDbidInfo();
187                }
188                else if( "CLASS".equals( type ) ) {
189                        String[] tmpVals = dbc.getDriverList();
190                        vals = new String[tmpVals.length][1];
191                        for( int i=0; i<tmpVals.length; i++ ) {
192                                vals[i][0] = tmpVals[i];
193                        }
194                }
195
196                return DBTableModelUtil.makeDBTable( keys, vals, getResource() );
197        }
198
199        /**
200         * DBConfig.xmlに情報を保存します。
201         *
202         * @param dbc DatabaseConfigオブジェクト
203         * @param keys 編集する情報のカラムキー配列
204         */
205        private void setDBConfig( final DatabaseConfig dbc, final String[] keys ) {
206                table = (DBTableModel)getObject( HybsSystem.TBL_MDL_KEY );
207
208                String tmpKeys = StringUtil.array2csv( table.getNames() );
209                if( !StringUtil.array2csv( keys ).equals( tmpKeys ) ) {
210                        throw new RuntimeException( "DBTableModelのキーが不正です" );
211                }
212
213                int row = table.getRowCount();
214                String[][] vals = new String[row][keys.length];
215                for( int i=0; i<row; i++ ) {
216                        vals[i] = table.getValues( i );
217                }
218
219                if( "DBID".equals( type ) ) {
220                        dbc.setDbidInfo( vals );
221                }
222                else if( "CLASS".equals( type ) ) {
223                        String[] tmpVals = new String[vals.length];
224                        for( int i=0; i<vals.length; i++ ) {
225                                tmpVals[i] = vals[i][0];
226                        }
227                        dbc.setDriverList( tmpVals );
228                }
229        }
230
231        /**
232         * タグリブオブジェクトをリリースします。
233         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
234         *
235         */
236        @Override
237        protected void release2() {
238                super.release2();
239                command                 = "GET";
240                type                    = "DBID";
241                xmlFile                 = null;
242        }
243
244        /**
245         * 【TAG】DBConfig.xmlに対する操作のコマンド(GET/SET/INFO)を指定します(初期値:GET)。
246         *
247         * @og.tag
248         *  GET  ⇒ typeに応じた情報をDBConfig.xmlから読み出し、DBTableModelに登録します。
249         *  SET  ⇒ typeに応じた情報をDBTableModelから読み出し、DBConfig.xmlに登録します。
250         *  INFO ⇒ DBConfig.xmlに登録されている DBID のキーとタイトルを連結したコードリソース情報を画面出力します。
251         *
252         * なお、保存(SET)を実行すると、元のDBConfig.xmlファイルと同じ場所に、タイプスタンプ付きの
253         * バックアップファイルが自動的に作成されます。
254         *
255         * また、xmlFile(DBConfig.xml)を指定しない状態で、保存(command="SET")を行うと、
256         * 内部にキャッシュしている接続情報は、一旦全てクリアされます。
257         *
258         * @og.rev 5.6.7.0 (2013/07/27) command として使用できる文字列をチェックします。
259         *
260         * @param       cmd コマンド
261         */
262        public void setCommand( final String cmd ) {
263                command = nval( getRequestParameter( cmd ),command );
264
265                // 5.6.7.0 (2013/07/27) command として使用できる文字列をチェックします。
266                if( "|GET|SET|INFO|".indexOf( "|" + command + "|" ) < 0 ) {
267                                String errMsg = "commandは GET,SET,INFO のどれかです。"
268                                                        + "command=" + command ;
269                                throw new HybsSystemException( errMsg );
270                }
271        }
272
273        /**
274         * 【TAG】DBConfig.xmlに対する操作のタイプ(DBID/CLASS)を指定します(初期値:DBID)。
275         *
276         * @og.tag
277         *  DBID  ⇒ DBIDの各種情報を読み取り/書き込みします。
278         *  CLASS ⇒ ロードするDBドライバーの一覧を読み取り/書き込みします。
279         *
280         * @og.rev 5.6.7.0 (2013/07/27) type として使用できる文字列をチェックします。
281         *
282         * @param       tp タイプ
283         */
284        public void setType( final String tp ) {
285                type = nval( getRequestParameter( tp ),type );
286
287                // 5.6.7.0 (2013/07/27) type として使用できる文字列をチェックします。
288                if( "|DBID|CLASS|".indexOf( "|" + type + "|" ) < 0 ) {
289                                String errMsg = "typeは DBID,CLASS のどれかです。"
290                                                        + "type=" + type ;
291                                throw new HybsSystemException( errMsg );
292                }
293        }
294
295        /**
296         * 【TAG】編集を行うDBConfig.xmlのファイルのパスを指定します(初期値:自身のDBConfig.xml)。
297         *
298         * @og.tag
299         * 何も指定されない場合は、自身のコンテキストのDBConfig.xmlに対する編集となります。
300         *
301         * @param       file DBConfig.xmlのファイルパス
302         */
303        public void setXmlFile( final String file ) {
304                xmlFile = nval( getRequestParameter( file ),xmlFile );
305        }
306
307        /**
308         * このオブジェクトの文字列表現を返します。
309         * 基本的にデバッグ目的に使用します。
310         *
311         * @return このクラスの文字列表現
312         */
313        @Override
314        public String toString() {
315                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
316                                .println( "VERSION"             ,VERSION        )
317                                .println( "command"             ,command        )
318                                .println( "type"                ,type           )
319                                .println( "xmlFile"             ,xmlFile        )
320                                .println( "Other..."    ,getAttributes().getAttribute() )
321                                .fixForm().toString() ;
322        }
323}