    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.fukurou.db;
    017
    018import java.io.File;
    019import java.net.URL;
    020import java.util.ArrayList;
    021import java.util.LinkedHashMap;
    022import java.util.List;
    023import java.util.Locale;
    024import java.util.Map;
    025import java.util.Collections;
    026
    027import org.opengion.fukurou.util.StringUtil;
    028import org.opengion.fukurou.util.FileUtil;
    029import org.opengion.fukurou.util.LogWriter;
    030import org.opengion.fukurou.xml.DomParser;
    031import org.w3c.dom.Document;
    032import org.w3c.dom.Element;
    033import org.w3c.dom.Node;
    034import org.w3c.dom.NodeList;
    035
    036/**
    037 * DB設定XMLの内容をJAXBを利用してロードする
    038 * Driverをロードする
    039 * 上記２つの機能を備えたクラスです
    040 *
    041 * 外部からはgetDbidメソッドを利用してDB設定(ExpandedDbid型)を取得します。
    042 * DB設定情報が無い場合にXMLを読みにいきます。
    043 * このDBIDを決めるキーは、内部取り込み字に、大文字変換されますので、大文字・
    044 * 小文字の区別はありません。
    045 *
    046 * @og.rev 4.0.0.0 (2007/10/25) 新規作成
    047 * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止
    048 * @og.group 初期化
    049 *
    050 * @version  4.0
    051 * @author 高橋正和
    052 * @since   JDK6.0,
    053 */
    054public class DatabaseConfig {
    055
    056        // fukurou内で完結させるため、HybsDataからは読み込まずにここに書く
    057        private static final String DEFAULT_DRIVER       = "oracle.jdbc.OracleDriver";
    058
    059        // XMLファイル関連
    060        private final String xmlFilename;                               // 5.7.2.2 (2014/01/24)
    061
    062        // 6.0.0.1 (2014/04/25) private 変数で、final 化できるものは、final 宣言する。
    063//      private final Map<String, EDbid> dbidMap = new LinkedHashMap<String, EDbid>();          // 5.6.7.0 (2013/07/27)
    064//      private final List<String> driverList = new ArrayList<String>();
    065        private final Map<String, EDbid> dbidMap = Collections.synchronizedMap( new LinkedHashMap<String, EDbid>() );   // 5.6.7.0 (2013/07/27)
    066        private final List<String> driverList = Collections.synchronizedList( new ArrayList<String>() );
    067
    068        // 5.6.7.0 (2013/07/27) プルダウンメニュー用の情報の、キャッシュ用変数。
    069        private String codeKeyVal = null;               // 初めて要求されたときに、セットします。
    070
    071        // 5.6.6.0 (2013/07/05) 表題(title)属性を追加
    072        private static final String[] DBID_INFO_KEYS
    073                                = { "dbidKey", "title", "url", "user", "password", "readonly"
    074                                        , "mincount", "maxcount", "pooltime", "applicationInfo","property" };
    075
    076        /* DBDRIVERのキーのを管理します。5.1.9.0 (2010/08/01) */
    077        private static final String DBDRIVER_CLASS_KEY = "class";
    078
    079        /**
    080         * 初期値を使ってXMLを読み込む
    081         * xmlFilenameの初期値は../DBConfig.xml
    082         *
    083         * @og.rev 4.3.1.1 (2008/08/23) 自分のコンストラクターを呼ぶように修正
    084         */
    085        public DatabaseConfig() {
    086                this( "../DBConfig.xml" );
    087        }
    088
    089        /**
    090         * XMLファイルの名前を指定して読み込む
    091         *
    092         * @og.rev 5.1.9.0 (2010/08/01) クラスローダー外からでもDBConfig.xmlを取得できるようにする
    093         * @og.rev 5.6.7.0 (2013/07/27) オブジェクト作成時に初期化も行っておきます。
    094         * @og.rev 5.6.8.2 (2013/09/20) Tomcat8で、クラスローダーが変更されているのでその対応
    095         * @og.rev 5.7.2.2 (2014/01/24) WEB-INF/classes フォルダがないと、xmlURL がnull になる対応。
    096         * @og.rev 5.7.2.3 (2014/01/31) ファイルの存在チェックを追加します。
    097         *
    098         * @param       xmlfile XMLファイルの名前
    099         */
    100        public DatabaseConfig( final String xmlfile ) {
    101                String fileName = null;
    102
    103                ClassLoader clsl        = getClass().getClassLoader();
    104                URL xmlURL                      = clsl.getResource( xmlfile );
    105
    106                if( xmlURL != null ) {
    107                        fileName = xmlURL.getFile();
    108                        // 5.7.2.3 (2014/01/31) ファイルの存在チェックを追加します。
    109                        if( ! new File( fileName ).exists() ) { fileName = null; }
    110                }
    111                // 5.6.8.2 (2013/09/20) Tomcat8で、xmlURL が取得できなくなっている・・・ようだ。
    112                else {
    113                        xmlURL = clsl.getResource( "/" );               // クラスパスのベースURL
    114                        // 5.7.2.2 (2014/01/24) Tomcat7で、WEB-INF/classes フォルダがないと、xmlURL がnull になる。
    115                        if( xmlURL != null ) {
    116                                File temp = new File( xmlURL.getPath() , xmlfile );
    117                                if( temp.exists() ) { fileName = temp.getAbsolutePath(); }
    118                        }
    119                }
    120
    121                // 5.1.9.0 (2010/08/01)  クラスローダー外からでもDBConfig.xmlを取得できるようにする
    122                if( fileName == null && new File( xmlfile ).exists() ) {
    123                        fileName = xmlfile;
    124                }
    125
    126                if( fileName == null ) {
    127                        // 5.5.7.2 (2012/10/09) コメント追加
    128                        String errMsg = "DBConfig.xmlが見つかりません。File=[" + xmlfile + "]\n"
    129                                                                + " WEB-INF/classes フォルダがないと、相対パスで見つけることができません。" ;
    130                        throw new RuntimeException( errMsg );
    131                }
    132
    133                xmlFilename                     = fileName;
    134
    135                init();                 // 5.6.7.0 (2013/07/27)
    136        }
    137
    138        /**
    139         * dbidKeyをキーにしてExpandedDbid型でマップの内容を返す。
    140         * 存在しない場合はNULLを返します。
    141         * キーが無い場合に初期化を行う。
    142         *
    143         * @og.rev 4.0.0.1 (2007/12/04) EDbid#clone() 廃止
    144         * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。
    145         * @og.rev 6.0.0.1 (2014/04/25) Collections.synchronizedMap を使用します。
    146         *
    147         * @param key XMLで登録したdbidKey
    148         *
    149         * @return EDbid型オブジェクト
    150         */
    151//      public synchronized EDbid getDbid( final String key ) {
    152        public EDbid getDbid( final String key ) {
    153                return dbidMap.get( key.toUpperCase( Locale.JAPAN ) ) ;
    154        }
    155
    156        /**
    157         * マップをクリアします。
    158         * XMLファイルを再読み込みする場合に使用します。
    159         *
    160         * @og.rev 5.1.9.0 (2010/08/01) ドライバーのリストもクリアする。
    161         * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。
    162         * @og.rev 6.0.0.1 (2014/04/25) Collections.synchronizedMap を使用します。
    163         */
    164//      public synchronized void reload() {
    165        public void reload() {
    166                dbidMap.clear();
    167                driverList.clear();
    168                init();
    169        }
    170
    171        /**
    172         * 初期化処理
    173         *
    174         * DB設定XMLファイル(DBConfig.xml)を読み込みます。
    175         * このファイルから、ドライバーリストの取得、DBIDのオブジェクトマップの作成を
    176         * 行います。
    177         * EDbidオブジェクト は、環境変数で、共通の初期値を定義しておくことが可能です。
    178         * 項目として、REALM_URL、REALM_NAME、REALM_PASSWORD が設定可能です。
    179         *
    180         * ドライバーリストの取得後、Class.forName で、ドライバの登録も行います。
    181         *
    182         * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止
    183         * @og.rev 5.6.7.0 (2013/07/27) dbidMap,driverList を書き込むのではなく、作成します。
    184         */
    185        private void init() {
    186                Document doc = DomParser.read( new File(xmlFilename) ) ;
    187                Element firstRoot = doc.getDocumentElement();
    188
    189                makeDriverList( firstRoot );                            // 5.6.7.0 (2013/07/27)
    190
    191                // 5.6.7.0 (2013/07/27) を、かけておきます。
    192                synchronized ( this ) {
    193                        for( String dr : driverList ) {
    194                                try {
    195                                        Class.forName( dr );
    196                                } catch ( ClassNotFoundException ex ) {
    197                                        String errMsg = "ドライバクラスが見つかりません。[" + dr + "]" ;
    198                                        LogWriter.log( errMsg );
    199                                        LogWriter.log( ex );
    200                                }
    201                        }
    202                }
    203
    204                EDbid defDdbid = new EDbid();           // 初期値
    205                defDdbid.setUrl(                System.getenv( "REALM_URL" ) );
    206                defDdbid.setUser(               System.getenv( "REALM_NAME" ) );
    207                defDdbid.setPassword(   System.getenv( "REALM_PASSWORD" ) );
    208
    209                makeDbidMap( firstRoot,defDdbid );                              // 5.6.7.0 (2013/07/27)
    210        }
    211
    212        /**
    213         * ドライバーリストを取得します。
    214         *
    215         * DB設定XMLファイル(DBConfig.xml)の、class タグを取り込みます。
    216         * このファイルから、ドライバーリストを取得します。
    217         *
    218         * 内部的に３段階の処理が実行されます。
    219         * 第１Step:DBConfig.xml から、ドライバーリストを取得
    220         * 第２Step:ドライバーリストが存在しない場合、環境変数の REALM_DRIVER からドライバーを取得
    221         * 第３Step:それでも存在しない場合、このクラスの DEFAULT_DRIVER 定数 からドライバーを取得
    222         *
    223         * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止
    224         * @og.rev 5.1.9.0 (2010/08/01) ドライバ一覧のListをオブジェクト変数化
    225         * @og.rev 5.6.7.0 (2013/07/27) driverList を書き込むのではなく、作成します。
    226         * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。
    227         *
    228         * @param       element DB設定XMLファイルのElementオブジェクト
    229         */
    230        private void makeDriverList( final Element element ) {
    231
    232                NodeList list = element.getElementsByTagName( "class" ) ;
    233                int num = list.getLength();
    234                for (int i = 0; i < num; i++) {
    235                        Element cls = (Element)list.item(i);
    236                        driverList.add( cls.getTextContent() );
    237                }
    238
    239                if( driverList.isEmpty() ) {
    240                        String realmDriver = System.getenv( "REALM_DRIVER" );
    241                        if( realmDriver != null && realmDriver.length() > 0 ) {
    242                                driverList.add( realmDriver );
    243                        }
    244                }
    245
    246                if( driverList.isEmpty() ) { driverList.add( DEFAULT_DRIVER ); }
    247        }
    248
    249        /**
    250         * EDbidオブジェクトのマップを取得します。
    251         *
    252         * DB設定XMLファイル(DBConfig.xml)の、dbid タグを取り込みます。
    253         * このファイルから、EDbidオブジェクトの属性情報を取得し、オブジェクトを構築します。
    254         *
    255         * EDbidオブジェクト は、初期値をコピーして、作成していきます。
    256         * EDbidオブジェクトをマップから取り出すキーとなる、dbidKey は、大文字化して設定します。
    257         *
    258         * @og.rev 5.1.7.0 (2010/06/01) org.opengion.fukurou.xml.jaxb.dbid 関係 廃止
    259         * @og.rev 5.1.9.0 (2010/08/01) Mapを返すように変更
    260         * @og.rev 5.5.2.0 (2012/05/01) property追加
    261         * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性の取得
    262         * @og.rev 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更。
    263         * @og.rev 5.6.7.0 (2013/07/27) dbidMap を書き込むのではなく、作成します。
    264         * @og.rev 5.6.7.0 (2013/07/27) synchronized メソッドにします。
    265         * @og.rev 5.6.7.1 (2013/08/09) DEFAULT と、RESOURCE の DBIDキーがなければ、内部的に作成します。
    266         * @og.rev 5.6.8.0 (2013/09/06) RESOURCE の DBIDキーを内部作成時に、title も設定します。
    267         *
    268         * @param  element DB設定XMLファイルのElementオブジェクト
    269         * @param  defDdbid 初期情報の設定された、EDbidオブジェクト
    270         */
    271        private void makeDbidMap( final Element element , EDbid defDdbid ) {
    272                NodeList list = element.getElementsByTagName( "dbid" ) ;
    273                int num = list.getLength();
    274                for (int i = 0; i < num; i++) {
    275                        Element ele = (Element)list.item(i);
    276                        NodeList childs = ele.getChildNodes();
    277                        int numChild = childs.getLength();
    278                        EDbid dbid = defDdbid.clone();          // 初期値をコピーして、作成
    279                        for (int j = 0; j < numChild; j++) {
    280                                Node nd = childs.item(j);
    281                                if( nd.getNodeType() == Node.ELEMENT_NODE ) {
    282                                        Element el = (Element)nd;
    283                                        String tag = el.getTagName();
    284                                        // dbidKey は、toUpperCase して、大文字のみとする。
    285                                        if( "dbidKey".equals( tag ) )   {
    286                                                String dbidKey = el.getTextContent();
    287                                                if( dbidKey != null && dbidKey.length() > 0 ) {
    288                                                        dbid.setDbidKey( dbidKey.toUpperCase( Locale.JAPAN ) );
    289                                                }
    290                                        }
    291                                        else if( "title".equals( tag ) )        { dbid.setTitle(        el.getTextContent() ); }                // 5.6.6.0 (2013/07/05) 表題(title)属性の取得
    292                                        else if( "url".equals( tag ) )          { dbid.setUrl(          el.getTextContent() ); }
    293                                        else if( "user".equals( tag ) )         { dbid.setUser(         el.getTextContent() ); }
    294                                        else if( "password".equals( tag ) ) { dbid.setPassword( el.getTextContent() ); }
    295                                        else if( "readonly".equals( tag ) ) { dbid.setReadonly( el.getTextContent() ); }
    296                                        else if( "mincount".equals( tag ) ) { dbid.setMincount( el.getTextContent() ); }
    297                                        else if( "maxcount".equals( tag ) ) { dbid.setMaxcount( el.getTextContent() ); }
    298                                        else if( "pooltime".equals( tag ) ) { dbid.setPooltime( el.getTextContent() ); }
    299                                        else if( "applicationInfo".equals( tag ) ) { dbid.setApplicationInfo( el.getTextContent() ); }
    300                                        else if ("property".equals( tag ) ) { dbid.addProp( el.getTextContent() ); } // 5.5.2.0 (2012/05/01)
    301                                        else {
    302                                                System.err.println( "警告：dbid に新しい属性が、追加されています。" );
    303                                        }
    304                                }
    305                        }
    306                        dbidMap.put( dbid.getDbidKey(), dbid );         // 5.6.7.0 (2013/07/27) 復活
    307                }
    308
    309                // 5.6.7.1 (2013/08/09) DEFAULT と、RESOURCE の DBIDキーがなければ、内部的に作成します。
    310                EDbid dbid_D = dbidMap.get( "DEFAULT" );                // DEFAULT が存在するか確認する。
    311                if( dbid_D == null ) {
    312                        dbid_D = defDdbid.clone();                                      // 初期値をコピー
    313                        dbid_D.setDbidKey( "DEFAULT" );
    314                        dbidMap.put( "DEFAULT", dbid_D );
    315                }
    316
    317                EDbid dbid_R = dbidMap.get( "RESOURCE" );               // RESOURCE が存在するか確認する。
    318                if( dbid_R == null ) {
    319                        dbid_R = dbid_D.clone();                                        // DEFAULT の DBIDをコピー(必ず存在するはず)
    320                        dbid_R.setDbidKey( "RESOURCE" );
    321                        dbid_R.setTitle( "RESOURCE" );                          // 5.6.8.0 (2013/09/06) title も設定します。
    322                        dbidMap.put( "RESOURCE", dbid_R );
    323                }
    324        }
    325
    326        /* ------------------------------------------------------------------------------------
    327         *
    328         * 以下は、DBConfig.xml編集用のメソッドです。
    329         * 編集用のメソッドでは、オブジェクト化されたDBID及びDBDRIVERの情報は使用せずに、
    330         * DBConfig.xmlからその情報を再度読み出して、SET/GETしています。
    331         * (オブジェクトとして依存しているのは、DBConfig.xmlのファイル名のみです)
    332         *
    333         * -------------------------------------------------------------------------------------
    334         */
    335        /**
    336         * DBIDとして管理している項目のキーの一覧を配列形式で返します。
    337         *
    338         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    339         *
    340         * @return 項目のキー一覧
    341         */
    342        public static String[] getDbidInfoKeys() {
    343                return DBID_INFO_KEYS.clone();
    344        }
    345
    346        /**
    347         * 全てのDBIDの属性情報のリスト(配列)で返します。
    348         *
    349         * 値の順番については、{@link #getDbidInfoKeys()}で返されるキーの一覧と同じです。
    350         *
    351         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    352         * @og.rev 5.5.2.1 (2012/05/07) propertiesを出力
    353         * @og.rev 5.6.6.0 (2013/07/05) 表題(title)属性を追加
    354         * @og.rev 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更。
    355         *
    356         * @return 全てのDBIDの属性情報のリスト(配列)
    357         * @see #getDbidInfoKeys()
    358         */
    359        public synchronized String[][] getDbidInfo() {
    360                String[][] dbidInfo = new String[dbidMap.size()][DBID_INFO_KEYS.length];
    361                int idx = 0;
    362                for( EDbid dbid : dbidMap.values() ) {
    363                        dbidInfo[idx][0] = dbid.getDbidKey();
    364                        dbidInfo[idx][1] = dbid.getTitle();                             // 5.6.6.0 (2013/07/05) 表題(title)属性を追加
    365                        dbidInfo[idx][2] = dbid.getUrl();
    366                        dbidInfo[idx][3] = dbid.getUser();
    367                        dbidInfo[idx][4] = dbid.getPassword();
    368                        dbidInfo[idx][5] = String.valueOf( dbid.isReadonly() );
    369                        dbidInfo[idx][6] = String.valueOf( dbid.getMincount() );
    370                        dbidInfo[idx][7] = String.valueOf( dbid.getMaxcount() );
    371                        dbidInfo[idx][8] = String.valueOf( dbid.getPooltime() );
    372                        dbidInfo[idx][9] = String.valueOf( dbid.isApplicationInfo() );
    373                        dbidInfo[idx][10]= String.valueOf( dbid.getProps().toString() ); // 5.5.2.1 (2012/05/07)
    374                        idx++;
    375                }
    376
    377                return dbidInfo;
    378        }
    379
    380        /**
    381         * 全てのDBIDの属性情報のリスト(配列)をセットします。
    382         *
    383         * このメソッドを呼び出すと、DBConfig.xmlで定義されているDBID情報一覧を"一旦削除し"、
    384         * その上で、引数のDBID情報一覧をDBConfig.xmlに書き込みます。
    385         *
    386         * 値の順番については、{@link #getDbidInfoKeys()}で返されるキーの一覧と同じです。
    387         *
    388         * 書き込みの直前に、同じフォルダにタイムスタンプを付加したバックアップファイルを作成します。
    389         *
    390         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    391         * @og.rev 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更。
    392         *
    393         * @param dbidVals 全てのDBIDの属性情報のリスト(配列)
    394         * @see #getDbidInfoKeys()
    395         */
    396        public void setDbidInfo( final String[][] dbidVals ) {
    397                FileUtil.copy( xmlFilename, xmlFilename + "_" + System.currentTimeMillis() );
    398
    399                Document doc = DomParser.read( new File(xmlFilename) ) ;
    400                Element firstRoot = doc.getDocumentElement();
    401                deleteChildElements( firstRoot, "dbid" );
    402
    403                if( dbidVals != null && dbidVals.length > 0 ) {
    404                        // 5.6.7.0 (2013/07/27) 内部MapをDBConfig.xmlの読み込み順に変更(なので、廃止)。
    405                        for( int i=0; i<dbidVals.length; i++ ) {
    406                                Element newEle = doc.createElement( "dbid" );
    407                                for( int j=0; j<dbidVals[i].length; j++ ) {
    408                                        Element newChEle = doc.createElement( DBID_INFO_KEYS[j] );
    409                                        newChEle.setTextContent( dbidVals[i][j] );
    410                                        newEle.appendChild( newChEle );
    411                                }
    412                                firstRoot.appendChild( newEle );
    413                                firstRoot.appendChild( doc.createTextNode( "\n\n" ) );
    414                        }
    415                }
    416
    417                DomParser.write( new File(xmlFilename), doc );
    418
    419                reload();               // 5.6.7.0 (2013/07/27) DBIDの属性情報のリストを更新後、初期化します。
    420        }
    421
    422        /**
    423         * DBドライバーの属性キーを返します。
    424         *
    425         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    426         *
    427         * @return      DBドライバーの属性キー
    428         */
    429        public static String getDriverKey() {
    430                return DBDRIVER_CLASS_KEY;
    431        }
    432
    433        /**
    434         * DBドライバーのリスト(配列)を返します。
    435         *
    436         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    437         * @og.rev 5.6.7.0 (2013/07/27) driverList を書き込むのではなく、作成します。
    438         *
    439         * @return      DBドライバーリスト(配列)
    440         */
    441//      public synchronized String[] getDriverList() {
    442        public String[] getDriverList() {
    443                return driverList.toArray( new String[driverList.size()] );
    444
    445//              String [] rtn = driverList.toArray( new String[driverList.size()] );
    446//              return rtn;
    447        }
    448
    449        /**
    450         * DBドライバーのリスト(配列)をセットします。
    451         *
    452         * このメソッドを呼び出すと、DBConfig.xmlで定義されているclass一覧を"一旦削除し"、
    453         * その上で、引数のDBドライバー一覧をDBConfig.xmlに書き込みます。
    454         *
    455         * 書き込みの直前に、同じフォルダにタイムスタンプを付加したバックアップファイルを作成します。
    456         *
    457         * @og.rev 5.1.9.0 (2010/08/01) 新規作成
    458         * @og.rev 5.6.7.0 (2013/07/27) DBドライバーのリストを更新後、初期化します。
    459         *
    460         * @param drivers DBドライバーのリスト(配列)
    461         */
    462        public void setDriverList( final String[] drivers ) {
    463                FileUtil.copy( xmlFilename, xmlFilename + "_" + System.currentTimeMillis() );
    464
    465                Document doc = DomParser.read( new File(xmlFilename) );
    466                Element firstRoot = doc.getDocumentElement();
    467
    468                Element parent = (Element)firstRoot.getElementsByTagName( "dbDriver" ).item( 0 );
    469                deleteChildElements( parent, "class" );
    470
    471                if( drivers != null && drivers.length > 0 ) {
    472                        for( int i=0; i<drivers.length; i++ ) {
    473                                Element newEle = doc.createElement( "class" );
    474                                newEle.setTextContent( drivers[i] );
    475                                parent.appendChild( newEle );
    476                        }
    477                }
    478
    479                DomParser.write( new File(xmlFilename), doc );
    480
    481                reload();               // 5.6.7.0 (2013/07/27) DBドライバーのリストを更新後、初期化します。
    482        }
    483
    484
    485        /**
    486         * DBID情報のキーとタイトルから、プルダウンメニューを作成するための情報を取得します。
    487         *
    488         * このメソッドを呼び出すと、DBConfig.xmlで定義されている dbidKey と、 title 属性から、
    489         * 「key1:val1 key2:val2 ・・・」という文字列を作成します。
    490         * これを利用すれば、プルダウンメニューが簡単に作成できます。
    491         *
    492         * @og.rev 5.6.7.0 (2013/07/27) プルダウンメニュー用の情報を作成します。
    493         * @og.rev 5.6.7.1 (2013/08/09) 表題(title)属性のスペース対策
    494         *
    495         * @return プルダウンメニューを作成するための情報
    496         */
    497        public synchronized String getCodeKeyVal() {
    498                if( codeKeyVal == null ) {
    499                        StringBuilder buf = new StringBuilder();
    500                        for( EDbid dbid : dbidMap.values() ) {
    501                                String key = dbid.getDbidKey();
    502                                String lbl = StringUtil.nval( dbid.getTitle() , key );
    503                                if( lbl.indexOf( ' ' ) >= 0 ) {                                                                 // 5.6.7.1 (2013/08/09) スペース対策
    504                                        buf.append( " " ).append( key ).append( ":\"" ).append( lbl ).append( "\"" );
    505                                }
    506                                else {
    507                                        buf.append( " " ).append( key ).append( ":" ).append( lbl );
    508                                }
    509                        }
    510
    511                        codeKeyVal = buf.substring( 1 );                // 先頭のスペースを削除
    512                }
    513
    514                return codeKeyVal;
    515        }
    516
    517        /**
    518         * 親要素を基点として、引数で指定されたタグ名を持つ子要素を削除します。
    519         *
    520         * @og.rev 5.6.7.0 (2013/07/27) staticメソッド を イスタンスメソッドに変更
    521         *
    522         * @param parent 親要素
    523         * @param childTagName 削除する子要素のタグ名
    524         */
    525        private void deleteChildElements( final Element parent, final String childTagName ) {
    526                Node child = parent.getFirstChild();
    527                boolean isDel = false;
    528                while ( child != null ) {
    529                        // エレメント間の改行Cも削除するため、次の異なる要素が来るまでは削除し続けます。
    530                        if( child.getNodeType() == Node.ELEMENT_NODE ) {
    531                                if( ((Element)child).getTagName().equalsIgnoreCase( childTagName ) ) {
    532                                        isDel = true;
    533                                }
    534                                else {
    535                                        isDel = false;
    536                                }
    537                        }
    538
    539                        Node next = child.getNextSibling();
    540                        if( isDel ) {
    541                                parent.removeChild( child );
    542                        }
    543                        child = next;
    544                }
    545        }
    546}