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